Skip to content
Merged
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
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4508,6 +4508,7 @@ dependencies = [
"rustc_middle",
"rustc_session",
"rustc_span",
"rustc_symbol_mangling",
"rustc_target",
"serde",
"serde_json",
Expand Down
70 changes: 50 additions & 20 deletions compiler/rustc_codegen_cranelift/src/global_asm.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
//! 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::{Path, PathBuf};
use std::process::{Command, Stdio};

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 @@ -107,29 +109,57 @@ 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 } => {
match value {
ConstScalar::Int(int) => {
let string = rustc_codegen_ssa::common::asm_const_to_str(
tcx,
span,
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, _) => {
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));
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 } => {
// FIXME handle the case where the function was made private to the
// current codegen unit
tcx.symbol_name(instance)
}
GlobalAlloc::Static(def_id) => {
Comment thread
bjorn3 marked this conversation as resolved.
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 } => {
GlobalAsmOperandRef::SymThreadLocalStatic { def_id } => {
if cfg!(not(feature = "inline_asm_sym")) {
tcx.dcx().span_err(
span,
Expand Down
10 changes: 9 additions & 1 deletion compiler/rustc_codegen_cranelift/src/inline_asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,18 @@ 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
157 changes: 102 additions & 55 deletions compiler/rustc_codegen_gcc/src/asm.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
// 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;
Expand All @@ -11,7 +13,9 @@ use rustc_codegen_ssa::traits::{
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::{DUMMY_SP, 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,17 +310,12 @@ 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 } => {
InlineAsmOperandRef::SymThreadLocalStatic { def_id } => {
// FIXME(@Amanieu): Additional mangling is needed on
// some targets to add a leading underscore (Mach-O).
constants_len +=
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::SymStatic { def_id } => {
inputs.push(AsmInOperand {
constraint: "X".into(),
rust_idx,
val: self.cx.get_static(def_id).get_address(None),
});
}
InlineAsmOperandRef::Const { value, ty: _ } => 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, true).unwrap();
const_syms.push(sym.unwrap());
inputs.push(AsmInOperand { constraint: "X".into(), rust_idx, val });
}
},

InlineAsmOperandRef::Const { .. } => {
// processed in the previous pass
InlineAsmOperandRef::SymThreadLocalStatic { def_id } => {
// 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 @@ -453,7 +453,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
template_str.push_str(escaped_char);
}
}
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier, span: _ } => {
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier, span } => {
let mut push_to_template = |modifier, gcc_idx| {
use std::fmt::Write;

Expand Down Expand Up @@ -495,26 +495,44 @@ 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 } => {
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,
span,
int,
self.layout_of(ty),
);
template_str.push_str(&string);
}

Scalar::Ptr(ptr, _) => {
let (_, offset) = ptr.prov_and_relative_offset();
let sym = 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(sym.name);

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

InlineAsmOperandRef::SymStatic { def_id } => {
InlineAsmOperandRef::SymThreadLocalStatic { def_id } => {
// FIXME(@Amanieu): Additional mangling is needed on
// some targets to add a leading underscore (Mach-O).
let instance = Instance::mono(self.tcx, def_id);
let name = self.tcx.symbol_name(instance).name;
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 @@ -933,26 +951,55 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
.unwrap_or(string.len());
}
}
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: _ } => {
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 } => {
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,
span,
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, true).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).
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 } => {
GlobalAsmOperandRef::SymThreadLocalStatic { def_id } => {
// FIXME(antoyo): set the global variable as used.
// FIXME(@Amanieu): Additional mangling is needed on
// some targets to add a leading underscore (Mach-O).
Expand Down
Loading
Loading