Skip to content

Commit 782f5aa

Browse files
committed
[CIR] [CIRGen] Handle CIR Gen for array of unions
Close llvm#1185 The patch itself seems slightly ad-hoc. As the issue tracked by llvm#1178, the fundamental solution may be to introduce two type systems to solve the inconsistent semantics for Union between LLVM IR and CIR. This will be great to handle other inconsistent semantics between LLVM IR and CIR if any. Back to the patch itself, although the code looks not good initially to me too. But I feel it may be a good workaround since clang/test/CIR/Lowering/union-array.c is an example for array of unions directly and clang/test/CIR/Lowering/nested-union-array.c gives an example for array of unions indirectly (array of structs which contain unions). So I feel we've already covered all the cases. And generally it should be good to use some simple and solid workaround before we introduce the formal full solution.
1 parent a989ecb commit 782f5aa

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

clang/lib/CIR/CodeGen/CIRGenExprConst.cpp

+17-1
Original file line numberDiff line numberDiff line change
@@ -1015,6 +1015,20 @@ class ConstExprEmitter
10151015
return {};
10161016
}
10171017

1018+
auto desiredType = CGM.getTypes().ConvertType(T);
1019+
bool isDesiredArrayOfUnionDirectly = [&]() {
1020+
auto desiredArrayType = dyn_cast<cir::ArrayType>(desiredType);
1021+
if (!desiredArrayType)
1022+
return false;
1023+
1024+
auto elementStructType =
1025+
dyn_cast<cir::StructType>(desiredArrayType.getEltType());
1026+
if (!elementStructType)
1027+
return false;
1028+
1029+
return elementStructType.isUnion();
1030+
}();
1031+
10181032
// Emit initializer elements as MLIR attributes and check for common type.
10191033
mlir::Type CommonElementType;
10201034
for (unsigned i = 0; i != NumInitableElts; ++i) {
@@ -1024,10 +1038,12 @@ class ConstExprEmitter
10241038
return {};
10251039
if (i == 0)
10261040
CommonElementType = C.getType();
1041+
else if (isDesiredArrayOfUnionDirectly &&
1042+
C.getType() != CommonElementType)
1043+
CommonElementType = nullptr;
10271044
Elts.push_back(std::move(C));
10281045
}
10291046

1030-
auto desiredType = CGM.getTypes().ConvertType(T);
10311047
auto typedFiller = llvm::dyn_cast_or_null<mlir::TypedAttr>(Filler);
10321048
if (Filler && !typedFiller)
10331049
llvm_unreachable("We shouldn't be receiving untyped attrs here");

clang/test/CIR/Lowering/union-array.c

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm -fno-clangir-call-conv-lowering %s -o %t.ll
2+
// RUN: FileCheck --input-file=%t.ll %s --check-prefix=LLVM
3+
4+
typedef struct {
5+
char a;
6+
} S_1;
7+
8+
typedef struct {
9+
long a, b;
10+
} S_2;
11+
12+
typedef union {
13+
S_1 a;
14+
S_2 b;
15+
} U;
16+
17+
void foo() { U arr[2] = {{.b = {1, 2}}, {.a = {1}}}; }
18+
19+
// LLVM: store { { %struct.S_2 }, { %struct.S_1, [15 x i8] } } { { %struct.S_2 } { %struct.S_2 { i64 1, i64 2 } }, { %struct.S_1, [15 x i8] } { %struct.S_1 { i8 1 }, [15 x i8] zeroinitializer } }

0 commit comments

Comments
 (0)