Skip to content

Commit 3b13e4a

Browse files
committed
[CHERIoT] Add __builtin_cheriot_sealing_type clang built-in
1 parent 592752f commit 3b13e4a

File tree

12 files changed

+454
-58
lines changed

12 files changed

+454
-58
lines changed

cheriot-sealing-type-builtin.ll

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
; ModuleID = 'clang/test/CodeGen/cheri/riscv/cheriot-sealing-type-builtin.c'
2+
source_filename = "clang/test/CodeGen/cheri/riscv/cheriot-sealing-type-builtin.c"
3+
target datalayout = "e-m:e-p:32:32-i64:64-n32-S128-pf200:64:64:64:32-A200-P200-G200"
4+
target triple = "riscv32cheriot-unknown-unknown"
5+
6+
%struct.OpaqueSealingKeyType = type opaque
7+
8+
@__import.sealing_type.static_sealing_test.StructSealingKey = external addrspace(200) constant %struct.OpaqueSealingKeyType #0
9+
@__import.sealing_type.static_sealing_test.EnumSealingKey = external addrspace(200) constant %struct.OpaqueSealingKeyType #1
10+
@__import.sealing_type.static_sealing_test.TypeDefSealingKey = external addrspace(200) constant %struct.OpaqueSealingKeyType #2
11+
@__import.sealing_type.static_sealing_test.int = external addrspace(200) constant %struct.OpaqueSealingKeyType #3
12+
13+
; Function Attrs: noinline nounwind optnone
14+
define dso_local void @func() addrspace(200) #4 {
15+
%1 = alloca ptr addrspace(200), align 8, addrspace(200)
16+
%2 = alloca ptr addrspace(200), align 8, addrspace(200)
17+
%3 = alloca ptr addrspace(200), align 8, addrspace(200)
18+
%4 = alloca ptr addrspace(200), align 8, addrspace(200)
19+
%5 = alloca ptr addrspace(200), align 8, addrspace(200)
20+
%6 = alloca ptr addrspace(200), align 8, addrspace(200)
21+
%7 = alloca ptr addrspace(200), align 8, addrspace(200)
22+
store ptr addrspace(200) @__import.sealing_type.static_sealing_test.StructSealingKey, ptr addrspace(200) %1, align 8
23+
store ptr addrspace(200) @__import.sealing_type.static_sealing_test.EnumSealingKey, ptr addrspace(200) %2, align 8
24+
store ptr addrspace(200) @__import.sealing_type.static_sealing_test.TypeDefSealingKey, ptr addrspace(200) %3, align 8
25+
store ptr addrspace(200) @__import.sealing_type.static_sealing_test.int, ptr addrspace(200) %4, align 8
26+
store ptr addrspace(200) @__import.sealing_type.static_sealing_test.int, ptr addrspace(200) %5, align 8
27+
store ptr addrspace(200) @__import.sealing_type.static_sealing_test.int, ptr addrspace(200) %6, align 8
28+
store ptr addrspace(200) @__import.sealing_type.static_sealing_test.int, ptr addrspace(200) %7, align 8
29+
ret void
30+
}
31+
32+
attributes #0 = { "cheri-compartment"="static_sealing_test" "cheriot_sealing_key"="sealing_type.static_sealing_test.StructSealingKey" }
33+
attributes #1 = { "cheri-compartment"="static_sealing_test" "cheriot_sealing_key"="sealing_type.static_sealing_test.EnumSealingKey" }
34+
attributes #2 = { "cheri-compartment"="static_sealing_test" "cheriot_sealing_key"="sealing_type.static_sealing_test.TypeDefSealingKey" }
35+
attributes #3 = { "cheri-compartment"="static_sealing_test" "cheriot_sealing_key"="sealing_type.static_sealing_test.int" }
36+
attributes #4 = { noinline nounwind optnone "cheri-compartment"="static_sealing_test" "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="cheriot" "target-features"="+32bit,+c,+cap-mode,+e,+m,+relax,+xcheri,+zmmul,-a,-b,-d,-experimental-sdext,-experimental-sdtrig,-experimental-smctr,-experimental-ssctr,-experimental-svukte,-experimental-xqcia,-experimental-xqciac,-experimental-xqcicli,-experimental-xqcicm,-experimental-xqcics,-experimental-xqcicsr,-experimental-xqciint,-experimental-xqcilo,-experimental-xqcilsm,-experimental-xqcisls,-experimental-zalasr,-experimental-zicfilp,-experimental-zicfiss,-experimental-zvbc32e,-experimental-zvkgs,-f,-h,-i,-sha,-shcounterenw,-shgatpa,-shtvala,-shvsatpa,-shvstvala,-shvstvecd,-smaia,-smcdeleg,-smcsrind,-smdbltrp,-smepmp,-smmpm,-smnpm,-smrnmi,-smstateen,-ssaia,-ssccfg,-ssccptr,-sscofpmf,-sscounterenw,-sscsrind,-ssdbltrp,-ssnpm,-sspm,-ssqosid,-ssstateen,-ssstrict,-sstc,-sstvala,-sstvecd,-ssu64xl,-supm,-svade,-svadu,-svbare,-svinval,-svnapot,-svpbmt,-svvptc,-v,-xcheriot,-xcvalu,-xcvbi,-xcvbitmanip,-xcvelw,-xcvmac,-xcvmem,-xcvsimd,-xmipscmove,-xmipslsp,-xsfcease,-xsfvcp,-xsfvfnrclipxfqf,-xsfvfwmaccqqq,-xsfvqmaccdod,-xsfvqmaccqoq,-xsifivecdiscarddlone,-xsifivecflushdlone,-xtheadba,-xtheadbb,-xtheadbs,-xtheadcmo,-xtheadcondmov,-xtheadfmemidx,-xtheadmac,-xtheadmemidx,-xtheadmempair,-xtheadsync,-xtheadvdot,-xventanacondops,-xwchc,-za128rs,-za64rs,-zaamo,-zabha,-zacas,-zalrsc,-zama16b,-zawrs,-zba,-zbb,-zbc,-zbkb,-zbkc,-zbkx,-zbs,-zca,-zcb,-zcd,-zce,-zcf,-zcmop,-zcmp,-zcmt,-zdinx,-zfa,-zfbfmin,-zfh,-zfhmin,-zfinx,-zhinx,-zhinxmin,-zic64b,-zicbom,-zicbop,-zicboz,-ziccamoa,-ziccif,-zicclsm,-ziccrse,-zicntr,-zicond,-zicsr,-zifencei,-zihintntl,-zihintpause,-zihpm,-zimop,-zk,-zkn,-zknd,-zkne,-zknh,-zkr,-zks,-zksed,-zksh,-zkt,-ztso,-zvbb,-zvbc,-zve32f,-zve32x,-zve64d,-zve64f,-zve64x,-zvfbfmin,-zvfbfwma,-zvfh,-zvfhmin,-zvkb,-zvkg,-zvkn,-zvknc,-zvkned,-zvkng,-zvknha,-zvknhb,-zvks,-zvksc,-zvksed,-zvksg,-zvksh,-zvkt,-zvl1024b,-zvl128b,-zvl16384b,-zvl2048b,-zvl256b,-zvl32768b,-zvl32b,-zvl4096b,-zvl512b,-zvl64b,-zvl65536b,-zvl8192b" }
37+
38+
!llvm.module.flags = !{!0, !1, !2, !4, !5}
39+
!llvm.ident = !{!6}
40+
41+
!0 = !{i32 1, !"wchar_size", i32 4}
42+
!1 = !{i32 1, !"target-abi", !"cheriot-baremetal"}
43+
!2 = !{i32 6, !"riscv-isa", !3}
44+
!3 = !{!"rv32e2p0_m2p0_c2p0_zmmul1p0_xcheri0p0"}
45+
!4 = !{i32 7, !"frame-pointer", i32 2}
46+
!5 = !{i32 8, !"SmallDataLimit", i32 0}
47+
!6 = !{!"clang version 20.1.3 (https://github.com/xdoardo/llvm-project 592752fee8b25c925a65fb40eeb8a496f1b0ee2c)"}

clang/include/clang/Basic/Builtins.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4648,6 +4648,12 @@ def CheriConditionalSeal : Builtin {
46484648
let Prototype = "void* __capability(void const* __capability,void const* __capability)";
46494649
}
46504650

4651+
def CHERIoTEmitSealingType : Builtin {
4652+
let Spellings = ["__builtin_cheriot_sealing_type"];
4653+
let Attributes = [NoThrow, Const, CustomTypeChecking];
4654+
let Prototype = "void*(char const*)";
4655+
}
4656+
46514657
// Safestack builtins.
46524658
def GetUnsafeStackStart : Builtin {
46534659
let Spellings = ["__builtin___get_unsafe_stack_start"];

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ def err_cheriot_non_addr_of_expr_on_sealed
155155
"the only valid operation on a sealed value is to take its address">;
156156
def err_cheriot_invalid_sealed_declaration
157157
: Error<"cannot declare a sealed variable as %0">;
158+
def err_cheriot_invalid_sealing_key_type_name
159+
: Error<"the sealing key type name '%0' is not a valid identifier">;
158160

159161
// C99 variable-length arrays
160162
def ext_vla : Extension<"variable length arrays are a C99 feature">,

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6155,6 +6155,44 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
61556155
return RValue::get(Builder.CreateIntrinsic(
61566156
llvm::Intrinsic::cheri_cap_perms_check, {SizeTy}, {Cap, Perms}));
61576157
}
6158+
case Builtin::BI__builtin_cheriot_sealing_type: {
6159+
const auto *ArgLit = dyn_cast<StringLiteral>(E->getArg(0));
6160+
assert(ArgLit && "Argument to built-in should be a string literal!");
6161+
auto SealingTypeName = ArgLit->getString().str();
6162+
SealingTypeName.erase(
6163+
std::remove_if(SealingTypeName.begin(), SealingTypeName.end(), isspace),
6164+
SealingTypeName.end());
6165+
6166+
auto CompartmentName = getLangOpts().CheriCompartmentName;
6167+
auto PrefixedImportName =
6168+
CHERIoTSealingKeyTypeAttr::getSealingTypeSymbolName(CompartmentName,
6169+
SealingTypeName);
6170+
auto *Mod = &CGM.getModule();
6171+
auto MangledImportName = "__import." + PrefixedImportName;
6172+
auto *GV = Mod->getGlobalVariable(MangledImportName);
6173+
6174+
if (!GV) {
6175+
// This global exists only so that we have a pointer to it and is more
6176+
// akin to a GOT entry than a "real" global value: it just
6177+
// represents a pointer that we have a way of getting.
6178+
6179+
auto *OpaqueTypeName = "struct.OpaqueSealingKeyType";
6180+
llvm::StructType *OpaqueType =
6181+
llvm::StructType::getTypeByName(CGM.getLLVMContext(), OpaqueTypeName);
6182+
if (!OpaqueType)
6183+
OpaqueType = llvm::StructType::create(CGM.getModule().getContext(),
6184+
OpaqueTypeName);
6185+
6186+
GV = new GlobalVariable(CGM.getModule(), OpaqueType, true,
6187+
GlobalValue::ExternalLinkage, nullptr,
6188+
MangledImportName);
6189+
GV->addAttribute(CHERIoTSealingKeyTypeAttr::getAttrName(),
6190+
PrefixedImportName);
6191+
GV->addAttribute("cheri-compartment", CompartmentName);
6192+
}
6193+
6194+
return RValue::get(GV);
6195+
}
61586196
// Round to capability precision:
61596197
// TODO: should we handle targets that don't have any precision constraints
61606198
// here or in the backend?

