Removed "Variable" parametricity for FunctionBuilder as discussed in PR https://github.com/CraneStation/cranelift/pull/437
This commit is contained in:
committed by
Dan Gohman
parent
b7d2df9307
commit
bed8e33c9d
@@ -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();
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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<()> {
|
||||||
|
|||||||
Reference in New Issue
Block a user