Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 48 additions & 20 deletions compiler/rustc_codegen_cranelift/src/global_asm.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
//! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a
//! standalone executable.

use std::fmt::Write as _;
use std::io::Write;
use std::path::PathBuf;
use std::process::{Command, Stdio};
use std::sync::Arc;

use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_codegen_ssa::traits::{AsmCodegenMethods, GlobalAsmOperandRef};
use rustc_middle::mir::interpret::{GlobalAlloc, PointerArithmetic, Scalar as ConstScalar};
use rustc_middle::ty::TyCtxt;
use rustc_middle::ty::layout::{
FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers,
Expand Down Expand Up @@ -108,27 +110,54 @@ fn codegen_global_asm_inner<'tcx>(
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);
}
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",
);
}
GlobalAsmOperandRef::Const { value, ty, instance: _ } => {
match value {
ConstScalar::Int(int) => {
let string = rustc_codegen_ssa::common::asm_const_to_str(
tcx,
int,
FullyMonomorphizedLayoutCx(tcx).layout_of(ty),
);
global_asm.push_str(&string);
}

let symbol = tcx.symbol_name(instance);
let symbol_name = if tcx.sess.target.is_like_darwin {
format!("_{}", symbol.name)
} else {
symbol.name.to_owned()
};
ConstScalar::Ptr(ptr, _) => {
let (prov, offset) = ptr.prov_and_relative_offset();
let global_alloc = tcx.global_alloc(prov.alloc_id());
let symbol = match global_alloc {
GlobalAlloc::Function { instance } => {
if cfg!(not(feature = "inline_asm_sym")) {
tcx.dcx().span_err(
span,
"asm! and global_asm! sym operands are not yet supported",
);
}

// FIXME handle the case where the function was made private to the
// current codegen unit
global_asm.push_str(&escape_symbol_name(tcx, &symbol_name, span));
// FIXME handle the case where the function was made private to the
// current codegen unit
tcx.symbol_name(instance)
}
GlobalAlloc::Static(def_id) => {
let instance = Instance::mono(tcx, def_id);
tcx.symbol_name(instance)
}
GlobalAlloc::Memory(_)
| GlobalAlloc::VTable(..)
| GlobalAlloc::TypeId { .. } => unreachable!(),
};
let symbol_name = if tcx.sess.target.is_like_darwin {
format!("_{}", symbol.name)
} else {
symbol.name.to_owned()
};
global_asm.push_str(&escape_symbol_name(tcx, &symbol_name, span));

if offset != Size::ZERO {
let offset = tcx.sign_extend_to_target_isize(offset.bytes());
write!(global_asm, "{offset:+}").unwrap();
}
}
}
}
GlobalAsmOperandRef::SymStatic { def_id } => {
if cfg!(not(feature = "inline_asm_sym")) {
Expand All @@ -137,7 +166,6 @@ fn codegen_global_asm_inner<'tcx>(
"asm! and global_asm! sym operands are not yet supported",
);
}

let instance = Instance::mono(tcx, def_id);
let symbol = tcx.symbol_name(instance);
let symbol_name = if tcx.sess.target.is_like_darwin {
Expand Down
11 changes: 9 additions & 2 deletions compiler/rustc_codegen_cranelift/src/inline_asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,17 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>(
}
InlineAsmOperand::Const { ref value } => {
let (const_value, ty) = crate::constant::eval_mir_constant(fx, value);
let mir::ConstValue::Scalar(scalar) = const_value else {
span_bug!(
span,
"expected Scalar for promoted asm const, but got {:#?}",
const_value
)
};

let value = rustc_codegen_ssa::common::asm_const_to_str(
fx.tcx,
span,
const_value,
scalar.assert_scalar_int(),
fx.layout_of(ty),
);
CInlineAsmOperand::Const { value }
Expand Down
146 changes: 96 additions & 50 deletions compiler/rustc_codegen_gcc/src/asm.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
// cSpell:ignoreRegExp [afkspqvwy]reg

use std::borrow::Cow;
use std::fmt::Write;

use gccjit::{LValue, RValue, ToRValue, Type};
use rustc_abi::Size;
use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_codegen_ssa::mir::operand::OperandValue;
use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::{
AsmBuilderMethods, AsmCodegenMethods, BaseTypeCodegenMethods, BuilderMethods,
GlobalAsmOperandRef, InlineAsmOperandRef,
ConstCodegenMethods, GlobalAsmOperandRef, InlineAsmOperandRef,
};
use rustc_middle::bug;
use rustc_middle::mir::interpret::{GlobalAlloc, PointerArithmetic, Scalar};
use rustc_middle::ty::Instance;
use rustc_middle::ty::layout::LayoutOf;
use rustc_span::Span;
use rustc_target::asm::*;

Expand Down Expand Up @@ -143,6 +147,9 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
// Clobbers collected from `out("explicit register") _` and `inout("explicit_reg") var => _`
let mut clobbers = vec![];

// Symbols name that needs to be inserted to asm const ptr template string.
let mut const_syms = vec![];

// We're trying to preallocate space for the template
let mut constants_len = 0;

Expand Down Expand Up @@ -303,16 +310,11 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
}
}

