about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbjorn3 <17426603+bjorn3@users.noreply.github.com>2024-12-12 20:31:20 +0000
committerbjorn3 <17426603+bjorn3@users.noreply.github.com>2025-04-14 09:38:04 +0000
commitf5c93fa3feb29b1161acf07191ff2684776b9abf (patch)
tree6b595ac247b650cbab2fbacc8eee3cdf98a44eb8
parent421f22e8bf404d7b67395a66e60300e99452549a (diff)
downloadrust-f5c93fa3feb29b1161acf07191ff2684776b9abf.tar.gz
rust-f5c93fa3feb29b1161acf07191ff2684776b9abf.zip
Use cg_ssa's version of codegen_naked_asm in cg_clif
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs39
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/aot.rs37
-rw-r--r--compiler/rustc_codegen_cranelift/src/driver/jit.rs12
-rw-r--r--compiler/rustc_codegen_cranelift/src/global_asm.rs260
-rw-r--r--compiler/rustc_codegen_cranelift/src/inline_asm.rs193
5 files changed, 258 insertions, 283 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index adaa754491e..4acbd4b9559 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -8,8 +8,6 @@ use rustc_ast::InlineAsmOptions;
 use rustc_codegen_ssa::base::is_call_from_compiler_builtins_to_upstream_monomorphization;
 use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_index::IndexVec;
-use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
-use rustc_middle::mir::InlineAsmMacro;
 use rustc_middle::ty::TypeVisitableExt;
 use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv};
@@ -18,7 +16,6 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
 use crate::constant::ConstantCx;
 use crate::debuginfo::{FunctionDebugContext, TypeDebugContext};
 use crate::enable_verifier;
-use crate::inline_asm::codegen_naked_asm;
 use crate::prelude::*;
 use crate::pretty_clif::CommentWriter;
 
@@ -37,7 +34,7 @@ pub(crate) fn codegen_fn<'tcx>(
     cached_func: Function,
     module: &mut dyn Module,
     instance: Instance<'tcx>,
-) -> Option<CodegenedFunction> {
+) -> CodegenedFunction {
     debug_assert!(!instance.args.has_infer());
 
     let symbol_name = tcx.symbol_name(instance).name.to_string();
@@ -54,38 +51,6 @@ pub(crate) fn codegen_fn<'tcx>(
         String::from_utf8_lossy(&buf).into_owned()
     });
 
-    if tcx.codegen_fn_attrs(instance.def_id()).flags.contains(CodegenFnAttrFlags::NAKED) {
-        assert_eq!(mir.basic_blocks.len(), 1);
-        assert!(mir.basic_blocks[START_BLOCK].statements.is_empty());
-
-        match &mir.basic_blocks[START_BLOCK].terminator().kind {
-            TerminatorKind::InlineAsm {
-                asm_macro: InlineAsmMacro::NakedAsm,
-                template,
-                operands,
-                options,
-                line_spans: _,
-                targets: _,
-                unwind: _,
-            } => {
-                codegen_naked_asm(
-                    tcx,
-                    cx,
-                    module,
-                    instance,
-                    mir.basic_blocks[START_BLOCK].terminator().source_info.span,
-                    &symbol_name,
-                    template,
-                    operands,
-                    *options,
-                );
-            }
-            _ => unreachable!(),
-        }
-
-        return None;
-    }
-
     // Declare function
     let sig = get_function_sig(tcx, module.target_config().default_call_conv, instance);
     let func_id = module.declare_function(&symbol_name, Linkage::Local, &sig).unwrap();
@@ -166,7 +131,7 @@ pub(crate) fn codegen_fn<'tcx>(
     // Verify function
     verify_func(tcx, &clif_comments, &func);
 
-    Some(CodegenedFunction { symbol_name, func_id, func, clif_comments, func_debug_cx })
+    CodegenedFunction { symbol_name, func_id, func, clif_comments, func_debug_cx }
 }
 
 pub(crate) fn compile_fn(
diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
index 00136ac4a57..1cb8f8bc439 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs
@@ -22,7 +22,10 @@ use rustc_data_structures::sync::{IntoDynSyncSend, par_map};
 use rustc_metadata::EncodedMetadata;
 use rustc_metadata::fs::copy_to_stdout;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
-use rustc_middle::mir::mono::{CodegenUnit, MonoItem};
+use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
+use rustc_middle::mir::mono::{
+    CodegenUnit, Linkage as RLinkage, MonoItem, MonoItemData, Visibility,
+};
 use rustc_session::Session;
 use rustc_session::config::{DebugInfo, OutFileName, OutputFilenames, OutputType};
 
@@ -30,7 +33,7 @@ use crate::CodegenCx;
 use crate::base::CodegenedFunction;
 use crate::concurrency_limiter::{ConcurrencyLimiter, ConcurrencyLimiterToken};
 use crate::debuginfo::TypeDebugContext;
-use crate::global_asm::GlobalAsmConfig;
+use crate::global_asm::{GlobalAsmConfig, GlobalAsmContext};
 use crate::prelude::*;
 use crate::unwind_module::UnwindModule;
 
@@ -530,19 +533,35 @@ fn codegen_cgu_content(
     let mut type_dbg = TypeDebugContext::default();
     super::predefine_mono_items(tcx, module, &mono_items);
     let mut codegened_functions = vec![];
-    for (mono_item, _) in mono_items {
+    for (mono_item, item_data) in mono_items {
         match mono_item {
-            MonoItem::Fn(inst) => {
-                if let Some(codegened_function) = crate::base::codegen_fn(
+            MonoItem::Fn(instance) => {
+                if tcx.codegen_fn_attrs(instance.def_id()).flags.contains(CodegenFnAttrFlags::NAKED)
+                {
+                    rustc_codegen_ssa::mir::naked_asm::codegen_naked_asm(
+                        &mut GlobalAsmContext { tcx, global_asm: &mut cx.global_asm },
+                        instance,
+                        MonoItemData {
+                            linkage: RLinkage::External,
+                            visibility: if item_data.linkage == RLinkage::Internal {
+                                Visibility::Hidden
+                            } else {
+                                item_data.visibility
+                            },
+                            ..item_data
+                        },
+                    );
+                    continue;
+                }
+                let codegened_function = crate::base::codegen_fn(
                     tcx,
                     &mut cx,
                     &mut type_dbg,
                     Function::new(),
                     module,
-                    inst,
-                ) {
-                    codegened_functions.push(codegened_function);
-                }
+                    instance,
+                );
+                codegened_functions.push(codegened_function);
             }
             MonoItem::Static(def_id) => {
                 let data_id = crate::constant::codegen_static(tcx, module, def_id);
diff --git a/compiler/rustc_codegen_cranelift/src/driver/jit.rs b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
index 41f8bb9161c..e368cf4386d 100644
--- a/compiler/rustc_codegen_cranelift/src/driver/jit.rs
+++ b/compiler/rustc_codegen_cranelift/src/driver/jit.rs
@@ -126,6 +126,11 @@ pub(crate) fn codegen_and_compile_fn<'tcx>(
     module: &mut dyn Module,
     instance: Instance<'tcx>,
 ) {
+    if tcx.codegen_fn_attrs(instance.def_id()).flags.contains(CodegenFnAttrFlags::NAKED) {
+        tcx.dcx()
+            .span_fatal(tcx.def_span(instance.def_id()), "Naked asm is not supported in JIT mode");
+    }
+
     cranelift_codegen::timing::set_thread_profiler(Box::new(super::MeasuremeProfiler(
         tcx.prof.clone(),
     )));
@@ -135,16 +140,15 @@ pub(crate) fn codegen_and_compile_fn<'tcx>(
             crate::PrintOnPanic(|| format!("{:?} {}", instance, tcx.symbol_name(instance).name));
 
         let cached_func = std::mem::replace(&mut cached_context.func, Function::new());
-        if let Some(codegened_func) = crate::base::codegen_fn(
+        let codegened_func = crate::base::codegen_fn(
             tcx,
             cx,
             &mut TypeDebugContext::default(),
             cached_func,
             module,
             instance,
-        ) {
-            crate::base::compile_fn(cx, &tcx.prof, cached_context, module, codegened_func);
-        }
+        );
+        crate::base::compile_fn(cx, &tcx.prof, cached_context, module, codegened_func);
     });
 }
 
diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs
index 79cefb05de3..18944a3be27 100644
--- a/compiler/rustc_codegen_cranelift/src/global_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs
@@ -7,102 +7,206 @@ use std::process::{Command, Stdio};
 use std::sync::Arc;
 
 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
+use rustc_codegen_ssa::traits::{AsmCodegenMethods, GlobalAsmOperandRef};
 use rustc_hir::{InlineAsmOperand, ItemId};
 use rustc_middle::mir::interpret::ErrorHandled;
+use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::layout::{
+    FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers,
+};
 use rustc_session::config::{OutputFilenames, OutputType};
 use rustc_target::asm::InlineAsmArch;
 
 use crate::prelude::*;
 
+pub(crate) struct GlobalAsmContext<'a, 'tcx> {
+    pub tcx: TyCtxt<'tcx>,
+    pub global_asm: &'a mut String,
+}
+
+impl<'tcx> AsmCodegenMethods<'tcx> for GlobalAsmContext<'_, 'tcx> {
+    fn codegen_global_asm(
+        &mut self,
+        template: &[InlineAsmTemplatePiece],
+        operands: &[GlobalAsmOperandRef<'tcx>],
+        options: InlineAsmOptions,
+        _line_spans: &[Span],
+    ) {
+        codegen_global_asm_inner(self.tcx, self.global_asm, template, operands, options);
+    }
+
+    fn mangled_name(&self, instance: Instance<'tcx>) -> String {
+        self.tcx.symbol_name(instance).name.to_owned()
+    }
+}
+
+impl<'tcx> LayoutOfHelpers<'tcx> for GlobalAsmContext<'_, 'tcx> {
+    #[inline]
+    fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
+        if let LayoutError::SizeOverflow(_) | LayoutError::ReferencesError(_) = err {
+            self.tcx.sess.dcx().span_fatal(span, err.to_string())
+        } else {
+            self.tcx
+                .sess
+                .dcx()
+                .span_fatal(span, format!("failed to get layout for `{}`: {}", ty, err))
+        }
+    }
+}
+
+impl<'tcx> FnAbiOfHelpers<'tcx> for GlobalAsmContext<'_, 'tcx> {
+    #[inline]
+    fn handle_fn_abi_err(
+        &self,
+        err: FnAbiError<'tcx>,
+        span: Span,
+        fn_abi_request: FnAbiRequest<'tcx>,
+    ) -> ! {
+        FullyMonomorphizedLayoutCx(self.tcx).handle_fn_abi_err(err, span, fn_abi_request)
+    }
+}
+
+impl<'tcx> HasTyCtxt<'tcx> for GlobalAsmContext<'_, 'tcx> {
+    fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+}
+
+impl<'tcx> rustc_abi::HasDataLayout for GlobalAsmContext<'_, 'tcx> {
+    fn data_layout(&self) -> &rustc_abi::TargetDataLayout {
+        &self.tcx.data_layout
+    }
+}
+
+impl<'tcx> HasTypingEnv<'tcx> for GlobalAsmContext<'_, 'tcx> {
+    fn typing_env(&self) -> ty::TypingEnv<'tcx> {
+        ty::TypingEnv::fully_monomorphized()
+    }
+}
+
 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 {
-        let is_x86 =
-            matches!(tcx.sess.asm_arch.unwrap(), InlineAsmArch::X86 | InlineAsmArch::X86_64);
-
-        if is_x86 {
-            if !asm.options.contains(InlineAsmOptions::ATT_SYNTAX) {
-                global_asm.push_str("\n.intel_syntax noprefix\n");
-            } else {
-                global_asm.push_str("\n.att_syntax\n");
+    let rustc_hir::ItemKind::GlobalAsm { asm, .. } = item.kind else {
+        bug!("Expected GlobalAsm found {:?}", item);
+    };
+
+    // Adapted from rustc_codegen_ssa::mono_items::MonoItem::define
+    let operands: Vec<_> = asm
+        .operands
+        .iter()
+        .map(|(op, op_sp)| match *op {
+            InlineAsmOperand::Const { ref anon_const } => {
+                match tcx.const_eval_poly(anon_const.def_id.to_def_id()) {
+                    Ok(const_value) => {
+                        let ty = tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id);
+                        let string = rustc_codegen_ssa::common::asm_const_to_str(
+                            tcx,
+                            *op_sp,
+                            const_value,
+                            FullyMonomorphizedLayoutCx(tcx).layout_of(ty),
+                        );
+                        GlobalAsmOperandRef::Const { string }
+                    }
+                    Err(ErrorHandled::Reported { .. }) => {
+                        // An error has already been reported and
+                        // compilation is guaranteed to fail if execution
+                        // hits this path. So an empty string instead of
+                        // a stringified constant value will suffice.
+                        GlobalAsmOperandRef::Const { string: String::new() }
+                    }
+                    Err(ErrorHandled::TooGeneric(_)) => {
+                        span_bug!(*op_sp, "asm const cannot be resolved; too generic")
+                    }
+                }
+            }
+            InlineAsmOperand::SymFn { expr } => {
+                if cfg!(not(feature = "inline_asm_sym")) {
+                    tcx.dcx().span_err(
+                        item.span,
+                        "asm! and global_asm! sym operands are not yet supported",
+                    );
+                }
+
+                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"),
+                };
+                GlobalAsmOperandRef::SymFn { instance }
             }
+            InlineAsmOperand::SymStatic { path: _, def_id } => {
+                GlobalAsmOperandRef::SymStatic { def_id }
+            }
+            InlineAsmOperand::In { .. }
+            | InlineAsmOperand::Out { .. }
+            | InlineAsmOperand::InOut { .. }
+            | InlineAsmOperand::SplitInOut { .. }
+            | InlineAsmOperand::Label { .. } => {
+                span_bug!(*op_sp, "invalid operand type for global_asm!")
+            }
+        })
+        .collect();
+
+    codegen_global_asm_inner(tcx, global_asm, asm.template, &operands, asm.options);
+}
+
+fn codegen_global_asm_inner<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    global_asm: &mut String,
+    template: &[InlineAsmTemplatePiece],
+    operands: &[GlobalAsmOperandRef<'tcx>],
+    options: InlineAsmOptions,
+) {
+    let is_x86 = matches!(tcx.sess.asm_arch.unwrap(), InlineAsmArch::X86 | InlineAsmArch::X86_64);
+
+    if is_x86 {
+        if !options.contains(InlineAsmOptions::ATT_SYNTAX) {
+            global_asm.push_str("\n.intel_syntax noprefix\n");
+        } else {
+            global_asm.push_str("\n.att_syntax\n");
         }
-        for piece in asm.template {
-            match *piece {
-                InlineAsmTemplatePiece::String(ref s) => global_asm.push_str(s),
-                InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: op_sp } => {
-                    match asm.operands[operand_idx].0 {
-                        InlineAsmOperand::Const { ref anon_const } => {
-                            match tcx.const_eval_poly(anon_const.def_id.to_def_id()) {
-                                Ok(const_value) => {
-                                    let ty = tcx
-                                        .typeck_body(anon_const.body)
-                                        .node_type(anon_const.hir_id);
-                                    let string = rustc_codegen_ssa::common::asm_const_to_str(
-                                        tcx,
-                                        op_sp,
-                                        const_value,
-                                        FullyMonomorphizedLayoutCx(tcx).layout_of(ty),
-                                    );
-                                    global_asm.push_str(&string);
-                                }
-                                Err(ErrorHandled::Reported { .. }) => {
-                                    // An error has already been reported and compilation is
-                                    // guaranteed to fail if execution hits this path.
-                                }
-                                Err(ErrorHandled::TooGeneric(_)) => {
-                                    span_bug!(op_sp, "asm const cannot be resolved; too generic");
-                                }
-                            }
-                        }
-                        InlineAsmOperand::SymFn { expr } => {
-                            if cfg!(not(feature = "inline_asm_sym")) {
-                                tcx.dcx().span_err(
-                                    item.span,
-                                    "asm! and global_asm! sym operands are not yet supported",
-                                );
-                            }
-
-                            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"),
-                            };
-                            let symbol = tcx.symbol_name(instance);
-                            // FIXME handle the case where the function was made private to the
-                            // current codegen unit
-                            global_asm.push_str(symbol.name);
-                        }
-                        InlineAsmOperand::SymStatic { path: _, def_id } => {
-                            if cfg!(not(feature = "inline_asm_sym")) {
-                                tcx.dcx().span_err(
-                                    item.span,
-                                    "asm! and global_asm! sym operands are not yet supported",
-                                );
-                            }
-
-                            let instance = Instance::mono(tcx, def_id);
-                            let symbol = tcx.symbol_name(instance);
-                            global_asm.push_str(symbol.name);
+    }
+    for piece in template {
+        match *piece {
+            InlineAsmTemplatePiece::String(ref s) => global_asm.push_str(s),
+            InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span } => {
+                match operands[operand_idx] {
+                    GlobalAsmOperandRef::Const { ref string } => {
+                        global_asm.push_str(string);
+                    }
+                    GlobalAsmOperandRef::SymFn { instance } => {
+                        if cfg!(not(feature = "inline_asm_sym")) {
+                            tcx.dcx().span_err(
+                                span,
+                                "asm! and global_asm! sym operands are not yet supported",
+                            );
                         }
-                        InlineAsmOperand::In { .. }
-                        | InlineAsmOperand::Out { .. }
-                        | InlineAsmOperand::InOut { .. }
-                        | InlineAsmOperand::SplitInOut { .. }
-                        | InlineAsmOperand::Label { .. } => {
-                            span_bug!(op_sp, "invalid operand type for global_asm!")
+
+                        let symbol = tcx.symbol_name(instance);
+                        // FIXME handle the case where the function was made private to the
+                        // current codegen unit
+                        global_asm.push_str(symbol.name);
+                    }
+                    GlobalAsmOperandRef::SymStatic { def_id } => {
+                        if cfg!(not(feature = "inline_asm_sym")) {
+                            tcx.dcx().span_err(
+                                span,
+                                "asm! and global_asm! sym operands are not yet supported",
+                            );
                         }
+
+                        let instance = Instance::mono(tcx, def_id);
+                        let symbol = tcx.symbol_name(instance);
+                        global_asm.push_str(symbol.name);
                     }
                 }
             }
         }
+    }
 
-        global_asm.push('\n');
-        if is_x86 {
-            global_asm.push_str(".att_syntax\n\n");
-        }
-    } else {
-        bug!("Expected GlobalAsm found {:?}", item);
+    global_asm.push('\n');
+    if is_x86 {
+        global_asm.push_str(".att_syntax\n\n");
     }
 }
 
diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
index fbc33a64285..afee5095549 100644
--- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
@@ -161,7 +161,6 @@ pub(crate) fn codegen_inline_asm_inner<'tcx>(
         stack_slots_input: Vec::new(),
         stack_slots_output: Vec::new(),
         stack_slot_size: Size::from_bytes(0),
-        is_naked: false,
     };
     asm_gen.allocate_registers();
     asm_gen.allocate_stack_slots();
@@ -201,114 +200,6 @@ pub(crate) fn codegen_inline_asm_inner<'tcx>(
     call_inline_asm(fx, &asm_name, asm_gen.stack_slot_size, inputs, outputs);
 }
 
-pub(crate) fn codegen_naked_asm<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    cx: &mut crate::CodegenCx,
-    module: &mut dyn Module,
-    instance: Instance<'tcx>,
-    span: Span,
-    symbol_name: &str,
-    template: &[InlineAsmTemplatePiece],
-    operands: &[InlineAsmOperand<'tcx>],
-    options: InlineAsmOptions,
-) {
-    // FIXME add .eh_frame unwind info directives
-
-    let operands = operands
-        .iter()
-        .map(|operand| match *operand {
-            InlineAsmOperand::In { .. }
-            | InlineAsmOperand::Out { .. }
-            | InlineAsmOperand::InOut { .. } => {
-                span_bug!(span, "invalid operand type for naked asm")
-            }
-            InlineAsmOperand::Const { ref value } => {
-                let cv = instance.instantiate_mir_and_normalize_erasing_regions(
-                    tcx,
-                    ty::TypingEnv::fully_monomorphized(),
-                    ty::EarlyBinder::bind(value.const_),
-                );
-                let const_value = cv
-                    .eval(tcx, ty::TypingEnv::fully_monomorphized(), value.span)
-                    .expect("erroneous constant missed by mono item collection");
-
-                let value = rustc_codegen_ssa::common::asm_const_to_str(
-                    tcx,
-                    span,
-                    const_value,
-                    FullyMonomorphizedLayoutCx(tcx).layout_of(cv.ty()),
-                );
-                CInlineAsmOperand::Const { value }
-            }
-            InlineAsmOperand::SymFn { ref value } => {
-                if cfg!(not(feature = "inline_asm_sym")) {
-                    tcx.dcx()
-                        .span_err(span, "asm! and global_asm! sym operands are not yet supported");
-                }
-
-                let const_ = instance.instantiate_mir_and_normalize_erasing_regions(
-                    tcx,
-                    ty::TypingEnv::fully_monomorphized(),
-                    ty::EarlyBinder::bind(value.const_),
-                );
-                if let ty::FnDef(def_id, args) = *const_.ty().kind() {
-                    let instance = ty::Instance::resolve_for_fn_ptr(
-                        tcx,
-                        ty::TypingEnv::fully_monomorphized(),
-                        def_id,
-                        args,
-                    )
-                    .unwrap();
-                    let symbol = tcx.symbol_name(instance);
-
-                    // Pass a wrapper rather than the function itself as the function itself may not
-                    // be exported from the main codegen unit and may thus be unreachable from the
-                    // object file created by an external assembler.
-                    let wrapper_name = format!(
-                        "__inline_asm_{}_wrapper_n{}",
-                        cx.cgu_name.as_str().replace('.', "__").replace('-', "_"),
-                        cx.inline_asm_index
-                    );
-                    cx.inline_asm_index += 1;
-                    let sig =
-                        get_function_sig(tcx, module.target_config().default_call_conv, instance);
-                    create_wrapper_function(module, sig, &wrapper_name, symbol.name);
-
-                    CInlineAsmOperand::Symbol { symbol: wrapper_name }
-                } else {
-                    span_bug!(span, "invalid type for asm sym (fn)");
-                }
-            }
-            InlineAsmOperand::SymStatic { def_id } => {
-                assert!(tcx.is_static(def_id));
-                let instance = Instance::mono(tcx, def_id);
-                CInlineAsmOperand::Symbol { symbol: tcx.symbol_name(instance).name.to_owned() }
-            }
-            InlineAsmOperand::Label { .. } => {
-                span_bug!(span, "asm! label operands are not yet supported");
-            }
-        })
-        .collect::<Vec<_>>();
-
-    let asm_gen = InlineAssemblyGenerator {
-        tcx,
-        arch: tcx.sess.asm_arch.unwrap(),
-        enclosing_def_id: instance.def_id(),
-        template,
-        operands: &operands,
-        options,
-        registers: Vec::new(),
-        stack_slots_clobber: Vec::new(),
-        stack_slots_input: Vec::new(),
-        stack_slots_output: Vec::new(),
-        stack_slot_size: Size::from_bytes(0),
-        is_naked: true,
-    };
-
-    let generated_asm = asm_gen.generate_asm_wrapper(symbol_name);
-    cx.global_asm.push_str(&generated_asm);
-}
-
 struct InlineAssemblyGenerator<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     arch: InlineAsmArch,
@@ -321,13 +212,10 @@ struct InlineAssemblyGenerator<'a, 'tcx> {
     stack_slots_input: Vec<Option<Size>>,
     stack_slots_output: Vec<Option<Size>>,
     stack_slot_size: Size,
-    is_naked: bool,
 }
 
 impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
     fn allocate_registers(&mut self) {
-        assert!(!self.is_naked);
-
         let sess = self.tcx.sess;
         let map = allocatable_registers(
             self.arch,
@@ -451,8 +339,6 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
     }
 
     fn allocate_stack_slots(&mut self) {
-        assert!(!self.is_naked);
-
         let mut slot_size = Size::from_bytes(0);
         let mut slots_clobber = vec![None; self.operands.len()];
         let mut slots_input = vec![None; self.operands.len()];
@@ -582,32 +468,31 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
         if is_x86 {
             generated_asm.push_str(".intel_syntax noprefix\n");
         }
-        if !self.is_naked {
-            Self::prologue(&mut generated_asm, self.arch);
-
-            // Save clobbered registers
-            if !self.options.contains(InlineAsmOptions::NORETURN) {
-                for (reg, slot) in self
-                    .registers
-                    .iter()
-                    .zip(self.stack_slots_clobber.iter().copied())
-                    .filter_map(|(r, s)| r.zip(s))
-                {
-                    Self::save_register(&mut generated_asm, self.arch, reg, slot);
-                }
-            }
 
-            // Write input registers
+        Self::prologue(&mut generated_asm, self.arch);
+
+        // Save clobbered registers
+        if !self.options.contains(InlineAsmOptions::NORETURN) {
             for (reg, slot) in self
                 .registers
                 .iter()
-                .zip(self.stack_slots_input.iter().copied())
+                .zip(self.stack_slots_clobber.iter().copied())
                 .filter_map(|(r, s)| r.zip(s))
             {
-                Self::restore_register(&mut generated_asm, self.arch, reg, slot);
+                Self::save_register(&mut generated_asm, self.arch, reg, slot);
             }
         }
 
+        // Write input registers
+        for (reg, slot) in self
+            .registers
+            .iter()
+            .zip(self.stack_slots_input.iter().copied())
+            .filter_map(|(r, s)| r.zip(s))
+        {
+            Self::restore_register(&mut generated_asm, self.arch, reg, slot);
+        }
+
         if is_x86 && self.options.contains(InlineAsmOptions::ATT_SYNTAX) {
             generated_asm.push_str(".att_syntax\n");
         }
@@ -701,32 +586,30 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
             generated_asm.push_str(".intel_syntax noprefix\n");
         }
 
-        if !self.is_naked {
-            if !self.options.contains(InlineAsmOptions::NORETURN) {
-                // Read output registers
-                for (reg, slot) in self
-                    .registers
-                    .iter()
-                    .zip(self.stack_slots_output.iter().copied())
-                    .filter_map(|(r, s)| r.zip(s))
-                {
-                    Self::save_register(&mut generated_asm, self.arch, reg, slot);
-                }
-
-                // Restore clobbered registers
-                for (reg, slot) in self
-                    .registers
-                    .iter()
-                    .zip(self.stack_slots_clobber.iter().copied())
-                    .filter_map(|(r, s)| r.zip(s))
-                {
-                    Self::restore_register(&mut generated_asm, self.arch, reg, slot);
-                }
+        if !self.options.contains(InlineAsmOptions::NORETURN) {
+            // Read output registers
+            for (reg, slot) in self
+                .registers
+                .iter()
+                .zip(self.stack_slots_output.iter().copied())
+                .filter_map(|(r, s)| r.zip(s))
+            {
+                Self::save_register(&mut generated_asm, self.arch, reg, slot);
+            }
 
-                Self::epilogue(&mut generated_asm, self.arch);
-            } else {
-                Self::epilogue_noreturn(&mut generated_asm, self.arch);
+            // Restore clobbered registers
+            for (reg, slot) in self
+                .registers
+                .iter()
+                .zip(self.stack_slots_clobber.iter().copied())
+                .filter_map(|(r, s)| r.zip(s))
+            {
+                Self::restore_register(&mut generated_asm, self.arch, reg, slot);
             }
+
+            Self::epilogue(&mut generated_asm, self.arch);
+        } else {
+            Self::epilogue_noreturn(&mut generated_asm, self.arch);
         }
 
         if is_x86 {