Skip to content

Commit

Permalink
[CIR][CodeGen][BugFix] Fixes structures name collisions (llvm#844)
Browse files Browse the repository at this point in the history
CIR Codegen fails to generate functions with local types with the same
names. For instance, the next code :
```
void foo(int a, float b) {
  struct A { int x; };
  struct A loc = {a};
  {
    struct A { float y; };
    struct A loc = {b};
  }
}
```
fails with on the next assertion: `Unable to find record layout
information for type`. The problem is that we don't create record layout
for the structures with equal names and
`CIRGenTypes::convertRecordDeclType` returns the wrong type for the
second struct type in the example above. This PR fixes this problem.

In the original codegen the call to `Ty->setName(name)` resolves name
collisions and assign a proper name for the type. In our case looks like
we need to use the same approach as we did for the anonymous structures,
i.e. to track the used names in the builder.

Also, I fixed the struct type creation. Previously, the type was created
several times - first in the `CIRGenTypes::convertRecordDeclType` and
then in the `CIRGenTypes::computeRecordLayout`. This is why the indexes
used by the anonymous structures naming had relatively big values and
this is where the most changes on the tests come from.
  • Loading branch information
gitoleg authored and smeenai committed Oct 9, 2024
1 parent d067fd4 commit 2f8af5e
Show file tree
Hide file tree
Showing 14 changed files with 83 additions and 60 deletions.
20 changes: 15 additions & 5 deletions clang/lib/CIR/CodeGen/CIRGenBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,26 @@ class CIRGenBuilderTy : public CIRBaseBuilderTy {
llvm::RoundingMode DefaultConstrainedRounding = llvm::RoundingMode::Dynamic;

llvm::StringMap<unsigned> GlobalsVersioning;
llvm::StringSet<> anonRecordNames;
llvm::StringMap<unsigned> RecordNames;

public:
CIRGenBuilderTy(mlir::MLIRContext &C, const CIRGenTypeCache &tc)
: CIRBaseBuilderTy(C), typeCache(tc) {}
: CIRBaseBuilderTy(C), typeCache(tc) {
RecordNames["anon"] = 0; // in order to start from the name "anon.0"
}

std::string getUniqueAnonRecordName() {
std::string name = "anon." + std::to_string(anonRecordNames.size());
anonRecordNames.insert(name);
return name;
return getUniqueRecordName("anon");
}

std::string getUniqueRecordName(const std::string& baseName) {
auto it = RecordNames.find(baseName);
if (it == RecordNames.end()) {
RecordNames[baseName] = 0;
return baseName;
}

return baseName + "." + std::to_string(RecordNames[baseName]++);
}

//
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CIR/CodeGen/CIRGenTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ std::string CIRGenTypes::getRecordTypeName(const clang::RecordDecl *recordDecl,
if (!suffix.empty())
outStream << suffix;

return std::string(typeName);
return Builder.getUniqueRecordName(std::string(typeName));
}

/// Return true if the specified type is already completely laid out.
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CIR/CodeGen/CIRRecordLayoutBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -689,8 +689,8 @@ CIRGenTypes::computeRecordLayout(const RecordDecl *D,
// Fill in the struct *after* computing the base type. Filling in the body
// signifies that the type is no longer opaque and record layout is complete,
// but we may need to recursively layout D while laying D out as a base type.
*Ty = Builder.getCompleteStructTy(
builder.fieldTypes, getRecordTypeName(D, ""), builder.isPacked, D);
auto astAttr = mlir::cir::ASTRecordDeclAttr::get(Ty->getContext(), D);
Ty->complete(builder.fieldTypes, builder.isPacked, astAttr);

auto RL = std::make_unique<CIRGenRecordLayout>(
Ty ? *Ty : mlir::cir::StructType{},
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CIR/CodeGen/bitfields.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@ typedef struct {

// CHECK: !ty_D = !cir.struct<struct "D" {!u16i, !s32i}>
// CHECK: !ty_T = !cir.struct<struct "T" {!u8i, !u32i} #cir.record.decl.ast>
// CHECK: !ty_anon2E1_ = !cir.struct<struct "anon.1" {!u32i} #cir.record.decl.ast>
// CHECK: !ty_anon2E0_ = !cir.struct<struct "anon.0" {!u32i} #cir.record.decl.ast>
// CHECK: !ty_anon_struct = !cir.struct<struct {!u8i, !u8i, !s32i}>
// CHECK: #bfi_a = #cir.bitfield_info<name = "a", storage_type = !u8i, size = 3, offset = 0, is_signed = true>
// CHECK: #bfi_e = #cir.bitfield_info<name = "e", storage_type = !u16i, size = 15, offset = 0, is_signed = true>
// CHECK: !ty_S = !cir.struct<struct "S" {!u32i, !cir.array<!u8i x 3>, !u16i, !u32i}>
// CHECK: !ty_U = !cir.struct<struct "U" {!s8i, !s8i, !s8i, !cir.array<!u8i x 9>}>
// CHECK: !ty___long = !cir.struct<struct "__long" {!ty_anon2E1_, !u32i, !cir.ptr<!u32i>}>
// CHECK: !ty___long = !cir.struct<struct "__long" {!ty_anon2E0_, !u32i, !cir.ptr<!u32i>}>
// CHECK: #bfi_d = #cir.bitfield_info<name = "d", storage_type = !cir.array<!u8i x 3>, size = 2, offset = 17, is_signed = true>

// CHECK: cir.func {{.*@store_field}}
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CIR/CodeGen/bitfields.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ typedef struct {
unsigned b;
} T;
// CHECK: !ty_T = !cir.struct<struct "T" {!u8i, !u32i} #cir.record.decl.ast>
// CHECK: !ty_anon2E1_ = !cir.struct<struct "anon.1" {!u32i} #cir.record.decl.ast>
// CHECK: !ty_anon2E0_ = !cir.struct<struct "anon.0" {!u32i} #cir.record.decl.ast>
// CHECK: !ty_S = !cir.struct<struct "S" {!u32i, !cir.array<!u8i x 3>, !u16i, !u32i}>
// CHECK: !ty___long = !cir.struct<struct "__long" {!ty_anon2E1_, !u32i, !cir.ptr<!u32i>}>
// CHECK: !ty___long = !cir.struct<struct "__long" {!ty_anon2E0_, !u32i, !cir.ptr<!u32i>}>

// CHECK: cir.func @_Z11store_field
// CHECK: [[TMP0:%.*]] = cir.alloca !ty_S, !cir.ptr<!ty_S>
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CIR/CodeGen/compound-literal.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ int foo() {

// CIR: cir.func no_proto @foo() -> !s32i
// CIR: [[RET_MEM:%.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64}
// CIR: [[COMPLITERAL_MEM:%.*]] = cir.alloca !ty_anon2E1_, !cir.ptr<!ty_anon2E1_>, [".compoundliteral"] {alignment = 4 : i64}
// CIR: [[FIELD:%.*]] = cir.get_member [[COMPLITERAL_MEM]][0] {name = "i"} : !cir.ptr<!ty_anon2E1_> -> !cir.ptr<!s32i>
// CIR: [[COMPLITERAL_MEM:%.*]] = cir.alloca !ty_anon2E0_, !cir.ptr<!ty_anon2E0_>, [".compoundliteral"] {alignment = 4 : i64}
// CIR: [[FIELD:%.*]] = cir.get_member [[COMPLITERAL_MEM]][0] {name = "i"} : !cir.ptr<!ty_anon2E0_> -> !cir.ptr<!s32i>
// CIR: [[ONE:%.*]] = cir.const #cir.int<1> : !s32i
// CIR: cir.store [[ONE]], [[FIELD]] : !s32i, !cir.ptr<!s32i>
// CIR: [[ONE:%.*]] = cir.const #cir.int<1> : !s32i
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CIR/CodeGen/coro-task.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,10 +356,10 @@ folly::coro::Task<int> go4() {
// CHECK: }

// CHECK: %12 = cir.scope {
// CHECK: %17 = cir.alloca !ty_anon2E5_, !cir.ptr<!ty_anon2E5_>, ["ref.tmp1"] {alignment = 1 : i64}
// CHECK: %17 = cir.alloca !ty_anon2E2_, !cir.ptr<!ty_anon2E2_>, ["ref.tmp1"] {alignment = 1 : i64}

// Get the lambda invoker ptr via `lambda operator folly::coro::Task<int> (*)(int const&)()`
// CHECK: %18 = cir.call @_ZZ3go4vENK3$_0cvPFN5folly4coro4TaskIiEERKiEEv(%17) : (!cir.ptr<!ty_anon2E5_>) -> !cir.ptr<!cir.func<![[IntTask]] (!cir.ptr<!s32i>)>>
// CHECK: %18 = cir.call @_ZZ3go4vENK3$_0cvPFN5folly4coro4TaskIiEERKiEEv(%17) : (!cir.ptr<!ty_anon2E2_>) -> !cir.ptr<!cir.func<![[IntTask]] (!cir.ptr<!s32i>)>>
// CHECK: %19 = cir.unary(plus, %18) : !cir.ptr<!cir.func<![[IntTask]] (!cir.ptr<!s32i>)>>, !cir.ptr<!cir.func<![[IntTask]] (!cir.ptr<!s32i>)>>
// CHECK: cir.yield %19 : !cir.ptr<!cir.func<![[IntTask]] (!cir.ptr<!s32i>)>>
// CHECK: }
Expand Down
13 changes: 6 additions & 7 deletions clang/test/CIR/CodeGen/forward-decls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,12 @@ void testIndirectSelfReference(struct StructNodeA arg) {
// RUN: FileCheck --check-prefix=CHECK5 --input-file=%t/complex_struct.cir %s

// A sizeable complex struct just to double check that stuff is working.

// CHECK5: !cir.struct<struct "anon.1" {!cir.ptr<!cir.struct<struct "A" {!cir.struct<struct "anon.1">, !cir.struct<struct "B" {!cir.ptr<!cir.struct<struct "B">>, !cir.struct<struct "C" {!cir.ptr<!cir.struct<struct "A">>, !cir.ptr<!cir.struct<struct "B">>, !cir.ptr<!cir.struct<struct "C">>} #cir.record.decl.ast>, !cir.struct<union "anon.5" {!cir.ptr<!cir.struct<struct "A">>, !cir.struct<struct "anon.4" {!cir.ptr<!cir.struct<struct "B">>} #cir.record.decl.ast>} #cir.record.decl.ast>} #cir.record.decl.ast>} #cir.record.decl.ast>>} #cir.record.decl.ast>
// CHECK5: !cir.struct<struct "C" {!cir.ptr<!cir.struct<struct "A" {!ty_anon2E1_, !cir.struct<struct "B" {!cir.ptr<!cir.struct<struct "B">>, !cir.struct<struct "C">, !cir.struct<union "anon.5" {!cir.ptr<!cir.struct<struct "A">>, !cir.struct<struct "anon.4" {!cir.ptr<!cir.struct<struct "B">>} #cir.record.decl.ast>} #cir.record.decl.ast>} #cir.record.decl.ast>} #cir.record.decl.ast>>, !cir.ptr<!cir.struct<struct "B" {!cir.ptr<!cir.struct<struct "B">>, !cir.struct<struct "C">, !cir.struct<union "anon.5" {!cir.ptr<!cir.struct<struct "A" {!ty_anon2E1_, !cir.struct<struct "B">} #cir.record.decl.ast>>, !cir.struct<struct "anon.4" {!cir.ptr<!cir.struct<struct "B">>} #cir.record.decl.ast>} #cir.record.decl.ast>} #cir.record.decl.ast>>, !cir.ptr<!cir.struct<struct "C">>} #cir.record.decl.ast>
// CHECK5: !cir.struct<struct "anon.4" {!cir.ptr<!cir.struct<struct "B" {!cir.ptr<!cir.struct<struct "B">>, !ty_C, !cir.struct<union "anon.5" {!cir.ptr<!cir.struct<struct "A" {!ty_anon2E1_, !cir.struct<struct "B">} #cir.record.decl.ast>>, !cir.struct<struct "anon.4">} #cir.record.decl.ast>} #cir.record.decl.ast>>} #cir.record.decl.ast>
// CHECK5: !cir.struct<union "anon.5" {!cir.ptr<!cir.struct<struct "A" {!ty_anon2E1_, !cir.struct<struct "B" {!cir.ptr<!cir.struct<struct "B">>, !ty_C, !cir.struct<union "anon.5">} #cir.record.decl.ast>} #cir.record.decl.ast>>, !ty_anon2E4_} #cir.record.decl.ast>
// CHECK5: !cir.struct<struct "B" {!cir.ptr<!cir.struct<struct "B">>, !ty_C, !ty_anon2E5_} #cir.record.decl.ast>
// CHECK5: !cir.struct<struct "A" {!ty_anon2E1_, !ty_B} #cir.record.decl.ast>
// CHECK5: !cir.struct<struct "anon.0" {!cir.ptr<!cir.struct<struct "A" {!cir.struct<struct "anon.0">, !cir.struct<struct "B" {!cir.ptr<!cir.struct<struct "B">>, !cir.struct<struct "C" {!cir.ptr<!cir.struct<struct "A">>, !cir.ptr<!cir.struct<struct "B">>, !cir.ptr<!cir.struct<struct "C">>} #cir.record.decl.ast>, !cir.struct<union "anon.1" {!cir.ptr<!cir.struct<struct "A">>, !cir.struct<struct "anon.2" {!cir.ptr<!cir.struct<struct "B">>} #cir.record.decl.ast>} #cir.record.decl.ast>} #cir.record.decl.ast>} #cir.record.decl.ast>>} #cir.record.decl.ast>
// CHECK5: !cir.struct<struct "C" {!cir.ptr<!cir.struct<struct "A" {!ty_anon2E0_, !cir.struct<struct "B" {!cir.ptr<!cir.struct<struct "B">>, !cir.struct<struct "C">, !cir.struct<union "anon.1" {!cir.ptr<!cir.struct<struct "A">>, !cir.struct<struct "anon.2" {!cir.ptr<!cir.struct<struct "B">>} #cir.record.decl.ast>} #cir.record.decl.ast>} #cir.record.decl.ast>} #cir.record.decl.ast>>, !cir.ptr<!cir.struct<struct "B" {!cir.ptr<!cir.struct<struct "B">>, !cir.struct<struct "C">, !cir.struct<union "anon.1" {!cir.ptr<!cir.struct<struct "A" {!ty_anon2E0_, !cir.struct<struct "B">} #cir.record.decl.ast>>, !cir.struct<struct "anon.2" {!cir.ptr<!cir.struct<struct "B">>} #cir.record.decl.ast>} #cir.record.decl.ast>} #cir.record.decl.ast>>, !cir.ptr<!cir.struct<struct "C">>} #cir.record.decl.ast>
// CHECK5: !cir.struct<struct "anon.2" {!cir.ptr<!cir.struct<struct "B" {!cir.ptr<!cir.struct<struct "B">>, !ty_C, !cir.struct<union "anon.1" {!cir.ptr<!cir.struct<struct "A" {!ty_anon2E0_, !cir.struct<struct "B">} #cir.record.decl.ast>>, !cir.struct<struct "anon.2">} #cir.record.decl.ast>} #cir.record.decl.ast>>} #cir.record.decl.ast>
// CHECK5: !cir.struct<union "anon.1" {!cir.ptr<!cir.struct<struct "A" {!ty_anon2E0_, !cir.struct<struct "B" {!cir.ptr<!cir.struct<struct "B">>, !ty_C, !cir.struct<union "anon.1">} #cir.record.decl.ast>} #cir.record.decl.ast>>, !ty_anon2E2_} #cir.record.decl.ast>
// CHECK5: !cir.struct<struct "B" {!cir.ptr<!cir.struct<struct "B">>, !ty_C, !ty_anon2E1_} #cir.record.decl.ast>
// CHECK5: !cir.struct<struct "A" {!ty_anon2E0_, !ty_B} #cir.record.decl.ast>
struct A {
struct {
struct A *a1;
Expand Down
8 changes: 4 additions & 4 deletions clang/test/CIR/CodeGen/globals.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,25 +57,25 @@ const int i = 12;
int i2 = i;
struct { int i; } i3 = {i};
// CHECK: cir.global external @i2 = #cir.int<12> : !s32i
// CHECK: cir.global external @i3 = #cir.const_struct<{#cir.int<12> : !s32i}> : !ty_anon2E7_
// CHECK: cir.global external @i3 = #cir.const_struct<{#cir.int<12> : !s32i}> : !ty_anon2E3_

int a[10][10][10];
int *a2 = &a[3][0][8];
struct { int *p; } a3 = {&a[3][0][8]};
// CHECK: cir.global external @a2 = #cir.global_view<@a, [3 : i32, 0 : i32, 8 : i32]> : !cir.ptr<!s32i>
// CHECK: cir.global external @a3 = #cir.const_struct<{#cir.global_view<@a, [3 : i32, 0 : i32, 8 : i32]> : !cir.ptr<!s32i>}> : !ty_anon2E9_
// CHECK: cir.global external @a3 = #cir.const_struct<{#cir.global_view<@a, [3 : i32, 0 : i32, 8 : i32]> : !cir.ptr<!s32i>}> : !ty_anon2E4_

int p[10];
int *p1 = &p[0];
struct { int *x; } p2 = {&p[0]};
// CHECK: cir.global external @p1 = #cir.global_view<@p> : !cir.ptr<!s32i>
// CHECK: cir.global external @p2 = #cir.const_struct<{#cir.global_view<@p> : !cir.ptr<!s32i>}> : !ty_anon2E11_
// CHECK: cir.global external @p2 = #cir.const_struct<{#cir.global_view<@p> : !cir.ptr<!s32i>}> : !ty_anon2E5_

int q[10];
int *q1 = q;
struct { int *x; } q2 = {q};
// CHECK: cir.global external @q1 = #cir.global_view<@q> : !cir.ptr<!s32i>
// CHECK: cir.global external @q2 = #cir.const_struct<{#cir.global_view<@q> : !cir.ptr<!s32i>}> : !ty_anon2E13_
// CHECK: cir.global external @q2 = #cir.const_struct<{#cir.global_view<@q> : !cir.ptr<!s32i>}> : !ty_anon2E6_

int foo() {
extern int optind;
Expand Down
46 changes: 23 additions & 23 deletions clang/test/CIR/CodeGen/lambda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ void fn() {
a();
}

// CHECK: !ty_anon2E2_ = !cir.struct<class "anon.2" {!u8i}>
// CHECK: !ty_anon2E0_ = !cir.struct<class "anon.0" {!u8i}>
// CHECK-DAG: module

// CHECK: cir.func lambda internal private @_ZZ2fnvENK3$_0clEv{{.*}}) extra

// CHECK: cir.func @_Z2fnv()
// CHECK-NEXT: %0 = cir.alloca !ty_anon2E2_, !cir.ptr<!ty_anon2E2_>, ["a"]
// CHECK-NEXT: %0 = cir.alloca !ty_anon2E0_, !cir.ptr<!ty_anon2E0_>, ["a"]
// CHECK: cir.call @_ZZ2fnvENK3$_0clEv

void l0() {
Expand All @@ -23,15 +23,15 @@ void l0() {

// CHECK: cir.func lambda internal private @_ZZ2l0vENK3$_0clEv({{.*}}) extra

// CHECK: %0 = cir.alloca !cir.ptr<!ty_anon2E4_>, !cir.ptr<!cir.ptr<!ty_anon2E4_>>, ["this", init] {alignment = 8 : i64}
// CHECK: cir.store %arg0, %0 : !cir.ptr<!ty_anon2E4_>, !cir.ptr<!cir.ptr<!ty_anon2E4_>>
// CHECK: %1 = cir.load %0 : !cir.ptr<!cir.ptr<!ty_anon2E4_>>, !cir.ptr<!ty_anon2E4_>
// CHECK: %2 = cir.get_member %1[0] {name = "i"} : !cir.ptr<!ty_anon2E4_> -> !cir.ptr<!cir.ptr<!s32i>>
// CHECK: %0 = cir.alloca !cir.ptr<!ty_anon2E2_>, !cir.ptr<!cir.ptr<!ty_anon2E2_>>, ["this", init] {alignment = 8 : i64}
// CHECK: cir.store %arg0, %0 : !cir.ptr<!ty_anon2E2_>, !cir.ptr<!cir.ptr<!ty_anon2E2_>>
// CHECK: %1 = cir.load %0 : !cir.ptr<!cir.ptr<!ty_anon2E2_>>, !cir.ptr<!ty_anon2E2_>
// CHECK: %2 = cir.get_member %1[0] {name = "i"} : !cir.ptr<!ty_anon2E2_> -> !cir.ptr<!cir.ptr<!s32i>>
// CHECK: %3 = cir.load %2 : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
// CHECK: %4 = cir.load %3 : !cir.ptr<!s32i>, !s32i
// CHECK: %5 = cir.const #cir.int<1> : !s32i
// CHECK: %6 = cir.binop(add, %4, %5) nsw : !s32i
// CHECK: %7 = cir.get_member %1[0] {name = "i"} : !cir.ptr<!ty_anon2E4_> -> !cir.ptr<!cir.ptr<!s32i>>
// CHECK: %7 = cir.get_member %1[0] {name = "i"} : !cir.ptr<!ty_anon2E2_> -> !cir.ptr<!cir.ptr<!s32i>>
// CHECK: %8 = cir.load %7 : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
// CHECK: cir.store %6, %8 : !s32i, !cir.ptr<!s32i>

Expand All @@ -45,15 +45,15 @@ auto g() {
};
}

// CHECK: cir.func @_Z1gv() -> !ty_anon2E6_
// CHECK: %0 = cir.alloca !ty_anon2E6_, !cir.ptr<!ty_anon2E6_>, ["__retval"] {alignment = 8 : i64}
// CHECK: cir.func @_Z1gv() -> !ty_anon2E3_
// CHECK: %0 = cir.alloca !ty_anon2E3_, !cir.ptr<!ty_anon2E3_>, ["__retval"] {alignment = 8 : i64}
// CHECK: %1 = cir.alloca !s32i, !cir.ptr<!s32i>, ["i", init] {alignment = 4 : i64}
// CHECK: %2 = cir.const #cir.int<12> : !s32i
// CHECK: cir.store %2, %1 : !s32i, !cir.ptr<!s32i>
// CHECK: %3 = cir.get_member %0[0] {name = "i"} : !cir.ptr<!ty_anon2E6_> -> !cir.ptr<!cir.ptr<!s32i>>
// CHECK: %3 = cir.get_member %0[0] {name = "i"} : !cir.ptr<!ty_anon2E3_> -> !cir.ptr<!cir.ptr<!s32i>>
// CHECK: cir.store %1, %3 : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
// CHECK: %4 = cir.load %0 : !cir.ptr<!ty_anon2E6_>, !ty_anon2E6_
// CHECK: cir.return %4 : !ty_anon2E6_
// CHECK: %4 = cir.load %0 : !cir.ptr<!ty_anon2E3_>, !ty_anon2E3_
// CHECK: cir.return %4 : !ty_anon2E3_

auto g2() {
int i = 12;
Expand All @@ -65,15 +65,15 @@ auto g2() {
}

// Should be same as above because of NRVO
// CHECK: cir.func @_Z2g2v() -> !ty_anon2E8_
// CHECK-NEXT: %0 = cir.alloca !ty_anon2E8_, !cir.ptr<!ty_anon2E8_>, ["__retval", init] {alignment = 8 : i64}
// CHECK: cir.func @_Z2g2v() -> !ty_anon2E4_
// CHECK-NEXT: %0 = cir.alloca !ty_anon2E4_, !cir.ptr<!ty_anon2E4_>, ["__retval", init] {alignment = 8 : i64}
// CHECK-NEXT: %1 = cir.alloca !s32i, !cir.ptr<!s32i>, ["i", init] {alignment = 4 : i64}
// CHECK-NEXT: %2 = cir.const #cir.int<12> : !s32i
// CHECK-NEXT: cir.store %2, %1 : !s32i, !cir.ptr<!s32i>
// CHECK-NEXT: %3 = cir.get_member %0[0] {name = "i"} : !cir.ptr<!ty_anon2E8_> -> !cir.ptr<!cir.ptr<!s32i>>
// CHECK-NEXT: %3 = cir.get_member %0[0] {name = "i"} : !cir.ptr<!ty_anon2E4_> -> !cir.ptr<!cir.ptr<!s32i>>
// CHECK-NEXT: cir.store %1, %3 : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
// CHECK-NEXT: %4 = cir.load %0 : !cir.ptr<!ty_anon2E8_>, !ty_anon2E8_
// CHECK-NEXT: cir.return %4 : !ty_anon2E8_
// CHECK-NEXT: %4 = cir.load %0 : !cir.ptr<!ty_anon2E4_>, !ty_anon2E4_
// CHECK-NEXT: cir.return %4 : !ty_anon2E4_

int f() {
return g2()();
Expand All @@ -82,10 +82,10 @@ int f() {
// CHECK: cir.func @_Z1fv() -> !s32i
// CHECK-NEXT: %0 = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64}
// CHECK-NEXT: cir.scope {
// CHECK-NEXT: %2 = cir.alloca !ty_anon2E8_, !cir.ptr<!ty_anon2E8_>, ["ref.tmp0"] {alignment = 8 : i64}
// CHECK-NEXT: %3 = cir.call @_Z2g2v() : () -> !ty_anon2E8_
// CHECK-NEXT: cir.store %3, %2 : !ty_anon2E8_, !cir.ptr<!ty_anon2E8_>
// CHECK-NEXT: %4 = cir.call @_ZZ2g2vENK3$_0clEv(%2) : (!cir.ptr<!ty_anon2E8_>) -> !s32i
// CHECK-NEXT: %2 = cir.alloca !ty_anon2E4_, !cir.ptr<!ty_anon2E4_>, ["ref.tmp0"] {alignment = 8 : i64}
// CHECK-NEXT: %3 = cir.call @_Z2g2v() : () -> !ty_anon2E4_
// CHECK-NEXT: cir.store %3, %2 : !ty_anon2E4_, !cir.ptr<!ty_anon2E4_>
// CHECK-NEXT: %4 = cir.call @_ZZ2g2vENK3$_0clEv(%2) : (!cir.ptr<!ty_anon2E4_>) -> !s32i
// CHECK-NEXT: cir.store %4, %0 : !s32i, !cir.ptr<!s32i>
// CHECK-NEXT: }
// CHECK-NEXT: %1 = cir.load %0 : !cir.ptr<!s32i>, !s32i
Expand Down Expand Up @@ -114,8 +114,8 @@ int g3() {

// 1. Use `operator int (*)(int const&)()` to retrieve the fnptr to `__invoke()`.
// CHECK: %3 = cir.scope {
// CHECK: %7 = cir.alloca !ty_anon2E11_, !cir.ptr<!ty_anon2E11_>, ["ref.tmp0"] {alignment = 1 : i64}
// CHECK: %8 = cir.call @_ZZ2g3vENK3$_0cvPFiRKiEEv(%7) : (!cir.ptr<!ty_anon2E11_>) -> !cir.ptr<!cir.func<!s32i (!cir.ptr<!s32i>)>>
// CHECK: %7 = cir.alloca !ty_anon2E5_, !cir.ptr<!ty_anon2E5_>, ["ref.tmp0"] {alignment = 1 : i64}
// CHECK: %8 = cir.call @_ZZ2g3vENK3$_0cvPFiRKiEEv(%7) : (!cir.ptr<!ty_anon2E5_>) -> !cir.ptr<!cir.func<!s32i (!cir.ptr<!s32i>)>>
// CHECK: %9 = cir.unary(plus, %8) : !cir.ptr<!cir.func<!s32i (!cir.ptr<!s32i>)>>, !cir.ptr<!cir.func<!s32i (!cir.ptr<!s32i>)>>
// CHECK: cir.yield %9 : !cir.ptr<!cir.func<!s32i (!cir.ptr<!s32i>)>>
// CHECK: }
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CIR/CodeGen/string-literals.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ struct {
// CIR: }>

// LLVM-LABEL: @literals
// LLVM: global %struct.anon.1 {
// LLVM: global %struct.anon.0 {
// LLVM: [10 x i8] c"1\00\00\00\00\00\00\00\00\00",
// LLVM: [10 x i8] zeroinitializer,
// LLVM: [10 x i8] zeroinitializer
Expand Down
14 changes: 14 additions & 0 deletions clang/test/CIR/CodeGen/struct.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ void baz(void) {
// CHECK-DAG: !ty_Node = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct "Node">>} #cir.record.decl.ast>
// CHECK-DAG: !ty_Bar = !cir.struct<struct "Bar" {!s32i, !s8i}>
// CHECK-DAG: !ty_Foo = !cir.struct<struct "Foo" {!s32i, !s8i, !ty_Bar}>
// CHECK-DAG: !ty_SLocal = !cir.struct<struct "SLocal" {!s32i}>
// CHECK-DAG: !ty_SLocal2E0_ = !cir.struct<struct "SLocal.0" {!cir.float}>
// CHECK-DAG: module {{.*}} {
// CHECK: cir.func @baz()
// CHECK-NEXT: %0 = cir.alloca !ty_Bar, !cir.ptr<!ty_Bar>, ["b"] {alignment = 4 : i64}
Expand Down Expand Up @@ -99,3 +101,15 @@ void local_decl(void) {
void useRecursiveType(NodeStru* a) {
a->next = 0;
}

// CHECK-DAG: cir.alloca !ty_SLocal, !cir.ptr<!ty_SLocal>, ["loc", init] {alignment = 4 : i64}
// CHECK-DAG: cir.scope {
// CHECK-DAG: cir.alloca !ty_SLocal2E0_, !cir.ptr<!ty_SLocal2E0_>, ["loc", init] {alignment = 4 : i64}
void local_structs(int a, float b) {
struct SLocal { int x; };
struct SLocal loc = {a};
{
struct SLocal { float y; };
struct SLocal loc = {b};
}
}
Loading

0 comments on commit 2f8af5e

Please sign in to comment.