diff --git a/compiler/rustc_codegen_cranelift/src/global_asm.rs b/compiler/rustc_codegen_cranelift/src/global_asm.rs index 97d6cecf6848..1daf428acf76 100644 --- a/compiler/rustc_codegen_cranelift/src/global_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/global_asm.rs @@ -106,6 +106,7 @@ fn codegen_global_asm_inner<'tcx>( match *piece { InlineAsmTemplatePiece::String(ref s) => global_asm.push_str(s), InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span } => { + use rustc_codegen_ssa::back::symbol_export::escape_symbol_name; match operands[operand_idx] { GlobalAsmOperandRef::Const { ref string } => { global_asm.push_str(string); @@ -121,7 +122,7 @@ fn codegen_global_asm_inner<'tcx>( 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); + global_asm.push_str(&escape_symbol_name(tcx, symbol.name, span)); } GlobalAsmOperandRef::SymStatic { def_id } => { if cfg!(not(feature = "inline_asm_sym")) { @@ -133,7 +134,7 @@ fn codegen_global_asm_inner<'tcx>( let instance = Instance::mono(tcx, def_id); let symbol = tcx.symbol_name(instance); - global_asm.push_str(symbol.name); + global_asm.push_str(&escape_symbol_name(tcx, symbol.name, span)); } } } diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index fd25fba2daac..80d77be1cc38 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -400,6 +400,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { match *piece { InlineAsmTemplatePiece::String(ref s) => template_str.push_str(s), InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span } => { + use rustc_codegen_ssa::back::symbol_export::escape_symbol_name; match operands[operand_idx] { GlobalAsmOperandRef::Const { ref string } => { // Const operands get injected directly into the @@ -414,7 +415,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { llvm::LLVMRustGetMangledName(llval, s); }) .expect("symbol is not valid UTF-8"); - template_str.push_str(&escape_symbol_name(self, symbol, span)); + template_str.push_str(&escape_symbol_name(self.tcx, &symbol, span)); } GlobalAsmOperandRef::SymStatic { def_id } => { let llval = self @@ -428,7 +429,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> { llvm::LLVMRustGetMangledName(llval, s); }) .expect("symbol is not valid UTF-8"); - template_str.push_str(&escape_symbol_name(self, symbol, span)); + template_str.push_str(&escape_symbol_name(self.tcx, &symbol, span)); } } } @@ -1390,42 +1391,3 @@ fn llvm_fixup_output_type<'ll, 'tcx>( _ => layout.llvm_type(cx), } } - -fn escape_symbol_name<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, symbol: String, span: Span) -> String { - use rustc_target::spec::{Arch, BinaryFormat}; - if !symbol.is_empty() - && symbol.chars().all(|c| matches!(c, '0'..='9' | 'A'..='Z' | 'a'..='z' | '_' | '$' | '.')) - { - return symbol; - } - if cx.tcx.sess.target.binary_format == BinaryFormat::Xcoff { - cx.tcx.sess.dcx().span_fatal( - span, - format!( - "symbol escaping is not supported for the binary format {}", - cx.tcx.sess.target.binary_format - ), - ); - } - if cx.tcx.sess.target.arch == Arch::Nvptx64 { - cx.tcx.sess.dcx().span_fatal( - span, - format!( - "symbol escaping is not supported for the architecture {}", - cx.tcx.sess.target.arch - ), - ); - } - let mut escaped_symbol = String::new(); - escaped_symbol.push('\"'); - for c in symbol.chars() { - match c { - '\n' => escaped_symbol.push_str("\\\n"), - '"' => escaped_symbol.push_str("\\\""), - '\\' => escaped_symbol.push_str("\\\\"), - c => escaped_symbol.push(c), - } - } - escaped_symbol.push('\"'); - escaped_symbol -} diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index c6e945691921..557b00b911aa 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -14,6 +14,7 @@ use rustc_middle::query::LocalCrate; use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, Instance, SymbolName, Ty, TyCtxt}; use rustc_middle::util::Providers; use rustc_session::config::CrateType; +use rustc_span::Span; use rustc_symbol_mangling::mangle_internal_symbol; use rustc_target::spec::{Arch, Os, TlsModel}; use tracing::debug; @@ -764,3 +765,43 @@ fn wasm_import_module_map(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap { ret } + +pub fn escape_symbol_name(tcx: TyCtxt<'_>, symbol: &str, span: Span) -> String { + // https://github.com/llvm/llvm-project/blob/a55fbab0cffc9b4af497b9e4f187b61143743e06/llvm/lib/MC/MCSymbol.cpp + use rustc_target::spec::{Arch, BinaryFormat}; + if !symbol.is_empty() + && symbol.chars().all(|c| matches!(c, '0'..='9' | 'A'..='Z' | 'a'..='z' | '_' | '$' | '.')) + { + return symbol.to_string(); + } + if tcx.sess.target.binary_format == BinaryFormat::Xcoff { + tcx.sess.dcx().span_fatal( + span, + format!( + "symbol escaping is not supported for the binary format {}", + tcx.sess.target.binary_format + ), + ); + } + if tcx.sess.target.arch == Arch::Nvptx64 { + tcx.sess.dcx().span_fatal( + span, + format!( + "symbol escaping is not supported for the architecture {}", + tcx.sess.target.arch + ), + ); + } + let mut escaped_symbol = String::new(); + escaped_symbol.push('\"'); + for c in symbol.chars() { + match c { + '\n' => escaped_symbol.push_str("\\\n"), + '"' => escaped_symbol.push_str("\\\""), + '\\' => escaped_symbol.push_str("\\\\"), + c => escaped_symbol.push(c), + } + } + escaped_symbol.push('\"'); + escaped_symbol +}