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
2 changes: 1 addition & 1 deletion .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ run_cheri_tests_task:
check_env_script: env
pull_main_script: git fetch origin main:refs/remotes/origin/main --depth 1
build_rustc_script: CC="clang" CXX="clang++" ./x build compiler std --target=riscv32cheriot-unknown-cheriotrtos
build_rust_tests_script: CC="clang" CXX="clang++" ./x test tests/codegen-llvm/cheri-intrinsics.rs --target=riscv32cheriot-unknown-cheriotrtos
run_x_cheriot_tests_task: CC="clang" CXX="clang++" ./x test tests/codegen-llvm --target=riscv32cheriot-unknown-cheriotrtos --skip src/tools/linkchecker
build_test_runner_script: cd ./cheri/tests/runner && . "$CARGO_HOME/env" && cargo build --release
run_tests_script: cd ./cheri/tests && ./runner/target/release/cheriot-runner -vvvvv .
--sysroot=../../build/host/llvm
Expand Down
7 changes: 7 additions & 0 deletions src/tools/compiletest/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,10 @@ impl Config {
*&self.target_cfg().pointer_width
}

pub fn get_default_address_space(&self) -> Option<u32> {
*&self.target_cfg().default_address_space
}

pub fn can_unwind(&self) -> bool {
self.target_cfg().panic == PanicStrategy::Unwind
}
Expand Down Expand Up @@ -1031,6 +1035,9 @@ pub struct TargetCfg {
/// Supported target atomic widths: e.g. `8` to `128` or `ptr`. This is derived from the builtin
/// `target_has_atomic` `cfg`s e.g. `target_has_atomic="8"`.
pub(crate) target_has_atomic: BTreeSet<String>,

#[serde(rename = "default-address-space", default)]
pub(crate) default_address_space: Option<u32>,
}

impl TargetCfg {
Expand Down
3 changes: 2 additions & 1 deletion src/tools/compiletest/src/directives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,8 @@ impl TestProps {
fn load_from(&mut self, testfile: &Utf8Path, test_revision: Option<&str>, config: &Config) {
if !testfile.is_dir() {
let file_contents = fs::read_to_string(testfile).unwrap();
let file_directives = FileDirectives::from_file_contents(testfile, &file_contents);
let file_directives =
FileDirectives::from_file_contents(config.suite, testfile, &file_contents);

iter_directives(
config.mode,
Expand Down
29 changes: 28 additions & 1 deletion src/tools/compiletest/src/directives/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,42 @@ pub(crate) struct FileDirectives<'a> {
}

impl<'a> FileDirectives<'a> {
pub(crate) fn from_file_contents(path: &'a Utf8Path, file_contents: &'a str) -> Self {
/// Create a new [`FileDirectives`] by iterating through the lines of `file_contents`.
///
/// # Note
///
/// When the `suite` argument matches [`crate::common::TestSuite::CodegenLlvm`] a synthetic
/// `needs-target-std` directive is inserted if needed - that is, if the file does not contain a
/// `#![no_std]` annotation.
///
/// The objective of this addition is that of making it at least a bit easier to run
/// the codegen-llvm test suite for targets that do not have a stdlib, without forcing test
/// writers to remember yet another directive.
pub(crate) fn from_file_contents(
suite: crate::common::TestSuite,
path: &'a Utf8Path,
file_contents: &'a str,
) -> Self {
let mut lines = vec![];
let mut generate_needs_std_stub = true;

for (line_number, ln) in (1..).zip(file_contents.lines()) {
let ln = ln.trim();

if let Some(directive_line) = line_directive(path, line_number, ln) {
if directive_line.name == "needs-target-std" {
generate_needs_std_stub = false;
}
lines.push(directive_line);
}

if ln == "#![no_std]" || ln == "#![no_core]" {
generate_needs_std_stub = false;
}
}

if generate_needs_std_stub && matches!(suite, crate::common::TestSuite::CodegenLlvm) {
lines.insert(0, crate::directives::line::generate_needs_std(path))
}

Self { path, lines }
Expand Down
13 changes: 13 additions & 0 deletions src/tools/compiletest/src/directives/line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,19 @@ pub(crate) fn line_directive<'a>(
Some(DirectiveLine { file_path, line_number, revision, raw_directive, name })
}

/// Generate a synthetic [`DirectiveLine`] to add the "needs-target-std" directive to a specific
/// test. See [`crate::FileDirectives::from_file_contents`] for an explanation why this is needed.
#[inline]
pub(crate) fn generate_needs_std<'a>(file_path: &'a Utf8Path) -> DirectiveLine<'a> {
DirectiveLine {
file_path,
line_number: 0,
revision: None,
raw_directive: "needs-target-std",
name: "needs-target-std",
}
}

/// The (partly) broken-down contents of a line containing a test directive,
/// which `iter_directives` passes to its callback function.
///
Expand Down
12 changes: 9 additions & 3 deletions src/tools/compiletest/src/directives/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ fn make_test_description(
) -> CollectedTestDesc {
let cache = DirectivesCache::load(config);
let mut poisoned = false;
let file_directives = FileDirectives::from_file_contents(path, file_contents);
let file_directives = FileDirectives::from_file_contents(config.suite, path, file_contents);

let mut aux_props = AuxProps::default();
let test = crate::directives::make_test_description(
Expand Down Expand Up @@ -259,7 +259,8 @@ fn cfg() -> ConfigBuilder {
}

fn parse_early_props(config: &Config, contents: &str) -> EarlyProps {
let file_directives = FileDirectives::from_file_contents(Utf8Path::new("a.rs"), contents);
let file_directives =
FileDirectives::from_file_contents(config.suite, Utf8Path::new("a.rs"), contents);
EarlyProps::from_file_directives(config, &file_directives)
}

Expand Down Expand Up @@ -820,7 +821,12 @@ fn threads_support() {
}

fn run_path(poisoned: &mut bool, path: &Utf8Path, file_contents: &str) {
let file_directives = FileDirectives::from_file_contents(path, file_contents);
let file_directives = FileDirectives::from_file_contents(
// Arbitrary suite to prevent from_file_contents to add synthetic directives.
crate::common::TestSuite::Coverage,
path,
file_contents,
);
let result = directives::do_early_directives_check(TestMode::Ui, &file_directives);
if result.is_err() {
*poisoned = true;
Expand Down
3 changes: 2 additions & 1 deletion src/tools/compiletest/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -871,7 +871,8 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te
// Scan the test file to discover its revisions, if any.
let file_contents =
fs::read_to_string(&test_path).expect("reading test file for directives should succeed");
let file_directives = FileDirectives::from_file_contents(&test_path, &file_contents);
let file_directives =
FileDirectives::from_file_contents(cx.config.suite, &test_path, &file_contents);

if let Err(message) = directives::do_early_directives_check(cx.config.mode, &file_directives) {
// FIXME(Zalathar): Overhaul compiletest error handling so that we
Expand Down
11 changes: 11 additions & 0 deletions src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2142,6 +2142,17 @@ impl<'test> TestCx<'test> {
filecheck.arg("--check-prefix").arg(rev);
}

// HACK: Some targets use a default address space that is different
// from the default one in LLVM.
// This variable is set to make it slightly easier to adapt existing
// tests to those targets using the [[ADDRSPACE]] variable.
if let Some(address_space) = self.config.get_default_address_space() {
// The leading whitespace is intended.
filecheck.arg(format!("-DADDRSPACE= addrspace({})", address_space));
} else {
filecheck.arg("-DADDRSPACE=");
}

// HACK: the filecheck tool normally fails if a prefix is defined but not used. However,
// sometimes revisions are used to specify *compiletest* directives which are not FileCheck
// concerns.
Expand Down
7 changes: 4 additions & 3 deletions tests/codegen-llvm/addr-of-mutate.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
//@ compile-flags: -C opt-level=3 -C no-prepopulate-passes

#![crate_type = "lib"]
#![no_std]

// Test for the absence of `readonly` on the argument when it is mutated via `&raw const`.
// See <https://github.com/rust-lang/rust/issues/111502>.

// CHECK: i8 @foo(ptr{{( dead_on_return)?}} noalias noundef align 1{{( captures\(address\))?}} dereferenceable(128) %x)
// CHECK: i8 @foo(ptr[[ADDRSPACE]]{{( dead_on_return)?}} noalias noundef align 1{{( captures\(address\))?}} dereferenceable(128) %x)
#[no_mangle]
pub fn foo(x: [u8; 128]) -> u8 {
let ptr = core::ptr::addr_of!(x).cast_mut();
Expand All @@ -15,7 +16,7 @@ pub fn foo(x: [u8; 128]) -> u8 {
x[0]
}

// CHECK: i1 @second(ptr{{( dead_on_return)?}} noalias noundef align {{[0-9]+}}{{( captures\(address\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
// CHECK: i1 @second(ptr[[ADDRSPACE]]{{( dead_on_return)?}} noalias noundef align {{[0-9]+}}{{( captures\(address\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
#[no_mangle]
pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
let b_bool_ptr = core::ptr::addr_of!(a_ptr_and_b.1.1).cast_mut();
Expand All @@ -24,7 +25,7 @@ pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
}

// If going through a deref (and there are no other mutating accesses), then `readonly` is fine.
// CHECK: i1 @third(ptr{{( dead_on_return)?}} noalias noundef readonly align {{[0-9]+}}{{( captures\(none\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
// CHECK: i1 @third(ptr[[ADDRSPACE]]{{( dead_on_return)?}} noalias noundef readonly align {{[0-9]+}}{{( captures\(none\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
#[no_mangle]
pub unsafe fn third(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
let b_bool_ptr = core::ptr::addr_of!((*a_ptr_and_b.0).1).cast_mut();
Expand Down
9 changes: 5 additions & 4 deletions tests/codegen-llvm/adjustments.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
//@ compile-flags: -C no-prepopulate-passes -Copt-level=0

#![crate_type = "lib"]
#![no_std]

// Hack to get the correct size for the length part in slices
// CHECK: @helper([[USIZE:i[0-9]+]] %_1)
// CHECK: @helper([[USIZE:i[0-9]+]]
#[no_mangle]
pub fn helper(_: usize) {}

Expand All @@ -12,9 +13,9 @@ pub fn helper(_: usize) {}
pub fn no_op_slice_adjustment(x: &[u8]) -> &[u8] {
// We used to generate an extra alloca and memcpy for the block's trailing expression value, so
// check that we copy directly to the return value slot
// CHECK: %0 = insertvalue { ptr, [[USIZE]] } poison, ptr %x.0, 0
// CHECK: %1 = insertvalue { ptr, [[USIZE]] } %0, [[USIZE]] %x.1, 1
// CHECK: ret { ptr, [[USIZE]] } %1
// CHECK: %0 = insertvalue { ptr[[ADDRSPACE]], [[USIZE]] } poison, ptr[[ADDRSPACE]] %x.0, 0
// CHECK: %1 = insertvalue { ptr[[ADDRSPACE]], [[USIZE]] } %0, [[USIZE]] %x.1, 1
// CHECK: ret { ptr[[ADDRSPACE]], [[USIZE]] } %1
{ x }
}

Expand Down
4 changes: 2 additions & 2 deletions tests/codegen-llvm/align-enum.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//@ compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0
//

#![crate_type = "lib"]
#![no_std]

#[repr(align(64))]
pub enum Align64 {
Expand All @@ -19,7 +19,7 @@ pub struct Nested64 {
#[no_mangle]
pub fn align64(a: u32) -> Align64 {
// CHECK: %a64 = alloca [64 x i8], align 64
// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 64 %{{.*}}, ptr align 64 %{{.*}}, i{{[0-9]+}} 64, i1 false)
// CHECK: call void @llvm.memcpy.{{.*}}(ptr[[ADDRSPACE]] align 64 %{{.*}}, ptr[[ADDRSPACE]] align 64 %{{.*}}, i{{[0-9]+}} 64, i1 false)
let a64 = Align64::A(a);
a64
}
Expand Down
1 change: 1 addition & 0 deletions tests/codegen-llvm/align-fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
//@ ignore-wasm32 aligning functions is not currently supported on wasm (#143368)

#![crate_type = "lib"]
#![no_std]
// FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity
#![feature(rustc_attrs)]
#![feature(fn_align)]
Expand Down
8 changes: 5 additions & 3 deletions tests/codegen-llvm/align-offset.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//@ compile-flags: -Copt-level=3
//@ ignore-riscv32cheriot-unknown-cheriotrtos FIXME: See CHERIoT-Platform/cheri-rust/issues/70

#![crate_type = "lib"]
#![no_std]

// CHECK-LABEL: @align8
#[no_mangle]
Expand All @@ -23,7 +25,7 @@ pub fn align_to4(x: &[u8]) -> bool {
// CHECK-LABEL: @align_offset_byte_ptr(ptr{{.+}}%ptr)
#[no_mangle]
pub fn align_offset_byte_ptr(ptr: *const u8) -> usize {
// CHECK: %[[ADDR:.+]] = ptrtoint ptr %ptr to [[USIZE:i[0-9]+]]
// CHECK: %[[ADDR:.+]] = ptrtoint ptr[[ADDRSPACE]] %ptr to [[USIZE:i[0-9]+]]
// CHECK: %[[UP:.+]] = add [[USIZE]] %[[ADDR]], 31
// CHECK: %[[ALIGNED:.+]] = and [[USIZE]] %[[UP]], -32
// CHECK: %[[OFFSET:.+]] = sub [[USIZE]] %[[ALIGNED]], %[[ADDR]]
Expand All @@ -40,7 +42,7 @@ pub fn align_offset_byte_ptr(ptr: *const u8) -> usize {
// CHECK-LABEL: @align_offset_word_slice(ptr{{.+}}align 4{{.+}}%slice.0
#[no_mangle]
pub fn align_offset_word_slice(slice: &[Align4]) -> usize {
// CHECK: %[[ADDR:.+]] = ptrtoint ptr %slice.0 to [[USIZE]]
// CHECK: %[[ADDR:.+]] = ptrtoint ptr[[ADDRSPACE]] %slice.0 to [[USIZE]]
// CHECK: %[[UP:.+]] = add [[USIZE]] %[[ADDR]], 31
// CHECK: %[[ALIGNED:.+]] = and [[USIZE]] %[[UP]], -32
// CHECK: %[[BOFFSET:.+]] = sub [[USIZE]] %[[ALIGNED]], %[[ADDR]]
Expand All @@ -56,7 +58,7 @@ pub fn align_offset_word_slice(slice: &[Align4]) -> usize {
// CHECK-LABEL: @align_offset_word_ptr(ptr{{.+}}%ptr
#[no_mangle]
pub fn align_offset_word_ptr(ptr: *const Align4) -> usize {
// CHECK: %[[ADDR:.+]] = ptrtoint ptr %ptr to [[USIZE]]
// CHECK: %[[ADDR:.+]] = ptrtoint ptr[[ADDRSPACE]] %ptr to [[USIZE]]
// CHECK: %[[UP:.+]] = add [[USIZE]] %[[ADDR]], 31
// CHECK: %[[ALIGNED:.+]] = and [[USIZE]] %[[UP]], -32
// CHECK: %[[BOFFSET:.+]] = sub [[USIZE]] %[[ALIGNED]], %[[ADDR]]
Expand Down
1 change: 1 addition & 0 deletions tests/codegen-llvm/align-static.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//@ compile-flags: -C no-prepopulate-passes -Z mir-opt-level=0

#![crate_type = "lib"]
#![no_std]
#![feature(static_align)]

// CHECK: @STATIC_ALIGN =
Expand Down
5 changes: 3 additions & 2 deletions tests/codegen-llvm/align-struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//@ ignore-i686-pc-windows-gnu

#![crate_type = "lib"]
#![no_std]

#[repr(align(64))]
pub struct Align64(i32);
Expand Down Expand Up @@ -31,7 +32,7 @@ pub enum Enum64 {
#[no_mangle]
pub fn align64(i: i32) -> Align64 {
// CHECK: %a64 = alloca [64 x i8], align 64
// CHECK: call void @llvm.memcpy.{{.*}}(ptr align 64 %{{.*}}, ptr align 64 %{{.*}}, i{{[0-9]+}} 64, i1 false)
// CHECK: call void @llvm.memcpy.{{.*}}(ptr[[ADDRSPACE]] align 64 %{{.*}}, ptr[[ADDRSPACE]] align 64 %{{.*}}, i{{[0-9]+}} 64, i1 false)
let a64 = Align64(i);
a64
}
Expand All @@ -41,7 +42,7 @@ pub fn align64(i: i32) -> Align64 {
// CHECK-LABEL: @align64_load
#[no_mangle]
pub fn align64_load(a: Align64) -> i32 {
// CHECK: {{%.*}} = load i32, ptr {{%.*}}, align 64
// CHECK: {{%.*}} = load i32, ptr[[ADDRSPACE]] {{%.*}}, align 64
a.0
}

Expand Down
6 changes: 6 additions & 0 deletions tests/codegen-llvm/alloc-optimisation.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
//@ compile-flags: -Copt-level=3
//@ ignore-riscv32cheriot-unknown-cheriotrtos FIXME: See CHERIoT-Platform/cheri-rust/issues/64

#![crate_type = "lib"]
#![no_std]

extern crate alloc;
use alloc::boxed::Box;

#[no_mangle]
pub fn alloc_test(data: u32) {
Expand Down
1 change: 1 addition & 0 deletions tests/codegen-llvm/annotate-moves/call-arg-scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// NOT have an inlinedAt scope pointing to compiler_move/compiler_copy.

#![crate_type = "lib"]
#![no_std]

#[derive(Clone, Copy)]
pub struct LargeStruct {
Expand Down
1 change: 1 addition & 0 deletions tests/codegen-llvm/annotate-moves/disabled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Test that move/copy operations are NOT annotated when the flag is disabled

#![crate_type = "lib"]
#![no_std]

struct LargeStruct {
data: [u64; 20], // 160 bytes - would normally trigger annotation
Expand Down
6 changes: 5 additions & 1 deletion tests/codegen-llvm/annotate-moves/integration.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
//@ compile-flags: -Z annotate-moves=1 -Copt-level=0 -g

#![crate_type = "lib"]
#![no_std]

extern crate alloc;
use alloc::string::{String, ToString};

// Test with large array (non-struct type, Copy)
type LargeArray = [u64; 20]; // 160 bytes
Expand Down Expand Up @@ -113,7 +117,7 @@ pub fn test_explicit_copy_assignment() {

// CHECK-LABEL: integration::test_array_move
pub fn test_array_move() {
let arr: [String; 20] = std::array::from_fn(|i| i.to_string());
let arr: [String; 20] = core::array::from_fn(|i| i.to_string());

// CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#ARRAY_MOVE_LOC:]]
let _moved = arr;
Expand Down
1 change: 1 addition & 0 deletions tests/codegen-llvm/annotate-moves/size-limit.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//@ compile-flags: -Z annotate-moves=100 -Copt-level=0 -g
// Test that custom size limits work correctly
#![crate_type = "lib"]
#![no_std]

struct Struct99 {
data: [u8; 99], // just below custom 100-byte threshold
Expand Down
1 change: 1 addition & 0 deletions tests/codegen-llvm/array-clone.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//@ compile-flags: -Copt-level=3

#![crate_type = "lib"]
#![no_std]

// CHECK-LABEL: @array_clone
#[no_mangle]
Expand Down
Loading