diff --git a/lib/cretonne/src/ir/function.rs b/lib/cretonne/src/ir/function.rs index 95b6458558..0c86ac66e0 100644 --- a/lib/cretonne/src/ir/function.rs +++ b/lib/cretonne/src/ir/function.rs @@ -7,6 +7,8 @@ use entity::{PrimaryMap, EntityMap}; use ir; use ir::{FunctionName, CallConv, Signature, DataFlowGraph, Layout}; use ir::{InstEncodings, ValueLocations, JumpTables, StackSlots, EbbOffsets}; +use ir::{Ebb, JumpTableData, JumpTable, StackSlotData, StackSlot, SigRef, ExtFuncData, FuncRef, + GlobalVarData, GlobalVar, HeapData, Heap}; use isa::TargetIsa; use std::fmt; use write::write_function; @@ -93,6 +95,42 @@ impl Function { Self::with_name_signature(FunctionName::default(), Signature::new(CallConv::Native)) } + /// Creates a jump table in the function, to be used by `br_table` instructions. + pub fn create_jump_table(&mut self, data: JumpTableData) -> JumpTable { + self.jump_tables.push(data) + } + + /// Inserts an entry in a previously declared jump table. + pub fn insert_jump_table_entry(&mut self, jt: JumpTable, index: usize, ebb: Ebb) { + self.jump_tables[jt].set_entry(index, ebb); + } + + /// Creates a stack slot in the function, to be used by `stack_load`, `stack_store` and + /// `stack_addr` instructions. + pub fn create_stack_slot(&mut self, data: StackSlotData) -> StackSlot { + self.stack_slots.push(data) + } + + /// Adds a signature which can later be used to declare an external function import. + pub fn import_signature(&mut self, signature: Signature) -> SigRef { + self.dfg.signatures.push(signature) + } + + /// Declare an external function import. + pub fn import_function(&mut self, data: ExtFuncData) -> FuncRef { + self.dfg.ext_funcs.push(data) + } + + /// Declares a global variable accessible to the function. + pub fn create_global_var(&mut self, data: GlobalVarData) -> GlobalVar { + self.global_vars.push(data) + } + + /// Declares a heap accessible to the function. + pub fn create_heap(&mut self, data: HeapData) -> Heap { + self.heaps.push(data) + } + /// Return an object that can display this function with correct ISA-specific annotations. pub fn display<'a, I: Into>>(&'a self, isa: I) -> DisplayFunction<'a> { DisplayFunction(self, isa.into()) diff --git a/lib/cretonne/src/ir/jumptable.rs b/lib/cretonne/src/ir/jumptable.rs index 5e34d07c4d..6d97341458 100644 --- a/lib/cretonne/src/ir/jumptable.rs +++ b/lib/cretonne/src/ir/jumptable.rs @@ -46,6 +46,11 @@ impl JumpTableData { self.table[idx] = dest.into(); } + /// Append a table entry. + pub fn push_entry(&mut self, dest: Ebb) { + self.table.push(dest.into()) + } + /// Clear a table entry. /// /// The `br_table` instruction will fall through if given an index corresponding to a cleared diff --git a/lib/cretonne/src/ir/stackslot.rs b/lib/cretonne/src/ir/stackslot.rs index effa65a25e..e5a4b10161 100644 --- a/lib/cretonne/src/ir/stackslot.rs +++ b/lib/cretonne/src/ir/stackslot.rs @@ -255,14 +255,8 @@ mod tests { fn stack_slot() { let mut func = Function::new(); - let ss0 = func.stack_slots.push(StackSlotData::new( - StackSlotKind::IncomingArg, - 4, - )); - let ss1 = func.stack_slots.push(StackSlotData::new( - StackSlotKind::SpillSlot, - 8, - )); + let ss0 = func.create_stack_slot(StackSlotData::new(StackSlotKind::IncomingArg, 4)); + let ss1 = func.create_stack_slot(StackSlotData::new(StackSlotKind::SpillSlot, 8)); assert_eq!(ss0.to_string(), "ss0"); assert_eq!(ss1.to_string(), "ss1"); diff --git a/lib/cretonne/src/write.rs b/lib/cretonne/src/write.rs index f69586b2ea..77f0209da3 100644 --- a/lib/cretonne/src/write.rs +++ b/lib/cretonne/src/write.rs @@ -395,9 +395,7 @@ mod tests { f.name = FunctionName::new("foo"); assert_eq!(f.to_string(), "function %foo() native {\n}\n"); - f.stack_slots.push( - StackSlotData::new(StackSlotKind::Local, 4), - ); + f.create_stack_slot(StackSlotData::new(StackSlotKind::Local, 4)); assert_eq!( f.to_string(), "function %foo() native {\n ss0 = local 4\n}\n" diff --git a/lib/frontend/src/frontend.rs b/lib/frontend/src/frontend.rs index 4f6d4ef640..00e6377897 100644 --- a/lib/frontend/src/frontend.rs +++ b/lib/frontend/src/frontend.rs @@ -2,7 +2,7 @@ use cretonne::cursor::{Cursor, FuncCursor}; use cretonne::ir::{Ebb, Type, Value, Function, Inst, JumpTable, StackSlot, JumpTableData, StackSlotData, DataFlowGraph, InstructionData, ExtFuncData, FuncRef, SigRef, - Signature, InstBuilderBase}; + Signature, InstBuilderBase, GlobalVarData, GlobalVar, HeapData, Heap}; use cretonne::ir::instructions::BranchInfo; use cretonne::ir::function::DisplayFunction; use cretonne::isa::TargetIsa; @@ -329,29 +329,39 @@ where } /// Creates a jump table in the function, to be used by `br_table` instructions. - pub fn create_jump_table(&mut self) -> JumpTable { - self.func.jump_tables.push(JumpTableData::new()) + pub fn create_jump_table(&mut self, data: JumpTableData) -> JumpTable { + self.func.create_jump_table(data) } /// Inserts an entry in a previously declared jump table. pub fn insert_jump_table_entry(&mut self, jt: JumpTable, index: usize, ebb: Ebb) { - self.func.jump_tables[jt].set_entry(index, ebb); + self.func.insert_jump_table_entry(jt, index, ebb) } /// Creates a stack slot in the function, to be used by `stack_load`, `stack_store` and /// `stack_addr` instructions. pub fn create_stack_slot(&mut self, data: StackSlotData) -> StackSlot { - self.func.stack_slots.push(data) + self.func.create_stack_slot(data) } /// Adds a signature which can later be used to declare an external function import. pub fn import_signature(&mut self, signature: Signature) -> SigRef { - self.func.dfg.signatures.push(signature) + self.func.import_signature(signature) } /// Declare an external function import. pub fn import_function(&mut self, data: ExtFuncData) -> FuncRef { - self.func.dfg.ext_funcs.push(data) + self.func.import_function(data) + } + + /// Declares a global variable accessible to the function. + pub fn create_global_var(&mut self, data: GlobalVarData) -> GlobalVar { + self.func.create_global_var(data) + } + + /// Declares a heap accessible to the function. + pub fn create_heap(&mut self, data: HeapData) -> Heap { + self.func.create_heap(data) } /// Returns an object with the [`InstBuilder`](../cretonne/ir/builder/trait.InstBuilder.html) diff --git a/lib/frontend/src/ssa.rs b/lib/frontend/src/ssa.rs index 60c5663866..a4c99885a0 100644 --- a/lib/frontend/src/ssa.rs +++ b/lib/frontend/src/ssa.rs @@ -1145,9 +1145,9 @@ mod tests { func.dfg.ins(cur).iconst(I32, 1) }; ssa.def_var(x_var, x1, block0); - let mut jt_data = JumpTableData::new(); - jt_data.set_entry(0, ebb1); - let jt = func.jump_tables.push(jt_data); + let mut data = JumpTableData::new(); + data.push_entry(ebb1); + let jt = func.create_jump_table(data); ssa.use_var( &mut func.dfg, &mut func.layout, diff --git a/lib/reader/src/parser.rs b/lib/reader/src/parser.rs index 259d462298..2169ded9c9 100644 --- a/lib/reader/src/parser.rs +++ b/lib/reader/src/parser.rs @@ -120,7 +120,7 @@ impl<'a> Context<'a> { fn add_ss(&mut self, number: u32, data: StackSlotData, loc: &Location) -> Result<()> { self.map.def_ss( number, - self.function.stack_slots.push(data), + self.function.create_stack_slot(data), loc, ) } @@ -137,7 +137,7 @@ impl<'a> Context<'a> { fn add_gv(&mut self, number: u32, data: GlobalVarData, loc: &Location) -> Result<()> { self.map.def_gv( number, - self.function.global_vars.push(data), + self.function.create_global_var(data), loc, ) } @@ -154,7 +154,7 @@ impl<'a> Context<'a> { fn add_heap(&mut self, number: u32, data: HeapData, loc: &Location) -> Result<()> { self.map.def_heap( number, - self.function.heaps.push(data), + self.function.create_heap(data), loc, ) } @@ -171,7 +171,7 @@ impl<'a> Context<'a> { fn add_sig(&mut self, number: u32, data: Signature, loc: &Location) -> Result<()> { self.map.def_sig( number, - self.function.dfg.signatures.push(data), + self.function.import_signature(data), loc, ) } @@ -188,7 +188,7 @@ impl<'a> Context<'a> { fn add_fn(&mut self, number: u32, data: ExtFuncData, loc: &Location) -> Result<()> { self.map.def_fn( number, - self.function.dfg.ext_funcs.push(data), + self.function.import_function(data), loc, ) } @@ -205,7 +205,7 @@ impl<'a> Context<'a> { fn add_jt(&mut self, number: u32, data: JumpTableData, loc: &Location) -> Result<()> { self.map.def_jt( number, - self.function.jump_tables.push(data), + self.function.create_jump_table(data), loc, ) } @@ -1275,7 +1275,7 @@ impl<'a> Parser<'a> { let data = match self.token() { Some(Token::Identifier("function")) => { let (loc, name, sig) = self.parse_function_spec(ctx.unique_isa)?; - let sigref = ctx.function.dfg.signatures.push(sig); + let sigref = ctx.function.import_signature(sig); ctx.map.def_entity(sigref.into(), &loc).expect( "duplicate SigRef entities created", ); diff --git a/lib/wasm/src/code_translator.rs b/lib/wasm/src/code_translator.rs index 04a3770ee8..096d7d2b4d 100644 --- a/lib/wasm/src/code_translator.rs +++ b/lib/wasm/src/code_translator.rs @@ -21,7 +21,8 @@ //! //! That is why `translate_function_body` takes an object having the `WasmRuntime` trait as //! argument. -use cretonne::ir::{self, Function, Signature, Type, InstBuilder, FunctionName, Ebb, MemFlags}; +use cretonne::ir::{self, Function, Signature, Type, InstBuilder, FunctionName, Ebb, MemFlags, + JumpTableData}; use cretonne::ir::types::*; use cretonne::ir::immediates::{Ieee32, Ieee64}; use cretonne::ir::condcodes::{IntCC, FloatCC}; @@ -363,14 +364,15 @@ pub fn translate_operator( if jump_args_count == 0 { // No jump arguments let val = state.pop1(); - let jt = builder.create_jump_table(); - for (index, depth) in depths.iter().enumerate() { - let i = state.control_stack.len() - 1 - (*depth as usize); + let mut data = JumpTableData::new(); + for depth in depths { + let i = state.control_stack.len() - 1 - (depth as usize); let frame = &mut state.control_stack[i]; let ebb = frame.br_destination(); - builder.insert_jump_table_entry(jt, index, ebb); + data.push_entry(ebb); frame.set_reachable(); } + let jt = builder.create_jump_table(data); builder.ins().br_table(val, jt); let i = state.control_stack.len() - 1 - (default as usize); let frame = &mut state.control_stack[i]; @@ -383,20 +385,20 @@ pub fn translate_operator( // We then proceed to split the edges going out of the br_table let val = state.pop1(); let cut_index = state.stack.len() - jump_args_count; - let jt = builder.create_jump_table(); - let dest_ebbs: HashMap = - depths.iter().enumerate().fold(HashMap::new(), |mut acc, - (index, &depth)| { - if acc.get(&(depth as usize)).is_none() { - let branch_ebb = builder.create_ebb(); - builder.insert_jump_table_entry(jt, index, branch_ebb); - acc.insert(depth as usize, branch_ebb); - return acc; - }; - let branch_ebb = acc[&(depth as usize)]; - builder.insert_jump_table_entry(jt, index, branch_ebb); - acc - }); + let mut data = JumpTableData::new(); + let dest_ebbs: HashMap = depths.iter().fold(HashMap::new(), |mut acc, + &depth| { + if acc.get(&(depth as usize)).is_none() { + let branch_ebb = builder.create_ebb(); + data.push_entry(branch_ebb); + acc.insert(depth as usize, branch_ebb); + return acc; + }; + let branch_ebb = acc[&(depth as usize)]; + data.push_entry(branch_ebb); + acc + }); + let jt = builder.create_jump_table(data); builder.ins().br_table(val, jt); let default_ebb = state.control_stack[state.control_stack.len() - 1 - (default as usize)] diff --git a/lib/wasm/src/runtime/dummy.rs b/lib/wasm/src/runtime/dummy.rs index 3517fabf84..04762988f2 100644 --- a/lib/wasm/src/runtime/dummy.rs +++ b/lib/wasm/src/runtime/dummy.rs @@ -40,7 +40,7 @@ impl FuncEnvironment for DummyRuntime { fn make_global(&self, func: &mut ir::Function, index: GlobalIndex) -> GlobalValue { // Just create a dummy `vmctx` global. let offset = ((index * 8) as i32 + 8).into(); - let gv = func.global_vars.push(ir::GlobalVarData::VmCtx { offset }); + let gv = func.create_global_var(ir::GlobalVarData::VmCtx { offset }); GlobalValue::Memory { gv, ty: self.globals[index].ty, @@ -48,7 +48,7 @@ impl FuncEnvironment for DummyRuntime { } fn make_heap(&self, func: &mut ir::Function, _index: MemoryIndex) -> ir::Heap { - func.heaps.push(ir::HeapData { + func.create_heap(ir::HeapData { base: ir::HeapBase::ReservedReg, min_size: 0.into(), guard_size: 0x8000_0000.into(), @@ -59,21 +59,21 @@ impl FuncEnvironment for DummyRuntime { fn make_indirect_sig(&self, func: &mut ir::Function, index: SignatureIndex) -> ir::SigRef { // A real implementation would probably change the calling convention and add `vmctx` and // signature index arguments. - func.dfg.signatures.push(self.signatures[index].clone()) + func.import_signature(self.signatures[index].clone()) } fn make_direct_func(&self, func: &mut ir::Function, index: FunctionIndex) -> ir::FuncRef { let sigidx = self.func_types[index]; // A real implementation would probably add a `vmctx` argument. // And maybe attempt some signature de-duplication. - let signature = func.dfg.signatures.push(self.signatures[sigidx].clone()); + let signature = func.import_signature(self.signatures[sigidx].clone()); let name = match self.imported_funcs.get(index) { Some(name) => name.clone(), None => ir::FunctionName::new(format!("localfunc{}", index)), }; - func.dfg.ext_funcs.push(ir::ExtFuncData { name, signature }) + func.import_function(ir::ExtFuncData { name, signature }) } fn translate_call_indirect(