https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124534
Bug ID: 124534
Summary: musttail: bugs when inlining functions that make tail
calls
Product: gcc
Version: 15.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: wingo at pobox dot com
Target Milestone: ---
Created attachment 63942
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=63942&action=edit
Gzipped test-inlining.c; invoke compiler as in description
I have a compiler from WebAssembly to C that uses `[[gnu::musttail]]` to
implement WebAssembly's tail calls (`return_call`, `return_call_ref`,
`return_call_indirect`). After some tweaks, it seems to be working fine, so
thank you!
After a couple of syntactic oddities
(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124532,
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124533), I had to work around what
would seem to be a compiler bug: inlining functions that make tail calls can
produce errors that are not present if inlining is off.
I modified my compiler to add TAIL_CALLER to the generated C declaration of
each function that makes tail calls. The default definition is
`__attribute__((noinline))`, in which case all goes swimmingly. However if I
compile with `-DTAIL_CALLER=`, thus allowing those functions to be inlined
(they are static), I get many inscrutable errors:
```
$ gcc -DTAIL_CALLER= -O2 -o /tmp/test-inlining.o -c /tmp/test-inlining.c
In function ‘func_306’,
inlined from ‘func_307’ at /tmp/wastrel-llCJtz/main.c:24603:35,
inlined from ‘func_310’ at /tmp/wastrel-llCJtz/main.c:24677:37:
/tmp/wastrel-llCJtz/main.c:24596:35: error: cannot tail-call: memory reference
or volatile after call
24596 | TAIL_CALL return func_308(tmp_0);
| ^
In function ‘func_112’,
inlined from ‘func_120.constprop’ at /tmp/wastrel-llCJtz/main.c:19634:39:
/tmp/wastrel-llCJtz/main.c:19399:37: error: cannot tail-call: other reasons
19399 | TAIL_CALL return func_298(local_0);
| ^~~
In function ‘func_109’,
inlined from ‘func_120.constprop’ at /tmp/wastrel-llCJtz/main.c:19703:37:
/tmp/wastrel-llCJtz/main.c:19371:37: error: cannot tail-call: other reasons
19371 | TAIL_CALL return func_296(local_0);
| ^~~
In function ‘func_294’,
inlined from ‘func_300’ at /tmp/wastrel-llCJtz/main.c:24480:37:
/tmp/wastrel-llCJtz/main.c:24322:35: error: cannot tail-call: other reasons
24322 | TAIL_CALL return func_299(tmp_0, local_1);
| ^~~~~~~~~~
In function ‘func_280’,
inlined from ‘func_281’ at /tmp/wastrel-llCJtz/main.c:24151:35,
inlined from ‘func_321’ at /tmp/wastrel-llCJtz/main.c:25184:43:
/tmp/wastrel-llCJtz/main.c:24144:35: error: cannot tail-call: memory reference
or volatile after call
24144 | TAIL_CALL return func_279(tmp_0, local_1);
| ^~~~~~~~~~
In function ‘func_275’,
inlined from ‘func_276’ at /tmp/wastrel-llCJtz/main.c:24114:35,
inlined from ‘func_321’ at /tmp/wastrel-llCJtz/main.c:25274:41:
/tmp/wastrel-llCJtz/main.c:24107:35: error: cannot tail-call: memory reference
or volatile after call
24107 | TAIL_CALL return func_279(f64_convert_i32_s(local_0), local_1);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...
```
I would try to reduce this file down but given that the errors show up in
different ways ("other reasons" vs "memory reference or volatile after call"),
I'll just attach the whole thing here.
I think that an inlining decision should not introduce a `musttail` failure.
Looking forward to your thoughts on the matter.