Skip to content
Merged
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
122 changes: 51 additions & 71 deletions src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,48 +7,44 @@ use rustc_middle::ty::layout::FnAbiOf;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::SymbolName;

use indexmap::IndexSet;

use crate::constant::ConstantCx;
use crate::debuginfo::FunctionDebugContext;
use crate::prelude::*;
use crate::pretty_clif::CommentWriter;

struct CodegenedFunction<'tcx> {
instance: Instance<'tcx>,
symbol_name: SymbolName<'tcx>,
func_id: FuncId,
func: Function,
clif_comments: CommentWriter,
source_info_set: IndexSet<SourceInfo>,
local_map: IndexVec<mir::Local, CPlace<'tcx>>,
func_debug_cx: Option<FunctionDebugContext>,
}

pub(crate) fn codegen_and_compile_fn<'tcx>(
cx: &mut crate::CodegenCx<'tcx>,
tcx: TyCtxt<'tcx>,
cx: &mut crate::CodegenCx,
cached_context: &mut Context,
module: &mut dyn Module,
instance: Instance<'tcx>,
) {
let tcx = cx.tcx;
let _inst_guard =
crate::PrintOnPanic(|| format!("{:?} {}", instance, tcx.symbol_name(instance).name));

let cached_func = std::mem::replace(&mut cached_context.func, Function::new());
let codegened_func = codegen_fn(cx, cached_func, module, instance);
let codegened_func = codegen_fn(tcx, cx, cached_func, module, instance);

compile_fn(cx, cached_context, module, codegened_func);
}

fn codegen_fn<'tcx>(
cx: &mut crate::CodegenCx<'tcx>,
tcx: TyCtxt<'tcx>,
cx: &mut crate::CodegenCx,
cached_func: Function,
module: &mut dyn Module,
instance: Instance<'tcx>,
) -> CodegenedFunction<'tcx> {
debug_assert!(!instance.substs.needs_infer());

let tcx = cx.tcx;

