Skip to content

Commit c1fa773

Browse files
committed
Add codegen for global_asm! sym operands
1 parent c34473b commit c1fa773

File tree

11 files changed

+137
-22
lines changed

11 files changed

+137
-22
lines changed

compiler/rustc_codegen_gcc/src/asm.rs

+28-4
Original file line numberDiff line numberDiff line change
@@ -258,9 +258,14 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
258258
}
259259

260260
InlineAsmOperandRef::SymFn { instance } => {
261+
// TODO(@Amanieu): Additional mangling is needed on
262+
// some targets to add a leading underscore (Mach-O)
263+
// or byte count suffixes (x86 Windows).
261264
constants_len += self.tcx.symbol_name(instance).name.len();
262265
}
263266
InlineAsmOperandRef::SymStatic { def_id } => {
267+
// TODO(@Amanieu): Additional mangling is needed on
268+
// some targets to add a leading underscore (Mach-O).
264269
constants_len += self.tcx.symbol_name(Instance::mono(self.tcx, def_id)).name.len();
265270
}
266271
}
@@ -412,13 +417,16 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
412417
}
413418

414419
InlineAsmOperandRef::SymFn { instance } => {
420+
// TODO(@Amanieu): Additional mangling is needed on
421+
// some targets to add a leading underscore (Mach-O)
422+
// or byte count suffixes (x86 Windows).
415423
let name = self.tcx.symbol_name(instance).name;
416424
template_str.push_str(name);
417425
}
418426

419427
InlineAsmOperandRef::SymStatic { def_id } => {
420-
// TODO(@Commeownist): This may not be sufficient for all kinds of statics.
421-
// Some statics may need the `@plt` suffix, like thread-local vars.
428+
// TODO(@Amanieu): Additional mangling is needed on
429+
// some targets to add a leading underscore (Mach-O).
422430
let instance = Instance::mono(self.tcx, def_id);
423431
let name = self.tcx.symbol_name(instance).name;
424432
template_str.push_str(name);
@@ -656,8 +664,8 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
656664
}
657665
}
658666

659-
impl<'gcc, 'tcx> AsmMethods for CodegenCx<'gcc, 'tcx> {
660-
fn codegen_global_asm(&self, template: &[InlineAsmTemplatePiece], operands: &[GlobalAsmOperandRef], options: InlineAsmOptions, _line_spans: &[Span]) {
667+
impl<'gcc, 'tcx> AsmMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
668+
fn codegen_global_asm(&self, template: &[InlineAsmTemplatePiece], operands: &[GlobalAsmOperandRef<'tcx>], options: InlineAsmOptions, _line_spans: &[Span]) {
661669
let asm_arch = self.tcx.sess.asm_arch.unwrap();
662670

663671
// Default to Intel syntax on x86
@@ -690,6 +698,22 @@ impl<'gcc, 'tcx> AsmMethods for CodegenCx<'gcc, 'tcx> {
690698
// here unlike normal inline assembly.
691699
template_str.push_str(string);
692700
}
701+
702+
GlobalAsmOperandRef::SymFn { instance } => {
703+
// TODO(@Amanieu): Additional mangling is needed on
704+
// some targets to add a leading underscore (Mach-O)
705+
// or byte count suffixes (x86 Windows).
706+
let name = self.tcx.symbol_name(instance).name;
707+
template_str.push_str(name);
708+
}
709+
710+
GlobalAsmOperandRef::SymStatic { def_id } => {
711+
// TODO(@Amanieu): Additional mangling is needed on
712+
// some targets to add a leading underscore (Mach-O).
713+
let instance = Instance::mono(self.tcx, def_id);
714+
let name = self.tcx.symbol_name(instance).name;
715+
template_str.push_str(name);
716+
}
693717
}
694718
}
695719
}

compiler/rustc_codegen_llvm/src/asm.rs

+25-2
Original file line numberDiff line numberDiff line change
@@ -307,11 +307,11 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
307307
}
308308
}
309309

