Move return_at_end out of Settings and into the wasm FuncEnvironment. (#547)

* Move `return_at_end` out of Settings and into the wasm FuncEnvironment.

The `return_at_end` flag supports users that want to append a custom
epilogue to Cranelift-produced functions. It arranges for functions to
always return via a single return statement at the end, and users are
expected to remove this return to append their code.

This patch makes two changes:
 - First, introduce a `fallthrough_return` instruction and use that
   instead of adding a `return` at the end. That's simpler than having
   users remove the `return` themselves.

 - Second, move this setting out of the Settings and into the wasm
   FuncEnvironment. This flag isn't something the code generator uses,
   it's something that the wasm translator uses. The code generator
   needs to preserve the property, however we can give the
   `fallthrough_return` instruction properties to ensure this as needed,
   such as marking it non-cloneable.
This commit is contained in:
Dan Gohman
2018-10-05 06:43:22 -07:00
committed by GitHub
parent c61722f83f
commit bf041e3ae2
14 changed files with 91 additions and 91 deletions

View File

@@ -370,7 +370,6 @@ mod tests {
call_conv = \"fast\"\n\
is_pic = false\n\
colocated_libcalls = false\n\
return_at_end = false\n\
avoid_div_traps = false\n\
enable_float = true\n\
enable_nan_canonicalization = false\n\

View File

@@ -307,7 +307,6 @@ struct Verifier<'a> {
func: &'a Function,
expected_cfg: ControlFlowGraph,
expected_domtree: DominatorTree,
flags: &'a Flags,
isa: Option<&'a TargetIsa>,
}
@@ -319,7 +318,6 @@ impl<'a> Verifier<'a> {
func,
expected_cfg,
expected_domtree,
flags: fisa.flags,
isa: fisa.isa,
}
}
@@ -1654,9 +1652,9 @@ impl<'a> Verifier<'a> {
// Instructions with side effects are not allowed to be ghost instructions.
let opcode = self.func.dfg[inst].opcode();
// The `fallthrough` instruction is marked as a terminator and a branch, but it is not
// required to have an encoding.
if opcode == Opcode::Fallthrough {
// The `fallthrough` and `fallthrough_return` instructions are marked as terminators and
// branches, but they are not required to have an encoding.
if opcode == Opcode::Fallthrough || opcode == Opcode::FallthroughReturn {
return Ok(());
}
@@ -1696,24 +1694,6 @@ impl<'a> Verifier<'a> {
Ok(())
}
/// Verify the `return_at_end` property which requires that there are no internal return
/// instructions.
fn verify_return_at_end(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
for ebb in self.func.layout.ebbs() {
let inst = self.func.layout.last_inst(ebb).unwrap();
if self.func.dfg[inst].opcode().is_return() && Some(ebb) != self.func.layout.last_ebb()
{
report!(
errors,
inst,
"Internal return not allowed with return_at_end=1"
);
}
}
errors.as_result()
}
pub fn run(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
self.verify_global_values(errors)?;
self.verify_heaps(errors)?;
@@ -1729,10 +1709,6 @@ impl<'a> Verifier<'a> {
}
}
if self.flags.return_at_end() {
self.verify_return_at_end(errors)?;
}
verify_flags(self.func, &self.expected_cfg, self.isa, errors)?;
Ok(())