Skip to content

Commit 8302242

Browse files
committed
[CHERIoT]: Add cheriot_sealing_type clang built-in
1 parent 592752f commit 8302242

File tree

10 files changed

+375
-58
lines changed

10 files changed

+375
-58
lines changed

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, Constexpr];
4654+
let Prototype = "void*(...)";
4655+
}
4656+
46514657
// Safestack builtins.
46524658
def GetUnsafeStackStart : Builtin {
46534659
let Spellings = ["__builtin___get_unsafe_stack_start"];

clang/include/clang/Basic/TokenKinds.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ KEYWORD(__cheri_input , KEYALL)
356356

357357
// CHERIoT Predefine Expr
358358
KEYWORD(__cheriot_minimum_stack__ , KEYALL)
359+
KEYWORD(__builtin_cheriot_sealing_type , KEYALL)
359360

360361
// Cheriot Qualifiers
361362
KEYWORD(__sealed_capability , KEYALL)

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6155,6 +6155,51 @@ 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 Expr *Callee = E->getCallee();
6160+
Callee = Callee->IgnoreImplicit();
6161+
6162+
const auto *DeclRef = dyn_cast<DeclRefExpr>(Callee);
6163+
assert(DeclRef && "DeclRef to built-in callee can't be null!");
6164+
assert(DeclRef->getTemplateArgs() &&
6165+
"template type in built-in callee can't be null!");
6166+
6167+
const auto SealingType =
6168+
DeclRef->getTemplateArgs()->getArgument().getAsType();
6169+
auto CompartmentName = getLangOpts().CheriCompartmentName;
6170+
6171+
clang::PrintingPolicy policy(getLangOpts());
6172+
policy.SuppressTagKeyword = true;
6173+
policy.SuppressElaboration = true;
6174+
policy.SuppressCapabilityQualifier = true;
6175+
6176+
std::string SealingTypeName = SealingType.getAsString(policy);
6177+
SealingTypeName.erase(
6178+
std::remove_if(SealingTypeName.begin(), SealingTypeName.end(), isspace),
6179+
SealingTypeName.end());
6180+
6181+
auto PrefixedImportName =
6182+
CHERIoTSealingKeyTypeAttr::getSealingTypeSymbolName(CompartmentName,
6183+
SealingTypeName);
6184+
auto *Mod = &CGM.getModule();
6185+
auto MangledImportName = "__import." + PrefixedImportName;
6186+
auto *GV = Mod->getGlobalVariable(MangledImportName);
6187+
6188+
if (!GV) {
6189+
// llvm::StructType* opaqueType =
6190+
// llvm::StructType::create(CGM.getModule().getContext(), "");
6191+
auto *opaquePtrType =
6192+
llvm::PointerType::getUnqual(CGM.getModule().getContext());
6193+
GV = new GlobalVariable(CGM.getModule(), opaquePtrType, true,
6194+
GlobalValue::ExternalLinkage, nullptr,
6195+
MangledImportName);
6196+
GV->addAttribute(CHERIoTSealingKeyTypeAttr::getAttrName(),
6197+
PrefixedImportName);
6198+
GV->addAttribute("cheri-compartment", CompartmentName);
6199+
}
6200+
6201+
return RValue::get(GV);
6202+
}
61586203
// Round to capability precision:
61596204
// TODO: should we handle targets that don't have any precision constraints
61606205
// here or in the backend?

clang/lib/Parse/ParseExpr.cpp

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,6 +1201,67 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind,
12011201
return ParseCastExpression(ParseKind, isAddressOfOperand, isTypeCast,
12021202
isVectorLiteral, NotPrimaryExpression);
12031203

