return_call and return_call_indirect are only valid if the return
types of the callee and caller match. We were previously not enforcing
that, which was producing invalid modules.
Details
Diff Detail
- Repository
- rL LLVM
Event Timeline
llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp | ||
---|---|---|
649 ↗ | (On Diff #211610) | It's preexisting, but GuaranteedTailCallOpt's description says:
Does this mean, should we at least try to do tail calls even if CLI.IsTailCall is not true, i.e., there is no tailcall property in the instruction of .ll file? If so, it seems the check for this condition should be outside of if (CLI.IsTailCall). Let me know if I'm mistaken. |
664 ↗ | (On Diff #211610) | We don't call fail in this case? |
672 ↗ | (On Diff #211610) | I'm unsure how the user interface should work. When should we error out and when should we silently switch to non-tail calls? I might be mistaken, but it looks to me that unless CLI.CS.isMustTailCall() is true we don't need to error out, no? But currently MustTail contains much broader conditions, so I'm wondering what the UI should look like. |
llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp | ||
---|---|---|
649 ↗ | (On Diff #211610) | I don't believe this is necessary. I checked and neither RISCV nor AArch64 try to do tail calls unless CLI.IsTailCall is true. There is some pass that runs that marks all possible tail calls as tail, so I guess in the common case at least it would be duplicating effort to check again so late in the backend. |
664 ↗ | (On Diff #211610) | It should be an LLVM IR-level validation error if the prototypes of callers and their musttail callees do no match, so we should never observe this condition. I will add a comment. |
672 ↗ | (On Diff #211610) | RISCV and AArch only error out when CLI.CS.isMustTailCall() is true, as you say. I will update this code to match that behavior. |
llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp | ||
---|---|---|
649 ↗ | (On Diff #212043) | Would we need a test case for vararg too? |
677 ↗ | (On Diff #212043) | Should we document about these restrictions (such as no vararg) here too, like other platforms? |
llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp | ||
238 ↗ | (On Diff #212043) | Why should we do this? Is the return type of the tail-called function different from that of the caller? If so, wouldn't we have already disabled tail calling in ISelLowering as you did above? |
llvm/test/CodeGen/WebAssembly/tailcall.ll | ||
215 ↗ | (On Diff #212043) | I'm not sure what this test is trying to test..? |
llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp | ||
---|---|---|
649 ↗ | (On Diff #212043) | There already is one that was updated for this change. |
677 ↗ | (On Diff #212043) | Yes, I'll add documentation. |
llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp | ||
238 ↗ | (On Diff #212043) | Up above the return types for the current machine instruction (Returns) are determined from the instruction's defs. But return_calls do not have defs, so we need this extra code to record their return types by examining the caller's return type. |
llvm/test/CodeGen/WebAssembly/tailcall.ll | ||
215 ↗ | (On Diff #212043) | This tests that we get the ReturnType: I32 correctly. Without the change you asked about above we incorrectly determine that the return type is none. |
LGTM!
llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp | ||
---|---|---|
649 ↗ | (On Diff #212043) | Oh I didn't see it, sorry. |