Skip to content

Commit

Permalink
Extended verification. Numerous fixes to binary operations and array …
Browse files Browse the repository at this point in the history
…access. Made bswap use bulitin .NET intrinsics. Added support for tests comparing beahvour between native Rust and .NET Rust
  • Loading branch information
FractalFir committed Feb 10, 2024
1 parent 08cd710 commit 6368a39
Show file tree
Hide file tree
Showing 14 changed files with 554 additions and 327 deletions.
6 changes: 5 additions & 1 deletion src/aggregate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,11 @@ pub fn handle_aggregate<'tyctx>(
tycache,
);
let sig = crate::function_sig::FnSig::new(
&[Type::Ptr(Into::<Type>::into(array_type.clone()).into()), Type::USize, element],
&[
Type::Ptr(Into::<Type>::into(array_type.clone()).into()),
Type::USize,
element,
],
&Type::Void,
);
let call_site = CallSite::boxed(Some(array_type), "set_Item".into(), sig, false);
Expand Down
49 changes: 31 additions & 18 deletions src/binop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,12 @@ pub(crate) fn binop_unchecked<'tyctx>(
[
ops_a,
ops_b,
vec![CILOp::SizeOf(pointed_ty),CILOp::ConvUSize(false), CILOp::Mul, CILOp::Add],
vec![
CILOp::SizeOf(pointed_ty),
CILOp::ConvUSize(false),
CILOp::Mul,
CILOp::Add,
],
]
.into_iter()
.flatten()
Expand Down Expand Up @@ -500,14 +505,14 @@ fn rem_unchecked<'tyctx>(
}

fn shr_unchecked<'tyctx>(
ty_a: Ty<'tyctx>,
ty_b: Ty<'tyctx>,
value_type: Ty<'tyctx>,
shift_type: Ty<'tyctx>,
tycache: &mut TyCache,
method_instance: &Instance<'tyctx>,
tyctx: TyCtxt<'tyctx>,
) -> Vec<CILOp> {
let type_b = tycache.type_from_cache(ty_b, tyctx, Some(*method_instance));
match ty_a.kind() {
let type_b = tycache.type_from_cache(shift_type, tyctx, Some(*method_instance));
match value_type.kind() {
TyKind::Uint(UintTy::U128) => {
let mut res = crate::casts::int_to_int(type_b.clone(), Type::I32);
res.push(CILOp::Call(CallSite::boxed(
Expand All @@ -528,36 +533,41 @@ fn shr_unchecked<'tyctx>(
)));
res
}

TyKind::Uint(_) => match ty_b.kind() {
TyKind::Uint(UintTy::U128) | TyKind::Int(IntTy::I128) => {
TyKind::Uint(_) => match shift_type.kind() {
TyKind::Uint(UintTy::U128)
| TyKind::Int(IntTy::I128)
| TyKind::Uint(UintTy::U64)
| TyKind::Int(IntTy::I64) => {
let mut res = crate::casts::int_to_int(type_b.clone(), Type::I32);
res.push(CILOp::ShrUn);
res
}
_ => vec![CILOp::ShrUn],
},
TyKind::Int(_) => match ty_b.kind() {
TyKind::Uint(UintTy::U128) | TyKind::Int(IntTy::I128) => {
TyKind::Int(_) => match shift_type.kind() {
TyKind::Uint(UintTy::U128)
| TyKind::Int(IntTy::I128)
| TyKind::Uint(UintTy::U64)
| TyKind::Int(IntTy::I64) => {
let mut res = crate::casts::int_to_int(type_b.clone(), Type::I32);
res.push(CILOp::Shr);
res
}

_ => vec![CILOp::Shr],
},
_ => panic!("Can't bitshift type {ty_a:?}"),
_ => panic!("Can't bitshift type {value_type:?}"),
}
}
fn shl_unchecked<'tyctx>(
ty_a: Ty<'tyctx>,
ty_b: Ty<'tyctx>,
value_type: Ty<'tyctx>,
shift_type: Ty<'tyctx>,
tycache: &mut TyCache,
method_instance: &Instance<'tyctx>,
tyctx: TyCtxt<'tyctx>,
) -> Vec<CILOp> {
let type_b = tycache.type_from_cache(ty_b, tyctx, Some(*method_instance));
match ty_a.kind() {
let type_b = tycache.type_from_cache(shift_type, tyctx, Some(*method_instance));
match value_type.kind() {
TyKind::Uint(UintTy::U128) => {
let mut res = crate::casts::int_to_int(type_b.clone(), Type::I32);
res.push(CILOp::Call(CallSite::boxed(
Expand All @@ -578,15 +588,18 @@ fn shl_unchecked<'tyctx>(
)));
res
}
TyKind::Uint(_) | TyKind::Int(_) => match ty_b.kind() {
TyKind::Uint(UintTy::U128) | TyKind::Int(IntTy::I128) => {
TyKind::Uint(_) | TyKind::Int(_) => match shift_type.kind() {
TyKind::Uint(UintTy::U128)
| TyKind::Int(IntTy::I128)
| TyKind::Uint(UintTy::U64)
| TyKind::Int(IntTy::I64) => {
let mut res = crate::casts::int_to_int(type_b.clone(), Type::I32);
res.push(CILOp::Shl);
res
}
_ => vec![CILOp::Shl],
},
_ => panic!("Can't bitshift type {ty_a:?}"),
_ => panic!("Can't bitshift type {value_type:?}"),
}
}
fn mul_unchecked<'tyctx>(
Expand Down
105 changes: 100 additions & 5 deletions src/compile_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ fn peverify(file_path: &str, test_dir: &str) {
}
}
#[cfg(test)]
fn test_dotnet_executable(file_path: &str, test_dir: &str) {
fn test_dotnet_executable(file_path: &str, test_dir: &str)->String {
use std::io::Write;

let exec_path = &format!("{file_path}.exe");
let mut stdout = String::new();
//println!("exec_path:{exec_path:?}");
if *IS_DOTNET_PRESENT {
let config_path = format!("{test_dir}/{file_path}.runtimeconfig.json");
Expand All @@ -40,6 +41,7 @@ fn test_dotnet_executable(file_path: &str, test_dir: &str) {
stderr.is_empty(),
"Test program failed with message {stderr:}"
);
stdout = String::from_utf8(out.stdout).expect("Stdout is not UTF8 String!");
}
if *IS_MONO_PRESENT && *crate::config::TEST_WITH_MONO {
// Execute the test assembly
Expand All @@ -61,6 +63,7 @@ fn test_dotnet_executable(file_path: &str, test_dir: &str) {
(*IS_DOTNET_PRESENT || *IS_MONO_PRESENT),
"You must have the dotnet runtime installed to run tests."
);
stdout
}
#[cfg(test)]
fn test_lib(args: &[&str], test_name: &str) {
Expand Down Expand Up @@ -107,6 +110,97 @@ fn test_lib(args: &[&str], test_name: &str) {
panic!("stdout:\n{stdout}\nstderr:\n{stderr}");
}
}
macro_rules! compare_tests {
($prefix:ident,$test_name:ident) => {
#[cfg(target_os = "linux")]
mod $test_name {
#[cfg(test)]
use ntest::timeout;
#[cfg(test)]
static COMPILE_LOCK: std::sync::Mutex<()> = std::sync::Mutex::new(());
#[test]
#[timeout(30_000)]

fn release() {
let lock = COMPILE_LOCK.lock();
let mut should_panic = false;
let test_dir = concat!("./test/", stringify!($prefix), "/");
// Ensures the test directory is present
std::fs::create_dir_all(test_dir).expect("Could not setup the test env");
// Builds the backend if neceasry
super::RUSTC_BUILD_STATUS
.as_ref()
.expect("Could not build rustc!");
// Compiles the test project
let mut cmd = std::process::Command::new("rustc");
//.env("RUST_TARGET_PATH","../../")
cmd.current_dir(test_dir).args([
"-O",
"-Z",
super::backend_path(),
"-C",
&format!(
"linker={}",
super::RUSTC_CODEGEN_CLR_LINKER.display()
),
concat!("./", stringify!($test_name), ".rs"),
"-o",
concat!("./", stringify!($test_name), ".exe"),
"--edition",
"2021",
//"--target",
//"clr64-unknown-clr"
]);
eprintln!("Command: {cmd:?}");
let out = cmd.output().expect("failed to execute process");
// If stderr is not empty, then something went wrong, so print the stdout and stderr for debuging.
if !out.stderr.is_empty() {
let stdout = String::from_utf8(out.stdout)
.expect("rustc error contained non-UTF8 characters.");
let stderr = String::from_utf8(out.stderr)
.expect("rustc error contained non-UTF8 characters.");
eprintln!("stdout:\n{stdout}\nstderr:\n{stderr}");
should_panic = true;
}
let exec_path = concat!("../", stringify!($test_name));
drop(lock);
//super::peverify(exec_path, test_dir);
eprintln!("Prepating to test with .NET");
let dotnet_out = super::test_dotnet_executable(exec_path, test_dir);
// Compiles the project with native rust
let mut cmd = std::process::Command::new("rustc");
//.env("RUST_TARGET_PATH","../../")
cmd.current_dir(test_dir).args([
"-O",
concat!("./", stringify!($test_name), ".rs"),
"-o",
concat!("./", stringify!($test_name), ".a"),
"--edition",
"2021",
]);
eprintln!("Buildin");
let out = cmd.output().expect("failed to execute process");
// If stderr is not empty, then something went wrong, so print the stdout and stderr for debuging.
if !out.stderr.is_empty() {
let stdout = String::from_utf8(out.stdout)
.expect("rustc error contained non-UTF8 characters.");
let stderr = String::from_utf8(out.stderr)
.expect("rustc error contained non-UTF8 characters.");
eprintln!("stdout:\n{stdout}\nstderr:\n{stderr}");
should_panic = true;
}
let rust_out = std::process::Command::new(concat!("./", stringify!($test_name), ".a")).current_dir(test_dir).output().expect("failed to execute process");
let rust_out = String::from_utf8(rust_out.stdout)
.expect("rust error contained non-UTF8 characters.");
assert_eq!(rust_out,dotnet_out);
if should_panic{
panic!("{rust_out}{dotnet_out}");
}
}
}
};
}

macro_rules! test_lib {
($test_name:ident,$is_stable:ident) => {
mod $test_name {
Expand Down Expand Up @@ -542,6 +636,7 @@ run_test! {arthm,sub,stable}

run_test! {types,tuple_structs,stable}
run_test! {types,enums,unstable}
run_test! {types,arr,stable}
run_test! {types,adt_enum,stable}
run_test! {types,nbody,stable}
run_test! {types,structs,stable}
Expand All @@ -563,7 +658,7 @@ run_test! {std,main,unstable}
run_test! {control_flow,cf_for,stable}
run_test! {control_flow,drop,stable}

run_test! {intrinsics,bswap,unstable}
run_test! {intrinsics,bswap,stable}
run_test! {intrinsics,assert,unstable}
run_test! {intrinsics,addr_of,stable}
run_test! {intrinsics,printf,unstable}
Expand All @@ -574,9 +669,9 @@ run_test! {fuzz,test0,stable}
run_test! {fuzz,test1,stable}

run_test! {fuzz,fuzz0,unstable}
run_test! {fuzz,fuzz1,unstable}
run_test! {fuzz,fuzz2,unstable}
run_test! {fuzz,fuzz3,unstable}
compare_tests! {fuzz,fuzz1}
compare_tests! {fuzz,fuzz2}
compare_tests! {fuzz,fuzz3}

run_test! {fuzz,fail0,stable}

Expand Down
Loading

0 comments on commit 6368a39

Please sign in to comment.