Skip to content

Commit

Permalink
pulley: Support runtests in Cranelift filetests
Browse files Browse the repository at this point in the history
This'll help when adding unit tests for Pulley and/or might be useful
when debugging various lowerings and such in the future. I hope to
enable more tests in the future once more pulley lowerings are
available.
  • Loading branch information
alexcrichton committed Dec 11, 2024
1 parent 65312bf commit 28f6b03
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 9 deletions.
2 changes: 1 addition & 1 deletion cranelift/filetests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ serde = { workspace = true }
serde_derive = { workspace = true }
cranelift.workspace = true
smallvec = { workspace = true }
pulley-interpreter = { workspace = true, features = ["disas", "std"] }
pulley-interpreter = { workspace = true, features = ["disas", "std", "interp"] }
4 changes: 4 additions & 0 deletions cranelift/filetests/filetests/runtests/br.clif
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ target s390x
target x86_64
target riscv64
target riscv64 has_c has_zcb
target pulley32
target pulley32be
target pulley64
target pulley64be

function %jump() -> i8 {
block0:
Expand Down
4 changes: 4 additions & 0 deletions cranelift/filetests/filetests/runtests/brif.clif
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ target s390x
target x86_64
target riscv64
target riscv64 has_c has_zcb
target pulley32
target pulley32be
target pulley64
target pulley64be

function %brif_value(i8) -> i64 {
block0(v0: i8):
Expand Down
42 changes: 39 additions & 3 deletions cranelift/filetests/src/function_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ use cranelift_jit::{JITBuilder, JITModule};
use cranelift_module::{FuncId, Linkage, Module, ModuleError};
use cranelift_native::builder_with_options;
use cranelift_reader::TestFile;
use pulley_interpreter::interp as pulley;
use std::cmp::max;
use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::ptr::NonNull;
use target_lexicon::Architecture;
use thiserror::Error;

const TESTFILE_NAMESPACE: u32 = 0;
Expand Down Expand Up @@ -370,12 +373,45 @@ impl<'a> Trampoline<'a> {
let function_ptr = self.module.get_finalized_function(self.func_id);
let trampoline_ptr = self.module.get_finalized_function(self.trampoline_id);

let callable_trampoline: fn(*const u8, *mut u128) -> () =
unsafe { mem::transmute(trampoline_ptr) };
callable_trampoline(function_ptr, arguments_address);
unsafe {
self.call_raw(trampoline_ptr, function_ptr, arguments_address);
}

values.collect_returns(&self.func_signature)
}

unsafe fn call_raw(
&self,
trampoline_ptr: *const u8,
function_ptr: *const u8,
arguments_address: *mut u128,
) {
match self.module.isa().triple().architecture {
// For the pulley target this is pulley bytecode, not machine code,
// so run the interpreter.
Architecture::Pulley32
| Architecture::Pulley64
| Architecture::Pulley32be
| Architecture::Pulley64be => {
let mut state = pulley::Vm::new();
state.call(
NonNull::new(trampoline_ptr.cast_mut()).unwrap(),
&[
pulley::XRegVal::new_ptr(function_ptr.cast_mut()).into(),
pulley::XRegVal::new_ptr(arguments_address).into(),
],
[],
);
}

// Other targets natively execute this machine code.
_ => {
let callable_trampoline: fn(*const u8, *mut u128) -> () =
unsafe { mem::transmute(trampoline_ptr) };
callable_trampoline(function_ptr, arguments_address);
}
}
}
}

/// Compilation Error when compiling a function.
Expand Down
44 changes: 39 additions & 5 deletions cranelift/filetests/src/test_run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,23 @@ fn is_isa_compatible(
let requested_arch = requested.triple().architecture;

match (host_arch, requested_arch) {
// If the host matches the requested target, then that's all good.
(host, requested) if host == requested => {}

// Allow minor differences in risc-v targets.
(Architecture::Riscv64(_), Architecture::Riscv64(_)) => {}

// Any host can run pulley so long as the pointer width and endianness
// match.
(
_,
Architecture::Pulley32
| Architecture::Pulley64
| Architecture::Pulley32be
| Architecture::Pulley64be,
) if host.triple().pointer_width() == requested.triple().pointer_width()
&& host.triple().endianness() == requested.triple().endianness() => {}

_ => {
return Err(format!(
"skipped {file_path}: host can't run {requested_arch:?} programs"
Expand All @@ -72,6 +87,10 @@ fn is_isa_compatible(
// we can't natively support on the host.
let requested_flags = requested.isa_flags();
for req_value in requested_flags {
// pointer_width for pulley already validated above
if req_value.name == "pointer_width" {
continue;
}
let requested = match req_value.as_bool() {
Some(requested) => requested,
None => unimplemented!("ISA flag {} of kind {:?}", req_value.name, req_value.kind()),
Expand Down Expand Up @@ -116,11 +135,26 @@ fn compile_testfile(
flags: &Flags,
isa: &dyn TargetIsa,
) -> anyhow::Result<CompiledTestFile> {
// We can't use the requested ISA directly since it does not contain info
// about the operating system / calling convention / etc..
//
// Copy the requested ISA flags into the host ISA and use that.
let isa = build_host_isa(false, flags.clone(), isa.isa_flags());
let isa = match isa.triple().architecture {
// Convert `&dyn TargetIsa` to `OwnedTargetIsa` by re-making the ISA and
// applying pulley flags/etc.
Architecture::Pulley32
| Architecture::Pulley64
| Architecture::Pulley32be
| Architecture::Pulley64be => {
let mut builder = cranelift_codegen::isa::lookup(isa.triple().clone())?;
for value in isa.isa_flags() {
builder.set(value.name, &value.value_string()).unwrap();
}
builder.finish(flags.clone())?
}

// We can't use the requested ISA directly since it does not contain info
// about the operating system / calling convention / etc..
//
// Copy the requested ISA flags into the host ISA and use that.
_ => build_host_isa(false, flags.clone(), isa.isa_flags()),
};

let mut tfc = TestFileCompiler::new(isa);
tfc.add_testfile(testfile)?;
Expand Down

0 comments on commit 28f6b03

Please sign in to comment.