about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2025-02-17 16:09:46 +0000
committerMichael Goulet <michael@errs.io>2025-02-22 00:12:07 +0000
commit6ba39f7dc709a90bcb125974964a7e464ed86ff2 (patch)
tree68d6c9515988454516ca2373683f87d01b890c9f /compiler
parent37060aae13d0fe771f9d3222f1c644820a9d2837 (diff)
downloadrust-6ba39f7dc709a90bcb125974964a7e464ed86ff2.tar.gz
rust-6ba39f7dc709a90bcb125974964a7e464ed86ff2.zip
Make a fake body to store typeck results for global_asm
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs18
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs5
-rw-r--r--compiler/rustc_borrowck/src/universal_regions.rs29
-rw-r--r--compiler/rustc_codegen_cranelift/src/global_asm.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/mono_item.rs9
-rw-r--r--compiler/rustc_hir/src/hir.rs25
-rw-r--r--compiler/rustc_hir/src/intravisit.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsicck.rs50
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs35
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs7
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs14
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs9
-rw-r--r--compiler/rustc_lint/src/builtin.rs8
-rw-r--r--compiler/rustc_middle/src/hir/map.rs3
-rw-r--r--compiler/rustc_middle/src/thir.rs4
-rw-r--r--compiler/rustc_middle/src/thir/visit.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs6
-rw-r--r--compiler/rustc_mir_build/src/builder/expr/into.rs17
-rw-r--r--compiler/rustc_mir_build/src/builder/mod.rs5
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs5
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs9
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs40
-rw-r--r--compiler/rustc_mir_build/src/thir/print.rs6
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs13
28 files changed, 181 insertions, 184 deletions
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index 96c230ec243..cfd32fc066f 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -1,13 +1,12 @@
 use std::collections::hash_map::Entry;
 use std::fmt::Write;
 
-use rustc_ast::ptr::P;
 use rustc_ast::*;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_session::parse::feature_err;
-use rustc_span::{Span, kw, sym};
+use rustc_span::{Span, sym};
 use rustc_target::asm;
 
 use super::LoweringContext;
@@ -230,20 +229,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                                 tokens: None,
                             };
 
-                            // Wrap the expression in an AnonConst.
-                            let parent_def_id = self.current_hir_id_owner.def_id;
-                            let node_id = self.next_node_id();
-                            self.create_def(
-                                parent_def_id,
-                                node_id,
-                                kw::Empty,
-                                DefKind::AnonConst,
-                                *op_sp,
-                            );
-                            let anon_const = AnonConst { id: node_id, value: P(expr) };
-                            hir::InlineAsmOperand::SymFn {
-                                anon_const: self.lower_anon_const_to_anon_const(&anon_const),
-                            }
+                            hir::InlineAsmOperand::SymFn { expr: self.lower_expr(&expr) }
                         }
                     }
                     InlineAsmOperand::Label { block } => {
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index a7a03f7d6db..1d3db64b47e 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -252,7 +252,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
             },
             ItemKind::GlobalAsm(asm) => {
-                hir::ItemKind::GlobalAsm { asm: self.lower_inline_asm(span, asm) }
+                let asm = self.lower_inline_asm(span, asm);
+                let fake_body =
+                    self.lower_body(|this| (&[], this.expr(span, hir::ExprKind::InlineAsm(asm))));
+                hir::ItemKind::GlobalAsm { asm, fake_body }
             }
             ItemKind::TyAlias(box TyAlias { generics, where_clauses, ty, .. }) => {
                 // We lower
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 9a68eeb3326..a71ca37bf13 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -126,6 +126,11 @@ pub(crate) enum DefiningTy<'tcx> {
     /// The MIR represents an inline const. The signature has no inputs and a
     /// single return value found via `InlineConstArgs::ty`.
     InlineConst(DefId, GenericArgsRef<'tcx>),
+
+    // Fake body for a global asm. Not particularly useful or interesting,
+    // but we need it so we can properly store the typeck results of the asm
+    // operands, which aren't associated with a body otherwise.
+    GlobalAsm(DefId),
 }
 
 impl<'tcx> DefiningTy<'tcx> {
@@ -138,9 +143,10 @@ impl<'tcx> DefiningTy<'tcx> {
             DefiningTy::Closure(_, args) => args.as_closure().upvar_tys(),
             DefiningTy::CoroutineClosure(_, args) => args.as_coroutine_closure().upvar_tys(),
             DefiningTy::Coroutine(_, args) => args.as_coroutine().upvar_tys(),
-            DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => {
-                ty::List::empty()
-            }
+            DefiningTy::FnDef(..)
+            | DefiningTy::Const(..)
+            | DefiningTy::InlineConst(..)
+            | DefiningTy::GlobalAsm(_) => ty::List::empty(),
         }
     }
 
@@ -152,7 +158,10 @@ impl<'tcx> DefiningTy<'tcx> {
             DefiningTy::Closure(..)
             | DefiningTy::CoroutineClosure(..)
             | DefiningTy::Coroutine(..) => 1,
-            DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => 0,
+            DefiningTy::FnDef(..)
+            | DefiningTy::Const(..)
+            | DefiningTy::InlineConst(..)
+            | DefiningTy::GlobalAsm(_) => 0,
         }
     }
 
