Commit e1844c8a authored by Isaac Oscar Gariano's avatar Isaac Oscar Gariano

Implemented NEWTHREAD on aarch64

parent ae1e02a5
...@@ -23,7 +23,7 @@ extern crate gcc; ...@@ -23,7 +23,7 @@ extern crate gcc;
fn main() { fn main() {
gcc::compile_library("libruntime_c.a", &["src/runtime/runtime_c_x64_sysv.c"]); gcc::compile_library("libruntime_c.a", &["src/runtime/runtime_c_x64_sysv.c"]);
gcc::Config::new() gcc::Build::new()
.flag("-O3") .flag("-O3")
.flag("-c") .flag("-c")
.file("src/runtime/runtime_asm_x64_sysv.S") .file("src/runtime/runtime_asm_x64_sysv.S")
...@@ -38,7 +38,7 @@ fn main() { ...@@ -38,7 +38,7 @@ fn main() {
fn main() { fn main() {
gcc::compile_library("libruntime_c.a", &["src/runtime/runtime_c_aarch64_sysv.c"]); gcc::compile_library("libruntime_c.a", &["src/runtime/runtime_c_aarch64_sysv.c"]);
gcc::Config::new() gcc::Build::new()
.flag("-O3") .flag("-O3")
.flag("-c") .flag("-c")
.file("src/runtime/runtime_asm_aarch64_sysv.S") .file("src/runtime/runtime_asm_aarch64_sysv.S")
...@@ -59,19 +59,19 @@ fn main() { ...@@ -59,19 +59,19 @@ fn main() {
use std::path::Path; use std::path::Path;
let mut compiler_name = String::new(); let mut compiler_name = String::new();
compiler_name.push_str("x86_64-rumprun-netbsd-gcc"); compiler_name.push_str("x86_64-rumprun-netbsd-gcc");
gcc::Config::new() gcc::Build::new()
.flag("-O3") .flag("-O3")
.flag("-c") .flag("-c")
.compiler(Path::new(compiler_name.as_str())) .compiler(Path::new(compiler_name.as_str()))
.file("src/runtime/runtime_x64_sel4_rumprun_sysv.c") .file("src/runtime/runtime_x64_sel4_rumprun_sysv.c")
.compile("libruntime_c.a"); .compile("libruntime_c.a");
gcc::Config::new() gcc::Build::new()
.flag("-O3") .flag("-O3")
.flag("-c") .flag("-c")
.compiler(Path::new(compiler_name.as_str())) .compiler(Path::new(compiler_name.as_str()))
.file("src/runtime/runtime_asm_x64_sel4_rumprun_sysv.S") .file("src/runtime/runtime_asm_x64_sel4_rumprun_sysv.S")
.compile("libruntime_asm.a"); .compile("libruntime_asm.a");
gcc::Config::new() gcc::Build::new()
.flag("-O3") .flag("-O3")
.flag("-c") .flag("-c")
.compiler(Path::new(compiler_name.as_str())) .compiler(Path::new(compiler_name.as_str()))
......
...@@ -92,8 +92,7 @@ impl Instruction { ...@@ -92,8 +92,7 @@ impl Instruction {
NewHybrid(_, _) | NewHybrid(_, _) |
AllocAHybrid(_, _) | AllocAHybrid(_, _) |
NewStack(_) | NewStack(_) |
NewThread(_, _) | NewThread{ .. } |
NewThreadExn(_, _) |
NewFrameCursor(_) | NewFrameCursor(_) |
GetIRef(_) | GetIRef(_) |
GetFieldIRef { .. } | GetFieldIRef { .. } |
...@@ -150,8 +149,7 @@ impl Instruction { ...@@ -150,8 +149,7 @@ impl Instruction {
NewHybrid(_, _) | NewHybrid(_, _) |
AllocAHybrid(_, _) | AllocAHybrid(_, _) |
NewStack(_) | NewStack(_) |
NewThread(_, _) | NewThread{ .. } |
NewThreadExn(_, _) |
NewFrameCursor(_) | NewFrameCursor(_) |
Fence(_) | Fence(_) |
Return(_) | Return(_) |
...@@ -228,8 +226,7 @@ impl Instruction { ...@@ -228,8 +226,7 @@ impl Instruction {
NewHybrid(_, _) | NewHybrid(_, _) |
AllocAHybrid(_, _) | AllocAHybrid(_, _) |
NewStack(_) | NewStack(_) |
NewThread(_, _) | NewThread{ .. } |
NewThreadExn(_, _) |
NewFrameCursor(_) | NewFrameCursor(_) |
GetIRef(_) | GetIRef(_) |
GetFieldIRef { .. } | GetFieldIRef { .. } |
...@@ -301,8 +298,7 @@ impl Instruction { ...@@ -301,8 +298,7 @@ impl Instruction {
NewHybrid(_, _) | NewHybrid(_, _) |
AllocAHybrid(_, _) | AllocAHybrid(_, _) |
NewStack(_) | NewStack(_) |
NewThread(_, _) | NewThread{ .. } |
NewThreadExn(_, _) |
NewFrameCursor(_) | NewFrameCursor(_) |
GetIRef(_) | GetIRef(_) |
GetFieldIRef { .. } | GetFieldIRef { .. } |
...@@ -459,11 +455,12 @@ pub enum Instruction_ { ...@@ -459,11 +455,12 @@ pub enum Instruction_ {
/// create a new Mu thread, yields thread reference /// create a new Mu thread, yields thread reference
/// args: stackref of a Mu stack, a list of arguments /// args: stackref of a Mu stack, a list of arguments
NewThread(OpIndex, Vec<OpIndex>), // stack, args NewThread {
stack: OpIndex,
/// create a new Mu thread, yields thread reference (thread resumes with exceptional value) thread_local: Option<OpIndex>,
/// args: stackref of a Mu stack, an exceptional value is_exception: bool,
NewThreadExn(OpIndex, OpIndex), // stack, exception args: Vec<OpIndex>
},
/// create a frame cursor reference /// create a frame cursor reference
/// args: stackref of a Mu stack /// args: stackref of a Mu stack
...@@ -724,16 +721,16 @@ impl Instruction_ { ...@@ -724,16 +721,16 @@ impl Instruction_ {
&Instruction_::NewHybrid(ref ty, len) => format!("NEWHYBRID {} {}", ty, ops[len]), &Instruction_::NewHybrid(ref ty, len) => format!("NEWHYBRID {} {}", ty, ops[len]),
&Instruction_::AllocAHybrid(ref ty, len) => format!("ALLOCAHYBRID {} {}", ty, ops[len]), &Instruction_::AllocAHybrid(ref ty, len) => format!("ALLOCAHYBRID {} {}", ty, ops[len]),
&Instruction_::NewStack(func) => format!("NEW_STACK {}", ops[func]), &Instruction_::NewStack(func) => format!("NEW_STACK {}", ops[func]),
&Instruction_::NewThread(stack, ref args) => { &Instruction_::NewThread{stack, thread_local, is_exception, ref args} => {
let thread_local = thread_local.map(|t| format!("{}", ops[t])).unwrap_or("NULL".to_string());
format!( format!(
"NEWTHREAD {} PASS_VALUES {}", "SWAPSTACK {} THREADLOCAL({}) {} {}",
ops[stack], ops[stack],
op_vector_str(args, ops) thread_local,
is_exception,
op_vector_str(args, ops),
) )
} }
&Instruction_::NewThreadExn(stack, exn) => {
format!("NEWTHREAD {} THROW_EXC {}", ops[stack], ops[exn])
}
&Instruction_::NewFrameCursor(stack) => format!("NEWFRAMECURSOR {}", ops[stack]), &Instruction_::NewFrameCursor(stack) => format!("NEWFRAMECURSOR {}", ops[stack]),
&Instruction_::GetIRef(reference) => format!("GETIREF {}", ops[reference]), &Instruction_::GetIRef(reference) => format!("GETIREF {}", ops[reference]),
&Instruction_::GetFieldIRef { &Instruction_::GetFieldIRef {
......
...@@ -1813,9 +1813,8 @@ impl<'a> InstructionSelection { ...@@ -1813,9 +1813,8 @@ impl<'a> InstructionSelection {
CALLER_SAVED_REGS.to_vec(), CALLER_SAVED_REGS.to_vec(),
true true
); );
// Record the callsitte
self.current_callsites self.record_callsite(None, callsite.unwrap(), 0);
.push_back((callsite.unwrap().to_relocatable(), 0, 0));
} }
// Runtime Entry // Runtime Entry
...@@ -2142,6 +2141,77 @@ impl<'a> InstructionSelection { ...@@ -2142,6 +2141,77 @@ impl<'a> InstructionSelection {
vm vm
); );
} }
Instruction_::NewThread{stack, thread_local, is_exception, ref args} => {
trace!("Instruction Selection on NEWTHREAD");
let ref ops = inst.ops;
let res = self.get_result_value(node, 0);
let stack = self.emit_ireg(&*ops[stack], f_content, f_context, vm);
let tl = match thread_local {
Some(op) => self.emit_ireg(&*ops[op], f_content, f_context, vm),
None => make_value_nullref(vm)
};
if is_exception {
let exc = self.emit_ireg(&*ops[args[0]], f_content, f_context, vm);
self.emit_runtime_entry(
&entrypoints::NEW_THREAD_EXCEPTIONAL,
vec![stack, tl, exc],
Some(vec![res.clone()]),
Some(node),
f_context,
vm
);
} else {
// Load the new stack pointer
let new_sp = make_temporary(f_context, ADDRESS_TYPE.clone(), vm);
emit_load_base_offset(
self.backend.as_mut(),
&new_sp,
&stack,
*thread::MUSTACK_SP_OFFSET as i64,
f_context,
vm
);
let arg_values = self.emit_arg_values(&args, ops, f_content, f_context, vm);
// Pass the arguments, stack arguments are placed below the new_sp,
// register arguments are placed above it
self.emit_precall_convention(
&new_sp,
// The frame contains space for the FP and LR
(2 * POINTER_SIZE) as isize,
false,
&arg_values,
&arg_values.iter().map(|a| a.ty.clone()).collect::<Vec<_>>(),
0,
false,
true,
true,
Some(&new_sp),
f_context,
vm
);
emit_sub_u64(self.backend.as_mut(), &new_sp, &new_sp, (ARGUMENT_REG_COUNT*WORD_SIZE) as u64);
emit_store_base_offset(
self.backend.as_mut(),
&stack,
*thread::MUSTACK_SP_OFFSET as i64,
&new_sp,
f_context,
vm
);
self.emit_runtime_entry(
&entrypoints::NEW_THREAD_NORMAL,
vec![stack, tl],
Some(vec![res.clone()]),
Some(node),
f_context,
vm
);
}
}
_ => unimplemented!() _ => unimplemented!()
} // main switch } // main switch
} }
...@@ -3808,6 +3878,7 @@ impl<'a> InstructionSelection { ...@@ -3808,6 +3878,7 @@ impl<'a> InstructionSelection {
modify_arg_base: bool, modify_arg_base: bool,
reg_args: bool, // Whether to pass register arguments reg_args: bool, // Whether to pass register arguments
stack_args: bool, // Whether to pass stack arguments stack_args: bool, // Whether to pass stack arguments
reg_arg_base: Option<&P<Value>>, // If this is none put reg arguments in registers, otherwise store them at an offset from reg_arg_base
f_context: &mut FunctionContext, f_context: &mut FunctionContext,
vm: &VM vm: &VM
) -> (usize, Vec<P<Value>>) { ) -> (usize, Vec<P<Value>>) {
...@@ -3869,12 +3940,21 @@ impl<'a> InstructionSelection { ...@@ -3869,12 +3940,21 @@ impl<'a> InstructionSelection {
let arg_val = let arg_val =
emit_reg_value(self.backend.as_mut(), &arg_val, f_context, vm); emit_reg_value(self.backend.as_mut(), &arg_val, f_context, vm);
let (val_l, val_h) = split_int128(&arg_val, f_context, vm); let (val_l, val_h) = split_int128(&arg_val, f_context, vm);
let arg_loc_h = get_register_from_id(arg_loc.id() + 2);
let arg_loc_h_id = arg_loc.id() + 2; //get_register_from_id();
let (arg_loc_l, arg_loc_h) = match reg_arg_base {
Some(ref b) => (
make_value_base_offset(b, get_argument_reg_offset(arg_loc.id()) as i64, &arg_loc.ty, vm),
make_value_base_offset(b, get_argument_reg_offset(arg_loc_h_id) as i64, &arg_loc.ty, vm)
),
None => (arg_loc.clone(), get_register_from_id(arg_loc_h_id))
};
arg_regs.push(arg_loc_h.clone()); arg_regs.push(arg_loc_h.clone());
emit_move_value_to_value( emit_move_value_to_value(
self.backend.as_mut(), self.backend.as_mut(),
&arg_loc, &arg_loc_l,
&val_l, &val_l,
f_context, f_context,
vm vm
...@@ -3888,6 +3968,11 @@ impl<'a> InstructionSelection { ...@@ -3888,6 +3968,11 @@ impl<'a> InstructionSelection {
); );
} else { } else {
if (reg_args && arg_loc.is_reg()) || (stack_args && !arg_loc.is_reg()) { if (reg_args && arg_loc.is_reg()) || (stack_args && !arg_loc.is_reg()) {
let arg_loc = match reg_arg_base {
Some(ref b) if arg_loc.is_reg() => make_value_base_offset(b, get_argument_reg_offset(arg_loc.id()) as i64, &arg_loc.ty, vm),
_ => arg_loc.clone(),
};
emit_move_value_to_value( emit_move_value_to_value(
self.backend.as_mut(), self.backend.as_mut(),
&arg_loc, &arg_loc,
...@@ -4230,6 +4315,7 @@ impl<'a> InstructionSelection { ...@@ -4230,6 +4315,7 @@ impl<'a> InstructionSelection {
true, true,
true, true,
true, true,
None,
f_context, f_context,
vm vm
); );
...@@ -4274,22 +4360,10 @@ impl<'a> InstructionSelection { ...@@ -4274,22 +4360,10 @@ impl<'a> InstructionSelection {
) )
} }
#[allow(unused_variables)] // resumption not implemented fn emit_arg_values(&mut self, args: &Vec<OpIndex>, ops: &Vec<P<TreeNode>>, f_content: &FunctionContent, f_context: &mut FunctionContext, vm: &VM) -> Vec<P<Value>> {
fn emit_c_call_ir(
&mut self,
inst: &Instruction,
calldata: &CallData,
resumption: Option<&ResumptionData>,
cur_node: &TreeNode,
f_content: &FunctionContent,
f_context: &mut FunctionContext,
vm: &VM
) {
let ref ops = inst.ops;
// prepare args (they could be instructions, we need to emit inst and get value) // prepare args (they could be instructions, we need to emit inst and get value)
let mut arg_values = vec![]; let mut arg_values = vec![];
for arg_index in calldata.args.iter() { for arg_index in args {
let ref arg = ops[*arg_index]; let ref arg = ops[*arg_index];
if match_node_imm(arg) { if match_node_imm(arg) {
...@@ -4302,7 +4376,23 @@ impl<'a> InstructionSelection { ...@@ -4302,7 +4376,23 @@ impl<'a> InstructionSelection {
unimplemented!(); unimplemented!();
} }
} }
let arg_values = arg_values; arg_values
}
#[allow(unused_variables)] // resumption not implemented
fn emit_c_call_ir(
&mut self,
inst: &Instruction,
calldata: &CallData,
resumption: Option<&ResumptionData>,
cur_node: &TreeNode,
f_content: &FunctionContent,
f_context: &mut FunctionContext,
vm: &VM
) {
let ref ops = inst.ops;
let arg_values = self.emit_arg_values(&calldata.args, ops, f_content, f_context, vm);
trace!("generating ccall"); trace!("generating ccall");
let ref func = ops[calldata.func]; let ref func = ops[calldata.func];
...@@ -4368,18 +4458,7 @@ impl<'a> InstructionSelection { ...@@ -4368,18 +4458,7 @@ impl<'a> InstructionSelection {
}; };
// Compute all the arguments... // Compute all the arguments...
let mut arg_values = vec![]; let mut arg_values = self.emit_arg_values(&args, ops, f_content, f_context, vm);
let arg_nodes = args.iter().map(|a| ops[*a].clone()).collect::<Vec<_>>();
for ref arg in &arg_nodes {
if match_node_imm(arg) {
arg_values.push(node_imm_to_value(arg))
} else if self.match_reg(arg) {
arg_values.push(self.emit_reg(arg, f_content, f_context, vm))
} else {
unimplemented!()
};
}
let tl = self.emit_get_threadlocal(f_context, vm); let tl = self.emit_get_threadlocal(f_context, vm);
let cur_stackref = make_temporary(f_context, STACKREF_TYPE.clone(), vm); let cur_stackref = make_temporary(f_context, STACKREF_TYPE.clone(), vm);
...@@ -4461,7 +4540,7 @@ impl<'a> InstructionSelection { ...@@ -4461,7 +4540,7 @@ impl<'a> InstructionSelection {
let arg_tys = arg_values.iter().map(|a| a.ty.clone()).collect::<Vec<_>>(); let arg_tys = arg_values.iter().map(|a| a.ty.clone()).collect::<Vec<_>>();
// Pass stack arguments before the old stack is killed // Pass stack arguments before the old stack is killed
let (stack_arg_size, _) = self.emit_precall_convention( self.emit_precall_convention(
&SP, &SP,
// The frame contains space for the FP and LR // The frame contains space for the FP and LR
(2 * POINTER_SIZE) as isize, (2 * POINTER_SIZE) as isize,
...@@ -4472,6 +4551,7 @@ impl<'a> InstructionSelection { ...@@ -4472,6 +4551,7 @@ impl<'a> InstructionSelection {
false, false,
false, // don't pass reg args false, // don't pass reg args
true, // pass stack args true, // pass stack args
None,
f_context, f_context,
vm vm
); );
...@@ -4500,6 +4580,7 @@ impl<'a> InstructionSelection { ...@@ -4500,6 +4580,7 @@ impl<'a> InstructionSelection {
false, false,
true, // don't pass stack args true, // don't pass stack args
false, // pass reg args false, // pass reg args
None,
f_context, f_context,
vm vm
); );
...@@ -4518,14 +4599,7 @@ impl<'a> InstructionSelection { ...@@ -4518,14 +4599,7 @@ impl<'a> InstructionSelection {
self.backend.emit_pop_pair(&FP, &LR, &SP); self.backend.emit_pop_pair(&FP, &LR, &SP);
} }
let potentially_excepting = { let potentially_excepting = Self::get_potentially_excepting(resumption, f_content);
if resumption.is_some() {
let target_id = resumption.unwrap().exn_dest.target;
Some(f_content.get_block(target_id).name())
} else {
None
}
};
// Call the function that swaps the stack // Call the function that swaps the stack
let callsite = { let callsite = {
...@@ -4556,21 +4630,9 @@ impl<'a> InstructionSelection { ...@@ -4556,21 +4630,9 @@ impl<'a> InstructionSelection {
} }
}; };
if resumption.is_some() {
let ref exn_dest = resumption.as_ref().unwrap().exn_dest;
let target_block = exn_dest.target;
self.current_callsites.push_back((
callsite.unwrap().to_relocatable(),
target_block,
stack_arg_size
));
} else if !is_kill {
self.current_callsites
.push_back((callsite.unwrap().to_relocatable(), 0, stack_arg_size));
}
if !is_kill { if !is_kill {
self.record_callsite(resumption, callsite.unwrap(), res_stack_size);
if resumption.is_some() { if resumption.is_some() {
self.finish_block(); self.finish_block();
let block_name = make_block_name(&node.name(), "stack_resumption"); let block_name = make_block_name(&node.name(), "stack_resumption");
...@@ -4582,6 +4644,28 @@ impl<'a> InstructionSelection { ...@@ -4582,6 +4644,28 @@ impl<'a> InstructionSelection {
} }
} }
fn get_potentially_excepting(resumption: Option<&ResumptionData>, f_content: &FunctionContent) -> Option<MuName> {
if resumption.is_some() {
let target_id = resumption.unwrap().exn_dest.target;
Some(f_content.get_block(target_id).name())
} else {
None
}
}
fn record_callsite(&mut self, resumption: Option<&ResumptionData>, callsite: ValueLocation, stack_arg_size: usize) {
let target_block = match resumption {
Some(rd) => rd.exn_dest.target,
None => 0
};
self.current_callsites.push_back((
callsite.to_relocatable(),
target_block,
stack_arg_size
));
}
fn emit_mu_call( fn emit_mu_call(
&mut self, &mut self,
is_tail: bool, // For tail calls is_tail: bool, // For tail calls
...@@ -4625,20 +4709,7 @@ impl<'a> InstructionSelection { ...@@ -4625,20 +4709,7 @@ impl<'a> InstructionSelection {
} }
// prepare args (they could be instructions, we need to emit inst and get value) // prepare args (they could be instructions, we need to emit inst and get value)
let mut arg_values = vec![]; let arg_values = self.emit_arg_values(&calldata.args, ops, f_content, f_context, vm);
for arg_index in calldata.args.iter() {
let ref arg = ops[*arg_index];
if match_node_imm(arg) {
let arg = node_imm_to_value(arg);
arg_values.push(arg);
} else if self.match_reg(arg) {
let arg = self.emit_reg(arg, f_content, f_context, vm);
arg_values.push(arg);
} else {
unimplemented!();
}
}
let return_type = self.combine_return_types(&func_sig, vm); let return_type = self.combine_return_types(&func_sig, vm);
let return_size = self.compute_return_allocation(&return_type, &vm); let return_size = self.compute_return_allocation(&return_type, &vm);
let (stack_arg_size, arg_regs) = self.emit_precall_convention( let (stack_arg_size, arg_regs) = self.emit_precall_convention(
...@@ -4651,19 +4722,13 @@ impl<'a> InstructionSelection { ...@@ -4651,19 +4722,13 @@ impl<'a> InstructionSelection {
!is_tail, !is_tail,
true, true,
true, true,
None,
f_context, f_context,
vm vm
); );
// check if this call has exception clause - need to tell backend about this // check if this call has exception clause - need to tell backend about this
let potentially_excepting = { let potentially_excepting = Self::get_potentially_excepting(resumption, f_content);
if resumption.is_some() {
let target_id = resumption.unwrap().exn_dest.target;
Some(f_content.get_block(target_id).name())
} else {
None
}
};
if is_tail { if is_tail {
// Restore callee saved registers and pop the frame // Restore callee saved registers and pop the frame
...@@ -4723,17 +4788,7 @@ impl<'a> InstructionSelection { ...@@ -4723,17 +4788,7 @@ impl<'a> InstructionSelection {
} }
}; };
// record exception branch self.record_callsite(resumption, callsite, stack_arg_size);
if resumption.is_some() {
let ref exn_dest = resumption.as_ref().unwrap().exn_dest;
let target_block = exn_dest.target;
self.current_callsites
.push_back((callsite.to_relocatable(), target_block, stack_arg_size));
} else {
self.current_callsites
.push_back((callsite.to_relocatable(), 0, stack_arg_size));
}
// deal with ret vals // deal with ret vals
self.emit_postcall_convention( self.emit_postcall_convention(
......
...@@ -53,6 +53,7 @@ use std::collections::HashMap; ...@@ -53,6 +53,7 @@ use std::collections::HashMap;
// Number of nromal callee saved registers (excluding FP and LR, and SP) // Number of nromal callee saved registers (excluding FP and LR, and SP)
pub const CALLEE_SAVED_COUNT: usize = 18; pub const CALLEE_SAVED_COUNT: usize = 18;
pub const ARGUMENT_REG_COUNT: usize = 16;
macro_rules! REGISTER { macro_rules! REGISTER {
($id:expr, $name: expr, $ty: ident) => { ($id:expr, $name: expr, $ty: ident) => {
...@@ -885,18 +886,18 @@ pub fn get_callee_saved_offset(reg: MuID) -> isize { ...@@ -885,18 +886,18 @@ pub fn get_callee_saved_offset(reg: MuID) -> isize {
(id as isize + 1) * (-8) (id as isize + 1) * (-8)
} }
// Returns the callee saved register with the id... // Gets the offset of the argument register when passed on the stack
/*pub fn get_callee_saved_register(offset: isize) -> P<Value> { pub fn get_argument_reg_offset(reg: MuID) -> isize {
debug_assert!(offset <= -8 && (-offset) % 8 == 0); let reg = get_color_for_precolored(reg);
let id = ((offset/-8) - 1) as usize;
if id < CALLEE_SAVED_GPRs.len() { let id = if reg >= FPR_ID_START {
CALLEE_SAVED_GPRs[id].clone() (reg - ARGUMENT_FPRS[0].id()) / 2
} else if id - CALLEE_SAVED_GPRs.len() < CALLEE_SAVED_FPRs.len() {
CALLEE_SAVED_FPRs[id - CALLEE_SAVED_GPRs.len()].clone()
} else { } else {
panic!("There is no callee saved register with id {}", offset) (reg - ARGUMENT_GPRS[0].id()) / 2 + ARGUMENT_FPRS.len()
} };
}*/
(id as isize + 1) * (-8)
}
pub fn is_callee_saved(reg_id: MuID) -> bool { pub fn is_callee_saved(reg_id: MuID) -> bool {
for reg in CALLEE_SAVED_GPRS.iter() { for reg in CALLEE_SAVED_GPRS.iter() {
...@@ -959,7 +960,7 @@ pub fn estimate_insts_for_ir(inst: &Instruction) -> usize { ...@@ -959,7 +960,7 @@ pub fn estimate_insts_for_ir(inst: &Instruction) -> usize {
// runtime // runtime
New(_) | NewHybrid(_, _) => 10, New(_) | NewHybrid(_, _) => 10,
NewStack(_) | NewThread(_, _) | NewThreadExn(_, _) | NewFrameCursor(_) => 10, NewStack(_) | NewThread { .. } | NewFrameCursor(_) => 10,
ThreadExit => 10, ThreadExit => 10,
CurrentStack => 10, CurrentStack => 10,
KillStack(_) => 10, KillStack(_) => 10,
...@@ -1526,6 +1527,14 @@ pub fn make_value_int_const(val: u64, vm: &VM) -> P<Value> { ...@@ -1526,6 +1527,14 @@ pub fn make_value_int_const(val: u64, vm: &VM) -> P<Value> {
}) })
} }
pub fn make_value_nullref(vm: &VM) -> P<Value> {
P(Value {
hdr: MuEntityHeader::unnamed(vm.next_id()),
ty: REF_VOID_TYPE.clone(),
v: Value_::Constant(Constant::NullRef)
})
}