parent
1987a3b6c0
commit
037d411bf4
5 changed files with 121 additions and 18 deletions
|
@ -562,6 +562,10 @@ pub macro line() { /* compiler built-in */ }
|
||||||
#[rustc_macro_transparency = "semitransparent"]
|
#[rustc_macro_transparency = "semitransparent"]
|
||||||
pub macro cfg() { /* compiler built-in */ }
|
pub macro cfg() { /* compiler built-in */ }
|
||||||
|
|
||||||
|
#[rustc_builtin_macro]
|
||||||
|
#[rustc_macro_transparency = "semitransparent"]
|
||||||
|
pub macro global_asm() { /* compiler built-in */ }
|
||||||
|
|
||||||
pub static A_STATIC: u8 = 42;
|
pub static A_STATIC: u8 = 42;
|
||||||
|
|
||||||
#[lang = "panic_location"]
|
#[lang = "panic_location"]
|
||||||
|
|
|
@ -284,6 +284,26 @@ fn main() {
|
||||||
|
|
||||||
#[cfg(not(jit))]
|
#[cfg(not(jit))]
|
||||||
test_tls();
|
test_tls();
|
||||||
|
|
||||||
|
#[cfg(not(jit))]
|
||||||
|
unsafe {
|
||||||
|
global_asm_test();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(jit))]
|
||||||
|
extern "C" {
|
||||||
|
fn global_asm_test();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(jit))]
|
||||||
|
global_asm! {
|
||||||
|
"
|
||||||
|
.global global_asm_test
|
||||||
|
global_asm_test:
|
||||||
|
// comment that would normally be removed by LLVM
|
||||||
|
ret
|
||||||
|
"
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
||||||
use rustc_middle::middle::cstore::EncodedMetadata;
|
use rustc_middle::middle::cstore::EncodedMetadata;
|
||||||
use rustc_middle::mir::mono::CodegenUnit;
|
use rustc_middle::mir::mono::CodegenUnit;
|
||||||
|
@ -110,19 +112,33 @@ fn module_codegen(tcx: TyCtxt<'_>, cgu_name: rustc_span::Symbol) -> ModuleCodege
|
||||||
|
|
||||||
let module = new_module(tcx, cgu_name.as_str().to_string());
|
let module = new_module(tcx, cgu_name.as_str().to_string());
|
||||||
|
|
||||||
|
let mut global_asm = Vec::new();
|
||||||
let mut cx = crate::CodegenCx::new(tcx, module, tcx.sess.opts.debuginfo != DebugInfo::None);
|
let mut cx = crate::CodegenCx::new(tcx, module, tcx.sess.opts.debuginfo != DebugInfo::None);
|
||||||
super::codegen_mono_items(&mut cx, mono_items);
|
super::codegen_mono_items(&mut cx, &mut global_asm, mono_items);
|
||||||
let (mut module, debug, mut unwind_context) = tcx.sess.time("finalize CodegenCx", || cx.finalize());
|
let (mut module, debug, mut unwind_context) = tcx.sess.time("finalize CodegenCx", || cx.finalize());
|
||||||
crate::main_shim::maybe_create_entry_wrapper(tcx, &mut module, &mut unwind_context);
|
crate::main_shim::maybe_create_entry_wrapper(tcx, &mut module, &mut unwind_context);
|
||||||
|
|
||||||
emit_module(
|
let global_asm = global_asm.into_iter().map(|hir_id| {
|
||||||
|
let item = tcx.hir().expect_item(hir_id);
|
||||||
|
if let rustc_hir::ItemKind::GlobalAsm(rustc_hir::GlobalAsm { asm }) = item.kind {
|
||||||
|
asm.as_str().to_string()
|
||||||
|
} else {
|
||||||
|
bug!("Expected GlobalAsm found {:?}", item);
|
||||||
|
}
|
||||||
|
}).collect::<Vec<String>>().join("\n");
|
||||||
|
|
||||||
|
let codegen_result = emit_module(
|
||||||
tcx,
|
tcx,
|
||||||
cgu.name().as_str().to_string(),
|
cgu.name().as_str().to_string(),
|
||||||
ModuleKind::Regular,
|
ModuleKind::Regular,
|
||||||
module,
|
module,
|
||||||
debug,
|
debug,
|
||||||
unwind_context,
|
unwind_context,
|
||||||
)
|
);
|
||||||
|
|
||||||
|
codegen_global_asm(tcx, &cgu.name().as_str(), &global_asm);
|
||||||
|
|
||||||
|
codegen_result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn run_aot(
|
pub(super) fn run_aot(
|
||||||
|
@ -253,6 +269,73 @@ pub(super) fn run_aot(
|
||||||
}, work_products))
|
}, work_products))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn codegen_global_asm(tcx: TyCtxt<'_>, cgu_name: &str, global_asm: &str) {
|
||||||
|
use std::io::Write;
|
||||||
|
use std::process::{Command, Stdio};
|
||||||
|
|
||||||
|
if global_asm.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove all LLVM style comments
|
||||||
|
let global_asm = global_asm.lines().map(|line| {
|
||||||
|
if let Some(index) = line.find("//") {
|
||||||
|
&line[0..index]
|
||||||
|
} else {
|
||||||
|
line
|
||||||
|
}
|
||||||
|
}).collect::<Vec<_>>().join("\n");
|
||||||
|
|
||||||
|
let output_object_file = tcx
|
||||||
|
.output_filenames(LOCAL_CRATE)
|
||||||
|
.temp_path(OutputType::Object, Some(cgu_name));
|
||||||
|
|
||||||
|
// Assemble `global_asm`
|
||||||
|
let global_asm_object_file = add_file_stem_postfix(output_object_file.clone(), ".asm");
|
||||||
|
let mut child = Command::new("as")
|
||||||
|
.arg("-o").arg(&global_asm_object_file)
|
||||||
|
.stdin(Stdio::piped())
|
||||||
|
.spawn()
|
||||||
|
.expect("Failed to spawn `as`.");
|
||||||
|
child.stdin.take().unwrap().write_all(global_asm.as_bytes()).unwrap();
|
||||||
|
let status = child.wait().expect("Failed to wait for `as`.");
|
||||||
|
if !status.success() {
|
||||||
|
tcx.sess.fatal(&format!("Failed to assemble `{}`", global_asm));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Link the global asm and main object file together
|
||||||
|
let main_object_file = add_file_stem_postfix(output_object_file.clone(), ".main");
|
||||||
|
std::fs::rename(&output_object_file, &main_object_file).unwrap();
|
||||||
|
let status = Command::new("ld")
|
||||||
|
.arg("-r") // Create a new object file
|
||||||
|
.arg("-o").arg(output_object_file)
|
||||||
|
.arg(&main_object_file)
|
||||||
|
.arg(&global_asm_object_file)
|
||||||
|
.status()
|
||||||
|
.unwrap();
|
||||||
|
if !status.success() {
|
||||||
|
tcx.sess.fatal(&format!(
|
||||||
|
"Failed to link `{}` and `{}` together",
|
||||||
|
main_object_file.display(),
|
||||||
|
global_asm_object_file.display(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::fs::remove_file(global_asm_object_file).unwrap();
|
||||||
|
std::fs::remove_file(main_object_file).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_file_stem_postfix(mut path: PathBuf, postfix: &str) -> PathBuf {
|
||||||
|
let mut new_filename = path.file_stem().unwrap().to_owned();
|
||||||
|
new_filename.push(postfix);
|
||||||
|
if let Some(extension) = path.extension() {
|
||||||
|
new_filename.push(".");
|
||||||
|
new_filename.push(extension);
|
||||||
|
}
|
||||||
|
path.set_file_name(new_filename);
|
||||||
|
path
|
||||||
|
}
|
||||||
|
|
||||||
// Adapted from https://github.com/rust-lang/rust/blob/303d8aff6092709edd4dbd35b1c88e9aa40bf6d8/src/librustc_codegen_ssa/base.rs#L922-L953
|
// Adapted from https://github.com/rust-lang/rust/blob/303d8aff6092709edd4dbd35b1c88e9aa40bf6d8/src/librustc_codegen_ssa/base.rs#L922-L953
|
||||||
fn determine_cgu_reuse<'tcx>(tcx: TyCtxt<'tcx>, cgu: &CodegenUnit<'tcx>) -> CguReuse {
|
fn determine_cgu_reuse<'tcx>(tcx: TyCtxt<'tcx>, cgu: &CodegenUnit<'tcx>) -> CguReuse {
|
||||||
if !tcx.dep_graph.is_fully_enabled() {
|
if !tcx.dep_graph.is_fully_enabled() {
|
||||||
|
|
|
@ -55,7 +55,12 @@ pub(super) fn run_jit(tcx: TyCtxt<'_>) -> ! {
|
||||||
let mut cx = crate::CodegenCx::new(tcx, jit_module, false);
|
let mut cx = crate::CodegenCx::new(tcx, jit_module, false);
|
||||||
|
|
||||||
let (mut jit_module, _debug, mut unwind_context) = super::time(tcx, "codegen mono items", || {
|
let (mut jit_module, _debug, mut unwind_context) = super::time(tcx, "codegen mono items", || {
|
||||||
super::codegen_mono_items(&mut cx, mono_items);
|
let mut global_asm = Vec::new();
|
||||||
|
super::codegen_mono_items(&mut cx, &mut global_asm, mono_items);
|
||||||
|
for hir_id in global_asm {
|
||||||
|
let item = tcx.hir().expect_item(hir_id);
|
||||||
|
tcx.sess.span_err(item.span, "Global asm is not supported in JIT mode");
|
||||||
|
}
|
||||||
tcx.sess.time("finalize CodegenCx", || cx.finalize())
|
tcx.sess.time("finalize CodegenCx", || cx.finalize())
|
||||||
});
|
});
|
||||||
crate::main_shim::maybe_create_entry_wrapper(tcx, &mut jit_module, &mut unwind_context);
|
crate::main_shim::maybe_create_entry_wrapper(tcx, &mut jit_module, &mut unwind_context);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
|
||||||
|
use rustc_hir::HirId;
|
||||||
use rustc_middle::middle::cstore::EncodedMetadata;
|
use rustc_middle::middle::cstore::EncodedMetadata;
|
||||||
use rustc_middle::mir::mono::{Linkage as RLinkage, MonoItem, Visibility};
|
use rustc_middle::mir::mono::{Linkage as RLinkage, MonoItem, Visibility};
|
||||||
|
|
||||||
|
@ -31,6 +32,7 @@ pub(crate) fn codegen_crate(
|
||||||
|
|
||||||
fn codegen_mono_items<'tcx>(
|
fn codegen_mono_items<'tcx>(
|
||||||
cx: &mut crate::CodegenCx<'tcx, impl Backend + 'static>,
|
cx: &mut crate::CodegenCx<'tcx, impl Backend + 'static>,
|
||||||
|
global_asm: &mut Vec<HirId>,
|
||||||
mono_items: Vec<(MonoItem<'tcx>, (RLinkage, Visibility))>,
|
mono_items: Vec<(MonoItem<'tcx>, (RLinkage, Visibility))>,
|
||||||
) {
|
) {
|
||||||
cx.tcx.sess.time("predefine functions", || {
|
cx.tcx.sess.time("predefine functions", || {
|
||||||
|
@ -49,12 +51,13 @@ fn codegen_mono_items<'tcx>(
|
||||||
|
|
||||||
for (mono_item, (linkage, visibility)) in mono_items {
|
for (mono_item, (linkage, visibility)) in mono_items {
|
||||||
let linkage = crate::linkage::get_clif_linkage(mono_item, linkage, visibility);
|
let linkage = crate::linkage::get_clif_linkage(mono_item, linkage, visibility);
|
||||||
trans_mono_item(cx, mono_item, linkage);
|
trans_mono_item(cx, global_asm, mono_item, linkage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trans_mono_item<'tcx, B: Backend + 'static>(
|
fn trans_mono_item<'tcx, B: Backend + 'static>(
|
||||||
cx: &mut crate::CodegenCx<'tcx, B>,
|
cx: &mut crate::CodegenCx<'tcx, B>,
|
||||||
|
global_asm: &mut Vec<HirId>,
|
||||||
mono_item: MonoItem<'tcx>,
|
mono_item: MonoItem<'tcx>,
|
||||||
linkage: Linkage,
|
linkage: Linkage,
|
||||||
) {
|
) {
|
||||||
|
@ -91,19 +94,7 @@ fn trans_mono_item<'tcx, B: Backend + 'static>(
|
||||||
crate::constant::codegen_static(&mut cx.constants_cx, def_id);
|
crate::constant::codegen_static(&mut cx.constants_cx, def_id);
|
||||||
}
|
}
|
||||||
MonoItem::GlobalAsm(hir_id) => {
|
MonoItem::GlobalAsm(hir_id) => {
|
||||||
let item = tcx.hir().expect_item(hir_id);
|
global_asm.push(hir_id);
|
||||||
if let rustc_hir::ItemKind::GlobalAsm(rustc_hir::GlobalAsm { asm }) = item.kind {
|
|
||||||
// FIXME implement global asm using an external assembler
|
|
||||||
if asm.as_str().contains("__rust_probestack") {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
tcx
|
|
||||||
.sess
|
|
||||||
.fatal(&format!("Unimplemented global asm mono item \"{}\"", asm));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
bug!("Expected GlobalAsm found {:?}", item);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue