Browse Source

Add FuncEnvironment hooks to generate prologue and epilogue code.

In some cases, it is useful to do some work at entry to or exit from a
Cranelift function translated from WebAssembly. This PR adds two
optional methods to the `FuncEnvironment` trait to do just this,
analogous to the pre/post-hooks on operators that already exist.

This PR also includes a drive-by compilation fix due to the latest
nightly wherein `.is_empty()` on a `Range` ambiguously refers to either
the `Range` impl or the `ExactSizeIterator` impl and can't resolve.
pull/2449/head
Chris Fallin 4 years ago
parent
commit
4300c2c075
  1. 2
      cranelift/codegen/src/isa/aarch64/inst/unwind.rs
  2. 20
      cranelift/wasm/src/environ/spec.rs
  3. 3
      cranelift/wasm/src/func_translator.rs

2
cranelift/codegen/src/isa/aarch64/inst/unwind.rs

@ -104,7 +104,7 @@ impl UnwindInfoGenerator<Inst> for AArch64UnwindInfo {
// TODO epilogues // TODO epilogues
let prologue_size = if context.prologue.is_empty() { let prologue_size = if context.prologue.len() == 0 {
0 0
} else { } else {
context.insts_layout[context.prologue.end as usize - 1] context.insts_layout[context.prologue.end as usize - 1]

20
cranelift/wasm/src/environ/spec.rs

@ -624,6 +624,26 @@ pub trait FuncEnvironment: TargetEnvironment {
) -> WasmResult<()> { ) -> WasmResult<()> {
Ok(()) Ok(())
} }
/// Optional callback for the `FunctionEnvironment` performing this translation to perform work
/// before the function body is translated.
fn before_translate_function(
&mut self,
_builder: &mut FunctionBuilder,
_state: &FuncTranslationState,
) -> WasmResult<()> {
Ok(())
}
/// Optional callback for the `FunctionEnvironment` performing this translation to perform work
/// after the function body is translated.
fn after_translate_function(
&mut self,
_builder: &mut FunctionBuilder,
_state: &FuncTranslationState,
) -> WasmResult<()> {
Ok(())
}
} }
/// An object satisfying the `ModuleEnvironment` trait can be passed as argument to the /// An object satisfying the `ModuleEnvironment` trait can be passed as argument to the

3
cranelift/wasm/src/func_translator.rs

@ -225,6 +225,7 @@ fn parse_function_body<FE: FuncEnvironment + ?Sized>(
// The control stack is initialized with a single block representing the whole function. // The control stack is initialized with a single block representing the whole function.
debug_assert_eq!(state.control_stack.len(), 1, "State not initialized"); debug_assert_eq!(state.control_stack.len(), 1, "State not initialized");
environ.before_translate_function(builder, state)?;
while !reader.eof() { while !reader.eof() {
let pos = reader.original_position(); let pos = reader.original_position();
builder.set_srcloc(cur_srcloc(&reader)); builder.set_srcloc(cur_srcloc(&reader));
@ -234,6 +235,7 @@ fn parse_function_body<FE: FuncEnvironment + ?Sized>(
translate_operator(validator, &op, builder, state, environ)?; translate_operator(validator, &op, builder, state, environ)?;
environ.after_translate_operator(&op, builder, state)?; environ.after_translate_operator(&op, builder, state)?;
} }
environ.after_translate_function(builder, state)?;
let pos = reader.original_position(); let pos = reader.original_position();
validator.finish(pos)?; validator.finish(pos)?;
@ -243,7 +245,6 @@ fn parse_function_body<FE: FuncEnvironment + ?Sized>(
// If the exit block is unreachable, it may not have the correct arguments, so we would // If the exit block is unreachable, it may not have the correct arguments, so we would
// generate a return instruction that doesn't match the signature. // generate a return instruction that doesn't match the signature.
if state.reachable { if state.reachable {
debug_assert!(builder.is_pristine());
if !builder.is_unreachable() { if !builder.is_unreachable() {
match environ.return_mode() { match environ.return_mode() {
ReturnMode::NormalReturns => { ReturnMode::NormalReturns => {

Loading…
Cancel
Save