Skip to content

Commit

Permalink
[CIR] [CIRGen] Handle CIR Gen for array of unions
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ChuanqiXu9 committed Dec 16, 2024
1 parent a989ecb commit 782f5aa
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 1 deletion.
18 changes: 17 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenExprConst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1015,6 +1015,20 @@ class ConstExprEmitter
return {};
}

auto desiredType = CGM.getTypes().ConvertType(T);
bool isDesiredArrayOfUnionDirectly = [&]() {
auto desiredArrayType = dyn_cast<cir::ArrayType>(desiredType);
if (!desiredArrayType)
return false;

auto elementStructType =
dyn_cast<cir::StructType>(desiredArrayType.getEltType());
if (!elementStructType)
return false;

return elementStructType.isUnion();
}();

// Emit initializer elements as MLIR attributes and check for common type.
mlir::Type CommonElementType;
for (unsigned i = 0; i != NumInitableElts; ++i) {
Expand All @@ -1024,10 +1038,12 @@ class ConstExprEmitter
return {};
if (i == 0)
CommonElementType = C.getType();
else if (isDesiredArrayOfUnionDirectly &&
C.getType() != CommonElementType)
CommonElementType = nullptr;
Elts.push_back(std::move(C));
}

auto desiredType = CGM.getTypes().ConvertType(T);
auto typedFiller = llvm::dyn_cast_or_null<mlir::TypedAttr>(Filler);
if (Filler && !typedFiller)
llvm_unreachable("We shouldn't be receiving untyped attrs here");
Expand Down
19 changes: 19 additions & 0 deletions clang/test/CIR/Lowering/union-array.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm -fno-clangir-call-conv-lowering %s -o %t.ll
// RUN: FileCheck --input-file=%t.ll %s --check-prefix=LLVM

typedef struct {
char a;
} S_1;

typedef struct {
long a, b;
} S_2;

typedef union {
S_1 a;
S_2 b;
} U;

void foo() { U arr[2] = {{.b = {1, 2}}, {.a = {1}}}; }

// 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 comments on commit 782f5aa

Please sign in to comment.