Don't take TyCtxt as argument for compile_global_asm

This allows it to be executed on a background thread.
This commit is contained in:
bjorn3 2022-08-12 09:55:59 +00:00
parent 066f844fff
commit 48b312f04a
2 changed files with 61 additions and 37 deletions

View File

@ -1,6 +1,8 @@
//! 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::sync::Arc;
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};
@ -14,6 +16,7 @@ use rustc_session::Session;
use cranelift_codegen::isa::TargetIsa; use cranelift_codegen::isa::TargetIsa;
use cranelift_object::{ObjectBuilder, ObjectModule}; use cranelift_object::{ObjectBuilder, ObjectModule};
use crate::global_asm::GlobalAsmConfig;
use crate::{prelude::*, BackendConfig}; use crate::{prelude::*, BackendConfig};
struct ModuleCodegenResult(CompiledModule, Option<(WorkProductId, WorkProduct)>); struct ModuleCodegenResult(CompiledModule, Option<(WorkProductId, WorkProduct)>);
@ -141,7 +144,11 @@ fn reuse_workproduct_for_cgu(tcx: TyCtxt<'_>, cgu: &CodegenUnit<'_>) -> ModuleCo
fn module_codegen( fn module_codegen(
tcx: TyCtxt<'_>, tcx: TyCtxt<'_>,
(backend_config, cgu_name): (BackendConfig, rustc_span::Symbol), (backend_config, global_asm_config, cgu_name): (
BackendConfig,
Arc<GlobalAsmConfig>,
rustc_span::Symbol,
),
) -> ModuleCodegenResult { ) -> ModuleCodegenResult {
let cgu = tcx.codegen_unit(cgu_name); let cgu = tcx.codegen_unit(cgu_name);
let mono_items = cgu.items_in_deterministic_order(tcx); let mono_items = cgu.items_in_deterministic_order(tcx);
@ -198,9 +205,13 @@ fn module_codegen(
) )
}); });
match crate::global_asm::compile_global_asm(tcx, cgu.name().as_str(), &cx.global_asm) { match crate::global_asm::compile_global_asm(
&global_asm_config,
cgu.name().as_str(),
&cx.global_asm,
) {
Ok(()) => {} Ok(()) => {}
Err(err) => tcx.sess.fatal(&err.to_string()), Err(err) => tcx.sess.fatal(&err),
} }
codegen_result codegen_result
@ -226,6 +237,8 @@ pub(crate) fn run_aot(
} }
} }
let global_asm_config = Arc::new(crate::global_asm::GlobalAsmConfig::new(tcx));
let modules = super::time(tcx, backend_config.display_cg_time, "codegen mono items", || { let modules = super::time(tcx, backend_config.display_cg_time, "codegen mono items", || {
cgus.iter() cgus.iter()
.map(|cgu| { .map(|cgu| {
@ -243,7 +256,7 @@ pub(crate) fn run_aot(
.with_task( .with_task(
dep_node, dep_node,
tcx, tcx,
(backend_config.clone(), cgu.name()), (backend_config.clone(), global_asm_config.clone(), cgu.name()),
module_codegen, module_codegen,
Some(rustc_middle::dep_graph::hash_result), Some(rustc_middle::dep_graph::hash_result),
) )

View File

@ -1,13 +1,14 @@
//! 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::io::{self, Write}; use std::io::Write;
use std::path::PathBuf; use std::path::PathBuf;
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
use std::sync::Arc;
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_hir::ItemId; use rustc_hir::ItemId;
use rustc_session::config::OutputType; use rustc_session::config::{OutputFilenames, OutputType};
use crate::prelude::*; use crate::prelude::*;
@ -31,40 +32,56 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String,
} }
} }
#[derive(Debug)]
pub(crate) struct GlobalAsmConfig {
asm_enabled: bool,
assembler: PathBuf,
linker: PathBuf,
output_filenames: Arc<OutputFilenames>,
}
impl GlobalAsmConfig {
pub(crate) fn new(tcx: TyCtxt<'_>) -> Self {
let asm_enabled = cfg!(feature = "inline_asm")
&& !tcx.sess.target.is_like_osx
&& !tcx.sess.target.is_like_windows;
GlobalAsmConfig {
asm_enabled,
assembler: crate::toolchain::get_toolchain_binary(tcx.sess, "as"),
linker: crate::toolchain::get_toolchain_binary(tcx.sess, "ld"),
output_filenames: tcx.output_filenames(()).clone(),
}
}
}
pub(crate) fn compile_global_asm( pub(crate) fn compile_global_asm(
tcx: TyCtxt<'_>, config: &GlobalAsmConfig,
cgu_name: &str, cgu_name: &str,
global_asm: &str, global_asm: &str,
) -> io::Result<()> { ) -> Result<(), String> {
if global_asm.is_empty() { if global_asm.is_empty() {
return Ok(()); return Ok(());
} }
if cfg!(not(feature = "inline_asm")) if !config.asm_enabled {
|| tcx.sess.target.is_like_osx
|| tcx.sess.target.is_like_windows
{
if global_asm.contains("__rust_probestack") { if global_asm.contains("__rust_probestack") {
return Ok(()); return Ok(());
} }
// FIXME fix linker error on macOS // FIXME fix linker error on macOS
if cfg!(not(feature = "inline_asm")) { if cfg!(not(feature = "inline_asm")) {
return Err(io::Error::new( return Err(
io::ErrorKind::Unsupported, "asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift"
"asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift", .to_owned(),
)); );
} else { } else {
return Err(io::Error::new( return Err(
io::ErrorKind::Unsupported, "asm! and global_asm! are not yet supported on macOS and Windows".to_owned()
"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 // Remove all LLVM style comments
let global_asm = global_asm let global_asm = global_asm
.lines() .lines()
@ -72,11 +89,11 @@ pub(crate) fn compile_global_asm(
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join("\n"); .join("\n");
let output_object_file = tcx.output_filenames(()).temp_path(OutputType::Object, Some(cgu_name)); let output_object_file = config.output_filenames.temp_path(OutputType::Object, Some(cgu_name));
// Assemble `global_asm` // Assemble `global_asm`
let global_asm_object_file = add_file_stem_postfix(output_object_file.clone(), ".asm"); let global_asm_object_file = add_file_stem_postfix(output_object_file.clone(), ".asm");
let mut child = Command::new(assembler) let mut child = Command::new(&config.assembler)
.arg("-o") .arg("-o")
.arg(&global_asm_object_file) .arg(&global_asm_object_file)
.stdin(Stdio::piped()) .stdin(Stdio::piped())
@ -85,16 +102,13 @@ pub(crate) fn compile_global_asm(
child.stdin.take().unwrap().write_all(global_asm.as_bytes()).unwrap(); child.stdin.take().unwrap().write_all(global_asm.as_bytes()).unwrap();
let status = child.wait().expect("Failed to wait for `as`."); let status = child.wait().expect("Failed to wait for `as`.");
if !status.success() { if !status.success() {
return Err(io::Error::new( return Err(format!("Failed to assemble `{}`", global_asm));
io::ErrorKind::Other,
format!("Failed to assemble `{}`", global_asm),
));
} }
// Link the global asm and main object file together // Link the global asm and main object file together
let main_object_file = add_file_stem_postfix(output_object_file.clone(), ".main"); let main_object_file = add_file_stem_postfix(output_object_file.clone(), ".main");
std::fs::rename(&output_object_file, &main_object_file).unwrap(); std::fs::rename(&output_object_file, &main_object_file).unwrap();
let status = Command::new(linker) let status = Command::new(&config.linker)
.arg("-r") // Create a new object file .arg("-r") // Create a new object file
.arg("-o") .arg("-o")
.arg(output_object_file) .arg(output_object_file)
@ -103,13 +117,10 @@ pub(crate) fn compile_global_asm(
.status() .status()
.unwrap(); .unwrap();
if !status.success() { if !status.success() {
return Err(io::Error::new( return Err(format!(
io::ErrorKind::Other,
format!(
"Failed to link `{}` and `{}` together", "Failed to link `{}` and `{}` together",
main_object_file.display(), main_object_file.display(),
global_asm_object_file.display(), global_asm_object_file.display(),
),
)); ));
} }