Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CHERI] Fix issue where tag_get was being CSE'd across free calls. #70

Merged
merged 1 commit into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/include/clang/Basic/Builtins.def
Original file line number Diff line number Diff line change
Expand Up @@ -1705,6 +1705,7 @@ BUILTIN(__builtin_cheri_sealed_get, "bvC*m", "nct")
BUILTIN(__builtin_cheri_subset_test, "bvC*mvC*m", "nct")
BUILTIN(__builtin_cheri_tag_clear, "v*mvC*m", "nct")
BUILTIN(__builtin_cheri_tag_get, "bvC*m", "nct")
BUILTIN(__builtin_cheri_tag_get_temporal, "bvC*m", "nct")
BUILTIN(__builtin_cheri_top_get, "zvC*m", "nct")
BUILTIN(__builtin_cheri_type_check, "vvC*mvC*m", "nct")
BUILTIN(__builtin_cheri_type_get, "YvC*m", "nct")
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Headers/cheri.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ __CHERI_GET(type, cheri_type_t, _get, 0)
__CHERI_ACCESSOR(perms, cheri_perms_t, _and, _get, 0)
__CHERI_ACCESSOR(flags, cheri_flags_t, _set, _get, 0)
__CHERI_GET(tag, __cheri_bool, _get, 0)
__CHERI_GET(tag, __cheri_bool, _get_temporal, 0)
__CHERI_GET(sealed, __cheri_bool, _get, 0)

static inline
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Headers/cheriintrin.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,11 @@
#define cheri_offset_set(x, y) __builtin_cheri_offset_set((x), (y))
#define cheri_tag_clear(x) __builtin_cheri_tag_clear(x)
#define cheri_tag_get(x) __builtin_cheri_tag_get(x)
#define cheri_tag_get_temporal(x) __builtin_cheri_tag_get_temporal(x)
#define cheri_is_valid(x) __builtin_cheri_tag_get(x)
#define cheri_is_valid_temporal(x) __builtin_cheri_tag_get_temporal(x)
#define cheri_is_invalid(x) (!__builtin_cheri_tag_get(x))
#define cheri_is_invalid_temporal(x) (!__builtin_cheri_tag_get_temporal(x))
#define cheri_is_equal_exact(x, y) __builtin_cheri_equal_exact((x), (y))
#define cheri_is_subset(x, y) __builtin_cheri_subset_test((x), (y))

Expand Down
1 change: 1 addition & 0 deletions clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2714,6 +2714,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
case Builtin::BI__builtin_cheri_perms_get:
case Builtin::BI__builtin_cheri_sealed_get:
case Builtin::BI__builtin_cheri_tag_get:
case Builtin::BI__builtin_cheri_tag_get_temporal:
case Builtin::BI__builtin_cheri_type_get: {
// The CHERI accessors should accept both capability pointer types and
// (u)intcap_t arguments.
Expand Down
3 changes: 3 additions & 0 deletions clang/test/CodeGen/cheri/cheri-builtin.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ long long test(void* __capability foo)
x &= __builtin_cheri_tag_get(foo);
// CHECK: call i1 @llvm.cheri.cap.tag.get
// ASM: cgettag ${{[0-9]+}}, $c{{[0-9]+}}
x &= __builtin_cheri_tag_get_temporal(foo);
// CHECK: call i1 @llvm.cheri.cap.tag.get
// ASM: cgettag ${{[0-9]+}}, $c{{[0-9]+}}
x &= __builtin_cheri_offset_get(foo);
// CHECK: call i64 @llvm.cheri.cap.offset.get.i64
// ASM: cgetoffset ${{[0-9]+}}, $c{{[0-9]+}}
Expand Down
5 changes: 4 additions & 1 deletion clang/test/CodeGen/cheri/cheri.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#define static
#define inline
#include <cheri.h>

// PTRS: define dso_local i32 @cheri_length_get(ptr nocapture noundef readnone
// PTRS: ret i32 -1
// PTRS: define dso_local i32 @cheri_base_get(ptr nocapture noundef readnone
Expand All @@ -26,6 +25,8 @@
// PTRS: ret ptr
// PTRS: define dso_local zeroext i1 @cheri_tag_get(ptr nocapture noundef readnone
// PTRS: ret i1 false
// PTRS: define dso_local zeroext i1 @cheri_tag_get_temporal(ptr nocapture noundef readnone
// PTRS: ret i1 false
// PTRS: define dso_local zeroext i1 @cheri_sealed_get(ptr nocapture noundef readnone
// PTRS: ret i1 false
// PTRS: define dso_local ptr @cheri_offset_increment(ptr noundef readnone{{( %.+)?}}, i32
Expand Down Expand Up @@ -70,6 +71,8 @@
// CAPS: call ptr addrspace(200) @llvm.cheri.cap.flags.set.i64(ptr addrspace(200){{( %.+)?}}, i64
// CAPS: define dso_local zeroext i1 @cheri_tag_get(ptr addrspace(200) noundef readnone
// CAPS: call i1 @llvm.cheri.cap.tag.get(ptr addrspace(200)
// CAPS: define dso_local zeroext i1 @cheri_tag_get_temporal(ptr addrspace(200) noundef readonly
// CAPS: call i1 @llvm.cheri.cap.tag.get.temporal(ptr addrspace(200)
// CAPS: define dso_local zeroext i1 @cheri_sealed_get(ptr addrspace(200) noundef readnone
// CAPS: call i1 @llvm.cheri.cap.sealed.get(ptr addrspace(200)
// CAPS: define dso_local ptr addrspace(200) @cheri_offset_increment(ptr addrspace(200) noundef readnone{{( %.+)?}}, i64 noundef signext
Expand Down
31 changes: 30 additions & 1 deletion clang/test/CodeGen/cheri/overloaded-builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ typedef _Bool bool;
size_t result26 = __builtin_cheri_high_get(x); \
T result27 = __builtin_cheri_high_set(x, 1); \
__builtin_cheri_perms_check(x, 1); \
__builtin_cheri_type_check(x, x2);
__builtin_cheri_type_check(x, x2); \
bool result28 = __builtin_cheri_tag_get_temporal(x);

// PURECAP-LABEL: define {{[^@]+}}@test_void_ptr
// PURECAP-SAME: (ptr addrspace(200) noundef [[ARG:%.*]], ptr addrspace(200) noundef [[ARG2:%.*]]) addrspace(200) #[[ATTR0:[0-9]+]] {
Expand Down Expand Up @@ -73,6 +74,8 @@ typedef _Bool bool;
// PURECAP-NEXT: [[TMP25:%.*]] = call ptr addrspace(200) @llvm.cheri.cap.high.set.i64(ptr addrspace(200) [[ARG]], i64 1)
// PURECAP-NEXT: call void @llvm.cheri.cap.perms.check.i64(ptr addrspace(200) [[ARG]], i64 1)
// PURECAP-NEXT: call void @llvm.cheri.cap.type.check(ptr addrspace(200) [[ARG]], ptr addrspace(200) [[ARG2]])
// PURECAP-NEXT: [[TMP26:%.*]] = call i1 @llvm.cheri.cap.tag.get.temporal(ptr addrspace(200) [[ARG]])
// PURECAP-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[TMP26]] to i8
// PURECAP-NEXT: ret void
//
// HYBRID-LABEL: define {{[^@]+}}@test_void_ptr
Expand Down Expand Up @@ -111,6 +114,8 @@ typedef _Bool bool;
// HYBRID-NEXT: [[TMP25:%.*]] = call ptr addrspace(200) @llvm.cheri.cap.high.set.i64(ptr addrspace(200) [[ARG]], i64 1)
// HYBRID-NEXT: call void @llvm.cheri.cap.perms.check.i64(ptr addrspace(200) [[ARG]], i64 1)
// HYBRID-NEXT: call void @llvm.cheri.cap.type.check(ptr addrspace(200) [[ARG]], ptr addrspace(200) [[ARG2]])
// HYBRID-NEXT: [[TMP26:%.*]] = call i1 @llvm.cheri.cap.tag.get.temporal(ptr addrspace(200) [[ARG]])
// HYBRID-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[TMP26]] to i8
// HYBRID-NEXT: ret void
//
void test_void_ptr(void *__capability arg, void *__capability arg2) {
Expand Down Expand Up @@ -153,6 +158,8 @@ void test_void_ptr(void *__capability arg, void *__capability arg2) {
// PURECAP-NEXT: [[TMP25:%.*]] = call ptr addrspace(200) @llvm.cheri.cap.high.set.i64(ptr addrspace(200) [[ARG]], i64 1)
// PURECAP-NEXT: call void @llvm.cheri.cap.perms.check.i64(ptr addrspace(200) [[ARG]], i64 1)
// PURECAP-NEXT: call void @llvm.cheri.cap.type.check(ptr addrspace(200) [[ARG]], ptr addrspace(200) [[ARG2]])
// PURECAP-NEXT: [[TMP26:%.*]] = call i1 @llvm.cheri.cap.tag.get.temporal(ptr addrspace(200) [[ARG]])
// PURECAP-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[TMP26]] to i8
// PURECAP-NEXT: ret void
//
// HYBRID-LABEL: define {{[^@]+}}@test_const_char_ptr
Expand Down Expand Up @@ -191,6 +198,8 @@ void test_void_ptr(void *__capability arg, void *__capability arg2) {
// HYBRID-NEXT: [[TMP25:%.*]] = call ptr addrspace(200) @llvm.cheri.cap.high.set.i64(ptr addrspace(200) [[ARG]], i64 1)
// HYBRID-NEXT: call void @llvm.cheri.cap.perms.check.i64(ptr addrspace(200) [[ARG]], i64 1)
// HYBRID-NEXT: call void @llvm.cheri.cap.type.check(ptr addrspace(200) [[ARG]], ptr addrspace(200) [[ARG2]])
// HYBRID-NEXT: [[TMP26:%.*]] = call i1 @llvm.cheri.cap.tag.get.temporal(ptr addrspace(200) [[ARG]])
// HYBRID-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[TMP26]] to i8
// HYBRID-NEXT: ret void
//
void test_const_char_ptr(const char *__capability arg, const char *__capability arg2) {
Expand Down Expand Up @@ -233,6 +242,8 @@ void test_const_char_ptr(const char *__capability arg, const char *__capability
// PURECAP-NEXT: [[TMP25:%.*]] = call ptr addrspace(200) @llvm.cheri.cap.high.set.i64(ptr addrspace(200) [[ARG]], i64 1)
// PURECAP-NEXT: call void @llvm.cheri.cap.perms.check.i64(ptr addrspace(200) [[ARG]], i64 1)
// PURECAP-NEXT: call void @llvm.cheri.cap.type.check(ptr addrspace(200) [[ARG]], ptr addrspace(200) [[ARG2]])
// PURECAP-NEXT: [[TMP26:%.*]] = call i1 @llvm.cheri.cap.tag.get.temporal(ptr addrspace(200) [[ARG]])
// PURECAP-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[TMP26]] to i8
// PURECAP-NEXT: ret void
//
// HYBRID-LABEL: define {{[^@]+}}@test_long_ptr
Expand Down Expand Up @@ -271,6 +282,8 @@ void test_const_char_ptr(const char *__capability arg, const char *__capability
// HYBRID-NEXT: [[TMP25:%.*]] = call ptr addrspace(200) @llvm.cheri.cap.high.set.i64(ptr addrspace(200) [[ARG]], i64 1)
// HYBRID-NEXT: call void @llvm.cheri.cap.perms.check.i64(ptr addrspace(200) [[ARG]], i64 1)
// HYBRID-NEXT: call void @llvm.cheri.cap.type.check(ptr addrspace(200) [[ARG]], ptr addrspace(200) [[ARG2]])
// HYBRID-NEXT: [[TMP26:%.*]] = call i1 @llvm.cheri.cap.tag.get.temporal(ptr addrspace(200) [[ARG]])
// HYBRID-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[TMP26]] to i8
// HYBRID-NEXT: ret void
//
void test_long_ptr(long *__capability arg, long *__capability arg2) {
Expand Down Expand Up @@ -313,6 +326,8 @@ void test_long_ptr(long *__capability arg, long *__capability arg2) {
// PURECAP-NEXT: [[TMP25:%.*]] = call ptr addrspace(200) @llvm.cheri.cap.high.set.i64(ptr addrspace(200) [[ARG]], i64 1)
// PURECAP-NEXT: call void @llvm.cheri.cap.perms.check.i64(ptr addrspace(200) [[ARG]], i64 1)
// PURECAP-NEXT: call void @llvm.cheri.cap.type.check(ptr addrspace(200) [[ARG]], ptr addrspace(200) [[ARG2]])
// PURECAP-NEXT: [[TMP26:%.*]] = call i1 @llvm.cheri.cap.tag.get.temporal(ptr addrspace(200) [[ARG]])
// PURECAP-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[TMP26]] to i8
// PURECAP-NEXT: ret void
//
// HYBRID-LABEL: define {{[^@]+}}@test_uintcap_t
Expand Down Expand Up @@ -351,6 +366,8 @@ void test_long_ptr(long *__capability arg, long *__capability arg2) {
// HYBRID-NEXT: [[TMP25:%.*]] = call ptr addrspace(200) @llvm.cheri.cap.high.set.i64(ptr addrspace(200) [[ARG]], i64 1)
// HYBRID-NEXT: call void @llvm.cheri.cap.perms.check.i64(ptr addrspace(200) [[ARG]], i64 1)
// HYBRID-NEXT: call void @llvm.cheri.cap.type.check(ptr addrspace(200) [[ARG]], ptr addrspace(200) [[ARG2]])
// HYBRID-NEXT: [[TMP26:%.*]] = call i1 @llvm.cheri.cap.tag.get.temporal(ptr addrspace(200) [[ARG]])
// HYBRID-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[TMP26]] to i8
// HYBRID-NEXT: ret void
//
void test_uintcap_t(__uintcap_t arg, __uintcap_t arg2) {
Expand Down Expand Up @@ -390,6 +407,8 @@ void test_uintcap_t(__uintcap_t arg, __uintcap_t arg2) {
// PURECAP-NEXT: [[TMP23:%.*]] = call ptr addrspace(200) @llvm.cheri.cap.high.set.i64(ptr addrspace(200) null, i64 1)
// PURECAP-NEXT: call void @llvm.cheri.cap.perms.check.i64(ptr addrspace(200) null, i64 1)
// PURECAP-NEXT: call void @llvm.cheri.cap.type.check(ptr addrspace(200) null, ptr addrspace(200) null)
// PURECAP-NEXT: [[TMP24:%.*]] = call i1 @llvm.cheri.cap.tag.get.temporal(ptr addrspace(200) null)
// PURECAP-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[TMP24]] to i8
// PURECAP-NEXT: ret void
//
// HYBRID-LABEL: define {{[^@]+}}@test_null_constant
Expand Down Expand Up @@ -425,6 +444,8 @@ void test_uintcap_t(__uintcap_t arg, __uintcap_t arg2) {
// HYBRID-NEXT: [[TMP23:%.*]] = call ptr addrspace(200) @llvm.cheri.cap.high.set.i64(ptr addrspace(200) null, i64 1)
// HYBRID-NEXT: call void @llvm.cheri.cap.perms.check.i64(ptr addrspace(200) null, i64 1)
// HYBRID-NEXT: call void @llvm.cheri.cap.type.check(ptr addrspace(200) null, ptr addrspace(200) null)
// HYBRID-NEXT: [[TMP24:%.*]] = call i1 @llvm.cheri.cap.tag.get.temporal(ptr addrspace(200) null)
// HYBRID-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[TMP24]] to i8
// HYBRID-NEXT: ret void
//
void test_null_constant(__uintcap_t arg) {
Expand Down Expand Up @@ -464,6 +485,8 @@ void test_null_constant(__uintcap_t arg) {
// PURECAP-NEXT: [[TMP23:%.*]] = call ptr addrspace(200) @llvm.cheri.cap.high.set.i64(ptr addrspace(200) null, i64 1)
// PURECAP-NEXT: call void @llvm.cheri.cap.perms.check.i64(ptr addrspace(200) null, i64 1)
// PURECAP-NEXT: call void @llvm.cheri.cap.type.check(ptr addrspace(200) null, ptr addrspace(200) null)
// PURECAP-NEXT: [[TMP24:%.*]] = call i1 @llvm.cheri.cap.tag.get.temporal(ptr addrspace(200) null)
// PURECAP-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[TMP24]] to i8
// PURECAP-NEXT: ret void
//
// HYBRID-LABEL: define {{[^@]+}}@test_null_int_ptr
Expand Down Expand Up @@ -499,6 +522,8 @@ void test_null_constant(__uintcap_t arg) {
// HYBRID-NEXT: [[TMP23:%.*]] = call ptr addrspace(200) @llvm.cheri.cap.high.set.i64(ptr addrspace(200) null, i64 1)
// HYBRID-NEXT: call void @llvm.cheri.cap.perms.check.i64(ptr addrspace(200) null, i64 1)
// HYBRID-NEXT: call void @llvm.cheri.cap.type.check(ptr addrspace(200) null, ptr addrspace(200) null)
// HYBRID-NEXT: [[TMP24:%.*]] = call i1 @llvm.cheri.cap.tag.get.temporal(ptr addrspace(200) null)
// HYBRID-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[TMP24]] to i8
// HYBRID-NEXT: ret void
//
void test_null_int_ptr(__uintcap_t arg) {
Expand Down Expand Up @@ -625,6 +650,8 @@ static char global_buffer2[32];
// PURECAP-NEXT: [[TMP25:%.*]] = call ptr addrspace(200) @llvm.cheri.cap.high.set.i64(ptr addrspace(200) @global_buffer, i64 1)
// PURECAP-NEXT: call void @llvm.cheri.cap.perms.check.i64(ptr addrspace(200) @global_buffer, i64 1)
// PURECAP-NEXT: call void @llvm.cheri.cap.type.check(ptr addrspace(200) @global_buffer, ptr addrspace(200) @global_buffer2)
// PURECAP-NEXT: [[TMP26:%.*]] = call i1 @llvm.cheri.cap.tag.get.temporal(ptr addrspace(200) @global_buffer)
// PURECAP-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[TMP26]] to i8
// PURECAP-NEXT: ret void
//
void test_array(void) {
Expand Down Expand Up @@ -668,6 +695,8 @@ typedef void (*__capability fnptr_t)(void);
// PURECAP-NEXT: [[TMP25:%.*]] = call ptr addrspace(200) @llvm.cheri.cap.high.set.i64(ptr addrspace(200) @test_function, i64 1)
// PURECAP-NEXT: call void @llvm.cheri.cap.perms.check.i64(ptr addrspace(200) @test_function, i64 1)
// PURECAP-NEXT: call void @llvm.cheri.cap.type.check(ptr addrspace(200) @test_function, ptr addrspace(200) @test_array)
// PURECAP-NEXT: [[TMP26:%.*]] = call i1 @llvm.cheri.cap.tag.get.temporal(ptr addrspace(200) @test_function)
// PURECAP-NEXT: [[FROMBOOL4:%.*]] = zext i1 [[TMP26]] to i8
// PURECAP-NEXT: ret void
//
void test_function(void) {
Expand Down
3 changes: 3 additions & 0 deletions clang/test/CodeGen/cheri/riscv/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ void standard(void * __capability cap) {
x = __builtin_cheri_tag_get(cap);
// RV32IXCHERI: call i1 @llvm.cheri.cap.tag.get
// RV64IXCHERI: call i1 @llvm.cheri.cap.tag.get
x = __builtin_cheri_tag_get_temporal(cap);
// RV32IXCHERI: call i1 @llvm.cheri.cap.tag.get.temporal
// RV64IXCHERI: call i1 @llvm.cheri.cap.tag.get.temporal
x = __builtin_cheri_offset_get(cap);
// RV32IXCHERI: call i32 @llvm.cheri.cap.offset.get.i32
// RV64IXCHERI: call i64 @llvm.cheri.cap.offset.get.i64
Expand Down
4 changes: 4 additions & 0 deletions clang/test/SemaCXX/cheri/polymorphic-builtins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ void test_good(Cap x) {
static_assert(__is_same(decltype(__builtin_cheri_subset_test(x, x)), bool), "");
static_assert(__is_same(decltype(__builtin_cheri_tag_clear(x)), T), "");
static_assert(__is_same(decltype(__builtin_cheri_tag_get(x)), bool), "");
static_assert(__is_same(decltype(__builtin_cheri_tag_get_temporal(x)), bool), "");
static_assert(__is_same(decltype(__builtin_cheri_type_get(x)), long), "");
static_assert(__is_same(decltype(__builtin_cheri_unseal(x, nullptr)), T), "");
static_assert(__is_same(decltype(__builtin_cheri_conditional_seal(x, nullptr)), T), "");
Expand Down Expand Up @@ -273,6 +274,7 @@ void test_bad() {
(void)__builtin_cheri_subset_test(x, x); // expected-error{{operand of type 'long' where capability is required}}
(void)__builtin_cheri_tag_clear(x); // expected-error{{operand of type 'long' where capability is required}}
(void)__builtin_cheri_tag_get(x); // expected-error{{operand of type 'long' where capability is required}}
(void)__builtin_cheri_tag_get_temporal(x); // expected-error{{operand of type 'long' where capability is required}}
(void)__builtin_cheri_type_get(x); // expected-error{{operand of type 'long' where capability is required}}
(void)__builtin_cheri_unseal(x, NULL); // expected-error{{operand of type 'long' where capability is required}}

Expand All @@ -297,6 +299,7 @@ void test_bad() {
(void)__builtin_cheri_subset_test(123, 123); // expected-error{{operand of type 'int' where capability is required}}
(void)__builtin_cheri_tag_clear(123); // expected-error{{operand of type 'int' where capability is required}}
(void)__builtin_cheri_tag_get(123); // expected-error{{operand of type 'int' where capability is required}}
(void)__builtin_cheri_tag_get_temporal(123); // expected-error{{operand of type 'int' where capability is required}}
(void)__builtin_cheri_type_get(123); // expected-error{{operand of type 'int' where capability is required}}
(void)__builtin_cheri_unseal(123, NULL); // expected-error{{operand of type 'int' where capability is required}}
// or floating-point ones
Expand All @@ -320,6 +323,7 @@ void test_bad() {
(void)__builtin_cheri_subset_test(1.0f, 1.0f); // expected-error{{operand of type 'float' where capability is required}}
(void)__builtin_cheri_tag_clear(1.0f); // expected-error{{operand of type 'float' where capability is required}}
(void)__builtin_cheri_tag_get(1.0f); // expected-error{{operand of type 'float' where capability is required}}
(void)__builtin_cheri_tag_get_temporal(1.0f); // expected-error{{operand of type 'float' where capability is required}}
(void)__builtin_cheri_type_get(1.0f); // expected-error{{operand of type 'float' where capability is required}}
(void)__builtin_cheri_unseal(1.0f, NULL); // expected-error{{operand of type 'float' where capability is required}}
}
5 changes: 5 additions & 0 deletions llvm/include/llvm/IR/IntrinsicsCHERICap.td
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ def int_cheri_cap_tag_get :
Intrinsic<[llvm_i1_ty],
[llvm_cap_ty],
[IntrNoMem, IntrWillReturn]>;
def int_cheri_cap_tag_get_temporal :
ClangBuiltin<"__builtin_cheri_tag_get_temporal">,
Intrinsic<[llvm_i1_ty],
[llvm_cap_ty],
[IntrReadMem, IntrWillReturn]>;
def int_cheri_cap_sealed_get :
ClangBuiltin<"__builtin_cheri_sealed_get">,
Intrinsic<[llvm_i1_ty],
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Analysis/InstructionSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6280,6 +6280,7 @@ static Value *simplifyUnaryIntrinsic(Function *F, Value *Op0,
return X;
break;
case Intrinsic::cheri_cap_tag_get:
case Intrinsic::cheri_cap_tag_get_temporal:
if (llvm::cheri::isKnownUntaggedCapability(Op0, &Q.DL))
return Constant::getNullValue(F->getReturnType());
break;
Expand Down
17 changes: 17 additions & 0 deletions llvm/lib/Target/Mips/MipsISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,7 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
if (Subtarget.isCheri()) {
// We also fold Incoffsets to andaddr if possible
setTargetDAGCombine(ISD::INTRINSIC_WO_CHAIN);
setTargetDAGCombine(ISD::INTRINSIC_W_CHAIN);
setTargetDAGCombine(ISD::PTRADD);
}

Expand Down Expand Up @@ -1484,6 +1485,22 @@ SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
return performCIncOffsetToCandAddrCombine(N, DAG, DCI, Subtarget);
case ISD::INTRINSIC_WO_CHAIN:
return performINTRINSIC_WO_CHAINCombine(N, DAG, DCI, Subtarget);
case ISD::INTRINSIC_W_CHAIN: {
unsigned IID = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
if (IID == Intrinsic::cheri_cap_tag_get_temporal) {
SDLoc DL(N);
EVT VT = Subtarget.isGP64bit() ? MVT::i64 : MVT::i32;
SDValue IntRes =
DAG.getNode(MipsISD::CapTagGet, DL, VT, N->getOperand(2));
IntRes = DAG.getNode(ISD::AssertZext, DL, VT, IntRes,
DAG.getValueType(MVT::i1));
IntRes = DAG.getSetCC(DL, MVT::i1, IntRes, DAG.getConstant(0, DL, VT),
ISD::SETNE);
DCI.CombineTo(N, {IntRes, N->getOperand(0)});
return SDValue();
}
break;
}
}

return SDValue();
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1367,6 +1367,12 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
return;
break;
}
case RISCVISD::CAP_TAG_GET: {
ReplaceNode(Node, CurDAG->getMachineNode(
RISCV::CGetTag, DL, Node->getVTList(),
{Node->getOperand(0), Node->getOperand(1)}));
return;
}
case ISD::INTRINSIC_WO_CHAIN: {
unsigned IntNo = Node->getConstantOperandVal(0);
switch (IntNo) {
Expand Down
Loading