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
|
@ -2061,6 +2061,20 @@ impl InlineAsmTemplatePiece {
|
|||
}
|
||||
}
|
||||
|
||||
/// Inline assembly symbol operands get their own AST node that is somewhat
|
||||
/// similar to `AnonConst`.
|
||||
///
|
||||
/// The main difference is that we specifically don't assign it `DefId` in
|
||||
/// `DefCollector`. Instead this is deferred until AST lowering where we
|
||||
/// lower it to an `AnonConst` (for functions) or a `Path` (for statics)
|
||||
/// depending on what the path resolves to.
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub struct InlineAsmSym {
|
||||
pub id: NodeId,
|
||||
pub qself: Option<QSelf>,
|
||||
pub path: Path,
|
||||
}
|
||||
|
||||
/// Inline assembly operand.
|
||||
///
|
||||
/// E.g., `out("eax") result` as in `asm!("mov eax, 2", out("eax") result)`.
|
||||
|
@ -2090,7 +2104,7 @@ pub enum InlineAsmOperand {
|
|||
anon_const: AnonConst,
|
||||
},
|
||||
Sym {
|
||||
expr: P<Expr>,
|
||||
sym: InlineAsmSym,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -280,6 +280,14 @@ pub trait MutVisitor: Sized {
|
|||
fn flat_map_pat_field(&mut self, fp: PatField) -> SmallVec<[PatField; 1]> {
|
||||
noop_flat_map_pat_field(fp, self)
|
||||
}
|
||||
|
||||
fn visit_inline_asm(&mut self, asm: &mut InlineAsm) {
|
||||
noop_visit_inline_asm(asm, self)
|
||||
}
|
||||
|
||||
fn visit_inline_asm_sym(&mut self, sym: &mut InlineAsmSym) {
|
||||
noop_visit_inline_asm_sym(sym, self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Use a map-style function (`FnOnce(T) -> T`) to overwrite a `&mut T`. Useful
|
||||
|
@ -1019,7 +1027,7 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
|
|||
}
|
||||
}
|
||||
ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
|
||||
ItemKind::GlobalAsm(asm) => noop_visit_inline_asm(asm, vis),
|
||||
ItemKind::GlobalAsm(asm) => vis.visit_inline_asm(asm),
|
||||
ItemKind::TyAlias(box TyAlias {
|
||||
defaultness, generics, where_clauses, bounds, ty, ..
|
||||
}) => {
|
||||
|
@ -1237,13 +1245,12 @@ pub fn noop_visit_anon_const<T: MutVisitor>(AnonConst { id, value }: &mut AnonCo
|
|||
vis.visit_expr(value);
|
||||
}
|
||||
|
||||
fn noop_visit_inline_asm<T: MutVisitor>(asm: &mut InlineAsm, vis: &mut T) {
|
||||
pub fn noop_visit_inline_asm<T: MutVisitor>(asm: &mut InlineAsm, vis: &mut T) {
|
||||
for (op, _) in &mut asm.operands {
|
||||
match op {
|
||||
InlineAsmOperand::In { expr, .. }
|
||||
| InlineAsmOperand::Out { expr: Some(expr), .. }
|
||||
| InlineAsmOperand::InOut { expr, .. }
|
||||
| InlineAsmOperand::Sym { expr, .. } => vis.visit_expr(expr),
|
||||
| InlineAsmOperand::InOut { expr, .. } => vis.visit_expr(expr),
|
||||
InlineAsmOperand::Out { expr: None, .. } => {}
|
||||
InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
|
||||
vis.visit_expr(in_expr);
|
||||
|
@ -1251,11 +1258,21 @@ fn noop_visit_inline_asm<T: MutVisitor>(asm: &mut InlineAsm, vis: &mut T) {
|
|||
vis.visit_expr(out_expr);
|
||||
}
|
||||
}
|
||||
InlineAsmOperand::Const { anon_const, .. } => vis.visit_anon_const(anon_const),
|
||||
InlineAsmOperand::Const { anon_const } => vis.visit_anon_const(anon_const),
|
||||
InlineAsmOperand::Sym { sym } => vis.visit_inline_asm_sym(sym),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn noop_visit_inline_asm_sym<T: MutVisitor>(
|
||||
InlineAsmSym { id, qself, path }: &mut InlineAsmSym,
|
||||
vis: &mut T,
|
||||
) {
|
||||
vis.visit_id(id);
|
||||
vis.visit_qself(qself);
|
||||
vis.visit_path(path);
|
||||
}
|
||||
|
||||
pub fn noop_visit_expr<T: MutVisitor>(
|
||||
Expr { kind, id, span, attrs, tokens }: &mut Expr,
|
||||
vis: &mut T,
|
||||
|
@ -1374,7 +1391,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
|
|||
ExprKind::Ret(expr) => {
|
||||
visit_opt(expr, |expr| vis.visit_expr(expr));
|
||||
}
|
||||
ExprKind::InlineAsm(asm) => noop_visit_inline_asm(asm, vis),
|
||||
ExprKind::InlineAsm(asm) => vis.visit_inline_asm(asm),
|
||||
ExprKind::MacCall(mac) => vis.visit_mac_call(mac),
|
||||
ExprKind::Struct(se) => {
|
||||
let StructExpr { qself, path, fields, rest } = se.deref_mut();
|
||||
|
|
|
@ -214,6 +214,12 @@ pub trait Visitor<'ast>: Sized {
|
|||
fn visit_crate(&mut self, krate: &'ast Crate) {
|
||||
walk_crate(self, krate)
|
||||
}
|
||||
fn visit_inline_asm(&mut self, asm: &'ast InlineAsm) {
|
||||
walk_inline_asm(self, asm)
|
||||
}
|
||||
fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) {
|
||||
walk_inline_asm_sym(self, sym)
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
|
@ -717,13 +723,12 @@ pub fn walk_anon_const<'a, V: Visitor<'a>>(visitor: &mut V, constant: &'a AnonCo
|
|||
visitor.visit_expr(&constant.value);
|
||||
}
|
||||
|
||||
fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) {
|
||||
pub fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) {
|
||||
for (op, _) in &asm.operands {
|
||||
match op {
|
||||
InlineAsmOperand::In { expr, .. }
|
||||
| InlineAsmOperand::Out { expr: Some(expr), .. }
|
||||
| InlineAsmOperand::InOut { expr, .. }
|
||||
| InlineAsmOperand::Sym { expr, .. } => visitor.visit_expr(expr),
|
||||
| InlineAsmOperand::InOut { expr, .. } => visitor.visit_expr(expr),
|
||||
InlineAsmOperand::Out { expr: None, .. } => {}
|
||||
InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
|
||||
visitor.visit_expr(in_expr);
|
||||
|
@ -732,10 +737,18 @@ fn walk_inline_asm<'a, V: Visitor<'a>>(visitor: &mut V, asm: &'a InlineAsm) {
|
|||
}
|
||||
}
|
||||
InlineAsmOperand::Const { anon_const, .. } => visitor.visit_anon_const(anon_const),
|
||||
InlineAsmOperand::Sym { sym } => visitor.visit_inline_asm_sym(sym),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn walk_inline_asm_sym<'a, V: Visitor<'a>>(visitor: &mut V, sym: &'a InlineAsmSym) {
|
||||
if let Some(ref qself) = sym.qself {
|
||||
visitor.visit_ty(&qself.ty);
|
||||
}
|
||||
visitor.visit_path(&sym.path, sym.id);
|
||||
}
|
||||
|
||||
pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
|
||||
walk_list!(visitor, visit_attribute, expression.attrs.iter());
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue