Cranelift: Introduce the return_call and return_call_indirect instructions (#5679)

* Cranelift: Introduce the `tail` calling convention

This is an unstable-ABI calling convention that we will eventually use to
support Wasm tail calls.

Co-Authored-By: Jamey Sharp <jsharp@fastly.com>

* Cranelift: Introduce the `return_call` and `return_call_indirect` instructions

These will be used to implement tail calls for Wasm and any other language
targeting CLIF. The `return_call_indirect` instruction differs from the Wasm
instruction of the same name by taking a native address callee rather than a
Wasm function index.

Co-Authored-By: Jamey Sharp <jsharp@fastly.com>

* Cranelift: Implement verification rules for `return_call[_indirect]`

They must:

* have the same return types between the caller and callee,
* have the same calling convention between caller and callee,
* and that calling convention must support tail calls.

Co-Authored-By: Jamey Sharp <jsharp@fastly.com>

* cargo fmt

---------

Co-authored-by: Jamey Sharp <jsharp@fastly.com>
This commit is contained in:
Nick Fitzgerald
2023-02-01 13:20:35 -08:00
committed by GitHub
parent ffbbfbffce
commit bdfb746548
8 changed files with 298 additions and 101 deletions

View File

@@ -253,6 +253,51 @@ fn define_control_flow(
.call(),
);
ig.push(
Inst::new(
"return_call",
r#"
Direct tail call.
Tail call a function which has been declared in the preamble. The
argument types must match the function's signature, the caller and
callee calling conventions must be the same, and must be a calling
convention that supports tail calls.
This instruction is a block terminator.
"#,
&formats.call,
)
.operands_in(vec![FN, args])
.returns()
.call(),
);
ig.push(
Inst::new(
"return_call_indirect",
r#"
Indirect tail call.
Call the function pointed to by `callee` with the given arguments. The
argument types must match the function's signature, the caller and
callee calling conventions must be the same, and must be a calling
convention that supports tail calls.
This instruction is a block terminator.
Note that this is different from WebAssembly's ``tail_call_indirect``;
the callee is a native address, rather than a table index. For
WebAssembly, `table_addr` and `load` are used to obtain a native address
from a table.
"#,
&formats.call_indirect,
)
.operands_in(vec![SIG, callee, args])
.returns()
.call(),
);
let FN = &Operand::new("FN", &entities.func_ref)
.with_doc("function to call, declared by `function`");
let addr = &Operand::new("addr", iAddr);