1204+
case tok::kw___builtin_cheriot_sealing_type: {
1205+
// We expect: `__builtin_cheriot_sealing_type<TYPENAME>()`.
1206+
auto KWLoc = Tok.getLocation();
1207+
ConsumeToken();
1208+
auto LAngleLoc = Tok.getLocation();
1209+
if (ExpectAndConsume(tok::less)) {
1210+
SkipUntil(tok::r_paren, StopAtSemi);
1211+
return ExprError();
1212+
}
1213+
1214+
auto TyArgLoc = Tok.getLocation();
1215+
TypeResult TyArg = ParseTypeName();
1216+
if (TyArg.isInvalid())
1217+
return ExprError();
1218+
1219+
TypeSourceInfo *SealingTypeInfo = nullptr;
1220+
QualType SealingType =
1221+
Actions.GetTypeFromParser(TyArg.get(), &SealingTypeInfo);
1222+
1223+
auto RAngleLoc = Tok.getLocation();
1224+
if (ExpectAndConsume(tok::greater)) {
1225+
SkipUntil(tok::r_paren, StopAtSemi);
1226+
return ExprError();
1227+
}
1228+
1229+
if (ExpectAndConsume(tok::l_paren)) {
1230+
SkipUntil(tok::r_paren, StopAtSemi);
1231+
return ExprError();
1232+
}
1233+
1234+
SourceLocation RParenLoc = Tok.getLocation();
1235+
if (ExpectAndConsume(tok::r_paren)) {
1236+
SkipUntil(tok::semi, StopAtSemi);
1237+
return ExprError();
1238+
}
1239+
1240+
auto *Ctxt = &Actions.getASTContext();
1241+
auto BuiltinID = clang::Builtin::BI__builtin_cheriot_sealing_type;
1242+
1243+
auto BuiltinName = Ctxt->BuiltinInfo.getName(BuiltinID);
1244+
IdentifierInfo *II = &Ctxt->Idents.get(BuiltinName);
1245+
LookupResult R(Actions, II, SourceLocation(), Sema::LookupOrdinaryName);
1246+
if (!Actions.LookupBuiltin(R)) {
1247+
return ExprError();
1248+
}
1249+
1250+
FunctionDecl *BuiltinDecl = dyn_cast<FunctionDecl>(R.getFoundDecl());
1251+
TemplateArgument Arg(SealingType);
1252+
TemplateArgumentListInfo TArgs(LAngleLoc, RAngleLoc);
1253+
1254+
TArgs.addArgument(TemplateArgumentLoc(
1255+
Arg, Ctxt->getTrivialTypeSourceInfo(SealingType, TyArgLoc)));
1256+
1257+
DeclRefExpr *FnRef = DeclRefExpr::Create(
1258+
*Ctxt, NestedNameSpecifierLoc(), SourceLocation(), BuiltinDecl, false,
1259+
KWLoc, BuiltinDecl->getType(), VK_LValue, R.getFoundDecl(), &TArgs);
1260+
1261+
return CallExpr::Create(*Ctxt, FnRef, {}, BuiltinDecl->getReturnType(),
1262+
clang::ExprValueKind::VK_PRValue, RParenLoc,
1263+
FPOptionsOverride());
1264+
}
12041265
case tok::identifier:
12051266
ParseIdentifier: { // primary-expression: identifier
12061267
// unqualified-id: identifier
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
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: @__import.sealing_type.static_sealing_test.StructSealingKey = external addrspace(200) constant ptr #0
9+
// CHECK: @__import.sealing_type.static_sealing_test.EnumSealingKey = external addrspace(200) constant ptr #1
10+
// CHECK: @__import.sealing_type.static_sealing_test.TypeDefSealingKey = external addrspace(200) constant ptr #2
11+
// CHECK: @__import.sealing_type.static_sealing_test.int = external addrspace(200) constant ptr #3
12+
// CHECK: @"__import.sealing_type.static_sealing_test.int*" = external addrspace(200) constant ptr #4
13+
14+
// CHECK: define dso_local void @func() addrspace(200) #5 {
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+
// CHECK: %SealingKey8 = alloca ptr addrspace(200), align 8, addrspace(200)
26+
27+
// CHECK: store ptr addrspace(200) @__import.sealing_type.static_sealing_test.StructSealingKey, ptr addrspace(200) %SealingKey1, align 8
28+
struct StructSealingKey *SealingKey1 = __builtin_cheriot_sealing_type<struct StructSealingKey>();
29+
30+
// CHECK: store ptr addrspace(200) @__import.sealing_type.static_sealing_test.EnumSealingKey, ptr addrspace(200) %SealingKey2, align 8
31+
enum EnumSealingKey *SealingKey2 = __builtin_cheriot_sealing_type<enum EnumSealingKey>();
32+
33+
// CHECK: store ptr addrspace(200) @__import.sealing_type.static_sealing_test.TypeDefSealingKey, ptr addrspace(200) %SealingKey3, align 8
34+
TypeDefSealingKey *SealingKey3 = __builtin_cheriot_sealing_type<TypeDefSealingKey>();
35+
36+
// CHECK: store ptr addrspace(200) @__import.sealing_type.static_sealing_test.int, ptr addrspace(200) %SealingKey4, align 8
37+
int *SealingKey4 = __builtin_cheriot_sealing_type<int>();
38+
39+
// CHECK: store ptr addrspace(200) @"__import.sealing_type.static_sealing_test.int*", ptr addrspace(200) %SealingKey5, align 8
40+
int **SealingKey5 = __builtin_cheriot_sealing_type<int*>();
41+
42+
// CHECK: store ptr addrspace(200) @__import.sealing_type.static_sealing_test.int, ptr addrspace(200) %SealingKey6, align 8
43+
int *SealingKey6 = __builtin_cheriot_sealing_type<int>();
44+
// CHECK: store ptr addrspace(200) @__import.sealing_type.static_sealing_test.int, ptr addrspace(200) %SealingKey7, align 8
45+
int *SealingKey7 = __builtin_cheriot_sealing_type<int>();
46+
// CHECK: store ptr addrspace(200) @__import.sealing_type.static_sealing_test.int, ptr addrspace(200) %SealingKey8, align 8
47+
int *SealingKey8 = __builtin_cheriot_sealing_type<int>();
48+
49+
// CHECK: ret void
50+
}
51+
52+
// CHECK: attributes #0 = { "cheri-compartment"="static_sealing_test" "cheriot_sealing_key"="sealing_type.static_sealing_test.StructSealingKey" }
53+
// CHECK: attributes #1 = { "cheri-compartment"="static_sealing_test" "cheriot_sealing_key"="sealing_type.static_sealing_test.EnumSealingKey" }
54+
// CHECK: attributes #2 = { "cheri-compartment"="static_sealing_test" "cheriot_sealing_key"="sealing_type.static_sealing_test.TypeDefSealingKey" }
55+
// CHECK: attributes #3 = { "cheri-compartment"="static_sealing_test" "cheriot_sealing_key"="sealing_type.static_sealing_test.int" }
56+
// CHECK: attributes #4 = { "cheri-compartment"="static_sealing_test" "cheriot_sealing_key"="sealing_type.static_sealing_test.int*" }

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)