diff --git a/clang/lib/Headers/cheriintrin.h b/clang/lib/Headers/cheriintrin.h index 021c6527839b..4baec3e75866 100644 --- a/clang/lib/Headers/cheriintrin.h +++ b/clang/lib/Headers/cheriintrin.h @@ -39,7 +39,7 @@ #define cheri_bounds_set_exact(x, y) __builtin_cheri_bounds_set_exact((x), (y)) /* Object types, sealing and unsealing: */ -typedef long cheri_otype_t; +typedef __PTRDIFF_TYPE__ cheri_otype_t; #if defined(__mips__) || defined(__riscv) /* CHERI-MIPS and CHERI-RISC-V use negative numbers for hardware-interpreted * otypes */ @@ -67,7 +67,10 @@ typedef long cheri_otype_t; #define cheri_type_copy(x, y) __builtin_cheri_cap_type_copy((x), (y)) /* Capability permissions: */ -typedef enum __attribute__((flag_enum, enum_extensibility(open))) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wfixed-enum-extension" +/* Use __PTRADDR_TYPE__ as the underlying type to avoid unnecessary truncates */ +typedef enum __attribute__((flag_enum, enum_extensibility(open))) : __PTRADDR_TYPE__ { CHERI_PERM_GLOBAL = __CHERI_CAP_PERMISSION_GLOBAL__, CHERI_PERM_EXECUTE = __CHERI_CAP_PERMISSION_PERMIT_EXECUTE__, CHERI_PERM_LOAD = __CHERI_CAP_PERMISSION_PERMIT_LOAD__, @@ -82,9 +85,9 @@ typedef enum __attribute__((flag_enum, enum_extensibility(open))) { /* TODO: architecture-dependent permissions */ } cheri_perms_t; #define cheri_perms_get(x) ((cheri_perms_t)(__builtin_cheri_perms_get(x))) -#define cheri_perms_and(x, y) __builtin_cheri_perms_and((x), (__SIZE_TYPE__)(y)) +#define cheri_perms_and(x, y) __builtin_cheri_perms_and((x), (cheri_perms_t)(y)) #define cheri_perms_clear(x, y) \ - __builtin_cheri_perms_and((x), ~(__SIZE_TYPE__)(y)) + __builtin_cheri_perms_and((x), ~(__PTRADDR_TYPE__)(y)) /* Accessors for capability registers. Currently exposes DDC and PCC. */ #define cheri_ddc_get() __builtin_cheri_global_data_get() diff --git a/clang/test/CodeGen/cheri/cheriintrin.c b/clang/test/CodeGen/cheri/cheriintrin.c index 1f6f5353c3e0..fcc13fe06299 100644 --- a/clang/test/CodeGen/cheri/cheriintrin.c +++ b/clang/test/CodeGen/cheri/cheriintrin.c @@ -1,5 +1,12 @@ -// RUN: %cheri_cc1 %s -o - -emit-llvm -O1 -Weverything -Werror -verify -Wno-declaration-after-statement | FileCheck %s -// RUN: %cheri_purecap_cc1 %s -o - -emit-llvm -O1 -Weverything -Werror -Wno-declaration-after-statement -verify | FileCheck %s +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %riscv64_cheri_cc1 -Weverything -Werror -Wno-declaration-after-statement -verify \ +// RUN: -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s --check-prefixes=CHECK64 +// RUN: %riscv64_cheri_purecap_cc1 -Weverything -Werror -Wno-declaration-after-statement -verify \ +// RUN: -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s --check-prefixes=CHECK64 +// RUN: %riscv32_cheri_cc1 -Weverything -Werror -Wno-declaration-after-statement -verify \ +// RUN: -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s --check-prefixes=CHECK32 +// RUN: %riscv32_cheri_purecap_cc1 -Weverything -Werror -Wno-declaration-after-statement -verify \ +// RUN: -disable-O0-optnone -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s --check-prefixes=CHECK32 // expected-no-diagnostics #include @@ -11,78 +18,155 @@ void use_cap(void *__capability p); void test(void *__capability cap, char *__capability cap2, __SIZE_TYPE__ i); -// CHECK-LABEL: define {{[^@]+}}@test -// CHECK-SAME: (i8 addrspace(200)* noundef [[CAP:%.*]], i8 addrspace(200)* noundef [[CAP2:%.*]], i64 noundef zeroext [[I:%.*]]) local_unnamed_addr -// CHECK-NEXT: entry: -// CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.cheri.cap.address.get.i64(i8 addrspace(200)* [[CAP]]) -// CHECK-NEXT: call void @use_size_t(i64 noundef zeroext [[TMP0]]) #5 -// CHECK-NEXT: [[TMP1:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.address.set.i64(i8 addrspace(200)* [[CAP]], i64 [[I]]) -// CHECK-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP1]]) #5 -// CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.cheri.cap.base.get.i64(i8 addrspace(200)* [[CAP]]) -// CHECK-NEXT: call void @use_size_t(i64 noundef zeroext [[TMP2]]) #5 -// CHECK-NEXT: [[TMP3:%.*]] = call i64 @llvm.cheri.cap.length.get.i64(i8 addrspace(200)* [[CAP]]) -// CHECK-NEXT: call void @use_size_t(i64 noundef zeroext [[TMP3]]) #5 -// CHECK-NEXT: [[TMP4:%.*]] = call i64 @llvm.cheri.cap.offset.get.i64(i8 addrspace(200)* [[CAP]]) -// CHECK-NEXT: call void @use_size_t(i64 noundef zeroext [[TMP4]]) #5 -// CHECK-NEXT: [[TMP5:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.offset.set.i64(i8 addrspace(200)* [[CAP]], i64 [[I]]) -// CHECK-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP5]]) #5 -// CHECK-NEXT: [[TMP6:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.tag.clear(i8 addrspace(200)* [[CAP]]) -// CHECK-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP6]]) #5 -// CHECK-NEXT: [[TMP7:%.*]] = call i1 @llvm.cheri.cap.tag.get(i8 addrspace(200)* [[CAP]]) -// CHECK-NEXT: call void @use_bool(i1 noundef zeroext [[TMP7]]) #5 -// CHECK-NEXT: call void @use_bool(i1 noundef zeroext [[TMP7]]) #5 -// CHECK-NEXT: [[LNOT:%.*]] = xor i1 [[TMP7]], true -// CHECK-NEXT: call void @use_bool(i1 noundef zeroext [[LNOT]]) #5 -// CHECK-NEXT: [[TMP8:%.*]] = call i1 @llvm.cheri.cap.equal.exact(i8 addrspace(200)* [[CAP]], i8 addrspace(200)* [[CAP2]]) -// CHECK-NEXT: call void @use_bool(i1 noundef zeroext [[TMP8]]) #5 -// CHECK-NEXT: [[TMP9:%.*]] = call i1 @llvm.cheri.cap.subset.test(i8 addrspace(200)* [[CAP]], i8 addrspace(200)* [[CAP2]]) -// CHECK-NEXT: call void @use_bool(i1 noundef zeroext [[TMP9]]) #5 -// CHECK-NEXT: [[TMP10:%.*]] = call i64 @llvm.cheri.round.representable.length.i64(i64 [[I]]) -// CHECK-NEXT: call void @use_size_t(i64 noundef zeroext [[TMP10]]) #5 -// CHECK-NEXT: [[TMP11:%.*]] = call i64 @llvm.cheri.representable.alignment.mask.i64(i64 [[I]]) -// CHECK-NEXT: call void @use_size_t(i64 noundef zeroext [[TMP11]]) #5 -// CHECK-NEXT: [[TMP12:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.bounds.set.i64(i8 addrspace(200)* [[CAP]], i64 [[I]]) -// CHECK-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP12]]) #5 -// CHECK-NEXT: [[TMP13:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.bounds.set.exact.i64(i8 addrspace(200)* [[CAP]], i64 [[I]]) -// CHECK-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP13]]) #5 -// CHECK-NEXT: [[TMP14:%.*]] = call i64 @llvm.cheri.cap.type.get.i64(i8 addrspace(200)* [[CAP]]) -// CHECK-NEXT: call void @use_size_t(i64 noundef zeroext [[TMP14]]) #5 -// CHECK-NEXT: [[TMP15:%.*]] = call i1 @llvm.cheri.cap.sealed.get(i8 addrspace(200)* [[CAP]]) -// CHECK-NEXT: call void @use_bool(i1 noundef zeroext [[TMP15]]) #5 -// CHECK-NEXT: [[LNOT1:%.*]] = xor i1 [[TMP15]], true -// CHECK-NEXT: call void @use_bool(i1 noundef zeroext [[LNOT1]]) #5 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[TMP14]], -2 -// CHECK-NEXT: call void @use_bool(i1 noundef zeroext [[CMP]]) #5 -// CHECK-NEXT: [[TMP16:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.seal.entry(i8 addrspace(200)* [[CAP]]) -// CHECK-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP16]]) #5 -// CHECK-NEXT: [[TMP17:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.seal(i8 addrspace(200)* [[CAP]], i8 addrspace(200)* [[CAP2]]) -// CHECK-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP17]]) #5 -// CHECK-NEXT: [[TMP18:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.unseal(i8 addrspace(200)* [[CAP]], i8 addrspace(200)* [[CAP2]]) -// CHECK-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP18]]) #5 -// CHECK-NEXT: [[TMP19:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.build(i8 addrspace(200)* [[CAP]], i8 addrspace(200)* [[CAP2]]) -// CHECK-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP19]]) #5 -// CHECK-NEXT: [[TMP20:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.conditional.seal(i8 addrspace(200)* [[CAP]], i8 addrspace(200)* [[CAP2]]) -// CHECK-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP20]]) #5 -// CHECK-NEXT: [[TMP21:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.type.copy(i8 addrspace(200)* [[CAP]], i8 addrspace(200)* [[CAP2]]) -// CHECK-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP21]]) #5 -// CHECK-NEXT: [[TMP22:%.*]] = call i64 @llvm.cheri.cap.perms.get.i64(i8 addrspace(200)* [[CAP]]) -// CHECK-NEXT: [[CONV2:%.*]] = and i64 [[TMP22]], 4294967295 -// CHECK-NEXT: call void @use_size_t(i64 noundef zeroext [[CONV2]]) #5 -// CHECK-NEXT: [[TMP23:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.perms.and.i64(i8 addrspace(200)* [[CAP]], i64 4) -// CHECK-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP23]]) #5 -// CHECK-NEXT: [[TMP24:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.perms.and.i64(i8 addrspace(200)* [[CAP]], i64 -3) -// CHECK-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP24]]) #5 -// CHECK-NEXT: [[TMP25:%.*]] = call i8 addrspace(200)* @llvm.cheri.ddc.get() -// CHECK-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP25]]) #5 -// CHECK-NEXT: [[TMP26:%.*]] = call i8 addrspace(200)* @llvm.cheri.pcc.get() -// CHECK-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP26]]) #5 -// CHECK-NEXT: [[TMP27:%.*]] = call i64 @llvm.cheri.cap.flags.get.i64(i8 addrspace(200)* [[CAP]]) -// CHECK-NEXT: call void @use_size_t(i64 noundef zeroext [[TMP27]]) #5 -// CHECK-NEXT: [[TMP28:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.flags.set.i64(i8 addrspace(200)* [[CAP]], i64 [[I]]) -// CHECK-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP28]]) #5 -// CHECK-NEXT: [[TMP29:%.*]] = call i64 @llvm.cheri.cap.load.tags.i64(i8 addrspace(200)* [[CAP]]) -// CHECK-NEXT: call void @use_size_t(i64 noundef zeroext [[TMP29]]) #5 -// CHECK-NEXT: ret void +// CHECK64-LABEL: @test( +// CHECK64-NEXT: entry: +// CHECK64-NEXT: [[TMP0:%.*]] = call i64 @llvm.cheri.cap.address.get.i64(i8 addrspace(200)* [[CAP:%.*]]) +// CHECK64-NEXT: call void @use_size_t(i64 noundef [[TMP0]]) +// CHECK64-NEXT: [[TMP1:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.address.set.i64(i8 addrspace(200)* [[CAP]], i64 [[I:%.*]]) +// CHECK64-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP1]]) +// CHECK64-NEXT: [[TMP2:%.*]] = call i64 @llvm.cheri.cap.base.get.i64(i8 addrspace(200)* [[CAP]]) +// CHECK64-NEXT: call void @use_size_t(i64 noundef [[TMP2]]) +// CHECK64-NEXT: [[TMP3:%.*]] = call i64 @llvm.cheri.cap.length.get.i64(i8 addrspace(200)* [[CAP]]) +// CHECK64-NEXT: call void @use_size_t(i64 noundef [[TMP3]]) +// CHECK64-NEXT: [[TMP4:%.*]] = call i64 @llvm.cheri.cap.offset.get.i64(i8 addrspace(200)* [[CAP]]) +// CHECK64-NEXT: call void @use_size_t(i64 noundef [[TMP4]]) +// CHECK64-NEXT: [[TMP5:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.offset.set.i64(i8 addrspace(200)* [[CAP]], i64 [[I]]) +// CHECK64-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP5]]) +// CHECK64-NEXT: [[TMP6:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.tag.clear(i8 addrspace(200)* [[CAP]]) +// CHECK64-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP6]]) +// CHECK64-NEXT: [[TMP7:%.*]] = call i1 @llvm.cheri.cap.tag.get(i8 addrspace(200)* [[CAP]]) +// CHECK64-NEXT: call void @use_bool(i1 noundef zeroext [[TMP7]]) +// CHECK64-NEXT: [[TMP8:%.*]] = call i1 @llvm.cheri.cap.tag.get(i8 addrspace(200)* [[CAP]]) +// CHECK64-NEXT: call void @use_bool(i1 noundef zeroext [[TMP8]]) +// CHECK64-NEXT: [[TMP9:%.*]] = call i1 @llvm.cheri.cap.tag.get(i8 addrspace(200)* [[CAP]]) +// CHECK64-NEXT: [[LNOT:%.*]] = xor i1 [[TMP9]], true +// CHECK64-NEXT: call void @use_bool(i1 noundef zeroext [[LNOT]]) +// CHECK64-NEXT: [[TMP10:%.*]] = call i1 @llvm.cheri.cap.equal.exact(i8 addrspace(200)* [[CAP]], i8 addrspace(200)* [[CAP2:%.*]]) +// CHECK64-NEXT: call void @use_bool(i1 noundef zeroext [[TMP10]]) +// CHECK64-NEXT: [[TMP11:%.*]] = call i1 @llvm.cheri.cap.subset.test(i8 addrspace(200)* [[CAP]], i8 addrspace(200)* [[CAP2]]) +// CHECK64-NEXT: call void @use_bool(i1 noundef zeroext [[TMP11]]) +// CHECK64-NEXT: [[TMP12:%.*]] = call i64 @llvm.cheri.round.representable.length.i64(i64 [[I]]) +// CHECK64-NEXT: call void @use_size_t(i64 noundef [[TMP12]]) +// CHECK64-NEXT: [[TMP13:%.*]] = call i64 @llvm.cheri.representable.alignment.mask.i64(i64 [[I]]) +// CHECK64-NEXT: call void @use_size_t(i64 noundef [[TMP13]]) +// CHECK64-NEXT: [[TMP14:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.bounds.set.i64(i8 addrspace(200)* [[CAP]], i64 [[I]]) +// CHECK64-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP14]]) +// CHECK64-NEXT: [[TMP15:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.bounds.set.exact.i64(i8 addrspace(200)* [[CAP]], i64 [[I]]) +// CHECK64-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP15]]) +// CHECK64-NEXT: [[TMP16:%.*]] = call i64 @llvm.cheri.cap.type.get.i64(i8 addrspace(200)* [[CAP]]) +// CHECK64-NEXT: call void @use_size_t(i64 noundef [[TMP16]]) +// CHECK64-NEXT: [[TMP17:%.*]] = call i1 @llvm.cheri.cap.sealed.get(i8 addrspace(200)* [[CAP]]) +// CHECK64-NEXT: call void @use_bool(i1 noundef zeroext [[TMP17]]) +// CHECK64-NEXT: [[TMP18:%.*]] = call i1 @llvm.cheri.cap.sealed.get(i8 addrspace(200)* [[CAP]]) +// CHECK64-NEXT: [[LNOT1:%.*]] = xor i1 [[TMP18]], true +// CHECK64-NEXT: call void @use_bool(i1 noundef zeroext [[LNOT1]]) +// CHECK64-NEXT: [[TMP19:%.*]] = call i64 @llvm.cheri.cap.type.get.i64(i8 addrspace(200)* [[CAP]]) +// CHECK64-NEXT: [[CMP:%.*]] = icmp eq i64 [[TMP19]], -2 +// CHECK64-NEXT: call void @use_bool(i1 noundef zeroext [[CMP]]) +// CHECK64-NEXT: [[TMP20:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.seal.entry(i8 addrspace(200)* [[CAP]]) +// CHECK64-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP20]]) +// CHECK64-NEXT: [[TMP21:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.seal(i8 addrspace(200)* [[CAP]], i8 addrspace(200)* [[CAP2]]) +// CHECK64-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP21]]) +// CHECK64-NEXT: [[TMP22:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.unseal(i8 addrspace(200)* [[CAP]], i8 addrspace(200)* [[CAP2]]) +// CHECK64-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP22]]) +// CHECK64-NEXT: [[TMP23:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.build(i8 addrspace(200)* [[CAP]], i8 addrspace(200)* [[CAP2]]) +// CHECK64-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP23]]) +// CHECK64-NEXT: [[TMP24:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.conditional.seal(i8 addrspace(200)* [[CAP]], i8 addrspace(200)* [[CAP2]]) +// CHECK64-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP24]]) +// CHECK64-NEXT: [[TMP25:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.type.copy(i8 addrspace(200)* [[CAP]], i8 addrspace(200)* [[CAP2]]) +// CHECK64-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP25]]) +// CHECK64-NEXT: [[TMP26:%.*]] = call i64 @llvm.cheri.cap.perms.get.i64(i8 addrspace(200)* [[CAP]]) +// CHECK64-NEXT: call void @use_size_t(i64 noundef [[TMP26]]) +// CHECK64-NEXT: [[TMP27:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.perms.and.i64(i8 addrspace(200)* [[CAP]], i64 4) +// CHECK64-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP27]]) +// CHECK64-NEXT: [[TMP28:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.perms.and.i64(i8 addrspace(200)* [[CAP]], i64 -3) +// CHECK64-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP28]]) +// CHECK64-NEXT: [[TMP29:%.*]] = call i8 addrspace(200)* @llvm.cheri.ddc.get() +// CHECK64-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP29]]) +// CHECK64-NEXT: [[TMP30:%.*]] = call i8 addrspace(200)* @llvm.cheri.pcc.get() +// CHECK64-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP30]]) +// CHECK64-NEXT: [[TMP31:%.*]] = call i64 @llvm.cheri.cap.flags.get.i64(i8 addrspace(200)* [[CAP]]) +// CHECK64-NEXT: call void @use_size_t(i64 noundef [[TMP31]]) +// CHECK64-NEXT: [[TMP32:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.flags.set.i64(i8 addrspace(200)* [[CAP]], i64 [[I]]) +// CHECK64-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP32]]) +// CHECK64-NEXT: [[TMP33:%.*]] = call i64 @llvm.cheri.cap.load.tags.i64(i8 addrspace(200)* [[CAP]]) +// CHECK64-NEXT: call void @use_size_t(i64 noundef [[TMP33]]) +// CHECK64-NEXT: ret void +// +// CHECK32-LABEL: @test( +// CHECK32-NEXT: entry: +// CHECK32-NEXT: [[TMP0:%.*]] = call i32 @llvm.cheri.cap.address.get.i32(i8 addrspace(200)* [[CAP:%.*]]) +// CHECK32-NEXT: call void @use_size_t(i32 noundef [[TMP0]]) +// CHECK32-NEXT: [[TMP1:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.address.set.i32(i8 addrspace(200)* [[CAP]], i32 [[I:%.*]]) +// CHECK32-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP1]]) +// CHECK32-NEXT: [[TMP2:%.*]] = call i32 @llvm.cheri.cap.base.get.i32(i8 addrspace(200)* [[CAP]]) +// CHECK32-NEXT: call void @use_size_t(i32 noundef [[TMP2]]) +// CHECK32-NEXT: [[TMP3:%.*]] = call i32 @llvm.cheri.cap.length.get.i32(i8 addrspace(200)* [[CAP]]) +// CHECK32-NEXT: call void @use_size_t(i32 noundef [[TMP3]]) +// CHECK32-NEXT: [[TMP4:%.*]] = call i32 @llvm.cheri.cap.offset.get.i32(i8 addrspace(200)* [[CAP]]) +// CHECK32-NEXT: call void @use_size_t(i32 noundef [[TMP4]]) +// CHECK32-NEXT: [[TMP5:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.offset.set.i32(i8 addrspace(200)* [[CAP]], i32 [[I]]) +// CHECK32-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP5]]) +// CHECK32-NEXT: [[TMP6:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.tag.clear(i8 addrspace(200)* [[CAP]]) +// CHECK32-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP6]]) +// CHECK32-NEXT: [[TMP7:%.*]] = call i1 @llvm.cheri.cap.tag.get(i8 addrspace(200)* [[CAP]]) +// CHECK32-NEXT: call void @use_bool(i1 noundef zeroext [[TMP7]]) +// CHECK32-NEXT: [[TMP8:%.*]] = call i1 @llvm.cheri.cap.tag.get(i8 addrspace(200)* [[CAP]]) +// CHECK32-NEXT: call void @use_bool(i1 noundef zeroext [[TMP8]]) +// CHECK32-NEXT: [[TMP9:%.*]] = call i1 @llvm.cheri.cap.tag.get(i8 addrspace(200)* [[CAP]]) +// CHECK32-NEXT: [[LNOT:%.*]] = xor i1 [[TMP9]], true +// CHECK32-NEXT: call void @use_bool(i1 noundef zeroext [[LNOT]]) +// CHECK32-NEXT: [[TMP10:%.*]] = call i1 @llvm.cheri.cap.equal.exact(i8 addrspace(200)* [[CAP]], i8 addrspace(200)* [[CAP2:%.*]]) +// CHECK32-NEXT: call void @use_bool(i1 noundef zeroext [[TMP10]]) +// CHECK32-NEXT: [[TMP11:%.*]] = call i1 @llvm.cheri.cap.subset.test(i8 addrspace(200)* [[CAP]], i8 addrspace(200)* [[CAP2]]) +// CHECK32-NEXT: call void @use_bool(i1 noundef zeroext [[TMP11]]) +// CHECK32-NEXT: [[TMP12:%.*]] = call i32 @llvm.cheri.round.representable.length.i32(i32 [[I]]) +// CHECK32-NEXT: call void @use_size_t(i32 noundef [[TMP12]]) +// CHECK32-NEXT: [[TMP13:%.*]] = call i32 @llvm.cheri.representable.alignment.mask.i32(i32 [[I]]) +// CHECK32-NEXT: call void @use_size_t(i32 noundef [[TMP13]]) +// CHECK32-NEXT: [[TMP14:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.bounds.set.i32(i8 addrspace(200)* [[CAP]], i32 [[I]]) +// CHECK32-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP14]]) +// CHECK32-NEXT: [[TMP15:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.bounds.set.exact.i32(i8 addrspace(200)* [[CAP]], i32 [[I]]) +// CHECK32-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP15]]) +// CHECK32-NEXT: [[TMP16:%.*]] = call i32 @llvm.cheri.cap.type.get.i32(i8 addrspace(200)* [[CAP]]) +// CHECK32-NEXT: call void @use_size_t(i32 noundef [[TMP16]]) +// CHECK32-NEXT: [[TMP17:%.*]] = call i1 @llvm.cheri.cap.sealed.get(i8 addrspace(200)* [[CAP]]) +// CHECK32-NEXT: call void @use_bool(i1 noundef zeroext [[TMP17]]) +// CHECK32-NEXT: [[TMP18:%.*]] = call i1 @llvm.cheri.cap.sealed.get(i8 addrspace(200)* [[CAP]]) +// CHECK32-NEXT: [[LNOT1:%.*]] = xor i1 [[TMP18]], true +// CHECK32-NEXT: call void @use_bool(i1 noundef zeroext [[LNOT1]]) +// CHECK32-NEXT: [[TMP19:%.*]] = call i32 @llvm.cheri.cap.type.get.i32(i8 addrspace(200)* [[CAP]]) +// CHECK32-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP19]], -2 +// CHECK32-NEXT: call void @use_bool(i1 noundef zeroext [[CMP]]) +// CHECK32-NEXT: [[TMP20:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.seal.entry(i8 addrspace(200)* [[CAP]]) +// CHECK32-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP20]]) +// CHECK32-NEXT: [[TMP21:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.seal(i8 addrspace(200)* [[CAP]], i8 addrspace(200)* [[CAP2]]) +// CHECK32-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP21]]) +// CHECK32-NEXT: [[TMP22:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.unseal(i8 addrspace(200)* [[CAP]], i8 addrspace(200)* [[CAP2]]) +// CHECK32-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP22]]) +// CHECK32-NEXT: [[TMP23:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.build(i8 addrspace(200)* [[CAP]], i8 addrspace(200)* [[CAP2]]) +// CHECK32-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP23]]) +// CHECK32-NEXT: [[TMP24:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.conditional.seal(i8 addrspace(200)* [[CAP]], i8 addrspace(200)* [[CAP2]]) +// CHECK32-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP24]]) +// CHECK32-NEXT: [[TMP25:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.type.copy(i8 addrspace(200)* [[CAP]], i8 addrspace(200)* [[CAP2]]) +// CHECK32-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP25]]) +// CHECK32-NEXT: [[TMP26:%.*]] = call i32 @llvm.cheri.cap.perms.get.i32(i8 addrspace(200)* [[CAP]]) +// CHECK32-NEXT: call void @use_size_t(i32 noundef [[TMP26]]) +// CHECK32-NEXT: [[TMP27:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.perms.and.i32(i8 addrspace(200)* [[CAP]], i32 4) +// CHECK32-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP27]]) +// CHECK32-NEXT: [[TMP28:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.perms.and.i32(i8 addrspace(200)* [[CAP]], i32 -3) +// CHECK32-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP28]]) +// CHECK32-NEXT: [[TMP29:%.*]] = call i8 addrspace(200)* @llvm.cheri.ddc.get() +// CHECK32-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP29]]) +// CHECK32-NEXT: [[TMP30:%.*]] = call i8 addrspace(200)* @llvm.cheri.pcc.get() +// CHECK32-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP30]]) +// CHECK32-NEXT: [[TMP31:%.*]] = call i32 @llvm.cheri.cap.flags.get.i32(i8 addrspace(200)* [[CAP]]) +// CHECK32-NEXT: call void @use_size_t(i32 noundef [[TMP31]]) +// CHECK32-NEXT: [[TMP32:%.*]] = call i8 addrspace(200)* @llvm.cheri.cap.flags.set.i32(i8 addrspace(200)* [[CAP]], i32 [[I]]) +// CHECK32-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[TMP32]]) +// CHECK32-NEXT: [[TMP33:%.*]] = call i32 @llvm.cheri.cap.load.tags.i32(i8 addrspace(200)* [[CAP]]) +// CHECK32-NEXT: call void @use_size_t(i32 noundef [[TMP33]]) +// CHECK32-NEXT: ret void // void test(void *__capability cap, char *__capability cap2, __SIZE_TYPE__ i) { use_size_t(cheri_address_get(cap)); @@ -111,7 +195,7 @@ void test(void *__capability cap, char *__capability cap2, __SIZE_TYPE__ i) { /* Check that the cheri_otype_t type is defined */ _Static_assert(__builtin_types_compatible_p(cheri_otype_t *, __typeof__(cheri_type_get(cap)) *), ""); - _Static_assert(__builtin_types_compatible_p(cheri_otype_t *, long *), ""); + _Static_assert(__builtin_types_compatible_p(cheri_otype_t *, __PTRDIFF_TYPE__ *), ""); _Static_assert(CHERI_OTYPE_UNSEALED == -1, "RISCV and MIPS expect -2"); _Static_assert(CHERI_OTYPE_SENTRY == -2, "RISCV and MIPS expect -2"); use_size_t((unsigned long)cheri_type_get(cap)); @@ -159,6 +243,58 @@ void test(void *__capability cap, char *__capability cap2, __SIZE_TYPE__ i) { */ void test_alignment_builtins(void *__capability cap, __SIZE_TYPE__ align); +// CHECK64-LABEL: @test_alignment_builtins( +// CHECK64-NEXT: entry: +// CHECK64-NEXT: [[MASK:%.*]] = sub i64 [[ALIGN:%.*]], 1 +// CHECK64-NEXT: [[PTRADDR:%.*]] = call i64 @llvm.cheri.cap.address.get.i64(i8 addrspace(200)* [[CAP:%.*]]) +// CHECK64-NEXT: [[OVER_BOUNDARY:%.*]] = add i64 [[PTRADDR]], [[MASK]] +// CHECK64-NEXT: [[INVERTED_MASK:%.*]] = xor i64 [[MASK]], -1 +// CHECK64-NEXT: [[ALIGNED_INTPTR:%.*]] = and i64 [[OVER_BOUNDARY]], [[INVERTED_MASK]] +// CHECK64-NEXT: [[DIFF:%.*]] = sub i64 [[ALIGNED_INTPTR]], [[PTRADDR]] +// CHECK64-NEXT: [[ALIGNED_RESULT:%.*]] = getelementptr inbounds i8, i8 addrspace(200)* [[CAP]], i64 [[DIFF]] +// CHECK64-NEXT: call void @llvm.assume(i1 true) [ "align"(i8 addrspace(200)* [[ALIGNED_RESULT]], i64 [[ALIGN]]) ] +// CHECK64-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[ALIGNED_RESULT]]) +// CHECK64-NEXT: [[MASK1:%.*]] = sub i64 [[ALIGN]], 1 +// CHECK64-NEXT: [[PTRADDR2:%.*]] = call i64 @llvm.cheri.cap.address.get.i64(i8 addrspace(200)* [[CAP]]) +// CHECK64-NEXT: [[INVERTED_MASK3:%.*]] = xor i64 [[MASK1]], -1 +// CHECK64-NEXT: [[ALIGNED_INTPTR5:%.*]] = and i64 [[PTRADDR2]], [[INVERTED_MASK3]] +// CHECK64-NEXT: [[DIFF6:%.*]] = sub i64 [[ALIGNED_INTPTR5]], [[PTRADDR2]] +// CHECK64-NEXT: [[ALIGNED_RESULT7:%.*]] = getelementptr inbounds i8, i8 addrspace(200)* [[CAP]], i64 [[DIFF6]] +// CHECK64-NEXT: call void @llvm.assume(i1 true) [ "align"(i8 addrspace(200)* [[ALIGNED_RESULT7]], i64 [[ALIGN]]) ] +// CHECK64-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[ALIGNED_RESULT7]]) +// CHECK64-NEXT: [[MASK8:%.*]] = sub i64 [[ALIGN]], 1 +// CHECK64-NEXT: [[PTRADDR9:%.*]] = call i64 @llvm.cheri.cap.address.get.i64(i8 addrspace(200)* [[CAP]]) +// CHECK64-NEXT: [[SET_BITS:%.*]] = and i64 [[PTRADDR9]], [[MASK8]] +// CHECK64-NEXT: [[IS_ALIGNED:%.*]] = icmp eq i64 [[SET_BITS]], 0 +// CHECK64-NEXT: call void @use_bool(i1 noundef zeroext [[IS_ALIGNED]]) +// CHECK64-NEXT: ret void +// +// CHECK32-LABEL: @test_alignment_builtins( +// CHECK32-NEXT: entry: +// CHECK32-NEXT: [[MASK:%.*]] = sub i32 [[ALIGN:%.*]], 1 +// CHECK32-NEXT: [[PTRADDR:%.*]] = call i32 @llvm.cheri.cap.address.get.i32(i8 addrspace(200)* [[CAP:%.*]]) +// CHECK32-NEXT: [[OVER_BOUNDARY:%.*]] = add i32 [[PTRADDR]], [[MASK]] +// CHECK32-NEXT: [[INVERTED_MASK:%.*]] = xor i32 [[MASK]], -1 +// CHECK32-NEXT: [[ALIGNED_INTPTR:%.*]] = and i32 [[OVER_BOUNDARY]], [[INVERTED_MASK]] +// CHECK32-NEXT: [[DIFF:%.*]] = sub i32 [[ALIGNED_INTPTR]], [[PTRADDR]] +// CHECK32-NEXT: [[ALIGNED_RESULT:%.*]] = getelementptr inbounds i8, i8 addrspace(200)* [[CAP]], i32 [[DIFF]] +// CHECK32-NEXT: call void @llvm.assume(i1 true) [ "align"(i8 addrspace(200)* [[ALIGNED_RESULT]], i32 [[ALIGN]]) ] +// CHECK32-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[ALIGNED_RESULT]]) +// CHECK32-NEXT: [[MASK1:%.*]] = sub i32 [[ALIGN]], 1 +// CHECK32-NEXT: [[PTRADDR2:%.*]] = call i32 @llvm.cheri.cap.address.get.i32(i8 addrspace(200)* [[CAP]]) +// CHECK32-NEXT: [[INVERTED_MASK3:%.*]] = xor i32 [[MASK1]], -1 +// CHECK32-NEXT: [[ALIGNED_INTPTR5:%.*]] = and i32 [[PTRADDR2]], [[INVERTED_MASK3]] +// CHECK32-NEXT: [[DIFF6:%.*]] = sub i32 [[ALIGNED_INTPTR5]], [[PTRADDR2]] +// CHECK32-NEXT: [[ALIGNED_RESULT7:%.*]] = getelementptr inbounds i8, i8 addrspace(200)* [[CAP]], i32 [[DIFF6]] +// CHECK32-NEXT: call void @llvm.assume(i1 true) [ "align"(i8 addrspace(200)* [[ALIGNED_RESULT7]], i32 [[ALIGN]]) ] +// CHECK32-NEXT: call void @use_cap(i8 addrspace(200)* noundef [[ALIGNED_RESULT7]]) +// CHECK32-NEXT: [[MASK8:%.*]] = sub i32 [[ALIGN]], 1 +// CHECK32-NEXT: [[PTRADDR9:%.*]] = call i32 @llvm.cheri.cap.address.get.i32(i8 addrspace(200)* [[CAP]]) +// CHECK32-NEXT: [[SET_BITS:%.*]] = and i32 [[PTRADDR9]], [[MASK8]] +// CHECK32-NEXT: [[IS_ALIGNED:%.*]] = icmp eq i32 [[SET_BITS]], 0 +// CHECK32-NEXT: call void @use_bool(i1 noundef zeroext [[IS_ALIGNED]]) +// CHECK32-NEXT: ret void +// void test_alignment_builtins(void *__capability cap, __SIZE_TYPE__ align) { use_cap(cheri_align_up(cap, align)); use_cap(cheri_align_down(cap, align));