Auto merge of #94468 - Amanieu:global_asm_sym, r=nagisa
Implement sym operands for global_asm! 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 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`
This commit is contained in:
commit
080d5452e1
50 changed files with 654 additions and 245 deletions
|
@ -1,12 +1,17 @@
|
|||
use crate::{ImplTraitContext, ImplTraitPosition, ParamMode};
|
||||
|
||||
use super::LoweringContext;
|
||||
|
||||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::*;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::stable_set::FxHashSet;
|
||||
use rustc_errors::struct_span_err;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::definitions::DefPathData;
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::{sym, Span};
|
||||
use rustc_span::{sym, ExpnId, Span};
|
||||
use rustc_target::asm;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::fmt::Write;
|
||||
|
@ -188,7 +193,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
anon_const: self.lower_anon_const(anon_const),
|
||||
}
|
||||
}
|
||||
InlineAsmOperand::Sym { ref expr } => {
|
||||
InlineAsmOperand::Sym { ref sym } => {
|
||||
if !self.sess.features_untracked().asm_sym {
|
||||
feature_err(
|
||||
&self.sess.parse_sess,
|
||||
|
@ -198,7 +203,54 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
)
|
||||
.emit();
|
||||
}
|
||||
hir::InlineAsmOperand::Sym { expr: self.lower_expr_mut(expr) }
|
||||
|
||||
let static_def_id = self
|
||||
.resolver
|
||||
.get_partial_res(sym.id)
|
||||
.filter(|res| res.unresolved_segments() == 0)
|
||||
.and_then(|res| {
|
||||
if let Res::Def(DefKind::Static(_), def_id) = res.base_res() {
|
||||
Some(def_id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(def_id) = static_def_id {
|
||||
let path = self.lower_qpath(
|
||||
sym.id,
|
||||
&sym.qself,
|
||||
&sym.path,
|
||||
ParamMode::Optional,
|
||||
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
|
||||
);
|
||||
hir::InlineAsmOperand::SymStatic { path, def_id }
|
||||
} else {
|
||||
// Replace the InlineAsmSym AST node with an
|
||||
// Expr using the name node id.
|
||||
let expr = Expr {
|
||||
id: sym.id,
|
||||
kind: ExprKind::Path(sym.qself.clone(), sym.path.clone()),
|
||||
span: *op_sp,
|
||||
attrs: AttrVec::new(),
|
||||
tokens: None,
|
||||
};
|
||||
|
||||
// Wrap the expression in an AnonConst.
|
||||
let parent_def_id = self.current_hir_id_owner;
|
||||
let node_id = self.resolver.next_node_id();
|
||||
self.resolver.create_def(
|
||||
parent_def_id,
|
||||
node_id,
|
||||
DefPathData::AnonConst,
|
||||
ExpnId::root(),
|
||||
*op_sp,
|
||||
);
|
||||
let anon_const = AnonConst { id: node_id, value: P(expr) };
|
||||
hir::InlineAsmOperand::SymFn {
|
||||
anon_const: self.lower_anon_const(&anon_const),
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
(op, self.lower_span(*op_sp))
|
||||
|
@ -260,7 +312,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
err.span_label(op_sp, "argument");
|
||||
err.emit();
|
||||
}
|
||||
hir::InlineAsmOperand::Sym { .. } => {
|
||||
hir::InlineAsmOperand::SymFn { .. }
|
||||
| hir::InlineAsmOperand::SymStatic { .. } => {
|
||||
let mut err = sess.struct_span_err(
|
||||
placeholder_span,
|
||||
"asm template modifiers are not allowed for `sym` arguments",
|
||||
|
@ -308,7 +361,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
hir::InlineAsmOperand::InOut { .. }
|
||||
| hir::InlineAsmOperand::SplitInOut { .. } => (true, true),
|
||||
|
||||
hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::Sym { .. } => {
|
||||
hir::InlineAsmOperand::Const { .. }
|
||||
| hir::InlineAsmOperand::SymFn { .. }
|
||||
| hir::InlineAsmOperand::SymStatic { .. } => {
|
||||
unreachable!()
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue