
The qualifier allows programmer to directly control how pointers are signed when they are stored in a particular variable. The qualifier takes three arguments: the signing key, a flag specifying whether address discrimination should be used, and a non-negative integer that is used for additional discrimination. ``` typedef void (*my_callback)(const void*); my_callback __ptrauth(ptrauth_key_process_dependent_code, 1, 0xe27a) callback; ``` Co-Authored-By: John McCall rjmccall@apple.com
746 lines
39 KiB
C
746 lines
39 KiB
C
// 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);
|
|
}
|