clang/lib/Sema/SemaChecking.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2920,6 +2920,24 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
29202920
return ExprError();
29212921
break;
29222922

2923+
case Builtin::BI__builtin_cheriot_sealing_type: {
2924+
if (checkArgCount(TheCall, 1))
2925+
return ExprError();
2926+
auto *Arg = dyn_cast<StringLiteral>(TheCall->getArg(0));
2927+
if (!Arg)
2928+
return ExprError();
2929+
auto ArgLit = Arg->getString();
2930+
if (!isValidAsciiIdentifier(ArgLit)) {
2931+
std::string Escaped;
2932+
llvm::raw_string_ostream OS(Escaped);
2933+
llvm::printEscapedString(ArgLit, OS);
2934+
OS.flush();
2935+
Diag(Arg->getExprLoc(), diag::err_cheriot_invalid_sealing_key_type_name)
2936+
<< Escaped;
2937+
return ExprError();
2938+
}
2939+
break;
2940+
}
29232941
// OpenCL v2.0, s6.13.16 - Pipe functions
29242942
case Builtin::BIread_pipe:
29252943
case Builtin::BIwrite_pipe:
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// RUN: %clang_cc1 %s -o - "-triple" "riscv32cheriot-unknown-unknown-cheriotrtos" "-emit-llvm" "-cheri-compartment=static_sealing_test" "-mframe-pointer=none" "-mcmodel=small" "-target-abi" "cheriot" "-O0" "-Werror" -std=c2x | FileCheck %s
2+
3+
4+
struct StructSealingKey { };
5+
enum EnumSealingKey { SEALING_KEY_KIND1, SEALING_KEY_KIND2 };
6+
typedef enum EnumSealingKey TypeDefSealingKey;
7+
8+
// CHECK: %struct.OpaqueSealingKeyType = type opaque
9+
// CHECK: @__import.sealing_type.static_sealing_test.StructSealingKey = external addrspace(200) constant %struct.OpaqueSealingKeyType #0
10+
// CHECK: @__import.sealing_type.static_sealing_test.EnumSealingKey = external addrspace(200) constant %struct.OpaqueSealingKeyType #1
11+
// CHECK: @__import.sealing_type.static_sealing_test.TypeDefSealingKey = external addrspace(200) constant %struct.OpaqueSealingKeyType #2
12+
// CHECK: @__import.sealing_type.static_sealing_test.int = external addrspace(200) constant %struct.OpaqueSealingKeyType #3
13+
14+
// CHECK: define dso_local void @func() addrspace(200) #4 {
15+
void func() {
16+
17+
// CHECK: entry:
18+
// CHECK: %SealingKey1 = alloca ptr addrspace(200), align 8, addrspace(200)
19+
// CHECK: %SealingKey2 = alloca ptr addrspace(200), align 8, addrspace(200)
20+
// CHECK: %SealingKey3 = alloca ptr addrspace(200), align 8, addrspace(200)
21+
// CHECK: %SealingKey4 = alloca ptr addrspace(200), align 8, addrspace(200)
22+
// CHECK: %SealingKey5 = alloca ptr addrspace(200), align 8, addrspace(200)
23+
// CHECK: %SealingKey6 = alloca ptr addrspace(200), align 8, addrspace(200)
24+
// CHECK: %SealingKey7 = alloca ptr addrspace(200), align 8, addrspace(200)
25+
26+
// CHECK: store ptr addrspace(200) @__import.sealing_type.static_sealing_test.StructSealingKey, ptr addrspace(200) %SealingKey1, align 8
27+
struct StructSealingKey *SealingKey1 = __builtin_cheriot_sealing_type("StructSealingKey");
28+
29+
// CHECK: store ptr addrspace(200) @__import.sealing_type.static_sealing_test.EnumSealingKey, ptr addrspace(200) %SealingKey2, align 8
30+
enum EnumSealingKey *SealingKey2 = __builtin_cheriot_sealing_type("EnumSealingKey");
31+
32+
// CHECK: store ptr addrspace(200) @__import.sealing_type.static_sealing_test.TypeDefSealingKey, ptr addrspace(200) %SealingKey3, align 8
33+
TypeDefSealingKey *SealingKey3 = __builtin_cheriot_sealing_type("TypeDefSealingKey");
34+
35+
// CHECK: store ptr addrspace(200) @__import.sealing_type.static_sealing_test.int, ptr addrspace(200) %SealingKey4, align 8
36+
int *SealingKey4 = __builtin_cheriot_sealing_type("int");
37+
38+
// CHECK: store ptr addrspace(200) @__import.sealing_type.static_sealing_test.int, ptr addrspace(200) %SealingKey5, align 8
39+
int *SealingKey5 = __builtin_cheriot_sealing_type("int");
40+
// CHECK: store ptr addrspace(200) @__import.sealing_type.static_sealing_test.int, ptr addrspace(200) %SealingKey6, align 8
41+
int *SealingKey6 = __builtin_cheriot_sealing_type("int");
42+
// CHECK: store ptr addrspace(200) @__import.sealing_type.static_sealing_test.int, ptr addrspace(200) %SealingKey7, align 8
43+
int *SealingKey7 = __builtin_cheriot_sealing_type("int");
44+
45+
// CHECK: ret void
46+
}
47+
48+
// CHECK: attributes #0 = { "cheri-compartment"="static_sealing_test" "cheriot_sealing_key"="sealing_type.static_sealing_test.StructSealingKey" }
49+
// CHECK: attributes #1 = { "cheri-compartment"="static_sealing_test" "cheriot_sealing_key"="sealing_type.static_sealing_test.EnumSealingKey" }
50+
// CHECK: attributes #2 = { "cheri-compartment"="static_sealing_test" "cheriot_sealing_key"="sealing_type.static_sealing_test.TypeDefSealingKey" }
51+
// CHECK: attributes #3 = { "cheri-compartment"="static_sealing_test" "cheriot_sealing_key"="sealing_type.static_sealing_test.int" }
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %riscv32_cheri_cc1 "-triple" "riscv32cheriot-unknown-unknown" "-target-abi" "cheriot" -verify %s
2+
3+
void func() {
4+
int *k1 = __builtin_cheriot_sealing_type(MySealingType); // expected-error{{use of undeclared identifier 'MySealingType'}}
5+
int *k2 = __builtin_cheriot_sealing_type("This is my key"); // expected-error{{the sealing key type name 'This is my key' is not a valid identifier}}
6+
int *k3 = __builtin_cheriot_sealing_type("αβγδ"); // expected-error{{the sealing key type name '\CE\B1\CE\B2\CE\B3\CE\B4' is not a valid identifier}}
7+
int *k4 = __builtin_cheriot_sealing_type("a\0b"); // expected-error{{the sealing key type name 'a\00b' is not a valid identifier}}
8+
int *k5 = __builtin_cheriot_sealing_type("a\"b"); // expected-error{{the sealing key type name 'a\22b' is not a valid identifier}}
9+
int *k6 = __builtin_cheriot_sealing_type("a\nb"); // expected-error{{the sealing key type name 'a\0Ab' is not a valid identifier}}
10+
int *k7 = __builtin_cheriot_sealing_type("a\bb"); // expected-error{{the sealing key type name 'a\08b' is not a valid identifier}}
11+
}

llvm/include/llvm/IR/Attributes.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,6 +1612,23 @@ class CHERIoTSealedValueAttr {
16121612
/// Get the name of the attribute.
16131613
static const std::string getAttrName() { return "cheriot_sealed_value"; }
16141614
};
1615+
1616+
/// Represents the LLVM-level attribute that is used to signal
1617+
/// that a global (variable) represents a sealing key type.
1618+
class CHERIoTSealingKeyTypeAttr {
1619+
public:
1620+
/// Get the name of the attribute.
1621+
static const std::string getAttrName() { return "cheriot_sealing_key"; }
1622+
1623+
/// Get the mangled name of the symbol representing the sealing key.
1624+
static const std::string
1625+
getSealingTypeSymbolName(StringRef CompartmentName,
1626+
StringRef SealingKeyTypeName) {
1627+
return "sealing_type." + CompartmentName.str() + "." +
1628+
SealingKeyTypeName.str();
1629+
}
1630+
};
1631+
16151632
} // end namespace llvm
16161633

16171634
#endif // LLVM_IR_ATTRIBUTES_H

0 commit comments

Comments
 (0)