about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/common.rs2
-rw-r--r--src/inline_asm.rs31
2 files changed, 27 insertions, 6 deletions
diff --git a/src/common.rs b/src/common.rs
index 16ae526090b..a8be0d32cc8 100644
--- a/src/common.rs
+++ b/src/common.rs
@@ -255,7 +255,7 @@ pub(crate) fn type_sign(ty: Ty<'_>) -> bool {
 }
 
 pub(crate) fn create_wrapper_function(
-    module: &mut impl Module,
+    module: &mut dyn Module,
     unwind_context: &mut UnwindContext,
     sig: Signature,
     wrapper_name: &str,
diff --git a/src/inline_asm.rs b/src/inline_asm.rs
index aa0b51181f4..6206fbf7dd5 100644
--- a/src/inline_asm.rs
+++ b/src/inline_asm.rs
@@ -6,7 +6,6 @@ use std::fmt::Write;
 
 use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_middle::mir::InlineAsmOperand;
-use rustc_middle::ty::SymbolName;
 use rustc_span::sym;
 use rustc_target::asm::*;
 
@@ -30,7 +29,7 @@ enum CInlineAsmOperand<'tcx> {
         value: String,
     },
     Symbol {
-        symbol: SymbolName<'tcx>,
+        symbol: String,
     },
 }
 
@@ -263,7 +262,29 @@ pub(crate) fn codegen_inline_asm<'tcx>(
                         substs,
                     )
                     .unwrap();
-                    CInlineAsmOperand::Symbol { symbol: fx.tcx.symbol_name(instance) }
+                    let symbol = fx.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 inline_asm_index = fx.cx.inline_asm_index.get();
+                    fx.cx.inline_asm_index.set(inline_asm_index + 1);
+                    let wrapper_name = format!(
+                        "__inline_asm_{}_wrapper_n{}",
+                        fx.cx.cgu_name.as_str().replace('.', "__").replace('-', "_"),
+                        inline_asm_index
+                    );
+                    let sig =
+                        get_function_sig(fx.tcx, fx.target_config.default_call_conv, instance);
+                    create_wrapper_function(
+                        fx.module,
+                        &mut fx.cx.unwind_context,
+                        sig,
+                        &wrapper_name,
+                        symbol.name,
+                    );
+
+                    CInlineAsmOperand::Symbol { symbol: wrapper_name }
                 } else {
                     span_bug!(span, "invalid type for asm sym (fn)");
                 }
@@ -271,7 +292,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
             InlineAsmOperand::SymStatic { def_id } => {
                 assert!(fx.tcx.is_static(def_id));
                 let instance = Instance::mono(fx.tcx, def_id).polymorphize(fx.tcx);
-                CInlineAsmOperand::Symbol { symbol: fx.tcx.symbol_name(instance) }
+                CInlineAsmOperand::Symbol { symbol: fx.tcx.symbol_name(instance).name.to_owned() }
             }
         })
         .collect::<Vec<_>>();
@@ -630,7 +651,7 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
                         CInlineAsmOperand::Const { ref value } => {
                             generated_asm.push_str(value);
                         }
-                        CInlineAsmOperand::Symbol { symbol } => generated_asm.push_str(symbol.name),
+                        CInlineAsmOperand::Symbol { ref symbol } => generated_asm.push_str(symbol),
                     }
                 }
             }