Skip to content

[CIR][CodeGen] Updates GlobalViewAttr's indices computation for the union type #1584

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
May 6, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions clang/lib/CIR/CodeGen/CIRGenBuilder.cpp
Original file line number Diff line number Diff line change
@@ -95,15 +95,21 @@ void CIRGenBuilderTy::computeGlobalViewIndicesFromFlatOffset(
unsigned AlignMask = Layout.getABITypeAlign(Elts[I]).value() - 1;
if (RecordTy.getPacked())
AlignMask = 0;
Pos = (Pos + AlignMask) & ~AlignMask;
// Union's fields have the same offset, so no need to change Pos here,
// we just need to find EltSize that is greater then the required offset.
// The same is true for the similar union type check below
if (!RecordTy.isUnion())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add some comment here so it's easy to understand why unions are different?

Pos = (Pos + AlignMask) & ~AlignMask;
assert(Offset >= 0);
if (Offset < Pos + EltSize) {
Indices.push_back(I);
SubType = Elts[I];
Offset -= Pos;
break;
}
Pos += EltSize;
// No need to update Pos here, see the comment above.
if (!RecordTy.isUnion())
Pos += EltSize;
}
} else {
llvm_unreachable("unexpected type");
20 changes: 20 additions & 0 deletions clang/test/CIR/CodeGen/union-array.c
Original file line number Diff line number Diff line change
@@ -26,6 +26,7 @@ static U1 g = {5};
// LLVM: @g = internal global { i32 } { i32 5 }
// FIXME: LLVM output should be: @g = internal global %union.U { i32 5 }

// LLVM: @g2 = global ptr getelementptr inbounds nuw (i8, ptr @g1, i64 24)

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

@@ -37,3 +38,22 @@ void bar(void) {
}
// CIR: cir.global "private" internal dsolocal @g = #cir.const_record<{#cir.int<5> : !s32i}> : !rec_anon_struct
// CIR: cir.const #cir.const_array<[#cir.global_view<@g> : !cir.ptr<!s32i>, #cir.global_view<@g> : !cir.ptr<!s32i>]> : !cir.array<!cir.ptr<!s32i> x 2>

typedef struct {
long s0;
int s1;
} S_3;

typedef union {
int f0;
S_3 f1;
} U2;


static U2 g1[3] = {{0x42},{0x42},{0x42}};
int* g2 = &g1[1].f1.s1;
// CIR: cir.global external @g2 = #cir.global_view<@g1, [1, 1, 4]> : !cir.ptr<!s32i>

void baz(void) {
(*g2) = 4;
}