310-
impl AsmMethods for CodegenCx<'_, '_> {
310+
impl<'tcx> AsmMethods<'tcx> for CodegenCx<'_, 'tcx> {
311311
fn codegen_global_asm(
312312
&self,
313313
template: &[InlineAsmTemplatePiece],
314-
operands: &[GlobalAsmOperandRef],
314+
operands: &[GlobalAsmOperandRef<'tcx>],
315315
options: InlineAsmOptions,
316316
_line_spans: &[Span],
317317
) {
@@ -337,6 +337,29 @@ impl AsmMethods for CodegenCx<'_, '_> {
337337
// here unlike normal inline assembly.
338338
template_str.push_str(string);
339339
}
340+
GlobalAsmOperandRef::SymFn { instance } => {
341+
let llval = self.get_fn(instance);
342+
self.add_compiler_used_global(llval);
343+
let symbol = llvm::build_string(|s| unsafe {
344+
llvm::LLVMRustGetMangledName(llval, s);
345+
})
346+
.expect("symbol is not valid UTF-8");
347+
template_str.push_str(&symbol);
348+
}
349+
GlobalAsmOperandRef::SymStatic { def_id } => {
350+
let llval = self
351+
.renamed_statics
352+
.borrow()
353+
.get(&def_id)
354+
.copied()
355+
.unwrap_or_else(|| self.get_static(def_id));
356+
self.add_compiler_used_global(llval);
357+
let symbol = llvm::build_string(|s| unsafe {
358+
llvm::LLVMRustGetMangledName(llval, s);
359+
})
360+
.expect("symbol is not valid UTF-8");
361+
template_str.push_str(&symbol);
362+
}
340363
}
341364
}
342365
}

compiler/rustc_codegen_llvm/src/base.rs

+10-9
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,16 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen
9999
attributes::apply_to_llfn(entry, llvm::AttributePlace::Function, &attrs);
100100
}
101101

102-
// Run replace-all-uses-with for statics that need it
102+
// Create the llvm.used and llvm.compiler.used variables.
103+
if !cx.used_statics().borrow().is_empty() {
104+
cx.create_used_variable()
105+
}
106+
if !cx.compiler_used_statics().borrow().is_empty() {
107+
cx.create_compiler_used_variable()
108+
}
109+
110+
// Run replace-all-uses-with for statics that need it. This must
111+
// happen after the llvm.used variables are created.
103112
for &(old_g, new_g) in cx.statics_to_rauw().borrow().iter() {
104113
unsafe {
105114
let bitcast = llvm::LLVMConstPointerCast(new_g, cx.val_ty(old_g));
@@ -114,14 +123,6 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen
114123
cx.coverageinfo_finalize();
115124
}
116125

117-
// Create the llvm.used and llvm.compiler.used variables.
118-
if !cx.used_statics().borrow().is_empty() {
119-
cx.create_used_variable()
120-
}
121-
if !cx.compiler_used_statics().borrow().is_empty() {
122-
cx.create_compiler_used_variable()
123-
}
124-
125126
// Finalize debuginfo
126127
if cx.sess().opts.debuginfo != DebugInfo::None {
127128
cx.debuginfo_finalize();

compiler/rustc_codegen_llvm/src/consts.rs

+7
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,13 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
409409
llvm::LLVMRustSetLinkage(new_g, linkage);
410410
llvm::LLVMRustSetVisibility(new_g, visibility);
411411

412+
// The old global has had its name removed but is returned by
413+
// get_static since it is in the instance cache. Provide an
414+
// alternative lookup that points to the new global so that
415+
// global_asm! can compute the correct mangled symbol name
416+
// for the global.
417+
self.renamed_statics.borrow_mut().insert(def_id, new_g);
418+
412419
// To avoid breaking any invariants, we leave around the old
413420
// global for the moment; we'll replace all references to it
414421
// with the new global later. (See base::codegen_backend.)

compiler/rustc_codegen_llvm/src/context.rs

+8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use rustc_codegen_ssa::traits::*;
1414
use rustc_data_structures::base_n;
1515
use rustc_data_structures::fx::FxHashMap;
1616
use rustc_data_structures::small_c_str::SmallCStr;
17+
use rustc_hir::def_id::DefId;
1718
use rustc_middle::mir::mono::CodegenUnit;
1819
use rustc_middle::ty::layout::{
1920
FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, LayoutError, LayoutOfHelpers,
@@ -105,6 +106,12 @@ pub struct CodegenCx<'ll, 'tcx> {
105106

106107
/// A counter that is used for generating local symbol names
107108
local_gen_sym_counter: Cell<usize>,
109+
110+
/// `codegen_static` will sometimes create a second global variable with a
111+
/// different type and clear the symbol name of the original global.
112+
/// `global_asm!` needs to be able to find this new global so that it can
113+
/// compute the correct mangled symbol name to insert into the asm.
114+
pub renamed_statics: RefCell<FxHashMap<DefId, &'ll Value>>,
108115
}
109116

110117
pub struct TypeLowering<'ll> {
@@ -436,6 +443,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
436443
rust_try_fn: Cell::new(None),
437444
intrinsics: Default::default(),
438445
local_gen_sym_counter: Cell::new(0),
446+
renamed_statics: Default::default(),
439447
}
440448
}
441449

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2537,4 +2537,6 @@ extern "C" {
25372537
remark_passes_len: usize,
25382538
);
25392539

2540+
#[allow(improper_ctypes)]
2541+
pub fn LLVMRustGetMangledName(V: &Value, out: &RustString);
25402542
}

compiler/rustc_codegen_ssa/src/mono_item.rs

+23-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ use crate::traits::*;
44
use rustc_hir as hir;
55
use rustc_middle::mir::mono::MonoItem;
66
use rustc_middle::mir::mono::{Linkage, Visibility};
7+
use rustc_middle::ty;
78
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
9+
use rustc_middle::ty::Instance;
810

911
pub trait MonoItemExt<'a, 'tcx> {
1012
fn define<Bx: BuilderMethods<'a, 'tcx>>(&self, cx: &'a Bx::CodegenCx);
@@ -56,7 +58,27 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
5658
);
5759
GlobalAsmOperandRef::Const { string }
5860
}
59-
_ => span_bug!(*op_sp, "invalid operand type for global_asm!"),
61+
hir::InlineAsmOperand::SymFn { ref anon_const } => {
62+
let ty = cx
63+
.tcx()
64+
.typeck_body(anon_const.body)
65+
.node_type(anon_const.hir_id);
66+
let instance = match ty.kind() {
67+
&ty::FnDef(def_id, substs) => Instance::new(def_id, substs),
68+
_ => span_bug!(*op_sp, "asm sym is not a function"),
69+
};
70+
71+
GlobalAsmOperandRef::SymFn { instance }
72+
}
73+
hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
74+
GlobalAsmOperandRef::SymStatic { def_id }
75+
}
76+
hir::InlineAsmOperand::In { .. }
77+
| hir::InlineAsmOperand::Out { .. }
78+
| hir::InlineAsmOperand::InOut { .. }
79+
| hir::InlineAsmOperand::SplitInOut { .. } => {
80+
span_bug!(*op_sp, "invalid operand type for global_asm!")
81+
}
6082
})
6183
.collect();
6284

compiler/rustc_codegen_ssa/src/traits/asm.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,10 @@ pub enum InlineAsmOperandRef<'tcx, B: BackendTypes + ?Sized> {
3636
}
3737

3838
#[derive(Debug)]
39-
pub enum GlobalAsmOperandRef {
39+
pub enum GlobalAsmOperandRef<'tcx> {
4040
Const { string: String },
41+
SymFn { instance: Instance<'tcx> },
42+
SymStatic { def_id: DefId },
4143
}
4244

4345
pub trait AsmBuilderMethods<'tcx>: BackendTypes {
@@ -53,11 +55,11 @@ pub trait AsmBuilderMethods<'tcx>: BackendTypes {
5355
);
5456
}
5557

56-
pub trait AsmMethods {
58+
pub trait AsmMethods<'tcx> {
5759
fn codegen_global_asm(
5860
&self,
5961
template: &[InlineAsmTemplatePiece],
60-
operands: &[GlobalAsmOperandRef],
62+
operands: &[GlobalAsmOperandRef<'tcx>],
6163
options: InlineAsmOptions,
6264
line_spans: &[Span],
6365
);

compiler/rustc_codegen_ssa/src/traits/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ pub trait CodegenMethods<'tcx>:
6060
+ StaticMethods
6161
+ CoverageInfoMethods<'tcx>
6262
+ DebugInfoMethods<'tcx>
63-
+ AsmMethods
63+
+ AsmMethods<'tcx>
6464
+ PreDefineMethods<'tcx>
6565
+ HasParamEnv<'tcx>
6666
+ HasTyCtxt<'tcx>
@@ -76,7 +76,7 @@ impl<'tcx, T> CodegenMethods<'tcx> for T where
7676
+ StaticMethods
7777
+ CoverageInfoMethods<'tcx>
7878
+ DebugInfoMethods<'tcx>
79-
+ AsmMethods
79+
+ AsmMethods<'tcx>
8080
+ PreDefineMethods<'tcx>
8181
+ HasParamEnv<'tcx>
8282
+ HasTyCtxt<'tcx>

compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -1835,3 +1835,9 @@ extern "C" void LLVMRustContextConfigureDiagnosticHandler(
18351835
unwrap(C)->setDiagnosticHandler(std::make_unique<RustDiagnosticHandler>(
18361836
DiagnosticHandlerCallback, DiagnosticHandlerContext, RemarkAllPasses, Passes));
18371837
}
1838+
1839+
extern "C" void LLVMRustGetMangledName(LLVMValueRef V, RustStringRef Str) {
1840+
RawRustStringOstream OS(Str);
1841+
GlobalValue *GV = unwrap<GlobalValue>(V);
1842+
Mangler().getNameWithPrefix(OS, GV, true);
1843+
}

compiler/rustc_monomorphize/src/collector.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,27 @@ fn collect_items_rec<'tcx>(
435435
// are supported. Therefore the value should not
436436
// depend on any other items.
437437
}
438-
_ => span_bug!(*op_sp, "invalid operand type for global_asm!"),
438+
hir::InlineAsmOperand::SymFn { anon_const } => {
439+
let def_id = tcx.hir().body_owner_def_id(anon_const.body).to_def_id();
440+
if let Ok(val) = tcx.const_eval_poly(def_id) {
441+
rustc_data_structures::stack::ensure_sufficient_stack(|| {
442+
collect_const_value(tcx, val, &mut neighbors);
443+
});
444+
}
445+
}
446+
hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
447+
let instance = Instance::mono(tcx, *def_id);
448+
if should_codegen_locally(tcx, &instance) {
449+
trace!("collecting static {:?}", def_id);
450+
neighbors.push(dummy_spanned(MonoItem::Static(*def_id)));
451+
}
452+
}
453+
hir::InlineAsmOperand::In { .. }
454+
| hir::InlineAsmOperand::Out { .. }
455+
| hir::InlineAsmOperand::InOut { .. }
456+
| hir::InlineAsmOperand::SplitInOut { .. } => {
457+
span_bug!(*op_sp, "invalid operand type for global_asm!")
458+
}
439459
}
440460
}
441461
} else {

0 commit comments

Comments
 (0)