185 lines · cpp
1// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir2// RUN: FileCheck --check-prefix=CIR %s < %t.cir3// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll4// RUN: FileCheck --check-prefix=LLVM %s < %t-cir.ll5// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll6// RUN: FileCheck --check-prefix=OGCG %s < %t.ll7 8int test_load(volatile int *ptr) {9 return *ptr;10}11 12// CIR: cir.func dso_local @_Z9test_loadPVi13// CIR: cir.load volatile14 15// LLVM: define {{.*}} i32 @_Z9test_loadPVi16// LLVM: load volatile i32, ptr %{{.*}}17 18// OGCG: define {{.*}} i32 @_Z9test_loadPVi19// OGCG: load volatile i32, ptr %{{.*}}20 21void test_store(volatile int *ptr) {22 *ptr = 42;23}24 25// CIR: cir.func dso_local @_Z10test_storePVi26// CIR: cir.store volatile27 28// LLVM: define {{.*}} void @_Z10test_storePVi29// LLVM: store volatile i32 42, ptr %{{.*}}30 31// OGCG: define {{.*}} void @_Z10test_storePVi32// OGCG: store volatile i32 42, ptr %{{.*}}33 34struct Foo {35 int x;36 volatile int y;37 volatile int z: 4;38};39 40int test_load_field1(volatile Foo *ptr) {41 return ptr->x;42}43 44// CIR: cir.func dso_local @_Z16test_load_field1PV3Foo45// CIR: %[[MEMBER_ADDR:.*]] = cir.get_member46// CIR: %{{.+}} = cir.load volatile{{.*}} %[[MEMBER_ADDR]]47 48// LLVM: define {{.*}} i32 @_Z16test_load_field1PV3Foo49// LLVM: %[[MEMBER_ADDR:.*]] = getelementptr %struct.Foo, ptr %{{.*}}, i32 0, i32 050// LLVM: %{{.*}} = load volatile i32, ptr %[[MEMBER_ADDR]]51 52// OGCG: define {{.*}} i32 @_Z16test_load_field1PV3Foo53// OGCG: %[[MEMBER_ADDR:.*]] = getelementptr inbounds nuw %struct.Foo, ptr %{{.*}}, i32 0, i32 054// OGCG: %{{.*}} = load volatile i32, ptr %[[MEMBER_ADDR]]55 56int test_load_field2(Foo *ptr) {57 return ptr->y;58}59 60// CIR: cir.func dso_local @_Z16test_load_field2P3Foo61// CIR: %[[MEMBER_ADDR:.*]] = cir.get_member62// CIR: %{{.+}} = cir.load volatile{{.*}} %[[MEMBER_ADDR]]63 64// LLVM: define {{.*}} i32 @_Z16test_load_field2P3Foo65// LLVM: %[[MEMBER_ADDR:.*]] = getelementptr %struct.Foo, ptr %{{.*}}, i32 0, i32 166// LLVM: %{{.*}} = load volatile i32, ptr %[[MEMBER_ADDR]]67 68// OGCG: define {{.*}} i32 @_Z16test_load_field2P3Foo69// OGCG: %[[MEMBER_ADDR:.*]] = getelementptr inbounds nuw %struct.Foo, ptr %{{.*}}, i32 0, i32 170// OGCG: %{{.*}} = load volatile i32, ptr %[[MEMBER_ADDR]]71 72int test_load_field3(Foo *ptr) {73 return ptr->z;74}75 76// CIR: cir.func dso_local @_Z16test_load_field3P3Foo77// CIR: %[[MEMBER_ADDR:.*]] = cir.get_member78// CIR: %{{.*}} = cir.get_bitfield align(4) (#bfi_z, %[[MEMBER_ADDR:.+]] {is_volatile} : !cir.ptr<!u8i>) -> !s32i79 80// LLVM: define {{.*}} i32 @_Z16test_load_field3P3Foo81// LLVM: %[[MEMBER_ADDR:.*]] = getelementptr %struct.Foo, ptr %{{.*}}, i32 0, i32 282// LLVM: %[[TMP1:.*]] = load volatile i8, ptr %[[MEMBER_ADDR]]83// LLVM: %[[TMP2:.*]] = shl i8 %[[TMP1]], 484// LLVM: %[[TMP3:.*]] = ashr i8 %[[TMP2]], 485// LLVM: %{{.*}} = sext i8 %[[TMP3]] to i3286 87// OGCG: define {{.*}} i32 @_Z16test_load_field3P3Foo88// OGCG: %[[MEMBER_ADDR:.*]] = getelementptr inbounds nuw %struct.Foo, ptr %{{.*}}, i32 0, i32 289// OGCG: %[[TMP1:.*]] = load volatile i8, ptr %[[MEMBER_ADDR]]90// OGCG: %[[TMP2:.*]] = shl i8 %[[TMP1]], 491// OGCG: %[[TMP3:.*]] = ashr i8 %[[TMP2]], 492// OGCG: %{{.*}} = sext i8 %[[TMP3]] to i3293 94void test_store_field1(volatile Foo *ptr) {95 ptr->x = 42;96}97 98// CIR: cir.func dso_local @_Z17test_store_field1PV3Foo99// CIR: %[[MEMBER_ADDR:.*]] = cir.get_member100// CIR: cir.store volatile{{.*}} %{{.+}}, %[[MEMBER_ADDR]]101 102// LLVM: define {{.*}} void @_Z17test_store_field1PV3Foo103// LLVM: %[[MEMBER_ADDR:.*]] = getelementptr %struct.Foo, ptr %{{.*}}, i32 0, i32 0104// LLVM: store volatile i32 42, ptr %[[MEMBER_ADDR]]105 106// OGCG: define {{.*}} void @_Z17test_store_field1PV3Foo107// OGCG: %[[MEMBER_ADDR:.*]] = getelementptr inbounds nuw %struct.Foo, ptr %{{.*}}, i32 0, i32 0108// OGCG: store volatile i32 42, ptr %[[MEMBER_ADDR]]109 110void test_store_field2(Foo *ptr) {111 ptr->y = 42;112}113 114// CIR: cir.func dso_local @_Z17test_store_field2P3Foo115// CIR: %[[MEMBER_ADDR:.*]] = cir.get_member116// CIR: cir.store volatile{{.*}} %{{.+}}, %[[MEMBER_ADDR]]117 118// LLVM: define {{.*}} void @_Z17test_store_field2P3Foo119// LLVM: %[[MEMBER_ADDR:.*]] = getelementptr %struct.Foo, ptr %{{.*}}, i32 0, i32 1120// LLVM: store volatile i32 42, ptr %[[MEMBER_ADDR]]121 122// OGCG: define {{.*}} void @_Z17test_store_field2P3Foo123// OGCG: %[[MEMBER_ADDR:.*]] = getelementptr inbounds nuw %struct.Foo, ptr %{{.*}}, i32 0, i32 1124// OGCG: store volatile i32 42, ptr %[[MEMBER_ADDR]]125 126void test_store_field3(Foo *ptr) {127 ptr->z = 4;128}129 130// CIR: cir.func dso_local @_Z17test_store_field3P3Foo131// CIR: %[[MEMBER_ADDR:.*]] = cir.get_member132// CIR: cir.set_bitfield align(4) (#bfi_z, %[[MEMBER_ADDR:.+]] : !cir.ptr<!u8i>, %1 : !s32i) {is_volatile}133 134// LLVM: define {{.*}} void @_Z17test_store_field3P3Foo135// LLVM: %[[MEMBER_ADDR:.*]] = getelementptr %struct.Foo, ptr %{{.*}}, i32 0, i32 2136// LLVM: %[[TMP1:.*]] = load volatile i8, ptr %[[MEMBER_ADDR]]137// LLVM: %[[TMP2:.*]] = and i8 %[[TMP1]], -16138// LLVM: %[[TMP3:.*]] = or i8 %[[TMP2]], 4139// LLVM: store volatile i8 %[[TMP3]], ptr %[[MEMBER_ADDR]]140 141// OGCG: define {{.*}} void @_Z17test_store_field3P3Foo142// OGCG: %[[MEMBER_ADDR:.*]] = getelementptr inbounds nuw %struct.Foo, ptr %{{.*}}, i32 0, i32 2143// OGCG: %[[TMP1:.*]] = load volatile i8, ptr %[[MEMBER_ADDR]]144// OGCG: %[[TMP2:.*]] = and i8 %[[TMP1]], -16145// OGCG: %[[TMP3:.*]] = or i8 %[[TMP2]], 4146// OGCG: store volatile i8 %[[TMP3]], ptr %[[MEMBER_ADDR]]147 148struct A {149 int x;150 void set_x(int val) volatile;151 int get_x() volatile;152};153 154void A::set_x(int val) volatile {155 x = val;156}157 158// CIR: cir.func dso_local @_ZNV1A5set_xEi159// CIR: %[[MEMBER_ADDR:.*]] = cir.get_member %{{.*}}[0] {name = "x"}160// CIR: cir.store volatile {{.*}} %{{.*}}, %[[MEMBER_ADDR]]161 162// LLVM: define {{.*}} void @_ZNV1A5set_xEi163// LLVM: %[[MEMBER_ADDR:.*]] = getelementptr %struct.A, ptr %{{.*}}, i32 0, i32 0164// LLVM: store volatile i32 %{{.*}}, ptr %[[MEMBER_ADDR]]165 166// OGCG: define {{.*}} void @_ZNV1A5set_xEi167// OGCG: %[[MEMBER_ADDR:.*]] = getelementptr inbounds nuw %struct.A, ptr %{{.*}}, i32 0, i32 0168// OGCG: store volatile i32 %{{.*}}, ptr %[[MEMBER_ADDR]]169 170int A::get_x() volatile {171 return x;172}173 174// CIR: cir.func dso_local @_ZNV1A5get_xEv175// CIR: %[[MEMBER_ADDR:.*]] = cir.get_member %{{.*}}[0] {name = "x"}176// CIR: cir.load volatile {{.*}} %[[MEMBER_ADDR]]177 178// LLVM: define {{.*}} i32 @_ZNV1A5get_xEv179// LLVM: %[[MEMBER_ADDR:.*]] = getelementptr %struct.A, ptr %{{.*}}, i32 0, i32 0180// LLVM: %{{.*}} = load volatile i32, ptr %[[MEMBER_ADDR]]181 182// OGCG: define {{.*}} i32 @_ZNV1A5get_xEv183// OGCG: %[[MEMBER_ADDR:.*]] = getelementptr inbounds nuw %struct.A, ptr %{{.*}}, i32 0, i32 0184// OGCG: %{{.*}} = load volatile i32, ptr %[[MEMBER_ADDR]]185