2015-04-24 13:20:54 +12:00
|
|
|
// See doc.rs for documentation.
|
|
|
|
mod doc;
|
2012-12-03 16:48:01 -08:00
|
|
|
|
2018-10-03 16:56:24 +02:00
|
|
|
use rustc_codegen_ssa::debuginfo::VariableAccess::*;
|
|
|
|
use rustc_codegen_ssa::debuginfo::VariableKind::*;
|
2015-04-24 17:20:13 +12:00
|
|
|
|
2016-05-01 12:46:55 -04:00
|
|
|
use self::utils::{DIB, span_start, create_DIArray, is_node_local_to_unit};
|
2017-12-20 21:28:10 -08:00
|
|
|
use self::namespace::mangled_name_of_instance;
|
2015-04-29 18:14:37 +12:00
|
|
|
use self::type_names::compute_debuginfo_type_name;
|
2016-07-31 22:33:41 +08:00
|
|
|
use self::metadata::{type_metadata, file_metadata, TypeMap};
|
2016-04-07 22:35:11 +03:00
|
|
|
use self::source_loc::InternalDebugLocation::{self, UnknownLocation};
|
2013-06-18 10:17:10 +02:00
|
|
|
|
2019-02-18 03:58:58 +09:00
|
|
|
use crate::llvm;
|
|
|
|
use crate::llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilder, DISubprogram, DIArray, DIFlags,
|
2019-01-16 09:59:03 -08:00
|
|
|
DISPFlags, DILexicalBlock};
|
2018-05-08 16:10:16 +03:00
|
|
|
use rustc::hir::CodegenFnAttrFlags;
|
2019-01-13 13:06:26 +01:00
|
|
|
use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
|
2019-02-26 09:30:34 +08:00
|
|
|
use rustc::ty::subst::{SubstsRef, UnpackedKind};
|
2015-07-31 00:04:06 -07:00
|
|
|
|
2019-02-18 03:58:58 +09:00
|
|
|
use crate::abi::Abi;
|
|
|
|
use crate::common::CodegenCx;
|
|
|
|
use crate::builder::Builder;
|
|
|
|
use crate::monomorphize::Instance;
|
|
|
|
use crate::value::Value;
|
2018-04-12 14:52:43 +02:00
|
|
|
use rustc::ty::{self, ParamEnv, Ty, InstanceDef};
|
2016-09-19 23:50:00 +03:00
|
|
|
use rustc::mir;
|
2018-07-26 11:41:10 -06:00
|
|
|
use rustc::session::config::{self, DebugInfo};
|
2017-05-27 20:48:09 +02:00
|
|
|
use rustc::util::nodemap::{DefIdMap, FxHashMap, FxHashSet};
|
2018-08-07 16:04:34 +02:00
|
|
|
use rustc_data_structures::small_c_str::SmallCStr;
|
2018-09-20 15:47:22 +02:00
|
|
|
use rustc_data_structures::indexed_vec::IndexVec;
|
2018-10-03 16:56:24 +02:00
|
|
|
use rustc_codegen_ssa::debuginfo::{FunctionDebugContext, MirDebugScope, VariableAccess,
|
|
|
|
VariableKind, FunctionDebugContextData};
|
2012-12-13 13:05:22 -08:00
|
|
|
|
2015-04-24 16:48:10 +12:00
|
|
|
use libc::c_uint;
|
2018-12-02 18:09:26 +01:00
|
|
|
use std::cell::RefCell;
|
2015-02-26 21:00:43 -08:00
|
|
|
use std::ffi::CString;
|
2015-07-31 00:04:06 -07:00
|
|
|
|
2016-06-21 18:08:13 -04:00
|
|
|
use syntax_pos::{self, Span, Pos};
|
|
|
|
use syntax::ast;
|
2018-03-21 14:46:05 +01:00
|
|
|
use syntax::symbol::{Symbol, InternedString};
|
2018-09-20 15:47:22 +02:00
|
|
|
use rustc::ty::layout::{self, LayoutOf, HasTyCtxt};
|
2018-11-16 13:45:28 +02:00
|
|
|
use rustc_codegen_ssa::traits::*;
|
2013-06-26 16:00:42 +02:00
|
|
|
|
2015-04-24 17:25:35 +12:00
|
|
|
pub mod gdb;
|
|
|
|
mod utils;
|
|
|
|
mod namespace;
|
2015-04-29 18:14:37 +12:00
|
|
|
mod type_names;
|
2016-07-13 00:40:38 +02:00
|
|
|
pub mod metadata;
|
2015-04-29 18:14:37 +12:00
|
|
|
mod create_scope_map;
|
|
|
|
mod source_loc;
|
|
|
|
|
2018-10-03 16:56:24 +02:00
|
|
|
pub use self::create_scope_map::{create_mir_scopes};
|
2015-04-29 18:14:37 +12:00
|
|
|
pub use self::metadata::create_global_var_metadata;
|
2016-08-24 19:34:31 -07:00
|
|
|
pub use self::metadata::extend_scope_to_file;
|
2016-12-16 13:25:18 -07:00
|
|
|
pub use self::source_loc::set_source_location;
|
2015-04-24 17:25:35 +12:00
|
|
|
|
2014-10-27 15:37:07 -07:00
|
|
|
#[allow(non_upper_case_globals)]
|
2014-12-06 11:39:25 -05:00
|
|
|
const DW_TAG_auto_variable: c_uint = 0x100;
|
2014-10-27 15:37:07 -07:00
|
|
|
#[allow(non_upper_case_globals)]
|
2014-12-06 11:39:25 -05:00
|
|
|
const DW_TAG_arg_variable: c_uint = 0x101;
|
2011-11-15 21:11:22 -05:00
|
|
|
|
2013-06-18 13:06:41 +02:00
|
|
|
/// A context object for maintaining all state needed by the debuginfo module.
|
2018-06-27 17:57:25 +03:00
|
|
|
pub struct CrateDebugContext<'a, 'tcx> {
|
|
|
|
llcontext: &'a llvm::Context,
|
|
|
|
llmod: &'a llvm::Module,
|
2018-07-17 18:45:33 +03:00
|
|
|
builder: &'a mut DIBuilder<'a>,
|
2018-07-04 16:36:49 +03:00
|
|
|
created_files: RefCell<FxHashMap<(Symbol, Symbol), &'a DIFile>>,
|
|
|
|
created_enum_disr_types: RefCell<FxHashMap<(DefId, layout::Primitive), &'a DIType>>,
|
2014-05-30 17:09:16 +02:00
|
|
|
|
2018-07-04 16:36:49 +03:00
|
|
|
type_map: RefCell<TypeMap<'a, 'tcx>>,
|
|
|
|
namespace_map: RefCell<DefIdMap<&'a DIScope>>,
|
2014-05-30 17:09:16 +02:00
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// This collection is used to assert that composite types (structs, enums,
|
|
|
|
// ...) have their members only set once:
|
2018-07-04 16:36:49 +03:00
|
|
|
composite_types_completed: RefCell<FxHashSet<&'a DIType>>,
|
2013-06-14 11:38:29 -07:00
|
|
|
}
|
|
|
|
|
2018-07-17 18:45:33 +03:00
|
|
|
impl Drop for CrateDebugContext<'a, 'tcx> {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
unsafe {
|
|
|
|
llvm::LLVMRustDIBuilderDispose(&mut *(self.builder as *mut _));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-27 17:57:25 +03:00
|
|
|
impl<'a, 'tcx> CrateDebugContext<'a, 'tcx> {
|
|
|
|
pub fn new(llmod: &'a llvm::Module) -> Self {
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("CrateDebugContext::new");
|
2016-08-02 02:35:09 +03:00
|
|
|
let builder = unsafe { llvm::LLVMRustDIBuilderCreate(llmod) };
|
2013-06-17 08:42:05 -07:00
|
|
|
// DIBuilder inherits context from the module, so we'd better use the same one
|
|
|
|
let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
|
2016-12-16 18:48:25 -07:00
|
|
|
CrateDebugContext {
|
2017-08-06 22:54:09 -07:00
|
|
|
llcontext,
|
|
|
|
llmod,
|
|
|
|
builder,
|
2018-10-16 16:57:53 +02:00
|
|
|
created_files: Default::default(),
|
|
|
|
created_enum_disr_types: Default::default(),
|
|
|
|
type_map: Default::default(),
|
2018-07-21 22:15:11 +03:00
|
|
|
namespace_map: RefCell::new(Default::default()),
|
2018-10-16 16:57:53 +02:00
|
|
|
composite_types_completed: Default::default(),
|
2016-12-16 18:48:25 -07:00
|
|
|
}
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// Creates any deferred debug metadata nodes
|
2019-02-25 08:40:18 +01:00
|
|
|
pub fn finalize(cx: &CodegenCx<'_, '_>) {
|
2018-01-05 06:58:34 +02:00
|
|
|
if cx.dbg_cx.is_none() {
|
2013-09-06 16:00:08 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("finalize");
|
2014-12-03 14:48:18 -08:00
|
|
|
|
2015-04-24 15:25:42 +12:00
|
|
|
if gdb::needs_gdb_debug_scripts_section(cx) {
|
2014-12-03 14:48:18 -08:00
|
|
|
// Add a .debug_gdb_scripts section to this compile-unit. This will
|
|
|
|
// cause GDB to try and load the gdb_load_rust_pretty_printers.py file,
|
|
|
|
// which activates the Rust pretty printers for binary this section is
|
|
|
|
// contained in.
|
2015-04-24 15:25:42 +12:00
|
|
|
gdb::get_or_insert_gdb_debug_scripts_section_global(cx);
|
2014-12-03 14:48:18 -08:00
|
|
|
}
|
|
|
|
|
2013-06-11 12:41:09 -07:00
|
|
|
unsafe {
|
2016-08-02 02:35:09 +03:00
|
|
|
llvm::LLVMRustDIBuilderFinalize(DIB(cx));
|
2014-01-28 00:05:33 -05:00
|
|
|
// Debuginfo generation in LLVM by default uses a higher
|
2017-03-12 14:13:35 -04:00
|
|
|
// version of dwarf than macOS currently understands. We can
|
2014-01-28 00:05:33 -05:00
|
|
|
// instruct LLVM to emit an older version of dwarf, however,
|
2017-03-12 14:13:35 -04:00
|
|
|
// for macOS to understand. For more info see #11352
|
2014-01-28 00:05:33 -05:00
|
|
|
// This can be overridden using --llvm-opts -dwarf-version,N.
|
2015-02-16 17:48:50 +09:00
|
|
|
// Android has the same issue (#22398)
|
|
|
|
if cx.sess().target.target.options.is_like_osx ||
|
|
|
|
cx.sess().target.target.options.is_like_android {
|
2018-01-05 06:58:34 +02:00
|
|
|
llvm::LLVMRustAddModuleFlag(cx.llmod,
|
2014-11-25 13:28:35 -08:00
|
|
|
"Dwarf Version\0".as_ptr() as *const _,
|
|
|
|
2)
|
2014-01-28 00:05:33 -05:00
|
|
|
}
|
|
|
|
|
2016-01-30 22:30:19 -08:00
|
|
|
// Indicate that we want CodeView debug information on MSVC
|
|
|
|
if cx.sess().target.target.options.is_like_msvc {
|
2018-01-05 06:58:34 +02:00
|
|
|
llvm::LLVMRustAddModuleFlag(cx.llmod,
|
2016-01-30 22:30:19 -08:00
|
|
|
"CodeView\0".as_ptr() as *const _,
|
|
|
|
1)
|
|
|
|
}
|
|
|
|
|
2014-01-28 00:05:33 -05:00
|
|
|
// Prevent bitcode readers from deleting the debug info.
|
2014-11-25 13:28:35 -08:00
|
|
|
let ptr = "Debug Info Version\0".as_ptr();
|
2018-01-05 06:58:34 +02:00
|
|
|
llvm::LLVMRustAddModuleFlag(cx.llmod, ptr as *const _,
|
2015-05-11 21:07:38 -07:00
|
|
|
llvm::LLVMRustDebugMetadataVersion());
|
2013-06-14 11:38:29 -07:00
|
|
|
};
|
2011-11-10 00:55:09 -05:00
|
|
|
}
|
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
impl DebugInfoBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
|
|
|
fn declare_local(
|
2018-10-05 15:08:49 +02:00
|
|
|
&mut self,
|
2018-09-20 15:47:22 +02:00
|
|
|
dbg_context: &FunctionDebugContext<&'ll DISubprogram>,
|
|
|
|
variable_name: ast::Name,
|
|
|
|
variable_type: Ty<'tcx>,
|
|
|
|
scope_metadata: &'ll DIScope,
|
|
|
|
variable_access: VariableAccess<'_, &'ll Value>,
|
|
|
|
variable_kind: VariableKind,
|
|
|
|
span: Span,
|
|
|
|
) {
|
2018-12-02 18:09:26 +01:00
|
|
|
assert!(!dbg_context.get_ref(span).source_locations_enabled);
|
2018-09-20 15:47:22 +02:00
|
|
|
let cx = self.cx();
|
|
|
|
|
|
|
|
let file = span_start(cx, span).file;
|
|
|
|
let file_metadata = file_metadata(cx,
|
|
|
|
&file.name,
|
|
|
|
dbg_context.get_ref(span).defining_crate);
|
|
|
|
|
|
|
|
let loc = span_start(cx, span);
|
|
|
|
let type_metadata = type_metadata(cx, variable_type, span);
|
|
|
|
|
|
|
|
let (argument_index, dwarf_tag) = match variable_kind {
|
|
|
|
ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),
|
|
|
|
LocalVariable => (0, DW_TAG_auto_variable)
|
|
|
|
};
|
|
|
|
let align = cx.align_of(variable_type);
|
|
|
|
|
|
|
|
let name = SmallCStr::new(&variable_name.as_str());
|
|
|
|
match (variable_access, &[][..]) {
|
|
|
|
(DirectVariable { alloca }, address_operations) |
|
|
|
|
(IndirectVariable {alloca, address_operations}, _) => {
|
|
|
|
let metadata = unsafe {
|
|
|
|
llvm::LLVMRustDIBuilderCreateVariable(
|
|
|
|
DIB(cx),
|
|
|
|
dwarf_tag,
|
|
|
|
scope_metadata,
|
|
|
|
name.as_ptr(),
|
|
|
|
file_metadata,
|
|
|
|
loc.line as c_uint,
|
|
|
|
type_metadata,
|
|
|
|
cx.sess().opts.optimize != config::OptLevel::No,
|
|
|
|
DIFlags::FlagZero,
|
|
|
|
argument_index,
|
2018-09-09 01:16:45 +03:00
|
|
|
align.bytes() as u32,
|
2018-09-20 15:47:22 +02:00
|
|
|
)
|
|
|
|
};
|
|
|
|
source_loc::set_debug_location(self,
|
|
|
|
InternalDebugLocation::new(scope_metadata, loc.line, loc.col.to_usize()));
|
|
|
|
unsafe {
|
|
|
|
let debug_loc = llvm::LLVMGetCurrentDebugLocation(self.llbuilder);
|
|
|
|
let instr = llvm::LLVMRustDIBuilderInsertDeclareAtEnd(
|
|
|
|
DIB(cx),
|
|
|
|
alloca,
|
|
|
|
metadata,
|
|
|
|
address_operations.as_ptr(),
|
|
|
|
address_operations.len() as c_uint,
|
|
|
|
debug_loc,
|
|
|
|
self.llbb());
|
|
|
|
|
|
|
|
llvm::LLVMSetInstDebugLocation(self.llbuilder, instr);
|
|
|
|
}
|
|
|
|
source_loc::set_debug_location(self, UnknownLocation);
|
|
|
|
}
|
|
|
|
}
|
2013-08-23 18:45:02 +02:00
|
|
|
}
|
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
fn set_source_location(
|
2018-10-05 15:08:49 +02:00
|
|
|
&mut self,
|
2018-12-02 18:25:42 +01:00
|
|
|
debug_context: &mut FunctionDebugContext<&'ll DISubprogram>,
|
2018-09-20 15:47:22 +02:00
|
|
|
scope: Option<&'ll DIScope>,
|
|
|
|
span: Span,
|
|
|
|
) {
|
|
|
|
set_source_location(debug_context, &self, scope, span)
|
2016-12-19 07:33:35 -07:00
|
|
|
}
|
2018-10-05 15:08:49 +02:00
|
|
|
fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) {
|
2018-09-24 15:26:39 +02:00
|
|
|
gdb::insert_reference_to_gdb_debug_scripts_section_global(self)
|
|
|
|
}
|
2018-12-04 20:20:45 +01:00
|
|
|
|
|
|
|
fn set_value_name(&mut self, value: &'ll Value, name: &str) {
|
|
|
|
let cname = SmallCStr::new(name);
|
|
|
|
unsafe {
|
|
|
|
llvm::LLVMSetValueName(value, cname.as_ptr());
|
|
|
|
}
|
|
|
|
}
|
2018-09-20 15:47:22 +02:00
|
|
|
}
|
2016-12-19 07:33:35 -07:00
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|
|
|
fn create_function_debug_context(
|
|
|
|
&self,
|
|
|
|
instance: Instance<'tcx>,
|
|
|
|
sig: ty::FnSig<'tcx>,
|
|
|
|
llfn: &'ll Value,
|
2019-02-25 08:40:18 +01:00
|
|
|
mir: &mir::Mir<'_>,
|
2018-09-20 15:47:22 +02:00
|
|
|
) -> FunctionDebugContext<&'ll DISubprogram> {
|
|
|
|
if self.sess().opts.debuginfo == DebugInfo::None {
|
|
|
|
return FunctionDebugContext::DebugInfoDisabled;
|
|
|
|
}
|
2016-05-01 12:46:55 -04:00
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
if let InstanceDef::Item(def_id) = instance.def {
|
|
|
|
if self.tcx().codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NO_DEBUG) {
|
|
|
|
return FunctionDebugContext::FunctionWithoutDebugInfo;
|
|
|
|
}
|
|
|
|
}
|
2013-08-23 18:45:02 +02:00
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
let span = mir.span;
|
2013-06-18 13:06:41 +02:00
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
// This can be the case for functions inlined from another crate
|
|
|
|
if span.is_dummy() {
|
|
|
|
// FIXME(simulacrum): Probably can't happen; remove.
|
|
|
|
return FunctionDebugContext::FunctionWithoutDebugInfo;
|
|
|
|
}
|
2013-08-13 12:52:39 +02:00
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
let def_id = instance.def_id();
|
|
|
|
let containing_scope = get_containing_scope(self, instance);
|
|
|
|
let loc = span_start(self, span);
|
|
|
|
let file_metadata = file_metadata(self, &loc.file.name, def_id.krate);
|
2016-11-03 22:19:33 +02:00
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
let function_type_metadata = unsafe {
|
|
|
|
let fn_signature = get_function_signature(self, sig);
|
|
|
|
llvm::LLVMRustDIBuilderCreateSubroutineType(DIB(self), file_metadata, fn_signature)
|
|
|
|
};
|
|
|
|
|
|
|
|
// Find the enclosing function, in case this is a closure.
|
|
|
|
let def_key = self.tcx().def_key(def_id);
|
|
|
|
let mut name = def_key.disambiguated_data.data.to_string();
|
|
|
|
|
|
|
|
let enclosing_fn_def_id = self.tcx().closure_base_def_id(def_id);
|
2016-04-06 15:37:19 +03:00
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
// Get_template_parameters() will append a `<...>` clause to the function
|
|
|
|
// name if necessary.
|
|
|
|
let generics = self.tcx().generics_of(enclosing_fn_def_id);
|
|
|
|
let substs = instance.substs.truncate_to(self.tcx(), generics);
|
|
|
|
let template_parameters = get_template_parameters(self,
|
|
|
|
&generics,
|
|
|
|
substs,
|
|
|
|
file_metadata,
|
|
|
|
&mut name);
|
2016-04-06 15:37:19 +03:00
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
// Get the linkage_name, which is just the symbol name
|
|
|
|
let linkage_name = mangled_name_of_instance(self, instance);
|
2013-09-06 16:00:08 +02:00
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
let scope_line = span_start(self, span).line;
|
2013-08-19 18:23:43 +02:00
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
let function_name = CString::new(name).unwrap();
|
|
|
|
let linkage_name = SmallCStr::new(&linkage_name.as_str());
|
2016-05-01 12:46:55 -04:00
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
let mut flags = DIFlags::FlagPrototyped;
|
2018-02-19 12:41:10 +01:00
|
|
|
|
2019-01-13 13:06:26 +01:00
|
|
|
if let Some((id, _)) = self.tcx.entry_fn(LOCAL_CRATE) {
|
|
|
|
if id == def_id {
|
2018-09-20 15:47:22 +02:00
|
|
|
flags |= DIFlags::FlagMainSubprogram;
|
|
|
|
}
|
2016-11-30 14:59:45 -07:00
|
|
|
}
|
2018-10-09 15:15:41 +02:00
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
if self.layout_of(sig.output()).abi.is_uninhabited() {
|
|
|
|
flags |= DIFlags::FlagNoReturn;
|
|
|
|
}
|
2016-11-30 14:59:45 -07:00
|
|
|
|
2019-01-16 09:59:03 -08:00
|
|
|
let mut spflags = DISPFlags::SPFlagDefinition;
|
|
|
|
if is_node_local_to_unit(self, def_id) {
|
|
|
|
spflags |= DISPFlags::SPFlagLocalToUnit;
|
|
|
|
}
|
|
|
|
if self.sess().opts.optimize != config::OptLevel::No {
|
|
|
|
spflags |= DISPFlags::SPFlagOptimized;
|
|
|
|
}
|
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
let fn_metadata = unsafe {
|
|
|
|
llvm::LLVMRustDIBuilderCreateFunction(
|
|
|
|
DIB(self),
|
|
|
|
containing_scope,
|
|
|
|
function_name.as_ptr(),
|
|
|
|
linkage_name.as_ptr(),
|
|
|
|
file_metadata,
|
|
|
|
loc.line as c_uint,
|
|
|
|
function_type_metadata,
|
|
|
|
scope_line as c_uint,
|
|
|
|
flags,
|
2019-01-16 09:59:03 -08:00
|
|
|
spflags,
|
2018-09-20 15:47:22 +02:00
|
|
|
llfn,
|
|
|
|
template_parameters,
|
|
|
|
None)
|
|
|
|
};
|
2013-08-13 12:52:39 +02:00
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
// Initialize fn debug context (including scope map and namespace map)
|
|
|
|
let fn_debug_context = FunctionDebugContextData {
|
|
|
|
fn_metadata,
|
2018-12-02 18:09:26 +01:00
|
|
|
source_locations_enabled: false,
|
2018-09-20 15:47:22 +02:00
|
|
|
defining_crate: def_id.krate,
|
|
|
|
};
|
2013-08-13 12:52:39 +02:00
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
return FunctionDebugContext::RegularContext(fn_debug_context);
|
2013-08-13 12:52:39 +02:00
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
fn get_function_signature<'ll, 'tcx>(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
sig: ty::FnSig<'tcx>,
|
|
|
|
) -> &'ll DIArray {
|
|
|
|
if cx.sess().opts.debuginfo == DebugInfo::Limited {
|
|
|
|
return create_DIArray(DIB(cx), &[]);
|
|
|
|
}
|
2013-08-13 12:52:39 +02:00
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
let mut signature = Vec::with_capacity(sig.inputs().len() + 1);
|
2015-07-13 21:48:07 +02:00
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
// Return type -- llvm::DIBuilder wants this at index 0
|
|
|
|
signature.push(match sig.output().sty {
|
|
|
|
ty::Tuple(ref tys) if tys.is_empty() => None,
|
|
|
|
_ => Some(type_metadata(cx, sig.output(), syntax_pos::DUMMY_SP))
|
|
|
|
});
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
let inputs = if sig.abi == Abi::RustCall {
|
|
|
|
&sig.inputs()[..sig.inputs().len() - 1]
|
|
|
|
} else {
|
|
|
|
sig.inputs()
|
|
|
|
};
|
2015-07-14 19:03:13 +02:00
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
// Arguments types
|
|
|
|
if cx.sess().target.target.options.is_like_msvc {
|
|
|
|
// FIXME(#42800):
|
|
|
|
// There is a bug in MSDIA that leads to a crash when it encounters
|
|
|
|
// a fixed-size array of `u8` or something zero-sized in a
|
|
|
|
// function-type (see #40477).
|
|
|
|
// As a workaround, we replace those fixed-size arrays with a
|
|
|
|
// pointer-type. So a function `fn foo(a: u8, b: [u8; 4])` would
|
|
|
|
// appear as `fn foo(a: u8, b: *const u8)` in debuginfo,
|
|
|
|
// and a function `fn bar(x: [(); 7])` as `fn bar(x: *const ())`.
|
|
|
|
// This transformed type is wrong, but these function types are
|
|
|
|
// already inaccurate due to ABI adjustments (see #42800).
|
|
|
|
signature.extend(inputs.iter().map(|&t| {
|
|
|
|
let t = match t.sty {
|
|
|
|
ty::Array(ct, _)
|
|
|
|
if (ct == cx.tcx.types.u8) || cx.layout_of(ct).is_zst() => {
|
|
|
|
cx.tcx.mk_imm_ptr(ct)
|
|
|
|
}
|
|
|
|
_ => t
|
|
|
|
};
|
|
|
|
Some(type_metadata(cx, t, syntax_pos::DUMMY_SP))
|
|
|
|
}));
|
|
|
|
} else {
|
|
|
|
signature.extend(inputs.iter().map(|t| {
|
|
|
|
Some(type_metadata(cx, t, syntax_pos::DUMMY_SP))
|
|
|
|
}));
|
|
|
|
}
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
if sig.abi == Abi::RustCall && !sig.inputs().is_empty() {
|
|
|
|
if let ty::Tuple(args) = sig.inputs()[sig.inputs().len() - 1].sty {
|
|
|
|
signature.extend(
|
|
|
|
args.iter().map(|argument_type| {
|
|
|
|
Some(type_metadata(cx, argument_type, syntax_pos::DUMMY_SP))
|
|
|
|
})
|
|
|
|
);
|
|
|
|
}
|
2016-03-06 16:30:21 +02:00
|
|
|
}
|
2018-09-20 15:47:22 +02:00
|
|
|
|
|
|
|
create_DIArray(DIB(cx), &signature[..])
|
2016-03-06 16:30:21 +02:00
|
|
|
}
|
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
fn get_template_parameters<'ll, 'tcx>(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
generics: &ty::Generics,
|
2019-02-26 09:30:34 +08:00
|
|
|
substs: SubstsRef<'tcx>,
|
2018-09-20 15:47:22 +02:00
|
|
|
file_metadata: &'ll DIFile,
|
|
|
|
name_to_append_suffix_to: &mut String,
|
|
|
|
) -> &'ll DIArray {
|
|
|
|
if substs.types().next().is_none() {
|
|
|
|
return create_DIArray(DIB(cx), &[]);
|
|
|
|
}
|
2013-08-08 18:33:06 +02:00
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
name_to_append_suffix_to.push('<');
|
|
|
|
for (i, actual_type) in substs.types().enumerate() {
|
|
|
|
if i != 0 {
|
|
|
|
name_to_append_suffix_to.push_str(",");
|
|
|
|
}
|
2013-08-08 18:33:06 +02:00
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
let actual_type =
|
|
|
|
cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), actual_type);
|
|
|
|
// Add actual type name to <...> clause of function name
|
|
|
|
let actual_type_name = compute_debuginfo_type_name(cx,
|
|
|
|
actual_type,
|
|
|
|
true);
|
|
|
|
name_to_append_suffix_to.push_str(&actual_type_name[..]);
|
2016-08-18 08:32:50 +03:00
|
|
|
}
|
2018-09-20 15:47:22 +02:00
|
|
|
name_to_append_suffix_to.push('>');
|
|
|
|
|
|
|
|
// Again, only create type information if full debuginfo is enabled
|
|
|
|
let template_params: Vec<_> = if cx.sess().opts.debuginfo == DebugInfo::Full {
|
|
|
|
let names = get_parameter_names(cx, generics);
|
|
|
|
substs.iter().zip(names).filter_map(|(kind, name)| {
|
|
|
|
if let UnpackedKind::Type(ty) = kind.unpack() {
|
|
|
|
let actual_type =
|
|
|
|
cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty);
|
|
|
|
let actual_type_metadata =
|
|
|
|
type_metadata(cx, actual_type, syntax_pos::DUMMY_SP);
|
|
|
|
let name = SmallCStr::new(&name.as_str());
|
|
|
|
Some(unsafe {
|
|
|
|
Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter(
|
|
|
|
DIB(cx),
|
|
|
|
None,
|
|
|
|
name.as_ptr(),
|
|
|
|
actual_type_metadata,
|
|
|
|
file_metadata,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
))
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}).collect()
|
|
|
|
} else {
|
|
|
|
vec![]
|
|
|
|
};
|
|
|
|
|
|
|
|
return create_DIArray(DIB(cx), &template_params[..]);
|
|
|
|
}
|
2016-08-18 08:32:50 +03:00
|
|
|
|
2019-02-25 08:40:18 +01:00
|
|
|
fn get_parameter_names(cx: &CodegenCx<'_, '_>,
|
2018-09-20 15:47:22 +02:00
|
|
|
generics: &ty::Generics)
|
|
|
|
-> Vec<InternedString> {
|
|
|
|
let mut names = generics.parent.map_or(vec![], |def_id| {
|
|
|
|
get_parameter_names(cx, cx.tcx.generics_of(def_id))
|
|
|
|
});
|
|
|
|
names.extend(generics.params.iter().map(|param| param.name));
|
|
|
|
names
|
2016-04-06 10:49:50 +03:00
|
|
|
}
|
2018-09-20 15:47:22 +02:00
|
|
|
|
|
|
|
fn get_containing_scope<'ll, 'tcx>(
|
|
|
|
cx: &CodegenCx<'ll, 'tcx>,
|
|
|
|
instance: Instance<'tcx>,
|
|
|
|
) -> &'ll DIScope {
|
|
|
|
// First, let's see if this is a method within an inherent impl. Because
|
|
|
|
// if yes, we want to make the result subroutine DIE a child of the
|
|
|
|
// subroutine's self-type.
|
|
|
|
let self_type = cx.tcx.impl_of_method(instance.def_id()).and_then(|impl_def_id| {
|
|
|
|
// If the method does *not* belong to a trait, proceed
|
|
|
|
if cx.tcx.trait_id_of_impl(impl_def_id).is_none() {
|
|
|
|
let impl_self_ty = cx.tcx.subst_and_normalize_erasing_regions(
|
|
|
|
instance.substs,
|
|
|
|
ty::ParamEnv::reveal_all(),
|
|
|
|
&cx.tcx.type_of(impl_def_id),
|
|
|
|
);
|
|
|
|
|
|
|
|
// Only "class" methods are generally understood by LLVM,
|
2018-11-27 02:59:49 +00:00
|
|
|
// so avoid methods on other types (e.g., `<*mut T>::null`).
|
2018-09-20 15:47:22 +02:00
|
|
|
match impl_self_ty.sty {
|
|
|
|
ty::Adt(def, ..) if !def.is_box() => {
|
|
|
|
Some(type_metadata(cx, impl_self_ty, syntax_pos::DUMMY_SP))
|
|
|
|
}
|
|
|
|
_ => None
|
|
|
|
}
|
2018-04-13 00:57:38 +01:00
|
|
|
} else {
|
2018-09-20 15:47:22 +02:00
|
|
|
// For trait method impls we still use the "parallel namespace"
|
|
|
|
// strategy
|
2018-04-13 00:57:38 +01:00
|
|
|
None
|
|
|
|
}
|
2018-09-20 15:47:22 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
self_type.unwrap_or_else(|| {
|
|
|
|
namespace::item_namespace(cx, DefId {
|
|
|
|
krate: instance.def_id().krate,
|
|
|
|
index: cx.tcx
|
|
|
|
.def_key(instance.def_id())
|
|
|
|
.parent
|
|
|
|
.expect("get_containing_scope: missing parent?")
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
2013-08-08 18:33:06 +02:00
|
|
|
}
|
2016-05-01 12:46:55 -04:00
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
fn create_vtable_metadata(
|
|
|
|
&self,
|
|
|
|
ty: Ty<'tcx>,
|
|
|
|
vtable: Self::Value,
|
|
|
|
) {
|
|
|
|
metadata::create_vtable_metadata(self, ty, vtable)
|
2016-08-10 20:39:09 +03:00
|
|
|
}
|
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
fn create_mir_scopes(
|
|
|
|
&self,
|
2019-02-25 08:40:18 +01:00
|
|
|
mir: &mir::Mir<'_>,
|
2018-12-02 18:25:42 +01:00
|
|
|
debug_context: &mut FunctionDebugContext<&'ll DISubprogram>,
|
2018-09-20 15:47:22 +02:00
|
|
|
) -> IndexVec<mir::SourceScope, MirDebugScope<&'ll DIScope>> {
|
|
|
|
create_scope_map::create_mir_scopes(self, mir, debug_context)
|
2016-05-01 12:46:55 -04:00
|
|
|
}
|
2013-06-18 13:06:41 +02:00
|
|
|
|
2018-09-20 15:47:22 +02:00
|
|
|
fn extend_scope_to_file(
|
2018-10-03 13:49:57 +02:00
|
|
|
&self,
|
|
|
|
scope_metadata: &'ll DIScope,
|
|
|
|
file: &syntax_pos::SourceFile,
|
|
|
|
defining_crate: CrateNum,
|
|
|
|
) -> &'ll DILexicalBlock {
|
|
|
|
metadata::extend_scope_to_file(&self, scope_metadata, file, defining_crate)
|
|
|
|
}
|
2018-09-26 17:00:01 +02:00
|
|
|
|
|
|
|
fn debuginfo_finalize(&self) {
|
|
|
|
finalize(self)
|
|
|
|
}
|
2018-10-03 13:49:57 +02:00
|
|
|
|
2018-10-03 16:56:24 +02:00
|
|
|
fn debuginfo_upvar_decls_ops_sequence(&self, byte_offset_of_var_in_env: u64) -> [i64; 4] {
|
2018-10-03 13:49:57 +02:00
|
|
|
unsafe {
|
|
|
|
[llvm::LLVMRustDIBuilderCreateOpDeref(),
|
|
|
|
llvm::LLVMRustDIBuilderCreateOpPlusUconst(),
|
|
|
|
byte_offset_of_var_in_env as i64,
|
|
|
|
llvm::LLVMRustDIBuilderCreateOpDeref()]
|
2018-10-03 16:56:24 +02:00
|
|
|
}
|
2018-10-03 13:49:57 +02:00
|
|
|
}
|
2014-05-15 14:13:33 +02:00
|
|
|
}
|