Removed "Variable" parametricity for FunctionBuilder as discussed in PR https://github.com/CraneStation/cranelift/pull/437

This commit is contained in:
Denis Merigoux
2018-08-14 14:37:19 +02:00
committed by Dan Gohman
parent b7d2df9307
commit bed8e33c9d
4 changed files with 34 additions and 72 deletions

View File

@@ -1,6 +1,6 @@
//! A frontend for building Cranelift IR from other languages. //! A frontend for building Cranelift IR from other languages.
use cranelift_codegen::cursor::{Cursor, FuncCursor}; use cranelift_codegen::cursor::{Cursor, FuncCursor};
use cranelift_codegen::entity::{EntityMap, EntityRef, EntitySet}; use cranelift_codegen::entity::{EntityMap, EntitySet};
use cranelift_codegen::ir; use cranelift_codegen::ir;
use cranelift_codegen::ir::function::DisplayFunction; use cranelift_codegen::ir::function::DisplayFunction;
use cranelift_codegen::ir::{ use cranelift_codegen::ir::{
@@ -11,7 +11,7 @@ use cranelift_codegen::ir::{
use cranelift_codegen::isa::TargetIsa; use cranelift_codegen::isa::TargetIsa;
use cranelift_codegen::packed_option::PackedOption; use cranelift_codegen::packed_option::PackedOption;
use ssa::{Block, SSABuilder, SideEffects}; use ssa::{Block, SSABuilder, SideEffects};
use std::fmt::Debug; use variable::Variable;
/// Structure used for translating a series of functions into Cranelift IR. /// Structure used for translating a series of functions into Cranelift IR.
/// ///
@@ -22,20 +22,14 @@ use std::fmt::Debug;
/// The `Variable` parameter can be any index-like type that can be made to /// The `Variable` parameter can be any index-like type that can be made to
/// implement `EntityRef`. For frontends that don't have an obvious type to /// implement `EntityRef`. For frontends that don't have an obvious type to
/// use here, `variable::Variable` can be used. /// use here, `variable::Variable` can be used.
pub struct FunctionBuilderContext<Variable> pub struct FunctionBuilderContext {
where
Variable: EntityRef + Debug,
{
ssa: SSABuilder<Variable>, ssa: SSABuilder<Variable>,
ebbs: EntityMap<Ebb, EbbData>, ebbs: EntityMap<Ebb, EbbData>,
types: EntityMap<Variable, Type>, types: EntityMap<Variable, Type>,
} }
/// Temporary object used to build a single Cranelift IR `Function`. /// Temporary object used to build a single Cranelift IR `Function`.
pub struct FunctionBuilder<'a, Variable: 'a> pub struct FunctionBuilder<'a> {
where
Variable: EntityRef + Debug,
{
/// The function currently being built. /// The function currently being built.
/// This field is public so the function can be re-borrowed. /// This field is public so the function can be re-borrowed.
pub func: &'a mut Function, pub func: &'a mut Function,
@@ -43,7 +37,7 @@ where
/// Source location to assign to all new instructions. /// Source location to assign to all new instructions.
srcloc: ir::SourceLoc, srcloc: ir::SourceLoc,
func_ctx: &'a mut FunctionBuilderContext<Variable>, func_ctx: &'a mut FunctionBuilderContext,
position: Position, position: Position,
} }
@@ -79,10 +73,7 @@ impl Position {
} }
} }
impl<Variable> FunctionBuilderContext<Variable> impl FunctionBuilderContext {
where
Variable: EntityRef + Debug,
{
/// Creates a FunctionBuilderContext structure. The structure is automatically cleared after /// Creates a FunctionBuilderContext structure. The structure is automatically cleared after
/// each [`FunctionBuilder`](struct.FunctionBuilder.html) completes translating a function. /// each [`FunctionBuilder`](struct.FunctionBuilder.html) completes translating a function.
pub fn new() -> Self { pub fn new() -> Self {
@@ -106,30 +97,18 @@ where
/// Implementation of the [`InstBuilder`](../codegen/ir/builder/trait.InstBuilder.html) that has /// Implementation of the [`InstBuilder`](../codegen/ir/builder/trait.InstBuilder.html) that has
/// one convenience method per Cranelift IR instruction. /// one convenience method per Cranelift IR instruction.
pub struct FuncInstBuilder<'short, 'long: 'short, Variable: 'long> pub struct FuncInstBuilder<'short, 'long: 'short> {
where builder: &'short mut FunctionBuilder<'long>,
Variable: EntityRef + Debug,
{
builder: &'short mut FunctionBuilder<'long, Variable>,
ebb: Ebb, ebb: Ebb,
} }
impl<'short, 'long, Variable> FuncInstBuilder<'short, 'long, Variable> impl<'short, 'long> FuncInstBuilder<'short, 'long> {
where fn new<'s, 'l>(builder: &'s mut FunctionBuilder<'l>, ebb: Ebb) -> FuncInstBuilder<'s, 'l> {
Variable: EntityRef + Debug,
{
fn new<'s, 'l>(
builder: &'s mut FunctionBuilder<'l, Variable>,
ebb: Ebb,
) -> FuncInstBuilder<'s, 'l, Variable> {
FuncInstBuilder { builder, ebb } FuncInstBuilder { builder, ebb }
} }
} }
impl<'short, 'long, Variable> InstBuilderBase<'short> for FuncInstBuilder<'short, 'long, Variable> impl<'short, 'long> InstBuilderBase<'short> for FuncInstBuilder<'short, 'long> {
where
Variable: EntityRef + Debug,
{
fn data_flow_graph(&self) -> &DataFlowGraph { fn data_flow_graph(&self) -> &DataFlowGraph {
&self.builder.func.dfg &self.builder.func.dfg
} }
@@ -229,16 +208,13 @@ where
/// function in a way that violate the coherence of the code. For instance: switching to a new /// function in a way that violate the coherence of the code. For instance: switching to a new
/// `Ebb` when you haven't filled the current one with a terminator instruction, inserting a /// `Ebb` when you haven't filled the current one with a terminator instruction, inserting a
/// return instruction with arguments that don't match the function's signature. /// return instruction with arguments that don't match the function's signature.
impl<'a, Variable> FunctionBuilder<'a, Variable> impl<'a> FunctionBuilder<'a> {
where
Variable: EntityRef + Debug,
{
/// Creates a new FunctionBuilder structure that will operate on a `Function` using a /// Creates a new FunctionBuilder structure that will operate on a `Function` using a
/// `FunctionBuilderContext`. /// `FunctionBuilderContext`.
pub fn new( pub fn new(
func: &'a mut Function, func: &'a mut Function,
func_ctx: &'a mut FunctionBuilderContext<Variable>, func_ctx: &'a mut FunctionBuilderContext,
) -> FunctionBuilder<'a, Variable> { ) -> FunctionBuilder<'a> {
debug_assert!(func_ctx.is_empty()); debug_assert!(func_ctx.is_empty());
FunctionBuilder { FunctionBuilder {
func, func,
@@ -393,7 +369,7 @@ where
/// Returns an object with the [`InstBuilder`](../codegen/ir/builder/trait.InstBuilder.html) /// Returns an object with the [`InstBuilder`](../codegen/ir/builder/trait.InstBuilder.html)
/// trait that allows to conveniently append an instruction to the current `Ebb` being built. /// trait that allows to conveniently append an instruction to the current `Ebb` being built.
pub fn ins<'short>(&'short mut self) -> FuncInstBuilder<'short, 'a, Variable> { pub fn ins<'short>(&'short mut self) -> FuncInstBuilder<'short, 'a> {
let ebb = self.position.ebb.unwrap(); let ebb = self.position.ebb.unwrap();
FuncInstBuilder::new(self, ebb) FuncInstBuilder::new(self, ebb)
} }
@@ -486,10 +462,7 @@ where
/// performance of your translation perform more complex transformations to your Cranelift IR /// performance of your translation perform more complex transformations to your Cranelift IR
/// function. The functions below help you inspect the function you're creating and modify it /// function. The functions below help you inspect the function you're creating and modify it
/// in ways that can be unsafe if used incorrectly. /// in ways that can be unsafe if used incorrectly.
impl<'a, Variable> FunctionBuilder<'a, Variable> impl<'a> FunctionBuilder<'a> {
where
Variable: EntityRef + Debug,
{
/// Retrieves all the parameters for an `Ebb` currently inferred from the jump instructions /// Retrieves all the parameters for an `Ebb` currently inferred from the jump instructions
/// inserted that target it and the SSA construction. /// inserted that target it and the SSA construction.
pub fn ebb_params(&self, ebb: Ebb) -> &[Value] { pub fn ebb_params(&self, ebb: Ebb) -> &[Value] {
@@ -574,10 +547,7 @@ where
} }
// Helper functions // Helper functions
impl<'a, Variable> FunctionBuilder<'a, Variable> impl<'a> FunctionBuilder<'a> {
where
Variable: EntityRef + Debug,
{
fn move_to_next_basic_block(&mut self) { fn move_to_next_basic_block(&mut self) {
self.position.basic_block = PackedOption::from( self.position.basic_block = PackedOption::from(
self.func_ctx self.func_ctx
@@ -625,10 +595,10 @@ mod tests {
sig.returns.push(AbiParam::new(I32)); sig.returns.push(AbiParam::new(I32));
sig.params.push(AbiParam::new(I32)); sig.params.push(AbiParam::new(I32));
let mut fn_ctx = FunctionBuilderContext::<Variable>::new(); let mut fn_ctx = FunctionBuilderContext::new();
let mut func = Function::with_name_signature(ExternalName::testcase("sample"), sig); let mut func = Function::with_name_signature(ExternalName::testcase("sample"), sig);
{ {
let mut builder = FunctionBuilder::<Variable>::new(&mut func, &mut fn_ctx); let mut builder = FunctionBuilder::new(&mut func, &mut fn_ctx);
let block0 = builder.create_ebb(); let block0 = builder.create_ebb();
let block1 = builder.create_ebb(); let block1 = builder.create_ebb();

View File

@@ -80,10 +80,10 @@
//! let mut sig = Signature::new(CallConv::SystemV); //! let mut sig = Signature::new(CallConv::SystemV);
//! sig.returns.push(AbiParam::new(I32)); //! sig.returns.push(AbiParam::new(I32));
//! sig.params.push(AbiParam::new(I32)); //! sig.params.push(AbiParam::new(I32));
//! let mut fn_builder_ctx = FunctionBuilderContext::<Variable>::new(); //! let mut fn_builder_ctx = FunctionBuilderContext::new();
//! let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig); //! let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig);
//! { //! {
//! let mut builder = FunctionBuilder::<Variable>::new(&mut func, &mut fn_builder_ctx); //! let mut builder = FunctionBuilder::new(&mut func, &mut fn_builder_ctx);
//! //!
//! let block0 = builder.create_ebb(); //! let block0 = builder.create_ebb();
//! let block1 = builder.create_ebb(); //! let block1 = builder.create_ebb();

View File

@@ -43,7 +43,7 @@ use wasmparser::{MemoryImmediate, Operator};
/// a return. /// a return.
pub fn translate_operator<FE: FuncEnvironment + ?Sized>( pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
op: Operator, op: Operator,
builder: &mut FunctionBuilder<Variable>, builder: &mut FunctionBuilder,
state: &mut TranslationState, state: &mut TranslationState,
environ: &mut FE, environ: &mut FE,
) -> WasmResult<()> { ) -> WasmResult<()> {
@@ -904,7 +904,7 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
/// portion so the translation state muts be updated accordingly. /// portion so the translation state muts be updated accordingly.
fn translate_unreachable_operator( fn translate_unreachable_operator(
op: &Operator, op: &Operator,
builder: &mut FunctionBuilder<Variable>, builder: &mut FunctionBuilder,
state: &mut TranslationState, state: &mut TranslationState,
) { ) {
match *op { match *op {
@@ -988,7 +988,7 @@ fn get_heap_addr(
addr32: ir::Value, addr32: ir::Value,
offset: u32, offset: u32,
addr_ty: Type, addr_ty: Type,
builder: &mut FunctionBuilder<Variable>, builder: &mut FunctionBuilder,
) -> (ir::Value, i32) { ) -> (ir::Value, i32) {
use std::cmp::min; use std::cmp::min;
@@ -1024,7 +1024,7 @@ fn translate_load<FE: FuncEnvironment + ?Sized>(
offset: u32, offset: u32,
opcode: ir::Opcode, opcode: ir::Opcode,
result_ty: Type, result_ty: Type,
builder: &mut FunctionBuilder<Variable>, builder: &mut FunctionBuilder,
state: &mut TranslationState, state: &mut TranslationState,
environ: &mut FE, environ: &mut FE,
) { ) {
@@ -1046,7 +1046,7 @@ fn translate_load<FE: FuncEnvironment + ?Sized>(
fn translate_store<FE: FuncEnvironment + ?Sized>( fn translate_store<FE: FuncEnvironment + ?Sized>(
offset: u32, offset: u32,
opcode: ir::Opcode, opcode: ir::Opcode,
builder: &mut FunctionBuilder<Variable>, builder: &mut FunctionBuilder,
state: &mut TranslationState, state: &mut TranslationState,
environ: &mut FE, environ: &mut FE,
) { ) {
@@ -1063,21 +1063,13 @@ fn translate_store<FE: FuncEnvironment + ?Sized>(
.Store(opcode, val_ty, flags, offset.into(), val, base); .Store(opcode, val_ty, flags, offset.into(), val, base);
} }
fn translate_icmp( fn translate_icmp(cc: IntCC, builder: &mut FunctionBuilder, state: &mut TranslationState) {
cc: IntCC,
builder: &mut FunctionBuilder<Variable>,
state: &mut TranslationState,
) {
let (arg0, arg1) = state.pop2(); let (arg0, arg1) = state.pop2();
let val = builder.ins().icmp(cc, arg0, arg1); let val = builder.ins().icmp(cc, arg0, arg1);
state.push1(builder.ins().bint(I32, val)); state.push1(builder.ins().bint(I32, val));
} }
fn translate_fcmp( fn translate_fcmp(cc: FloatCC, builder: &mut FunctionBuilder, state: &mut TranslationState) {
cc: FloatCC,
builder: &mut FunctionBuilder<Variable>,
state: &mut TranslationState,
) {
let (arg0, arg1) = state.pop2(); let (arg0, arg1) = state.pop2();
let val = builder.ins().fcmp(cc, arg0, arg1); let val = builder.ins().fcmp(cc, arg0, arg1);
state.push1(builder.ins().bint(I32, val)); state.push1(builder.ins().bint(I32, val));
@@ -1085,7 +1077,7 @@ fn translate_fcmp(
fn translate_br_if( fn translate_br_if(
relative_depth: u32, relative_depth: u32,
builder: &mut FunctionBuilder<Variable>, builder: &mut FunctionBuilder,
state: &mut TranslationState, state: &mut TranslationState,
) { ) {
let val = state.pop1(); let val = state.pop1();

View File

@@ -19,7 +19,7 @@ use wasmparser::{self, BinaryReader};
/// by a `FuncEnvironment` object. A single translator instance can be reused to translate multiple /// by a `FuncEnvironment` object. A single translator instance can be reused to translate multiple
/// functions which will reduce heap allocation traffic. /// functions which will reduce heap allocation traffic.
pub struct FuncTranslator { pub struct FuncTranslator {
func_ctx: FunctionBuilderContext<Variable>, func_ctx: FunctionBuilderContext,
state: TranslationState, state: TranslationState,
} }
@@ -105,7 +105,7 @@ impl FuncTranslator {
/// Declare local variables for the signature parameters that correspond to WebAssembly locals. /// Declare local variables for the signature parameters that correspond to WebAssembly locals.
/// ///
/// Return the number of local variables declared. /// Return the number of local variables declared.
fn declare_wasm_parameters(builder: &mut FunctionBuilder<Variable>, entry_block: Ebb) -> usize { fn declare_wasm_parameters(builder: &mut FunctionBuilder, entry_block: Ebb) -> usize {
let sig_len = builder.func.signature.params.len(); let sig_len = builder.func.signature.params.len();
let mut next_local = 0; let mut next_local = 0;
for i in 0..sig_len { for i in 0..sig_len {
@@ -131,7 +131,7 @@ fn declare_wasm_parameters(builder: &mut FunctionBuilder<Variable>, entry_block:
/// Declare local variables, starting from `num_params`. /// Declare local variables, starting from `num_params`.
fn parse_local_decls( fn parse_local_decls(
reader: &mut BinaryReader, reader: &mut BinaryReader,
builder: &mut FunctionBuilder<Variable>, builder: &mut FunctionBuilder,
num_params: usize, num_params: usize,
) -> WasmResult<()> { ) -> WasmResult<()> {
let mut next_local = num_params; let mut next_local = num_params;
@@ -155,7 +155,7 @@ fn parse_local_decls(
/// ///
/// Fail of too many locals are declared in the function, or if the type is not valid for a local. /// Fail of too many locals are declared in the function, or if the type is not valid for a local.
fn declare_locals( fn declare_locals(
builder: &mut FunctionBuilder<Variable>, builder: &mut FunctionBuilder,
count: u32, count: u32,
wasm_type: wasmparser::Type, wasm_type: wasmparser::Type,
next_local: &mut usize, next_local: &mut usize,
@@ -185,7 +185,7 @@ fn declare_locals(
/// arguments and locals are declared in the builder. /// arguments and locals are declared in the builder.
fn parse_function_body<FE: FuncEnvironment + ?Sized>( fn parse_function_body<FE: FuncEnvironment + ?Sized>(
mut reader: BinaryReader, mut reader: BinaryReader,
builder: &mut FunctionBuilder<Variable>, builder: &mut FunctionBuilder,
state: &mut TranslationState, state: &mut TranslationState,
environ: &mut FE, environ: &mut FE,
) -> WasmResult<()> { ) -> WasmResult<()> {