Extract global_asm module
This commit is contained in:
parent
c5adc96532
commit
7cc97ebcbb
3 changed files with 119 additions and 107 deletions
|
@ -1,9 +1,6 @@
|
||||||
//! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a
|
//! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a
|
||||||
//! standalone executable.
|
//! standalone executable.
|
||||||
|
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
|
||||||
use rustc_codegen_ssa::back::metadata::create_compressed_metadata_file;
|
use rustc_codegen_ssa::back::metadata::create_compressed_metadata_file;
|
||||||
use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind};
|
use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind};
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
|
@ -175,23 +172,7 @@ fn module_codegen(
|
||||||
}
|
}
|
||||||
MonoItem::Static(def_id) => crate::constant::codegen_static(tcx, &mut module, def_id),
|
MonoItem::Static(def_id) => crate::constant::codegen_static(tcx, &mut module, def_id),
|
||||||
MonoItem::GlobalAsm(item_id) => {
|
MonoItem::GlobalAsm(item_id) => {
|
||||||
let item = cx.tcx.hir().item(item_id);
|
crate::global_asm::codegen_global_asm_item(tcx, &mut cx.global_asm, item_id);
|
||||||
if let rustc_hir::ItemKind::GlobalAsm(asm) = item.kind {
|
|
||||||
if !asm.options.contains(InlineAsmOptions::ATT_SYNTAX) {
|
|
||||||
cx.global_asm.push_str("\n.intel_syntax noprefix\n");
|
|
||||||
} else {
|
|
||||||
cx.global_asm.push_str("\n.att_syntax\n");
|
|
||||||
}
|
|
||||||
for piece in asm.template {
|
|
||||||
match *piece {
|
|
||||||
InlineAsmTemplatePiece::String(ref s) => cx.global_asm.push_str(s),
|
|
||||||
InlineAsmTemplatePiece::Placeholder { .. } => todo!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cx.global_asm.push_str("\n.att_syntax\n\n");
|
|
||||||
} else {
|
|
||||||
bug!("Expected GlobalAsm found {:?}", item);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,7 +198,7 @@ fn module_codegen(
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
codegen_global_asm(tcx, cgu.name().as_str(), &cx.global_asm);
|
crate::global_asm::compile_global_asm(tcx, cgu.name().as_str(), &cx.global_asm);
|
||||||
|
|
||||||
codegen_result
|
codegen_result
|
||||||
}
|
}
|
||||||
|
@ -353,92 +334,6 @@ pub(crate) fn run_aot(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if cfg!(not(feature = "inline_asm"))
|
|
||||||
|| tcx.sess.target.is_like_osx
|
|
||||||
|| tcx.sess.target.is_like_windows
|
|
||||||
{
|
|
||||||
if global_asm.contains("__rust_probestack") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME fix linker error on macOS
|
|
||||||
if cfg!(not(feature = "inline_asm")) {
|
|
||||||
tcx.sess.fatal(
|
|
||||||
"asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift",
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
tcx.sess.fatal("asm! and global_asm! are not yet supported on macOS and Windows");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let assembler = crate::toolchain::get_toolchain_binary(tcx.sess, "as");
|
|
||||||
let linker = crate::toolchain::get_toolchain_binary(tcx.sess, "ld");
|
|
||||||
|
|
||||||
// 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(()).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(assembler)
|
|
||||||
.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(linker)
|
|
||||||
.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() {
|
||||||
|
|
116
src/global_asm.rs
Normal file
116
src/global_asm.rs
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
//! The AOT driver uses [`cranelift_object`] to write object files suitable for linking into a
|
||||||
|
//! standalone executable.
|
||||||
|
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
||||||
|
use rustc_hir::ItemId;
|
||||||
|
use rustc_session::config::OutputType;
|
||||||
|
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, item_id: ItemId) {
|
||||||
|
let item = tcx.hir().item(item_id);
|
||||||
|
if let rustc_hir::ItemKind::GlobalAsm(asm) = item.kind {
|
||||||
|
if !asm.options.contains(InlineAsmOptions::ATT_SYNTAX) {
|
||||||
|
global_asm.push_str("\n.intel_syntax noprefix\n");
|
||||||
|
} else {
|
||||||
|
global_asm.push_str("\n.att_syntax\n");
|
||||||
|
}
|
||||||
|
for piece in asm.template {
|
||||||
|
match *piece {
|
||||||
|
InlineAsmTemplatePiece::String(ref s) => global_asm.push_str(s),
|
||||||
|
InlineAsmTemplatePiece::Placeholder { .. } => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
global_asm.push_str("\n.att_syntax\n\n");
|
||||||
|
} else {
|
||||||
|
bug!("Expected GlobalAsm found {:?}", item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn compile_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg!(not(feature = "inline_asm"))
|
||||||
|
|| tcx.sess.target.is_like_osx
|
||||||
|
|| tcx.sess.target.is_like_windows
|
||||||
|
{
|
||||||
|
if global_asm.contains("__rust_probestack") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME fix linker error on macOS
|
||||||
|
if cfg!(not(feature = "inline_asm")) {
|
||||||
|
tcx.sess.fatal(
|
||||||
|
"asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift",
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
tcx.sess.fatal("asm! and global_asm! are not yet supported on macOS and Windows");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let assembler = crate::toolchain::get_toolchain_binary(tcx.sess, "as");
|
||||||
|
let linker = crate::toolchain::get_toolchain_binary(tcx.sess, "ld");
|
||||||
|
|
||||||
|
// 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(()).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(assembler)
|
||||||
|
.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(linker)
|
||||||
|
.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
|
||||||
|
}
|
|
@ -56,6 +56,7 @@ mod constant;
|
||||||
mod debuginfo;
|
mod debuginfo;
|
||||||
mod discriminant;
|
mod discriminant;
|
||||||
mod driver;
|
mod driver;
|
||||||
|
mod global_asm;
|
||||||
mod inline_asm;
|
mod inline_asm;
|
||||||
mod intrinsics;
|
mod intrinsics;
|
||||||
mod linkage;
|
mod linkage;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue