|
13 | 13 | // CIR-DAG: !rec_InnerS = !cir.record<struct "InnerS" {!s32i, !s8i}>
|
14 | 14 | // CIR-DAG: !rec_PackedS = !cir.record<struct "PackedS" packed {!s32i, !s8i}>
|
15 | 15 | // CIR-DAG: !rec_PackedAndPaddedS = !cir.record<struct "PackedAndPaddedS" packed padded {!s32i, !s8i, !u8i}>
|
| 16 | +// CIR-DAG: !rec_NodeS = !cir.record<struct "NodeS" {!cir.ptr<!cir.record<struct "NodeS">>}> |
| 17 | +// CIR-DAG: !rec_RightS = !cir.record<struct "RightS" {!cir.ptr<!cir.record<struct "LeftS" {!cir.ptr<!cir.record<struct "RightS">>}>>}> |
| 18 | +// CIR-DAG: !rec_LeftS = !cir.record<struct "LeftS" {!cir.ptr<!rec_RightS>}> |
| 19 | +// CIR-DAG: !rec_CycleEnd = !cir.record<struct "CycleEnd" {!cir.ptr<!cir.record<struct "CycleStart" {!cir.ptr<!cir.record<struct "CycleMiddle" {!cir.ptr<!cir.record<struct "CycleEnd">>}>>}>>}> |
| 20 | +// CIR-DAG: !rec_CycleMiddle = !cir.record<struct "CycleMiddle" {!cir.ptr<!rec_CycleEnd>}> |
| 21 | +// CIR-DAG: !rec_CycleStart = !cir.record<struct "CycleStart" {!cir.ptr<!rec_CycleMiddle>}> |
16 | 22 | // LLVM-DAG: %struct.CompleteS = type { i32, i8 }
|
17 | 23 | // LLVM-DAG: %struct.OuterS = type { %struct.InnerS, i32 }
|
18 | 24 | // LLVM-DAG: %struct.InnerS = type { i32, i8 }
|
19 | 25 | // LLVM-DAG: %struct.PackedS = type <{ i32, i8 }>
|
20 | 26 | // LLVM-DAG: %struct.PackedAndPaddedS = type <{ i32, i8, i8 }>
|
| 27 | +// LLVM-DAG: %struct.NodeS = type { ptr } |
| 28 | +// LLVM-DAG: %struct.LeftS = type { ptr } |
| 29 | +// LLVM-DAG: %struct.RightS = type { ptr } |
| 30 | +// LLVM-DAG: %struct.CycleStart = type { ptr } |
| 31 | +// LLVM-DAG: %struct.CycleMiddle = type { ptr } |
| 32 | +// LLVM-DAG: %struct.CycleEnd = type { ptr } |
21 | 33 | // OGCG-DAG: %struct.CompleteS = type { i32, i8 }
|
22 | 34 | // OGCG-DAG: %struct.OuterS = type { %struct.InnerS, i32 }
|
23 | 35 | // OGCG-DAG: %struct.InnerS = type { i32, i8 }
|
24 | 36 | // OGCG-DAG: %struct.PackedS = type <{ i32, i8 }>
|
25 | 37 | // OGCG-DAG: %struct.PackedAndPaddedS = type <{ i32, i8, i8 }>
|
| 38 | +// OGCG-DAG: %struct.NodeS = type { ptr } |
| 39 | +// OGCG-DAG: %struct.LeftS = type { ptr } |
| 40 | +// OGCG-DAG: %struct.RightS = type { ptr } |
| 41 | +// OGCG-DAG: %struct.CycleStart = type { ptr } |
| 42 | +// OGCG-DAG: %struct.CycleMiddle = type { ptr } |
| 43 | +// OGCG-DAG: %struct.CycleEnd = type { ptr } |
26 | 44 |
|
27 | 45 | struct IncompleteS *p;
|
28 | 46 |
|
@@ -78,6 +96,59 @@ struct PackedAndPaddedS {
|
78 | 96 |
|
79 | 97 | #pragma pack(pop)
|
80 | 98 |
|
| 99 | +// Recursive type |
| 100 | +struct NodeS { |
| 101 | + struct NodeS* next; |
| 102 | +} node; |
| 103 | + |
| 104 | +// CIR: cir.global{{.*}} @node = #cir.zero : !rec_NodeS |
| 105 | +// LLVM-DAG: @node = dso_local global %struct.NodeS zeroinitializer |
| 106 | +// OGCG-DAG: @node = global %struct.NodeS zeroinitializer |
| 107 | + |
| 108 | +// Mutually dependent types |
| 109 | +struct RightS; |
| 110 | +struct LeftS { |
| 111 | + struct RightS* right; |
| 112 | +} ls; |
| 113 | + |
| 114 | +// CIR: cir.global{{.*}} @ls = #cir.zero : !rec_LeftS |
| 115 | +// LLVM-DAG: @ls = dso_local global %struct.LeftS zeroinitializer |
| 116 | +// OGCG-DAG: @ls = global %struct.LeftS zeroinitializer |
| 117 | + |
| 118 | +struct RightS { |
| 119 | + struct LeftS* left; |
| 120 | +} rs; |
| 121 | + |
| 122 | +// CIR: cir.global{{.*}} @rs = #cir.zero : !rec_RightS |
| 123 | +// LLVM-DAG: @rs = dso_local global %struct.RightS zeroinitializer |
| 124 | +// OGCG-DAG: @rs = global %struct.RightS zeroinitializer |
| 125 | + |
| 126 | +struct CycleMiddle; |
| 127 | +struct CycleEnd; |
| 128 | +struct CycleStart { |
| 129 | + struct CycleMiddle* middle; |
| 130 | +} start; |
| 131 | + |
| 132 | +// CIR: cir.global{{.*}} @start = #cir.zero : !rec_CycleStart |
| 133 | +// LLVM-DAG: @start = dso_local global %struct.CycleStart zeroinitializer |
| 134 | +// OGCG-DAG: @start = global %struct.CycleStart zeroinitializer |
| 135 | + |
| 136 | +struct CycleMiddle { |
| 137 | + struct CycleEnd* end; |
| 138 | +} middle; |
| 139 | + |
| 140 | +// CIR: cir.global{{.*}} @middle = #cir.zero : !rec_CycleMiddle |
| 141 | +// LLVM-DAG: @middle = dso_local global %struct.CycleMiddle zeroinitializer |
| 142 | +// OGCG-DAG: @middle = global %struct.CycleMiddle zeroinitializer |
| 143 | + |
| 144 | +struct CycleEnd { |
| 145 | + struct CycleStart* start; |
| 146 | +} end; |
| 147 | + |
| 148 | +// CIR: cir.global{{.*}} @end = #cir.zero : !rec_CycleEnd |
| 149 | +// LLVM-DAG: @end = dso_local global %struct.CycleEnd zeroinitializer |
| 150 | +// OGCG-DAG: @end = global %struct.CycleEnd zeroinitializer |
| 151 | + |
81 | 152 | void f(void) {
|
82 | 153 | struct IncompleteS *p;
|
83 | 154 | }
|
@@ -205,3 +276,40 @@ char f4(int a, struct CompleteS *p) {
|
205 | 276 | // OGCG-NEXT: %[[P_B:.*]] = getelementptr inbounds nuw %struct.CompleteS, ptr %[[P2]], i32 0, i32 1
|
206 | 277 | // OGCG-NEXT: %[[P_B_VAL:.*]] = load i8, ptr %[[P_B]], align 4
|
207 | 278 | // OGCG-NEXT: ret i8 %[[P_B_VAL]]
|
| 279 | + |
| 280 | +void f5(struct NodeS* a) { |
| 281 | + a->next = 0; |
| 282 | +} |
| 283 | + |
| 284 | +// CIR: cir.func @f5 |
| 285 | +// CIR: %[[NEXT:.*]] = cir.get_member {{%.}}[0] {name = "next"} : !cir.ptr<!rec_NodeS> -> !cir.ptr<!cir.ptr<!rec_NodeS>> |
| 286 | +// CIR: cir.store {{.*}}, %[[NEXT]] |
| 287 | + |
| 288 | +// LLVM: define{{.*}} void @f5 |
| 289 | +// LLVM: %[[NEXT:.*]] = getelementptr %struct.NodeS, ptr %{{.*}}, i32 0, i32 0 |
| 290 | +// LLVM: store ptr null, ptr %[[NEXT]] |
| 291 | + |
| 292 | +// OGCG: define{{.*}} void @f5 |
| 293 | +// OGCG: %[[NEXT:.*]] = getelementptr inbounds nuw %struct.NodeS, ptr %{{.*}}, i32 0, i32 0 |
| 294 | +// OGCG: store ptr null, ptr %[[NEXT]] |
| 295 | + |
| 296 | +void f6(struct CycleStart *start) { |
| 297 | + struct CycleMiddle *middle = start->middle; |
| 298 | + struct CycleEnd *end = middle->end; |
| 299 | + struct CycleStart *start2 = end->start; |
| 300 | +} |
| 301 | + |
| 302 | +// CIR: cir.func @f6 |
| 303 | +// CIR: %[[MIDDLE:.*]] = cir.get_member {{.*}}[0] {name = "middle"} : !cir.ptr<!rec_CycleStart> -> !cir.ptr<!cir.ptr<!rec_CycleMiddle>> |
| 304 | +// CIR: %[[END:.*]] = cir.get_member %{{.*}}[0] {name = "end"} : !cir.ptr<!rec_CycleMiddle> -> !cir.ptr<!cir.ptr<!rec_CycleEnd>> |
| 305 | +// CIR: %[[START2:.*]] = cir.get_member %{{.*}}[0] {name = "start"} : !cir.ptr<!rec_CycleEnd> -> !cir.ptr<!cir.ptr<!rec_CycleStart>> |
| 306 | + |
| 307 | +// LLVM: define{{.*}} void @f6 |
| 308 | +// LLVM: %[[MIDDLE:.*]] = getelementptr %struct.CycleStart, ptr %{{.*}}, i32 0, i32 0 |
| 309 | +// LLVM: %[[END:.*]] = getelementptr %struct.CycleMiddle, ptr %{{.*}}, i32 0, i32 0 |
| 310 | +// LLVM: %[[START2:.*]] = getelementptr %struct.CycleEnd, ptr %{{.*}}, i32 0, i32 0 |
| 311 | + |
| 312 | +// OGCG: define{{.*}} void @f6 |
| 313 | +// OGCG: %[[MIDDLE:.*]] = getelementptr inbounds nuw %struct.CycleStart, ptr %{{.*}}, i32 0, i32 0 |
| 314 | +// OGCG: %[[END:.*]] = getelementptr inbounds nuw %struct.CycleMiddle, ptr %{{.*}}, i32 0, i32 0 |
| 315 | +// OGCG: %[[START2:.*]] = getelementptr inbounds nuw %struct.CycleEnd, ptr %{{.*}}, i32 0, i32 0 |
0 commit comments