Commit 841d47a1 authored by Yi Lin's avatar Yi Lin

Merge branch 'aarch64' into 'master'

Merge aarch64 into master

See merge request !10
parents 99a65c69 f9dcc877
Pipeline #573 passed with stages
in 58 minutes and 36 seconds
......@@ -21,6 +21,7 @@ ast = {path = "src/ast"}
utils = {path = "src/utils"}
gc = {path = "src/gc"}
field-offset = "0.1.1"
libloading = "0.3"
lazy_static = "0.1.15"
......@@ -34,4 +35,5 @@ time = "0.1.34"
maplit = "0.1.4"
docopt = "0.6"
petgraph = "0.4.1"
extprim = "*"
\ No newline at end of file
extprim = "*"
num-traits = "*"
......@@ -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 {
match self.v {
Value_::Constant(Constant::Int(_)) => true,
......@@ -742,7 +750,13 @@ impl Value {
_ => 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 {
match self.v {
Value_::Constant(Constant::Int(val)) => val,
......@@ -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> {
match self.v {
Value_::SSAVar(id) => Some(id),
......
......@@ -210,7 +210,7 @@ impl CmpOp {
FUGT => FULT,
FULT => FUGT,
_ => self, // all other comparisons are reflexive
_ => self, // all other comparisons are symmetric
}
}
pub fn invert(self) -> CmpOp {
......@@ -256,6 +256,18 @@ impl CmpOp {
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 {
use op::CmpOp::*;
match self {
......@@ -263,6 +275,14 @@ impl CmpOp {
_ => 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)]
......
......@@ -23,8 +23,10 @@ pub trait CodeGenerator {
fn end_block(&mut self, block_name: MuName);
// add CFI info
fn add_cfi_sections(&mut self, arg: &str);
fn add_cfi_startproc(&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_offset(&mut self, offset: i32);
fn add_cfi_offset(&mut self, reg: Reg, offset: i32);
......@@ -35,6 +37,10 @@ pub trait CodeGenerator {
fn emit_frame_grow(&mut self); // Emits a SUB
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
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
......
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 {
base: aarch64::FP.clone(),
offset: Some(Value::make_int_const(vm.next_id(), self.offset as u64)),
scale: 1,
signed: false
signed: true
}
)
})
......
......@@ -132,8 +132,8 @@ lazy_static! {
pub static ref UDIV_U128 : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![UINT64_TYPE.clone(); 2],
arg_tys: vec![UINT64_TYPE.clone(); 4]
ret_tys: vec![UINT128_TYPE.clone(); 1],
arg_tys: vec![UINT128_TYPE.clone(); 2]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_udiv_u128")),
jit: RwLock::new(None)
......@@ -142,8 +142,8 @@ lazy_static! {
pub static ref SDIV_I128 : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![UINT64_TYPE.clone(); 2],
arg_tys: vec![UINT64_TYPE.clone(); 4]
ret_tys: vec![UINT128_TYPE.clone(); 1],
arg_tys: vec![UINT128_TYPE.clone(); 2]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_sdiv_i128")),
jit: RwLock::new(None)
......@@ -152,8 +152,8 @@ lazy_static! {
pub static ref UREM_U128 : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![UINT64_TYPE.clone(); 2],
arg_tys: vec![UINT64_TYPE.clone(); 4]
ret_tys: vec![UINT128_TYPE.clone(); 1],
arg_tys: vec![UINT128_TYPE.clone(); 2]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_urem_u128")),
jit: RwLock::new(None)
......@@ -162,13 +162,92 @@ lazy_static! {
pub static ref SREM_I128 : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
hdr: MuEntityHeader::unnamed(ir::new_internal_id()),
ret_tys: vec![UINT64_TYPE.clone(); 2],
arg_tys: vec![UINT64_TYPE.clone(); 4]
ret_tys: vec![UINT128_TYPE.clone(); 1],
arg_tys: vec![UINT128_TYPE.clone(); 2]
}),
aot: ValueLocation::Relocatable(RegGroup::GPR, String::from("muentry_srem_i128")),
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
pub static ref PRINT_HEX : RuntimeEntrypoint = RuntimeEntrypoint {
sig: P(MuFuncSig {
......
......@@ -14,29 +14,46 @@ pub extern fn muentry_frem64(a: f64, b: f64) -> f64 {
a.rem(b)
}
extern crate num_traits;
use extprim::u128::u128;
use extprim::i128::i128;
use runtime::math::num_traits::ToPrimitive;
use runtime::math::num_traits::FromPrimitive;
#[no_mangle]
#[allow(unreachable_code)]
pub extern fn muentry_udiv_u128(a: u128, b: u128) -> u128 {
a.wrapping_div(b)
}
#[no_mangle]
#[allow(unreachable_code)]
pub extern fn muentry_sdiv_i128(a: i128, b: i128) -> i128 {
a.wrapping_div(b)
}
#[no_mangle]
#[allow(unreachable_code)]
pub extern fn muentry_urem_u128(a: u128, b: u128) -> u128 {
a.wrapping_rem(b)
}
#[no_mangle]
#[allow(unreachable_code)]
pub extern fn muentry_srem_i128(a: i128, b: i128) -> i128 {
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
# -- on new stack --
# arguments (reverse order of thread.rs - runtime_load_args)
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
# branch to entry
RET X9
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
HLT #0
end_func entry_returned
ADRP x0, .Lentry_returned_message
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)
# X0
// _swap_back_to_native_stack(sp_loc: Address)
// X0
begin_func muentry_swap_back_to_native_stack
# SP = *sp_loc
LDR X9, [X0]
......
......@@ -127,6 +127,7 @@ impl MuStack {
match reg_group {
RegGroup::GPR => gpr_used.push(word),
RegGroup::FPR => fpr_used.push(word),
RegGroup::GPREX => unimplemented!(),
}
}
......
......@@ -1291,4 +1291,96 @@ fn store_funcref() -> 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() {
}
}
fn add_u128() -> VM {
let vm = VM::new();
pub fn add_u128() -> VM {
let vm = VM::new_with_opts("init_mu --disable-inline");
typedef! ((vm) u128 = mu_int(128));
......@@ -61,6 +61,56 @@ fn add_u128() -> VM {
vm
}
#[test]
fn test_sub_u128() {
let lib = testutil::compile_fnc("sub_u128", &sub_u128);
unsafe {
use std::u64;
let sub_u128 : libloading::Symbol<unsafe extern fn(u64, u64, u64, u64) -> (u64, u64)> = lib.get(b"sub_u128").unwrap();
let res = sub_u128(1, 0, 1, 0);
println!("sub_u128(1, 1) = {:?}", res);
assert!(res == (0, 0));
let res = sub_u128(u64::MAX, 0, u64::MAX, u64::MAX);
println!("sub_u128(u64::MAX, -1) = {:?}", res);
assert!(res == (0, 1));
}
}
fn sub_u128() -> VM {
let vm = VM::new();
typedef! ((vm) u128 = mu_int(128));
funcsig! ((vm) sig = (u128, u128) -> (u128));
funcdecl! ((vm) <sig> sub_u128);
funcdef! ((vm) <sig> sub_u128 VERSION sub_u128_v1);
block! ((vm, sub_u128_v1) blk_entry);
ssa! ((vm, sub_u128_v1) <u128> a);
ssa! ((vm, sub_u128_v1) <u128> b);
// sum = sub %a %b
ssa! ((vm, sub_u128_v1) <u128> sum);
inst! ((vm, sub_u128_v1) blk_entry_sub_u128:
sum = BINOP (BinOp::Sub) a b
);
inst! ((vm, sub_u128_v1) blk_entry_ret:
RET (sum)
);
define_block! ((vm, sub_u128_v1) blk_entry(a, b) {
blk_entry_sub_u128, blk_entry_ret
});
define_func_ver!((vm) sub_u128_v1 (entry: blk_entry) {blk_entry});
vm
}
#[test]
fn test_add_const_u128() {
let lib = testutil::compile_fnc("add_const_u128", &add_const_u128);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment