2015-04-24 13:20:54 +12:00
|
|
|
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
2015-04-24 17:25:35 +12:00
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
2015-04-24 13:20:54 +12:00
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
2015-04-24 17:25:35 +12:00
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
2015-04-24 13:20:54 +12:00
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
|
|
|
// See doc.rs for documentation.
|
|
|
|
mod doc;
|
2012-12-03 16:48:01 -08:00
|
|
|
|
2015-04-24 17:20:13 +12:00
|
|
|
use self::VariableAccess::*;
|
|
|
|
use self::VariableKind::*;
|
|
|
|
|
2015-04-29 18:14:37 +12:00
|
|
|
use self::utils::{DIB, span_start, assert_type_for_node_id, contains_nodebug_attribute,
|
|
|
|
create_DIArray, is_node_local_to_unit};
|
2015-04-24 16:08:11 +12:00
|
|
|
use self::namespace::{namespace_for_item, NamespaceTreeNode};
|
2015-04-29 18:14:37 +12:00
|
|
|
use self::type_names::compute_debuginfo_type_name;
|
2015-07-13 21:48:07 +02:00
|
|
|
use self::metadata::{type_metadata, diverging_type_metadata};
|
|
|
|
use self::metadata::{file_metadata, scope_metadata, TypeMap, compile_unit_metadata};
|
2015-04-29 18:14:37 +12:00
|
|
|
use self::source_loc::InternalDebugLocation;
|
2013-06-18 10:17:10 +02:00
|
|
|
|
2014-07-07 17:58:01 -07:00
|
|
|
use llvm;
|
|
|
|
use llvm::{ModuleRef, ContextRef, ValueRef};
|
2015-04-29 18:14:37 +12:00
|
|
|
use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray,
|
|
|
|
DIDescriptor, FlagPrototyped};
|
2015-01-03 22:42:21 -05:00
|
|
|
use middle::subst::{self, Substs};
|
2015-06-10 02:40:45 +03:00
|
|
|
use rustc::ast_map;
|
2015-04-29 18:14:37 +12:00
|
|
|
use trans::common::{NodeIdAndSpan, CrateContext, FunctionContext, Block};
|
|
|
|
use trans;
|
2014-12-17 14:16:28 -05:00
|
|
|
use trans::monomorphize;
|
2015-07-13 21:48:07 +02:00
|
|
|
use middle::ty::{self, Ty};
|
2015-01-03 22:42:21 -05:00
|
|
|
use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
|
2015-07-16 01:34:13 -07:00
|
|
|
use util::nodemap::{NodeMap, FnvHashMap, FnvHashSet};
|
2012-12-13 13:05:22 -08:00
|
|
|
|
2015-04-24 16:48:10 +12:00
|
|
|
use libc::c_uint;
|
2013-12-18 19:09:14 -08:00
|
|
|
use std::cell::{Cell, RefCell};
|
2015-02-26 21:00:43 -08:00
|
|
|
use std::ffi::CString;
|
2013-06-28 18:32:26 -04:00
|
|
|
use std::ptr;
|
2015-04-24 16:00:47 +12:00
|
|
|
use std::rc::Rc;
|
2013-09-15 09:50:17 -07:00
|
|
|
use syntax::codemap::{Span, Pos};
|
2015-06-10 02:40:45 +03:00
|
|
|
use syntax::{ast, codemap, ast_util};
|
2015-07-16 01:34:13 -07:00
|
|
|
use syntax::attr::IntType;
|
2015-01-03 22:42:21 -05:00
|
|
|
use syntax::parse::token::{self, special_idents};
|
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;
|
2015-04-24 17:25:35 +12:00
|
|
|
mod metadata;
|
2015-04-29 18:14:37 +12:00
|
|
|
mod create_scope_map;
|
|
|
|
mod source_loc;
|
|
|
|
|
|
|
|
pub use self::source_loc::set_source_location;
|
|
|
|
pub use self::source_loc::clear_source_location;
|
|
|
|
pub use self::source_loc::start_emitting_source_locations;
|
|
|
|
pub use self::source_loc::get_cleanup_debug_loc_for_ast_node;
|
|
|
|
pub use self::source_loc::with_source_location_override;
|
|
|
|
pub use self::metadata::create_match_binding_metadata;
|
|
|
|
pub use self::metadata::create_argument_metadata;
|
|
|
|
pub use self::metadata::create_captured_var_metadata;
|
|
|
|
pub use self::metadata::create_global_var_metadata;
|
|
|
|
pub use self::metadata::create_local_var_metadata;
|
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.
|
2014-09-29 22:11:30 +03:00
|
|
|
pub struct CrateDebugContext<'tcx> {
|
2014-03-28 10:05:27 -07:00
|
|
|
llcontext: ContextRef,
|
|
|
|
builder: DIBuilderRef,
|
2014-12-11 13:53:30 +01:00
|
|
|
current_debug_location: Cell<InternalDebugLocation>,
|
2014-11-10 00:59:56 +02:00
|
|
|
created_files: RefCell<FnvHashMap<String, DIFile>>,
|
2015-07-16 01:34:13 -07:00
|
|
|
created_enum_disr_types: RefCell<FnvHashMap<(ast::DefId, IntType), DIType>>,
|
2014-05-30 17:09:16 +02:00
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
type_map: RefCell<TypeMap<'tcx>>,
|
2014-11-10 00:59:56 +02:00
|
|
|
namespace_map: RefCell<FnvHashMap<Vec<ast::Name>, Rc<NamespaceTreeNode>>>,
|
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:
|
2014-11-10 00:59:56 +02:00
|
|
|
composite_types_completed: RefCell<FnvHashSet<DIType>>,
|
2013-06-14 11:38:29 -07:00
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
impl<'tcx> CrateDebugContext<'tcx> {
|
|
|
|
pub fn new(llmod: ModuleRef) -> CrateDebugContext<'tcx> {
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("CrateDebugContext::new");
|
2013-06-17 08:42:05 -07:00
|
|
|
let builder = unsafe { llvm::LLVMDIBuilderCreate(llmod) };
|
|
|
|
// DIBuilder inherits context from the module, so we'd better use the same one
|
|
|
|
let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
|
2013-08-29 11:44:11 +02:00
|
|
|
return CrateDebugContext {
|
2013-06-17 08:42:05 -07:00
|
|
|
llcontext: llcontext,
|
|
|
|
builder: builder,
|
2015-04-29 18:14:37 +12:00
|
|
|
current_debug_location: Cell::new(InternalDebugLocation::UnknownLocation),
|
2015-01-16 14:27:43 -08:00
|
|
|
created_files: RefCell::new(FnvHashMap()),
|
2015-07-16 01:34:13 -07:00
|
|
|
created_enum_disr_types: RefCell::new(FnvHashMap()),
|
2014-05-30 17:09:16 +02:00
|
|
|
type_map: RefCell::new(TypeMap::new()),
|
2015-01-16 14:27:43 -08:00
|
|
|
namespace_map: RefCell::new(FnvHashMap()),
|
|
|
|
composite_types_completed: RefCell::new(FnvHashSet()),
|
2013-08-05 11:12:40 +02:00
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-19 11:37:49 +01:00
|
|
|
pub enum FunctionDebugContext {
|
|
|
|
RegularContext(Box<FunctionDebugContextData>),
|
2014-04-15 18:05:38 -07:00
|
|
|
DebugInfoDisabled,
|
|
|
|
FunctionWithoutDebugInfo,
|
2013-08-23 18:45:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl FunctionDebugContext {
|
2014-06-18 15:07:26 +12:00
|
|
|
fn get_ref<'a>(&'a self,
|
|
|
|
cx: &CrateContext,
|
|
|
|
span: Span)
|
|
|
|
-> &'a FunctionDebugContextData {
|
2014-12-19 11:37:49 +01:00
|
|
|
match *self {
|
|
|
|
FunctionDebugContext::RegularContext(box ref data) => data,
|
|
|
|
FunctionDebugContext::DebugInfoDisabled => {
|
2014-06-18 15:07:26 +12:00
|
|
|
cx.sess().span_bug(span,
|
|
|
|
FunctionDebugContext::debuginfo_disabled_message());
|
2013-08-23 18:45:02 +02:00
|
|
|
}
|
2014-12-19 11:37:49 +01:00
|
|
|
FunctionDebugContext::FunctionWithoutDebugInfo => {
|
2014-06-18 15:07:26 +12:00
|
|
|
cx.sess().span_bug(span,
|
|
|
|
FunctionDebugContext::should_be_ignored_message());
|
2013-08-23 18:45:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-09 17:58:58 +02:00
|
|
|
fn debuginfo_disabled_message() -> &'static str {
|
|
|
|
"debuginfo: Error trying to access FunctionDebugContext although debug info is disabled!"
|
|
|
|
}
|
|
|
|
|
|
|
|
fn should_be_ignored_message() -> &'static str {
|
|
|
|
"debuginfo: Error trying to access FunctionDebugContext for function that should be \
|
|
|
|
ignored by debug info!"
|
|
|
|
}
|
2013-08-23 18:45:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
struct FunctionDebugContextData {
|
2014-11-10 00:59:56 +02:00
|
|
|
scope_map: RefCell<NodeMap<DIScope>>,
|
2013-08-23 18:45:02 +02:00
|
|
|
fn_metadata: DISubprogram,
|
2015-03-25 17:06:52 -07:00
|
|
|
argument_counter: Cell<usize>,
|
2013-12-20 20:57:25 -08:00
|
|
|
source_locations_enabled: Cell<bool>,
|
2015-03-05 15:00:25 +01:00
|
|
|
source_location_override: Cell<bool>,
|
2013-08-23 18:45:02 +02:00
|
|
|
}
|
|
|
|
|
2015-04-24 15:49:20 +12:00
|
|
|
pub enum VariableAccess<'a> {
|
2013-09-03 18:23:59 +02:00
|
|
|
// The llptr given is an alloca containing the variable's value
|
|
|
|
DirectVariable { alloca: ValueRef },
|
2014-06-18 15:07:26 +12:00
|
|
|
// The llptr given is an alloca containing the start of some pointer chain
|
|
|
|
// leading to the variable's content.
|
2015-01-30 19:25:07 +01:00
|
|
|
IndirectVariable { alloca: ValueRef, address_operations: &'a [i64] }
|
2013-08-23 18:45:02 +02:00
|
|
|
}
|
|
|
|
|
2015-04-24 15:49:20 +12:00
|
|
|
pub enum VariableKind {
|
2015-03-25 17:06:52 -07:00
|
|
|
ArgumentVariable(usize /*index*/),
|
2013-08-23 18:45:02 +02:00
|
|
|
LocalVariable,
|
|
|
|
CapturedVariable,
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
|
2013-06-14 11:59:49 -07:00
|
|
|
/// Create any deferred debug metadata nodes
|
2014-03-06 18:47:24 +02:00
|
|
|
pub fn finalize(cx: &CrateContext) {
|
2014-09-05 09:18:53 -07: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
|
|
|
let _ = compile_unit_metadata(cx);
|
|
|
|
|
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 {
|
2013-06-17 08:42:05 -07:00
|
|
|
llvm::LLVMDIBuilderFinalize(DIB(cx));
|
|
|
|
llvm::LLVMDIBuilderDispose(DIB(cx));
|
2014-01-28 00:05:33 -05:00
|
|
|
// Debuginfo generation in LLVM by default uses a higher
|
|
|
|
// version of dwarf than OS X currently understands. We can
|
|
|
|
// instruct LLVM to emit an older version of dwarf, however,
|
|
|
|
// for OS X to understand. For more info see #11352
|
|
|
|
// 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 {
|
2014-11-25 13:28:35 -08:00
|
|
|
llvm::LLVMRustAddModuleFlag(cx.llmod(),
|
|
|
|
"Dwarf Version\0".as_ptr() as *const _,
|
|
|
|
2)
|
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();
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2013-08-29 11:44:11 +02:00
|
|
|
/// Creates the function-specific debug context.
|
|
|
|
///
|
2014-06-18 15:07:26 +12:00
|
|
|
/// Returns the FunctionDebugContext for the function which holds state needed
|
|
|
|
/// for debug info creation. The function may also return another variant of the
|
|
|
|
/// FunctionDebugContext enum which indicates why no debuginfo should be created
|
|
|
|
/// for the function.
|
2014-09-29 22:11:30 +03:00
|
|
|
pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|
|
|
fn_ast_id: ast::NodeId,
|
2014-11-06 09:24:44 +02:00
|
|
|
param_substs: &Substs<'tcx>,
|
2014-09-29 22:11:30 +03:00
|
|
|
llfn: ValueRef) -> FunctionDebugContext {
|
2014-03-05 16:36:01 +02:00
|
|
|
if cx.sess().opts.debuginfo == NoDebugInfo {
|
2014-12-19 11:37:49 +01:00
|
|
|
return FunctionDebugContext::DebugInfoDisabled;
|
2013-08-23 18:45:02 +02:00
|
|
|
}
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// Clear the debug location so we don't assign them in the function prelude.
|
|
|
|
// Do this here already, in case we do an early exit from this function.
|
2015-04-29 18:14:37 +12:00
|
|
|
source_loc::set_debug_location(cx, InternalDebugLocation::UnknownLocation);
|
2014-03-27 13:43:01 +01:00
|
|
|
|
debuginfo: Make sure that all calls to drop glue are associated with debug locations.
This commit makes rustc emit debug locations for all call
and invoke statements in LLVM IR, if they are contained
within a function that debuginfo is enabled for. This is
important because LLVM does not handle the case where a
function body containing debuginfo is inlined into another
function with debuginfo, but the inlined call statement
does not have a debug location. In this case, LLVM will
not know where (in terms of source code coordinates) the
function was inlined to and we end up with some statements
still linked to the source locations in there original,
non-inlined function without any indication that they are
indeed an inline-copy. Later, when generating DWARF from
the IR, LLVM will interpret this as corrupt IR and abort.
Unfortunately, the undesirable case described above can
still occur when using LTO. If there is a crate compiled
without debuginfo calling into a crate compiled with
debuginfo, we again end up with the conditions triggering
the error. This is why some LTO tests still fail with the
dreaded assertion, if the standard library was built with
debuginfo enabled.
That is, `RUSTFLAGS_STAGE2=-g make rustc-stage2` will
succeed but `RUSTFLAGS_STAGE2=-g make check` will still
fail after this commit has been merged. This is a problem
that has to be dealt with separately.
Fixes #17201
Fixes #15816
Fixes #15156
2014-09-24 08:49:38 +02:00
|
|
|
if fn_ast_id == ast::DUMMY_NODE_ID {
|
|
|
|
// This is a function not linked to any source location, so don't
|
|
|
|
// generate debuginfo for it.
|
2014-12-19 11:37:49 +01:00
|
|
|
return FunctionDebugContext::FunctionWithoutDebugInfo;
|
2013-08-23 18:45:02 +02:00
|
|
|
}
|
2013-06-18 13:06:41 +02:00
|
|
|
|
2014-08-11 09:32:26 -07:00
|
|
|
let empty_generics = ast_util::empty_generics();
|
2013-08-15 18:21:16 +02:00
|
|
|
|
2014-09-05 09:18:53 -07:00
|
|
|
let fnitem = cx.tcx().map.get(fn_ast_id);
|
2014-01-17 23:23:09 +11:00
|
|
|
|
2015-03-23 19:41:35 -05:00
|
|
|
let (name, fn_decl, generics, top_level_block, span, has_path) = match fnitem {
|
2014-02-14 07:07:09 +02:00
|
|
|
ast_map::NodeItem(ref item) => {
|
2015-02-01 21:53:25 -05:00
|
|
|
if contains_nodebug_attribute(&item.attrs) {
|
2014-12-19 11:37:49 +01:00
|
|
|
return FunctionDebugContext::FunctionWithoutDebugInfo;
|
2014-07-10 17:01:11 +02:00
|
|
|
}
|
|
|
|
|
2013-07-11 18:00:21 +02:00
|
|
|
match item.node {
|
2015-05-05 08:47:04 -04:00
|
|
|
ast::ItemFn(ref fn_decl, _, _, _, ref generics, ref top_level_block) => {
|
2015-03-23 19:41:35 -05:00
|
|
|
(item.ident.name, fn_decl, generics, top_level_block, item.span, true)
|
2013-08-16 18:46:29 +02:00
|
|
|
}
|
|
|
|
_ => {
|
2014-03-05 16:36:01 +02:00
|
|
|
cx.sess().span_bug(item.span,
|
2013-08-16 18:46:29 +02:00
|
|
|
"create_function_debug_context: item bound to non-function");
|
2013-07-11 18:00:21 +02:00
|
|
|
}
|
|
|
|
}
|
2013-06-18 13:06:41 +02:00
|
|
|
}
|
2015-03-10 12:28:44 +02:00
|
|
|
ast_map::NodeImplItem(impl_item) => {
|
|
|
|
match impl_item.node {
|
2015-03-11 23:38:58 +02:00
|
|
|
ast::MethodImplItem(ref sig, ref body) => {
|
2015-03-10 12:28:44 +02:00
|
|
|
if contains_nodebug_attribute(&impl_item.attrs) {
|
2014-12-19 11:37:49 +01:00
|
|
|
return FunctionDebugContext::FunctionWithoutDebugInfo;
|
2014-07-10 17:01:11 +02:00
|
|
|
}
|
|
|
|
|
2015-03-23 19:41:35 -05:00
|
|
|
(impl_item.ident.name,
|
2015-03-11 23:38:58 +02:00
|
|
|
&sig.decl,
|
|
|
|
&sig.generics,
|
|
|
|
body,
|
2015-03-10 12:28:44 +02:00
|
|
|
impl_item.span,
|
2014-08-04 13:56:56 -07:00
|
|
|
true)
|
|
|
|
}
|
2015-03-14 12:05:00 -06:00
|
|
|
_ => {
|
2015-03-11 23:38:58 +02:00
|
|
|
cx.sess().span_bug(impl_item.span,
|
|
|
|
"create_function_debug_context() \
|
2015-03-14 12:05:00 -06:00
|
|
|
called on non-method impl item?!")
|
2015-03-11 23:38:58 +02:00
|
|
|
}
|
2014-08-04 13:56:56 -07:00
|
|
|
}
|
2013-06-18 13:06:41 +02:00
|
|
|
}
|
2014-01-09 15:05:33 +02:00
|
|
|
ast_map::NodeExpr(ref expr) => {
|
2013-07-11 18:00:21 +02:00
|
|
|
match expr.node {
|
2015-02-03 11:34:05 -05:00
|
|
|
ast::ExprClosure(_, ref fn_decl, ref top_level_block) => {
|
2013-09-27 22:38:08 -07:00
|
|
|
let name = format!("fn{}", token::gensym("fn"));
|
2015-03-23 19:41:35 -05:00
|
|
|
let name = token::intern(&name[..]);
|
2015-03-11 08:38:27 +02:00
|
|
|
(name, fn_decl,
|
2014-06-18 15:07:26 +12:00
|
|
|
// This is not quite right. It should actually inherit
|
|
|
|
// the generics of the enclosing function.
|
2013-08-15 18:21:16 +02:00
|
|
|
&empty_generics,
|
2015-03-11 23:38:58 +02:00
|
|
|
top_level_block,
|
2013-10-01 12:24:50 +02:00
|
|
|
expr.span,
|
|
|
|
// Don't try to lookup the item path:
|
|
|
|
false)
|
2013-07-11 18:00:21 +02:00
|
|
|
}
|
2014-03-05 16:36:01 +02:00
|
|
|
_ => cx.sess().span_bug(expr.span,
|
2013-08-16 18:46:29 +02:00
|
|
|
"create_function_debug_context: expected an expr_fn_block here")
|
2013-07-11 18:00:21 +02:00
|
|
|
}
|
|
|
|
}
|
2015-03-10 12:28:44 +02:00
|
|
|
ast_map::NodeTraitItem(trait_item) => {
|
|
|
|
match trait_item.node {
|
2015-03-11 23:38:58 +02:00
|
|
|
ast::MethodTraitItem(ref sig, Some(ref body)) => {
|
2015-03-10 12:28:44 +02:00
|
|
|
if contains_nodebug_attribute(&trait_item.attrs) {
|
2014-12-19 11:37:49 +01:00
|
|
|
return FunctionDebugContext::FunctionWithoutDebugInfo;
|
2014-07-10 17:01:11 +02:00
|
|
|
}
|
|
|
|
|
2015-03-23 19:41:35 -05:00
|
|
|
(trait_item.ident.name,
|
2015-03-11 23:38:58 +02:00
|
|
|
&sig.decl,
|
|
|
|
&sig.generics,
|
|
|
|
body,
|
2015-03-10 12:28:44 +02:00
|
|
|
trait_item.span,
|
2014-01-03 15:08:48 -08:00
|
|
|
true)
|
|
|
|
}
|
|
|
|
_ => {
|
2014-03-05 16:36:01 +02:00
|
|
|
cx.sess()
|
2015-01-07 11:58:31 -05:00
|
|
|
.bug(&format!("create_function_debug_context: \
|
2014-12-20 00:09:35 -08:00
|
|
|
unexpected sort of node: {:?}",
|
2015-02-20 14:08:14 -05:00
|
|
|
fnitem))
|
2014-01-03 15:08:48 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ast_map::NodeForeignItem(..) |
|
|
|
|
ast_map::NodeVariant(..) |
|
|
|
|
ast_map::NodeStructCtor(..) => {
|
2014-12-19 11:37:49 +01:00
|
|
|
return FunctionDebugContext::FunctionWithoutDebugInfo;
|
2013-08-16 18:46:29 +02:00
|
|
|
}
|
2015-01-07 11:58:31 -05:00
|
|
|
_ => cx.sess().bug(&format!("create_function_debug_context: \
|
2014-12-20 00:09:35 -08:00
|
|
|
unexpected sort of node: {:?}",
|
2015-02-20 14:08:14 -05:00
|
|
|
fnitem))
|
2013-06-18 13:06:41 +02:00
|
|
|
};
|
|
|
|
|
2013-08-23 18:45:02 +02:00
|
|
|
// This can be the case for functions inlined from another crate
|
2014-01-01 15:53:22 +09:00
|
|
|
if span == codemap::DUMMY_SP {
|
2014-12-19 11:37:49 +01:00
|
|
|
return FunctionDebugContext::FunctionWithoutDebugInfo;
|
2013-08-23 18:45:02 +02:00
|
|
|
}
|
|
|
|
|
2013-06-18 13:06:41 +02:00
|
|
|
let loc = span_start(cx, span);
|
2015-02-20 14:08:14 -05:00
|
|
|
let file_metadata = file_metadata(cx, &loc.file.name);
|
2013-06-18 13:06:41 +02:00
|
|
|
|
2013-08-13 12:52:39 +02:00
|
|
|
let function_type_metadata = unsafe {
|
2014-06-18 15:07:26 +12:00
|
|
|
let fn_signature = get_function_signature(cx,
|
|
|
|
fn_ast_id,
|
|
|
|
param_substs,
|
|
|
|
span);
|
2013-08-13 12:52:39 +02:00
|
|
|
llvm::LLVMDIBuilderCreateSubroutineType(DIB(cx), file_metadata, fn_signature)
|
|
|
|
};
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// Get_template_parameters() will append a `<...>` clause to the function
|
|
|
|
// name if necessary.
|
2015-06-08 16:55:35 +02:00
|
|
|
let mut function_name = String::from(&*token::get_name(name));
|
2013-09-15 12:26:47 +02:00
|
|
|
let template_parameters = get_template_parameters(cx,
|
|
|
|
generics,
|
|
|
|
param_substs,
|
|
|
|
file_metadata,
|
|
|
|
&mut function_name);
|
2013-08-13 12:52:39 +02:00
|
|
|
|
2014-11-19 11:18:17 -05:00
|
|
|
// There is no ast_map::Path for ast::ExprClosure-type functions. For now,
|
2014-06-18 15:07:26 +12:00
|
|
|
// just don't put them into a namespace. In the future this could be improved
|
|
|
|
// somehow (storing a path in the ast_map, or construct a path using the
|
|
|
|
// enclosing function).
|
2013-10-01 12:24:50 +02:00
|
|
|
let (linkage_name, containing_scope) = if has_path {
|
2014-02-14 07:07:09 +02:00
|
|
|
let namespace_node = namespace_for_item(cx, ast_util::local_def(fn_ast_id));
|
2014-04-02 16:54:22 -07:00
|
|
|
let linkage_name = namespace_node.mangled_name_of_contained_item(
|
2015-02-18 14:48:57 -05:00
|
|
|
&function_name[..]);
|
2013-10-01 12:24:50 +02:00
|
|
|
let containing_scope = namespace_node.scope;
|
|
|
|
(linkage_name, containing_scope)
|
|
|
|
} else {
|
2014-11-27 14:10:25 -05:00
|
|
|
(function_name.clone(), file_metadata)
|
2013-09-06 16:00:08 +02:00
|
|
|
};
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// Clang sets this parameter to the opening brace of the function's block,
|
|
|
|
// so let's do this too.
|
2013-12-13 14:34:44 +01:00
|
|
|
let scope_line = span_start(cx, top_level_block.span).line;
|
2013-12-14 17:12:59 +01:00
|
|
|
|
2014-02-20 20:44:29 -05:00
|
|
|
let is_local_to_unit = is_node_local_to_unit(cx, fn_ast_id);
|
2013-08-19 18:23:43 +02:00
|
|
|
|
2015-02-17 22:47:40 -08:00
|
|
|
let function_name = CString::new(function_name).unwrap();
|
|
|
|
let linkage_name = CString::new(linkage_name).unwrap();
|
2014-11-25 13:28:35 -08:00
|
|
|
let fn_metadata = unsafe {
|
|
|
|
llvm::LLVMDIBuilderCreateFunction(
|
|
|
|
DIB(cx),
|
|
|
|
containing_scope,
|
|
|
|
function_name.as_ptr(),
|
|
|
|
linkage_name.as_ptr(),
|
|
|
|
file_metadata,
|
|
|
|
loc.line as c_uint,
|
|
|
|
function_type_metadata,
|
|
|
|
is_local_to_unit,
|
|
|
|
true,
|
|
|
|
scope_line as c_uint,
|
|
|
|
FlagPrototyped as c_uint,
|
|
|
|
cx.sess().opts.optimize != config::No,
|
|
|
|
llfn,
|
|
|
|
template_parameters,
|
|
|
|
ptr::null_mut())
|
|
|
|
};
|
2013-08-13 12:52:39 +02:00
|
|
|
|
2015-04-29 18:14:37 +12:00
|
|
|
let scope_map = create_scope_map::create_scope_map(cx,
|
|
|
|
&fn_decl.inputs,
|
|
|
|
&*top_level_block,
|
|
|
|
fn_metadata,
|
|
|
|
fn_ast_id);
|
2014-12-19 11:37:49 +01:00
|
|
|
|
2013-09-06 16:00:08 +02:00
|
|
|
// Initialize fn debug context (including scope map and namespace map)
|
2014-04-25 01:08:02 -07:00
|
|
|
let fn_debug_context = box FunctionDebugContextData {
|
2014-12-19 11:37:49 +01:00
|
|
|
scope_map: RefCell::new(scope_map),
|
2013-08-16 18:46:29 +02:00
|
|
|
fn_metadata: fn_metadata,
|
2013-12-20 20:55:55 -08:00
|
|
|
argument_counter: Cell::new(1),
|
2013-12-20 20:57:25 -08:00
|
|
|
source_locations_enabled: Cell::new(false),
|
2015-03-05 15:00:25 +01:00
|
|
|
source_location_override: Cell::new(false),
|
2013-08-16 18:46:29 +02:00
|
|
|
};
|
2013-08-13 12:52:39 +02:00
|
|
|
|
|
|
|
|
2014-12-19 11:37:49 +01:00
|
|
|
|
|
|
|
return FunctionDebugContext::RegularContext(fn_debug_context);
|
2013-08-13 12:52:39 +02:00
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
fn get_function_signature<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|
|
|
fn_ast_id: ast::NodeId,
|
2014-11-06 09:24:44 +02:00
|
|
|
param_substs: &Substs<'tcx>,
|
2014-09-29 22:11:30 +03:00
|
|
|
error_reporting_span: Span) -> DIArray {
|
2014-03-05 16:36:01 +02:00
|
|
|
if cx.sess().opts.debuginfo == LimitedDebugInfo {
|
2014-11-17 21:39:01 +13:00
|
|
|
return create_DIArray(DIB(cx), &[]);
|
2013-08-13 12:52:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Return type -- llvm::DIBuilder wants this at index 0
|
2015-01-18 22:49:19 +09:00
|
|
|
assert_type_for_node_id(cx, fn_ast_id, error_reporting_span);
|
2015-07-13 21:48:07 +02:00
|
|
|
let fn_type = cx.tcx().node_id_to_type(fn_ast_id);
|
|
|
|
|
|
|
|
let sig = match fn_type.sty {
|
|
|
|
ty::TyBareFn(_, ref barefnty) => {
|
|
|
|
cx.tcx().erase_late_bound_regions(&barefnty.sig)
|
|
|
|
}
|
|
|
|
ty::TyClosure(def_id, substs) => {
|
|
|
|
cx.tcx().erase_late_bound_regions(&cx.tcx().closure_type(def_id, substs).sig)
|
|
|
|
}
|
|
|
|
|
|
|
|
_ => cx.sess().bug("get_function_metdata: Expected a function type!")
|
|
|
|
};
|
|
|
|
let sig = monomorphize::apply_param_substs(cx.tcx(), param_substs, &sig);
|
|
|
|
|
|
|
|
let mut signature = Vec::with_capacity(sig.inputs.len() + 1);
|
|
|
|
|
|
|
|
// Return type -- llvm::DIBuilder wants this at index 0
|
|
|
|
signature.push(match sig.output {
|
|
|
|
ty::FnConverging(ret_ty) => match ret_ty.sty {
|
|
|
|
ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(),
|
|
|
|
_ => type_metadata(cx, ret_ty, codemap::DUMMY_SP)
|
|
|
|
},
|
|
|
|
ty::FnDiverging => diverging_type_metadata(cx)
|
|
|
|
});
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2013-09-06 16:00:08 +02:00
|
|
|
// Arguments types
|
2015-07-13 21:48:07 +02:00
|
|
|
for &argument_type in &sig.inputs {
|
|
|
|
signature.push(type_metadata(cx, argument_type, codemap::DUMMY_SP));
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
|
2015-02-18 14:48:57 -05:00
|
|
|
return create_DIArray(DIB(cx), &signature[..]);
|
2013-08-13 12:52:39 +02:00
|
|
|
}
|
2013-08-08 18:33:06 +02:00
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|
|
|
generics: &ast::Generics,
|
2014-11-06 09:24:44 +02:00
|
|
|
param_substs: &Substs<'tcx>,
|
2014-09-29 22:11:30 +03:00
|
|
|
file_metadata: DIFile,
|
|
|
|
name_to_append_suffix_to: &mut String)
|
2014-12-17 14:16:28 -05:00
|
|
|
-> DIArray
|
|
|
|
{
|
2014-11-06 09:24:44 +02:00
|
|
|
let self_type = param_substs.self_ty();
|
2014-12-17 14:16:28 -05:00
|
|
|
let self_type = monomorphize::normalize_associated_type(cx.tcx(), &self_type);
|
2013-08-08 18:33:06 +02:00
|
|
|
|
2013-08-15 18:21:16 +02:00
|
|
|
// Only true for static default methods:
|
|
|
|
let has_self_type = self_type.is_some();
|
2013-08-13 12:52:39 +02:00
|
|
|
|
2013-08-15 18:21:16 +02:00
|
|
|
if !generics.is_type_parameterized() && !has_self_type {
|
2014-11-17 21:39:01 +13:00
|
|
|
return create_DIArray(DIB(cx), &[]);
|
2013-08-15 18:21:16 +02:00
|
|
|
}
|
2013-08-08 18:33:06 +02:00
|
|
|
|
2014-10-14 23:05:01 -07:00
|
|
|
name_to_append_suffix_to.push('<');
|
2013-08-08 18:33:06 +02:00
|
|
|
|
2013-08-15 18:21:16 +02:00
|
|
|
// The list to be filled with template parameters:
|
2014-03-08 21:36:22 +01:00
|
|
|
let mut template_params: Vec<DIDescriptor> =
|
|
|
|
Vec::with_capacity(generics.ty_params.len() + 1);
|
2013-08-15 12:25:35 +02:00
|
|
|
|
2013-08-15 18:21:16 +02:00
|
|
|
// Handle self type
|
|
|
|
if has_self_type {
|
|
|
|
let actual_self_type = self_type.unwrap();
|
|
|
|
// Add self type name to <...> clause of function name
|
debuginfo: Make names of types in debuginfo reliable and omit source locations from debug info type descriptions.
So far, type names generated for debuginfo where a bit sketchy. It was not clearly defined when a name should be fully qualified and when not, if region parameters should be shown or not, and other things like that.
This commit makes the debuginfo module responsible for creating type names instead of using ppaux::ty_to_str() and brings type names, as they show up in the DWARF information, in line with GCC and Clang:
* The name of the type being described is unqualified. It's path is defined by its position in the namespace hierarchy.
* Type arguments are always fully qualified, no matter if they would actually be in scope at the type definition location.
Care is also taken to reliably make type names consistent across crate boundaries. That is, the code now tries make the type name the same, regardless if the type is in the local crate or reconstructed from metadata. Otherwise LLVM will complain about violating the one-definition-rule when using link-time-optimization.
This commit also removes all source location information from type descriptions because these cannot be reconstructed for types instantiated from metadata. Again, with LTO enabled, this can lead to two versions of the debuginfo type description, one with and one without source location information, which then triggers the LLVM ODR assertion.
Fortunately, source location information about types is rarely used, so this has little impact. Once source location information is preserved in metadata (#1972) it can also be reenabled for type descriptions.
2014-06-26 13:46:54 +02:00
|
|
|
let actual_self_type_name = compute_debuginfo_type_name(
|
|
|
|
cx,
|
|
|
|
actual_self_type,
|
|
|
|
true);
|
|
|
|
|
2015-02-18 14:48:57 -05:00
|
|
|
name_to_append_suffix_to.push_str(&actual_self_type_name[..]);
|
2013-09-15 12:26:47 +02:00
|
|
|
|
2013-08-15 18:21:16 +02:00
|
|
|
if generics.is_type_parameterized() {
|
|
|
|
name_to_append_suffix_to.push_str(",");
|
|
|
|
}
|
|
|
|
|
2014-03-05 09:51:47 +01:00
|
|
|
// Only create type information if full debuginfo is enabled
|
2014-03-05 16:36:01 +02:00
|
|
|
if cx.sess().opts.debuginfo == FullDebugInfo {
|
2013-09-15 12:26:47 +02:00
|
|
|
let actual_self_type_metadata = type_metadata(cx,
|
|
|
|
actual_self_type,
|
2014-01-01 15:53:22 +09:00
|
|
|
codemap::DUMMY_SP);
|
2013-09-15 12:26:47 +02:00
|
|
|
|
2015-03-23 19:41:35 -05:00
|
|
|
let name = token::get_name(special_idents::type_self.name);
|
2013-09-15 12:26:47 +02:00
|
|
|
|
2015-03-23 19:41:35 -05:00
|
|
|
let name = CString::new(name.as_bytes()).unwrap();
|
2014-11-25 13:28:35 -08:00
|
|
|
let param_metadata = unsafe {
|
|
|
|
llvm::LLVMDIBuilderCreateTemplateTypeParameter(
|
|
|
|
DIB(cx),
|
rustc: Update LLVM
This commit updates the LLVM submodule in use to the current HEAD of the LLVM
repository. This is primarily being done to start picking up unwinding support
for MSVC, which is currently unimplemented in the revision of LLVM we are using.
Along the way a few changes had to be made:
* As usual, lots of C++ debuginfo bindings in LLVM changed, so there were some
significant changes to our RustWrapper.cpp
* As usual, some pass management changed in LLVM, so clang was re-scrutinized to
ensure that we're doing the same thing as clang.
* Some optimization options are now passed directly into the
`PassManagerBuilder` instead of through CLI switches to LLVM.
* The `NoFramePointerElim` option was removed from LLVM, favoring instead the
`no-frame-pointer-elim` function attribute instead.
Additionally, LLVM has picked up some new optimizations which required fixing an
existing soundness hole in the IR we generate. It appears that the current LLVM
we use does not expose this hole. When an enum is moved, the previous slot in
memory is overwritten with a bit pattern corresponding to "dropped". When the
drop glue for this slot is run, however, the switch on the discriminant can
often start executing the `unreachable` block of the switch due to the
discriminant now being outside the normal range. This was patched over locally
for now by having the `unreachable` block just change to a `ret void`.
2015-05-14 12:10:43 -07:00
|
|
|
ptr::null_mut(),
|
2014-11-25 13:28:35 -08:00
|
|
|
name.as_ptr(),
|
|
|
|
actual_self_type_metadata,
|
rustc: Update LLVM
This commit updates the LLVM submodule in use to the current HEAD of the LLVM
repository. This is primarily being done to start picking up unwinding support
for MSVC, which is currently unimplemented in the revision of LLVM we are using.
Along the way a few changes had to be made:
* As usual, lots of C++ debuginfo bindings in LLVM changed, so there were some
significant changes to our RustWrapper.cpp
* As usual, some pass management changed in LLVM, so clang was re-scrutinized to
ensure that we're doing the same thing as clang.
* Some optimization options are now passed directly into the
`PassManagerBuilder` instead of through CLI switches to LLVM.
* The `NoFramePointerElim` option was removed from LLVM, favoring instead the
`no-frame-pointer-elim` function attribute instead.
Additionally, LLVM has picked up some new optimizations which required fixing an
existing soundness hole in the IR we generate. It appears that the current LLVM
we use does not expose this hole. When an enum is moved, the previous slot in
memory is overwritten with a bit pattern corresponding to "dropped". When the
drop glue for this slot is run, however, the switch on the discriminant can
often start executing the `unreachable` block of the switch due to the
discriminant now being outside the normal range. This was patched over locally
for now by having the `unreachable` block just change to a `ret void`.
2015-05-14 12:10:43 -07:00
|
|
|
file_metadata,
|
2014-11-25 13:28:35 -08:00
|
|
|
0,
|
|
|
|
0)
|
|
|
|
};
|
2013-08-13 12:52:39 +02:00
|
|
|
|
2013-09-15 12:26:47 +02:00
|
|
|
template_params.push(param_metadata);
|
|
|
|
}
|
2013-08-15 18:21:16 +02:00
|
|
|
}
|
2013-08-15 12:25:35 +02:00
|
|
|
|
2013-08-15 18:21:16 +02:00
|
|
|
// Handle other generic parameters
|
2014-11-06 09:24:44 +02:00
|
|
|
let actual_types = param_substs.types.get_slice(subst::FnSpace);
|
2014-10-06 13:36:53 +13:00
|
|
|
for (index, &ast::TyParam{ ident, .. }) in generics.ty_params.iter().enumerate() {
|
2014-07-04 16:39:28 +02:00
|
|
|
let actual_type = actual_types[index];
|
2013-08-15 18:21:16 +02:00
|
|
|
// Add actual type name to <...> clause of function name
|
debuginfo: Make names of types in debuginfo reliable and omit source locations from debug info type descriptions.
So far, type names generated for debuginfo where a bit sketchy. It was not clearly defined when a name should be fully qualified and when not, if region parameters should be shown or not, and other things like that.
This commit makes the debuginfo module responsible for creating type names instead of using ppaux::ty_to_str() and brings type names, as they show up in the DWARF information, in line with GCC and Clang:
* The name of the type being described is unqualified. It's path is defined by its position in the namespace hierarchy.
* Type arguments are always fully qualified, no matter if they would actually be in scope at the type definition location.
Care is also taken to reliably make type names consistent across crate boundaries. That is, the code now tries make the type name the same, regardless if the type is in the local crate or reconstructed from metadata. Otherwise LLVM will complain about violating the one-definition-rule when using link-time-optimization.
This commit also removes all source location information from type descriptions because these cannot be reconstructed for types instantiated from metadata. Again, with LTO enabled, this can lead to two versions of the debuginfo type description, one with and one without source location information, which then triggers the LLVM ODR assertion.
Fortunately, source location information about types is rarely used, so this has little impact. Once source location information is preserved in metadata (#1972) it can also be reenabled for type descriptions.
2014-06-26 13:46:54 +02:00
|
|
|
let actual_type_name = compute_debuginfo_type_name(cx,
|
|
|
|
actual_type,
|
|
|
|
true);
|
2015-02-18 14:48:57 -05:00
|
|
|
name_to_append_suffix_to.push_str(&actual_type_name[..]);
|
2013-08-13 12:52:39 +02:00
|
|
|
|
2013-08-15 18:21:16 +02:00
|
|
|
if index != generics.ty_params.len() - 1 {
|
|
|
|
name_to_append_suffix_to.push_str(",");
|
|
|
|
}
|
2013-08-15 12:25:35 +02:00
|
|
|
|
2014-03-05 09:51:47 +01:00
|
|
|
// Again, only create type information if full debuginfo is enabled
|
2014-03-05 16:36:01 +02:00
|
|
|
if cx.sess().opts.debuginfo == FullDebugInfo {
|
2014-01-01 15:53:22 +09:00
|
|
|
let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP);
|
2014-11-25 13:28:35 -08:00
|
|
|
let ident = token::get_ident(ident);
|
2015-02-17 22:47:40 -08:00
|
|
|
let name = CString::new(ident.as_bytes()).unwrap();
|
2014-11-25 13:28:35 -08:00
|
|
|
let param_metadata = unsafe {
|
|
|
|
llvm::LLVMDIBuilderCreateTemplateTypeParameter(
|
|
|
|
DIB(cx),
|
rustc: Update LLVM
This commit updates the LLVM submodule in use to the current HEAD of the LLVM
repository. This is primarily being done to start picking up unwinding support
for MSVC, which is currently unimplemented in the revision of LLVM we are using.
Along the way a few changes had to be made:
* As usual, lots of C++ debuginfo bindings in LLVM changed, so there were some
significant changes to our RustWrapper.cpp
* As usual, some pass management changed in LLVM, so clang was re-scrutinized to
ensure that we're doing the same thing as clang.
* Some optimization options are now passed directly into the
`PassManagerBuilder` instead of through CLI switches to LLVM.
* The `NoFramePointerElim` option was removed from LLVM, favoring instead the
`no-frame-pointer-elim` function attribute instead.
Additionally, LLVM has picked up some new optimizations which required fixing an
existing soundness hole in the IR we generate. It appears that the current LLVM
we use does not expose this hole. When an enum is moved, the previous slot in
memory is overwritten with a bit pattern corresponding to "dropped". When the
drop glue for this slot is run, however, the switch on the discriminant can
often start executing the `unreachable` block of the switch due to the
discriminant now being outside the normal range. This was patched over locally
for now by having the `unreachable` block just change to a `ret void`.
2015-05-14 12:10:43 -07:00
|
|
|
ptr::null_mut(),
|
2014-11-25 13:28:35 -08:00
|
|
|
name.as_ptr(),
|
|
|
|
actual_type_metadata,
|
rustc: Update LLVM
This commit updates the LLVM submodule in use to the current HEAD of the LLVM
repository. This is primarily being done to start picking up unwinding support
for MSVC, which is currently unimplemented in the revision of LLVM we are using.
Along the way a few changes had to be made:
* As usual, lots of C++ debuginfo bindings in LLVM changed, so there were some
significant changes to our RustWrapper.cpp
* As usual, some pass management changed in LLVM, so clang was re-scrutinized to
ensure that we're doing the same thing as clang.
* Some optimization options are now passed directly into the
`PassManagerBuilder` instead of through CLI switches to LLVM.
* The `NoFramePointerElim` option was removed from LLVM, favoring instead the
`no-frame-pointer-elim` function attribute instead.
Additionally, LLVM has picked up some new optimizations which required fixing an
existing soundness hole in the IR we generate. It appears that the current LLVM
we use does not expose this hole. When an enum is moved, the previous slot in
memory is overwritten with a bit pattern corresponding to "dropped". When the
drop glue for this slot is run, however, the switch on the discriminant can
often start executing the `unreachable` block of the switch due to the
discriminant now being outside the normal range. This was patched over locally
for now by having the `unreachable` block just change to a `ret void`.
2015-05-14 12:10:43 -07:00
|
|
|
file_metadata,
|
2014-11-25 13:28:35 -08:00
|
|
|
0,
|
|
|
|
0)
|
|
|
|
};
|
2013-09-15 12:26:47 +02:00
|
|
|
template_params.push(param_metadata);
|
|
|
|
}
|
2013-08-08 18:33:06 +02:00
|
|
|
}
|
2013-08-15 18:21:16 +02:00
|
|
|
|
2014-10-14 23:05:01 -07:00
|
|
|
name_to_append_suffix_to.push('>');
|
2013-08-15 18:21:16 +02:00
|
|
|
|
2015-02-18 14:48:57 -05:00
|
|
|
return create_DIArray(DIB(cx), &template_params[..]);
|
2013-08-08 18:33:06 +02:00
|
|
|
}
|
2013-08-19 18:23:43 +02:00
|
|
|
}
|
2013-06-18 13:06:41 +02:00
|
|
|
|
2015-04-29 18:14:37 +12:00
|
|
|
fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|
|
|
variable_name: ast::Name,
|
|
|
|
variable_type: Ty<'tcx>,
|
|
|
|
scope_metadata: DIScope,
|
|
|
|
variable_access: VariableAccess,
|
|
|
|
variable_kind: VariableKind,
|
|
|
|
span: Span) {
|
|
|
|
let cx: &CrateContext = bcx.ccx();
|
2014-05-15 14:13:33 +02:00
|
|
|
|
2015-04-29 18:14:37 +12:00
|
|
|
let filename = span_start(cx, span).file.name.clone();
|
|
|
|
let file_metadata = file_metadata(cx, &filename[..]);
|
2014-05-30 17:09:16 +02:00
|
|
|
|
2015-04-29 18:14:37 +12:00
|
|
|
let name = token::get_name(variable_name);
|
|
|
|
let loc = span_start(cx, span);
|
|
|
|
let type_metadata = type_metadata(cx, variable_type, span);
|
2014-05-15 14:13:33 +02:00
|
|
|
|
2015-04-29 18:14:37 +12:00
|
|
|
let (argument_index, dwarf_tag) = match variable_kind {
|
|
|
|
ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),
|
|
|
|
LocalVariable |
|
|
|
|
CapturedVariable => (0, DW_TAG_auto_variable)
|
|
|
|
};
|
2014-05-15 14:13:33 +02:00
|
|
|
|
2015-04-29 18:14:37 +12:00
|
|
|
let name = CString::new(name.as_bytes()).unwrap();
|
|
|
|
match (variable_access, &[][..]) {
|
|
|
|
(DirectVariable { alloca }, address_operations) |
|
|
|
|
(IndirectVariable {alloca, address_operations}, _) => {
|
|
|
|
let metadata = unsafe {
|
|
|
|
llvm::LLVMDIBuilderCreateVariable(
|
|
|
|
DIB(cx),
|
|
|
|
dwarf_tag,
|
|
|
|
scope_metadata,
|
|
|
|
name.as_ptr(),
|
|
|
|
file_metadata,
|
|
|
|
loc.line as c_uint,
|
|
|
|
type_metadata,
|
|
|
|
cx.sess().opts.optimize != config::No,
|
|
|
|
0,
|
|
|
|
address_operations.as_ptr(),
|
|
|
|
address_operations.len() as c_uint,
|
|
|
|
argument_index)
|
|
|
|
};
|
|
|
|
source_loc::set_debug_location(cx, InternalDebugLocation::new(scope_metadata,
|
|
|
|
loc.line,
|
|
|
|
loc.col.to_usize()));
|
|
|
|
unsafe {
|
rustc: Update LLVM
This commit updates the LLVM submodule in use to the current HEAD of the LLVM
repository. This is primarily being done to start picking up unwinding support
for MSVC, which is currently unimplemented in the revision of LLVM we are using.
Along the way a few changes had to be made:
* As usual, lots of C++ debuginfo bindings in LLVM changed, so there were some
significant changes to our RustWrapper.cpp
* As usual, some pass management changed in LLVM, so clang was re-scrutinized to
ensure that we're doing the same thing as clang.
* Some optimization options are now passed directly into the
`PassManagerBuilder` instead of through CLI switches to LLVM.
* The `NoFramePointerElim` option was removed from LLVM, favoring instead the
`no-frame-pointer-elim` function attribute instead.
Additionally, LLVM has picked up some new optimizations which required fixing an
existing soundness hole in the IR we generate. It appears that the current LLVM
we use does not expose this hole. When an enum is moved, the previous slot in
memory is overwritten with a bit pattern corresponding to "dropped". When the
drop glue for this slot is run, however, the switch on the discriminant can
often start executing the `unreachable` block of the switch due to the
discriminant now being outside the normal range. This was patched over locally
for now by having the `unreachable` block just change to a `ret void`.
2015-05-14 12:10:43 -07:00
|
|
|
let debug_loc = llvm::LLVMGetCurrentDebugLocation(cx.raw_builder());
|
2015-04-29 18:14:37 +12:00
|
|
|
let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
|
|
|
|
DIB(cx),
|
|
|
|
alloca,
|
|
|
|
metadata,
|
|
|
|
address_operations.as_ptr(),
|
|
|
|
address_operations.len() as c_uint,
|
rustc: Update LLVM
This commit updates the LLVM submodule in use to the current HEAD of the LLVM
repository. This is primarily being done to start picking up unwinding support
for MSVC, which is currently unimplemented in the revision of LLVM we are using.
Along the way a few changes had to be made:
* As usual, lots of C++ debuginfo bindings in LLVM changed, so there were some
significant changes to our RustWrapper.cpp
* As usual, some pass management changed in LLVM, so clang was re-scrutinized to
ensure that we're doing the same thing as clang.
* Some optimization options are now passed directly into the
`PassManagerBuilder` instead of through CLI switches to LLVM.
* The `NoFramePointerElim` option was removed from LLVM, favoring instead the
`no-frame-pointer-elim` function attribute instead.
Additionally, LLVM has picked up some new optimizations which required fixing an
existing soundness hole in the IR we generate. It appears that the current LLVM
we use does not expose this hole. When an enum is moved, the previous slot in
memory is overwritten with a bit pattern corresponding to "dropped". When the
drop glue for this slot is run, however, the switch on the discriminant can
often start executing the `unreachable` block of the switch due to the
discriminant now being outside the normal range. This was patched over locally
for now by having the `unreachable` block just change to a `ret void`.
2015-05-14 12:10:43 -07:00
|
|
|
debug_loc,
|
2015-04-29 18:14:37 +12:00
|
|
|
bcx.llbb);
|
|
|
|
|
|
|
|
llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr);
|
2014-05-15 14:13:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-04-29 18:14:37 +12:00
|
|
|
|
|
|
|
match variable_kind {
|
|
|
|
ArgumentVariable(_) | CapturedVariable => {
|
|
|
|
assert!(!bcx.fcx
|
|
|
|
.debug_context
|
|
|
|
.get_ref(cx, span)
|
|
|
|
.source_locations_enabled
|
|
|
|
.get());
|
|
|
|
source_loc::set_debug_location(cx, InternalDebugLocation::UnknownLocation);
|
|
|
|
}
|
|
|
|
_ => { /* nothing to do */ }
|
|
|
|
}
|
2014-05-15 14:13:33 +02:00
|
|
|
}
|
|
|
|
|
2015-04-29 18:14:37 +12:00
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
|
|
|
pub enum DebugLoc {
|
|
|
|
At(ast::NodeId, Span),
|
|
|
|
None
|
2013-08-19 18:23:43 +02:00
|
|
|
}
|
|
|
|
|
2015-04-29 18:14:37 +12:00
|
|
|
impl DebugLoc {
|
|
|
|
pub fn apply(&self, fcx: &FunctionContext) {
|
|
|
|
match *self {
|
|
|
|
DebugLoc::At(node_id, span) => {
|
|
|
|
source_loc::set_source_location(fcx, node_id, span);
|
|
|
|
}
|
|
|
|
DebugLoc::None => {
|
|
|
|
source_loc::clear_source_location(fcx);
|
|
|
|
}
|
2013-08-19 18:23:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-29 18:14:37 +12:00
|
|
|
pub trait ToDebugLoc {
|
|
|
|
fn debug_loc(&self) -> DebugLoc;
|
|
|
|
}
|
2013-06-14 11:59:49 -07:00
|
|
|
|
2015-04-29 18:14:37 +12:00
|
|
|
impl ToDebugLoc for ast::Expr {
|
|
|
|
fn debug_loc(&self) -> DebugLoc {
|
|
|
|
DebugLoc::At(self.id, self.span)
|
|
|
|
}
|
|
|
|
}
|
2013-08-19 18:23:43 +02:00
|
|
|
|
2015-04-29 18:14:37 +12:00
|
|
|
impl ToDebugLoc for NodeIdAndSpan {
|
|
|
|
fn debug_loc(&self) -> DebugLoc {
|
|
|
|
DebugLoc::At(self.id, self.span)
|
|
|
|
}
|
|
|
|
}
|
2015-01-30 19:25:07 +01:00
|
|
|
|
2015-04-29 18:14:37 +12:00
|
|
|
impl ToDebugLoc for Option<NodeIdAndSpan> {
|
|
|
|
fn debug_loc(&self) -> DebugLoc {
|
|
|
|
match *self {
|
|
|
|
Some(NodeIdAndSpan { id, span }) => DebugLoc::At(id, span),
|
|
|
|
None => DebugLoc::None
|
2013-08-19 18:23:43 +02:00
|
|
|
}
|
2013-01-10 21:23:07 -08:00
|
|
|
}
|
2011-11-16 19:30:45 -05:00
|
|
|
}
|