Skip to content

Commit f2f792e

Browse files
committed
Modify LLVM wrapper to support CHERI tag options for memcpy and memmove
1 parent 6b00bc3 commit f2f792e

File tree

19 files changed

+110
-27
lines changed

19 files changed

+110
-27
lines changed

compiler/rustc_codegen_llvm/src/abi.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
242242
scratch_align,
243243
bx.const_usize(copy_bytes),
244244
MemFlags::empty(),
245+
rustc_codegen_ssa::common::PreserveCheriTags::Unknown,
245246
);
246247
bx.lifetime_end(llscratch, scratch_size);
247248
}

compiler/rustc_codegen_llvm/src/builder.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,9 +1111,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
11111111
src_align: Align,
11121112
size: &'ll Value,
11131113
flags: MemFlags,
1114+
preserve_tags: rustc_codegen_ssa::common::PreserveCheriTags,
11141115
) {
11151116
assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memcpy not supported");
11161117
let size = self.intcast(size, self.type_isize(), false);
1118+
let preserve_tags = llvm::PreserveCheriTags::from_generic(preserve_tags);
11171119
let is_volatile = flags.contains(MemFlags::VOLATILE);
11181120
unsafe {
11191121
llvm::LLVMRustBuildMemCpy(
@@ -1123,6 +1125,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
11231125
src,
11241126
src_align.bytes() as c_uint,
11251127
size,
1128+
preserve_tags,
11261129
is_volatile,
11271130
);
11281131
}
@@ -1136,9 +1139,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
11361139
src_align: Align,
11371140
size: &'ll Value,
11381141
flags: MemFlags,
1142+
preserve_tags: rustc_codegen_ssa::common::PreserveCheriTags,
11391143
) {
11401144
assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memmove not supported");
11411145
let size = self.intcast(size, self.type_isize(), false);
1146+
let preserve_tags = llvm::PreserveCheriTags::from_generic(preserve_tags);
11421147
let is_volatile = flags.contains(MemFlags::VOLATILE);
11431148
unsafe {
11441149
llvm::LLVMRustBuildMemMove(
@@ -1148,6 +1153,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
11481153
src,
11491154
src_align.bytes() as c_uint,
11501155
size,
1156+
preserve_tags,
11511157
is_volatile,
11521158
);
11531159
}

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,27 @@ pub(crate) enum MemoryEffects {
656656
InaccessibleMemOnly,
657657
}
658658

659+
/// LLVMRustPreserveCheriTags
660+
#[derive(Copy, Clone)]
661+
#[repr(C)]
662+
pub(crate) enum PreserveCheriTags {
663+
Unknown,
664+
Required,
665+
Unnecessary,
666+
}
667+
668+
impl PreserveCheriTags {
669+
pub(crate) fn from_generic(value: rustc_codegen_ssa::common::PreserveCheriTags) -> Self {
670+
match value {
671+
rustc_codegen_ssa::common::PreserveCheriTags::Unknown => PreserveCheriTags::Unknown,
672+
rustc_codegen_ssa::common::PreserveCheriTags::Required => PreserveCheriTags::Required,
673+
rustc_codegen_ssa::common::PreserveCheriTags::Unnecessary => {
674+
PreserveCheriTags::Unnecessary
675+
}
676+
}
677+
}
678+
}
679+
659680
/// LLVMOpcode
660681
#[derive(Copy, Clone, PartialEq, Eq)]
661682
#[repr(C)]
@@ -1896,6 +1917,7 @@ unsafe extern "C" {
18961917
Src: &'a Value,
18971918
SrcAlign: c_uint,
18981919
Size: &'a Value,
1920+
PreserveTags: PreserveCheriTags,
18991921
IsVolatile: bool,
19001922
) -> &'a Value;
19011923
pub(crate) fn LLVMRustBuildMemMove<'a>(
@@ -1905,6 +1927,7 @@ unsafe extern "C" {
19051927
Src: &'a Value,
19061928
SrcAlign: c_uint,
19071929
Size: &'a Value,
1930+
PreserveTags: PreserveCheriTags,
19081931
IsVolatile: bool,
19091932
) -> &'a Value;
19101933
pub(crate) fn LLVMRustBuildMemSet<'a>(

compiler/rustc_codegen_ssa/src/common.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ pub enum AtomicRmwBinOp {
5959
AtomicUMin,
6060
}
6161

62+
#[derive(Copy, Clone)]
63+
pub enum PreserveCheriTags {
64+
Unknown,
65+
Required,
66+
Unnecessary,
67+
}
68+
6269
#[derive(Copy, Clone, Debug)]
6370
pub enum AtomicOrdering {
6471
Unordered,

compiler/rustc_codegen_ssa/src/mir/block.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,6 +1589,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
15891589
align,
15901590
bx.const_usize(copy_bytes),
15911591
MemFlags::empty(),
1592+
common::PreserveCheriTags::Unknown,
15921593
);
15931594
// ...and then load it with the ABI type.
15941595
let cast_ty = bx.cast_backend_type(cast);

compiler/rustc_codegen_ssa/src/mir/intrinsic.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ fn copy_intrinsic<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
2727
let size = bx.mul(bx.const_usize(size.bytes()), count);
2828
let flags = if volatile { MemFlags::VOLATILE } else { MemFlags::empty() };
2929
if allow_overlap {
30-
bx.memmove(dst, align, src, align, size, flags);
30+
bx.memmove(dst, align, src, align, size, flags, crate::common::PreserveCheriTags::Unknown);
3131
} else {
32-
bx.memcpy(dst, align, src, align, size, flags);
32+
bx.memcpy(dst, align, src, align, size, flags, crate::common::PreserveCheriTags::Unknown);
3333
}
3434
}
3535

