diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConst.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConst.cpp index 61a3d66fea08..168b1c61792a 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprConst.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprConst.cpp @@ -1106,48 +1106,6 @@ class ConstExprEmitter } auto desiredType = CGM.convertType(T); - // FIXME(cir): A hack to handle the emission of arrays of unions directly. - // See clang/test/CIR/CodeGen/union-array.c and - // clang/test/CIR/Lowering/nested-union-array.c for example. The root - // cause of these problems is CIR handles union differently than LLVM IR. - // So we can't fix the problem fundamentally by mocking LLVM's handling for - // unions. In LLVM, the union is basically a struct with the largest member - // of the union and consumers cast the union arbitrarily according to their - // needs. But in CIR, we tried to express union semantics properly. This is - // a fundamental difference. - // - // Concretely, for the problem here, if we're constructing the initializer - // for the array of unions, we can't even assume the type of the elements in - // the initializer are the same! It is odd that we can have an array with - // different element types. Here we just pretend it is fine by checking if - // we're constructing an array for an array of unions. If we didn't do so, - // we may meet problems during lowering to LLVM. To solve the problem, we - // may need to introduce 2 type systems for CIR: one for the CIR itself and - // one for lowering. e.g., we can compare the type of CIR during CIRGen, - // analysis and transformations without worrying the concerns here. And - // lower to LLVM IR (or anyother dialects) with the proper type. - // - // (Although the idea to make CIR's type system self contained and generate - // LLVM's - // types in later passes look fine, it has engineering level concern that - // it will make the skeleton of CIRGen to be diverged from the traditional - // CodeGen.) - // - // Besides union, there are other differences between CIR and LLVM's type - // system. e.g., LLVM's pointer types are opaque while CIR has concrete - // pointer types. - bool isDesiredArrayOfUnionDirectly = [&]() { - auto desiredArrayType = dyn_cast(desiredType); - if (!desiredArrayType) - return false; - - auto elementRecordType = - dyn_cast(desiredArrayType.getElementType()); - if (!elementRecordType) - return false; - - return elementRecordType.isUnion(); - }(); // Emit initializer elements as MLIR attributes and check for common type. mlir::Type CommonElementType; @@ -1159,8 +1117,7 @@ class ConstExprEmitter if (i == 0) CommonElementType = C.getType(); - else if (isDesiredArrayOfUnionDirectly && - C.getType() != CommonElementType) + else if (C.getType() != CommonElementType) CommonElementType = nullptr; Elts.push_back(std::move(C)); } diff --git a/clang/test/CIR/CodeGen/array-init.c b/clang/test/CIR/CodeGen/array-init.c index 12f07219999b..50444f2f39b2 100644 --- a/clang/test/CIR/CodeGen/array-init.c +++ b/clang/test/CIR/CodeGen/array-init.c @@ -9,6 +9,48 @@ typedef struct { long b; } T; +// Test array initialization with different elements. +typedef struct { + long a0; + int a1; +} Inner; +typedef struct { + int b0; + Inner b1[1]; +} Outer; +Outer outers[2] = { + {1, {0, 1} }, + {1, {0, 0} } +}; +// CIR: cir.global{{.*}} @outers = +// CIR-SAME: #cir.const_record<{ +// CIR-SAME: #cir.const_record<{ +// CIR-SAME: #cir.int<1> : !s32i, +// CIR-SAME: #cir.const_array<[#cir.zero : !u8i, #cir.zero : !u8i, #cir.zero : !u8i, #cir.zero : !u8i]> : !cir.array, +// CIR-SAME: #cir.const_array<[ +// CIR-SAME: #cir.const_record<{#cir.int<0> : !s64i, +// CIR-SAME: #cir.int<1> : !s32i, +// CIR-SAME: #cir.const_array<[#cir.zero : !u8i, #cir.zero : !u8i, #cir.zero : !u8i, #cir.zero : !u8i]> : !cir.array +// CIR-SAME: }> : !rec_anon_struct +// CIR-SAME: ]> : !cir.array +// CIR-SAME: }> : !rec_anon_struct2, +// CIR-SAME: #cir.const_record<{#cir.int<1> : !s32i, +// CIR-SAME: #cir.const_array<[#cir.zero : !u8i, #cir.zero : !u8i, #cir.zero : !u8i, #cir.zero : !u8i]> : !cir.array, +// CIR-SAME: #cir.zero : !cir.array +// CIR-SAME: }> : !rec_anon_struct1 +// CIR-SAME: }> : !rec_anon_struct3 +// LLVM: @outers = {{.*}}global +// LLVM-SAME: { +// LLVM-SAME: { i32, [4 x i8], [1 x { i64, i32, [4 x i8] }] }, +// LLVM-SAME: { i32, [4 x i8], [1 x %struct.Inner] } +// LLVM-SAME: } +// LLVM-SAME: { +// LLVM-SAME: { i32, [4 x i8], [1 x { i64, i32, [4 x i8] }] } +// LLVM-SAME: { i32 1, [4 x i8] zeroinitializer, [1 x { i64, i32, [4 x i8] }] [{ i64, i32, [4 x i8] } { i64 0, i32 1, [4 x i8] zeroinitializer }] }, +// LLVM-SAME: { i32, [4 x i8], [1 x %struct.Inner] } +// LLVM-SAME: { i32 1, [4 x i8] zeroinitializer, [1 x %struct.Inner] zeroinitializer } +// LLVM-SAME: } + void buz(int x) { T arr[] = { {x, x}, {0, 0} }; } diff --git a/clang/test/CIR/Lowering/nested-union-array.c b/clang/test/CIR/Lowering/nested-union-array.c index f48f687dc2ab..1cf04242d398 100644 --- a/clang/test/CIR/Lowering/nested-union-array.c +++ b/clang/test/CIR/Lowering/nested-union-array.c @@ -11,7 +11,7 @@ struct nested static const char * const test[] = { "test", }; -const struct nested data[] = +const struct nested data[] = { { { @@ -25,4 +25,4 @@ const struct nested data[] = }, }; -// LLVM: @data = constant [2 x {{.*}}] +// LLVM: @data = constant { { { ptr } }, { { ptr } } }