Skip to content

Commit

Permalink
[CIR][Codegen] Fix union init with constant (#548)
Browse files Browse the repository at this point in the history
Minor fix for the case when union fields have different sizes and union
is inited with a constant.
Example:
```
typedef union {
  short a;
  int b;
} A;
```
  • Loading branch information
gitoleg authored and lanza committed Apr 29, 2024
1 parent 9e9f342 commit d2a6011
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 1 deletion.
6 changes: 5 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenExprConst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,11 @@ mlir::Attribute ConstantAggregateBuilder::buildFrom(
NaturalLayout = false;
Packed = true;
} else if (DesiredSize > AlignedSize) {
llvm_unreachable("NYI");
// The natural layout would be too small. Add padding to fix it. (This
// is ignored if we choose a packed layout.)
UnpackedElemStorage.assign(Elems.begin(), Elems.end());
UnpackedElemStorage.push_back(Utils.getPadding(DesiredSize - Size));
UnpackedElems = UnpackedElemStorage;
}

// If we don't have a natural layout, insert padding as necessary.
Expand Down
13 changes: 13 additions & 0 deletions clang/test/CIR/CodeGen/union.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,16 @@ void shouldGenerateUnionAccess(union U u) {
u.d;
// CHECK: %[[#BASE:]] = cir.get_member %0[4] {name = "d"} : !cir.ptr<!ty_22U22> -> !cir.ptr<!cir.double>
}

typedef union {
short a;
int b;
} A;

void noCrushOnDifferentSizes() {
A a = {0};
// CHECK: %[[#TMP0:]] = cir.alloca !ty_22A22, cir.ptr <!ty_22A22>, ["a"] {alignment = 4 : i64}
// CHECK: %[[#TMP1:]] = cir.cast(bitcast, %[[#TMP0]] : !cir.ptr<!ty_22A22>), !cir.ptr<!ty_anon_struct>
// CHECK: %[[#TMP2:]] = cir.const(#cir.zero : !ty_anon_struct) : !ty_anon_struct
// CHECK: cir.store %[[#TMP2]], %[[#TMP1]] : !ty_anon_struct, cir.ptr <!ty_anon_struct>
}

0 comments on commit d2a6011

Please sign in to comment.