compiler/rustc_codegen_ssa/src/mir/operand.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -722,7 +722,15 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
722722
let neg_address = bx.neg(address);
723723
let offset = bx.and(neg_address, align_minus_1);
724724
let dst = bx.inbounds_ptradd(alloca, offset);
725-
bx.memcpy(dst, min_align, llptr, min_align, size, MemFlags::empty());
725+
bx.memcpy(
726+
dst,
727+
min_align,
728+
llptr,
729+
min_align,
730+
size,
731+
MemFlags::empty(),
732+
crate::common::PreserveCheriTags::Unknown,
733+
);
726734

727735
// Store the allocated region and the extra to the indirect place.
728736
let indirect_operand = OperandValue::Pair(dst, llextra);

compiler/rustc_codegen_ssa/src/mir/statement.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
8585
let align = pointee_layout.align;
8686
let dst = dst_val.immediate();
8787
let src = src_val.immediate();
88-
bx.memcpy(dst, align, src, align, bytes, crate::MemFlags::empty());
88+
bx.memcpy(
89+
dst,
90+
align,
91+
src,
92+
align,
93+
bytes,
94+
crate::MemFlags::empty(),
95+
crate::common::PreserveCheriTags::Unknown,
96+
);
8997
}
9098
mir::StatementKind::FakeRead(..)
9199
| mir::StatementKind::Retag { .. }

