286 lines · c
1// RUN: %clang_cc1 -triple aarch64-unknown-linux-gnu -fclangir -emit-cir -fdump-record-layouts %s -o %t.cir > %t.cirlayout2// RUN: FileCheck --input-file=%t.cirlayout %s --check-prefix=CIR-LAYOUT3// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR4 5// RUN: %clang_cc1 -triple aarch64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll6// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM7 8// RUN: %clang_cc1 -triple aarch64-unknown-linux-gnu -emit-llvm -fdump-record-layouts %s -o %t.ll > %t.ogcglayout9// RUN: FileCheck --input-file=%t.ogcglayout %s --check-prefix=OGCG-LAYOUT10// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG11 12typedef struct {13 unsigned int a : 9;14 volatile unsigned int b : 1;15 unsigned int c : 1;16} st1;17 18// CIR-LAYOUT: BitFields:[19// CIR-LAYOUT-NEXT: <CIRBitFieldInfo name:a offset:0 size:9 isSigned:0 storageSize:16 storageOffset:0 volatileOffset:0 volatileStorageSize:32 volatileStorageOffset:0>20// CIR-LAYOUT-NEXT: <CIRBitFieldInfo name:b offset:9 size:1 isSigned:0 storageSize:16 storageOffset:0 volatileOffset:9 volatileStorageSize:32 volatileStorageOffset:0>21// CIR-LAYOUT-NEXT: <CIRBitFieldInfo name:c offset:10 size:1 isSigned:0 storageSize:16 storageOffset:0 volatileOffset:10 volatileStorageSize:32 volatileStorageOffset:0>22 23// OGCG-LAYOUT: BitFields:[24// OGCG-LAYOUT-NEXT: <CGBitFieldInfo Offset:0 Size:9 IsSigned:0 StorageSize:16 StorageOffset:0 VolatileOffset:0 VolatileStorageSize:32 VolatileStorageOffset:0>25// OGCG-LAYOUT-NEXT: <CGBitFieldInfo Offset:9 Size:1 IsSigned:0 StorageSize:16 StorageOffset:0 VolatileOffset:9 VolatileStorageSize:32 VolatileStorageOffset:0>26// OGCG-LAYOUT-NEXT: <CGBitFieldInfo Offset:10 Size:1 IsSigned:0 StorageSize:16 StorageOffset:0 VolatileOffset:10 VolatileStorageSize:32 VolatileStorageOffset:0>27 28// different base types29typedef struct{30 volatile short a : 3;31 volatile int b: 13;32 volatile long c : 5;33} st2;34 35// CIR-LAYOUT: BitFields:[36// CIR-LAYOUT-NEXT: <CIRBitFieldInfo name:a offset:0 size:3 isSigned:1 storageSize:32 storageOffset:0 volatileOffset:0 volatileStorageSize:16 volatileStorageOffset:0>37// CIR-LAYOUT-NEXT: <CIRBitFieldInfo name:b offset:3 size:13 isSigned:1 storageSize:32 storageOffset:0 volatileOffset:3 volatileStorageSize:32 volatileStorageOffset:0>38// CIR-LAYOUT-NEXT: <CIRBitFieldInfo name:c offset:16 size:5 isSigned:1 storageSize:32 storageOffset:0 volatileOffset:16 volatileStorageSize:64 volatileStorageOffset:0>39 40// OGCG-LAYOUT: BitFields:[41// OGCG-LAYOUT-NEXT: <CGBitFieldInfo Offset:0 Size:3 IsSigned:1 StorageSize:32 StorageOffset:0 VolatileOffset:0 VolatileStorageSize:16 VolatileStorageOffset:0>42// OGCG-LAYOUT-NEXT: <CGBitFieldInfo Offset:3 Size:13 IsSigned:1 StorageSize:32 StorageOffset:0 VolatileOffset:3 VolatileStorageSize:32 VolatileStorageOffset:0>43// OGCG-LAYOUT-NEXT: <CGBitFieldInfo Offset:16 Size:5 IsSigned:1 StorageSize:32 StorageOffset:0 VolatileOffset:16 VolatileStorageSize:64 VolatileStorageOffset:0>44 45typedef struct{46 volatile unsigned int a : 3;47 unsigned int : 0; // zero-length bit-field force next field to aligned int boundary48 volatile unsigned int b : 5;49} st3;50 51// CIR-LAYOUT: BitFields:[52// CIR-LAYOUT-NEXT: <CIRBitFieldInfo name:a offset:0 size:3 isSigned:0 storageSize:8 storageOffset:0 volatileOffset:0 volatileStorageSize:32 volatileStorageOffset:0>53// CIR-LAYOUT-NEXT: <CIRBitFieldInfo name:b offset:0 size:5 isSigned:0 storageSize:8 storageOffset:4 volatileOffset:0 volatileStorageSize:0 volatileStorageOffset:0>54 55// OGCG-LAYOUT: BitFields:[56// OGCG-LAYOUT-NEXT: <CGBitFieldInfo Offset:0 Size:3 IsSigned:0 StorageSize:8 StorageOffset:0 VolatileOffset:0 VolatileStorageSize:32 VolatileStorageOffset:0>57// OGCG-LAYOUT-NEXT: <CGBitFieldInfo Offset:0 Size:5 IsSigned:0 StorageSize:8 StorageOffset:4 VolatileOffset:0 VolatileStorageSize:0 VolatileStorageOffset:0>58 59typedef struct{60 volatile unsigned int a : 3;61 unsigned int z;62 volatile unsigned long b : 16;63} st4;64 65// CIR-LAYOUT: BitFields:[66// CIR-LAYOUT-NEXT: <CIRBitFieldInfo name:a offset:0 size:3 isSigned:0 storageSize:8 storageOffset:0 volatileOffset:0 volatileStorageSize:32 volatileStorageOffset:0>67// CIR-LAYOUT-NEXT: <CIRBitFieldInfo name:b offset:0 size:16 isSigned:0 storageSize:16 storageOffset:8 volatileOffset:0 volatileStorageSize:64 volatileStorageOffset:1>68 69// OGCG-LAYOUT: BitFields:[70// OGCG-LAYOUT-NEXT: <CGBitFieldInfo Offset:0 Size:3 IsSigned:0 StorageSize:8 StorageOffset:0 VolatileOffset:0 VolatileStorageSize:32 VolatileStorageOffset:0>71// OGCG-LAYOUT-NEXT: <CGBitFieldInfo Offset:0 Size:16 IsSigned:0 StorageSize:16 StorageOffset:8 VolatileOffset:0 VolatileStorageSize:64 VolatileStorageOffset:1>72 73 74void def () {75 st1 s1;76 st2 s2;77 st3 s3;78 st4 s4;79}80 81int check_load(st1 *s1) {82 return s1->b;83}84 85// CIR: cir.func dso_local @check_load86// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_st1>>, !cir.ptr<!rec_st1>87// CIR: [[MEMBER:%.*]] = cir.get_member [[LOAD]][0] {name = "b"} : !cir.ptr<!rec_st1> -> !cir.ptr<!u16i>88// CIR: [[BITFI:%.*]] = cir.get_bitfield align(4) (#bfi_b, [[MEMBER]] {is_volatile} : !cir.ptr<!u16i>) -> !u32i89// CIR: [[CAST:%.*]] = cir.cast integral [[BITFI]] : !u32i -> !s32i90// CIR: cir.store [[CAST]], [[RETVAL:%.*]] : !s32i, !cir.ptr<!s32i>91// CIR: [[RET:%.*]] = cir.load [[RETVAL]] : !cir.ptr<!s32i>, !s32i92// CIR: cir.return [[RET]] : !s32i93 94// LLVM:define dso_local i32 @check_load95// LLVM: [[LOAD:%.*]] = load ptr, ptr {{.*}}, align 896// LLVM: [[MEMBER:%.*]] = getelementptr %struct.st1, ptr [[LOAD]], i32 0, i32 097// LLVM: [[LOADVOL:%.*]] = load volatile i32, ptr [[MEMBER]], align 498// LLVM: [[LSHR:%.*]] = lshr i32 [[LOADVOL]], 999// LLVM: [[CLEAR:%.*]] = and i32 [[LSHR]], 1100// LLVM: store i32 [[CLEAR]], ptr [[RETVAL:%.*]], align 4101// LLVM: [[RET:%.*]] = load i32, ptr [[RETVAL]], align 4102// LLVM: ret i32 [[RET]]103 104// OGCG: define dso_local i32 @check_load105// OGCG: [[LOAD:%.*]] = load ptr, ptr {{.*}}, align 8106// OGCG: [[LOADVOL:%.*]] = load volatile i32, ptr [[LOAD]], align 4107// OGCG: [[LSHR:%.*]] = lshr i32 [[LOADVOL]], 9108// OGCG: [[CLEAR:%.*]] = and i32 [[LSHR]], 1109// OGCG: ret i32 [[CLEAR]]110 111// this volatile bit-field container overlaps with a zero-length bit-field,112// so it may be accessed without using the container's width.113int check_load_exception(st3 *s3) {114 return s3->b;115}116 117// CIR: cir.func dso_local @check_load_exception118// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_st3>>, !cir.ptr<!rec_st3>119// CIR: [[MEMBER:%.*]] = cir.get_member [[LOAD]][2] {name = "b"} : !cir.ptr<!rec_st3> -> !cir.ptr<!u8i>120// CIR: [[BITFI:%.*]] = cir.get_bitfield align(4) (#bfi_b1, [[MEMBER]] {is_volatile} : !cir.ptr<!u8i>) -> !u32i121// CIR: [[CAST:%.*]] = cir.cast integral [[BITFI]] : !u32i -> !s32i122// CIR: cir.store [[CAST]], [[RETVAL:%.*]] : !s32i, !cir.ptr<!s32i>123// CIR: [[RET:%.*]] = cir.load [[RETVAL]] : !cir.ptr<!s32i>, !s32i124// CIR: cir.return [[RET]] : !s32i125 126// LLVM:define dso_local i32 @check_load_exception127// LLVM: [[LOAD:%.*]] = load ptr, ptr {{.*}}, align 8128// LLVM: [[MEMBER:%.*]] = getelementptr %struct.st3, ptr [[LOAD]], i32 0, i32 2129// LLVM: [[LOADVOL:%.*]] = load volatile i8, ptr [[MEMBER]], align 4130// LLVM: [[CLEAR:%.*]] = and i8 [[LOADVOL]], 31131// LLVM: [[CAST:%.*]] = zext i8 [[CLEAR]] to i32132// LLVM: store i32 [[CAST]], ptr [[RETVAL:%.*]], align 4133// LLVM: [[RET:%.*]] = load i32, ptr [[RETVAL]], align 4134// LLVM: ret i32 [[RET]]135 136// OGCG: define dso_local i32 @check_load_exception137// OGCG: [[LOAD:%.*]] = load ptr, ptr {{.*}}, align 8138// OGCG: [[MEMBER:%.*]] = getelementptr inbounds nuw %struct.st3, ptr [[LOAD]], i32 0, i32 2139// OGCG: [[LOADVOL:%.*]] = load volatile i8, ptr [[MEMBER]], align 4140// OGCG: [[CLEAR:%.*]] = and i8 [[LOADVOL]], 31141// OGCG: [[CAST:%.*]] = zext i8 [[CLEAR]] to i32142// OGCG: ret i32 [[CAST]]143 144typedef struct {145 volatile int a : 24;146 char b;147 volatile int c: 30;148 } clip;149 150int clip_load_exception2(clip *c) {151 return c->a;152}153 154// CIR: cir.func dso_local @clip_load_exception2155// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_clip>>, !cir.ptr<!rec_clip>156// CIR: [[MEMBER:%.*]] = cir.get_member [[LOAD]][0] {name = "a"} : !cir.ptr<!rec_clip> -> !cir.ptr<!cir.array<!u8i x 3>>157// CIR: [[BITFI:%.*]] = cir.get_bitfield align(4) (#bfi_a1, [[MEMBER]] {is_volatile} : !cir.ptr<!cir.array<!u8i x 3>>) -> !s32i158// CIR: cir.store [[BITFI]], [[RETVAL:%.*]] : !s32i, !cir.ptr<!s32i>159// CIR: [[RET:%.*]] = cir.load [[RETVAL]] : !cir.ptr<!s32i>, !s32i160// CIR: cir.return [[RET]] : !s32i161 162// LLVM:define dso_local i32 @clip_load_exception2163// LLVM: [[LOAD:%.*]] = load ptr, ptr {{.*}}, align 8164// LLVM: [[MEMBER:%.*]] = getelementptr %struct.clip, ptr [[LOAD]], i32 0, i32 0165// LLVM: [[LOADVOL:%.*]] = load volatile i24, ptr [[MEMBER]], align 4166// LLVM: [[CAST:%.*]] = sext i24 [[LOADVOL]] to i32167// LLVM: store i32 [[CAST]], ptr [[RETVAL:%.*]], align 4168// LLVM: [[RET:%.*]] = load i32, ptr [[RETVAL]], align 4169// LLVM: ret i32 [[RET]]170 171// OGCG: define dso_local i32 @clip_load_exception2172// OGCG: [[LOAD:%.*]] = load ptr, ptr {{.*}}, align 8173// OGCG: [[LOADVOL:%.*]] = load volatile i24, ptr [[LOAD]], align 4174// OGCG: [[CAST:%.*]] = sext i24 [[LOADVOL]] to i32175// OGCG: ret i32 [[CAST]]176 177void check_store(st2 *s2) {178 s2->a = 1;179}180 181// CIR: cir.func dso_local @check_store182// CIR: [[CONST:%.*]] = cir.const #cir.int<1> : !s32i183// CIR: [[CAST:%.*]] = cir.cast integral [[CONST]] : !s32i -> !s16i184// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_st2>>, !cir.ptr<!rec_st2>185// CIR: [[MEMBER:%.*]] = cir.get_member [[LOAD]][0] {name = "a"} : !cir.ptr<!rec_st2> -> !cir.ptr<!u32i>186// CIR: [[SETBF:%.*]] = cir.set_bitfield align(8) (#bfi_a, [[MEMBER]] : !cir.ptr<!u32i>, [[CAST]] : !s16i) {is_volatile} -> !s16i187// CIR: cir.return188 189// LLVM:define dso_local void @check_store190// LLVM: [[LOAD:%.*]] = load ptr, ptr {{.*}}, align 8191// LLVM: [[MEMBER:%.*]] = getelementptr %struct.st2, ptr [[LOAD]], i32 0, i32 0192// LLVM: [[LOADVOL:%.*]] = load volatile i16, ptr [[MEMBER]], align 8193// LLVM: [[CLEAR:%.*]] = and i16 [[LOADVOL]], -8194// LLVM: [[SET:%.*]] = or i16 [[CLEAR]], 1195// LLVM: store volatile i16 [[SET]], ptr [[MEMBER]], align 8196// LLVM: ret void197 198// OGCG: define dso_local void @check_store199// OGCG: [[LOAD:%.*]] = load ptr, ptr {{.*}}, align 8200// OGCG: [[LOADVOL:%.*]] = load volatile i16, ptr [[LOAD]], align 8201// OGCG: [[CLEAR:%.*]] = and i16 [[LOADVOL]], -8202// OGCG: [[SET:%.*]] = or i16 [[CLEAR]], 1203// OGCG: store volatile i16 [[SET]], ptr [[LOAD]], align 8204// OGCG: ret void205 206// this volatile bit-field container overlaps with a zero-length bit-field,207// so it may be accessed without using the container's width.208void check_store_exception(st3 *s3) {209 s3->b = 2;210}211 212// CIR: cir.func dso_local @check_store_exception213// CIR: [[CONST:%.*]] = cir.const #cir.int<2> : !s32i214// CIR: [[CAST:%.*]] = cir.cast integral [[CONST]] : !s32i -> !u32i215// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_st3>>, !cir.ptr<!rec_st3>216// CIR: [[MEMBER:%.*]] = cir.get_member [[LOAD]][2] {name = "b"} : !cir.ptr<!rec_st3> -> !cir.ptr<!u8i>217// CIR: [[SETBF:%.*]] = cir.set_bitfield align(4) (#bfi_b1, [[MEMBER]] : !cir.ptr<!u8i>, [[CAST]] : !u32i) {is_volatile} -> !u32i218// CIR: cir.return219 220// LLVM:define dso_local void @check_store_exception221// LLVM: [[LOAD:%.*]] = load ptr, ptr {{.*}}, align 8222// LLVM: [[MEMBER:%.*]] = getelementptr %struct.st3, ptr [[LOAD]], i32 0, i32 2223// LLVM: [[LOADVOL:%.*]] = load volatile i8, ptr [[MEMBER]], align 4224// LLVM: [[CLEAR:%.*]] = and i8 [[LOADVOL]], -32225// LLVM: [[SET:%.*]] = or i8 [[CLEAR]], 2226// LLVM: store volatile i8 [[SET]], ptr [[MEMBER]], align 4227// LLVM: ret void228 229// OGCG: define dso_local void @check_store_exception230// OGCG: [[LOAD:%.*]] = load ptr, ptr {{.*}}, align 8231// OGCG: [[MEMBER:%.*]] = getelementptr inbounds nuw %struct.st3, ptr [[LOAD]], i32 0, i32 2232// OGCG: [[LOADVOL:%.*]] = load volatile i8, ptr [[MEMBER]], align 4233// OGCG: [[CLEAR:%.*]] = and i8 [[LOADVOL]], -32234// OGCG: [[SET:%.*]] = or i8 [[CLEAR]], 2235// OGCG: store volatile i8 [[SET]], ptr [[MEMBER]], align 4236// OGCG: ret void237 238void clip_store_exception2(clip *c) {239 c->a = 3;240}241 242// CIR: cir.func dso_local @clip_store_exception2243// CIR: [[CONST:%.*]] = cir.const #cir.int<3> : !s32i244// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_clip>>, !cir.ptr<!rec_clip>245// CIR: [[MEMBER:%.*]] = cir.get_member [[LOAD]][0] {name = "a"} : !cir.ptr<!rec_clip> -> !cir.ptr<!cir.array<!u8i x 3>>246// CIR: [[SETBF:%.*]] = cir.set_bitfield align(4) (#bfi_a1, [[MEMBER]] : !cir.ptr<!cir.array<!u8i x 3>>, [[CONST]] : !s32i) {is_volatile} -> !s32i247// CIR: cir.return248 249// LLVM:define dso_local void @clip_store_exception2250// LLVM: [[LOAD:%.*]] = load ptr, ptr {{.*}}, align 8251// LLVM: [[MEMBER:%.*]] = getelementptr %struct.clip, ptr [[LOAD]], i32 0, i32 0252// LLVM: store volatile i24 3, ptr [[MEMBER]], align 4253// LLVM: ret void254 255// OGCG: define dso_local void @clip_store_exception2256// OGCG: [[LOAD:%.*]] = load ptr, ptr {{.*}}, align 8257// OGCG: store volatile i24 3, ptr [[LOAD]], align 4258// OGCG: ret void259 260void check_store_second_member (st4 *s4) {261 s4->b = 1;262}263 264// CIR: cir.func dso_local @check_store_second_member265// CIR: [[ONE:%.*]] = cir.const #cir.int<1> : !s32i266// CIR: [[CAST:%.*]] = cir.cast integral [[ONE]] : !s32i -> !u64i267// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_st4>>, !cir.ptr<!rec_st4>268// CIR: [[MEMBER:%.*]] = cir.get_member [[LOAD]][2] {name = "b"} : !cir.ptr<!rec_st4> -> !cir.ptr<!u16i>269// CIR: cir.set_bitfield align(8) (#bfi_b2, [[MEMBER]] : !cir.ptr<!u16i>, [[CAST]] : !u64i) {is_volatile} -> !u64i270 271// LLVM: define dso_local void @check_store_second_member272// LLVM: [[LOAD:%.*]] = load ptr, ptr {{.*}}, align 8273// LLVM: [[MEMBER:%.*]] = getelementptr %struct.st4, ptr [[LOAD]], i32 0, i32 2274// LLVM: [[VAL:%.*]] = load volatile i64, ptr [[MEMBER]], align 8275// LLVM: [[CLEAR:%.*]] = and i64 [[VAL]], -65536276// LLVM: [[SET:%.*]] = or i64 [[CLEAR]], 1277// LLVM: store volatile i64 [[SET]], ptr [[MEMBER]], align 8278 279// OGCG: define dso_local void @check_store_second_member280// OGCG: [[LOAD:%.*]] = load ptr, ptr {{.*}}, align 8281// OGCG: [[MEMBER:%.*]] = getelementptr inbounds i64, ptr [[LOAD]], i64 1282// OGCG: [[LOADBF:%.*]] = load volatile i64, ptr [[MEMBER]], align 8283// OGCG: [[CLR:%.*]] = and i64 [[LOADBF]], -65536284// OGCG: [[SET:%.*]] = or i64 [[CLR]], 1285// OGCG: store volatile i64 [[SET]], ptr [[MEMBER]], align 8286