-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Implement sym operands for global_asm! #94468
Conversation
Some changes occured to rustc_codegen_gcc cc @antoyo Some changes occurred in src/tools/clippy. cc @rust-lang/clippy |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The gcc part looks good to me.
Note that there is still an issue on the GCC side: symbols are not mangled correctly on Mach-O (leading underscore) and x86 Windows (cdecl/stdcall/fastcall/vectorcall mangling). This is why we need to call LLVM to get the full mangled symbol name on those platforms. |
extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) { | ||
RawRustStringOstream OS(Str); | ||
GlobalValue *GV = unwrap<GlobalValue>(V); | ||
Mangler().getNameWithPrefix(OS, GV, true); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if long-term we could implement this on the rustc
side by getting the "mangling" flavor out of the datalayout
string.
(Also, I wish both high-level mangling and this lower-level concept weren't both called "mangling" ugh)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rustc already parses the datalayout string for type layouts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I was referring to the m:<mangling>
field specifically. Though, looking at the docs:
x
: Windows x86 COFF mangling: Private symbols get the usual prefix. Regular C symbols get a_
prefix. Functions with__stdcall
,__fastcall
, and__vectorcall
have custom mangling that appends@N
whereN
is the number of bytes used to pass parameters. C++ symbols starting with?
are not mangled in any way.
Yikes, that's a pretty hefty ask. Even if we generated it ourselves we'd probably still want to assert that we got it right by asking the backend what it would generate based on its own knowledge.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if long-term we could implement this on the
rustc
side by getting the "mangling" flavor out of thedatalayout
string.
LLVM seems to be moving in the direction of moving the responsibility for low-level mangling to the front-end: llvm/llvm-project#54090
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM on the typeck/THIR side of things, nothing surprising there.
@@ -59,6 +61,11 @@ fn main() { | |||
} | |||
} | |||
|
|||
unsafe fn generic<T>() { | |||
asm!("{}", sym generic::<T>); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this actually work correctly when the generic_const_exprs
is enabled? Could you add a test for that as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This fails with error: unconstrained generic constant
and I'm not exactly sure how to go about fixing it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be fair, I feel like this should work, without any additional feature gates. I don't consider it a blocker for landing this PR, but I suspect it may require some significant changes to the approach (again) in order to make it work.
src/test/ui/asm/type-check-1.stderr
Outdated
error[E0435]: attempt to use a non-constant value in a constant | ||
--> $DIR/type-check-1.rs:47:24 | ||
| | ||
LL | let x = 0; | ||
| ----- help: consider using `const` instead of `let`: `const x` | ||
... | ||
LL | asm!("{}", sym x); | ||
| ^ non-constant value |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would argue that the “sym
operand must point to a function or static” kind of error would be more actionable here.
Especially because changing the let
to a const
won't help either way (I believe in any case, since FnDef
types cannot be named)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this might be possible by using a custom rib kind in the resolver instead of using ConstantItemRibKind
. I'll look into it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've reworked name resolution to generate a specific error for referring to a local in a sym operand.
| hir::InlineAsmOperand::SplitInOut { .. } => {} | ||
// No special checking is needed for these: | ||
// - Typeck has checked that Const operands are integers. | ||
// - AST lowering guarantees that SymStatic points to a static. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it guarantee that all sym STATIC
s become a SymStatic
, though? It if does, that's also important to note (otherwise we'd start outputting errors in the branch below.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the DefId
for a static is resolved during AST lowering and kept in the operand.
☔ The latest upstream changes (presumably #90076) made this pull request unmergeable. Please resolve the merge conflicts. |
// TODO(@Commeownist): This may not be sufficient for all kinds of statics. | ||
// Some statics may need the `@plt` suffix, like thread-local vars. | ||
// TODO(@Amanieu): Additional mangling is needed on | ||
// some targets to add a leading underscore (Mach-O). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this change imply correct handling of @PLT
and similar? If so, is there a test to that effect?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We never add @
suffixes to symbol names, it's the user's responsibility to add any necessary suffixes.
Addressed all review feedback. |
@bors r+ 🥳 |
📌 Commit e0ed0f4 has been approved by |
⌛ Testing commit 2d90e592e668e7aa8fd72062a51e604d128c9e34 with merge 4f6221d74fef75b3704a708f9f6a97a6d5749072... |
@bors retry (yield to rollup) |
This comment has been minimized.
This comment has been minimized.
⌛ Testing commit 2d90e592e668e7aa8fd72062a51e604d128c9e34 with merge 276047d2ef1543eb466b420e5e82b72b912c9b5a... |
💔 Test failed - checks-actions |
This comment has been minimized.
This comment has been minimized.
@bors r=nagisa |
📌 Commit bdba897 has been approved by |
☀️ Test successful - checks-actions |
Finished benchmarking commit (080d545): comparison url. Summary:
If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf. @rustbot label: -perf-regression Footnotes |
Implement sym operands for global_asm! Tracking issue: rust-lang#93333 This PR is pretty much a complete rewrite of `sym` operand support for inline assembly so that the same implementation can be shared by `asm!` and `global_asm!`. The main changes are: - At the AST level, `sym` is represented as a special `InlineAsmSym` AST node containing a path instead of an `Expr`. - At the HIR level, `sym` is split into `SymStatic` and `SymFn` depending on whether the path resolves to a static during AST lowering (defaults to `SynFn` if `get_early_res` fails). - `SymFn` is just an `AnonConst`. It runs through typeck and we just collect the resulting type at the end. An error is emitted if the type is not a `FnDef`. - `SymStatic` directly holds a path and the `DefId` of the `static` that it is pointing to. - The representation at the MIR level is mostly unchanged. There is a minor change to THIR where `SymFn` is a constant instead of an expression. - At the codegen level we need to apply the target's symbol mangling to the result of `tcx.symbol_name()` depending on the target. This is done by calling the LLVM name mangler, which handles all of the details. - On Mach-O, all symbols have a leading underscore. - On x86 Windows, different mangling is used for cdecl, stdcall, fastcall and vectorcall. - No mangling is needed on other platforms. r? `@nagisa` cc `@eddyb`
Tracking issue: #93333
This PR is pretty much a complete rewrite of
sym
operand support for inline assembly so that the same implementation can be shared byasm!
andglobal_asm!
. The main changes are:sym
is represented as a specialInlineAsmSym
AST node containing a path instead of anExpr
.sym
is split intoSymStatic
andSymFn
depending on whether the path resolves to a static during AST lowering (defaults toSynFn
ifget_early_res
fails).SymFn
is just anAnonConst
. It runs through typeck and we just collect the resulting type at the end. An error is emitted if the type is not aFnDef
.SymStatic
directly holds a path and theDefId
of thestatic
that it is pointing to.SymFn
is a constant instead of an expression.tcx.symbol_name()
depending on the target. This is done by calling the LLVM name mangler, which handles all of the details.r? @nagisa
cc @eddyb