GitLab will be upgraded to the 12.10.14-ce.0 on 28 Sept 2020 at 2.00pm (AEDT) to 2.30pm (AEDT). During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to us at N110 (b) CSIT building.

Commit 2230463c authored by Isaac Gariano's avatar Isaac Gariano

Merge branch 'aarch64' into 'develop'

Merge Aarch64 into develop

See merge request !11
parents 226a7b25 e995a3d0
...@@ -21,6 +21,7 @@ ast = {path = "src/ast"} ...@@ -21,6 +21,7 @@ ast = {path = "src/ast"}
utils = {path = "src/utils"} utils = {path = "src/utils"}
gc = {path = "src/gc"} gc = {path = "src/gc"}
field-offset = "0.1.1" field-offset = "0.1.1"
libloading = "0.3" libloading = "0.3"
lazy_static = "0.1.15" lazy_static = "0.1.15"
...@@ -34,4 +35,5 @@ time = "0.1.34" ...@@ -34,4 +35,5 @@ time = "0.1.34"
maplit = "0.1.4" maplit = "0.1.4"
docopt = "0.6" docopt = "0.6"
petgraph = "0.4.1" petgraph = "0.4.1"
extprim = "*" extprim = "*"
\ No newline at end of file num-traits = "*"
set -e
if [ -z "$MU_ZEBU" ]
then
export MU_ZEBU=$PWD
fi
export MU_LOG_LEVEL=none
export RUST_TEST_THREADS=1
export RUST_BACKTRACE=0
export PYTHONPATH="$MU_ZEBU/tests/test_jit/mu-client-pypy/:$MU_ZEBU/tests/test_jit/RPySOM/src"
export LD_LIBRARY_PATH="$MU_ZEBU/tests/test_jit/:$MU_ZEBU/tests/test_jit"
export ZEBU_BUILD=release
rm -rf $MU_ZEBU/emit
rm -rf $MU_ZEBU/tests/test_jit/emit
#cargo clean
cargo test --release --no-run --color=always 2>&1 | tee build_out.txt
/usr/bin/time -f "finished in %e secs" -a -o cargo_test_out.txt ./test-release --color=always 2>/dev/null | tee cargo_test_out.txt
cd $MU_ZEBU/tests/test_jit/mu-client-pypy
git pull
cd $MU_ZEBU/tests/test_jit/RPySOM
git pull
cd $MU_ZEBU/tests/test_jit/
ZEBU_BUILD=release LD_LIBRARY_PATH=. PYTHONPATH=mu-client-pypy:RPySOM/src pytest test_*.py -v --color=yes 2>&1 | tee $MU_ZEBU/pytest_out.txt
...@@ -735,6 +735,14 @@ impl Value { ...@@ -735,6 +735,14 @@ impl Value {
}) })
} }
pub fn is_int_ex_const(&self) -> bool {
match self.v {
Value_::Constant(Constant::IntEx(_)) => true,
_ => false
}
}
pub fn is_int_const(&self) -> bool { pub fn is_int_const(&self) -> bool {
match self.v { match self.v {
Value_::Constant(Constant::Int(_)) => true, Value_::Constant(Constant::Int(_)) => true,
...@@ -742,7 +750,13 @@ impl Value { ...@@ -742,7 +750,13 @@ impl Value {
_ => false _ => false
} }
} }
pub fn is_fp_const(&self) -> bool {
match self.v {
Value_::Constant(Constant::Float(_)) => true,
Value_::Constant(Constant::Double(_)) => true,
_ => false
}
}
pub fn extract_int_const(&self) -> u64 { pub fn extract_int_const(&self) -> u64 {
match self.v { match self.v {
Value_::Constant(Constant::Int(val)) => val, Value_::Constant(Constant::Int(val)) => val,
...@@ -751,6 +765,13 @@ impl Value { ...@@ -751,6 +765,13 @@ impl Value {
} }
} }
pub fn extract_int_ex_const(&self) -> Vec<u64> {
match self.v {
Value_::Constant(Constant::IntEx(ref val)) => val.clone(),
_ => panic!("expect int ex const")
}
}
pub fn extract_ssa_id(&self) -> Option<MuID> { pub fn extract_ssa_id(&self) -> Option<MuID> {
match self.v { match self.v {
Value_::SSAVar(id) => Some(id), Value_::SSAVar(id) => Some(id),
......
...@@ -211,7 +211,7 @@ impl CmpOp { ...@@ -211,7 +211,7 @@ impl CmpOp {
FUGT => FULT, FUGT => FULT,
FULT => FUGT, FULT => FUGT,
_ => self, // all other comparisons are reflexive _ => self, // all other comparisons are symmetric
} }
} }
pub fn invert(self) -> CmpOp { pub fn invert(self) -> CmpOp {
...@@ -257,6 +257,18 @@ impl CmpOp { ...@@ -257,6 +257,18 @@ impl CmpOp {
FTRUE => FFALSE, FTRUE => FFALSE,
} }
} }
// gets the unsigned version of the comparison
pub fn get_unsigned(self) -> CmpOp {
use op::CmpOp::*;
match self {
SGE => UGE,
SLT => ULT,
SGT => UGT,
SLE => ULE,
_ => self,
}
}
pub fn is_signed(self) -> bool { pub fn is_signed(self) -> bool {
use op::CmpOp::*; use op::CmpOp::*;
match self { match self {
...@@ -264,6 +276,14 @@ impl CmpOp { ...@@ -264,6 +276,14 @@ impl CmpOp {
_ => false _ => false
} }
} }
pub fn is_symmetric(self) -> bool {
use op::CmpOp::*;
match self {
EQ | NE | FORD| FUNO| FUNE | FUEQ | FONE | FOEQ => true,
_ => false
}
}
} }
#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] #[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
......
...@@ -23,8 +23,10 @@ pub trait CodeGenerator { ...@@ -23,8 +23,10 @@ pub trait CodeGenerator {
fn end_block(&mut self, block_name: MuName); fn end_block(&mut self, block_name: MuName);
// add CFI info // add CFI info
fn add_cfi_sections(&mut self, arg: &str);
fn add_cfi_startproc(&mut self); fn add_cfi_startproc(&mut self);
fn add_cfi_endproc(&mut self); fn add_cfi_endproc(&mut self);
fn add_cfi_def_cfa(&mut self, reg: Reg, offset: i32);
fn add_cfi_def_cfa_register(&mut self, reg: Reg); fn add_cfi_def_cfa_register(&mut self, reg: Reg);
fn add_cfi_def_cfa_offset(&mut self, offset: i32); fn add_cfi_def_cfa_offset(&mut self, offset: i32);
fn add_cfi_offset(&mut self, reg: Reg, offset: i32); fn add_cfi_offset(&mut self, reg: Reg, offset: i32);
...@@ -35,6 +37,10 @@ pub trait CodeGenerator { ...@@ -35,6 +37,10 @@ pub trait CodeGenerator {
fn emit_frame_grow(&mut self); // Emits a SUB fn emit_frame_grow(&mut self); // Emits a SUB
fn emit_frame_shrink(&mut self); // Emits an ADD fn emit_frame_shrink(&mut self); // Emits an ADD
// Used to pass a string that the assembler will interpret as an immediate argument
// (This is neccesary to support the use of ELF relocations like ':tprel_hi12:foo')
fn emit_add_str(&mut self, dest: Reg, src1: Reg, src2: &str);
// stack minimpulation // stack minimpulation
fn emit_push_pair(&mut self, src1: Reg, src2: Reg, stack: Reg); // Emits a STP fn emit_push_pair(&mut self, src1: Reg, src2: Reg, stack: Reg); // Emits a STP
fn emit_pop_pair(&mut self, dest1: Reg, dest2: Reg, stack: Reg); // Emits a LDP fn emit_pop_pair(&mut self, dest1: Reg, dest2: Reg, stack: Reg); // Emits a LDP
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
...@@ -186,7 +186,7 @@ impl FrameSlot { ...@@ -186,7 +186,7 @@ impl FrameSlot {
base: aarch64::FP.clone(), base: aarch64::FP.clone(),
offset: Some(Value::make_int_const(vm.next_id(), self.offset as u64)), offset: Some(Value::make_int_const(vm.next_id(), self.offset as u64)),
scale: 1, scale: 1,
signed: false signed: true
} }
) )
}) })
......
...@@ -144,8 +144,8 @@ lazy_static! { ...@@ -144,8 +144,8 @@ lazy_static! {
pub static ref UDIV_U128 : RuntimeEntrypoint = RuntimeEntrypoint { pub static ref UDIV_U128 : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig { sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()), hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![UINT64_TYPE.clone(); 2], ret_tys: vec![UINT128_TYPE.clone(); 1],
arg_tys: vec![UINT64_TYPE.clone(); 4] arg_tys: vec![UINT128_TYPE.clone(); 2]
}), }),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_udiv_u128")), aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_udiv_u128")),
jit: RwLock::new(None) jit: RwLock::new(None)
...@@ -154,8 +154,8 @@ lazy_static! { ...@@ -154,8 +154,8 @@ lazy_static! {
pub static ref SDIV_I128 : RuntimeEntrypoint = RuntimeEntrypoint { pub static ref SDIV_I128 : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig { sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()), hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![UINT64_TYPE.clone(); 2], ret_tys: vec![UINT128_TYPE.clone(); 1],
arg_tys: vec![UINT64_TYPE.clone(); 4] arg_tys: vec![UINT128_TYPE.clone(); 2]
}), }),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_sdiv_i128")), aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_sdiv_i128")),
jit: RwLock::new(None) jit: RwLock::new(None)
...@@ -164,8 +164,8 @@ lazy_static! { ...@@ -164,8 +164,8 @@ lazy_static! {
pub static ref UREM_U128 : RuntimeEntrypoint = RuntimeEntrypoint { pub static ref UREM_U128 : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig { sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()), hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![UINT64_TYPE.clone(); 2], ret_tys: vec![UINT128_TYPE.clone(); 1],
arg_tys: vec![UINT64_TYPE.clone(); 4] arg_tys: vec![UINT128_TYPE.clone(); 2]
}), }),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_urem_u128")), aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_urem_u128")),
jit: RwLock::new(None) jit: RwLock::new(None)
...@@ -174,13 +174,92 @@ lazy_static! { ...@@ -174,13 +174,92 @@ lazy_static! {
pub static ref SREM_I128 : RuntimeEntrypoint = RuntimeEntrypoint { pub static ref SREM_I128 : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig { sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()), hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![UINT64_TYPE.clone(); 2], ret_tys: vec![UINT128_TYPE.clone(); 1],
arg_tys: vec![UINT64_TYPE.clone(); 4] arg_tys: vec![UINT128_TYPE.clone(); 2]
}), }),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_srem_i128")), aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_srem_i128")),
jit: RwLock::new(None) jit: RwLock::new(None)
}; };
pub static ref FPTOUI_DOUBLE_U128 : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![UINT128_TYPE.clone(); 1],
arg_tys: vec![DOUBLE_TYPE.clone(); 1]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_fptoui_double_u128")),
jit: RwLock::new(None)
};
pub static ref FPTOSI_DOUBLE_I128 : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![UINT128_TYPE.clone(); 1],
arg_tys: vec![DOUBLE_TYPE.clone(); 1]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_fptosi_double_i128")),
jit: RwLock::new(None)
};
pub static ref UITOFP_U128_DOUBLE : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![DOUBLE_TYPE.clone(); 1],
arg_tys: vec![UINT128_TYPE.clone(); 1]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_uitofp_u128_double")),
jit: RwLock::new(None)
};
pub static ref SITOFP_I128_DOUBLE : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![DOUBLE_TYPE.clone(); 1],
arg_tys: vec![UINT128_TYPE.clone(); 1]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_sitofp_i128_double")),
jit: RwLock::new(None)
};
// Conversion to/from int<128> from/to float
pub static ref FPTOUI_FLOAT_U128 : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![UINT128_TYPE.clone(); 1],
arg_tys: vec![FLOAT_TYPE.clone(); 1]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_fptoui_float_u128")),
jit: RwLock::new(None)
};
pub static ref FPTOSI_FLOAT_I128 : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![UINT128_TYPE.clone(); 1],
arg_tys: vec![FLOAT_TYPE.clone(); 1]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_fptosi_float_i128")),
jit: RwLock::new(None)
};
pub static ref UITOFP_U128_FLOAT : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![FLOAT_TYPE.clone(); 1],
arg_tys: vec![UINT128_TYPE.clone(); 1]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_uitofp_u128_float")),
jit: RwLock::new(None)
};
pub static ref SITOFP_I128_FLOAT : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![FLOAT_TYPE.clone(); 1],
arg_tys: vec![UINT128_TYPE.clone(); 1]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_sitofp_i128_float")),
jit: RwLock::new(None)
};
// impl/decl: mod.rs // impl/decl: mod.rs
pub static ref PRINT_HEX : RuntimeEntrypoint = RuntimeEntrypoint { pub static ref PRINT_HEX : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig { sig: P(MuFuncSig {
......
...@@ -5,7 +5,6 @@ use utils::Address; ...@@ -5,7 +5,6 @@ use utils::Address;
use utils::Word; use utils::Word;
use utils::POINTER_SIZE; use utils::POINTER_SIZE;
use runtime::thread; use runtime::thread;
use runtime::PRINT_BACKTRACE;
use std::sync::RwLock; use std::sync::RwLock;
use std::sync::RwLockReadGuard; use std::sync::RwLockReadGuard;
...@@ -45,7 +44,9 @@ pub extern fn throw_exception_internal(exception_obj: Address, last_frame_callee ...@@ -45,7 +44,9 @@ pub extern fn throw_exception_internal(exception_obj: Address, last_frame_callee
trace!("throwing exception: {}", exception_obj); trace!("throwing exception: {}", exception_obj);
trace!("callee saved registers of last frame is saved at {}", last_frame_callee_saved); trace!("callee saved registers of last frame is saved at {}", last_frame_callee_saved);
inspect_higher_address(last_frame_callee_saved, 20); if cfg!(debug_assertions) {
inspect_higher_address(last_frame_callee_saved, 20);
}
let mut cur_thread = thread::MuThread::current_mut(); let mut cur_thread = thread::MuThread::current_mut();
// set exception object // set exception object
...@@ -100,7 +101,7 @@ pub extern fn throw_exception_internal(exception_obj: Address, last_frame_callee ...@@ -100,7 +101,7 @@ pub extern fn throw_exception_internal(exception_obj: Address, last_frame_callee
} }
}; };
if PRINT_BACKTRACE { if cfg!(debug_assertions) {
print_backtrace(throw_frame_callsite, cursor.clone()); print_backtrace(throw_frame_callsite, cursor.clone());
} }
......
...@@ -45,8 +45,10 @@ pub extern fn throw_exception_internal(exception_obj: Address, last_frame_callee ...@@ -45,8 +45,10 @@ pub extern fn throw_exception_internal(exception_obj: Address, last_frame_callee
trace!("throwing exception: {}", exception_obj); trace!("throwing exception: {}", exception_obj);
trace!("callee saved registers of last frame is saved at {}", last_frame_callee_saved); trace!("callee saved registers of last frame is saved at {}", last_frame_callee_saved);
inspect_nearby_address(last_frame_callee_saved, 8); if cfg!(debug_assertions) {
inspect_nearby_address(last_frame_callee_saved, 8);
}
let mut cur_thread = thread::MuThread::current_mut(); let mut cur_thread = thread::MuThread::current_mut();
// set exception object // set exception object
cur_thread.exception_obj = exception_obj; cur_thread.exception_obj = exception_obj;
...@@ -84,7 +86,7 @@ pub extern fn throw_exception_internal(exception_obj: Address, last_frame_callee ...@@ -84,7 +86,7 @@ pub extern fn throw_exception_internal(exception_obj: Address, last_frame_callee
} }
}; };
if PRINT_BACKTRACE { if cfg!(debug_assertions) {
print_backtrace(throw_frame_callsite, cursor.clone()); print_backtrace(throw_frame_callsite, cursor.clone());
} }
......
...@@ -14,29 +14,46 @@ pub extern fn muentry_frem64(a: f64, b: f64) -> f64 { ...@@ -14,29 +14,46 @@ pub extern fn muentry_frem64(a: f64, b: f64) -> f64 {
a.rem(b) a.rem(b)
} }
extern crate num_traits;
use extprim::u128::u128; use extprim::u128::u128;
use extprim::i128::i128; use extprim::i128::i128;
use runtime::math::num_traits::ToPrimitive;
use runtime::math::num_traits::FromPrimitive;
#[no_mangle] #[no_mangle]
#[allow(unreachable_code)]
pub extern fn muentry_udiv_u128(a: u128, b: u128) -> u128 { pub extern fn muentry_udiv_u128(a: u128, b: u128) -> u128 {
a.wrapping_div(b) a.wrapping_div(b)
} }
#[no_mangle] #[no_mangle]
#[allow(unreachable_code)]
pub extern fn muentry_sdiv_i128(a: i128, b: i128) -> i128 { pub extern fn muentry_sdiv_i128(a: i128, b: i128) -> i128 {
a.wrapping_div(b) a.wrapping_div(b)
} }
#[no_mangle] #[no_mangle]
#[allow(unreachable_code)]
pub extern fn muentry_urem_u128(a: u128, b: u128) -> u128 { pub extern fn muentry_urem_u128(a: u128, b: u128) -> u128 {
a.wrapping_rem(b) a.wrapping_rem(b)
} }
#[no_mangle] #[no_mangle]
#[allow(unreachable_code)]
pub extern fn muentry_srem_i128(a: i128, b: i128) -> i128 { pub extern fn muentry_srem_i128(a: i128, b: i128) -> i128 {
a.wrapping_rem(b) a.wrapping_rem(b)
} }
\ No newline at end of file
#[no_mangle]
pub extern fn muentry_fptoui_double_u128(a: f64) -> u128 { u128::from_f64(a).unwrap() }
#[no_mangle]
pub extern fn muentry_fptosi_double_i128(a: f64) -> i128 { i128::from_f64(a).unwrap() }
#[no_mangle]
pub extern fn muentry_uitofp_u128_double(a: u128) -> f64 { a.to_f64().unwrap() }
#[no_mangle]
pub extern fn muentry_sitofp_i128_double(a: i128) -> f64 { a.to_f64().unwrap() }
#[no_mangle]
pub extern fn muentry_fptoui_float_u128(a: f32) -> u128 { u128::from_f32(a).unwrap() }
#[no_mangle]
pub extern fn muentry_fptosi_float_i128(a: f32) -> i128 { i128::from_f32(a).unwrap() }
#[no_mangle]
pub extern fn muentry_uitofp_u128_float(a: u128) -> f32 { a.to_f32().unwrap() }
#[no_mangle]
pub extern fn muentry_sitofp_i128_float(a: i128) -> f32 { a.to_f32().unwrap() }
\ No newline at end of file
...@@ -24,23 +24,41 @@ begin_func swap_to_mu_stack ...@@ -24,23 +24,41 @@ begin_func swap_to_mu_stack
# -- on new stack -- # -- on new stack --
# arguments (reverse order of thread.rs - runtime_load_args) # arguments (reverse order of thread.rs - runtime_load_args)
pop_arguments pop_arguments
//enter_frame // Unncesary Note saves the return address of the function that called this function
# If entry tries to return (IT SHOULDN'T) it will return to entry_returned # If entry tries to return (IT SHOULDN'T) it will call entry_returned (which will panic!)
ADR LR, entry_returned ADR LR, entry_returned
# branch to entry # branch to entry
RET X9 RET X9
end_func swap_to_mu_stack end_func swap_to_mu_stack
# For debuging only, executes # The error message to print when entry returns
.type .Lentry_returned_message, @object
.section .rodata.str1.1,"aMS",@progbits,1
.Lentry_returned_message:
.asciz "ERROR: The entry function returned\n"
.size .Lentry_returned_message, 36
# Prints an error mesage and calls exit(1)
begin_func entry_returned begin_func entry_returned
HLT #0 ADRP x0, .Lentry_returned_message
end_func entry_returned ADD x0, x0, :lo12:.Lentry_returned_message // Loads x0 with the adress of .Lentry_returned_message
MOV X1, #35 // Length of string
MOV X2, #1 // Number of elements
ADRP X3, :got:stderr
LDR X3, [X3, :got_lo12:stderr]
LDR X3, [X3] // Load X3 with the address of stderr
BL fwrite // calls fwrite(x0, x1, x2, x3)
MOV W0, 1
BL exit // call exit(1)
end_func entry_returned
# _swap_back_to_native_stack(sp_loc: Address) // _swap_back_to_native_stack(sp_loc: Address)
# X0 // X0
begin_func muentry_swap_back_to_native_stack begin_func muentry_swap_back_to_native_stack
# SP = *sp_loc # SP = *sp_loc
LDR X9, [X0] LDR X9, [X0]
......
...@@ -127,6 +127,7 @@ impl MuStack { ...@@ -127,6 +127,7 @@ impl MuStack {
match reg_group { match reg_group {
RegGroup::GPR => gpr_used.push(word), RegGroup::GPR => gpr_used.push(word),
RegGroup::FPR => fpr_used.push(word), RegGroup::FPR => fpr_used.push(word),
RegGroup::GPREX => unimplemented!(),
} }
} }
......
...@@ -1291,4 +1291,96 @@ fn store_funcref() -> VM { ...@@ -1291,4 +1291,96 @@ fn store_funcref() -> VM {
}); });
vm vm
}
use test_compiler::test_int128::add_u128;
#[test]
fn test_call_int128_arg() {
VM::start_logging_trace();
let vm = Arc::new(add_u128());
call_add_u128(&vm);
let func_add = vm.id_of("add_u128");
let func_call = vm.id_of("call_add_u128");
let compiler = Compiler::new(CompilerPolicy::default(), &vm);
{
let funcs = vm.funcs().read().unwrap();
let func_vers = vm.func_vers().read().unwrap();
{
let func = funcs.get(&func_add).unwrap().read().unwrap();
let mut func_ver = func_vers.get(&func.cur_ver.unwrap()).unwrap().write().unwrap();
compiler.compile(&mut func_ver);
}
{
let func = funcs.get(&func_call).unwrap().read().unwrap();
let mut func_ver = func_vers.get(&func.cur_ver.unwrap()).unwrap().write().unwrap();
compiler.compile(&mut func_ver);
}
}
vm.make_primordial_thread(func_call, true, vec![]);
backend::emit_context(&vm);
let executable = aot::link_primordial(vec![Mu("add_u128"), Mu("call_add_u128")], "test_call_int128_arg", &vm);
let output = aot::execute_nocheck(executable);
// exit with (84)
assert!(output.status.code().is_some());
assert_eq!(output.status.code().unwrap(), 84);
}
fn call_add_u128(vm: &VM) {
let add_u128_sig = vm.get_func_sig(vm.id_of("sig"));
let add_u128_id = vm.id_of("add_u128");
typedef! ((vm) int64 = mu_int(64));
typedef! ((vm) int128 = mu_int(128));
constdef! ((vm) <int128> int128_42 = Constant::IntEx(vec![42, 0]));
typedef! ((vm) funcref_add_u128 = mu_funcref(add_u128_sig));
constdef! ((vm) <funcref_add_u128> const_funcref_add_u128 = Constant::FuncRef(add_u128_id));
funcsig! ((vm) call_add_u128_sig = () -> ());
funcdecl! ((vm) <call_add_u128_sig> call_add_u128);
funcdef! ((vm) <call_add_u128_sig> call_add_u128 VERSION call_add_u128_v1);
// blk_entry
block! ((vm, call_add_u128_v1) blk_entry);
// EXPRCALL add_u128 (42, 42)
ssa! ((vm, call_add_u128_v1) <int128> res);
consta! ((vm, call_add_u128_v1) int128_42_local = int128_42);
consta! ((vm, call_add_u128_v1) const_funcref_add_u128_local = const_funcref_add_u128);
inst! ((vm, call_add_u128_v1) blk_entry_call:
res = EXPRCALL (CallConvention::Mu, is_abort: false) const_funcref_add_u128_local (int128_42_local, int128_42_local)
);
ssa! ((vm, call_add_u128_v1) <int64> trunc_res);
inst! ((vm, call_add_u128_v1) blk_entry_trunc:
trunc_res = CONVOP (ConvOp::TRUNC) <int128 int64> res
);
let blk_entry_exit = gen_ccall_exit(trunc_res.clone(), &mut call_add_u128_v1, &vm);
inst! ((vm, call_add_u128_v1) blk_entry_ret:
RET
);
define_block!((vm, call_add_u128_v1) blk_entry() {
blk_entry_call,
blk_entry_trunc,
blk_entry_exit,
blk_entry_ret
});
define_func_ver!((vm) call_add_u128_v1 (entry: blk_entry) {
blk_entry
});
} }
\ No newline at end of file
...@@ -29,8 +29,8 @@ fn test_add_u128() { ...@@ -29,8 +29,8 @@ fn test_add_u128() {
} }
} }
fn add_u128() -> VM { pub fn add_u128() -> VM {
let vm = VM::new(); let vm = VM::new_with_opts("init_mu --disable-inline");
typedef! ((vm) u128 = mu_int(128)); typedef! ((vm) u128 = mu_int(128));
...@@ -61,6 +61,56 @@ fn add_u128() -> VM { ...@@ -61,6 +61,56 @@ fn add_u128() -> VM {
vm vm
} }
#[test]
fn test_sub_u128() {
let lib = testutil::compile_fnc("sub_u128", &sub_u128);