| // RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics -emit-llvm %s -o - | FileCheck %s |
| // RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics -emit-llvm %s -o - | FileCheck %s |
| |
| #define IQ __ptrauth(1,0,50) |
| #define AQ __ptrauth(1,1,50) |
| #define DIFF_IQ __ptrauth(1,0,100) |
| #define DIFF_AQ __ptrauth(1,1,100) |
| #define ZERO_IQ __ptrauth(1,0,0) |
| #define ZERO_AQ __ptrauth(1,1,0) |
| |
| extern int external_int; |
| extern int * global_upi; |
| extern int * IQ global_iqpi; |
| extern int * AQ global_aqpi; |
| extern void use_upi(int *ptr); |
| |
| typedef void func_t(void); |
| extern void external_func(void); |
| extern func_t *global_upf; |
| extern func_t * IQ global_iqpf; |
| extern func_t * AQ global_aqpf; |
| extern void use_upf(func_t *ptr); |
| |
| // Data with address-independent qualifiers. |
| |
| // CHECK-LABEL: define {{.*}}void @test_store_data_i_constant() |
| void test_store_data_i_constant() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[SIGN:%.*]] = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr @external_int to i64), i32 1, i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = inttoptr i64 [[SIGN]] to ptr |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| int * IQ iqpi = &external_int; |
| // CHECK-NEXT: [[T0:%.*]] = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr @external_int to i64), i32 1, i64 50) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T0]] to ptr |
| // CHECK-NEXT: store ptr [[SIGNED]], ptr [[V]], |
| // CHECK-NEXT: ret void |
| iqpi = &external_int; |
| } |
| |
| // CHECK-LABEL: define {{.*}}void @test_store_data_iu() |
| void test_store_data_iu() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_upi, |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.sign(i64 [[T0]], i32 1, i64 50) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| int * IQ iqpi = global_upi; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_upi, |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.sign(i64 [[T0]], i32 1, i64 50) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| iqpi = global_upi; |
| } |
| |
| // CHECK-LABEL: define {{.*}}void @test_store_data_ia() |
| void test_store_data_ia() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_aqpi, |
| // CHECK-NEXT: [[OLDDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr @global_aqpi to i64), i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 [[OLDDISC]], i32 1, i64 50) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| int * IQ iqpi = global_aqpi; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_aqpi, |
| // CHECK-NEXT: [[OLDDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr @global_aqpi to i64), i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 [[OLDDISC]], i32 1, i64 50) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| iqpi = global_aqpi; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_aqpi, |
| // CHECK-NEXT: [[OLDDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr @global_aqpi to i64), i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 [[OLDDISC]], i32 1, i64 50) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[RESULT:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[RESULT]], ptr [[V]], |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[RESULT]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[RESULT]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[T0]], i32 1, i64 50) |
| // CHECK-NEXT: [[AUTHED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[RESULT:%.*]] = phi ptr [ null, {{.*}} ], [ [[AUTHED]], {{.*}} ] |
| // CHECK-NEXT: call void @use_upi(ptr noundef [[RESULT]]) |
| use_upi(iqpi = global_aqpi); |
| } |
| |
| // CHECK-LABEL: define {{.*}}void @test_store_data_ii_same() |
| void test_store_data_ii_same() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_iqpi, |
| // CHECK-NEXT: store ptr [[LOAD]], ptr [[V]], |
| int * IQ iqpi = global_iqpi; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_iqpi, |
| // CHECK-NEXT: store ptr [[LOAD]], ptr [[V]], |
| iqpi = global_iqpi; |
| } |
| |
| // CHECK-LABEL: define {{.*}}void @test_store_data_ii_different() |
| void test_store_data_ii_different() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_iqpi, |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 50, i32 1, i64 100) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| int * DIFF_IQ iqpi = global_iqpi; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_iqpi, |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 50, i32 1, i64 100) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| iqpi = global_iqpi; |
| } |
| |
| // CHECK-LABEL: define {{.*}}void @test_store_data_ii_zero() |
| void test_store_data_ii_zero() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_iqpi, |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 50, i32 1, i64 0) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| int * ZERO_IQ iqpi = global_iqpi; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr [[V]] |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 0, i32 1, i64 50) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr @global_iqpi, |
| global_iqpi = iqpi; |
| } |
| |
| // CHECK-LABEL: define {{.*}}void @test_load_data_i() |
| void test_load_data_i() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_iqpi, |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[T0]], i32 1, i64 50) |
| // CHECK-NEXT: [[AUTHED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[AUTHED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| int *upi = global_iqpi; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_iqpi, |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[T0]], i32 1, i64 50) |
| // CHECK-NEXT: [[AUTHED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[AUTHED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| upi = global_iqpi; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_iqpi, |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[T0]], i32 1, i64 50) |
| // CHECK-NEXT: [[AUTHED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[AUTHED]], {{.*}} ] |
| // CHECK-NEXT: call void @use_upi(ptr noundef [[T0]]) |
| use_upi(global_iqpi); |
| } |
| |
| // Data with address-discriminated qualifiers. |
| |
| // CHECK-LABEL: define {{.*}}void @test_store_data_a_constant() |
| void test_store_data_a_constant() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[V]] to i64 |
| // CHECK-NEXT: [[NEWDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 50) |
| // CHECK-NEXT: [[SIGN:%.*]] = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr @external_int to i64), i32 1, i64 [[NEWDISC]]) |
| // CHECK-NEXT: [[T0:%.*]] = inttoptr i64 [[SIGN]] to ptr |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| int * AQ aqpi = &external_int; |
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[V]] to i64 |
| // CHECK-NEXT: [[NEWDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 50) |
| // CHECK-NEXT: [[SIGN:%.*]] = call i64 @llvm.ptrauth.sign(i64 ptrtoint (ptr @external_int to i64), i32 1, i64 [[NEWDISC]]) |
| // CHECK-NEXT: [[T0:%.*]] = inttoptr i64 [[SIGN]] to ptr |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| aqpi = &external_int; |
| } |
| |
| // CHECK-LABEL: define {{.*}}void @test_store_data_au() |
| void test_store_data_au() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_upi, |
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[V]] to i64 |
| // CHECK-NEXT: [[NEWDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.sign(i64 [[T0]], i32 1, i64 [[NEWDISC]]) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| int * AQ aqpi = global_upi; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_upi, |
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[V]] to i64 |
| // CHECK-NEXT: [[NEWDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.sign(i64 [[T0]], i32 1, i64 [[NEWDISC]]) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| aqpi = global_upi; |
| } |
| |
| // CHECK-LABEL: define {{.*}}void @test_store_data_ai() |
| void test_store_data_ai() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_iqpi, |
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[V]] to i64 |
| // CHECK-NEXT: [[NEWDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 50, i32 1, i64 [[NEWDISC]]) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| int * AQ aqpi = global_iqpi; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_iqpi, |
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[V]] to i64 |
| // CHECK-NEXT: [[NEWDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 50, i32 1, i64 [[NEWDISC]]) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| aqpi = global_iqpi; |
| } |
| |
| // CHECK-LABEL: define {{.*}}void @test_store_data_aa_same() |
| void test_store_data_aa_same() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_aqpi, |
| // CHECK-NEXT: [[OLDDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr @global_aqpi to i64), i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[V]] to i64 |
| // CHECK-NEXT: [[NEWDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 [[OLDDISC]], i32 1, i64 [[NEWDISC]]) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| int * AQ aqpi = global_aqpi; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_aqpi, |
| // CHECK-NEXT: [[OLDDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr @global_aqpi to i64), i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[V]] to i64 |
| // CHECK-NEXT: [[NEWDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 [[OLDDISC]], i32 1, i64 [[NEWDISC]]) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| aqpi = global_aqpi; |
| } |
| |
| // CHECK-LABEL: define {{.*}}void @test_store_data_aa_different() |
| void test_store_data_aa_different() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_aqpi, |
| // CHECK-NEXT: [[OLDDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr @global_aqpi to i64), i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[V]] to i64 |
| // CHECK-NEXT: [[NEWDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 100) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 [[OLDDISC]], i32 1, i64 [[NEWDISC]]) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| int * DIFF_AQ aqpi = global_aqpi; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_aqpi, |
| // CHECK-NEXT: [[OLDDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr @global_aqpi to i64), i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[V]] to i64 |
| // CHECK-NEXT: [[NEWDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 100) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 [[OLDDISC]], i32 1, i64 [[NEWDISC]]) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| aqpi = global_aqpi; |
| } |
| |
| // CHECK-LABEL: define {{.*}}void @test_store_data_aa_zero() |
| void test_store_data_aa_zero() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_aqpi, |
| // CHECK-NEXT: [[OLDDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr @global_aqpi to i64), i64 50) |
| // CHECK-NEXT: [[NEWDISC:%.*]] = ptrtoint ptr [[V]] to i64 |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 [[OLDDISC]], i32 1, i64 [[NEWDISC]]) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| int * ZERO_AQ aqpi = global_aqpi; |
| // CHECK: [[LOAD:%.*]] = load ptr, ptr [[V]], |
| // CHECK-NEXT: [[OLDDISC:%.*]] = ptrtoint ptr [[V]] to i64 |
| // CHECK-NEXT: [[NEWDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr @global_aqpi to i64), i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 [[OLDDISC]], i32 1, i64 [[NEWDISC]]) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr @global_aqpi, |
| global_aqpi = aqpi; |
| } |
| |
| // CHECK-LABEL: define {{.*}}void @test_load_data_a() |
| void test_load_data_a() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_aqpi, |
| // CHECK-NEXT: [[OLDDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr @global_aqpi to i64), i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[T0]], i32 1, i64 [[OLDDISC]]) |
| // CHECK-NEXT: [[AUTHED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[AUTHED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| int *upi = global_aqpi; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_aqpi, |
| // CHECK-NEXT: [[OLDDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr @global_aqpi to i64), i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[T0]], i32 1, i64 [[OLDDISC]]) |
| // CHECK-NEXT: [[AUTHED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[AUTHED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| upi = global_aqpi; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_aqpi, |
| // CHECK-NEXT: [[OLDDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr @global_aqpi to i64), i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.auth(i64 [[T0]], i32 1, i64 [[OLDDISC]]) |
| // CHECK-NEXT: [[AUTHED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[AUTHED]], {{.*}} ] |
| // CHECK-NEXT: call void @use_upi(ptr noundef [[T0]]) |
| use_upi(global_aqpi); |
| } |
| |
| // Function with address-independent qualifiers. |
| |
| // CHECK-LABEL: define {{.*}}void @test_store_function_i_constant() |
| void test_store_function_i_constant() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[SIGN:%.*]] = call i64 @llvm.ptrauth.resign(i64 ptrtoint (ptr ptrauth (ptr @external_func, i32 0, i64 18983) to i64), i32 0, i64 18983, i32 1, i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = inttoptr i64 [[SIGN]] to ptr |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| func_t * IQ iqpf = &external_func; |
| // CHECK-NEXT: [[SIGN:%.*]] = call i64 @llvm.ptrauth.resign(i64 ptrtoint (ptr ptrauth (ptr @external_func, i32 0, i64 18983) to i64), i32 0, i64 18983, i32 1, i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = inttoptr i64 [[SIGN]] to ptr |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| iqpf = &external_func; |
| } |
| |
| // CHECK-LABEL: define {{.*}}void @test_store_function_iu() |
| void test_store_function_iu() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_upf, |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 0, i64 18983, i32 1, i64 50) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| func_t * IQ iqpf = global_upf; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_upf, |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 0, i64 18983, i32 1, i64 50) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| iqpf = global_upf; |
| } |
| |
| // CHECK-LABEL: define {{.*}}void @test_store_function_ia() |
| void test_store_function_ia() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_aqpf, |
| // CHECK-NEXT: [[OLDDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr @global_aqpf to i64), i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 [[OLDDISC]], i32 1, i64 50) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| func_t * IQ iqpf = global_aqpf; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_aqpf, |
| // CHECK-NEXT: [[OLDDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr @global_aqpf to i64), i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 [[OLDDISC]], i32 1, i64 50) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| iqpf = global_aqpf; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_aqpf, |
| // CHECK-NEXT: [[OLDDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr @global_aqpf to i64), i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 [[OLDDISC]], i32 1, i64 50) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[RESULT:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[RESULT]], ptr [[V]], |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[RESULT]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[RESULT]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 50, i32 0, i64 18983) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: call void @use_upf(ptr noundef [[T0]]) |
| use_upf(iqpf = global_aqpf); |
| } |
| |
| // CHECK-LABEL: define {{.*}}void @test_store_function_ii_same() |
| void test_store_function_ii_same() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_iqpf, |
| // CHECK-NEXT: store ptr [[LOAD]], ptr [[V]], |
| func_t * IQ iqpf = global_iqpf; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_iqpf, |
| // CHECK-NEXT: store ptr [[LOAD]], ptr [[V]], |
| iqpf = global_iqpf; |
| } |
| |
| // CHECK-LABEL: define {{.*}}void @test_store_function_ii_different() |
| void test_store_function_ii_different() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_iqpf, |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 50, i32 1, i64 100) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| func_t * DIFF_IQ iqpf = global_iqpf; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_iqpf, |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 50, i32 1, i64 100) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| iqpf = global_iqpf; |
| } |
| |
| // CHECK-LABEL: define {{.*}}void @test_load_function_i() |
| void test_load_function_i() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_iqpf, |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 50, i32 0, i64 18983) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| func_t *upf = global_iqpf; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_iqpf, |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 50, i32 0, i64 18983) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| upf = global_iqpf; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_iqpf, |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 50, i32 0, i64 18983) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: call void @use_upf(ptr noundef [[T0]]) |
| use_upf(global_iqpf); |
| } |
| |
| // Function with address-discriminated qualifiers. |
| |
| // CHECK-LABEL: define {{.*}}void @test_store_function_a_constant() |
| void test_store_function_a_constant() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[V]] to i64 |
| // CHECK-NEXT: [[NEWDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 50) |
| // CHECK-NEXT: [[SIGN:%.*]] = call i64 @llvm.ptrauth.resign(i64 ptrtoint (ptr ptrauth (ptr @external_func, i32 0, i64 18983) to i64), i32 0, i64 18983, i32 1, i64 [[NEWDISC]]) |
| // CHECK-NEXT: [[T0:%.*]] = inttoptr i64 [[SIGN]] to ptr |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| func_t * AQ aqpf = &external_func; |
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[V]] to i64 |
| // CHECK-NEXT: [[NEWDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 50) |
| // CHECK-NEXT: [[SIGN:%.*]] = call i64 @llvm.ptrauth.resign(i64 ptrtoint (ptr ptrauth (ptr @external_func, i32 0, i64 18983) to i64), i32 0, i64 18983, i32 1, i64 [[NEWDISC]]) |
| // CHECK-NEXT: [[T0:%.*]] = inttoptr i64 [[SIGN]] to ptr |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| aqpf = &external_func; |
| } |
| |
| // CHECK-LABEL: define {{.*}}void @test_store_function_au() |
| void test_store_function_au() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_upf, |
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[V]] to i64 |
| // CHECK-NEXT: [[NEWDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 0, i64 18983, i32 1, i64 [[NEWDISC]]) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| func_t * AQ aqpf = global_upf; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_upf, |
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[V]] to i64 |
| // CHECK-NEXT: [[NEWDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 0, i64 18983, i32 1, i64 [[NEWDISC]]) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| aqpf = global_upf; |
| } |
| |
| // CHECK-LABEL: define {{.*}}void @test_store_function_ai() |
| void test_store_function_ai() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_iqpf, |
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[V]] to i64 |
| // CHECK-NEXT: [[NEWDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 50, i32 1, i64 [[NEWDISC]]) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| func_t * AQ aqpf = global_iqpf; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_iqpf, |
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[V]] to i64 |
| // CHECK-NEXT: [[NEWDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 50, i32 1, i64 [[NEWDISC]]) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| aqpf = global_iqpf; |
| } |
| |
| // CHECK-LABEL: define {{.*}}void @test_store_function_aa_same() |
| void test_store_function_aa_same() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_aqpf, |
| // CHECK-NEXT: [[OLDDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr @global_aqpf to i64), i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[V]] to i64 |
| // CHECK-NEXT: [[NEWDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 [[OLDDISC]], i32 1, i64 [[NEWDISC]]) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| func_t * AQ aqpf = global_aqpf; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_aqpf, |
| // CHECK-NEXT: [[OLDDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr @global_aqpf to i64), i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[V]] to i64 |
| // CHECK-NEXT: [[NEWDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 [[OLDDISC]], i32 1, i64 [[NEWDISC]]) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| aqpf = global_aqpf; |
| } |
| |
| // CHECK-LABEL: define {{.*}}void @test_store_function_aa_different() |
| void test_store_function_aa_different() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_aqpf, |
| // CHECK-NEXT: [[OLDDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr @global_aqpf to i64), i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[V]] to i64 |
| // CHECK-NEXT: [[NEWDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 100) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 [[OLDDISC]], i32 1, i64 [[NEWDISC]]) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| func_t * DIFF_AQ aqpf = global_aqpf; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_aqpf, |
| // CHECK-NEXT: [[OLDDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr @global_aqpf to i64), i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = ptrtoint ptr [[V]] to i64 |
| // CHECK-NEXT: [[NEWDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 [[T0]], i64 100) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 [[OLDDISC]], i32 1, i64 [[NEWDISC]]) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| aqpf = global_aqpf; |
| } |
| |
| // CHECK-LABEL: define {{.*}}void @test_load_function_a() |
| void test_load_function_a() { |
| // CHECK: [[V:%.*]] = alloca ptr, |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_aqpf, |
| // CHECK-NEXT: [[OLDDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr @global_aqpf to i64), i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 [[OLDDISC]], i32 0, i64 18983) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| func_t *upf = global_aqpf; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_aqpf, |
| // CHECK-NEXT: [[OLDDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr @global_aqpf to i64), i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 [[OLDDISC]], i32 0, i64 18983) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: store ptr [[T0]], ptr [[V]], |
| upf = global_aqpf; |
| // CHECK-NEXT: [[LOAD:%.*]] = load ptr, ptr @global_aqpf, |
| // CHECK-NEXT: [[OLDDISC:%.*]] = call i64 @llvm.ptrauth.blend(i64 ptrtoint (ptr @global_aqpf to i64), i64 50) |
| // CHECK-NEXT: [[T0:%.*]] = icmp ne ptr [[LOAD]], null |
| // CHECK-NEXT: br i1 [[T0]], |
| // CHECK: [[T0:%.*]] = ptrtoint ptr [[LOAD]] to i64 |
| // CHECK-NEXT: [[T1:%.*]] = call i64 @llvm.ptrauth.resign(i64 [[T0]], i32 1, i64 [[OLDDISC]], i32 0, i64 18983) |
| // CHECK-NEXT: [[SIGNED:%.*]] = inttoptr i64 [[T1]] to ptr |
| // CHECK-NEXT: br label |
| // CHECK: [[T0:%.*]] = phi ptr [ null, {{.*}} ], [ [[SIGNED]], {{.*}} ] |
| // CHECK-NEXT: call void @use_upf(ptr noundef [[T0]]) |
| use_upf(global_aqpf); |
| } |