blob: db259ed950fec80b10a3ec9d51daa28bc1b5c6c9 [file] [log] [blame]
// 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);
}