@@ -171,7 +180,8 @@ impl<'tcx> DefiningTy<'tcx> {
             | DefiningTy::Coroutine(def_id, ..)
             | DefiningTy::FnDef(def_id, ..)
             | DefiningTy::Const(def_id, ..)
-            | DefiningTy::InlineConst(def_id, ..) => def_id,
+            | DefiningTy::InlineConst(def_id, ..)
+            | DefiningTy::GlobalAsm(def_id) => def_id,
         }
     }
 }
@@ -411,6 +421,7 @@ impl<'tcx> UniversalRegions<'tcx> {
                     tcx.def_path_str_with_args(def_id, args),
                 ));
             }
+            DefiningTy::GlobalAsm(_) => unreachable!(),
         }
     }
 
@@ -633,6 +644,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                     DefiningTy::InlineConst(self.mir_def.to_def_id(), args)
                 }
             }
+
+            BodyOwnerKind::GlobalAsm => DefiningTy::GlobalAsm(self.mir_def.to_def_id()),
         }
     }
 
@@ -666,6 +679,8 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
             }
 
             DefiningTy::FnDef(_, args) | DefiningTy::Const(_, args) => args,
+
+            DefiningTy::GlobalAsm(_) => ty::List::empty(),
         };
 
         let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static));
@@ -802,6 +817,10 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> {
                 let ty = args.as_inline_const().ty();
                 ty::Binder::dummy(tcx.mk_type_list(&[ty]))
             }
+
+            DefiningTy::GlobalAsm(def_id) => {
+                ty::Binder::dummy(tcx.mk_type_list(&[tcx.type_of(def_id).instantiate_identity()]))
+            }
         };
 
         // FIXME(#129952): We probably want a more principled approach here.
diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs
index 0a23f63d6ba..9ea92c300f8 100644
--- a/compiler/rustc_codegen_cranelift/src/global_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs
@@ -16,7 +16,7 @@ use crate::prelude::*;
 
 pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) {
     let item = tcx.hir_item(item_id);
-    if let rustc_hir::ItemKind::GlobalAsm { asm } = item.kind {
+    if let rustc_hir::ItemKind::GlobalAsm { asm, .. } = item.kind {
         let is_x86 =
             matches!(tcx.sess.asm_arch.unwrap(), InlineAsmArch::X86 | InlineAsmArch::X86_64);
 
@@ -55,7 +55,7 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String,
                                 }
                             }
                         }
