-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[llvm][ARM] Unable to use .cantunwind
(and similar directives) in inline assembly
#115891
Comments
@llvm/issue-subscribers-backend-arm Author: Alex Rønne Petersen (alexrp)
```c
void _start(void)
{
asm volatile (".cantunwind");
}
```
❯ arm-linux-gnueabihf-gcc --version
arm-linux-gnueabihf-gcc (Ubuntu 13.2.0-4ubuntu3) 13.2.0
❯ arm-linux-gnueabihf-gcc test.c -nostdlib -fasynchronous-unwind-tables
❯ clang --version
clang version 19.1.2 (git@<!-- -->github.com:llvm/llvm-project.git d5498c39fe6a17e271ad5a02917103445eb89373)
❯ clang --target=arm-linux-gnueabihf test.c -nostdlib -fasynchronous-unwind-tables
test.c:3:19: error: .fnstart must precede .cantunwind directive
3 | asm volatile (".cantunwind");
| ^
<inline asm>:1:2: note: instantiated into assembly here
1 | .cantunwind
| ^
1 error generated. I would guess that |
The function is not marked .cantunwind for Arm/Thumb because of an LLVM assembler bug: llvm/llvm-project#115891
Whatever was in the frame pointer register prior to clone() will no longer be valid in the child process, so zero it to protect FP-based unwinders. Similarly, mark the link register as undefined to protect DWARF-based unwinders. This is only zeroing the frame pointer(s) on Arm/Thumb because of an LLVM assembler bug: llvm/llvm-project#115891
The function is not marked .cantunwind for Arm/Thumb because of an LLVM assembler bug: llvm/llvm-project#115891
Whatever was in the frame pointer register prior to clone() will no longer be valid in the child process, so zero it to protect FP-based unwinders. Similarly, mark the link register as undefined to protect DWARF-based unwinders. This is only zeroing the frame pointer(s) on Arm/Thumb because of an LLVM assembler bug: llvm/llvm-project#115891
The function is not marked .cantunwind for Arm/Thumb because of an LLVM assembler bug: llvm/llvm-project#115891
Whatever was in the frame pointer register prior to clone() will no longer be valid in the child process, so zero it to protect FP-based unwinders. Similarly, mark the link register as undefined to protect DWARF-based unwinders. This is only zeroing the frame pointer(s) on Arm/Thumb because of an LLVM assembler bug: llvm/llvm-project#115891
The function is not marked .cantunwind for Arm/Thumb because of an LLVM assembler bug: llvm/llvm-project#115891
Whatever was in the frame pointer register prior to clone() will no longer be valid in the child process, so zero it to protect FP-based unwinders. Similarly, mark the link register as undefined to protect DWARF-based unwinders. This is only zeroing the frame pointer(s) on Arm/Thumb because of an LLVM assembler bug: llvm/llvm-project#115891
The function is not marked .cantunwind for Arm/Thumb because of an LLVM assembler bug: llvm/llvm-project#115891
Whatever was in the frame pointer register prior to clone() will no longer be valid in the child process, so zero it to protect FP-based unwinders. Similarly, mark the link register as undefined to protect DWARF-based unwinders. This is only zeroing the frame pointer(s) on Arm/Thumb because of an LLVM assembler bug: llvm/llvm-project#115891
The function is not marked .cantunwind for Arm/Thumb because of an LLVM assembler bug: llvm/llvm-project#115891
Whatever was in the frame pointer register prior to clone() will no longer be valid in the child process, so zero it to protect FP-based unwinders. Similarly, mark the link register as undefined to protect DWARF-based unwinders. This is only zeroing the frame pointer(s) on Arm/Thumb because of an LLVM assembler bug: llvm/llvm-project#115891
If you define a complete function inside an
|
Just to clarify: I'm using C in the example, but I actually ran into the issue in Zig.
I don't quite understand why this would have to be the case for
(We don't have an |
We don't make promises about the exact structure of emitted assembly outside the |
That doesn't seem right. This:
compiled with
|
To be more precise: There are two layers involved here: the "parser", and the "streamer". The parser converts text into an internal representation, and the streamer processes it. For stuff that isn't inline asm, the compiler normally just pokes the streamer directly. The error checking here is part of the "parser". The Arm asm parser does its own tracking for whether there's a .fnstart. The compiler's .fnstart doesn't use the asm parser to emit .fnstart (it skips straight to the streamer), so the asm parser thinks there's a missing .fnstart, so it emits an error. The generic CFI parsing doesn't track anything; it just throws it all at the asm streamer. And the streamer will silently discard directives. But it will also allow mixing up directives with the ones the compiler emits internally. Maybe there's some solution where we can make the parser cooperate with the streamer to emit error messages. |
Ah, I see what you mean now. That makes sense. If my understanding of the parser/printer/streamer abstractions is correct (it very well might not be!), then it should be sufficient to add state tracking for |
I would guess that
.fnstart
/.fnend
is lacking similar handling to.cfi_startproc
/.cfi_endproc
in the integrated assembler?The text was updated successfully, but these errors were encountered: