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
1 change: 1 addition & 0 deletions build_system/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[
&[],
),
TestCase::build_bin_and_run("aot.float-minmax-pass", "example/float-minmax-pass.rs", &[]),
TestCase::build_bin_and_run("aot.naked-asm-const-ptr", "example/naked-asm-const-ptr.rs", &[]),
TestCase::custom("aot.powi_libcall_signature", &|runner| {
let mut cmd = runner.rustc_command(["example/powi-libcall-signature.rs"]);
let output = cmd.output().unwrap();
Expand Down
1 change: 1 addition & 0 deletions config.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ aot.dst_field_align
aot.subslice-patterns-const-eval
aot.track-caller-attribute
aot.float-minmax-pass
aot.naked-asm-const-ptr
aot.powi_libcall_signature
aot.issue-72793
aot.issue-59326
Expand Down
19 changes: 19 additions & 0 deletions example/naked-asm-const-ptr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Regression test for https://github.com/rust-lang/rustc_codegen_cranelift/issues/1690
// run-pass

#![feature(asm_const_ptr)]

use std::arch::naked_asm;

#[unsafe(naked)]
extern "C" fn naked() {
// `ret` is x86-specific; s390x returns via `br %r14` (see `has_mnemonic` in src/lib.rs).
#[cfg(not(target_arch = "s390x"))]
naked_asm!("ret /* {} */", const &0);
#[cfg(target_arch = "s390x")]
naked_asm!("br %r14 /* {} */", const &0);
}

fn main() {
naked();
}
20 changes: 18 additions & 2 deletions src/driver/aot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use rustc_session::config::{OptLevel, OutputFilenames, OutputType};
use rustc_span::Symbol;

use crate::base::CodegenedFunction;
use crate::constant::ConstantCx;
use crate::debuginfo::TypeDebugContext;
use crate::global_asm::{GlobalAsmConfig, GlobalAsmContext};
use crate::prelude::*;
Expand All @@ -39,6 +40,7 @@ pub(crate) struct AotModule {
debug_context: Option<DebugContext>,
codegened_functions: Vec<CodegenedFunction>,
global_asm: String,
constants_cx: ConstantCx,
}

fn make_module(tcx: TyCtxt<'_>, cgu_name: &str) -> AotModule {
Expand Down Expand Up @@ -77,6 +79,7 @@ fn make_module(tcx: TyCtxt<'_>, cgu_name: &str) -> AotModule {
debug_context,
codegened_functions,
global_asm,
constants_cx: ConstantCx::new(),
}
}

Expand Down Expand Up @@ -159,7 +162,12 @@ fn codegen_cgu(tcx: TyCtxt<'_>, cgu_name: Symbol) -> AotModule {
let flags = tcx.codegen_instance_attrs(instance.def).flags;
if flags.contains(CodegenFnAttrFlags::NAKED) {
rustc_codegen_ssa::mir::naked_asm::codegen_naked_asm(
&mut GlobalAsmContext { tcx, global_asm: &mut module.global_asm },
&mut GlobalAsmContext {
tcx,
global_asm: &mut module.global_asm,
module: &mut module.module,
constants_cx: &mut module.constants_cx,
},
instance,
MonoItemData {
linkage: RLinkage::External,
Expand Down Expand Up @@ -192,14 +200,22 @@ fn codegen_cgu(tcx: TyCtxt<'_>, cgu_name: Symbol) -> AotModule {
}
MonoItem::GlobalAsm(item_id) => {
rustc_codegen_ssa::base::codegen_global_asm(
&mut GlobalAsmContext { tcx, global_asm: &mut module.global_asm },
&mut GlobalAsmContext {
tcx,
global_asm: &mut module.global_asm,
module: &mut module.module,
constants_cx: &mut module.constants_cx,
},
item_id,
);
}
}
}
crate::main_shim::maybe_create_entry_wrapper(tcx, &mut module.module, false, cgu.is_primary());

let constants_cx = std::mem::replace(&mut module.constants_cx, ConstantCx::new());
constants_cx.finalize(tcx, &mut module.module);

module
}

Expand Down
129 changes: 85 additions & 44 deletions src/global_asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@ use rustc_middle::ty::layout::{
use rustc_session::Session;
use rustc_target::asm::InlineAsmArch;

use crate::constant::ConstantCx;
use crate::prelude::*;

pub(crate) struct GlobalAsmContext<'a, 'tcx> {
pub tcx: TyCtxt<'tcx>,
pub global_asm: &'a mut String,
pub module: &'a mut dyn Module,
pub constants_cx: &'a mut ConstantCx,
}

impl<'tcx> AsmCodegenMethods<'tcx> for GlobalAsmContext<'_, 'tcx> {
Expand All @@ -31,7 +34,15 @@ impl<'tcx> AsmCodegenMethods<'tcx> for GlobalAsmContext<'_, 'tcx> {
options: InlineAsmOptions,
_line_spans: &[Span],
) {
codegen_global_asm_inner(self.tcx, self.global_asm, template, operands, options);
codegen_global_asm_inner(
self.tcx,
self.global_asm,
self.module,
self.constants_cx,
template,
operands,
options,
);
}

fn mangled_name(&self, instance: Instance<'tcx>) -> String {
Expand Down Expand Up @@ -90,6 +101,8 @@ impl<'tcx> HasTypingEnv<'tcx> for GlobalAsmContext<'_, 'tcx> {
fn codegen_global_asm_inner<'tcx>(
tcx: TyCtxt<'tcx>,
global_asm: &mut String,
module: &mut dyn Module,
constants_cx: &mut ConstantCx,
template: &[InlineAsmTemplatePiece],
operands: &[GlobalAsmOperandRef<'tcx>],
options: InlineAsmOptions,
Expand All @@ -103,68 +116,96 @@ fn codegen_global_asm_inner<'tcx>(
global_asm.push_str("\n.att_syntax\n");
}
}
for piece in template {
'template: for piece in template {
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 { 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);
}
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);
}

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",
);
}
ConstScalar::Ptr(ptr, _) => {
let (prov, offset) = ptr.prov_and_relative_offset();
let global_alloc = tcx.global_alloc(prov.alloc_id());
let symbol_name = 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",
);
continue 'template;
}

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)
let symbol = tcx.symbol_name(instance);
if tcx.sess.target.is_like_darwin {
format!("_{}", symbol.name)
} else {
symbol.name.to_owned()
}
GlobalAlloc::Static(def_id) => {
let instance = Instance::mono(tcx, def_id);
tcx.symbol_name(instance)
}
GlobalAlloc::Static(def_id) => {
if cfg!(not(feature = "inline_asm_sym")) {
tcx.dcx().span_err(
span,
"asm! and global_asm! sym operands are not yet supported",
);
continue 'template;
}
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();
let instance = Instance::mono(tcx, def_id);
let symbol = tcx.symbol_name(instance);
if tcx.sess.target.is_like_darwin {
format!("_{}", symbol.name)
} else {
symbol.name.to_owned()
}
}
GlobalAlloc::Memory(alloc) => {
let data_id = crate::constant::data_id_for_alloc_id(
constants_cx,
module,
prov.alloc_id(),
alloc.inner().mutability,
);
module
.declarations()
.get_data_decl(data_id)
.linkage_name(data_id)
.into_owned()
}
GlobalAlloc::VTable(..) | GlobalAlloc::TypeId { .. } => {
tcx.dcx().span_err(
span,
"unsupported allocation for global_asm const pointer",
);
continue 'template;
}
};
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::SymThreadLocalStatic { def_id } => {
if cfg!(not(feature = "inline_asm_sym")) {
tcx.dcx().span_err(
span,
"asm! and global_asm! sym operands are not yet supported",
);
continue 'template;
}

let instance = Instance::mono(tcx, def_id);
Expand Down
Loading