From 4300c2c075ab1eeb53b34bbffab581b2c0f0e1bc Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Tue, 24 Nov 2020 16:22:29 -0800 Subject: [PATCH] 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. --- .../codegen/src/isa/aarch64/inst/unwind.rs | 2 +- cranelift/wasm/src/environ/spec.rs | 20 +++++++++++++++++++ cranelift/wasm/src/func_translator.rs | 3 ++- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/cranelift/codegen/src/isa/aarch64/inst/unwind.rs b/cranelift/codegen/src/isa/aarch64/inst/unwind.rs index 698e094795..33eabfb173 100644 --- a/cranelift/codegen/src/isa/aarch64/inst/unwind.rs +++ b/cranelift/codegen/src/isa/aarch64/inst/unwind.rs @@ -104,7 +104,7 @@ impl UnwindInfoGenerator for AArch64UnwindInfo { // TODO epilogues - let prologue_size = if context.prologue.is_empty() { + let prologue_size = if context.prologue.len() == 0 { 0 } else { context.insts_layout[context.prologue.end as usize - 1] diff --git a/cranelift/wasm/src/environ/spec.rs b/cranelift/wasm/src/environ/spec.rs index 149e55d6dc..c33bec92ae 100644 --- a/cranelift/wasm/src/environ/spec.rs +++ b/cranelift/wasm/src/environ/spec.rs @@ -624,6 +624,26 @@ pub trait FuncEnvironment: TargetEnvironment { ) -> WasmResult<()> { 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 diff --git a/cranelift/wasm/src/func_translator.rs b/cranelift/wasm/src/func_translator.rs index 158271ab96..7a8f9c19d2 100644 --- a/cranelift/wasm/src/func_translator.rs +++ b/cranelift/wasm/src/func_translator.rs @@ -225,6 +225,7 @@ fn parse_function_body( // The control stack is initialized with a single block representing the whole function. debug_assert_eq!(state.control_stack.len(), 1, "State not initialized"); + environ.before_translate_function(builder, state)?; while !reader.eof() { let pos = reader.original_position(); builder.set_srcloc(cur_srcloc(&reader)); @@ -234,6 +235,7 @@ fn parse_function_body( translate_operator(validator, &op, builder, state, environ)?; environ.after_translate_operator(&op, builder, state)?; } + environ.after_translate_function(builder, state)?; let pos = reader.original_position(); validator.finish(pos)?; @@ -243,7 +245,6 @@ fn parse_function_body( // 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. if state.reachable { - debug_assert!(builder.is_pristine()); if !builder.is_unreachable() { match environ.return_mode() { ReturnMode::NormalReturns => {