[llvm] [wasm] Disallow tail calls when passing structs on the stack (PR #124443)

Timothy Herchen via llvm-commits llvm-commits at lists.llvm.org
Sat Jan 25 20:30:43 PST 2025


https://github.com/anematode created https://github.com/llvm/llvm-project/pull/124443

[The following code is incorrectly compiled with `-mtail-call`](https://godbolt.org/z/vd95cYh1E):

```
struct passed_by_value { int a; int b; };
int f(struct passed_by_value val);
int g(struct passed_by_value in) {
    return f(in);
}
```

Output:

```
g:
        global.get      __stack_pointer
        i32.const       16
        i32.sub 
        local.tee       1
        global.set      __stack_pointer
        local.get       1
        local.get       0
        i64.load        0:p2align=2
        i64.store       8
        local.get       1
        i32.const       16
        i32.add 
        global.set      __stack_pointer
        local.get       1
        i32.const       8
        i32.add 
        return_call     f
        end_function
```

Stack space is reserved for the struct arguments, but the stack pointer is moved back before the `return_call`. So I added a check to prevent TCO from happening if we're passing things on the stack.

>From 4100b33bcf7a6a628203fa5d0bc8d0b2ee3cb6d2 Mon Sep 17 00:00:00 2001
From: Timothy Herchen <timothy.herchen at gmail.com>
Date: Sat, 25 Jan 2025 20:19:00 -0800
Subject: [PATCH] [wasm] disallow tail calls when passing structs on the stack

---
 llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
index 02db1b142a22b5..ec745ebabb4f63 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -1211,6 +1211,15 @@ WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI,
         }
       }
     }
+
+    // If outgoing arguments are passed via the stack, we cannot tail call
+    for (const ISD::OutputArg &Out : CLI.Outs) {
+      if (Out.Flags.isByVal() && Out.Flags.getByValSize() != 0) {
+        NoTail(
+            "WebAssembly does not support tail calling with stack arguments");
+        break;
+      }
+    }
   }
 
   SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;



More information about the llvm-commits mailing list