Skip to content
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
13 changes: 9 additions & 4 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6026,10 +6026,15 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
return RValue::get(Builder.CreateIntToPtr(Ptr, ResultTy));
}

case Builtin::BI__builtin_cheri_address_get:
return RValue::get(
Builder.CreateIntrinsic(llvm::Intrinsic::cheri_cap_address_get,
{IntPtrTy}, {EmitScalarExpr(E->getArg(0))}));
case Builtin::BI__builtin_cheri_address_get: {
const auto *Arg = E->getArg(0);
auto *RArg = EmitScalarExpr(Arg);
if (Arg->getType()->isCHERISealedCapabilityType(getContext()))
RArg = Builder.CreateIntrinsic(llvm::Intrinsic::launder_alignment,
{UnqualPtrTy}, {RArg});
return RValue::get(Builder.CreateIntrinsic(
llvm::Intrinsic::cheri_cap_address_get, {IntPtrTy}, {RArg}));
}
case Builtin::BI__builtin_cheri_address_set: {
Value *Cap = EmitScalarExpr(E->getArg(0));
Value *Address = EmitScalarExpr(E->getArg(1));
Expand Down
18 changes: 16 additions & 2 deletions clang/test/CodeGen/cheri/riscv/cheriot-static-sealed-value-attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,32 @@ SealedInt Obj2 = 10;
// CHECK: @llvm.compiler.used = appending addrspace(200) global [2 x ptr addrspace(200)] [ptr addrspace(200) @Obj1, ptr addrspace(200) @Obj2], section "llvm.metadata"

void doSomething(struct SealedStructObj *__sealed_capability obj);
void doSomethingWithAddr(int addr);
void doSomething2(SealedInt *__sealed_capability obj);

// CHECK: ; Function Attrs: minsize nounwind optsize
// CHECK: define dso_local void @func() local_unnamed_addr addrspace(200) #1 {
void func() {
// CHECK: entry:
// CHECK: tail call void @doSomething(ptr addrspace(200) noundef nonnull @Obj1) #3
// CHECK: tail call void @doSomething(ptr addrspace(200) noundef nonnull @Obj1) #5
doSomething(&Obj1);

// CHECK: tail call void @doSomething2(ptr addrspace(200) noundef nonnull @Obj2) #3
// Verify that observing the address of a sealed global value is done through a call to the launder built-in, so that
// the KnownBits optimisation pass can't assume anything about the value of the pointer, specifically nothing about the alignment of the pointer.
// This is because the CHERIoT RTOS uses the lower bits of the address to store the permissions of the sealed capability, and KnownBits can in turn
// optimise away logical computations on lower parts of the address.

// CHECK: %0 = tail call ptr addrspace(200) @llvm.launder.alignment.p200(ptr addrspace(200) nonnull @Obj1)
// CHECK: %1 = tail call i32 @llvm.cheri.cap.address.get.i32(ptr addrspace(200) nonnull %0)
// CHECK: tail call void @doSomethingWithAddr(i32 noundef %1) #5
doSomethingWithAddr(__builtin_cheri_address_get(&Obj1));

// CHECK: tail call void @doSomething2(ptr addrspace(200) noundef nonnull @Obj2) #5
doSomething2(&Obj2);
}

// CHECK: declare void @doSomething(ptr addrspace(200) noundef) local_unnamed_addr addrspace(200) #2
// CHECK: declare void @doSomethingWithAddr(i32 noundef) local_unnamed_addr addrspace(200) #2
// CHECK: declare ptr addrspace(200) @llvm.launder.alignment.p200(ptr addrspace(200)) addrspace(200) #3
// CHECK: declare i32 @llvm.cheri.cap.address.get.i32(ptr addrspace(200)) addrspace(200) #4
// CHECK: declare void @doSomething2(ptr addrspace(200) noundef) local_unnamed_addr addrspace(200) #2
32 changes: 32 additions & 0 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26826,6 +26826,38 @@ Returns another pointer that aliases its argument but which has no associated
``invariant.group`` metadata.
It does not read any memory and can be speculated.

'``llvm.launder.alignment``' Intrinsic
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Syntax:
"""""""
This is an overloaded intrinsic. The returned pointer must belong to the same
address space as the argument.

::

declare ptr @llvm.launder.alignment.p0(ptr <ptr>)

Overview:
"""""""""

The '``llvm.launder.alignment``' intrinsic can be used when the informations
regarding the alignment of the type the argument points to must be removed, so
to block unwanted optimizations.


Arguments:
""""""""""

The ``llvm.launder.alignment`` takes only one argument, which is a pointer
to the memory.

Semantics:
""""""""""

Returns another pointer that aliases its argument but which has no associated
alignment metadata.
It does not read any memory and can be speculated.


.. _constrainedfp:
Expand Down
4 changes: 4 additions & 0 deletions llvm/include/llvm/IR/Intrinsics.td
Original file line number Diff line number Diff line change
Expand Up @@ -1699,6 +1699,10 @@ def int_strip_invariant_group : DefaultAttrsIntrinsic<[llvm_anyptr_ty],
[LLVMMatchType<0>],
[IntrSpeculatable, IntrNoMem]>;

def int_launder_alignment : DefaultAttrsIntrinsic<[llvm_anyptr_ty],
[LLVMMatchType<0>],
[IntrInaccessibleMemOnly, IntrSpeculatable]>;

//===------------------------ Stackmap Intrinsics -------------------------===//
//
def int_experimental_stackmap : DefaultAttrsIntrinsic<[],
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6757,6 +6757,7 @@ bool llvm::isIntrinsicReturningPointerAliasingArgumentWithoutCapturing(
// MustPreserveNullness (and, at time of writing, they are not), but we
// document this fact out of an abundance of caution.
case Intrinsic::amdgcn_make_buffer_rsrc:
case Intrinsic::launder_alignment:
return true;
case Intrinsic::ptrmask:
return !MustPreserveNullness;
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7463,6 +7463,7 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
case Intrinsic::annotation:
case Intrinsic::ptr_annotation:
case Intrinsic::launder_invariant_group:
case Intrinsic::launder_alignment:
case Intrinsic::strip_invariant_group:
// Drop the intrinsic, but forward the value
setValue(&I, getValue(I.getOperand(0)));
Expand Down