trans/codegen_c: Collapse Rust asm! double-dollar escape for GCC inline asm#412
Open
rautyrauty wants to merge 1 commit into
Open
trans/codegen_c: Collapse Rust asm! double-dollar escape for GCC inline asm#412rautyrauty wants to merge 1 commit into
rautyrauty wants to merge 1 commit into
Conversation
…g GCC inline asm
This is necessary because Rust asm! templates target LLVM's $-based
operand syntax (where $$ escapes a literal $), but mrustc lowers them
through GCC inline-asm where operands are %-prefixed and $ has no
escape. The doubled $ survives into the asm text; with .intel_syntax
noprefix GAS evaluates "$$0x80" as a non-8-bit expression and rejects
the int instruction, breaking rustix-1.0.8 on i586 ("int $$0x80" in
its i686 syscall wrappers).
thepowersgang
requested changes
May 24, 2026
Comment on lines
+5621
to
+5642
| // Rust's `asm!` templates are passed verbatim to LLVM, where `$$` | ||
| // is the escape for a literal `$` (LLVM IR uses `$N` for operand | ||
| // references). The GCC inline-asm backend has no such escape, and | ||
| // a stray `$` survives into the GAS input as e.g. `int $0x80` — | ||
| // which GAS rejects in `.intel_syntax noprefix` mode with | ||
| // "operand type mismatch". Collapse `$$` here: drop it entirely | ||
| // for Intel-syntax blocks (so `int $$0x80` -> `int 0x80`), and | ||
| // halve it for AT&T blocks (so the immediate prefix survives). | ||
| auto xlat_dollars = [&](const std::string& s) { | ||
| std::string r; | ||
| r.reserve(s.size()); | ||
| for(size_t i = 0; i < s.size(); ++i) { | ||
| if(s[i] == '$' && i+1 < s.size() && s[i+1] == '$') { | ||
| if(se.options.att_syntax) r += '$'; | ||
| i++; | ||
| } | ||
| else { | ||
| r += s[i]; | ||
| } | ||
| } | ||
| return r; | ||
| }; |
Owner
There was a problem hiding this comment.
This translation should be in operator<<(::std::ostream& os, const FmtGccAsm& x) instead of as pre-processing pass.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rust
asm!templates target LLVM's$-based operand syntax (where$$escapes a literal$), but mrustc lowers them through the GCC inline-asm protocol where operands are%-prefixed and$has no escape. The doubled$therefore survives into the assembly text. With the surrounding.intel_syntax noprefixwrapper GAS evaluates"$$0x80"as a non-8-bit expression and rejects theintinstruction, breaking rustix-1.0.8 on i586 — its i686 syscall wrappers use"int $$0x80".Collapse
$$at codegen time: drop it for Intel-syntax blocks (so"int $$0x80"lowers to"int 0x80") and halve it for AT&T blocks (so the$-immediate prefix survives).