1
Fork 0

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:
bors 2022-04-16 04:46:01 +00:00
commit 080d5452e1
50 changed files with 654 additions and 245 deletions

View file

@ -2520,12 +2520,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.check_expr_asm_operand(out_expr, false);
}
}
hir::InlineAsmOperand::Const { anon_const } => {
hir::InlineAsmOperand::Const { anon_const }
| hir::InlineAsmOperand::SymFn { anon_const } => {
self.to_const(anon_const);
}
hir::InlineAsmOperand::Sym { expr } => {
self.check_expr(expr);
}
hir::InlineAsmOperand::SymStatic { .. } => {}
}
}
if asm.options.contains(ast::InlineAsmOptions::NORETURN) {

View file

@ -427,16 +427,29 @@ fn typeck_with_fallback<'tcx>(
span,
}),
Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), .. })
| Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), .. })
if asm.operands.iter().any(|(op, _op_sp)| match op {
hir::InlineAsmOperand::Const { anon_const } => {
anon_const.hir_id == id
}
_ => false,
}) =>
{
// Inline assembly constants must be integers.
fcx.next_int_var()
| Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm(asm), .. }) => {
let operand_ty = asm
.operands
.iter()
.filter_map(|(op, _op_sp)| match op {
hir::InlineAsmOperand::Const { anon_const }
if anon_const.hir_id == id =>
{
// Inline assembly constants must be integers.
Some(fcx.next_int_var())
}
hir::InlineAsmOperand::SymFn { anon_const }
if anon_const.hir_id == id =>
{
Some(fcx.next_ty_var(TypeVariableOrigin {
kind: TypeVariableOriginKind::MiscVariable,
span,
}))
}
_ => None,
})
.next();
operand_ty.unwrap_or_else(fallback)
}
_ => fallback(),
},

View file

@ -450,7 +450,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
| Node::Item(&Item { kind: ItemKind::GlobalAsm(asm), .. })
if asm.operands.iter().any(|(op, _op_sp)| match op {
hir::InlineAsmOperand::Const { anon_const } => anon_const.hir_id == hir_id,
hir::InlineAsmOperand::Const { anon_const }
| hir::InlineAsmOperand::SymFn { anon_const } => anon_const.hir_id == hir_id,
_ => false,
}) =>
{

View file

@ -358,8 +358,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
hir::ExprKind::InlineAsm(asm) => {
for (op, _op_sp) in asm.operands {
match op {
hir::InlineAsmOperand::In { expr, .. }
| hir::InlineAsmOperand::Sym { expr, .. } => self.consume_expr(expr),
hir::InlineAsmOperand::In { expr, .. } => self.consume_expr(expr),
hir::InlineAsmOperand::Out { expr: Some(expr), .. }
| hir::InlineAsmOperand::InOut { expr, .. } => {
self.mutate_expr(expr);
@ -371,7 +370,9 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
}
}
hir::InlineAsmOperand::Out { expr: None, .. }
| hir::InlineAsmOperand::Const { .. } => {}
| hir::InlineAsmOperand::Const { .. }
| hir::InlineAsmOperand::SymFn { .. }
| hir::InlineAsmOperand::SymStatic { .. } => {}
}
}
}