vitalybuka created this revision.
vitalybuka added reviewers: rsmith, jfb.
Herald added subscribers: cfe-commits, dexonsmith.
Herald added a project: clang.
vitalybuka edited the summary of this revision.
vitalybuka edited the summary of this revision.

Existing implementation puts undef into padding bits which almost always
compiled into zeroes. However with -ftrivial-auto-var-init=pattern those undefs
became 0xAA pattern and break some code. We need to zero initialized them.

C++ requires zeroes in padding bit.

  11.6 Initializers
  (6.3) — if T is a (possibly cv-qualified) union type, its padding bits (6.7) 
are initialized to zero bits

Looks like C does not require, as union is not aggregate, but a lot of code 
already relies on this behavior.

  6.7.9 Initialization
  10. If an object that has automatic storage duration is not initialized 
explicitly, its value is indeterminate.
  If an object that has static or thread storage duration is not initialized 
explicitly, then:
  — if it is a union, the first named member is initialized (recursively) 
according to these rules, and
  any padding is initialized to zero bits;
  21. If there are fewer initializers in a brace-enclosed list than there are 
elements or members of an
  aggregate, or fewer characters in a string literal used to initialize an 
array of known size than there
  are elements in the array, the remainder of the aggregate shall be 
initialized implicitly the same as
  objects that have static storage duration.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D68115

Files:
  clang/lib/CodeGen/CGExprConstant.cpp
  clang/test/CodeGen/2008-08-07-AlignPadding1.c
  clang/test/CodeGen/64bit-swiftcall.c
  clang/test/CodeGen/arm-swiftcall.c
  clang/test/CodeGen/designated-initializers.c
  clang/test/CodeGen/init.c
  clang/test/CodeGen/union-init2.c
  clang/test/CodeGen/windows-swiftcall.c
  clang/test/CodeGenCXX/auto-var-init.cpp
  clang/test/CodeGenCXX/const-init-cxx11.cpp
  clang/test/CodeGenCXX/cxx11-initializer-aggregate.cpp
  clang/test/CodeGenCXX/designated-init.cpp
  clang/test/CodeGenCXX/static-init.cpp

Index: clang/test/CodeGenCXX/static-init.cpp
===================================================================
--- clang/test/CodeGenCXX/static-init.cpp
+++ clang/test/CodeGenCXX/static-init.cpp
@@ -5,7 +5,7 @@
 // CHECK: @base_req = global [4 x i8] c"foo\00", align 1
 // CHECK: @base_req_uchar = global [4 x i8] c"bar\00", align 1
 
-// CHECK: @_ZZN5test31BC1EvE1u = internal global { i8, [3 x i8] } { i8 97, [3 x i8] undef }, align 4
+// CHECK: @_ZZN5test31BC1EvE1u = internal global { i8, [3 x i8] } { i8 97, [3 x i8] zeroinitializer }, align 4
 
 // CHECK: @_ZZ2h2vE1i = linkonce_odr global i32 0, comdat, align 4
 // CHECK: @_ZGVZ2h2vE1i = linkonce_odr global i64 0, comdat, align 8{{$}}
Index: clang/test/CodeGenCXX/designated-init.cpp
===================================================================
--- clang/test/CodeGenCXX/designated-init.cpp
+++ clang/test/CodeGenCXX/designated-init.cpp
@@ -1,5 +1,7 @@
-// RUN: %clang_cc1 -std=c++98 -emit-llvm -o - %s -triple x86_64-linux-gnu | FileCheck %s
-// RUN: %clang_cc1 -std=c++11 -emit-llvm -o - %s -triple x86_64-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 -w -std=c++98 -emit-llvm -o - %s -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-LE
+// RUN: %clang_cc1 -w -std=c++11 -emit-llvm -o - %s -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-LE
+// RUN: %clang_cc1 -w -std=c++98 -emit-llvm -o - %s -triple aarch64_be-none-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-BE
+// RUN: %clang_cc1 -w -std=c++11 -emit-llvm -o - %s -triple aarch64_be-none-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-BE
 
 struct A { int x, y[3]; };
 struct B { A a; };
@@ -34,7 +36,8 @@
   int n;
   Bitfield b;
 };
-// CHECK: @bitfield = {{.*}} { i32 1, { i8, i8, [2 x i8] } { i8 42, i8 2, [2 x i8] undef } }
+// CHECK-LE: @bitfield = {{.*}} { i32 1, { i8, i8, [2 x i8] } { i8 42, i8 2, [2 x i8] undef } }
+// CHECK-BE: @bitfield = {{.*}} { i32 1, { i8, i8, [2 x i8] } { i8 74, i8 64, [2 x i8] undef } }
 WithBitfield bitfield = {1, (Bitfield){2, 3, 4}, .b.b = 5};
 
 struct String {
@@ -62,5 +65,6 @@
 struct WithOverwritePaddingWithBitfield {
   OverwritePaddingWithBitfield a;
 };
-// CHECK: @overwrite_padding = global { { i8, i8 } } { { i8, i8 } { i8 3, i8 1 } }
+// CHECK-LE: @overwrite_padding = global { { i8, i8 } } { { i8, i8 } { i8 3, i8 0 } }
+// CHECK-BE: @overwrite_padding = global { { i8, i8, i8, i8 } } { { i8, i8, i8, i8 } { i8 96, i8 0, i8 0, i8 0 } }
 WithOverwritePaddingWithBitfield overwrite_padding = {(OverwritePaddingWithBitfield){1}, .a.bitfield = 3};
Index: clang/test/CodeGenCXX/cxx11-initializer-aggregate.cpp
===================================================================
--- clang/test/CodeGenCXX/cxx11-initializer-aggregate.cpp
+++ clang/test/CodeGenCXX/cxx11-initializer-aggregate.cpp
@@ -23,27 +23,24 @@
     char x;
     int a;
   };
-  // FIXME: [dcl.init]p2, the padding bits of the union object should be
-  // initialized to 0, not undef, which would allow us to collapse the tail
-  // of these arrays to zeroinitializer.
-  // CHECK-DAG: @_ZN7PR375601cE = global <{ { i8, [3 x i8] } }> <{ { i8, [3 x i8] } { i8 0, [3 x i8] undef } }>
+  // CHECK-DAG: @_ZN7PR375601cE = global [1 x [[UU:%"[^"]*"]]] zeroinitializer
   U c[1] = {};
-  // CHECK-DAG: @_ZN7PR375601dE = global {{.*}} <{ { i8, [3 x i8] } { i8 97, [3 x i8] undef }, %"{{[^"]*}}" { i32 123 }, { i8, [3 x i8] } { i8 98, [3 x i8] undef }, { i8, [3 x i8] } { i8 0, [3 x i8] undef },
+  // CHECK-DAG: @_ZN7PR375601dE = global <{ { i8, [3 x i8] }, [[UU]], { i8, [3 x i8] }, [13 x [[UU]]] }> <{ { i8, [3 x i8] } { i8 97, [3 x i8] zeroinitializer }, [[UU]] { i32 123 }, { i8, [3 x i8] } { i8 98, [3 x i8] zeroinitializer }, [13 x [[UU]]] zeroinitializer }>
   U d[16] = {'a', {.a = 123}, 'b'};
-  // CHECK-DAG: @_ZN7PR375601eE = global {{.*}} <{ %"{{[^"]*}}" { i32 123 }, %"{{[^"]*}}" { i32 456 }, { i8, [3 x i8] } { i8 0, [3 x i8] undef },
+  // CHECK-DAG: @_ZN7PR375601eE = global <{ [[UU]], [[UU]], [14 x [[UU]]] }> <{ [[UU]] { i32 123 }, [[UU]] { i32 456 }, [14 x [[UU]]] zeroinitializer }>
   U e[16] = {{.a = 123}, {.a = 456}};
 
   union V {
     int a;
     char x;
   };
-  // CHECK-DAG: @_ZN7PR375601fE = global [1 x %"{{[^"]*}}"] zeroinitializer
+  // CHECK-DAG: @_ZN7PR375601fE = global [1 x [[UV:%"[^"]*"]]] zeroinitializer
   V f[1] = {};
-  // CHECK-DAG: @_ZN7PR375601gE = global {{.*}} <{ { i8, [3 x i8] } { i8 97, [3 x i8] undef }, %"{{[^"]*}}" { i32 123 }, { i8, [3 x i8] } { i8 98, [3 x i8] undef }, [13 x %"{{[^"]*}}"] zeroinitializer }>
+  // CHECK-DAG: @_ZN7PR375601gE = global <{ { i8, [3 x i8] }, [[UV]], { i8, [3 x i8] }, [13 x [[UV]]] }> <{ { i8, [3 x i8] } { i8 97, [3 x i8] zeroinitializer }, [[UV]] { i32 123 }, { i8, [3 x i8] } { i8 98, [3 x i8] zeroinitializer }, [13 x [[UV]]] zeroinitializer }>
   V g[16] = {{.x = 'a'}, {.a = 123}, {.x = 'b'}};
-  // CHECK-DAG: @_ZN7PR375601hE = global {{.*}} <{ %"{{[^"]*}}" { i32 123 }, %"{{[^"]*}}" { i32 456 }, [14 x %"{{[^"]*}}"] zeroinitializer }>
+  // CHECK-DAG: @_ZN7PR375601hE = global <{ [[UV]], [[UV]], [14 x [[UV]]] }> <{ [[UV]] { i32 123 }, [[UV]] { i32 456 }, [14 x [[UV]]] zeroinitializer }>
   V h[16] = {{.a = 123}, {.a = 456}};
-  // CHECK-DAG: @_ZN7PR375601iE = global [4 x %"{{[^"]*}}"] [%"{{[^"]*}}" { i32 123 }, %"{{[^"]*}}" { i32 456 }, %"{{[^"]*}}" zeroinitializer, %"{{[^"]*}}" zeroinitializer]
+  // CHECK-DAG: @_ZN7PR375601iE = global [4 x [[UV]]] {{\[}}[[UV]] { i32 123 }, [[UV]] { i32 456 }, [[UV]] zeroinitializer, [[UV]] zeroinitializer]
   V i[4] = {{.a = 123}, {.a = 456}};
 }
 
Index: clang/test/CodeGenCXX/const-init-cxx11.cpp
===================================================================
--- clang/test/CodeGenCXX/const-init-cxx11.cpp
+++ clang/test/CodeGenCXX/const-init-cxx11.cpp
@@ -16,7 +16,7 @@
     constexpr A(int n, double d, const char *y) : n(n), d(d), u(y) {}
   };
 
-  // CHECK: @_ZN11StructUnion1aE = constant {{.*}} { i32 1, double 2.000000e+00, {{.*}} { i32 3, [4 x i8] undef } }
+  // CHECK: @_ZN11StructUnion1aE = constant {{.*}} { i32 1, double 2.000000e+00, {{.*}} { i32 3, [4 x i8] zeroinitializer } }
   extern constexpr A a(1, 2.0, 3);
 
   // CHECK: @_ZN11StructUnion1bE = constant {{.*}} { i32 4, double 5.000000e+00, {{.*}} { i8* getelementptr inbounds ([6 x i8], [6 x i8]* @{{.*}}, i32 0, i32 0) } }
Index: clang/test/CodeGenCXX/auto-var-init.cpp
===================================================================
--- clang/test/CodeGenCXX/auto-var-init.cpp
+++ clang/test/CodeGenCXX/auto-var-init.cpp
@@ -221,7 +221,7 @@
 union unmatched { char c; int i; };
 // PATTERN-O0: @__const.test_unmatchedreverse_uninit.uninit = private unnamed_addr constant %union.unmatchedreverse { i32 [[I32]] }, align 4
 // PATTERN-O1-NOT: @__const.test_unmatchedreverse_uninit.uninit
-// PATTERN-O0: @__const.test_unmatchedreverse_custom.custom = private unnamed_addr constant { i8, [3 x i8] } { i8 42, [3 x i8] c"\[[IC]]\[[IC]]\[[IC]]" }, align 4
+// PATTERN-O0: @__const.test_unmatchedreverse_custom.custom = private unnamed_addr constant { i8, [3 x i8] } { i8 42, [3 x i8] zeroinitializer }, align 4
 // PATTERN-O1-NOT: @__const.test_unmatchedreverse_custom.custom
 // ZERO-O0: @__const.test_unmatchedreverse_custom.custom = private unnamed_addr constant { i8, [3 x i8] } { i8 42, [3 x i8] zeroinitializer }, align 4
 // ZERO-O1-NOT: @__const.test_unmatchedreverse_custom.custom
@@ -1424,7 +1424,7 @@
 // CHECK-LABEL: @test_unmatched_braces()
 // CHECK:       %braces = alloca %union.unmatched, align
 // CHECK-NEXT:  bitcast
-// CHECK-NEXT:  call void @llvm.memcpy
+// CHECK-NEXT:  call void @llvm.memset.p0i8.i64(i8* align 4 %0, i8 0, i64 4, i1 false
 // CHECK-NEXT:  call void @{{.*}}used{{.*}}%braces)
 
 TEST_CUSTOM(unmatched, unmatched, { .i = 0x3badbeef });
@@ -1458,7 +1458,7 @@
 // CHECK-O0:    bitcast
 // CHECK-O0:    call void @llvm.memcpy
 // CHECK-O0:    call void @{{.*}}used{{.*}}%custom)
-// PATTERN-O1:  store i32 -1431655894, i32* {{.*}}, align 4
+// PATTERN-O1:  store i32 -1431655766, i32* {{.*}}, align 4
 // ZERO-O1:     store i32 42, i32* {{.*}}, align 4
 
 TEST_UNINIT(unmatchedfp, unmatchedfp);
@@ -1475,7 +1475,7 @@
 // CHECK-LABEL: @test_unmatchedfp_braces()
 // CHECK:       %braces = alloca %union.unmatchedfp, align
 // CHECK-NEXT:  bitcast
-// CHECK-NEXT:  call void @llvm.memcpy
+// CHECK-NEXT:  call void @llvm.memset.p0i8.i64(i8* align 8 %0, i8 0, i64 8, i1 false
 // CHECK-NEXT:  call void @{{.*}}used{{.*}}%braces)
 
 TEST_CUSTOM(unmatchedfp, unmatchedfp, { .d = 3.1415926535897932384626433 });
Index: clang/test/CodeGen/windows-swiftcall.c
===================================================================
--- clang/test/CodeGen/windows-swiftcall.c
+++ clang/test/CodeGen/windows-swiftcall.c
@@ -249,7 +249,7 @@
 // CHECK-LABEL: define dso_local swiftcc i64 @return_union_het_fp()
 // CHECK:  [[RET:%.*]] = alloca [[UNION:%.*]], align 8
 // CHECK:  [[CAST:%.*]] = bitcast [[UNION]]* [[RET]] to i8*
-// CHECK:  call void @llvm.memcpy{{.*}}(i8* align {{[0-9]+}} [[CAST]]
+// CHECK:  call void @llvm.memset{{.*}}(i8* align {{[0-9]+}} [[CAST]]
 // CHECK:  [[CAST:%.*]] = bitcast [[UNION]]* [[RET]] to { i64 }*
 // CHECK:  [[GEP:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[CAST]], i32 0, i32 0
 // CHECK:  [[R0:%.*]] = load i64, i64* [[GEP]], align 8
@@ -274,7 +274,6 @@
 // CHECK:   ret void
 // CHECK: }
 
-
 typedef union {
   float f1;
   float f2;
Index: clang/test/CodeGen/union-init2.c
===================================================================
--- clang/test/CodeGen/union-init2.c
+++ clang/test/CodeGen/union-init2.c
@@ -1,13 +1,29 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple i686-pc-linux-gnu | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple i686-pc-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-LE
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple aarch64_be-none-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-BE
 
 // Make sure we generate something sane instead of a ptrtoint
-// CHECK: bitcast ({ %union.x*, [4 x i8] }* @r to %union.x*), [4 x i8] undef
+// CHECK-LE: @r = global { %union.x*, [4 x i8] } { %union.x* bitcast ({ %union.x*, [4 x i8] }* @r to %union.x*), [4 x i8] zeroinitializer }, align [[ALIGN:4]]
+// CHECK-BE: @r = global { %union.x* } { %union.x* bitcast ({ %union.x* }* @r to %union.x*) }, align [[ALIGN:8]]
 union x {long long b;union x* a;} r = {.a = &r};
 
-
-// CHECK: global { [3 x i8], [5 x i8] } { [3 x i8] zeroinitializer, [5 x i8] undef }
 union z {
   char a[3];
   long long b;
 };
+// CHECK: @y = global { [3 x i8], [5 x i8] } zeroinitializer, align [[ALIGN]]
 union z y = {};
+
+// CHECK: @y2 = global { [3 x i8], [5 x i8] } { [3 x i8] c"\03\00\00", [5 x i8] zeroinitializer }, align [[ALIGN]]
+union z y2 = {3};
+
+union u {
+  int a : 13;
+  long long b;
+};
+
+// CHECK: @t = global { i8, i8, i8, i8, i8, i8, i8, i8 } zeroinitializer, align [[ALIGN]]
+union u t = {};
+
+// CHECK-LE: @t2 = global { i8, i8, i8, i8, i8, i8, i8, i8 } { i8 2, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0 }, align [[ALIGN]]
+// CHECK-BE: @t2 = global { i8, i8, i8, i8, i8, i8, i8, i8 } { i8 0, i8 16, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0 }, align [[ALIGN]]
+union u t2 = {2};
Index: clang/test/CodeGen/init.c
===================================================================
--- clang/test/CodeGen/init.c
+++ clang/test/CodeGen/init.c
@@ -11,6 +11,8 @@
 // CHECK-DAG: [1 x %struct.M] [%struct.M { [2 x %struct.I] [%struct.I { [3 x i32] [i32 4, i32 4, i32 0] }, %struct.I { [3 x i32] [i32 4, i32 4, i32 5] }] }],
 // CHECK-DAG: [2 x [3 x i32]] {{[[][[]}}3 x i32] [i32 2222, i32 2222, i32 0], [3 x i32] [i32 2222, i32 2222, i32 3333]],
 // CHECK-DAG: [[INIT14:.*]] = private global [16 x i32] [i32 0, i32 0, i32 0, i32 0, i32 0, i32 17, i32 17, i32 17, i32 17, i32 17, i32 17, i32 17, i32 0, i32 0, i32 0, i32 0], align 4
+// CHECK-DAG: [[INIT_PADDEDUNION:.*]] = private unnamed_addr constant [9 x { i8, [3 x i8] }] [{ i8, [3 x i8] } { i8 -16, [3 x i8] zeroinitializer }, { i8, [3 x i8] } { i8 -16, [3 x i8] zeroinitializer }, { i8, [3 x i8] } { i8 -16, [3 x i8] zeroinitializer }, { i8, [3 x i8] } { i8 -16, [3 x i8] zeroinitializer }, { i8, [3 x i8] } { i8 -16, [3 x i8] zeroinitializer }, { i8, [3 x i8] } { i8 -16, [3 x i8] zeroinitializer }, { i8, [3 x i8] } { i8 -16, [3 x i8] zeroinitializer }, { i8, [3 x i8] } { i8 -16, [3 x i8] zeroinitializer }, { i8, [3 x i8] } { i8 -16, [3 x i8] zeroinitializer }], align 4
+// CHECK-DAG: [[INIT_NESTEDUNION:.*]] = private unnamed_addr constant [5 x { { i8, [3 x i8] }, i16, [2 x i8] }] [{ { i8, [3 x i8] }, i16, [2 x i8] } { { i8, [3 x i8] } { i8 -16, [3 x i8] zeroinitializer }, i16 -3856, [2 x i8] undef }, { { i8, [3 x i8] }, i16, [2 x i8] } { { i8, [3 x i8] } { i8 -16, [3 x i8] zeroinitializer }, i16 -3856, [2 x i8] undef }, { { i8, [3 x i8] }, i16, [2 x i8] } { { i8, [3 x i8] } { i8 -16, [3 x i8] zeroinitializer }, i16 -3856, [2 x i8] undef }, { { i8, [3 x i8] }, i16, [2 x i8] } { { i8, [3 x i8] } { i8 -16, [3 x i8] zeroinitializer }, i16 -3856, [2 x i8] undef }, { { i8, [3 x i8] }, i16, [2 x i8] } { { i8, [3 x i8] } { i8 -16, [3 x i8] zeroinitializer }, i16 -3856, [2 x i8] undef }], align 4
 
 void f1() {
   // Scalars in braces.
@@ -192,9 +194,7 @@
   union U { char c; int i; };
   union U arr[9] = { 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, };
   // CHECK-LABEL: @nonzeroPaddedUnionMemset(
-  // CHECK-NOT: store
-  // CHECK-NOT: memcpy
-  // CHECK: call void @llvm.memset.p0i8.i32(i8* {{.*}}, i8 -16, i32 36, i1 false)
+  // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 {{.*}}, i8* align 4 {{.*}} [[INIT_PADDEDUNION]], {{.*}}, i32 36, i1 false)
 }
 
 void nonzeroNestedMemset() {
@@ -202,9 +202,7 @@
   struct S { union U u; short i; };
   struct S arr[5] = { { {0xF0}, 0xF0F0 }, { {0xF0}, 0xF0F0 }, { {0xF0}, 0xF0F0 }, { {0xF0}, 0xF0F0 }, { {0xF0}, 0xF0F0 }, };
   // CHECK-LABEL: @nonzeroNestedMemset(
-  // CHECK-NOT: store
-  // CHECK-NOT: memcpy
-  // CHECK: call void @llvm.memset.p0i8.i32(i8* {{.*}}, i8 -16, i32 40, i1 false)
+  // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 {{.*}}, i8* align 4 {{.*}} [[INIT_NESTEDUNION]], {{.*}}, i32 40, i1 false)
 }
 
 // PR9257
Index: clang/test/CodeGen/designated-initializers.c
===================================================================
--- clang/test/CodeGen/designated-initializers.c
+++ clang/test/CodeGen/designated-initializers.c
@@ -8,7 +8,7 @@
 // CHECK: @u = global %union.anon zeroinitializer
 union { int i; float f; } u = { };
 
-// CHECK: @u2 = global { i32, [4 x i8] } { i32 0, [4 x i8] undef }
+// CHECK: @u2 = global { i32, [4 x i8] } zeroinitializer, align 4
 union { int i; double f; } u2 = { };
 
 // CHECK: @u3 = global  %union.anon.1 zeroinitializer
Index: clang/test/CodeGen/arm-swiftcall.c
===================================================================
--- clang/test/CodeGen/arm-swiftcall.c
+++ clang/test/CodeGen/arm-swiftcall.c
@@ -276,7 +276,7 @@
 TEST(union_het_fp)
 // CHECK-LABEL: define {{.*}} @return_union_het_fp()
 // CHECK:   [[RET:%.*]] = alloca [[REC:%.*]], align {{(4|8)}}
-// CHECK:   @llvm.memcpy
+// CHECK:   @llvm.memset
 // CHECK:   [[CAST_TMP:%.*]] = bitcast [[REC]]* [[RET]] to [[AGG:{ i32, i32 }]]*
 // CHECK:   [[T0:%.*]] = getelementptr inbounds [[AGG]], [[AGG]]* [[CAST_TMP]], i32 0, i32 0
 // CHECK:   [[FIRST:%.*]] = load i32, i32* [[T0]], align {{(4|8)}}
@@ -311,7 +311,6 @@
 // CHECK:   call [[SWIFTCC]] void @take_union_het_fp(i32 [[FIRST]], i32 [[SECOND]])
 // CHECK:   ret void
 
-
 typedef union {
   float f1;
   float f2;
Index: clang/test/CodeGen/64bit-swiftcall.c
===================================================================
--- clang/test/CodeGen/64bit-swiftcall.c
+++ clang/test/CodeGen/64bit-swiftcall.c
@@ -258,7 +258,7 @@
 // CHECK-LABEL: define swiftcc i64 @return_union_het_fp()
 // CHECK:  [[RET:%.*]] = alloca [[UNION:%.*]], align 8
 // CHECK:  [[CAST:%.*]] = bitcast [[UNION]]* [[RET]] to i8*
-// CHECK:  call void @llvm.memcpy{{.*}}(i8* align 8 [[CAST]]
+// CHECK:  call void @llvm.memset{{.*}}(i8* align 8 [[CAST]]
 // CHECK:  [[CAST:%.*]] = bitcast [[UNION]]* [[RET]] to { i64 }*
 // CHECK:  [[GEP:%.*]] = getelementptr inbounds { i64 }, { i64 }* [[CAST]], i32 0, i32 0
 // CHECK:  [[R0:%.*]] = load i64, i64* [[GEP]], align 8
@@ -283,7 +283,6 @@
 // CHECK:   ret void
 // CHECK: }
 
-
 typedef union {
   float f1;
   float f2;
Index: clang/test/CodeGen/2008-08-07-AlignPadding1.c
===================================================================
--- clang/test/CodeGen/2008-08-07-AlignPadding1.c
+++ clang/test/CodeGen/2008-08-07-AlignPadding1.c
@@ -22,7 +22,7 @@
 
 // The idea is that there are 6 undefs in this structure initializer to cover
 // the padding between elements.
-// CHECK: @generations = global [3 x %struct.gc_generation] [%struct.gc_generation { %union._gc_head { %struct.anon { %union._gc_head* getelementptr inbounds ([3 x %struct.gc_generation], [3 x %struct.gc_generation]* @generations, i32 0, i32 0, i32 0), %union._gc_head* getelementptr inbounds ([3 x %struct.gc_generation], [3 x %struct.gc_generation]* @generations, i32 0, i32 0, i32 0), i64 0 }, [8 x i8] undef }, i32 700, i32 0, [8 x i8] undef }, %struct.gc_generation { %union._gc_head { %struct.anon { %union._gc_head* bitcast (i8* getelementptr (i8, i8* bitcast ([3 x %struct.gc_generation]* @generations to i8*), i64 48) to %union._gc_head*), %union._gc_head* bitcast (i8* getelementptr (i8, i8* bitcast ([3 x %struct.gc_generation]* @generations to i8*), i64 48) to %union._gc_head*), i64 0 }, [8 x i8] undef }, i32 10, i32 0, [8 x i8] undef }, %struct.gc_generation { %union._gc_head { %struct.anon { %union._gc_head* bitcast (i8* getelementptr (i8, i8* bitcast ([3 x %struct.gc_generation]* @generations to i8*), i64 96) to %union._gc_head*), %union._gc_head* bitcast (i8* getelementptr (i8, i8* bitcast ([3 x %struct.gc_generation]* @generations to i8*), i64 96) to %union._gc_head*), i64 0 }, [8 x i8] undef }, i32 10, i32 0, [8 x i8] undef }]
+// CHECK: @generations = global [3 x %struct.gc_generation] [%struct.gc_generation { %union._gc_head { %struct.anon { %union._gc_head* getelementptr inbounds ([3 x %struct.gc_generation], [3 x %struct.gc_generation]* @generations, i32 0, i32 0, i32 0), %union._gc_head* getelementptr inbounds ([3 x %struct.gc_generation], [3 x %struct.gc_generation]* @generations, i32 0, i32 0, i32 0), i64 0 }, [8 x i8] zeroinitializer }, i32 700, i32 0, [8 x i8] undef }, %struct.gc_generation { %union._gc_head { %struct.anon { %union._gc_head* bitcast (i8* getelementptr (i8, i8* bitcast ([3 x %struct.gc_generation]* @generations to i8*), i64 48) to %union._gc_head*), %union._gc_head* bitcast (i8* getelementptr (i8, i8* bitcast ([3 x %struct.gc_generation]* @generations to i8*), i64 48) to %union._gc_head*), i64 0 }, [8 x i8] zeroinitializer }, i32 10, i32 0, [8 x i8] undef }, %struct.gc_generation { %union._gc_head { %struct.anon { %union._gc_head* bitcast (i8* getelementptr (i8, i8* bitcast ([3 x %struct.gc_generation]* @generations to i8*), i64 96) to %union._gc_head*), %union._gc_head* bitcast (i8* getelementptr (i8, i8* bitcast ([3 x %struct.gc_generation]* @generations to i8*), i64 96) to %union._gc_head*), i64 0 }, [8 x i8] zeroinitializer }, i32 10, i32 0, [8 x i8] undef }]
 /* linked lists of container objects */
 struct gc_generation generations[3] = {
         /* PyGC_Head,                           threshold,      count */
Index: clang/lib/CodeGen/CGExprConstant.cpp
===================================================================
--- clang/lib/CodeGen/CGExprConstant.cpp
+++ clang/lib/CodeGen/CGExprConstant.cpp
@@ -71,7 +71,7 @@
 
 /// Incremental builder for an llvm::Constant* holding a struct or array
 /// constant.
-class ConstantAggregateBuilder : private ConstantAggregateBuilderUtils {
+class ConstantAggregateBuilder : public ConstantAggregateBuilderUtils {
   /// The elements of the constant. These two arrays must have the same size;
   /// Offsets[i] describes the offset of Elems[i] within the constant. The
   /// elements are kept in increasing offset order, and we ensure that there
@@ -576,7 +576,20 @@
 
   CharUnits FieldOffsetInChars = Context.toCharUnitsFromBits(FieldOffset);
 
-  return AppendBytes(FieldOffsetInChars, InitCst, AllowOverwrite);
+  if (!AppendBytes(FieldOffsetInChars, InitCst, AllowOverwrite))
+    return false;
+
+  if (!Field->getParent()->isUnion())
+    return true;
+
+  const ASTRecordLayout &Layout =
+      CGM.getContext().getASTRecordLayout(Field->getParent());
+  auto ZeroInit = Layout.getSize();
+  auto Z = Builder.getSize(InitCst);
+  if (ZeroInit <= Z)
+    return true;
+  return AppendBytes(FieldOffsetInChars + Z, Builder.getZeroes(ZeroInit - Z),
+                     AllowOverwrite);
 }
 
 bool ConstStructBuilder::AppendBytes(CharUnits FieldOffsetInChars,
@@ -602,6 +615,21 @@
   if (FieldSize < FieldValue.getBitWidth())
     FieldValue = FieldValue.trunc(FieldSize);
 
+  if (Field->getParent()->isUnion()) {
+    const uint64_t CharWidth = CGM.getContext().getCharWidth();
+    assert(FieldOffset % CharWidth == 0);
+
+    const ASTRecordLayout &Layout =
+        CGM.getContext().getASTRecordLayout(Field->getParent());
+    uint64_t ZeroInit = CGM.getContext().toBits(Layout.getSize());
+    if (ZeroInit > FieldSize) {
+      uint64_t AddZeroes = ZeroInit - FieldSize;
+      FieldValue = FieldValue.zext(ZeroInit);
+      if (CGM.getDataLayout().isBigEndian())
+        FieldValue = FieldValue.shl(AddZeroes);
+    }
+  }
+
   return Builder.addBits(FieldValue,
                          CGM.getContext().toBits(StartOffset) + FieldOffset,
                          AllowOverwrite);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to