InlineAsmOperandRef::Const { ref string } => {
constants_len += string.len() + att_dialect as usize;
InlineAsmOperandRef::Const { .. } => {
// We don't know the size at this point, just some estimate.
constants_len += 20;
}

InlineAsmOperandRef::SymFn { instance } => {
// FIXME(@Amanieu): Additional mangling is needed on
// some targets to add a leading underscore (Mach-O)
// or byte count suffixes (x86 Windows).
constants_len += self.tcx.symbol_name(instance).name.len();
}
InlineAsmOperandRef::SymStatic { def_id } => {
// FIXME(@Amanieu): Additional mangling is needed on
// some targets to add a leading underscore (Mach-O).
Expand Down Expand Up @@ -402,24 +404,22 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
// processed in the previous pass
}

InlineAsmOperandRef::SymFn { instance } => {
inputs.push(AsmInOperand {
constraint: "X".into(),
rust_idx,
val: get_fn(self.cx, instance).get_address(None),
});
}
InlineAsmOperandRef::Const { value, ty: _, instance } => match value {
Scalar::Int(_) => (),
Scalar::Ptr(ptr, _) => {
let (prov, _) = ptr.prov_and_relative_offset();
let global_alloc = self.tcx.global_alloc(prov.alloc_id());
let (val, sym) = self.cx.alloc_to_backend(global_alloc, instance).unwrap();
const_syms.push(sym.unwrap());
inputs.push(AsmInOperand { constraint: "X".into(), rust_idx, val });
}
},

InlineAsmOperandRef::SymStatic { def_id } => {
inputs.push(AsmInOperand {
constraint: "X".into(),
rust_idx,
val: self.cx.get_static(def_id).get_address(None),
});
}

InlineAsmOperandRef::Const { .. } => {
// processed in the previous pass
// FIXME(@Amanieu): Additional mangling is needed on
// some targets to add a leading underscore (MachO).
constants_len +=
self.tcx.symbol_name(Instance::mono(self.tcx, def_id)).name.len();
}

InlineAsmOperandRef::Label { .. } => {
Expand Down Expand Up @@ -495,12 +495,33 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
push_to_template(modifier, gcc_index);
}

InlineAsmOperandRef::SymFn { instance } => {
// FIXME(@Amanieu): Additional mangling is needed on
// some targets to add a leading underscore (Mach-O)
// or byte count suffixes (x86 Windows).
let name = self.tcx.symbol_name(instance).name;
template_str.push_str(name);
InlineAsmOperandRef::Const { value, ty, instance: _ } => {
match value {
Scalar::Int(int) => {
// Const operands get injected directly into the template
let string = rustc_codegen_ssa::common::asm_const_to_str(
self.tcx,
int,
self.layout_of(ty),
);
template_str.push_str(&string);
}

Scalar::Ptr(ptr, _) => {
let (_, offset) = ptr.prov_and_relative_offset();
let instance = const_syms.remove(0);
// FIXME(@Amanieu): Additional mangling is needed on
// some targets to add a leading underscore (Mach-O)
// or byte count suffixes (x86 Windows).
template_str.push_str(self.tcx.symbol_name(instance).name);

if offset != Size::ZERO {
let offset =
self.sign_extend_to_target_isize(offset.bytes());
write!(template_str, "{offset:+}").unwrap();
}
}
}
}

InlineAsmOperandRef::SymStatic { def_id } => {
Expand All @@ -511,10 +532,6 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
template_str.push_str(name);
}

InlineAsmOperandRef::Const { ref string } => {
template_str.push_str(string);
}

InlineAsmOperandRef::Label { label } => {
let label_gcc_index =
labels.iter().position(|&l| l == label).expect("wrong rust index");
Expand Down Expand Up @@ -907,23 +924,52 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
}
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: _ } => {
match operands[operand_idx] {
GlobalAsmOperandRef::Const { ref string } => {
// Const operands get injected directly into the
// template. Note that we don't need to escape %
// here unlike normal inline assembly.
template_str.push_str(string);
}
GlobalAsmOperandRef::Const { value, ty, instance } => {
match value {
Scalar::Int(int) => {
// Const operands get injected directly into the
// template. Note that we don't need to escape %
// here unlike normal inline assembly.
let string = rustc_codegen_ssa::common::asm_const_to_str(
self.tcx,
int,
self.layout_of(ty),
);
template_str.push_str(&string);
}

GlobalAsmOperandRef::SymFn { instance } => {
let function = get_fn(self, instance);
self.add_used_function(function);
// FIXME(@Amanieu): Additional mangling is needed on
// some targets to add a leading underscore (Mach-O)
// or byte count suffixes (x86 Windows).
let name = self.tcx.symbol_name(instance).name;
template_str.push_str(name);
Scalar::Ptr(ptr, _) => {
let (prov, offset) = ptr.prov_and_relative_offset();
let global_alloc = self.tcx.global_alloc(prov.alloc_id());
let symbol_name = match global_alloc {
GlobalAlloc::Function { instance } => {
let function = get_fn(self, instance);
self.add_used_function(function);
// FIXME(@Amanieu): Additional mangling is needed on
// some targets to add a leading underscore (Mach-O)
// or byte count suffixes (x86 Windows).
self.tcx.symbol_name(instance)
}
_ => {
let (_, syms) = self
.alloc_to_backend(global_alloc, instance)
.unwrap();
// FIXME(antoyo): set the global variable as used.
// FIXME(@Amanieu): Additional mangling is needed on
// some targets to add a leading underscore (Mach-O).
self.tcx.symbol_name(syms.unwrap())
}
};
template_str.push_str(symbol_name.name);

if offset != Size::ZERO {
let offset =
self.sign_extend_to_target_isize(offset.bytes());
write!(template_str, "{offset:+}").unwrap();
}
}
}
}

GlobalAsmOperandRef::SymStatic { def_id } => {
// FIXME(antoyo): set the global variable as used.
// FIXME(@Amanieu): Additional mangling is needed on
Expand Down
Loading
Loading