let mir = tcx.instance_mir(instance.def);
let _mir_guard = crate::PrintOnPanic(|| {
let mut buf = Vec::new();
Expand Down Expand Up @@ -84,13 +80,20 @@ fn codegen_fn<'tcx>(
let pointer_type = target_config.pointer_type();
let clif_comments = crate::pretty_clif::CommentWriter::new(tcx, instance);

let func_debug_cx = if let Some(debug_context) = &mut cx.debug_context {
Some(debug_context.define_function(tcx, symbol_name.name, mir.span))
} else {
None
};

let mut fx = FunctionCx {
cx,
module,
tcx,
target_config,
pointer_type,
constants_cx: ConstantCx::new(),
func_debug_cx,

instance,
symbol_name,
Expand All @@ -103,52 +106,42 @@ fn codegen_fn<'tcx>(
caller_location: None, // set by `codegen_fn_prelude`

clif_comments,
source_info_set: indexmap::IndexSet::new(),
last_source_file: None,
next_ssa_var: 0,
};

tcx.sess.time("codegen clif ir", || codegen_fn_body(&mut fx, start_block));

// Recover all necessary data from fx, before accessing func will prevent future access to it.
let instance = fx.instance;
let clif_comments = fx.clif_comments;
let source_info_set = fx.source_info_set;
let local_map = fx.local_map;
let func_debug_cx = fx.func_debug_cx;

fx.constants_cx.finalize(fx.tcx, &mut *fx.module);

crate::pretty_clif::write_clif_file(
tcx,
"unopt",
module.isa(),
instance,
&func,
&clif_comments,
);
if cx.should_write_ir {
crate::pretty_clif::write_clif_file(
tcx.output_filenames(()),
symbol_name.name,
"unopt",
module.isa(),
&func,
&clif_comments,
);
}

// Verify function
verify_func(tcx, &clif_comments, &func);

CodegenedFunction {
instance,
symbol_name,
func_id,
func,
clif_comments,
source_info_set,
local_map,
}
CodegenedFunction { symbol_name, func_id, func, clif_comments, func_debug_cx }
}

fn compile_fn<'tcx>(
cx: &mut crate::CodegenCx<'tcx>,
cx: &mut crate::CodegenCx,
cached_context: &mut Context,
module: &mut dyn Module,
codegened_func: CodegenedFunction<'tcx>,
) {
let tcx = cx.tcx;

let mut clif_comments = codegened_func.clif_comments;
let clif_comments = codegened_func.clif_comments;

// Store function in context
let context = cached_context;
Expand All @@ -165,17 +158,6 @@ fn compile_fn<'tcx>(
// invalidate it when it would change.
context.domtree.clear();

// Perform rust specific optimizations
tcx.sess.time("optimize clif ir", || {
crate::optimize::optimize_function(
tcx,
module.isa(),
codegened_func.instance,
context,
&mut clif_comments,
);
});

#[cfg(any())] // This is never true
let _clif_guard = {
use std::fmt::Write;
Expand Down Expand Up @@ -204,43 +186,41 @@ fn compile_fn<'tcx>(
};

// Define function
tcx.sess.time("define function", || {
context.want_disasm = crate::pretty_clif::should_write_ir(tcx);
cx.profiler.verbose_generic_activity("define function").run(|| {
context.want_disasm = cx.should_write_ir;
module.define_function(codegened_func.func_id, context).unwrap();
});

// Write optimized function to file for debugging
crate::pretty_clif::write_clif_file(
tcx,
"opt",
module.isa(),
codegened_func.instance,
&context.func,
&clif_comments,
);
if cx.should_write_ir {
// Write optimized function to file for debugging
crate::pretty_clif::write_clif_file(
&cx.output_filenames,
codegened_func.symbol_name.name,
"opt",
module.isa(),
&context.func,
&clif_comments,
);

if let Some(disasm) = &context.mach_compile_result.as_ref().unwrap().disasm {
crate::pretty_clif::write_ir_file(
tcx,
|| format!("{}.vcode", tcx.symbol_name(codegened_func.instance).name),
|file| file.write_all(disasm.as_bytes()),
)
if let Some(disasm) = &context.mach_compile_result.as_ref().unwrap().disasm {
crate::pretty_clif::write_ir_file(
&cx.output_filenames,
&format!("{}.vcode", codegened_func.symbol_name.name),
|file| file.write_all(disasm.as_bytes()),
)
}
}

// Define debuginfo for function
let isa = module.isa();
let debug_context = &mut cx.debug_context;
let unwind_context = &mut cx.unwind_context;
tcx.sess.time("generate debug info", || {
cx.profiler.verbose_generic_activity("generate debug info").run(|| {
if let Some(debug_context) = debug_context {
debug_context.define_function(
codegened_func.instance,
codegened_func.func_debug_cx.unwrap().finalize(
debug_context,
codegened_func.func_id,
codegened_func.symbol_name.name,
isa,
context,
&codegened_func.source_info_set,
codegened_func.local_map,
);
}
unwind_context.add_function(codegened_func.func_id, &context, isa);
Expand Down
41 changes: 37 additions & 4 deletions src/common.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
use cranelift_codegen::isa::TargetFrontendConfig;
use gimli::write::FileId;

use rustc_data_structures::sync::Lrc;
use rustc_index::vec::IndexVec;
use rustc_middle::ty::layout::{
FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers,
};
use rustc_middle::ty::SymbolName;
use rustc_span::SourceFile;
use rustc_target::abi::call::FnAbi;
use rustc_target::abi::{Integer, Primitive};
use rustc_target::spec::{HasTargetSpec, Target};

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

pub(crate) fn pointer_ty(tcx: TyCtxt<'_>) -> types::Type {
Expand Down Expand Up @@ -232,12 +237,13 @@ pub(crate) fn type_sign(ty: Ty<'_>) -> bool {
}

pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
pub(crate) cx: &'clif mut crate::CodegenCx<'tcx>,
pub(crate) cx: &'clif mut crate::CodegenCx,
pub(crate) module: &'m mut dyn Module,
pub(crate) tcx: TyCtxt<'tcx>,
pub(crate) target_config: TargetFrontendConfig, // Cached from module
pub(crate) pointer_type: Type, // Cached from module
pub(crate) constants_cx: ConstantCx,
pub(crate) func_debug_cx: Option<FunctionDebugContext>,

pub(crate) instance: Instance<'tcx>,
pub(crate) symbol_name: SymbolName<'tcx>,
Expand All @@ -252,7 +258,11 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
pub(crate) caller_location: Option<CValue<'tcx>>,

pub(crate) clif_comments: crate::pretty_clif::CommentWriter,
pub(crate) source_info_set: indexmap::IndexSet<SourceInfo>,

/// Last accessed source file and it's debuginfo file id.
///
/// For optimization purposes only
pub(crate) last_source_file: Option<(Lrc<SourceFile>, FileId)>,

/// This should only be accessed by `CPlace::new_var`.
pub(crate) next_ssa_var: u32,
Expand Down Expand Up @@ -336,8 +346,31 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
}

pub(crate) fn set_debug_loc(&mut self, source_info: mir::SourceInfo) {
let (index, _) = self.source_info_set.insert_full(source_info);
self.bcx.set_srcloc(SourceLoc::new(index as u32));
if let Some(debug_context) = &mut self.cx.debug_context {
let (file, line, column) =
DebugContext::get_span_loc(self.tcx, self.mir.span, source_info.span);

// add_source_file is very slow.
// Optimize for the common case of the current file not being changed.
let mut cached_file_id = None;
if let Some((ref last_source_file, last_file_id)) = self.last_source_file {
// If the allocations are not equal, the files may still be equal, but that
// doesn't matter, as this is just an optimization.
if rustc_data_structures::sync::Lrc::ptr_eq(last_source_file, &file) {
cached_file_id = Some(last_file_id);
}
}

let file_id = if let Some(file_id) = cached_file_id {
file_id
} else {
debug_context.add_source_file(&file)
};

let source_loc =
self.func_debug_cx.as_mut().unwrap().add_dbg_loc(file_id, line, column);
self.bcx.set_srcloc(source_loc);
}
}

// Note: must be kept in sync with get_caller_location from cg_ssa
Expand Down
2 changes: 1 addition & 1 deletion src/debuginfo/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use gimli::{RunTimeEndian, SectionId};
use super::object::WriteDebugInfo;
use super::DebugContext;

impl DebugContext<'_> {
impl DebugContext {
pub(crate) fn emit(&mut self, product: &mut ObjectProduct) {
let unit_range_list_id = self.dwarf.unit.ranges.add(self.unit_range_list.clone());
let root = self.dwarf.unit.root();
Expand Down
Loading