compiler/rustc_codegen_ssa/src/traits/builder.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ use super::type_::{ArgAbiBuilderMethods, BaseTypeCodegenMethods, LayoutTypeCodeg
2020
use super::{CodegenMethods, StaticBuilderMethods};
2121
use crate::MemFlags;
2222
use crate::common::{
23-
AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope, TypeKind,
23+
AtomicOrdering, AtomicRmwBinOp, AtomicRmwBinOp, IntPredicate, IntPredicate, PreserveCheriTags,
24+
RealPredicate, RealPredicate, SynchronizationScope, SynchronizationScope, TypeKind, TypeKind,
2425
};
2526
use crate::mir::operand::{OperandRef, OperandValue};
2627
use crate::mir::place::{PlaceRef, PlaceValue};
@@ -417,6 +418,7 @@ pub trait BuilderMethods<'a, 'tcx>:
417418
src_align: Align,
418419
size: Self::Value,
419420
flags: MemFlags,
421+
preserve_tags: PreserveCheriTags,
420422
);
421423
fn memmove(
422424
&mut self,
@@ -426,6 +428,7 @@ pub trait BuilderMethods<'a, 'tcx>:
426428
src_align: Align,
427429
size: Self::Value,
428430
flags: MemFlags,
431+
preserve_tags: PreserveCheriTags,
429432
);
430433
fn memset(
431434
&mut self,
@@ -473,7 +476,15 @@ pub trait BuilderMethods<'a, 'tcx>:
473476
temp.val.store_with_flags(self, dst.with_type(layout), flags);
474477
} else if !layout.is_zst() {
475478
let bytes = self.const_usize(layout.size.bytes());
476-
self.memcpy(dst.llval, dst.align, src.llval, src.align, bytes, flags);
479+
self.memcpy(
480+
dst.llval,
481+
dst.align,
482+
src.llval,
483+
src.align,
484+
bytes,
485+
flags,
486+
PreserveCheriTags::Unknown,
487+
);
477488
}
478489
}
479490

compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,23 +1591,41 @@ LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef, RustStringRef MessageOut,
15911591
return true;
15921592
}
15931593

1594-
extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst,
1595-
unsigned DstAlign, LLVMValueRef Src,
1596-
unsigned SrcAlign,
1597-
LLVMValueRef Size,
1598-
bool IsVolatile) {
1599-
return wrap(unwrap(B)->CreateMemCpy(unwrap(Dst), MaybeAlign(DstAlign),
1600-
unwrap(Src), MaybeAlign(SrcAlign),
1601-
unwrap(Size), IsVolatile));
1594+
enum class LLVMPreserveCheriTags {
1595+
Unknown,
1596+
Required,
1597+
Unnecessary,
1598+
};
1599+
1600+
static PreserveCheriTags fromRust(LLVMPreserveCheriTags PreserveTags) {
1601+
switch (PreserveTags) {
1602+
case LLVMPreserveCheriTags::Unknown:
1603+
return PreserveCheriTags::Unknown;
1604+
case LLVMPreserveCheriTags::Required:
1605+
return PreserveCheriTags::Required;
1606+
case LLVMPreserveCheriTags::Unnecessary:
1607+
return PreserveCheriTags::Unnecessary;
1608+
}
1609+
1610+
report_fatal_error("Invalid LLVMPreserveCheriTags value!");
1611+
}
1612+
1613+
extern "C" LLVMValueRef
1614+
LLVMRustBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign,
1615+
LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size,
1616+
LLVMPreserveCheriTags PreserveTags, bool IsVolatile) {
1617+
return wrap(unwrap(B)->CreateMemCpy(
1618+
unwrap(Dst), MaybeAlign(DstAlign), unwrap(Src), MaybeAlign(SrcAlign),
1619+
unwrap(Size), fromRust(PreserveTags), IsVolatile));
16021620
}
16031621

16041622
extern "C" LLVMValueRef
16051623
LLVMRustBuildMemMove(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign,
16061624
LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size,
1607-
bool IsVolatile) {
1608-
return wrap(unwrap(B)->CreateMemMove(unwrap(Dst), MaybeAlign(DstAlign),
1609-
unwrap(Src), MaybeAlign(SrcAlign),
1610-
unwrap(Size), IsVolatile));
1625+
LLVMPreserveCheriTags PreserveTags, bool IsVolatile) {
1626+
return wrap(unwrap(B)->CreateMemMove(
1627+
unwrap(Dst), MaybeAlign(DstAlign), unwrap(Src), MaybeAlign(SrcAlign),
1628+
unwrap(Size), fromRust(PreserveTags), IsVolatile));
16111629
}
16121630

16131631
extern "C" LLVMValueRef LLVMRustBuildMemSet(LLVMBuilderRef B, LLVMValueRef Dst,

0 commit comments

Comments
 (0)