128 lines · cpp
1// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir2// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR3// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll4// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM5// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll6// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG7 8typedef struct {9 int a : 4;10 int b : 27;11 int c : 17;12 int d : 2;13 int e : 15;14 unsigned f; // type other than int above, not a bitfield15} S;16// CIR-DAG: !rec_S = !cir.record<struct "S" {!u64i, !u16i, !u32i}>17// CIR-DAG: #bfi_c = #cir.bitfield_info<name = "c", storage_type = !u64i, size = 17, offset = 32, is_signed = true>18// LLVM-DAG: %struct.S = type { i64, i16, i32 }19// OGCG-DAG: %struct.S = type { i64, i16, i32 }20 21typedef struct {22 int a : 3; // one bitfield with size < 823 unsigned b;24} T;25 26// CIR-DAG: !rec_T = !cir.record<struct "T" {!u8i, !u32i}>27// LLVM-DAG: %struct.T = type { i8, i32 }28// OGCG-DAG: %struct.T = type { i8, i32 }29 30void def() {31 S s;32 T t;33}34 35int load_field(S* s) {36 return s->c;37}38// CIR: cir.func dso_local @_Z10load_field39// CIR: [[TMP0:%.*]] = cir.alloca !cir.ptr<!rec_S>, !cir.ptr<!cir.ptr<!rec_S>>, ["s", init]40// CIR: [[TMP1:%.*]] = cir.load{{.*}} [[TMP0]] : !cir.ptr<!cir.ptr<!rec_S>>, !cir.ptr<!rec_S>41// CIR: [[TMP2:%.*]] = cir.get_member [[TMP1]][0] {name = "c"} : !cir.ptr<!rec_S> -> !cir.ptr<!u64i>42// CIR: [[TMP3:%.*]] = cir.get_bitfield align(4) (#bfi_c, [[TMP2]] : !cir.ptr<!u64i>) -> !s32i43 44// LLVM: define dso_local i32 @_Z10load_fieldP1S45// LLVM: [[TMP0:%.*]] = alloca ptr, i64 1, align 846// LLVM: [[TMP1:%.*]] = alloca i32, i64 1, align 447// LLVM: [[TMP2:%.*]] = load ptr, ptr [[TMP0]], align 848// LLVM: [[TMP3:%.*]] = getelementptr %struct.S, ptr [[TMP2]], i32 0, i32 049// LLVM: [[TMP4:%.*]] = load i64, ptr [[TMP3]], align 450// LLVM: [[TMP5:%.*]] = shl i64 [[TMP4]], 1551// LLVM: [[TMP6:%.*]] = ashr i64 [[TMP5]], 4752// LLVM: [[TMP7:%.*]] = trunc i64 [[TMP6]] to i3253 54// OGCG: define dso_local noundef i32 @_Z10load_fieldP1S55// OGCG: [[TMP0:%.*]] = alloca ptr, align 856// OGCG: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 857// OGCG: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 458// OGCG: [[TMP3:%.*]] = shl i64 [[TMP2]], 1559// OGCG: [[TMP4:%.*]] = ashr i64 [[TMP3]], 4760// OGCG: [[TMP5:%.*]] = trunc i64 [[TMP4]] to i3261 62void store_field() {63 S s;64 s.a = 3;65}66// CIR: cir.func dso_local @_Z11store_field67// CIR: [[TMP0:%.*]] = cir.alloca !rec_S, !cir.ptr<!rec_S>68// CIR: [[TMP1:%.*]] = cir.const #cir.int<3> : !s32i69// CIR: [[TMP2:%.*]] = cir.get_member [[TMP0]][0] {name = "a"} : !cir.ptr<!rec_S> -> !cir.ptr<!u64i>70// CIR: cir.set_bitfield align(4) (#bfi_a, [[TMP2]] : !cir.ptr<!u64i>, [[TMP1]] : !s32i)71 72// LLVM: define dso_local void @_Z11store_fieldv73// LLVM: [[TMP0:%.*]] = alloca %struct.S, i64 1, align 474// LLVM: [[TMP1:%.*]] = getelementptr %struct.S, ptr [[TMP0]], i32 0, i32 075// LLVM: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 476// LLVM: [[TMP3:%.*]] = and i64 [[TMP2]], -1677// LLVM: [[TMP4:%.*]] = or i64 [[TMP3]], 378// LLVM: store i64 [[TMP4]], ptr [[TMP1]], align 479 80// OGCG: define dso_local void @_Z11store_fieldv()81// OGCG: [[TMP0:%.*]] = alloca %struct.S, align 482// OGCG: [[TMP1:%.*]] = load i64, ptr [[TMP0]], align 483// OGCG: [[TMP2:%.*]] = and i64 [[TMP1]], -1684// OGCG: [[TMP3:%.*]] = or i64 [[TMP2]], 385// OGCG: store i64 [[TMP3]], ptr [[TMP0]], align 486 87void store_bitfield_to_bitfield(S* s) {88 s->a = s->b = 3;89}90 91// CIR: cir.func dso_local @_Z26store_bitfield_to_bitfieldP1S92// CIR: [[TMP0:%.*]] = cir.alloca !cir.ptr<!rec_S>, !cir.ptr<!cir.ptr<!rec_S>>, ["s", init] {alignment = 8 : i64}93// CIR: [[TMP1:%.*]] = cir.const #cir.int<3> : !s32i94// CIR: [[TMP2:%.*]] = cir.load align(8) [[TMP0]] : !cir.ptr<!cir.ptr<!rec_S>>, !cir.ptr<!rec_S>95// CIR: [[TMP3:%.*]] = cir.get_member [[TMP2]][0] {name = "b"} : !cir.ptr<!rec_S> -> !cir.ptr<!u64i>96// CIR: [[TMP4:%.*]] = cir.set_bitfield align(4) (#bfi_b, [[TMP3]] : !cir.ptr<!u64i>, [[TMP1]] : !s32i) -> !s32i97// CIR: [[TMP5:%.*]] = cir.load align(8) [[TMP0]] : !cir.ptr<!cir.ptr<!rec_S>>, !cir.ptr<!rec_S>98// CIR: [[TMP6:%.*]] = cir.get_member [[TMP5]][0] {name = "a"} : !cir.ptr<!rec_S> -> !cir.ptr<!u64i>99// CIR: [[TMP7:%.*]] = cir.set_bitfield align(4) (#bfi_a, [[TMP6]] : !cir.ptr<!u64i>, [[TMP4]] : !s32i) -> !s32i100 101// LLVM: define dso_local void @_Z26store_bitfield_to_bitfieldP1S102// LLVM: [[TMP0:%.*]] = alloca ptr, i64 1, align 8103// LLVM: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8104// LLVM: [[TMP2:%.*]] = getelementptr %struct.S, ptr [[TMP1]], i32 0, i32 0105// LLVM: [[TMP3:%.*]] = load i64, ptr [[TMP2]], align 4106// LLVM: [[TMP4:%.*]] = and i64 [[TMP3]], -2147483633107// LLVM: [[TMP5:%.*]] = or i64 [[TMP4]], 48108// LLVM: store i64 [[TMP5]], ptr [[TMP2]], align 4109// LLVM: [[TMP6:%.*]] = load ptr, ptr [[TMP0]], align 8110// LLVM: [[TMP7:%.*]] = getelementptr %struct.S, ptr [[TMP6]], i32 0, i32 0111// LLVM: [[TMP8:%.*]] = load i64, ptr [[TMP7]], align 4112// LLVM: [[TMP9:%.*]] = and i64 [[TMP8]], -16113// LLVM: [[TMP10:%.*]] = or i64 [[TMP9]], 3114// LLVM: store i64 [[TMP10]], ptr [[TMP7]], align 4115 116// OGCG: define dso_local void @_Z26store_bitfield_to_bitfieldP1S117// OGCG: [[TMP0:%.*]] = alloca ptr, align 8118// OGCG: [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8119// OGCG: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4120// OGCG: [[TMP3:%.*]] = and i64 [[TMP2]], -2147483633121// OGCG: [[TMP4:%.*]] = or i64 [[TMP3]], 48122// OGCG: store i64 [[TMP4]], ptr [[TMP1]], align 4123// OGCG: [[TMP5:%.*]] = load ptr, ptr [[TMP0]], align 8124// OGCG: [[TMP6:%.*]] = load i64, ptr [[TMP5]], align 4125// OGCG: [[TMP7:%.*]] = and i64 [[TMP6]], -16126// OGCG: [[TMP8:%.*]] = or i64 [[TMP7]], 3127// OGCG: store i64 [[TMP8]], ptr [[TMP5]], align 4128