use std::path::PathBuf;
-use rustc_codegen_ssa::back::linker::LinkerInfo;
+use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::middle::cstore::EncodedMetadata;
-use rustc_middle::mir::mono::CodegenUnit;
+use rustc_middle::mir::mono::{CodegenUnit, MonoItem};
use rustc_session::cgu_reuse_tracker::CguReuse;
use rustc_session::config::{DebugInfo, OutputType};
-use cranelift_object::{ObjectModule, ObjectProduct};
+use cranelift_object::ObjectModule;
-use crate::prelude::*;
-
-use crate::backend::AddConstructor;
-
-fn new_module(tcx: TyCtxt<'_>, name: String) -> ObjectModule {
- let module = crate::backend::make_module(tcx.sess, name);
- assert_eq!(pointer_ty(tcx), module.target_config().pointer_type());
- module
-}
+use crate::{prelude::*, BackendConfig};
struct ModuleCodegenResult(CompiledModule, Option<(WorkProductId, WorkProduct)>);
fn emit_module(
tcx: TyCtxt<'_>,
+ backend_config: &BackendConfig,
name: String,
kind: ModuleKind,
module: ObjectModule,
debug: Option<DebugContext<'_>>,
- unwind_context: UnwindContext<'_>,
- map_product: impl FnOnce(ObjectProduct) -> ObjectProduct,
+ unwind_context: UnwindContext,
) -> ModuleCodegenResult {
let mut product = module.finish();
unwind_context.emit(&mut product);
- let product = map_product(product);
-
- let tmp_file = tcx
- .output_filenames(LOCAL_CRATE)
- .temp_path(OutputType::Object, Some(&name));
+ let tmp_file = tcx.output_filenames(()).temp_path(OutputType::Object, Some(&name));
let obj = product.object.write().unwrap();
if let Err(err) = std::fs::write(&tmp_file, obj) {
- tcx.sess
- .fatal(&format!("error writing object file: {}", err));
+ tcx.sess.fatal(&format!("error writing object file: {}", err));
}
- let work_product = if std::env::var("CG_CLIF_INCR_CACHE_DISABLED").is_ok() {
+ let work_product = if backend_config.disable_incr_cache {
None
} else {
rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir(
};
ModuleCodegenResult(
- CompiledModule {
- name,
- kind,
- object: Some(tmp_file),
- bytecode: None,
- },
+ CompiledModule { name, kind, object: Some(tmp_file), dwarf_object: None, bytecode: None },
work_product,
)
}
let mut object = None;
let work_product = cgu.work_product(tcx);
if let Some(saved_file) = &work_product.saved_file {
- let obj_out = tcx
- .output_filenames(LOCAL_CRATE)
- .temp_path(OutputType::Object, Some(&cgu.name().as_str()));
+ let obj_out =
+ tcx.output_filenames(()).temp_path(OutputType::Object, Some(&cgu.name().as_str()));
object = Some(obj_out.clone());
let source_file = rustc_incremental::in_incr_comp_dir(&incr_comp_session_dir, &saved_file);
if let Err(err) = rustc_fs_util::link_or_copy(&source_file, &obj_out) {
name: cgu.name().to_string(),
kind: ModuleKind::Regular,
object,
+ dwarf_object: None,
bytecode: None,
}
}
-fn module_codegen(tcx: TyCtxt<'_>, cgu_name: rustc_span::Symbol) -> ModuleCodegenResult {
+fn module_codegen(
+ tcx: TyCtxt<'_>,
+ (backend_config, cgu_name): (BackendConfig, rustc_span::Symbol),
+) -> ModuleCodegenResult {
let cgu = tcx.codegen_unit(cgu_name);
let mono_items = cgu.items_in_deterministic_order(tcx);
- let mut module = new_module(tcx, cgu_name.as_str().to_string());
+ let isa = crate::build_isa(tcx.sess, &backend_config);
+ let mut module = crate::backend::make_module(tcx.sess, isa, cgu_name.as_str().to_string());
- // Initialize the global atomic mutex using a constructor for proc-macros.
- // FIXME implement atomic instructions in Cranelift.
- let mut init_atomics_mutex_from_constructor = None;
- if tcx
- .sess
- .crate_types()
- .contains(&rustc_session::config::CrateType::ProcMacro)
- {
- if mono_items.iter().any(|(mono_item, _)| match mono_item {
- rustc_middle::mir::mono::MonoItem::Static(def_id) => tcx
- .symbol_name(Instance::mono(tcx, *def_id))
- .name
- .contains("__rustc_proc_macro_decls_"),
- _ => false,
- }) {
- init_atomics_mutex_from_constructor =
- Some(crate::atomic_shim::init_global_lock_constructor(
- &mut module,
- &format!("{}_init_atomics_mutex", cgu_name.as_str()),
- ));
+ let mut cx = crate::CodegenCx::new(
+ tcx,
+ backend_config.clone(),
+ module.isa(),
+ tcx.sess.opts.debuginfo != DebugInfo::None,
+ );
+ super::predefine_mono_items(tcx, &mut module, &mono_items);
+ for (mono_item, _) in mono_items {
+ match mono_item {
+ MonoItem::Fn(inst) => {
+ cx.tcx
+ .sess
+ .time("codegen fn", || crate::base::codegen_fn(&mut cx, &mut module, inst));
+ }
+ MonoItem::Static(def_id) => crate::constant::codegen_static(tcx, &mut module, def_id),
+ MonoItem::GlobalAsm(item_id) => {
+ let item = cx.tcx.hir().item(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);
+ }
+ }
}
}
-
- let mut cx = crate::CodegenCx::new(tcx, module, tcx.sess.opts.debuginfo != DebugInfo::None);
- super::predefine_mono_items(&mut cx, &mono_items);
- for (mono_item, (linkage, visibility)) in mono_items {
- let linkage = crate::linkage::get_clif_linkage(mono_item, linkage, visibility);
- super::codegen_mono_item(&mut cx, mono_item, linkage);
- }
- let (mut module, global_asm, debug, mut unwind_context) =
- tcx.sess.time("finalize CodegenCx", || cx.finalize());
- crate::main_shim::maybe_create_entry_wrapper(tcx, &mut module, &mut unwind_context, false);
-
- let codegen_result = emit_module(
+ crate::main_shim::maybe_create_entry_wrapper(
tcx,
- cgu.name().as_str().to_string(),
- ModuleKind::Regular,
- module,
- debug,
- unwind_context,
- |mut product| {
- if let Some(func_id) = init_atomics_mutex_from_constructor {
- product.add_constructor(func_id);
- }
-
- product
- },
+ &mut module,
+ &mut cx.unwind_context,
+ false,
+ cgu.is_primary(),
);
- codegen_global_asm(tcx, &cgu.name().as_str(), &global_asm);
+ let debug_context = cx.debug_context;
+ let unwind_context = cx.unwind_context;
+ let codegen_result = tcx.sess.time("write object file", || {
+ emit_module(
+ tcx,
+ &backend_config,
+ cgu.name().as_str().to_string(),
+ ModuleKind::Regular,
+ module,
+ debug_context,
+ unwind_context,
+ )
+ });
+
+ codegen_global_asm(tcx, &cgu.name().as_str(), &cx.global_asm);
codegen_result
}
-pub(super) fn run_aot(
+pub(crate) fn run_aot(
tcx: TyCtxt<'_>,
+ backend_config: BackendConfig,
metadata: EncodedMetadata,
need_metadata_module: bool,
) -> Box<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>)> {
let mut work_products = FxHashMap::default();
let cgus = if tcx.sess.opts.output_types.should_codegen() {
- tcx.collect_and_partition_mono_items(LOCAL_CRATE).1
+ tcx.collect_and_partition_mono_items(()).1
} else {
// If only `--emit metadata` is used, we shouldn't perform any codegen.
// Also `tcx.collect_and_partition_mono_items` may panic in that case.
}
}
- let modules = super::time(tcx, "codegen mono items", || {
+ let modules = super::time(tcx, backend_config.display_cg_time, "codegen mono items", || {
cgus.iter()
.map(|cgu| {
let cgu_reuse = determine_cgu_reuse(tcx, cgu);
- tcx.sess
- .cgu_reuse_tracker
- .set_actual_reuse(&cgu.name().as_str(), cgu_reuse);
+ tcx.sess.cgu_reuse_tracker.set_actual_reuse(&cgu.name().as_str(), cgu_reuse);
match cgu_reuse {
- _ if std::env::var("CG_CLIF_INCR_CACHE_DISABLED").is_ok() => {}
+ _ if backend_config.disable_incr_cache => {}
CguReuse::No => {}
CguReuse::PreLto => {
return reuse_workproduct_for_cgu(tcx, &*cgu, &mut work_products);
let (ModuleCodegenResult(module, work_product), _) = tcx.dep_graph.with_task(
dep_node,
tcx,
- cgu.name(),
+ (backend_config.clone(), cgu.name()),
module_codegen,
rustc_middle::dep_graph::hash_result,
);
tcx.sess.abort_if_errors();
- let mut allocator_module = new_module(tcx, "allocator_shim".to_string());
- let mut allocator_unwind_context = UnwindContext::new(tcx, allocator_module.isa());
+ let isa = crate::build_isa(tcx.sess, &backend_config);
+ let mut allocator_module =
+ crate::backend::make_module(tcx.sess, isa, "allocator_shim".to_string());
+ assert_eq!(pointer_ty(tcx), allocator_module.target_config().pointer_type());
+ let mut allocator_unwind_context = UnwindContext::new(tcx, allocator_module.isa(), true);
let created_alloc_shim =
crate::allocator::codegen(tcx, &mut allocator_module, &mut allocator_unwind_context);
let allocator_module = if created_alloc_shim {
let ModuleCodegenResult(module, work_product) = emit_module(
tcx,
+ &backend_config,
"allocator_shim".to_string(),
ModuleKind::Allocator,
allocator_module,
None,
allocator_unwind_context,
- |product| product,
);
if let Some((id, product)) = work_product {
work_products.insert(id, product);
None
};
- rustc_incremental::assert_dep_graph(tcx);
- rustc_incremental::save_dep_graph(tcx);
-
let metadata_module = if need_metadata_module {
let _timer = tcx.prof.generic_activity("codegen crate metadata");
let (metadata_cgu_name, tmp_file) = tcx.sess.time("write compressed metadata", || {
.as_str()
.to_string();
- let tmp_file = tcx
- .output_filenames(LOCAL_CRATE)
- .temp_path(OutputType::Metadata, Some(&metadata_cgu_name));
+ let tmp_file =
+ tcx.output_filenames(()).temp_path(OutputType::Metadata, Some(&metadata_cgu_name));
let obj = crate::backend::with_object(tcx.sess, &metadata_cgu_name, |object| {
crate::metadata::write_metadata(tcx, object);
});
if let Err(err) = std::fs::write(&tmp_file, obj) {
- tcx.sess
- .fatal(&format!("error writing metadata object file: {}", err));
+ tcx.sess.fatal(&format!("error writing metadata object file: {}", err));
}
(metadata_cgu_name, tmp_file)
name: metadata_cgu_name,
kind: ModuleKind::Metadata,
object: Some(tmp_file),
+ dwarf_object: None,
bytecode: None,
})
} else {
None
};
- if tcx.sess.opts.output_types.should_codegen() {
- rustc_incremental::assert_module_sources::assert_module_sources(tcx);
- }
-
+ // FIXME handle `-Ctarget-cpu=native`
+ let target_cpu =
+ tcx.sess.opts.cg.target_cpu.as_ref().unwrap_or(&tcx.sess.target.cpu).to_owned();
Box::new((
CodegenResults {
- crate_name: tcx.crate_name(LOCAL_CRATE),
modules,
allocator_module,
metadata_module,
metadata,
- windows_subsystem: None, // Windows is not yet supported
- linker_info: LinkerInfo::new(tcx),
- crate_info: CrateInfo::new(tcx),
+ crate_info: CrateInfo::new(tcx, target_cpu),
},
work_products,
))
"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");
+ tcx.sess.fatal("asm! and global_asm! are not yet supported on macOS and Windows");
}
}
// Remove all LLVM style comments
let global_asm = global_asm
.lines()
- .map(|line| {
- if let Some(index) = line.find("//") {
- &line[0..index]
- } else {
- line
- }
- })
+ .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));
+ 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");
.stdin(Stdio::piped())
.spawn()
.expect("Failed to spawn `as`.");
- 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`.");
if !status.success() {
- tcx.sess
- .fatal(&format!("Failed to assemble `{}`", global_asm));
+ tcx.sess.fatal(&format!("Failed to assemble `{}`", global_asm));
}
// Link the global asm and main object file together
}
let work_product_id = &cgu.work_product_id();
- if tcx
- .dep_graph
- .previous_work_product(work_product_id)
- .is_none()
- {
+ if tcx.dep_graph.previous_work_product(work_product_id).is_none() {
// We don't have anything cached for this CGU. This can happen
// if the CGU did not exist in the previous session.
return CguReuse::No;
cgu.name()
);
- if tcx.dep_graph.try_mark_green(tcx, &dep_node).is_some() {
- CguReuse::PreLto
- } else {
- CguReuse::No
- }
+ if tcx.try_mark_green(&dep_node) { CguReuse::PreLto } else { CguReuse::No }
}