-                        InlineAsmOperand::SymFn { anon_const } => {
+                        InlineAsmOperand::SymFn { expr } => {
                             if cfg!(not(feature = "inline_asm_sym")) {
                                 tcx.dcx().span_err(
                                     item.span,
@@ -63,7 +63,7 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String,
                                 );
                             }
 
-                            let ty = tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id);
+                            let ty = tcx.typeck(item_id.owner_id).expr_ty(expr);
                             let instance = match ty.kind() {
                                 &ty::FnDef(def_id, args) => Instance::new(def_id, args),
                                 _ => span_bug!(op_sp, "asm sym is not a function"),
diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs
index a4d5f8bb701..f6af889fd6e 100644
--- a/compiler/rustc_codegen_ssa/src/mono_item.rs
+++ b/compiler/rustc_codegen_ssa/src/mono_item.rs
@@ -36,7 +36,7 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
             }
             MonoItem::GlobalAsm(item_id) => {
                 let item = cx.tcx().hir_item(item_id);
-                if let hir::ItemKind::GlobalAsm { asm } = item.kind {
+                if let hir::ItemKind::GlobalAsm { asm, .. } = item.kind {
                     let operands: Vec<_> = asm
                         .operands
                         .iter()
@@ -71,11 +71,8 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
                                     }
                                 }
                             }
-                            hir::InlineAsmOperand::SymFn { ref anon_const } => {
-                                let ty = cx
-                                    .tcx()
-                                    .typeck_body(anon_const.body)
-                                    .node_type(anon_const.hir_id);
+                            hir::InlineAsmOperand::SymFn { expr } => {
+                                let ty = cx.tcx().typeck(item_id.owner_id).expr_ty(expr);
                                 let instance = match ty.kind() {
                                     &ty::FnDef(def_id, args) => Instance::new(def_id, args),
                                     _ => span_bug!(*op_sp, "asm sym is not a function"),
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 7cd30372783..61f64e62058 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1913,13 +1913,18 @@ pub enum BodyOwnerKind {
 
     /// Initializer of a `static` item.
     Static(Mutability),
+
+    /// Fake body for a global asm to store its const-like value types.
+    GlobalAsm,
 }
 
 impl BodyOwnerKind {
     pub fn is_fn_or_closure(self) -> bool {
         match self {
             BodyOwnerKind::Fn | BodyOwnerKind::Closure => true,
-            BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(_) => false,
+            BodyOwnerKind::Const { .. } | BodyOwnerKind::Static(_) | BodyOwnerKind::GlobalAsm => {
+                false
+            }
         }
     }
 }
@@ -3420,7 +3425,7 @@ pub enum InlineAsmOperand<'hir> {
         anon_const: &'hir AnonConst,
     },
     SymFn {
-        anon_const: &'hir AnonConst,
+        expr: &'hir Expr<'hir>,
     },
     SymStatic {
         path: QPath<'hir>,
@@ -3848,7 +3853,7 @@ impl<'hir> Item<'hir> {
         expect_foreign_mod, (ExternAbi, &'hir [ForeignItemRef]),
             ItemKind::ForeignMod { abi, items }, (*abi, items);
 
-        expect_global_asm, &'hir InlineAsm<'hir>, ItemKind::GlobalAsm { asm }, asm;
+        expect_global_asm, &'hir InlineAsm<'hir>, ItemKind::GlobalAsm { asm, .. }, asm;
 
         expect_ty_alias, (&'hir Ty<'hir>, &'hir Generics<'hir>),
             ItemKind::TyAlias(ty, generics), (ty, generics);
@@ -4015,7 +4020,15 @@ pub enum ItemKind<'hir> {
     /// An external module, e.g. `extern { .. }`.
     ForeignMod { abi: ExternAbi, items: &'hir [ForeignItemRef] },
     /// Module-level inline assembly (from `global_asm!`).
-    GlobalAsm { asm: &'hir InlineAsm<'hir> },
+    GlobalAsm {
+        asm: &'hir InlineAsm<'hir>,
+        /// A fake body which stores typeck results for the global asm's sym_fn
+        /// operands, which are represented as path expressions. This body contains
+        /// a single [`ExprKind::InlineAsm`] which points to the asm in the field
+        /// above, and which is typechecked like a inline asm expr just for the
+        /// typeck results.
+        fake_body: BodyId,
+    },
     /// A type alias, e.g., `type Foo = Bar<u8>`.
     TyAlias(&'hir Ty<'hir>, &'hir Generics<'hir>),
     /// An enum definition, e.g., `enum Foo<A, B> {C<A>, D<B>}`.
@@ -4540,6 +4553,10 @@ impl<'hir> Node<'hir> {
                 ..
             }) => Some((owner_id.def_id, *body)),
 
+            Node::Item(Item {
+                owner_id, kind: ItemKind::GlobalAsm { asm: _, fake_body }, ..
+            }) => Some((owner_id.def_id, *fake_body)),
+
             Node::Expr(Expr { kind: ExprKind::Closure(Closure { def_id, body, .. }), .. }) => {
                 Some((*def_id, *body))
             }
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 5a002423a0c..89a58e947cb 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -573,9 +573,13 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V::
             try_visit!(visitor.visit_id(item.hir_id()));
             walk_list!(visitor, visit_foreign_item_ref, items);
         }
-        ItemKind::GlobalAsm { asm } => {
+        ItemKind::GlobalAsm { asm: _, fake_body } => {
             try_visit!(visitor.visit_id(item.hir_id()));
-            try_visit!(visitor.visit_inline_asm(asm, item.hir_id()));
+            // Visit the fake body, which contains the asm statement.
+            // Therefore we should not visit the asm statement again
+            // outside of the body, or some visitors won't have their
+            // typeck results set correctly.
+            try_visit!(visitor.visit_nested_body(fake_body));
         }
         ItemKind::TyAlias(ref ty, ref generics) => {
             try_visit!(visitor.visit_id(item.hir_id()));
@@ -1442,10 +1446,12 @@ pub fn walk_inline_asm<'v, V: Visitor<'v>>(
                 try_visit!(visitor.visit_expr(in_expr));
                 visit_opt!(visitor, visit_expr, out_expr);
             }
-            InlineAsmOperand::Const { anon_const, .. }
-            | InlineAsmOperand::SymFn { anon_const, .. } => {
+            InlineAsmOperand::Const { anon_const, .. } => {
                 try_visit!(visitor.visit_anon_const(anon_const));
             }
+            InlineAsmOperand::SymFn { expr, .. } => {
+                try_visit!(visitor.visit_expr(expr));
+            }
             InlineAsmOperand::SymStatic { path, .. } => {
                 try_visit!(visitor.visit_qpath(path, id, *op_sp));
             }
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 0d34b657dfc..3236e0a3644 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -15,7 +15,6 @@ use rustc_lint_defs::builtin::{
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
 use rustc_middle::middle::stability::EvalResult;
-use rustc_middle::span_bug;
 use rustc_middle::ty::error::TypeErrorToStringExt;
 use rustc_middle::ty::fold::{BottomUpFolder, fold_regions};
 use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
@@ -35,7 +34,6 @@ use {rustc_attr_parsing as attr, rustc_hir as hir};
 
 use super::compare_impl_item::check_type_bounds;
 use super::*;
-use crate::check::intrinsicck::InlineAsmCtxt;
 
 pub fn check_abi(tcx: TyCtxt<'_>, span: Span, abi: ExternAbi) {
     if !tcx.sess.target.is_abi_supported(abi) {
@@ -895,13 +893,6 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
                 }
             }
         }
-        DefKind::GlobalAsm => {
-            let it = tcx.hir().expect_item(def_id);
-            let hir::ItemKind::GlobalAsm { asm } = it.kind else {
-                span_bug!(it.span, "DefKind::GlobalAsm but got {:#?}", it)
-            };
-            InlineAsmCtxt::new_global_asm(tcx, def_id).check_asm(asm);
-        }
         _ => {}
     }
 }
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index 00f2d46931f..e1727fc48a8 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{self as hir, LangItem};
 use rustc_middle::bug;
-use rustc_middle::ty::{self, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy};
+use rustc_middle::ty::{self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy};
 use rustc_session::lint;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{Symbol, sym};
@@ -30,7 +30,11 @@ enum NonAsmTypeReason<'tcx> {
 }
 
 impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
-    pub fn new_global_asm(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
+    pub fn new(
+        tcx: TyCtxt<'tcx>,
+        def_id: LocalDefId,
+        get_operand_ty: impl Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a,
+    ) -> Self {
         InlineAsmCtxt {
             tcx,
             typing_env: ty::TypingEnv {
@@ -38,23 +42,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
                 param_env: ty::ParamEnv::empty(),
             },
             target_features: tcx.asm_target_features(def_id),
-            expr_ty: Box::new(|e| bug!("asm operand in global asm: {e:?}")),
-        }
-    }
-
-    // FIXME(#132279): This likely causes us to incorrectly handle opaque types in their
-    // defining scope.
-    pub fn new_in_fn(
-        tcx: TyCtxt<'tcx>,
-        typing_env: ty::TypingEnv<'tcx>,
-        def_id: LocalDefId,
-        expr_ty: impl Fn(&hir::Expr<'tcx>) -> Ty<'tcx> + 'a,
-    ) -> Self {
-        InlineAsmCtxt {
-            tcx,
-            typing_env,
-            target_features: tcx.asm_target_features(def_id),
-            expr_ty: Box::new(expr_ty),
+            expr_ty: Box::new(get_operand_ty),
         }
     }
 
@@ -492,11 +480,25 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
                     );
                 }
                 // Typeck has checked that SymFn refers to a function.
-                hir::InlineAsmOperand::SymFn { anon_const } => {
-                    debug_assert_matches!(
-                        self.tcx.type_of(anon_const.def_id).instantiate_identity().kind(),
-                        ty::Error(_) | ty::FnDef(..)
-                    );
+                hir::InlineAsmOperand::SymFn { expr } => {
+                    let ty = self.expr_ty(expr);
+                    match ty.kind() {
+                        ty::FnDef(..) => {}
+                        ty::Error(_) => {}
+                        _ => {
+                            self.tcx
+                                .dcx()
+                                .struct_span_err(op_sp, "invalid `sym` operand")
+                                .with_span_label(
+                                    expr.span,
+                                    format!("is {} `{}`", ty.kind().article(), ty),
+                                )
+                                .with_help(
+                                    "`sym` operands must refer to either a function or a static",
+                                )
+                                .emit();
+                        }
+                    }
                 }
                 // AST lowering guarantees that SymStatic points to a static.
                 hir::InlineAsmOperand::SymStatic { .. } => {}
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index a363076b75a..2cdd9a3a934 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -189,8 +189,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
                     // Exclude `GlobalAsm` here which cannot have generics.
                     Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
                         if asm.operands.iter().any(|(op, _op_sp)| match op {
-                            hir::InlineAsmOperand::Const { anon_const }
-                            | hir::InlineAsmOperand::SymFn { anon_const } => {
+                            hir::InlineAsmOperand::Const { anon_const } => {
                                 anon_const.hir_id == hir_id
                             }
                             _ => false,
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 19b78f48cfc..37c9e061091 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -35,13 +35,6 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx
     let parent_node_id = tcx.parent_hir_id(hir_id);
     let parent_node = tcx.hir_node(parent_node_id);
 
-    let find_sym_fn = |&(op, op_sp)| match op {
-        hir::InlineAsmOperand::SymFn { anon_const } if anon_const.hir_id == hir_id => {
-            Some((anon_const, op_sp))
-        }
-        _ => None,
-    };
-
     let find_const = |&(op, op_sp)| match op {
         hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == hir_id => {
             Some((anon_const, op_sp))
@@ -59,31 +52,7 @@ fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx
 
         // Anon consts outside the type system.
         Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
-        | Node::Item(&Item { kind: ItemKind::GlobalAsm { asm }, .. })
-            if let Some((anon_const, op_sp)) = asm.operands.iter().find_map(find_sym_fn) =>
-        {
-            let ty = tcx.typeck(def_id).node_type(hir_id);
-
-            match ty.kind() {
-                ty::Error(_) => ty,
-                ty::FnDef(..) => ty,
-                _ => {
-                    let guar = tcx
-                        .dcx()
-                        .struct_span_err(op_sp, "invalid `sym` operand")
-                        .with_span_label(
-                            tcx.def_span(anon_const.def_id),
-                            format!("is {} `{}`", ty.kind().article(), ty),
-                        )
-                        .with_help("`sym` operands must refer to either a function or a static")
-                        .emit();
-
-                    Ty::new_error(tcx, guar)
-                }
-            }
-        }
-        Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
-        | Node::Item(&Item { kind: ItemKind::GlobalAsm { asm }, .. })
+        | Node::Item(&Item { kind: ItemKind::GlobalAsm { asm, .. }, .. })
             if let Some((anon_const, op_sp)) = asm.operands.iter().find_map(find_const) =>
         {
             let ty = tcx.typeck(def_id).node_type(hir_id);
@@ -313,12 +282,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
                 let args = ty::GenericArgs::identity_for_item(tcx, def_id);
                 Ty::new_adt(tcx, def, args)
             }
+            ItemKind::GlobalAsm { .. } => tcx.typeck(def_id).node_type(hir_id),
             ItemKind::Trait(..)
             | ItemKind::TraitAlias(..)
             | ItemKind::Macro(..)
             | ItemKind::Mod(..)
             | ItemKind::ForeignMod { .. }
-            | ItemKind::GlobalAsm { .. }
             | ItemKind::ExternCrate(..)
             | ItemKind::Use(..) => {
                 span_bug!(item.span, "compute_type_of_item: unexpected item type: {:?}", item.kind);
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index b485b426c28..b9cdf3ddc34 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -692,7 +692,7 @@ impl<'a> State<'a> {
                 }
                 self.bclose(item.span);
             }
-            hir::ItemKind::GlobalAsm { asm } => {
+            hir::ItemKind::GlobalAsm { asm, .. } => {
                 self.head("global_asm!");
                 self.print_inline_asm(asm);
                 self.end()
@@ -1431,10 +1431,10 @@ impl<'a> State<'a> {
                     s.space();
                     s.print_anon_const(anon_const);
                 }
-                hir::InlineAsmOperand::SymFn { ref anon_const } => {
+                hir::InlineAsmOperand::SymFn { ref expr } => {
                     s.word("sym_fn");
                     s.space();
-                    s.print_anon_const(anon_const);
+                    s.print_expr(expr);
                 }
                 hir::InlineAsmOperand::SymStatic { ref path, def_id: _ } => {
                     s.word("sym_static");
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 277396da19c..0c71ef4655c 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -3763,7 +3763,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let mut diverge = asm.asm_macro.diverges(asm.options);
 
         for (op, _op_sp) in asm.operands {
-            match op {
+            match *op {
                 hir::InlineAsmOperand::In { expr, .. } => {
                     self.check_expr_asm_operand(expr, true);
                 }
@@ -3778,10 +3778,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         self.check_expr_asm_operand(out_expr, false);
                     }
                 }
+                hir::InlineAsmOperand::SymFn { expr } => {
+                    self.check_expr(expr);
+                }
                 // `AnonConst`s have their own body and is type-checked separately.
                 // As they don't flow into the type system we don't need them to
                 // be well-formed.
-                hir::InlineAsmOperand::Const { .. } | hir::InlineAsmOperand::SymFn { .. } => {}
+                hir::InlineAsmOperand::Const { .. } => {}
                 hir::InlineAsmOperand::SymStatic { .. } => {}
                 hir::InlineAsmOperand::Label { block } => {
                     let previous_diverges = self.diverges.get();
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index bce9fbbd6d1..120a43576e8 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -110,13 +110,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     self.tcx.erase_regions(ty)
                 }
             };
-            InlineAsmCtxt::new_in_fn(
-                self.tcx,
-                self.infcx.typing_env(self.param_env),
-                enclosing_id,
-                expr_ty,
-            )
-            .check_asm(asm);
+            InlineAsmCtxt::new(self.tcx, enclosing_id, expr_ty).check_asm(asm);
         }
     }
 
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index c1ed5b0aa50..0130ad775d9 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -133,7 +133,12 @@ fn typeck_with_inspect<'tcx>(
     }
     let mut fcx = FnCtxt::new(&root_ctxt, param_env, def_id);
 
-    if let Some(hir::FnSig { header, decl, .. }) = node.fn_sig() {
+    if let hir::Node::Item(hir::Item { kind: hir::ItemKind::GlobalAsm { .. }, .. }) = node {
+        // Check the fake body of a global ASM. There's not much to do here except
+        // for visit the asm expr of the body.
+        let ty = fcx.check_expr(body.value);
+        fcx.write_ty(id, ty);
+    } else if let Some(hir::FnSig { header, decl, .. }) = node.fn_sig() {
         let fn_sig = if decl.output.is_suggestable_infer_ty().is_some() {
             // In the case that we're recovering `fn() -> W<_>` or some other return
             // type that has an infer in it, lower the type directly so that it'll
@@ -277,12 +282,9 @@ fn infer_type_if_missing<'tcx>(fcx: &FnCtxt<'_, 'tcx>, node: Node<'tcx>) -> Opti
                 Some(fcx.next_ty_var(span))
             }
             Node::Expr(&hir::Expr { kind: hir::ExprKind::InlineAsm(asm), span, .. })
-            | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm { asm }, span, .. }) => {
+            | Node::Item(&hir::Item { kind: hir::ItemKind::GlobalAsm { asm, .. }, span, .. }) => {
                 asm.operands.iter().find_map(|(op, _op_sp)| match op {
-                    hir::InlineAsmOperand::Const { anon_const }
-                    | hir::InlineAsmOperand::SymFn { anon_const }
-                        if anon_const.hir_id == id =>
-                    {
+                    hir::InlineAsmOperand::Const { anon_const } if anon_const.hir_id == id => {
                         Some(fcx.next_ty_var(span))
                     }
                     _ => None,
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 8c50cc59c1d..3e9ce0e11e4 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -48,13 +48,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         for param in body.params {
             wbcx.visit_node_id(param.pat.span, param.hir_id);
         }
-        // Type only exists for constants and statics, not functions.
         match self.tcx.hir_body_owner_kind(item_def_id) {
-            hir::BodyOwnerKind::Const { .. } | hir::BodyOwnerKind::Static(_) => {
+            // Visit the type of a const or static, which is used during THIR building.
+            hir::BodyOwnerKind::Const { .. }
+            | hir::BodyOwnerKind::Static(_)
+            | hir::BodyOwnerKind::GlobalAsm => {
                 let item_hir_id = self.tcx.local_def_id_to_hir_id(item_def_id);
                 wbcx.visit_node_id(body.value.span, item_hir_id);
             }
-            hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => (),
+            // For closures and consts, we already plan to visit liberated signatures.
+            hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => {}
         }
         wbcx.visit_body(body);
         wbcx.visit_min_capture_map();
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index b5f09ff346a..6c5a2dcd146 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -2909,7 +2909,13 @@ enum AsmLabelKind {
 impl<'tcx> LateLintPass<'tcx> for AsmLabels {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
         if let hir::Expr {
-            kind: hir::ExprKind::InlineAsm(hir::InlineAsm { template_strs, options, .. }),
+            kind:
+                hir::ExprKind::InlineAsm(hir::InlineAsm {
+                    asm_macro: AsmMacro::Asm | AsmMacro::NakedAsm,
+                    template_strs,
+                    options,
+                    ..
+                }),
             ..
         } = expr
         {
diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs
index 832f8026614..ec046d82ef6 100644
--- a/compiler/rustc_middle/src/hir/map.rs
+++ b/compiler/rustc_middle/src/hir/map.rs
@@ -305,6 +305,7 @@ impl<'tcx> TyCtxt<'tcx> {
             DefKind::Static { safety: _, mutability, nested: false } => {
                 BodyOwnerKind::Static(mutability)
             }
+            DefKind::GlobalAsm => BodyOwnerKind::GlobalAsm,
             dk => bug!("{:?} is not a body node: {:?}", def_id, dk),
         }
     }
@@ -327,7 +328,7 @@ impl<'tcx> TyCtxt<'tcx> {
                 ConstContext::ConstFn
             }
             BodyOwnerKind::Fn if self.is_const_default_method(def_id) => ConstContext::ConstFn,
-            BodyOwnerKind::Fn | BodyOwnerKind::Closure => return None,
+            BodyOwnerKind::Fn | BodyOwnerKind::Closure | BodyOwnerKind::GlobalAsm => return None,
         };
 
         Some(ccx)
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 98cc00c367c..6a2672ac02b 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -94,6 +94,7 @@ thir_with_elements! {
 pub enum BodyTy<'tcx> {
     Const(Ty<'tcx>),
     Fn(FnSig<'tcx>),
+    GlobalAsm(Ty<'tcx>),
 }
 
 /// Description of a type-checked function parameter.
@@ -605,8 +606,7 @@ pub enum InlineAsmOperand<'tcx> {
         span: Span,
     },
     SymFn {
-        value: mir::Const<'tcx>,
-        span: Span,
+        value: ExprId,
     },
     SymStatic {
         def_id: DefId,
diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs
index 13b8af55e51..e347a64e45d 100644
--- a/compiler/rustc_middle/src/thir/visit.rs
+++ b/compiler/rustc_middle/src/thir/visit.rs
@@ -172,7 +172,7 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
                     }
                     Out { expr: None, reg: _, late: _ }
                     | Const { value: _, span: _ }
-                    | SymFn { value: _, span: _ }
+                    | SymFn { value: _ }
                     | SymStatic { def_id: _ } => {}
                     Label { block } => visitor.visit_block(&visitor.thir()[*block]),
                 }
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 32a9e67f9ad..361e204fb0f 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1472,7 +1472,11 @@ impl<'tcx> TyCtxt<'tcx> {
             self.codegen_fn_attrs(def_id)
         } else if matches!(
             def_kind,
-            DefKind::AnonConst | DefKind::AssocConst | DefKind::Const | DefKind::InlineConst
+            DefKind::AnonConst
+                | DefKind::AssocConst
+                | DefKind::Const
+                | DefKind::InlineConst
+                | DefKind::GlobalAsm
         ) {
             CodegenFnAttrs::EMPTY
         } else {
diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs
index 65dd061003d..72443e2f60d 100644
--- a/compiler/rustc_mir_build/src/builder/expr/into.rs
+++ b/compiler/rustc_mir_build/src/builder/expr/into.rs
@@ -482,15 +482,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                                 }),
                             }
                         }
-                        thir::InlineAsmOperand::SymFn { value, span } => {
-                            mir::InlineAsmOperand::SymFn {
-                                value: Box::new(ConstOperand {
-                                    span,
-                                    user_ty: None,
-                                    const_: value,
-                                }),
-                            }
-                        }
+                        thir::InlineAsmOperand::SymFn { value } => mir::InlineAsmOperand::SymFn {
+                            value: Box::new(this.as_constant(&this.thir[value])),
+                        },
                         thir::InlineAsmOperand::SymStatic { def_id } => {
                             mir::InlineAsmOperand::SymStatic { def_id }
                         }
@@ -518,10 +512,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 }
 
                 let asm_macro = match asm_macro {
-                    AsmMacro::Asm => InlineAsmMacro::Asm,
-                    AsmMacro::GlobalAsm => {
-                        span_bug!(expr_span, "unexpected global_asm! in inline asm")
-                    }
+                    AsmMacro::Asm | AsmMacro::GlobalAsm => InlineAsmMacro::Asm,
                     AsmMacro::NakedAsm => InlineAsmMacro::NakedAsm,
                 };
 
diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs
index 4348b7a4b4c..94955954934 100644
--- a/compiler/rustc_mir_build/src/builder/mod.rs
+++ b/compiler/rustc_mir_build/src/builder/mod.rs
@@ -61,7 +61,9 @@ pub fn build_mir<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Body<'tcx> {
         Ok((thir, expr)) => {
             let build_mir = |thir: &Thir<'tcx>| match thir.body_type {
                 thir::BodyTy::Fn(fn_sig) => construct_fn(tcx, def, thir, expr, fn_sig),
-                thir::BodyTy::Const(ty) => construct_const(tcx, def, thir, expr, ty),
+                thir::BodyTy::Const(ty) | thir::BodyTy::GlobalAsm(ty) => {
+                    construct_const(tcx, def, thir, expr, ty)
+                }
             };
 
             // this must run before MIR dump, because
@@ -576,6 +578,7 @@ fn construct_const<'a, 'tcx>(
             let span = tcx.def_span(def);
             (span, span)
         }
+        Node::Item(hir::Item { kind: hir::ItemKind::GlobalAsm { .. }, span, .. }) => (*span, *span),
         _ => span_bug!(tcx.def_span(def), "can't build MIR for {:?}", def),
     };
 
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index d65c2097d22..c2eafd0a74e 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -2,6 +2,7 @@ use std::borrow::Cow;
 use std::mem;
 use std::ops::Bound;
 
+use rustc_ast::AsmMacro;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::DiagArgValue;
 use rustc_hir::def::DefKind;
@@ -559,7 +560,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
                 }
             }
             ExprKind::InlineAsm(box InlineAsmExpr {
-                asm_macro: _,
+                asm_macro: AsmMacro::Asm | AsmMacro::NakedAsm,
                 ref operands,
                 template: _,
                 options: _,
@@ -583,7 +584,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
                         }
                         Out { expr: None, reg: _, late: _ }
                         | Const { value: _, span: _ }
-                        | SymFn { value: _, span: _ }
+                        | SymFn { value: _ }
                         | SymStatic { def_id: _ } => {}
                         Label { block } => {
                             // Label blocks are safe context.
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index d0fca76fcf0..29bc1d6572d 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -739,13 +739,8 @@ impl<'tcx> ThirBuildCx<'tcx> {
 
                             InlineAsmOperand::Const { value, span }
                         }
-                        hir::InlineAsmOperand::SymFn { ref anon_const } => {
-                            let value =
-                                mir::Const::from_unevaluated(tcx, anon_const.def_id.to_def_id())
-                                    .instantiate_identity();
-                            let span = tcx.def_span(anon_const.def_id);
-
-                            InlineAsmOperand::SymFn { value, span }
+                        hir::InlineAsmOperand::SymFn { expr } => {
+                            InlineAsmOperand::SymFn { value: self.mirror_expr(expr) }
                         }
                         hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
                             InlineAsmOperand::SymStatic { def_id }
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index 7a9f6e46304..c32082c609e 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -76,23 +76,29 @@ impl<'tcx> ThirBuildCx<'tcx> {
         let hir = tcx.hir();
         let hir_id = tcx.local_def_id_to_hir_id(def);
 
-        let body_type = if tcx.hir_body_owner_kind(def).is_fn_or_closure() {
-            // fetch the fully liberated fn signature (that is, all bound
-            // types/lifetimes replaced)
-            BodyTy::Fn(typeck_results.liberated_fn_sigs()[hir_id])
-        } else {
-            // Get the revealed type of this const. This is *not* the adjusted
-            // type of its body, which may be a subtype of this type. For
-            // example:
-            //
-            // fn foo(_: &()) {}
-            // static X: fn(&'static ()) = foo;
-            //
-            // The adjusted type of the body of X is `for<'a> fn(&'a ())` which
-            // is not the same as the type of X. We need the type of the return
-            // place to be the type of the constant because NLL typeck will
-            // equate them.
-            BodyTy::Const(typeck_results.node_type(hir_id))
+        let body_type = match tcx.hir_body_owner_kind(def) {
+            rustc_hir::BodyOwnerKind::Fn | rustc_hir::BodyOwnerKind::Closure => {
+                // fetch the fully liberated fn signature (that is, all bound
+                // types/lifetimes replaced)
+                BodyTy::Fn(typeck_results.liberated_fn_sigs()[hir_id])
+            }
+            rustc_hir::BodyOwnerKind::Const { .. } | rustc_hir::BodyOwnerKind::Static(_) => {
+                // Get the revealed type of this const. This is *not* the adjusted
+                // type of its body, which may be a subtype of this type. For
+                // example:
+                //
+                // fn foo(_: &()) {}
+                // static X: fn(&'static ()) = foo;
+                //
+                // The adjusted type of the body of X is `for<'a> fn(&'a ())` which
+                // is not the same as the type of X. We need the type of the return
+                // place to be the type of the constant because NLL typeck will
+                // equate them.
+                BodyTy::Const(typeck_results.node_type(hir_id))
+            }
+            rustc_hir::BodyOwnerKind::GlobalAsm => {
+                BodyTy::GlobalAsm(typeck_results.node_type(hir_id))
+            }
         };
 
         Self {
diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs
index 9ab87dd99ff..cd56d93afcf 100644
--- a/compiler/rustc_mir_build/src/thir/print.rs
+++ b/compiler/rustc_mir_build/src/thir/print.rs
@@ -921,10 +921,10 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
                 print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
                 print_indented!(self, "}", depth_lvl + 1);
             }
-            InlineAsmOperand::SymFn { value, span } => {
+            InlineAsmOperand::SymFn { value } => {
                 print_indented!(self, "InlineAsmOperand::SymFn {", depth_lvl);
-                print_indented!(self, format!("value: {:?}", *value), depth_lvl + 1);
-                print_indented!(self, format!("span: {:?}", span), depth_lvl + 1);
+                print_indented!(self, "value: ", depth_lvl + 1);
+                self.print_expr(*value, depth_lvl + 2);
                 print_indented!(self, "}", depth_lvl + 1);
             }
             InlineAsmOperand::SymStatic { def_id } => {
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index bf56f468179..694a4dd5b4c 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -479,24 +479,23 @@ fn collect_items_rec<'tcx>(
             recursion_depth_reset = None;
 
             let item = tcx.hir_item(item_id);
-            if let hir::ItemKind::GlobalAsm { asm } = item.kind {
+            if let hir::ItemKind::GlobalAsm { asm, .. } = item.kind {
                 for (op, op_sp) in asm.operands {
-                    match op {
+                    match *op {
                         hir::InlineAsmOperand::Const { .. } => {
                             // Only constants which resolve to a plain integer
                             // are supported. Therefore the value should not
                             // depend on any other items.
                         }
-                        hir::InlineAsmOperand::SymFn { anon_const } => {
-                            let fn_ty =
-                                tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id);
+                        hir::InlineAsmOperand::SymFn { expr } => {
+                            let fn_ty = tcx.typeck(item_id.owner_id).expr_ty(expr);
                             visit_fn_use(tcx, fn_ty, false, *op_sp, &mut used_items);
                         }
                         hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
-                            let instance = Instance::mono(tcx, *def_id);
+                            let instance = Instance::mono(tcx, def_id);
                             if tcx.should_codegen_locally(instance) {
                                 trace!("collecting static {:?}", def_id);
-                                used_items.push(dummy_spanned(MonoItem::Static(*def_id)));
+                                used_items.push(dummy_spanned(MonoItem::Static(def_id)));
                             }
                         }
                         hir::InlineAsmOperand::In { .. }