2015-04-24 11:38:53 +12:00
|
|
|
//! Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
//! file at the top-level directory of this distribution and at
|
|
|
|
//! http://!rust-lang.org/COPYRIGHT.
|
|
|
|
//!
|
|
|
|
//! Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
//! http://!www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
//! <LICENSE-MIT or http://!opensource.org/licenses/MIT>, at your
|
|
|
|
//! option. This file may not be copied, modified, or distributed
|
|
|
|
//! except according to those terms.
|
2012-12-03 16:48:01 -08:00
|
|
|
|
2014-11-25 21:17:11 -05:00
|
|
|
//! # Debug Info Module
|
|
|
|
//!
|
|
|
|
//! This module serves the purpose of generating debug symbols. We use LLVM's
|
2015-04-24 11:38:53 +12:00
|
|
|
//! [source level debugging](http://!llvm.org/docs/SourceLevelDebugging.html)
|
|
|
|
//! features for generating the debug information. The general principle is
|
|
|
|
//! this:
|
2014-11-25 21:17:11 -05:00
|
|
|
//!
|
|
|
|
//! Given the right metadata in the LLVM IR, the LLVM code generator is able to
|
|
|
|
//! create DWARF debug symbols for the given code. The
|
2015-04-24 11:38:53 +12:00
|
|
|
//! [metadata](http://!llvm.org/docs/LangRef.html#metadata-type) is structured
|
|
|
|
//! much like DWARF *debugging information entries* (DIE), representing type
|
|
|
|
//! information such as datatype layout, function signatures, block layout,
|
|
|
|
//! variable location and scope information, etc. It is the purpose of this
|
|
|
|
//! module to generate correct metadata and insert it into the LLVM IR.
|
2014-11-25 21:17:11 -05:00
|
|
|
//!
|
|
|
|
//! As the exact format of metadata trees may change between different LLVM
|
|
|
|
//! versions, we now use LLVM
|
2015-04-24 11:38:53 +12:00
|
|
|
//! [DIBuilder](http://!llvm.org/docs/doxygen/html/classllvm_1_1DIBuilder.html)
|
|
|
|
//! to create metadata where possible. This will hopefully ease the adaption of
|
|
|
|
//! this module to future LLVM versions.
|
2014-11-25 21:17:11 -05:00
|
|
|
//!
|
2015-04-24 11:38:53 +12:00
|
|
|
//! The public API of the module is a set of functions that will insert the
|
|
|
|
//! correct metadata into the LLVM IR when called with the right parameters.
|
|
|
|
//! The module is thus driven from an outside client with functions like
|
2014-11-25 21:17:11 -05:00
|
|
|
//! `debuginfo::create_local_var_metadata(bcx: block, local: &ast::local)`.
|
|
|
|
//!
|
2015-04-24 11:38:53 +12:00
|
|
|
//! Internally the module will try to reuse already created metadata by
|
|
|
|
//! utilizing a cache. The way to get a shared metadata node when needed is
|
|
|
|
//! thus to just call the corresponding function in this module:
|
2014-11-25 21:17:11 -05:00
|
|
|
//!
|
|
|
|
//! let file_metadata = file_metadata(crate_context, path);
|
|
|
|
//!
|
2015-04-24 11:38:53 +12:00
|
|
|
//! The function will take care of probing the cache for an existing node for
|
|
|
|
//! that exact file path.
|
2014-11-25 21:17:11 -05:00
|
|
|
//!
|
|
|
|
//! All private state used by the module is stored within either the
|
2015-04-24 11:38:53 +12:00
|
|
|
//! CrateDebugContext struct (owned by the CrateContext) or the
|
|
|
|
//! FunctionDebugContext (owned by the FunctionContext).
|
2014-11-25 21:17:11 -05:00
|
|
|
//!
|
|
|
|
//! This file consists of three conceptual sections:
|
|
|
|
//! 1. The public interface of the module
|
|
|
|
//! 2. Module-internal metadata creation functions
|
|
|
|
//! 3. Minor utility functions
|
|
|
|
//!
|
|
|
|
//!
|
|
|
|
//! ## Recursive Types
|
|
|
|
//!
|
2015-04-24 11:38:53 +12:00
|
|
|
//! Some kinds of types, such as structs and enums can be recursive. That means
|
|
|
|
//! that the type definition of some type X refers to some other type which in
|
|
|
|
//! turn (transitively) refers to X. This introduces cycles into the type
|
|
|
|
//! referral graph. A naive algorithm doing an on-demand, depth-first traversal
|
|
|
|
//! of this graph when describing types, can get trapped in an endless loop
|
|
|
|
//! when it reaches such a cycle.
|
2014-11-25 21:17:11 -05:00
|
|
|
//!
|
|
|
|
//! For example, the following simple type for a singly-linked list...
|
|
|
|
//!
|
|
|
|
//! ```
|
|
|
|
//! struct List {
|
|
|
|
//! value: int,
|
|
|
|
//! tail: Option<Box<List>>,
|
|
|
|
//! }
|
|
|
|
//! ```
|
|
|
|
//!
|
|
|
|
//! will generate the following callstack with a naive DFS algorithm:
|
|
|
|
//!
|
|
|
|
//! ```
|
|
|
|
//! describe(t = List)
|
|
|
|
//! describe(t = int)
|
|
|
|
//! describe(t = Option<Box<List>>)
|
|
|
|
//! describe(t = Box<List>)
|
|
|
|
//! describe(t = List) // at the beginning again...
|
|
|
|
//! ...
|
|
|
|
//! ```
|
|
|
|
//!
|
2015-04-24 11:38:53 +12:00
|
|
|
//! To break cycles like these, we use "forward declarations". That is, when
|
|
|
|
//! the algorithm encounters a possibly recursive type (any struct or enum), it
|
2014-11-25 21:17:11 -05:00
|
|
|
//! immediately creates a type description node and inserts it into the cache
|
2015-04-24 11:38:53 +12:00
|
|
|
//! *before* describing the members of the type. This type description is just
|
|
|
|
//! a stub (as type members are not described and added to it yet) but it
|
|
|
|
//! allows the algorithm to already refer to the type. After the stub is
|
|
|
|
//! inserted into the cache, the algorithm continues as before. If it now
|
|
|
|
//! encounters a recursive reference, it will hit the cache and does not try to
|
|
|
|
//! describe the type anew.
|
2014-11-25 21:17:11 -05:00
|
|
|
//!
|
2015-04-24 11:38:53 +12:00
|
|
|
//! This behaviour is encapsulated in the 'RecursiveTypeDescription' enum,
|
|
|
|
//! which represents a kind of continuation, storing all state needed to
|
|
|
|
//! continue traversal at the type members after the type has been registered
|
|
|
|
//! with the cache. (This implementation approach might be a tad over-
|
|
|
|
//! engineered and may change in the future)
|
2014-11-25 21:17:11 -05:00
|
|
|
//!
|
|
|
|
//!
|
|
|
|
//! ## Source Locations and Line Information
|
|
|
|
//!
|
2015-04-24 11:38:53 +12:00
|
|
|
//! In addition to data type descriptions the debugging information must also
|
|
|
|
//! allow to map machine code locations back to source code locations in order
|
|
|
|
//! to be useful. This functionality is also handled in this module. The
|
|
|
|
//! following functions allow to control source mappings:
|
2014-11-25 21:17:11 -05:00
|
|
|
//!
|
|
|
|
//! + set_source_location()
|
|
|
|
//! + clear_source_location()
|
|
|
|
//! + start_emitting_source_locations()
|
|
|
|
//!
|
|
|
|
//! `set_source_location()` allows to set the current source location. All IR
|
2015-04-24 11:38:53 +12:00
|
|
|
//! instructions created after a call to this function will be linked to the
|
|
|
|
//! given source location, until another location is specified with
|
2014-11-25 21:17:11 -05:00
|
|
|
//! `set_source_location()` or the source location is cleared with
|
2015-04-24 11:38:53 +12:00
|
|
|
//! `clear_source_location()`. In the later case, subsequent IR instruction
|
|
|
|
//! will not be linked to any source location. As you can see, this is a
|
|
|
|
//! stateful API (mimicking the one in LLVM), so be careful with source
|
|
|
|
//! locations set by previous calls. It's probably best to not rely on any
|
|
|
|
//! specific state being present at a given point in code.
|
2014-11-25 21:17:11 -05:00
|
|
|
//!
|
2015-04-24 11:38:53 +12:00
|
|
|
//! One topic that deserves some extra attention is *function prologues*. At
|
|
|
|
//! the beginning of a function's machine code there are typically a few
|
|
|
|
//! instructions for loading argument values into allocas and checking if
|
|
|
|
//! there's enough stack space for the function to execute. This *prologue* is
|
|
|
|
//! not visible in the source code and LLVM puts a special PROLOGUE END marker
|
|
|
|
//! into the line table at the first non-prologue instruction of the function.
|
|
|
|
//! In order to find out where the prologue ends, LLVM looks for the first
|
|
|
|
//! instruction in the function body that is linked to a source location. So,
|
|
|
|
//! when generating prologue instructions we have to make sure that we don't
|
|
|
|
//! emit source location information until the 'real' function body begins. For
|
|
|
|
//! this reason, source location emission is disabled by default for any new
|
|
|
|
//! function being translated and is only activated after a call to the third
|
|
|
|
//! function from the list above, `start_emitting_source_locations()`. This
|
|
|
|
//! function should be called right before regularly starting to translate the
|
2014-11-25 21:17:11 -05:00
|
|
|
//! top-level block of the given function.
|
|
|
|
//!
|
2015-04-24 11:38:53 +12:00
|
|
|
//! There is one exception to the above rule: `llvm.dbg.declare` instruction
|
|
|
|
//! must be linked to the source location of the variable being declared. For
|
|
|
|
//! function parameters these `llvm.dbg.declare` instructions typically occur
|
|
|
|
//! in the middle of the prologue, however, they are ignored by LLVM's prologue
|
|
|
|
//! detection. The `create_argument_metadata()` and related functions take care
|
|
|
|
//! of linking the `llvm.dbg.declare` instructions to the correct source
|
|
|
|
//! locations even while source location emission is still disabled, so there
|
|
|
|
//! is no need to do anything special with source location handling here.
|
2014-11-25 21:17:11 -05:00
|
|
|
//!
|
|
|
|
//! ## Unique Type Identification
|
|
|
|
//!
|
2015-04-24 11:38:53 +12:00
|
|
|
//! In order for link-time optimization to work properly, LLVM needs a unique
|
|
|
|
//! type identifier that tells it across compilation units which types are the
|
|
|
|
//! same as others. This type identifier is created by
|
|
|
|
//! TypeMap::get_unique_type_id_of_type() using the following algorithm:
|
2014-11-25 21:17:11 -05:00
|
|
|
//!
|
|
|
|
//! (1) Primitive types have their name as ID
|
|
|
|
//! (2) Structs, enums and traits have a multipart identifier
|
|
|
|
//!
|
2015-04-24 11:38:53 +12:00
|
|
|
//! (1) The first part is the SVH (strict version hash) of the crate they
|
|
|
|
//! wereoriginally defined in
|
2014-11-25 21:17:11 -05:00
|
|
|
//!
|
2015-04-24 11:38:53 +12:00
|
|
|
//! (2) The second part is the ast::NodeId of the definition in their
|
|
|
|
//! originalcrate
|
2014-11-25 21:17:11 -05:00
|
|
|
//!
|
2015-04-24 11:38:53 +12:00
|
|
|
//! (3) The final part is a concatenation of the type IDs of their concrete
|
|
|
|
//! typearguments if they are generic types.
|
2014-11-25 21:17:11 -05:00
|
|
|
//!
|
2015-04-24 11:38:53 +12:00
|
|
|
//! (3) Tuple-, pointer and function types are structurally identified, which
|
|
|
|
//! means that they are equivalent if their component types are equivalent
|
|
|
|
//! (i.e. (int, int) is the same regardless in which crate it is used).
|
2014-11-25 21:17:11 -05:00
|
|
|
//!
|
2015-04-24 11:38:53 +12:00
|
|
|
//! This algorithm also provides a stable ID for types that are defined in one
|
|
|
|
//! crate but instantiated from metadata within another crate. We just have to
|
|
|
|
//! take care to always map crate and node IDs back to the original crate
|
|
|
|
//! context.
|
2014-11-25 21:17:11 -05:00
|
|
|
//!
|
2015-04-24 11:38:53 +12:00
|
|
|
//! As a side-effect these unique type IDs also help to solve a problem arising
|
|
|
|
//! from lifetime parameters. Since lifetime parameters are completely omitted
|
|
|
|
//! in debuginfo, more than one `Ty` instance may map to the same debuginfo
|
|
|
|
//! type metadata, that is, some struct `Struct<'a>` may have N instantiations
|
|
|
|
//! with different concrete substitutions for `'a`, and thus there will be N
|
|
|
|
//! `Ty` instances for the type `Struct<'a>` even though it is not generic
|
|
|
|
//! otherwise. Unfortunately this means that we cannot use `ty::type_id()` as
|
|
|
|
//! cheap identifier for type metadata---we have done this in the past, but it
|
|
|
|
//! led to unnecessary metadata duplication in the best case and LLVM
|
|
|
|
//! assertions in the worst. However, the unique type ID as described above
|
|
|
|
//! *can* be used as identifier. Since it is comparatively expensive to
|
|
|
|
//! construct, though, `ty::type_id()` is still used additionally as an
|
|
|
|
//! optimization for cases where the exact same type has been seen before
|
|
|
|
//! (which is most of the time).
|
2014-11-06 00:05:53 -08:00
|
|
|
use self::VariableAccess::*;
|
|
|
|
use self::VariableKind::*;
|
|
|
|
use self::MemberOffset::*;
|
|
|
|
use self::MemberDescriptionFactory::*;
|
|
|
|
use self::RecursiveTypeDescription::*;
|
|
|
|
use self::EnumDiscriminantInfo::*;
|
2014-12-11 13:53:30 +01:00
|
|
|
use self::InternalDebugLocation::*;
|
2013-06-18 10:17:10 +02:00
|
|
|
|
2014-07-07 17:58:01 -07:00
|
|
|
use llvm;
|
|
|
|
use llvm::{ModuleRef, ContextRef, ValueRef};
|
|
|
|
use llvm::debuginfo::*;
|
2014-03-27 15:47:13 +01:00
|
|
|
use metadata::csearch;
|
2015-01-03 22:42:21 -05:00
|
|
|
use middle::subst::{self, Substs};
|
|
|
|
use trans::{self, adt, machine, type_of};
|
2015-03-04 01:08:06 +02:00
|
|
|
use trans::common::{self, NodeIdAndSpan, CrateContext, FunctionContext, Block, C_bytes,
|
|
|
|
NormalizingClosureTyper};
|
|
|
|
use trans::declare;
|
2014-11-15 20:30:33 -05:00
|
|
|
use trans::_match::{BindingInfo, TrByCopy, TrByMove, TrByRef};
|
2014-12-17 14:16:28 -05:00
|
|
|
use trans::monomorphize;
|
2014-11-15 20:30:33 -05:00
|
|
|
use trans::type_::Type;
|
2015-01-24 22:00:03 +02:00
|
|
|
use middle::ty::{self, Ty, ClosureTyper};
|
2013-07-12 10:16:54 +02:00
|
|
|
use middle::pat_util;
|
2015-01-03 22:42:21 -05:00
|
|
|
use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
|
2014-11-10 00:59:56 +02:00
|
|
|
use util::nodemap::{DefIdMap, NodeMap, FnvHashMap, FnvHashSet};
|
2013-09-11 11:08:44 +02:00
|
|
|
use util::ppaux;
|
2015-02-26 21:00:43 -08:00
|
|
|
use util::common::path2cstr;
|
2012-12-13 13:05:22 -08:00
|
|
|
|
2015-01-08 16:50:45 +01:00
|
|
|
use libc::{c_uint, c_longlong};
|
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;
|
|
|
|
use std::path::Path;
|
2013-06-28 18:32:26 -04:00
|
|
|
use std::ptr;
|
2014-05-16 10:15:33 -07:00
|
|
|
use std::rc::{Rc, Weak};
|
2014-05-30 17:09:16 +02:00
|
|
|
use syntax::util::interner::Interner;
|
2013-09-15 09:50:17 -07:00
|
|
|
use syntax::codemap::{Span, Pos};
|
2014-12-03 14:48:18 -08:00
|
|
|
use syntax::{ast, codemap, ast_util, ast_map, attr};
|
2015-01-03 22:42:21 -05:00
|
|
|
use syntax::parse::token::{self, special_idents};
|
2013-06-26 16:00:42 +02:00
|
|
|
|
2014-12-06 11:39:25 -05:00
|
|
|
const DW_LANG_RUST: c_uint = 0x9000;
|
2011-11-10 00:55:09 -05: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
|
|
|
|
2014-10-27 15:37:07 -07:00
|
|
|
#[allow(non_upper_case_globals)]
|
2014-12-06 11:39:25 -05:00
|
|
|
const DW_ATE_boolean: c_uint = 0x02;
|
2014-10-27 15:37:07 -07:00
|
|
|
#[allow(non_upper_case_globals)]
|
2014-12-06 11:39:25 -05:00
|
|
|
const DW_ATE_float: c_uint = 0x04;
|
2014-10-27 15:37:07 -07:00
|
|
|
#[allow(non_upper_case_globals)]
|
2014-12-06 11:39:25 -05:00
|
|
|
const DW_ATE_signed: c_uint = 0x05;
|
2014-10-27 15:37:07 -07:00
|
|
|
#[allow(non_upper_case_globals)]
|
2014-12-06 11:39:25 -05:00
|
|
|
const DW_ATE_unsigned: c_uint = 0x07;
|
2014-10-27 15:37:07 -07:00
|
|
|
#[allow(non_upper_case_globals)]
|
2014-12-06 11:39:25 -05:00
|
|
|
const DW_ATE_unsigned_char: c_uint = 0x08;
|
2011-11-10 00:55:09 -05:00
|
|
|
|
2014-12-06 11:39:25 -05:00
|
|
|
const UNKNOWN_LINE_NUMBER: c_uint = 0;
|
|
|
|
const UNKNOWN_COLUMN_NUMBER: c_uint = 0;
|
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
|
|
|
|
|
|
|
// ptr::null() doesn't work :(
|
2014-12-06 11:39:25 -05:00
|
|
|
const UNKNOWN_FILE_METADATA: DIFile = (0 as DIFile);
|
|
|
|
const UNKNOWN_SCOPE_METADATA: DIScope = (0 as DIScope);
|
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
|
|
|
|
2014-12-06 11:39:25 -05:00
|
|
|
const FLAGS_NONE: c_uint = 0;
|
2014-07-30 15:56:42 +02:00
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
//=-----------------------------------------------------------------------------
|
2013-06-18 13:06:41 +02:00
|
|
|
// Public Interface of debuginfo module
|
2014-06-18 15:07:26 +12:00
|
|
|
//=-----------------------------------------------------------------------------
|
2013-06-18 13:06:41 +02:00
|
|
|
|
2015-01-28 08:34:18 -05:00
|
|
|
#[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)]
|
2014-05-30 17:09:16 +02:00
|
|
|
struct UniqueTypeId(ast::Name);
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// The TypeMap is where the CrateDebugContext holds the type metadata nodes
|
|
|
|
// created so far. The metadata nodes are indexed by UniqueTypeId, and, for
|
2014-09-13 21:09:25 +03:00
|
|
|
// faster lookup, also by Ty. The TypeMap is responsible for creating
|
2014-06-18 15:07:26 +12:00
|
|
|
// UniqueTypeIds.
|
2014-09-29 22:11:30 +03:00
|
|
|
struct TypeMap<'tcx> {
|
2014-05-30 17:09:16 +02:00
|
|
|
// The UniqueTypeIds created so far
|
|
|
|
unique_id_interner: Interner<Rc<String>>,
|
|
|
|
// A map from UniqueTypeId to debuginfo metadata for that type. This is a 1:1 mapping.
|
2014-11-10 00:59:56 +02:00
|
|
|
unique_id_to_metadata: FnvHashMap<UniqueTypeId, DIType>,
|
|
|
|
// A map from types to debuginfo metadata. This is a N:1 mapping.
|
2014-09-29 22:11:30 +03:00
|
|
|
type_to_metadata: FnvHashMap<Ty<'tcx>, DIType>,
|
2014-11-10 00:59:56 +02:00
|
|
|
// A map from types to UniqueTypeId. This is a N:1 mapping.
|
2014-09-29 22:11:30 +03:00
|
|
|
type_to_unique_id: FnvHashMap<Ty<'tcx>, UniqueTypeId>
|
2014-05-30 17:09:16 +02:00
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
impl<'tcx> TypeMap<'tcx> {
|
2014-05-30 17:09:16 +02:00
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
fn new() -> TypeMap<'tcx> {
|
2014-05-30 17:09:16 +02:00
|
|
|
TypeMap {
|
|
|
|
unique_id_interner: Interner::new(),
|
2015-01-16 14:27:43 -08:00
|
|
|
type_to_metadata: FnvHashMap(),
|
|
|
|
unique_id_to_metadata: FnvHashMap(),
|
|
|
|
type_to_unique_id: FnvHashMap(),
|
2014-05-30 17:09:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-13 21:09:25 +03:00
|
|
|
// Adds a Ty to metadata mapping to the TypeMap. The method will fail if
|
2014-06-18 15:07:26 +12:00
|
|
|
// the mapping already exists.
|
2014-09-29 22:11:30 +03:00
|
|
|
fn register_type_with_metadata<'a>(&mut self,
|
|
|
|
cx: &CrateContext<'a, 'tcx>,
|
|
|
|
type_: Ty<'tcx>,
|
|
|
|
metadata: DIType) {
|
2014-11-10 00:59:56 +02:00
|
|
|
if self.type_to_metadata.insert(type_, metadata).is_some() {
|
2015-01-07 11:58:31 -05:00
|
|
|
cx.sess().bug(&format!("Type metadata for Ty '{}' is already in the TypeMap!",
|
2015-02-20 14:08:14 -05:00
|
|
|
ppaux::ty_to_string(cx.tcx(), type_)));
|
2014-05-30 17:09:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// Adds a UniqueTypeId to metadata mapping to the TypeMap. The method will
|
|
|
|
// fail if the mapping already exists.
|
2014-05-30 17:09:16 +02:00
|
|
|
fn register_unique_id_with_metadata(&mut self,
|
|
|
|
cx: &CrateContext,
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
metadata: DIType) {
|
2014-11-06 12:25:16 -05:00
|
|
|
if self.unique_id_to_metadata.insert(unique_type_id, metadata).is_some() {
|
2014-05-30 17:09:16 +02:00
|
|
|
let unique_type_id_str = self.get_unique_type_id_as_string(unique_type_id);
|
2015-01-07 11:58:31 -05:00
|
|
|
cx.sess().bug(&format!("Type metadata for unique id '{}' is already in the TypeMap!",
|
2015-02-20 14:08:14 -05:00
|
|
|
&unique_type_id_str[..]));
|
2014-05-30 17:09:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
fn find_metadata_for_type(&self, type_: Ty<'tcx>) -> Option<DIType> {
|
2014-11-07 14:35:18 -05:00
|
|
|
self.type_to_metadata.get(&type_).cloned()
|
2014-05-30 17:09:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn find_metadata_for_unique_id(&self, unique_type_id: UniqueTypeId) -> Option<DIType> {
|
2014-11-07 14:35:18 -05:00
|
|
|
self.unique_id_to_metadata.get(&unique_type_id).cloned()
|
2014-05-30 17:09:16 +02:00
|
|
|
}
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// Get the string representation of a UniqueTypeId. This method will fail if
|
|
|
|
// the id is unknown.
|
2014-05-30 17:09:16 +02:00
|
|
|
fn get_unique_type_id_as_string(&self, unique_type_id: UniqueTypeId) -> Rc<String> {
|
|
|
|
let UniqueTypeId(interner_key) = unique_type_id;
|
|
|
|
self.unique_id_interner.get(interner_key)
|
|
|
|
}
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// Get the UniqueTypeId for the given type. If the UniqueTypeId for the given
|
|
|
|
// type has been requested before, this is just a table lookup. Otherwise an
|
|
|
|
// ID will be generated and stored for later lookup.
|
2014-09-29 22:11:30 +03:00
|
|
|
fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>,
|
|
|
|
type_: Ty<'tcx>) -> UniqueTypeId {
|
2014-05-30 17:09:16 +02:00
|
|
|
|
2015-01-14 12:44:21 -05:00
|
|
|
// basic type -> {:name of the type:}
|
|
|
|
// tuple -> {tuple_(:param-uid:)*}
|
|
|
|
// struct -> {struct_:svh: / :node-id:_<(:param-uid:),*> }
|
|
|
|
// enum -> {enum_:svh: / :node-id:_<(:param-uid:),*> }
|
|
|
|
// enum variant -> {variant_:variant-name:_:enum-uid:}
|
|
|
|
// reference (&) -> {& :pointee-uid:}
|
|
|
|
// mut reference (&mut) -> {&mut :pointee-uid:}
|
|
|
|
// ptr (*) -> {* :pointee-uid:}
|
|
|
|
// mut ptr (*mut) -> {*mut :pointee-uid:}
|
|
|
|
// unique ptr (~) -> {~ :pointee-uid:}
|
|
|
|
// @-ptr (@) -> {@ :pointee-uid:}
|
|
|
|
// sized vec ([T; x]) -> {[:size:] :element-uid:}
|
|
|
|
// unsized vec ([T]) -> {[] :element-uid:}
|
|
|
|
// trait (T) -> {trait_:svh: / :node-id:_<(:param-uid:),*> }
|
|
|
|
// closure -> {<unsafe_> <once_> :store-sigil: |(:param-uid:),* <,_...>| -> \
|
|
|
|
// :return-type-uid: : (:bounds:)*}
|
|
|
|
// function -> {<unsafe_> <abi_> fn( (:param-uid:)* <,_...> ) -> \
|
|
|
|
// :return-type-uid:}
|
|
|
|
// unique vec box (~[]) -> {HEAP_VEC_BOX<:pointee-uid:>}
|
|
|
|
// gc box -> {GC_BOX<:pointee-uid:>}
|
2014-05-30 17:09:16 +02:00
|
|
|
|
2014-11-07 14:35:18 -05:00
|
|
|
match self.type_to_unique_id.get(&type_).cloned() {
|
2014-05-30 17:09:16 +02:00
|
|
|
Some(unique_type_id) => return unique_type_id,
|
|
|
|
None => { /* generate one */}
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut unique_type_id = String::with_capacity(256);
|
2014-10-14 23:05:01 -07:00
|
|
|
unique_type_id.push('{');
|
2014-05-30 17:09:16 +02:00
|
|
|
|
2014-10-31 10:51:16 +02:00
|
|
|
match type_.sty {
|
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
|
|
|
ty::ty_bool |
|
|
|
|
ty::ty_char |
|
|
|
|
ty::ty_str |
|
|
|
|
ty::ty_int(_) |
|
|
|
|
ty::ty_uint(_) |
|
2014-05-30 17:09:16 +02:00
|
|
|
ty::ty_float(_) => {
|
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
|
|
|
push_debuginfo_type_name(cx, type_, false, &mut unique_type_id);
|
2014-05-30 17:09:16 +02:00
|
|
|
},
|
2014-12-03 16:01:29 -08:00
|
|
|
ty::ty_enum(def_id, substs) => {
|
2014-05-30 17:09:16 +02:00
|
|
|
unique_type_id.push_str("enum ");
|
|
|
|
from_def_id_and_substs(self, cx, def_id, substs, &mut unique_type_id);
|
|
|
|
},
|
2014-12-03 16:01:29 -08:00
|
|
|
ty::ty_struct(def_id, substs) => {
|
2014-05-30 17:09:16 +02:00
|
|
|
unique_type_id.push_str("struct ");
|
|
|
|
from_def_id_and_substs(self, cx, def_id, substs, &mut unique_type_id);
|
|
|
|
},
|
2014-11-04 07:57:21 -05:00
|
|
|
ty::ty_tup(ref component_types) if component_types.is_empty() => {
|
|
|
|
push_debuginfo_type_name(cx, type_, false, &mut unique_type_id);
|
|
|
|
},
|
2014-05-30 17:09:16 +02:00
|
|
|
ty::ty_tup(ref component_types) => {
|
|
|
|
unique_type_id.push_str("tuple ");
|
2015-01-31 12:20:46 -05:00
|
|
|
for &component_type in component_types {
|
2014-06-18 15:07:26 +12:00
|
|
|
let component_type_id =
|
|
|
|
self.get_unique_type_id_of_type(cx, component_type);
|
|
|
|
let component_type_id =
|
|
|
|
self.get_unique_type_id_as_string(component_type_id);
|
2015-02-18 14:48:57 -05:00
|
|
|
unique_type_id.push_str(&component_type_id[..]);
|
2014-05-30 17:09:16 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
ty::ty_uniq(inner_type) => {
|
2014-10-14 23:05:01 -07:00
|
|
|
unique_type_id.push('~');
|
2014-05-30 17:09:16 +02:00
|
|
|
let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
|
|
|
|
let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
|
2015-02-18 14:48:57 -05:00
|
|
|
unique_type_id.push_str(&inner_type_id[..]);
|
2014-05-30 17:09:16 +02:00
|
|
|
},
|
|
|
|
ty::ty_ptr(ty::mt { ty: inner_type, mutbl } ) => {
|
2014-10-14 23:05:01 -07:00
|
|
|
unique_type_id.push('*');
|
2014-05-30 17:09:16 +02:00
|
|
|
if mutbl == ast::MutMutable {
|
|
|
|
unique_type_id.push_str("mut");
|
|
|
|
}
|
|
|
|
|
|
|
|
let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
|
|
|
|
let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
|
2015-02-18 14:48:57 -05:00
|
|
|
unique_type_id.push_str(&inner_type_id[..]);
|
2014-05-30 17:09:16 +02:00
|
|
|
},
|
|
|
|
ty::ty_rptr(_, ty::mt { ty: inner_type, mutbl }) => {
|
2014-10-14 23:05:01 -07:00
|
|
|
unique_type_id.push('&');
|
2014-05-30 17:09:16 +02:00
|
|
|
if mutbl == ast::MutMutable {
|
|
|
|
unique_type_id.push_str("mut");
|
|
|
|
}
|
|
|
|
|
|
|
|
let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
|
|
|
|
let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
|
2015-02-18 14:48:57 -05:00
|
|
|
unique_type_id.push_str(&inner_type_id[..]);
|
2014-05-30 17:09:16 +02:00
|
|
|
},
|
DST coercions and DST structs
[breaking-change]
1. The internal layout for traits has changed from (vtable, data) to (data, vtable). If you were relying on this in unsafe transmutes, you might get some very weird and apparently unrelated errors. You should not be doing this! Prefer not to do this at all, but if you must, you should use raw::TraitObject rather than hardcoding rustc's internal representation into your code.
2. The minimal type of reference-to-vec-literals (e.g., `&[1, 2, 3]`) is now a fixed size vec (e.g., `&[int, ..3]`) where it used to be an unsized vec (e.g., `&[int]`). If you want the unszied type, you must explicitly give the type (e.g., `let x: &[_] = &[1, 2, 3]`). Note in particular where multiple blocks must have the same type (e.g., if and else clauses, vec elements), the compiler will not coerce to the unsized type without a hint. E.g., `[&[1], &[1, 2]]` used to be a valid expression of type '[&[int]]'. It no longer type checks since the first element now has type `&[int, ..1]` and the second has type &[int, ..2]` which are incompatible.
3. The type of blocks (including functions) must be coercible to the expected type (used to be a subtype). Mostly this makes things more flexible and not less (in particular, in the case of coercing function bodies to the return type). However, in some rare cases, this is less flexible. TBH, I'm not exactly sure of the exact effects. I think the change causes us to resolve inferred type variables slightly earlier which might make us slightly more restrictive. Possibly it only affects blocks with unreachable code. E.g., `if ... { fail!(); "Hello" }` used to type check, it no longer does. The fix is to add a semicolon after the string.
2014-08-04 14:20:11 +02:00
|
|
|
ty::ty_vec(inner_type, optional_length) => {
|
2014-05-30 17:09:16 +02:00
|
|
|
match optional_length {
|
|
|
|
Some(len) => {
|
2015-02-20 14:08:14 -05:00
|
|
|
unique_type_id.push_str(&format!("[{}]", len));
|
2014-05-30 17:09:16 +02:00
|
|
|
}
|
|
|
|
None => {
|
2015-01-04 17:43:24 +13:00
|
|
|
unique_type_id.push_str("[]");
|
2014-05-30 17:09:16 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
|
|
|
|
let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
|
2015-02-18 14:48:57 -05:00
|
|
|
unique_type_id.push_str(&inner_type_id[..]);
|
2014-05-30 17:09:16 +02:00
|
|
|
},
|
|
|
|
ty::ty_trait(ref trait_data) => {
|
|
|
|
unique_type_id.push_str("trait ");
|
|
|
|
|
2015-01-06 05:03:42 -05:00
|
|
|
let principal =
|
|
|
|
ty::erase_late_bound_regions(cx.tcx(),
|
|
|
|
&trait_data.principal);
|
|
|
|
|
2014-05-30 17:09:16 +02:00
|
|
|
from_def_id_and_substs(self,
|
|
|
|
cx,
|
2015-01-06 05:03:42 -05:00
|
|
|
principal.def_id,
|
|
|
|
principal.substs,
|
2014-05-30 17:09:16 +02:00
|
|
|
&mut unique_type_id);
|
|
|
|
},
|
2014-12-04 14:52:20 -08:00
|
|
|
ty::ty_bare_fn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => {
|
2014-12-09 10:36:46 -05:00
|
|
|
if unsafety == ast::Unsafety::Unsafe {
|
2014-05-30 17:09:16 +02:00
|
|
|
unique_type_id.push_str("unsafe ");
|
|
|
|
}
|
|
|
|
|
|
|
|
unique_type_id.push_str(abi.name());
|
|
|
|
|
|
|
|
unique_type_id.push_str(" fn(");
|
|
|
|
|
2015-01-06 05:03:42 -05:00
|
|
|
let sig = ty::erase_late_bound_regions(cx.tcx(), sig);
|
|
|
|
|
2015-01-31 12:20:46 -05:00
|
|
|
for ¶meter_type in &sig.inputs {
|
2014-06-18 15:07:26 +12:00
|
|
|
let parameter_type_id =
|
|
|
|
self.get_unique_type_id_of_type(cx, parameter_type);
|
|
|
|
let parameter_type_id =
|
|
|
|
self.get_unique_type_id_as_string(parameter_type_id);
|
2015-02-18 14:48:57 -05:00
|
|
|
unique_type_id.push_str(¶meter_type_id[..]);
|
2014-10-14 23:05:01 -07:00
|
|
|
unique_type_id.push(',');
|
2014-05-30 17:09:16 +02:00
|
|
|
}
|
|
|
|
|
2015-01-06 05:03:42 -05:00
|
|
|
if sig.variadic {
|
2014-05-30 17:09:16 +02:00
|
|
|
unique_type_id.push_str("...");
|
|
|
|
}
|
|
|
|
|
|
|
|
unique_type_id.push_str(")->");
|
2015-01-06 05:03:42 -05:00
|
|
|
match sig.output {
|
2014-10-24 21:14:37 +02:00
|
|
|
ty::FnConverging(ret_ty) => {
|
|
|
|
let return_type_id = self.get_unique_type_id_of_type(cx, ret_ty);
|
|
|
|
let return_type_id = self.get_unique_type_id_as_string(return_type_id);
|
2015-02-18 14:48:57 -05:00
|
|
|
unique_type_id.push_str(&return_type_id[..]);
|
2014-10-24 21:14:37 +02:00
|
|
|
}
|
|
|
|
ty::FnDiverging => {
|
|
|
|
unique_type_id.push_str("!");
|
|
|
|
}
|
|
|
|
}
|
2014-05-30 17:09:16 +02:00
|
|
|
},
|
2015-02-28 19:34:16 -05:00
|
|
|
ty::ty_closure(def_id, substs) => {
|
2015-01-24 22:00:03 +02:00
|
|
|
let typer = NormalizingClosureTyper::new(cx.tcx());
|
|
|
|
let closure_ty = typer.closure_type(def_id, substs);
|
2014-10-05 12:19:22 -07:00
|
|
|
self.get_unique_type_id_of_closure_type(cx,
|
|
|
|
closure_ty,
|
|
|
|
&mut unique_type_id);
|
2014-05-30 17:09:16 +02:00
|
|
|
},
|
2015-01-14 12:44:21 -05:00
|
|
|
_ => {
|
2015-01-07 11:58:31 -05:00
|
|
|
cx.sess().bug(&format!("get_unique_type_id_of_type() - unexpected type: {}, {:?}",
|
2015-02-20 14:08:14 -05:00
|
|
|
&ppaux::ty_to_string(cx.tcx(), type_),
|
|
|
|
type_.sty))
|
2014-05-30 17:09:16 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-10-14 23:05:01 -07:00
|
|
|
unique_type_id.push('}');
|
2014-05-30 17:09:16 +02:00
|
|
|
|
|
|
|
// Trim to size before storing permanently
|
|
|
|
unique_type_id.shrink_to_fit();
|
|
|
|
|
|
|
|
let key = self.unique_id_interner.intern(Rc::new(unique_type_id));
|
2014-11-10 00:59:56 +02:00
|
|
|
self.type_to_unique_id.insert(type_, UniqueTypeId(key));
|
2014-05-30 17:09:16 +02:00
|
|
|
|
|
|
|
return UniqueTypeId(key);
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
fn from_def_id_and_substs<'a, 'tcx>(type_map: &mut TypeMap<'tcx>,
|
|
|
|
cx: &CrateContext<'a, 'tcx>,
|
|
|
|
def_id: ast::DefId,
|
|
|
|
substs: &subst::Substs<'tcx>,
|
|
|
|
output: &mut String) {
|
2014-06-18 15:07:26 +12:00
|
|
|
// First, find out the 'real' def_id of the type. Items inlined from
|
|
|
|
// other crates have to be mapped back to their source.
|
2014-05-30 17:09:16 +02:00
|
|
|
let source_def_id = if def_id.krate == ast::LOCAL_CRATE {
|
2014-11-07 14:35:18 -05:00
|
|
|
match cx.external_srcs().borrow().get(&def_id.node).cloned() {
|
2014-05-30 17:09:16 +02:00
|
|
|
Some(source_def_id) => {
|
2014-06-18 15:07:26 +12:00
|
|
|
// The given def_id identifies the inlined copy of a
|
|
|
|
// type definition, let's take the source of the copy.
|
2014-05-30 17:09:16 +02:00
|
|
|
source_def_id
|
|
|
|
}
|
|
|
|
None => def_id
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
def_id
|
|
|
|
};
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// Get the crate hash as first part of the identifier.
|
2014-05-30 17:09:16 +02:00
|
|
|
let crate_hash = if source_def_id.krate == ast::LOCAL_CRATE {
|
2014-09-05 09:18:53 -07:00
|
|
|
cx.link_meta().crate_hash.clone()
|
2014-05-30 17:09:16 +02:00
|
|
|
} else {
|
|
|
|
cx.sess().cstore.get_crate_hash(source_def_id.krate)
|
|
|
|
};
|
|
|
|
|
|
|
|
output.push_str(crate_hash.as_str());
|
|
|
|
output.push_str("/");
|
2015-02-20 14:08:14 -05:00
|
|
|
output.push_str(&format!("{:x}", def_id.node));
|
2014-05-30 17:09:16 +02:00
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// Maybe check that there is no self type here.
|
2014-05-30 17:09:16 +02:00
|
|
|
|
2014-07-04 16:39:28 +02:00
|
|
|
let tps = substs.types.get_slice(subst::TypeSpace);
|
2015-03-24 16:54:09 -07:00
|
|
|
if !tps.is_empty() {
|
2014-10-14 23:05:01 -07:00
|
|
|
output.push('<');
|
2014-05-30 17:09:16 +02:00
|
|
|
|
2015-01-31 12:20:46 -05:00
|
|
|
for &type_parameter in tps {
|
2014-06-18 15:07:26 +12:00
|
|
|
let param_type_id =
|
|
|
|
type_map.get_unique_type_id_of_type(cx, type_parameter);
|
|
|
|
let param_type_id =
|
|
|
|
type_map.get_unique_type_id_as_string(param_type_id);
|
2015-02-18 14:48:57 -05:00
|
|
|
output.push_str(¶m_type_id[..]);
|
2014-10-14 23:05:01 -07:00
|
|
|
output.push(',');
|
2014-05-30 17:09:16 +02:00
|
|
|
}
|
|
|
|
|
2014-10-14 23:05:01 -07:00
|
|
|
output.push('>');
|
2014-05-30 17:09:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
fn get_unique_type_id_of_closure_type<'a>(&mut self,
|
|
|
|
cx: &CrateContext<'a, 'tcx>,
|
|
|
|
closure_ty: ty::ClosureTy<'tcx>,
|
|
|
|
unique_type_id: &mut String) {
|
2014-12-09 10:36:46 -05:00
|
|
|
let ty::ClosureTy { unsafety,
|
2014-10-05 12:19:22 -07:00
|
|
|
ref sig,
|
|
|
|
abi: _ } = closure_ty;
|
2015-01-18 21:01:58 +02:00
|
|
|
|
2014-12-09 10:36:46 -05:00
|
|
|
if unsafety == ast::Unsafety::Unsafe {
|
2014-10-05 12:19:22 -07:00
|
|
|
unique_type_id.push_str("unsafe ");
|
|
|
|
}
|
|
|
|
|
2015-01-18 20:27:41 +02:00
|
|
|
unique_type_id.push_str("|");
|
2014-10-05 12:19:22 -07:00
|
|
|
|
2015-01-06 05:03:42 -05:00
|
|
|
let sig = ty::erase_late_bound_regions(cx.tcx(), sig);
|
|
|
|
|
2015-01-31 12:20:46 -05:00
|
|
|
for ¶meter_type in &sig.inputs {
|
2014-10-05 12:19:22 -07:00
|
|
|
let parameter_type_id =
|
|
|
|
self.get_unique_type_id_of_type(cx, parameter_type);
|
|
|
|
let parameter_type_id =
|
|
|
|
self.get_unique_type_id_as_string(parameter_type_id);
|
2015-02-18 14:48:57 -05:00
|
|
|
unique_type_id.push_str(¶meter_type_id[..]);
|
2014-10-14 23:05:01 -07:00
|
|
|
unique_type_id.push(',');
|
2014-10-05 12:19:22 -07:00
|
|
|
}
|
|
|
|
|
2015-01-06 05:03:42 -05:00
|
|
|
if sig.variadic {
|
2014-10-05 12:19:22 -07:00
|
|
|
unique_type_id.push_str("...");
|
|
|
|
}
|
|
|
|
|
|
|
|
unique_type_id.push_str("|->");
|
|
|
|
|
2015-01-06 05:03:42 -05:00
|
|
|
match sig.output {
|
2014-10-24 21:14:37 +02:00
|
|
|
ty::FnConverging(ret_ty) => {
|
|
|
|
let return_type_id = self.get_unique_type_id_of_type(cx, ret_ty);
|
|
|
|
let return_type_id = self.get_unique_type_id_as_string(return_type_id);
|
2015-02-18 14:48:57 -05:00
|
|
|
unique_type_id.push_str(&return_type_id[..]);
|
2014-10-24 21:14:37 +02:00
|
|
|
}
|
|
|
|
ty::FnDiverging => {
|
|
|
|
unique_type_id.push_str("!");
|
|
|
|
}
|
|
|
|
}
|
2014-10-05 12:19:22 -07:00
|
|
|
}
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// Get the UniqueTypeId for an enum variant. Enum variants are not really
|
|
|
|
// types of their own, so they need special handling. We still need a
|
|
|
|
// UniqueTypeId for them, since to debuginfo they *are* real types.
|
2014-09-29 22:11:30 +03:00
|
|
|
fn get_unique_type_id_of_enum_variant<'a>(&mut self,
|
|
|
|
cx: &CrateContext<'a, 'tcx>,
|
|
|
|
enum_type: Ty<'tcx>,
|
|
|
|
variant_name: &str)
|
|
|
|
-> UniqueTypeId {
|
2014-05-30 17:09:16 +02:00
|
|
|
let enum_type_id = self.get_unique_type_id_of_type(cx, enum_type);
|
|
|
|
let enum_variant_type_id = format!("{}::{}",
|
2015-02-20 14:08:14 -05:00
|
|
|
&self.get_unique_type_id_as_string(enum_type_id),
|
2014-05-30 17:09:16 +02:00
|
|
|
variant_name);
|
|
|
|
let interner_key = self.unique_id_interner.intern(Rc::new(enum_variant_type_id));
|
|
|
|
UniqueTypeId(interner_key)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
// Returns from the enclosing function if the type metadata with the given
|
|
|
|
// unique id can be found in the type map
|
2014-11-14 09:18:10 -08:00
|
|
|
macro_rules! return_if_metadata_created_in_meantime {
|
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
|
|
|
($cx: expr, $unique_type_id: expr) => (
|
|
|
|
match debug_context($cx).type_map
|
|
|
|
.borrow()
|
|
|
|
.find_metadata_for_unique_id($unique_type_id) {
|
|
|
|
Some(metadata) => return MetadataCreationResult::new(metadata, true),
|
|
|
|
None => { /* proceed normally */ }
|
|
|
|
};
|
|
|
|
)
|
2014-11-14 09:18:10 -08:00
|
|
|
}
|
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
|
|
|
|
2014-05-30 17:09:16 +02: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>>,
|
|
|
|
created_enum_disr_types: RefCell<DefIdMap<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,
|
2013-12-18 19:09:14 -08:00
|
|
|
current_debug_location: Cell::new(UnknownLocation),
|
2015-01-16 14:27:43 -08:00
|
|
|
created_files: RefCell::new(FnvHashMap()),
|
|
|
|
created_enum_disr_types: RefCell::new(DefIdMap()),
|
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
|
|
|
}
|
|
|
|
|
2013-12-09 23:16:18 -08:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
if needs_gdb_debug_scripts_section(cx) {
|
|
|
|
// 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.
|
|
|
|
get_or_insert_gdb_debug_scripts_section_global(cx);
|
|
|
|
}
|
|
|
|
|
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 _,
|
|
|
|
llvm::LLVMRustDebugMetadataVersion);
|
2013-06-14 11:38:29 -07:00
|
|
|
};
|
2011-11-10 00:55:09 -05:00
|
|
|
}
|
|
|
|
|
2014-02-20 20:44:29 -05:00
|
|
|
/// Creates debug information for the given global variable.
|
|
|
|
///
|
|
|
|
/// Adds the created metadata nodes directly to the crate's IR.
|
|
|
|
pub fn create_global_var_metadata(cx: &CrateContext,
|
|
|
|
node_id: ast::NodeId,
|
|
|
|
global: ValueRef) {
|
2014-09-05 09:18:53 -07:00
|
|
|
if cx.dbg_cx().is_none() {
|
2014-02-20 20:44:29 -05:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// Don't create debuginfo for globals inlined from other crates. The other
|
|
|
|
// crate should already contain debuginfo for it. More importantly, the
|
|
|
|
// global might not even exist in un-inlined form anywhere which would lead
|
|
|
|
// to a linker errors.
|
2014-09-05 09:18:53 -07:00
|
|
|
if cx.external_srcs().borrow().contains_key(&node_id) {
|
2014-04-10 10:25:13 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-09-05 09:18:53 -07:00
|
|
|
let var_item = cx.tcx().map.get(node_id);
|
2014-02-20 20:44:29 -05:00
|
|
|
|
2015-03-23 19:41:35 -05:00
|
|
|
let (name, span) = match var_item {
|
2014-02-20 20:44:29 -05:00
|
|
|
ast_map::NodeItem(item) => {
|
|
|
|
match item.node {
|
2015-03-23 19:41:35 -05:00
|
|
|
ast::ItemStatic(..) => (item.ident.name, item.span),
|
|
|
|
ast::ItemConst(..) => (item.ident.name, item.span),
|
2014-05-16 10:45:16 -07:00
|
|
|
_ => {
|
|
|
|
cx.sess()
|
|
|
|
.span_bug(item.span,
|
2015-01-07 11:58:31 -05:00
|
|
|
&format!("debuginfo::\
|
2014-05-16 10:45:16 -07:00
|
|
|
create_global_var_metadata() -
|
|
|
|
Captured var-id refers to \
|
2014-12-20 00:09:35 -08:00
|
|
|
unexpected ast_item variant: {:?}",
|
2015-02-20 14:08:14 -05:00
|
|
|
var_item))
|
2014-05-16 10:45:16 -07:00
|
|
|
}
|
2014-02-20 20:44:29 -05:00
|
|
|
}
|
|
|
|
},
|
2015-01-07 11:58:31 -05:00
|
|
|
_ => cx.sess().bug(&format!("debuginfo::create_global_var_metadata() \
|
2014-05-16 10:45:16 -07:00
|
|
|
- Captured var-id refers to unexpected \
|
2014-12-20 00:09:35 -08:00
|
|
|
ast_map variant: {:?}",
|
2015-02-20 14:08:14 -05:00
|
|
|
var_item))
|
2014-02-20 20:44:29 -05:00
|
|
|
};
|
|
|
|
|
2014-07-10 15:38:57 +02:00
|
|
|
let (file_metadata, line_number) = if span != codemap::DUMMY_SP {
|
|
|
|
let loc = span_start(cx, span);
|
2015-02-20 14:08:14 -05:00
|
|
|
(file_metadata(cx, &loc.file.name), loc.line as c_uint)
|
2014-07-10 15:38:57 +02:00
|
|
|
} else {
|
|
|
|
(UNKNOWN_FILE_METADATA, UNKNOWN_LINE_NUMBER)
|
|
|
|
};
|
2014-02-20 20:44:29 -05:00
|
|
|
|
|
|
|
let is_local_to_unit = is_node_local_to_unit(cx, node_id);
|
|
|
|
let variable_type = ty::node_id_to_type(cx.tcx(), node_id);
|
|
|
|
let type_metadata = type_metadata(cx, variable_type, span);
|
|
|
|
let namespace_node = namespace_for_item(cx, ast_util::local_def(node_id));
|
2015-03-23 19:41:35 -05:00
|
|
|
let var_name = token::get_name(name).to_string();
|
2014-05-16 10:45:16 -07:00
|
|
|
let linkage_name =
|
2015-02-18 14:48:57 -05:00
|
|
|
namespace_node.mangled_name_of_contained_item(&var_name[..]);
|
2014-02-20 20:44:29 -05:00
|
|
|
let var_scope = namespace_node.scope;
|
|
|
|
|
2015-02-17 22:47:40 -08:00
|
|
|
let var_name = CString::new(var_name).unwrap();
|
|
|
|
let linkage_name = CString::new(linkage_name).unwrap();
|
2014-11-25 13:28:35 -08:00
|
|
|
unsafe {
|
|
|
|
llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx),
|
|
|
|
var_scope,
|
|
|
|
var_name.as_ptr(),
|
|
|
|
linkage_name.as_ptr(),
|
|
|
|
file_metadata,
|
|
|
|
line_number,
|
|
|
|
type_metadata,
|
|
|
|
is_local_to_unit,
|
|
|
|
global,
|
|
|
|
ptr::null_mut());
|
|
|
|
}
|
2014-02-20 20:44:29 -05:00
|
|
|
}
|
|
|
|
|
2013-06-18 13:06:41 +02:00
|
|
|
/// Creates debug information for the given local variable.
|
|
|
|
///
|
2014-12-19 11:37:49 +01:00
|
|
|
/// This function assumes that there's a datum for each pattern component of the
|
|
|
|
/// local in `bcx.fcx.lllocals`.
|
2013-06-20 11:50:02 +02:00
|
|
|
/// Adds the created metadata nodes directly to the crate's IR.
|
2014-09-06 19:13:04 +03:00
|
|
|
pub fn create_local_var_metadata(bcx: Block, local: &ast::Local) {
|
2015-01-15 15:22:56 +01:00
|
|
|
if bcx.unreachable.get() ||
|
|
|
|
fn_should_be_ignored(bcx.fcx) ||
|
|
|
|
bcx.sess().opts.debuginfo != FullDebugInfo {
|
2013-08-23 18:45:02 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-06-18 13:06:41 +02:00
|
|
|
let cx = bcx.ccx();
|
2014-09-05 09:18:53 -07:00
|
|
|
let def_map = &cx.tcx().def_map;
|
2014-12-19 11:37:49 +01:00
|
|
|
let locals = bcx.fcx.lllocals.borrow();
|
2013-07-12 10:16:54 +02:00
|
|
|
|
2014-12-19 11:37:49 +01:00
|
|
|
pat_util::pat_bindings(def_map, &*local.pat, |_, node_id, span, var_ident| {
|
|
|
|
let datum = match locals.get(&node_id) {
|
2014-03-20 19:49:20 -07:00
|
|
|
Some(datum) => datum,
|
|
|
|
None => {
|
|
|
|
bcx.sess().span_bug(span,
|
2015-01-07 11:58:31 -05:00
|
|
|
&format!("no entry in lllocals table for {}",
|
2015-02-20 14:08:14 -05:00
|
|
|
node_id));
|
2013-08-23 18:45:02 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-12-19 11:37:49 +01:00
|
|
|
if unsafe { llvm::LLVMIsAAllocaInst(datum.val) } == ptr::null_mut() {
|
|
|
|
cx.sess().span_bug(span, "debuginfo::create_local_var_metadata() - \
|
|
|
|
Referenced variable location is not an alloca!");
|
|
|
|
}
|
|
|
|
|
2013-08-23 18:45:02 +02:00
|
|
|
let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
|
|
|
|
|
|
|
|
declare_local(bcx,
|
2015-03-23 19:41:35 -05:00
|
|
|
var_ident.node.name,
|
2014-01-11 16:39:32 +02:00
|
|
|
datum.ty,
|
2013-08-23 18:45:02 +02:00
|
|
|
scope_metadata,
|
2014-01-11 16:39:32 +02:00
|
|
|
DirectVariable { alloca: datum.val },
|
2013-08-23 18:45:02 +02:00
|
|
|
LocalVariable,
|
|
|
|
span);
|
2013-11-21 15:42:55 -08:00
|
|
|
})
|
2013-06-18 13:06:41 +02:00
|
|
|
}
|
|
|
|
|
2013-08-29 11:44:11 +02:00
|
|
|
/// Creates debug information for a variable captured in a closure.
|
2013-08-23 18:45:02 +02:00
|
|
|
///
|
2013-08-29 11:44:11 +02:00
|
|
|
/// Adds the created metadata nodes directly to the crate's IR.
|
2014-09-29 22:11:30 +03:00
|
|
|
pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|
|
|
node_id: ast::NodeId,
|
|
|
|
env_pointer: ValueRef,
|
2015-03-25 17:06:52 -07:00
|
|
|
env_index: usize,
|
2014-11-27 15:52:16 +01:00
|
|
|
captured_by_ref: bool,
|
2014-09-29 22:11:30 +03:00
|
|
|
span: Span) {
|
2015-01-15 15:22:56 +01:00
|
|
|
if bcx.unreachable.get() ||
|
|
|
|
fn_should_be_ignored(bcx.fcx) ||
|
|
|
|
bcx.sess().opts.debuginfo != FullDebugInfo {
|
2013-08-23 18:45:02 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let cx = bcx.ccx();
|
|
|
|
|
2014-09-05 09:18:53 -07:00
|
|
|
let ast_item = cx.tcx().map.find(node_id);
|
2014-01-17 23:23:09 +11:00
|
|
|
|
2015-03-23 19:41:35 -05:00
|
|
|
let variable_name = match ast_item {
|
2013-08-23 18:45:02 +02:00
|
|
|
None => {
|
2014-03-05 16:36:01 +02:00
|
|
|
cx.sess().span_bug(span, "debuginfo::create_captured_var_metadata: node not found");
|
2013-08-23 18:45:02 +02:00
|
|
|
}
|
2014-01-27 14:18:36 +02:00
|
|
|
Some(ast_map::NodeLocal(pat)) | Some(ast_map::NodeArg(pat)) => {
|
2014-01-03 15:08:48 -08:00
|
|
|
match pat.node {
|
2014-06-30 18:02:14 -07:00
|
|
|
ast::PatIdent(_, ref path1, _) => {
|
2015-03-23 19:41:35 -05:00
|
|
|
path1.node.name
|
2014-01-03 15:08:48 -08:00
|
|
|
}
|
|
|
|
_ => {
|
2014-03-05 16:36:01 +02:00
|
|
|
cx.sess()
|
2014-01-03 15:08:48 -08:00
|
|
|
.span_bug(span,
|
2015-01-07 11:58:31 -05:00
|
|
|
&format!(
|
2014-01-03 15:08:48 -08:00
|
|
|
"debuginfo::create_captured_var_metadata() - \
|
|
|
|
Captured var-id refers to unexpected \
|
2014-12-20 00:09:35 -08:00
|
|
|
ast_map variant: {:?}",
|
2015-02-20 14:08:14 -05:00
|
|
|
ast_item));
|
2014-01-03 15:08:48 -08:00
|
|
|
}
|
|
|
|
}
|
2013-08-23 18:45:02 +02:00
|
|
|
}
|
|
|
|
_ => {
|
2014-05-16 10:45:16 -07:00
|
|
|
cx.sess()
|
|
|
|
.span_bug(span,
|
2015-01-07 11:58:31 -05:00
|
|
|
&format!("debuginfo::create_captured_var_metadata() - \
|
2014-05-16 10:45:16 -07:00
|
|
|
Captured var-id refers to unexpected \
|
2014-12-20 00:09:35 -08:00
|
|
|
ast_map variant: {:?}",
|
2015-02-20 14:08:14 -05:00
|
|
|
ast_item));
|
2013-08-23 18:45:02 +02:00
|
|
|
}
|
|
|
|
};
|
2013-09-03 18:23:59 +02:00
|
|
|
|
2014-12-11 13:53:30 +01:00
|
|
|
let variable_type = common::node_id_type(bcx, node_id);
|
2013-08-23 18:45:02 +02:00
|
|
|
let scope_metadata = bcx.fcx.debug_context.get_ref(cx, span).fn_metadata;
|
|
|
|
|
2014-12-05 18:35:16 -05:00
|
|
|
// env_pointer is the alloca containing the pointer to the environment,
|
|
|
|
// so it's type is **EnvironmentType. In order to find out the type of
|
|
|
|
// the environment we have to "dereference" two times.
|
2014-12-11 13:53:30 +01:00
|
|
|
let llvm_env_data_type = common::val_ty(env_pointer).element_type()
|
|
|
|
.element_type();
|
2014-06-18 15:07:26 +12:00
|
|
|
let byte_offset_of_var_in_env = machine::llelement_offset(cx,
|
|
|
|
llvm_env_data_type,
|
|
|
|
env_index);
|
2013-09-03 18:23:59 +02:00
|
|
|
|
|
|
|
let address_operations = unsafe {
|
2015-01-30 19:25:07 +01:00
|
|
|
[llvm::LLVMDIBuilderCreateOpDeref(),
|
|
|
|
llvm::LLVMDIBuilderCreateOpPlus(),
|
|
|
|
byte_offset_of_var_in_env as i64,
|
|
|
|
llvm::LLVMDIBuilderCreateOpDeref()]
|
2013-09-03 18:23:59 +02:00
|
|
|
};
|
|
|
|
|
2014-11-27 15:52:16 +01:00
|
|
|
let address_op_count = if captured_by_ref {
|
|
|
|
address_operations.len()
|
|
|
|
} else {
|
|
|
|
address_operations.len() - 1
|
2013-09-03 18:23:59 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
let variable_access = IndirectVariable {
|
|
|
|
alloca: env_pointer,
|
2015-01-12 16:59:18 -05:00
|
|
|
address_operations: &address_operations[..address_op_count]
|
2013-09-03 18:23:59 +02:00
|
|
|
};
|
|
|
|
|
2013-08-23 18:45:02 +02:00
|
|
|
declare_local(bcx,
|
2015-03-23 19:41:35 -05:00
|
|
|
variable_name,
|
2013-08-23 18:45:02 +02:00
|
|
|
variable_type,
|
|
|
|
scope_metadata,
|
2013-09-03 18:23:59 +02:00
|
|
|
variable_access,
|
2013-08-23 18:45:02 +02:00
|
|
|
CapturedVariable,
|
|
|
|
span);
|
|
|
|
}
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
/// Creates debug information for a local variable introduced in the head of a
|
|
|
|
/// match-statement arm.
|
2013-08-15 09:56:05 +02:00
|
|
|
///
|
|
|
|
/// Adds the created metadata nodes directly to the crate's IR.
|
2014-09-29 22:11:30 +03:00
|
|
|
pub fn create_match_binding_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
2015-03-23 19:41:35 -05:00
|
|
|
variable_name: ast::Name,
|
2014-09-29 22:11:30 +03:00
|
|
|
binding: BindingInfo<'tcx>) {
|
2015-01-15 15:22:56 +01:00
|
|
|
if bcx.unreachable.get() ||
|
|
|
|
fn_should_be_ignored(bcx.fcx) ||
|
|
|
|
bcx.sess().opts.debuginfo != FullDebugInfo {
|
2013-08-23 18:45:02 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-06-21 08:01:12 -04:00
|
|
|
let scope_metadata = scope_metadata(bcx.fcx, binding.id, binding.span);
|
|
|
|
let aops = unsafe {
|
2015-01-30 19:25:07 +01:00
|
|
|
[llvm::LLVMDIBuilderCreateOpDeref()]
|
2014-06-21 08:01:12 -04:00
|
|
|
};
|
2015-04-24 11:38:53 +12:00
|
|
|
// Regardless of the actual type (`T`) we're always passed the stack slot
|
|
|
|
// (alloca) for the binding. For ByRef bindings that's a `T*` but for ByMove
|
|
|
|
// bindings we actually have `T**`. So to get the actual variable we need to
|
|
|
|
// dereference once more. For ByCopy we just use the stack slot we created
|
|
|
|
// for the binding.
|
2014-12-19 11:37:49 +01:00
|
|
|
let var_access = match binding.trmode {
|
2014-06-21 17:05:05 -04:00
|
|
|
TrByCopy(llbinding) => DirectVariable {
|
|
|
|
alloca: llbinding
|
|
|
|
},
|
|
|
|
TrByMove => IndirectVariable {
|
2014-06-21 08:01:12 -04:00
|
|
|
alloca: binding.llmatch,
|
2014-11-17 21:39:01 +13:00
|
|
|
address_operations: &aops
|
2014-06-21 08:01:12 -04:00
|
|
|
},
|
|
|
|
TrByRef => DirectVariable {
|
|
|
|
alloca: binding.llmatch
|
|
|
|
}
|
|
|
|
};
|
2013-08-23 18:45:02 +02:00
|
|
|
|
|
|
|
declare_local(bcx,
|
2015-03-23 19:41:35 -05:00
|
|
|
variable_name,
|
2014-06-21 08:01:12 -04:00
|
|
|
binding.ty,
|
2013-08-23 18:45:02 +02:00
|
|
|
scope_metadata,
|
2014-12-19 11:37:49 +01:00
|
|
|
var_access,
|
2013-08-23 18:45:02 +02:00
|
|
|
LocalVariable,
|
2014-06-21 08:01:12 -04:00
|
|
|
binding.span);
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
|
2013-06-18 13:06:41 +02:00
|
|
|
/// Creates debug information for the given function argument.
|
|
|
|
///
|
2014-12-19 11:37:49 +01:00
|
|
|
/// This function assumes that there's a datum for each pattern component of the
|
|
|
|
/// argument in `bcx.fcx.lllocals`.
|
2013-06-20 11:50:02 +02:00
|
|
|
/// Adds the created metadata nodes directly to the crate's IR.
|
2014-09-06 19:13:04 +03:00
|
|
|
pub fn create_argument_metadata(bcx: Block, arg: &ast::Arg) {
|
2015-01-15 15:22:56 +01:00
|
|
|
if bcx.unreachable.get() ||
|
|
|
|
fn_should_be_ignored(bcx.fcx) ||
|
|
|
|
bcx.sess().opts.debuginfo != FullDebugInfo {
|
2013-08-23 18:45:02 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-12-19 11:37:49 +01:00
|
|
|
let def_map = &bcx.tcx().def_map;
|
|
|
|
let scope_metadata = bcx
|
|
|
|
.fcx
|
|
|
|
.debug_context
|
|
|
|
.get_ref(bcx.ccx(), arg.pat.span)
|
|
|
|
.fn_metadata;
|
|
|
|
let locals = bcx.fcx.lllocals.borrow();
|
2014-12-22 08:25:34 -08:00
|
|
|
|
2014-12-19 11:37:49 +01:00
|
|
|
pat_util::pat_bindings(def_map, &*arg.pat, |_, node_id, span, var_ident| {
|
|
|
|
let datum = match locals.get(&node_id) {
|
2014-03-20 19:49:20 -07:00
|
|
|
Some(v) => v,
|
|
|
|
None => {
|
|
|
|
bcx.sess().span_bug(span,
|
2015-01-07 11:58:31 -05:00
|
|
|
&format!("no entry in lllocals table for {}",
|
2015-02-20 14:08:14 -05:00
|
|
|
node_id));
|
2013-07-18 12:04:33 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-12-19 11:37:49 +01:00
|
|
|
if unsafe { llvm::LLVMIsAAllocaInst(datum.val) } == ptr::null_mut() {
|
|
|
|
bcx.sess().span_bug(span, "debuginfo::create_argument_metadata() - \
|
|
|
|
Referenced variable location is not an alloca!");
|
2013-09-03 18:23:59 +02:00
|
|
|
}
|
2013-08-28 17:47:31 +02:00
|
|
|
|
2013-08-23 18:45:02 +02:00
|
|
|
let argument_index = {
|
2014-12-19 11:37:49 +01:00
|
|
|
let counter = &bcx
|
|
|
|
.fcx
|
|
|
|
.debug_context
|
|
|
|
.get_ref(bcx.ccx(), span)
|
|
|
|
.argument_counter;
|
2013-12-20 20:55:55 -08:00
|
|
|
let argument_index = counter.get();
|
|
|
|
counter.set(argument_index + 1);
|
2013-08-23 18:45:02 +02:00
|
|
|
argument_index
|
|
|
|
};
|
|
|
|
|
|
|
|
declare_local(bcx,
|
2015-03-23 19:41:35 -05:00
|
|
|
var_ident.node.name,
|
2014-12-19 11:37:49 +01:00
|
|
|
datum.ty,
|
2013-08-23 18:45:02 +02:00
|
|
|
scope_metadata,
|
2014-12-19 11:37:49 +01:00
|
|
|
DirectVariable { alloca: datum.val },
|
2013-08-23 18:45:02 +02:00
|
|
|
ArgumentVariable(argument_index),
|
|
|
|
span);
|
2014-12-19 09:48:28 +01:00
|
|
|
})
|
2013-06-18 13:06:41 +02:00
|
|
|
}
|
|
|
|
|
2014-11-27 13:54:01 +01:00
|
|
|
pub fn get_cleanup_debug_loc_for_ast_node<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|
|
|
node_id: ast::NodeId,
|
|
|
|
node_span: Span,
|
|
|
|
is_block: bool)
|
2014-12-11 13:53:30 +01:00
|
|
|
-> NodeIdAndSpan {
|
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
|
|
|
// A debug location needs two things:
|
|
|
|
// (1) A span (of which only the beginning will actually be used)
|
|
|
|
// (2) An AST node-id which will be used to look up the lexical scope
|
|
|
|
// for the location in the functions scope-map
|
|
|
|
//
|
|
|
|
// This function will calculate the debug location for compiler-generated
|
|
|
|
// cleanup calls that are executed when control-flow leaves the
|
|
|
|
// scope identified by `node_id`.
|
|
|
|
//
|
|
|
|
// For everything but block-like things we can simply take id and span of
|
|
|
|
// the given expression, meaning that from a debugger's view cleanup code is
|
|
|
|
// executed at the same source location as the statement/expr itself.
|
|
|
|
//
|
|
|
|
// Blocks are a special case. Here we want the cleanup to be linked to the
|
|
|
|
// closing curly brace of the block. The *scope* the cleanup is executed in
|
|
|
|
// is up to debate: It could either still be *within* the block being
|
|
|
|
// cleaned up, meaning that locals from the block are still visible in the
|
|
|
|
// debugger.
|
|
|
|
// Or it could be in the scope that the block is contained in, so any locals
|
|
|
|
// from within the block are already considered out-of-scope and thus not
|
|
|
|
// accessible in the debugger anymore.
|
|
|
|
//
|
|
|
|
// The current implementation opts for the second option: cleanup of a block
|
|
|
|
// already happens in the parent scope of the block. The main reason for
|
|
|
|
// this decision is that scoping becomes controlflow dependent when variable
|
|
|
|
// shadowing is involved and it's impossible to decide statically which
|
|
|
|
// scope is actually left when the cleanup code is executed.
|
|
|
|
// In practice it shouldn't make much of a difference.
|
|
|
|
|
2014-11-27 13:54:01 +01:00
|
|
|
let mut cleanup_span = node_span;
|
|
|
|
|
|
|
|
if is_block {
|
|
|
|
// Not all blocks actually have curly braces (e.g. simple closure
|
|
|
|
// bodies), in which case we also just want to return the span of the
|
|
|
|
// whole expression.
|
|
|
|
let code_snippet = cx.sess().codemap().span_to_snippet(node_span);
|
2015-02-05 16:02:22 +01:00
|
|
|
if let Ok(code_snippet) = code_snippet {
|
2014-11-27 13:54:01 +01:00
|
|
|
let bytes = code_snippet.as_bytes();
|
|
|
|
|
2015-03-24 16:54:09 -07:00
|
|
|
if !bytes.is_empty() && &bytes[bytes.len()-1..] == b"}" {
|
2014-11-27 13:54:01 +01:00
|
|
|
cleanup_span = Span {
|
|
|
|
lo: node_span.hi - codemap::BytePos(1),
|
|
|
|
hi: node_span.hi,
|
|
|
|
expn_id: node_span.expn_id
|
|
|
|
};
|
|
|
|
}
|
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
|
|
|
}
|
2014-11-27 13:54: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
|
|
|
|
2014-12-11 13:53:30 +01:00
|
|
|
NodeIdAndSpan {
|
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
|
|
|
id: node_id,
|
|
|
|
span: cleanup_span
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-04 17:16:59 +01:00
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
2014-12-11 13:53:30 +01:00
|
|
|
pub enum DebugLoc {
|
|
|
|
At(ast::NodeId, Span),
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DebugLoc {
|
|
|
|
pub fn apply(&self, fcx: &FunctionContext) {
|
|
|
|
match *self {
|
|
|
|
DebugLoc::At(node_id, span) => {
|
|
|
|
set_source_location(fcx, node_id, span);
|
|
|
|
}
|
|
|
|
DebugLoc::None => {
|
|
|
|
clear_source_location(fcx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait ToDebugLoc {
|
|
|
|
fn debug_loc(&self) -> DebugLoc;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ToDebugLoc for ast::Expr {
|
|
|
|
fn debug_loc(&self) -> DebugLoc {
|
|
|
|
DebugLoc::At(self.id, self.span)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ToDebugLoc for NodeIdAndSpan {
|
|
|
|
fn debug_loc(&self) -> DebugLoc {
|
|
|
|
DebugLoc::At(self.id, self.span)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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-13 16:31:42 +02:00
|
|
|
/// Sets the current debug location at the beginning of the span.
|
2013-06-18 13:06:41 +02:00
|
|
|
///
|
2014-06-18 15:07:26 +12:00
|
|
|
/// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...). The node_id
|
|
|
|
/// parameter is used to reliably find the correct visibility scope for the code
|
|
|
|
/// position.
|
2013-08-19 18:23:43 +02:00
|
|
|
pub fn set_source_location(fcx: &FunctionContext,
|
|
|
|
node_id: ast::NodeId,
|
2013-09-03 12:15:56 +02:00
|
|
|
span: Span) {
|
2014-12-19 11:37:49 +01:00
|
|
|
match fcx.debug_context {
|
|
|
|
FunctionDebugContext::DebugInfoDisabled => return,
|
|
|
|
FunctionDebugContext::FunctionWithoutDebugInfo => {
|
2014-03-27 13:43:01 +01:00
|
|
|
set_debug_location(fcx.ccx, UnknownLocation);
|
|
|
|
return;
|
|
|
|
}
|
2014-12-19 11:37:49 +01:00
|
|
|
FunctionDebugContext::RegularContext(box ref function_debug_context) => {
|
2015-03-05 15:00:25 +01:00
|
|
|
if function_debug_context.source_location_override.get() {
|
|
|
|
// Just ignore any attempts to set a new debug location while
|
|
|
|
// the override is active.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-03-27 13:43:01 +01:00
|
|
|
let cx = fcx.ccx;
|
2013-08-23 18:45:02 +02:00
|
|
|
|
2014-06-21 03:39:03 -07:00
|
|
|
debug!("set_source_location: {}", cx.sess().codemap().span_to_string(span));
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2014-03-27 13:43:01 +01:00
|
|
|
if function_debug_context.source_locations_enabled.get() {
|
|
|
|
let loc = span_start(cx, span);
|
|
|
|
let scope = scope_metadata(fcx, node_id, span);
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2014-12-11 13:53:30 +01:00
|
|
|
set_debug_location(cx, InternalDebugLocation::new(scope,
|
|
|
|
loc.line,
|
2015-01-21 11:50:34 -08:00
|
|
|
loc.col.to_usize()));
|
2014-03-27 13:43:01 +01:00
|
|
|
} else {
|
|
|
|
set_debug_location(cx, UnknownLocation);
|
|
|
|
}
|
|
|
|
}
|
2013-08-19 18:23:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-05 15:00:25 +01:00
|
|
|
/// This function makes sure that all debug locations emitted while executing
|
|
|
|
/// `wrapped_function` are set to the given `debug_loc`.
|
|
|
|
pub fn with_source_location_override<F, R>(fcx: &FunctionContext,
|
|
|
|
debug_loc: DebugLoc,
|
|
|
|
wrapped_function: F) -> R
|
|
|
|
where F: FnOnce() -> R
|
|
|
|
{
|
|
|
|
match fcx.debug_context {
|
|
|
|
FunctionDebugContext::DebugInfoDisabled => {
|
|
|
|
wrapped_function()
|
|
|
|
}
|
|
|
|
FunctionDebugContext::FunctionWithoutDebugInfo => {
|
|
|
|
set_debug_location(fcx.ccx, UnknownLocation);
|
|
|
|
wrapped_function()
|
|
|
|
}
|
|
|
|
FunctionDebugContext::RegularContext(box ref function_debug_context) => {
|
|
|
|
if function_debug_context.source_location_override.get() {
|
|
|
|
wrapped_function()
|
|
|
|
} else {
|
|
|
|
debug_loc.apply(fcx);
|
|
|
|
function_debug_context.source_location_override.set(true);
|
|
|
|
let result = wrapped_function();
|
|
|
|
function_debug_context.source_location_override.set(false);
|
|
|
|
result
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-18 16:56:44 +01:00
|
|
|
/// Clears the current debug location.
|
|
|
|
///
|
|
|
|
/// Instructions generated hereafter won't be assigned a source location.
|
|
|
|
pub fn clear_source_location(fcx: &FunctionContext) {
|
|
|
|
if fn_should_be_ignored(fcx) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
set_debug_location(fcx.ccx, UnknownLocation);
|
|
|
|
}
|
|
|
|
|
2013-08-29 11:44:11 +02:00
|
|
|
/// Enables emitting source locations for the given functions.
|
|
|
|
///
|
2014-06-18 15:07:26 +12:00
|
|
|
/// Since we don't want source locations to be emitted for the function prelude,
|
|
|
|
/// they are disabled when beginning to translate a new function. This functions
|
|
|
|
/// switches source location emitting on and must therefore be called before the
|
|
|
|
/// first real statement/expression of the function is translated.
|
2013-12-20 21:00:15 -08:00
|
|
|
pub fn start_emitting_source_locations(fcx: &FunctionContext) {
|
2014-12-19 11:37:49 +01:00
|
|
|
match fcx.debug_context {
|
|
|
|
FunctionDebugContext::RegularContext(box ref data) => {
|
2013-12-20 20:57:25 -08:00
|
|
|
data.source_locations_enabled.set(true)
|
|
|
|
},
|
2013-08-29 11:44:11 +02:00
|
|
|
_ => { /* safe to ignore */ }
|
2013-08-19 18:23:43 +02:00
|
|
|
}
|
2013-06-18 13:06:41 +02: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.
|
2014-03-27 13:43:01 +01:00
|
|
|
set_debug_location(cx, UnknownLocation);
|
|
|
|
|
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 {
|
2014-09-07 20:09:06 +03: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,
|
|
|
|
&*fn_decl,
|
|
|
|
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-03-23 19:41:35 -05:00
|
|
|
let mut function_name = String::from_str(&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
|
|
|
|
2014-12-19 11:37:49 +01:00
|
|
|
let scope_map = create_scope_map(cx,
|
2015-02-01 21:53:25 -05:00
|
|
|
&fn_decl.inputs,
|
2014-12-19 11:37:49 +01:00
|
|
|
&*top_level_block,
|
|
|
|
fn_metadata,
|
|
|
|
fn_ast_id);
|
|
|
|
|
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,
|
|
|
|
fn_decl: &ast::FnDecl,
|
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
|
|
|
}
|
|
|
|
|
2014-04-17 15:59:07 -07:00
|
|
|
let mut signature = Vec::with_capacity(fn_decl.inputs.len() + 1);
|
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);
|
|
|
|
let return_type = ty::node_id_to_type(cx.tcx(), fn_ast_id);
|
|
|
|
let return_type = monomorphize::apply_param_substs(cx.tcx(),
|
|
|
|
param_substs,
|
|
|
|
&return_type);
|
|
|
|
if ty::type_is_nil(return_type) {
|
|
|
|
signature.push(ptr::null_mut())
|
|
|
|
} else {
|
|
|
|
signature.push(type_metadata(cx, return_type, codemap::DUMMY_SP));
|
2013-06-18 13:06:41 +02:00
|
|
|
}
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2013-09-06 16:00:08 +02:00
|
|
|
// Arguments types
|
2015-01-31 12:20:46 -05:00
|
|
|
for arg in &fn_decl.inputs {
|
2013-09-11 14:09:18 +02:00
|
|
|
assert_type_for_node_id(cx, arg.pat.id, arg.pat.span);
|
2014-03-15 22:29:34 +02:00
|
|
|
let arg_type = ty::node_id_to_type(cx.tcx(), arg.pat.id);
|
2014-12-17 14:16:28 -05:00
|
|
|
let arg_type = monomorphize::apply_param_substs(cx.tcx(),
|
|
|
|
param_substs,
|
|
|
|
&arg_type);
|
2014-01-01 15:53:22 +09:00
|
|
|
signature.push(type_metadata(cx, arg_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),
|
|
|
|
file_metadata,
|
|
|
|
name.as_ptr(),
|
|
|
|
actual_self_type_metadata,
|
|
|
|
ptr::null_mut(),
|
|
|
|
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),
|
|
|
|
file_metadata,
|
|
|
|
name.as_ptr(),
|
|
|
|
actual_type_metadata,
|
|
|
|
ptr::null_mut(),
|
|
|
|
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
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
//=-----------------------------------------------------------------------------
|
2013-06-18 13:06:41 +02:00
|
|
|
// Module-Internal debug info creation functions
|
2014-06-18 15:07:26 +12:00
|
|
|
//=-----------------------------------------------------------------------------
|
2013-06-18 13:06:41 +02:00
|
|
|
|
2014-02-20 20:44:29 -05:00
|
|
|
fn is_node_local_to_unit(cx: &CrateContext, node_id: ast::NodeId) -> bool
|
|
|
|
{
|
2014-06-18 15:07:26 +12:00
|
|
|
// The is_local_to_unit flag indicates whether a function is local to the
|
|
|
|
// current compilation unit (i.e. if it is *static* in the C-sense). The
|
|
|
|
// *reachable* set should provide a good approximation of this, as it
|
|
|
|
// contains everything that might leak out of the current crate (by being
|
2015-04-24 11:38:53 +12:00
|
|
|
// externally visible or by being inlined into something externally
|
|
|
|
// visible). It might better to use the `exported_items` set from
|
|
|
|
// `driver::CrateAnalysis` in the future, but (atm) this set is not
|
|
|
|
// available in the translation pass.
|
2014-09-05 09:18:53 -07:00
|
|
|
!cx.reachable().contains(&node_id)
|
2014-02-20 20:44:29 -05:00
|
|
|
}
|
|
|
|
|
2014-07-19 00:45:17 +12:00
|
|
|
#[allow(non_snake_case)]
|
2013-06-14 11:59:49 -07:00
|
|
|
fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
|
|
|
|
return unsafe {
|
2013-12-15 23:35:12 +11:00
|
|
|
llvm::LLVMDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32)
|
2013-06-14 11:59:49 -07:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2014-12-03 14:48:18 -08:00
|
|
|
fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor {
|
2014-03-05 16:36:01 +02:00
|
|
|
let work_dir = &cx.sess().working_dir;
|
|
|
|
let compile_unit_name = match cx.sess().local_crate_source_file {
|
2014-01-27 14:58:40 +01:00
|
|
|
None => fallback_path(cx),
|
|
|
|
Some(ref abs_path) => {
|
|
|
|
if abs_path.is_relative() {
|
2014-03-05 16:36:01 +02:00
|
|
|
cx.sess().warn("debuginfo: Invalid path to crate's local root source file!");
|
2014-01-27 14:58:40 +01:00
|
|
|
fallback_path(cx)
|
|
|
|
} else {
|
2015-02-26 21:00:43 -08:00
|
|
|
match abs_path.relative_from(work_dir) {
|
2014-01-27 14:58:40 +01:00
|
|
|
Some(ref p) if p.is_relative() => {
|
2015-02-26 21:00:43 -08:00
|
|
|
if p.starts_with(Path::new("./")) {
|
|
|
|
path2cstr(p)
|
|
|
|
} else {
|
|
|
|
path2cstr(&Path::new(".").join(p))
|
2014-01-27 14:58:40 +01:00
|
|
|
}
|
2014-11-25 13:28:35 -08:00
|
|
|
}
|
2014-01-27 14:58:40 +01:00
|
|
|
_ => fallback_path(cx)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2013-06-19 16:30:35 +02:00
|
|
|
|
2014-12-20 00:09:35 -08:00
|
|
|
debug!("compile_unit_metadata: {:?}", compile_unit_name);
|
2014-04-23 15:56:58 -04:00
|
|
|
let producer = format!("rustc version {}",
|
|
|
|
(option_env!("CFG_VERSION")).expect("CFG_VERSION"));
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2014-06-14 22:50:07 +10:00
|
|
|
let compile_unit_name = compile_unit_name.as_ptr();
|
2015-02-26 21:00:43 -08:00
|
|
|
let work_dir = path2cstr(&work_dir);
|
2015-02-17 22:47:40 -08:00
|
|
|
let producer = CString::new(producer).unwrap();
|
2014-11-25 13:28:35 -08:00
|
|
|
let flags = "\0";
|
|
|
|
let split_name = "\0";
|
|
|
|
return unsafe {
|
|
|
|
llvm::LLVMDIBuilderCreateCompileUnit(
|
|
|
|
debug_context(cx).builder,
|
|
|
|
DW_LANG_RUST,
|
|
|
|
compile_unit_name,
|
|
|
|
work_dir.as_ptr(),
|
|
|
|
producer.as_ptr(),
|
|
|
|
cx.sess().opts.optimize != config::No,
|
|
|
|
flags.as_ptr() as *const _,
|
|
|
|
0,
|
|
|
|
split_name.as_ptr() as *const _)
|
|
|
|
};
|
2014-01-27 14:58:40 +01:00
|
|
|
|
|
|
|
fn fallback_path(cx: &CrateContext) -> CString {
|
2015-02-17 22:47:40 -08:00
|
|
|
CString::new(cx.link_meta().crate_name.clone()).unwrap()
|
2014-01-27 14:58:40 +01:00
|
|
|
}
|
2013-06-14 11:38:29 -07:00
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
2015-03-23 19:41:35 -05:00
|
|
|
variable_name: ast::Name,
|
2014-09-29 22:11:30 +03:00
|
|
|
variable_type: Ty<'tcx>,
|
|
|
|
scope_metadata: DIScope,
|
|
|
|
variable_access: VariableAccess,
|
|
|
|
variable_kind: VariableKind,
|
|
|
|
span: Span) {
|
2013-12-19 16:47:15 -08:00
|
|
|
let cx: &CrateContext = bcx.ccx();
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2014-03-20 22:10:44 -07:00
|
|
|
let filename = span_start(cx, span).file.name.clone();
|
2015-02-18 14:48:57 -05:00
|
|
|
let file_metadata = file_metadata(cx, &filename[..]);
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2015-03-23 19:41:35 -05:00
|
|
|
let name = token::get_name(variable_name);
|
2013-08-05 11:12:40 +02:00
|
|
|
let loc = span_start(cx, span);
|
|
|
|
let type_metadata = type_metadata(cx, variable_type, span);
|
2013-08-23 18:45:02 +02:00
|
|
|
|
2014-01-02 15:20:43 +01:00
|
|
|
let (argument_index, dwarf_tag) = match variable_kind {
|
|
|
|
ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),
|
2013-08-23 18:45:02 +02:00
|
|
|
LocalVariable |
|
2014-01-02 15:20:43 +01:00
|
|
|
CapturedVariable => (0, DW_TAG_auto_variable)
|
|
|
|
};
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2015-02-17 22:47:40 -08:00
|
|
|
let name = CString::new(name.as_bytes()).unwrap();
|
2015-03-18 09:14:54 -07:00
|
|
|
match (variable_access, &[][..]) {
|
2015-01-30 19:25:07 +01:00
|
|
|
(DirectVariable { alloca }, address_operations) |
|
|
|
|
(IndirectVariable {alloca, address_operations}, _) => {
|
|
|
|
let metadata = unsafe {
|
|
|
|
llvm::LLVMDIBuilderCreateVariable(
|
2014-11-25 13:28:35 -08:00
|
|
|
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)
|
2015-01-30 19:25:07 +01:00
|
|
|
};
|
|
|
|
set_debug_location(cx, InternalDebugLocation::new(scope_metadata,
|
2014-12-11 13:53:30 +01:00
|
|
|
loc.line,
|
2015-01-21 11:50:34 -08:00
|
|
|
loc.col.to_usize()));
|
2015-01-30 19:25:07 +01:00
|
|
|
unsafe {
|
|
|
|
let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
|
|
|
|
DIB(cx),
|
|
|
|
alloca,
|
|
|
|
metadata,
|
|
|
|
address_operations.as_ptr(),
|
|
|
|
address_operations.len() as c_uint,
|
|
|
|
bcx.llbb);
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2015-01-30 19:25:07 +01:00
|
|
|
llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr);
|
|
|
|
}
|
|
|
|
}
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
2013-08-23 18:45:02 +02:00
|
|
|
|
|
|
|
match variable_kind {
|
|
|
|
ArgumentVariable(_) | CapturedVariable => {
|
2013-12-20 20:57:25 -08:00
|
|
|
assert!(!bcx.fcx
|
|
|
|
.debug_context
|
|
|
|
.get_ref(cx, span)
|
|
|
|
.source_locations_enabled
|
|
|
|
.get());
|
2013-08-23 18:45:02 +02:00
|
|
|
set_debug_location(cx, UnknownLocation);
|
|
|
|
}
|
2013-09-09 17:58:58 +02:00
|
|
|
_ => { /* nothing to do */ }
|
2013-08-23 18:45:02 +02:00
|
|
|
}
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
|
2013-12-19 16:47:15 -08:00
|
|
|
fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
|
2014-11-12 15:51:51 -08:00
|
|
|
match debug_context(cx).created_files.borrow().get(full_path) {
|
2014-03-20 19:49:20 -07:00
|
|
|
Some(file_metadata) => return *file_metadata,
|
|
|
|
None => ()
|
2011-11-10 00:55:09 -05:00
|
|
|
}
|
2011-12-14 15:14:06 -05:00
|
|
|
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("file_metadata: {}", full_path);
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-09-26 17:21:59 -07:00
|
|
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
2015-02-26 21:00:43 -08:00
|
|
|
let work_dir = cx.sess().working_dir.to_str().unwrap();
|
2013-06-11 12:41:09 -07:00
|
|
|
let file_name =
|
2013-06-10 18:34:51 -07:00
|
|
|
if full_path.starts_with(work_dir) {
|
2015-01-25 10:58:43 +00:00
|
|
|
&full_path[work_dir.len() + 1..full_path.len()]
|
2013-06-10 18:34:51 -07:00
|
|
|
} else {
|
|
|
|
full_path
|
|
|
|
};
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2015-02-17 22:47:40 -08:00
|
|
|
let file_name = CString::new(file_name).unwrap();
|
|
|
|
let work_dir = CString::new(work_dir).unwrap();
|
2014-11-25 13:28:35 -08:00
|
|
|
let file_metadata = unsafe {
|
|
|
|
llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name.as_ptr(),
|
|
|
|
work_dir.as_ptr())
|
|
|
|
};
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-12-18 18:46:40 -08:00
|
|
|
let mut created_files = debug_context(cx).created_files.borrow_mut();
|
2014-05-25 03:17:19 -07:00
|
|
|
created_files.insert(full_path.to_string(), file_metadata);
|
2013-07-10 18:35:38 +02:00
|
|
|
return file_metadata;
|
2011-11-10 00:55:09 -05:00
|
|
|
}
|
|
|
|
|
2013-08-05 11:12:40 +02:00
|
|
|
/// Finds the scope metadata node for the given AST node.
|
|
|
|
fn scope_metadata(fcx: &FunctionContext,
|
|
|
|
node_id: ast::NodeId,
|
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
|
|
|
error_reporting_span: Span)
|
2013-08-23 18:45:02 +02:00
|
|
|
-> DIScope {
|
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
|
|
|
let scope_map = &fcx.debug_context
|
|
|
|
.get_ref(fcx.ccx, error_reporting_span)
|
|
|
|
.scope_map;
|
2014-11-07 14:35:18 -05:00
|
|
|
match scope_map.borrow().get(&node_id).cloned() {
|
2013-08-05 11:12:40 +02:00
|
|
|
Some(scope_metadata) => scope_metadata,
|
|
|
|
None => {
|
2014-09-05 09:18:53 -07:00
|
|
|
let node = fcx.ccx.tcx().map.get(node_id);
|
2013-06-11 12:41:09 -07: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
|
|
|
fcx.ccx.sess().span_bug(error_reporting_span,
|
2015-01-07 11:58:31 -05:00
|
|
|
&format!("debuginfo: Could not find scope info for node {:?}",
|
2015-02-20 14:08:14 -05:00
|
|
|
node));
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
}
|
2011-11-15 21:11:22 -05:00
|
|
|
}
|
|
|
|
|
2014-10-24 21:14:37 +02:00
|
|
|
fn diverging_type_metadata(cx: &CrateContext) -> DIType {
|
2014-11-25 13:28:35 -08:00
|
|
|
unsafe {
|
|
|
|
llvm::LLVMDIBuilderCreateBasicType(
|
|
|
|
DIB(cx),
|
|
|
|
"!\0".as_ptr() as *const _,
|
|
|
|
bytes_to_bits(0),
|
|
|
|
bytes_to_bits(0),
|
|
|
|
DW_ATE_unsigned)
|
|
|
|
}
|
2014-10-24 21:14:37 +02:00
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|
|
|
t: Ty<'tcx>) -> DIType {
|
2013-06-18 13:06:41 +02:00
|
|
|
|
2014-12-20 00:09:35 -08:00
|
|
|
debug!("basic_type_metadata: {:?}", t);
|
2013-06-14 11:38:29 -07:00
|
|
|
|
2014-10-31 10:51:16 +02:00
|
|
|
let (name, encoding) = match t.sty {
|
2014-11-09 16:14:15 +01:00
|
|
|
ty::ty_tup(ref elements) if elements.is_empty() =>
|
|
|
|
("()".to_string(), DW_ATE_unsigned),
|
2014-05-25 03:10:11 -07:00
|
|
|
ty::ty_bool => ("bool".to_string(), DW_ATE_boolean),
|
|
|
|
ty::ty_char => ("char".to_string(), DW_ATE_unsigned_char),
|
2013-02-27 13:35:56 -05:00
|
|
|
ty::ty_int(int_ty) => match int_ty {
|
2015-03-24 13:26:16 -07:00
|
|
|
ast::TyIs => ("isize".to_string(), DW_ATE_signed),
|
2014-05-25 03:10:11 -07:00
|
|
|
ast::TyI8 => ("i8".to_string(), DW_ATE_signed),
|
|
|
|
ast::TyI16 => ("i16".to_string(), DW_ATE_signed),
|
|
|
|
ast::TyI32 => ("i32".to_string(), DW_ATE_signed),
|
|
|
|
ast::TyI64 => ("i64".to_string(), DW_ATE_signed)
|
2013-02-27 13:35:56 -05:00
|
|
|
},
|
|
|
|
ty::ty_uint(uint_ty) => match uint_ty {
|
2015-03-24 13:26:16 -07:00
|
|
|
ast::TyUs => ("usize".to_string(), DW_ATE_unsigned),
|
2014-05-25 03:10:11 -07:00
|
|
|
ast::TyU8 => ("u8".to_string(), DW_ATE_unsigned),
|
|
|
|
ast::TyU16 => ("u16".to_string(), DW_ATE_unsigned),
|
|
|
|
ast::TyU32 => ("u32".to_string(), DW_ATE_unsigned),
|
|
|
|
ast::TyU64 => ("u64".to_string(), DW_ATE_unsigned)
|
2013-02-27 13:35:56 -05:00
|
|
|
},
|
|
|
|
ty::ty_float(float_ty) => match float_ty {
|
2014-05-25 03:10:11 -07:00
|
|
|
ast::TyF32 => ("f32".to_string(), DW_ATE_float),
|
|
|
|
ast::TyF64 => ("f64".to_string(), DW_ATE_float),
|
2013-02-27 13:35:56 -05:00
|
|
|
},
|
2014-03-05 16:36:01 +02:00
|
|
|
_ => cx.sess().bug("debuginfo::basic_type_metadata - t is invalid type")
|
2013-02-27 13:35:56 -05:00
|
|
|
};
|
2011-12-14 15:14:06 -05:00
|
|
|
|
2013-07-10 18:35:38 +02:00
|
|
|
let llvm_type = type_of::type_of(cx, t);
|
|
|
|
let (size, align) = size_and_align_of(cx, llvm_type);
|
2015-02-17 22:47:40 -08:00
|
|
|
let name = CString::new(name).unwrap();
|
2014-11-25 13:28:35 -08:00
|
|
|
let ty_metadata = unsafe {
|
|
|
|
llvm::LLVMDIBuilderCreateBasicType(
|
|
|
|
DIB(cx),
|
|
|
|
name.as_ptr(),
|
|
|
|
bytes_to_bits(size),
|
|
|
|
bytes_to_bits(align),
|
|
|
|
encoding)
|
|
|
|
};
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-07-10 18:35:38 +02:00
|
|
|
return ty_metadata;
|
2011-12-07 16:08:25 -05:00
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
fn pointer_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|
|
|
pointer_type: Ty<'tcx>,
|
|
|
|
pointee_type_metadata: DIType)
|
|
|
|
-> DIType {
|
2013-07-10 18:35:38 +02:00
|
|
|
let pointer_llvm_type = type_of::type_of(cx, pointer_type);
|
|
|
|
let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
|
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 name = compute_debuginfo_type_name(cx, pointer_type, false);
|
2015-02-17 22:47:40 -08:00
|
|
|
let name = CString::new(name).unwrap();
|
2014-11-25 13:28:35 -08:00
|
|
|
let ptr_metadata = unsafe {
|
|
|
|
llvm::LLVMDIBuilderCreatePointerType(
|
|
|
|
DIB(cx),
|
|
|
|
pointee_type_metadata,
|
|
|
|
bytes_to_bits(pointer_size),
|
|
|
|
bytes_to_bits(pointer_align),
|
|
|
|
name.as_ptr())
|
|
|
|
};
|
2013-07-10 18:35:38 +02:00
|
|
|
return ptr_metadata;
|
2013-06-14 11:38:29 -07:00
|
|
|
}
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
//=-----------------------------------------------------------------------------
|
2014-05-15 14:13:33 +02:00
|
|
|
// Common facilities for record-like types (structs, enums, tuples)
|
2014-06-18 15:07:26 +12:00
|
|
|
//=-----------------------------------------------------------------------------
|
2014-05-15 14:13:33 +02:00
|
|
|
|
|
|
|
enum MemberOffset {
|
2015-03-25 17:06:52 -07:00
|
|
|
FixedMemberOffset { bytes: usize },
|
2015-04-24 11:38:53 +12:00
|
|
|
// For ComputedMemberOffset, the offset is read from the llvm type definition.
|
2014-05-15 14:13:33 +02:00
|
|
|
ComputedMemberOffset
|
|
|
|
}
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// Description of a type member, which can either be a regular field (as in
|
2015-04-24 11:38:53 +12:00
|
|
|
// structs or tuples) or an enum variant.
|
2014-05-15 14:13:33 +02:00
|
|
|
struct MemberDescription {
|
|
|
|
name: String,
|
|
|
|
llvm_type: Type,
|
|
|
|
type_metadata: DIType,
|
|
|
|
offset: MemberOffset,
|
2014-07-30 15:56:42 +02:00
|
|
|
flags: c_uint
|
2014-05-15 14:13:33 +02:00
|
|
|
}
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// A factory for MemberDescriptions. It produces a list of member descriptions
|
|
|
|
// for some record-like type. MemberDescriptionFactories are used to defer the
|
|
|
|
// creation of type member descriptions in order to break cycles arising from
|
|
|
|
// recursive type definitions.
|
2014-09-29 22:11:30 +03:00
|
|
|
enum MemberDescriptionFactory<'tcx> {
|
|
|
|
StructMDF(StructMemberDescriptionFactory<'tcx>),
|
|
|
|
TupleMDF(TupleMemberDescriptionFactory<'tcx>),
|
|
|
|
EnumMDF(EnumMemberDescriptionFactory<'tcx>),
|
|
|
|
VariantMDF(VariantMemberDescriptionFactory<'tcx>)
|
2014-02-07 00:38:33 +02:00
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
impl<'tcx> MemberDescriptionFactory<'tcx> {
|
|
|
|
fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
|
|
|
|
-> Vec<MemberDescription> {
|
2014-02-07 00:38:33 +02:00
|
|
|
match *self {
|
2014-05-15 14:13:33 +02:00
|
|
|
StructMDF(ref this) => {
|
2014-02-07 00:38:33 +02:00
|
|
|
this.create_member_descriptions(cx)
|
|
|
|
}
|
2014-05-15 14:13:33 +02:00
|
|
|
TupleMDF(ref this) => {
|
2014-02-07 00:38:33 +02:00
|
|
|
this.create_member_descriptions(cx)
|
|
|
|
}
|
2014-05-15 14:13:33 +02:00
|
|
|
EnumMDF(ref this) => {
|
2014-02-07 00:38:33 +02:00
|
|
|
this.create_member_descriptions(cx)
|
|
|
|
}
|
2014-05-15 14:13:33 +02:00
|
|
|
VariantMDF(ref this) => {
|
2014-02-07 00:38:33 +02:00
|
|
|
this.create_member_descriptions(cx)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-09-18 18:18:45 -07:00
|
|
|
}
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// A description of some recursive type. It can either be already finished (as
|
|
|
|
// with FinalMetadata) or it is not yet finished, but contains all information
|
2015-04-24 11:38:53 +12:00
|
|
|
// needed to generate the missing parts of the description. See the
|
|
|
|
// documentation section on Recursive Types at the top of this file for more
|
|
|
|
// information.
|
2014-09-29 22:11:30 +03:00
|
|
|
enum RecursiveTypeDescription<'tcx> {
|
2014-05-15 14:13:33 +02:00
|
|
|
UnfinishedMetadata {
|
2014-09-29 22:11:30 +03:00
|
|
|
unfinished_type: Ty<'tcx>,
|
2014-05-30 17:09:16 +02:00
|
|
|
unique_type_id: UniqueTypeId,
|
2014-05-15 14:13:33 +02:00
|
|
|
metadata_stub: DICompositeType,
|
|
|
|
llvm_type: Type,
|
2014-09-29 22:11:30 +03:00
|
|
|
member_description_factory: MemberDescriptionFactory<'tcx>,
|
2014-05-15 14:13:33 +02:00
|
|
|
},
|
|
|
|
FinalMetadata(DICompositeType)
|
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
fn create_and_register_recursive_type_forward_declaration<'a, 'tcx>(
|
|
|
|
cx: &CrateContext<'a, 'tcx>,
|
|
|
|
unfinished_type: Ty<'tcx>,
|
2014-05-30 17:09:16 +02:00
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
metadata_stub: DICompositeType,
|
|
|
|
llvm_type: Type,
|
2014-09-29 22:11:30 +03:00
|
|
|
member_description_factory: MemberDescriptionFactory<'tcx>)
|
|
|
|
-> RecursiveTypeDescription<'tcx> {
|
2014-05-30 17:09:16 +02:00
|
|
|
|
|
|
|
// Insert the stub into the TypeMap in order to allow for recursive references
|
|
|
|
let mut type_map = debug_context(cx).type_map.borrow_mut();
|
|
|
|
type_map.register_unique_id_with_metadata(cx, unique_type_id, metadata_stub);
|
|
|
|
type_map.register_type_with_metadata(cx, unfinished_type, metadata_stub);
|
|
|
|
|
|
|
|
UnfinishedMetadata {
|
|
|
|
unfinished_type: unfinished_type,
|
|
|
|
unique_type_id: unique_type_id,
|
|
|
|
metadata_stub: metadata_stub,
|
|
|
|
llvm_type: llvm_type,
|
|
|
|
member_description_factory: member_description_factory,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
impl<'tcx> RecursiveTypeDescription<'tcx> {
|
2014-06-18 15:07:26 +12:00
|
|
|
// Finishes up the description of the type in question (mostly by providing
|
2015-04-24 11:38:53 +12:00
|
|
|
// descriptions of the fields of the given type) and returns the final type
|
|
|
|
// metadata.
|
2014-09-29 22:11:30 +03:00
|
|
|
fn finalize<'a>(&self, cx: &CrateContext<'a, 'tcx>) -> MetadataCreationResult {
|
2014-05-15 14:13:33 +02:00
|
|
|
match *self {
|
2014-06-16 14:28:05 +02:00
|
|
|
FinalMetadata(metadata) => MetadataCreationResult::new(metadata, false),
|
2014-05-15 14:13:33 +02:00
|
|
|
UnfinishedMetadata {
|
2014-05-30 17:09:16 +02:00
|
|
|
unfinished_type,
|
|
|
|
unique_type_id,
|
2014-05-15 14:13:33 +02:00
|
|
|
metadata_stub,
|
|
|
|
llvm_type,
|
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
|
|
|
ref member_description_factory,
|
|
|
|
..
|
2014-05-15 14:13:33 +02:00
|
|
|
} => {
|
2014-06-18 15:07:26 +12:00
|
|
|
// Make sure that we have a forward declaration of the type in
|
|
|
|
// the TypeMap so that recursive references are possible. This
|
|
|
|
// will always be the case if the RecursiveTypeDescription has
|
|
|
|
// been properly created through the
|
2015-04-24 11:38:53 +12:00
|
|
|
// create_and_register_recursive_type_forward_declaration()
|
|
|
|
// function.
|
2014-05-30 17:09:16 +02:00
|
|
|
{
|
|
|
|
let type_map = debug_context(cx).type_map.borrow();
|
|
|
|
if type_map.find_metadata_for_unique_id(unique_type_id).is_none() ||
|
|
|
|
type_map.find_metadata_for_type(unfinished_type).is_none() {
|
2015-01-07 11:58:31 -05:00
|
|
|
cx.sess().bug(&format!("Forward declaration of potentially recursive type \
|
2014-05-30 17:09:16 +02:00
|
|
|
'{}' was not found in TypeMap!",
|
2014-06-21 03:39:03 -07:00
|
|
|
ppaux::ty_to_string(cx.tcx(), unfinished_type))
|
2015-02-20 14:08:14 -05:00
|
|
|
);
|
2014-05-30 17:09:16 +02:00
|
|
|
}
|
|
|
|
}
|
2014-05-15 14:13:33 +02:00
|
|
|
|
|
|
|
// ... then create the member descriptions ...
|
2014-06-18 15:07:26 +12:00
|
|
|
let member_descriptions =
|
|
|
|
member_description_factory.create_member_descriptions(cx);
|
2014-05-15 14:13:33 +02:00
|
|
|
|
|
|
|
// ... and attach them to the stub to complete it.
|
|
|
|
set_members_of_composite_type(cx,
|
|
|
|
metadata_stub,
|
|
|
|
llvm_type,
|
2015-02-18 14:48:57 -05:00
|
|
|
&member_descriptions[..]);
|
2014-06-16 14:28:05 +02:00
|
|
|
return MetadataCreationResult::new(metadata_stub, true);
|
2014-05-15 14:13:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
//=-----------------------------------------------------------------------------
|
2014-05-15 14:13:33 +02:00
|
|
|
// Structs
|
2014-06-18 15:07:26 +12:00
|
|
|
//=-----------------------------------------------------------------------------
|
2014-05-15 14:13:33 +02:00
|
|
|
|
|
|
|
// Creates MemberDescriptions for the fields of a struct
|
2014-09-29 22:11:30 +03:00
|
|
|
struct StructMemberDescriptionFactory<'tcx> {
|
|
|
|
fields: Vec<ty::field<'tcx>>,
|
2014-03-26 17:53:59 +01:00
|
|
|
is_simd: bool,
|
2013-09-18 18:18:45 -07:00
|
|
|
span: Span,
|
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
impl<'tcx> StructMemberDescriptionFactory<'tcx> {
|
|
|
|
fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
|
|
|
|
-> Vec<MemberDescription> {
|
2015-03-24 16:53:34 -07:00
|
|
|
if self.fields.is_empty() {
|
2014-03-26 17:53:59 +01:00
|
|
|
return Vec::new();
|
|
|
|
}
|
|
|
|
|
|
|
|
let field_size = if self.is_simd {
|
2015-03-25 17:06:52 -07:00
|
|
|
machine::llsize_of_alloc(cx, type_of::type_of(cx, self.fields[0].mt.ty)) as usize
|
2014-03-26 17:53:59 +01:00
|
|
|
} else {
|
|
|
|
0xdeadbeef
|
|
|
|
};
|
|
|
|
|
|
|
|
self.fields.iter().enumerate().map(|(i, field)| {
|
2014-09-30 19:11:34 -05:00
|
|
|
let name = if field.name == special_idents::unnamed_field.name {
|
2015-04-06 11:39:51 -07:00
|
|
|
format!("__{}", i)
|
2013-09-18 18:18:45 -07:00
|
|
|
} else {
|
2015-02-04 01:04:50 +01:00
|
|
|
token::get_name(field.name).to_string()
|
2013-09-18 18:18:45 -07:00
|
|
|
};
|
|
|
|
|
2014-03-26 17:53:59 +01:00
|
|
|
let offset = if self.is_simd {
|
|
|
|
assert!(field_size != 0xdeadbeef);
|
2014-05-15 14:13:33 +02:00
|
|
|
FixedMemberOffset { bytes: i * field_size }
|
2014-03-26 17:53:59 +01:00
|
|
|
} else {
|
|
|
|
ComputedMemberOffset
|
|
|
|
};
|
|
|
|
|
2013-09-18 18:18:45 -07:00
|
|
|
MemberDescription {
|
|
|
|
name: name,
|
|
|
|
llvm_type: type_of::type_of(cx, field.mt.ty),
|
|
|
|
type_metadata: type_metadata(cx, field.mt.ty, self.span),
|
2014-03-26 17:53:59 +01:00
|
|
|
offset: offset,
|
2014-07-30 15:56:42 +02:00
|
|
|
flags: FLAGS_NONE,
|
2013-09-18 18:18:45 -07:00
|
|
|
}
|
2014-03-28 20:42:34 +01:00
|
|
|
}).collect()
|
2013-09-18 18:18:45 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|
|
|
struct_type: Ty<'tcx>,
|
|
|
|
def_id: ast::DefId,
|
|
|
|
substs: &subst::Substs<'tcx>,
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
span: Span)
|
|
|
|
-> RecursiveTypeDescription<'tcx> {
|
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 struct_name = compute_debuginfo_type_name(cx, struct_type, false);
|
2013-06-26 16:00:42 +02:00
|
|
|
let struct_llvm_type = type_of::type_of(cx, struct_type);
|
2013-09-13 16:26:35 +02:00
|
|
|
|
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 (containing_scope, _) = get_namespace_and_span_for_item(cx, def_id);
|
2013-09-11 16:37:43 +02:00
|
|
|
|
|
|
|
let struct_metadata_stub = create_struct_stub(cx,
|
|
|
|
struct_llvm_type,
|
2015-02-18 14:48:57 -05:00
|
|
|
&struct_name[..],
|
2014-05-30 17:09:16 +02:00
|
|
|
unique_type_id,
|
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
|
|
|
containing_scope);
|
2013-09-11 16:37:43 +02:00
|
|
|
|
2015-01-21 17:10:02 +01:00
|
|
|
let mut fields = ty::struct_fields(cx.tcx(), def_id, substs);
|
|
|
|
|
|
|
|
// The `Ty` values returned by `ty::struct_fields` can still contain
|
|
|
|
// `ty_projection` variants, so normalize those away.
|
2015-01-31 20:02:00 -05:00
|
|
|
for field in &mut fields {
|
2015-01-21 17:10:02 +01:00
|
|
|
field.mt.ty = monomorphize::normalize_associated_type(cx.tcx(), &field.mt.ty);
|
|
|
|
}
|
2013-09-09 17:58:58 +02:00
|
|
|
|
2014-05-30 17:09:16 +02:00
|
|
|
create_and_register_recursive_type_forward_declaration(
|
|
|
|
cx,
|
|
|
|
struct_type,
|
|
|
|
unique_type_id,
|
|
|
|
struct_metadata_stub,
|
|
|
|
struct_llvm_type,
|
|
|
|
StructMDF(StructMemberDescriptionFactory {
|
2013-09-18 18:18:45 -07:00
|
|
|
fields: fields,
|
2014-03-26 17:53:59 +01:00
|
|
|
is_simd: ty::type_is_simd(cx.tcx(), struct_type),
|
2013-09-18 18:18:45 -07:00
|
|
|
span: span,
|
2014-05-30 17:09:16 +02:00
|
|
|
})
|
|
|
|
)
|
2013-09-11 16:37:43 +02:00
|
|
|
}
|
2013-09-09 17:58:58 +02:00
|
|
|
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
//=-----------------------------------------------------------------------------
|
2014-05-15 14:13:33 +02:00
|
|
|
// Tuples
|
2014-06-18 15:07:26 +12:00
|
|
|
//=-----------------------------------------------------------------------------
|
2013-06-26 16:00:42 +02:00
|
|
|
|
2014-05-15 14:13:33 +02:00
|
|
|
// Creates MemberDescriptions for the fields of a tuple
|
2014-09-29 22:11:30 +03:00
|
|
|
struct TupleMemberDescriptionFactory<'tcx> {
|
|
|
|
component_types: Vec<Ty<'tcx>>,
|
2013-09-18 18:18:45 -07:00
|
|
|
span: Span,
|
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
impl<'tcx> TupleMemberDescriptionFactory<'tcx> {
|
|
|
|
fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
|
|
|
|
-> Vec<MemberDescription> {
|
2015-04-06 11:39:51 -07:00
|
|
|
self.component_types
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.map(|(i, &component_type)| {
|
2013-09-18 18:18:45 -07:00
|
|
|
MemberDescription {
|
2015-04-06 11:39:51 -07:00
|
|
|
name: format!("__{}", i),
|
2013-09-18 18:18:45 -07:00
|
|
|
llvm_type: type_of::type_of(cx, component_type),
|
|
|
|
type_metadata: type_metadata(cx, component_type, self.span),
|
|
|
|
offset: ComputedMemberOffset,
|
2014-07-30 15:56:42 +02:00
|
|
|
flags: FLAGS_NONE,
|
2013-09-18 18:18:45 -07:00
|
|
|
}
|
2014-03-28 20:42:34 +01:00
|
|
|
}).collect()
|
2013-09-18 18:18:45 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
fn prepare_tuple_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|
|
|
tuple_type: Ty<'tcx>,
|
|
|
|
component_types: &[Ty<'tcx>],
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
span: Span)
|
|
|
|
-> RecursiveTypeDescription<'tcx> {
|
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 tuple_name = compute_debuginfo_type_name(cx, tuple_type, false);
|
2013-06-26 16:00:42 +02:00
|
|
|
let tuple_llvm_type = type_of::type_of(cx, tuple_type);
|
|
|
|
|
2014-05-30 17:09:16 +02:00
|
|
|
create_and_register_recursive_type_forward_declaration(
|
|
|
|
cx,
|
|
|
|
tuple_type,
|
|
|
|
unique_type_id,
|
|
|
|
create_struct_stub(cx,
|
|
|
|
tuple_llvm_type,
|
2015-02-18 14:48:57 -05:00
|
|
|
&tuple_name[..],
|
2014-05-30 17:09:16 +02:00
|
|
|
unique_type_id,
|
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
|
|
|
UNKNOWN_SCOPE_METADATA),
|
2014-05-30 17:09:16 +02:00
|
|
|
tuple_llvm_type,
|
|
|
|
TupleMDF(TupleMemberDescriptionFactory {
|
2014-10-14 23:05:01 -07:00
|
|
|
component_types: component_types.to_vec(),
|
2013-09-18 18:18:45 -07:00
|
|
|
span: span,
|
2014-02-07 00:38:33 +02:00
|
|
|
})
|
2014-05-30 17:09:16 +02:00
|
|
|
)
|
2013-09-18 18:18:45 -07:00
|
|
|
}
|
|
|
|
|
2014-05-15 14:13:33 +02:00
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
//=-----------------------------------------------------------------------------
|
2014-05-15 14:13:33 +02:00
|
|
|
// Enums
|
2014-06-18 15:07:26 +12:00
|
|
|
//=-----------------------------------------------------------------------------
|
2014-05-15 14:13:33 +02:00
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// Describes the members of an enum value: An enum is described as a union of
|
|
|
|
// structs in DWARF. This MemberDescriptionFactory provides the description for
|
2015-04-24 11:38:53 +12:00
|
|
|
// the members of this union; so for every variant of the given enum, this
|
|
|
|
// factory will produce one MemberDescription (all with no name and a fixed
|
|
|
|
// offset of zero bytes).
|
2014-09-29 22:11:30 +03:00
|
|
|
struct EnumMemberDescriptionFactory<'tcx> {
|
|
|
|
enum_type: Ty<'tcx>,
|
|
|
|
type_rep: Rc<adt::Repr<'tcx>>,
|
|
|
|
variants: Rc<Vec<Rc<ty::VariantInfo<'tcx>>>>,
|
2014-05-15 15:33:51 +02:00
|
|
|
discriminant_type_metadata: Option<DIType>,
|
2013-09-18 18:18:45 -07:00
|
|
|
containing_scope: DIScope,
|
|
|
|
file_metadata: DIFile,
|
|
|
|
span: Span,
|
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
|
|
|
|
fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
|
|
|
|
-> Vec<MemberDescription> {
|
2014-05-15 15:33:51 +02:00
|
|
|
match *self.type_rep {
|
2014-06-14 15:55:55 +02:00
|
|
|
adt::General(_, ref struct_defs, _) => {
|
2014-05-15 15:33:51 +02:00
|
|
|
let discriminant_info = RegularDiscriminant(self.discriminant_type_metadata
|
|
|
|
.expect(""));
|
|
|
|
|
|
|
|
struct_defs
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.map(|(i, struct_def)| {
|
2014-06-18 15:07:26 +12:00
|
|
|
let (variant_type_metadata,
|
|
|
|
variant_llvm_type,
|
|
|
|
member_desc_factory) =
|
2014-05-15 15:33:51 +02:00
|
|
|
describe_enum_variant(cx,
|
2014-05-30 17:09:16 +02:00
|
|
|
self.enum_type,
|
2014-05-15 15:33:51 +02:00
|
|
|
struct_def,
|
2014-10-14 23:05:01 -07:00
|
|
|
&*(*self.variants)[i],
|
2014-05-15 15:33:51 +02:00
|
|
|
discriminant_info,
|
|
|
|
self.containing_scope,
|
|
|
|
self.span);
|
|
|
|
|
|
|
|
let member_descriptions = member_desc_factory
|
|
|
|
.create_member_descriptions(cx);
|
|
|
|
|
|
|
|
set_members_of_composite_type(cx,
|
|
|
|
variant_type_metadata,
|
|
|
|
variant_llvm_type,
|
2015-02-18 14:48:57 -05:00
|
|
|
&member_descriptions[..]);
|
2014-05-15 15:33:51 +02:00
|
|
|
MemberDescription {
|
|
|
|
name: "".to_string(),
|
|
|
|
llvm_type: variant_llvm_type,
|
|
|
|
type_metadata: variant_type_metadata,
|
|
|
|
offset: FixedMemberOffset { bytes: 0 },
|
2014-07-30 15:56:42 +02:00
|
|
|
flags: FLAGS_NONE
|
2014-05-15 15:33:51 +02:00
|
|
|
}
|
|
|
|
}).collect()
|
|
|
|
},
|
|
|
|
adt::Univariant(ref struct_def, _) => {
|
|
|
|
assert!(self.variants.len() <= 1);
|
|
|
|
|
2015-03-24 16:53:34 -07:00
|
|
|
if self.variants.is_empty() {
|
2014-05-15 15:33:51 +02:00
|
|
|
vec![]
|
|
|
|
} else {
|
2014-06-18 15:07:26 +12:00
|
|
|
let (variant_type_metadata,
|
|
|
|
variant_llvm_type,
|
|
|
|
member_description_factory) =
|
2014-05-15 15:33:51 +02:00
|
|
|
describe_enum_variant(cx,
|
2014-05-30 17:09:16 +02:00
|
|
|
self.enum_type,
|
2014-05-15 15:33:51 +02:00
|
|
|
struct_def,
|
2014-10-14 23:05:01 -07:00
|
|
|
&*(*self.variants)[0],
|
2014-05-15 15:33:51 +02:00
|
|
|
NoDiscriminant,
|
|
|
|
self.containing_scope,
|
|
|
|
self.span);
|
|
|
|
|
|
|
|
let member_descriptions =
|
|
|
|
member_description_factory.create_member_descriptions(cx);
|
|
|
|
|
|
|
|
set_members_of_composite_type(cx,
|
|
|
|
variant_type_metadata,
|
|
|
|
variant_llvm_type,
|
2015-02-18 14:48:57 -05:00
|
|
|
&member_descriptions[..]);
|
2014-05-15 15:33:51 +02:00
|
|
|
vec![
|
|
|
|
MemberDescription {
|
|
|
|
name: "".to_string(),
|
|
|
|
llvm_type: variant_llvm_type,
|
|
|
|
type_metadata: variant_type_metadata,
|
|
|
|
offset: FixedMemberOffset { bytes: 0 },
|
2014-07-30 15:56:42 +02:00
|
|
|
flags: FLAGS_NONE
|
2014-05-15 15:33:51 +02:00
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
adt::RawNullablePointer { nndiscr: non_null_variant_index, nnty, .. } => {
|
2014-06-18 15:07:26 +12:00
|
|
|
// As far as debuginfo is concerned, the pointer this enum
|
|
|
|
// represents is still wrapped in a struct. This is to make the
|
|
|
|
// DWARF representation of enums uniform.
|
2014-05-15 15:33:51 +02:00
|
|
|
|
2014-06-09 00:00:52 -04:00
|
|
|
// First create a description of the artificial wrapper struct:
|
2015-03-25 17:06:52 -07:00
|
|
|
let non_null_variant = &(*self.variants)[non_null_variant_index as usize];
|
2014-09-30 19:11:34 -05:00
|
|
|
let non_null_variant_name = token::get_name(non_null_variant.name);
|
2014-05-15 15:33:51 +02:00
|
|
|
|
|
|
|
// The llvm type and metadata of the pointer
|
|
|
|
let non_null_llvm_type = type_of::type_of(cx, nnty);
|
|
|
|
let non_null_type_metadata = type_metadata(cx, nnty, self.span);
|
|
|
|
|
|
|
|
// The type of the artificial struct wrapping the pointer
|
2014-06-18 15:07:26 +12:00
|
|
|
let artificial_struct_llvm_type = Type::struct_(cx,
|
|
|
|
&[non_null_llvm_type],
|
|
|
|
false);
|
2014-05-15 15:33:51 +02:00
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// For the metadata of the wrapper struct, we need to create a
|
|
|
|
// MemberDescription of the struct's single field.
|
2014-05-15 15:33:51 +02:00
|
|
|
let sole_struct_member_description = MemberDescription {
|
|
|
|
name: match non_null_variant.arg_names {
|
2015-03-23 19:41:35 -05:00
|
|
|
Some(ref names) => token::get_name(names[0]).to_string(),
|
2015-04-06 11:39:51 -07:00
|
|
|
None => "__0".to_string()
|
2014-05-15 15:33:51 +02:00
|
|
|
},
|
|
|
|
llvm_type: non_null_llvm_type,
|
|
|
|
type_metadata: non_null_type_metadata,
|
|
|
|
offset: FixedMemberOffset { bytes: 0 },
|
2014-07-30 15:56:42 +02:00
|
|
|
flags: FLAGS_NONE
|
2014-05-15 15:33:51 +02:00
|
|
|
};
|
|
|
|
|
2014-05-30 17:09:16 +02:00
|
|
|
let unique_type_id = debug_context(cx).type_map
|
|
|
|
.borrow_mut()
|
|
|
|
.get_unique_type_id_of_enum_variant(
|
|
|
|
cx,
|
|
|
|
self.enum_type,
|
2015-02-04 21:48:12 +01:00
|
|
|
&non_null_variant_name);
|
2014-05-30 17:09:16 +02:00
|
|
|
|
2014-05-15 15:33:51 +02:00
|
|
|
// Now we can create the metadata of the artificial struct
|
|
|
|
let artificial_struct_metadata =
|
|
|
|
composite_type_metadata(cx,
|
|
|
|
artificial_struct_llvm_type,
|
2015-02-04 21:48:12 +01:00
|
|
|
&non_null_variant_name,
|
2014-05-30 17:09:16 +02:00
|
|
|
unique_type_id,
|
2014-05-15 15:33:51 +02:00
|
|
|
&[sole_struct_member_description],
|
|
|
|
self.containing_scope,
|
|
|
|
self.file_metadata,
|
|
|
|
codemap::DUMMY_SP);
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// Encode the information about the null variant in the union
|
|
|
|
// member's name.
|
2015-03-25 17:06:52 -07:00
|
|
|
let null_variant_index = (1 - non_null_variant_index) as usize;
|
2014-09-30 19:11:34 -05:00
|
|
|
let null_variant_name = token::get_name((*self.variants)[null_variant_index].name);
|
2014-04-21 17:58:52 -04:00
|
|
|
let union_member_name = format!("RUST$ENCODED$ENUM${}${}",
|
2015-01-25 10:58:43 +00:00
|
|
|
0,
|
2014-04-21 17:58:52 -04:00
|
|
|
null_variant_name);
|
2014-05-15 15:33:51 +02:00
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// Finally create the (singleton) list of descriptions of union
|
|
|
|
// members.
|
2014-05-15 15:33:51 +02:00
|
|
|
vec![
|
|
|
|
MemberDescription {
|
|
|
|
name: union_member_name,
|
|
|
|
llvm_type: artificial_struct_llvm_type,
|
|
|
|
type_metadata: artificial_struct_metadata,
|
|
|
|
offset: FixedMemberOffset { bytes: 0 },
|
2014-07-30 15:56:42 +02:00
|
|
|
flags: FLAGS_NONE
|
2014-05-15 15:33:51 +02:00
|
|
|
}
|
|
|
|
]
|
|
|
|
},
|
2014-06-18 15:07:26 +12:00
|
|
|
adt::StructWrappedNullablePointer { nonnull: ref struct_def,
|
|
|
|
nndiscr,
|
2014-12-04 16:44:51 -05:00
|
|
|
ref discrfield, ..} => {
|
2014-05-15 15:33:51 +02:00
|
|
|
// Create a description of the non-null variant
|
|
|
|
let (variant_type_metadata, variant_llvm_type, member_description_factory) =
|
2014-01-02 15:20:43 +01:00
|
|
|
describe_enum_variant(cx,
|
2014-05-30 17:09:16 +02:00
|
|
|
self.enum_type,
|
2014-01-02 15:20:43 +01:00
|
|
|
struct_def,
|
2015-03-25 17:06:52 -07:00
|
|
|
&*(*self.variants)[nndiscr as usize],
|
2014-12-04 16:44:51 -05:00
|
|
|
OptimizedDiscriminant,
|
2014-01-02 15:20:43 +01:00
|
|
|
self.containing_scope,
|
|
|
|
self.span);
|
2013-09-18 18:18:45 -07:00
|
|
|
|
2014-05-15 15:33:51 +02:00
|
|
|
let variant_member_descriptions =
|
|
|
|
member_description_factory.create_member_descriptions(cx);
|
2013-09-18 18:18:45 -07:00
|
|
|
|
|
|
|
set_members_of_composite_type(cx,
|
|
|
|
variant_type_metadata,
|
|
|
|
variant_llvm_type,
|
2015-02-18 14:48:57 -05:00
|
|
|
&variant_member_descriptions[..]);
|
2014-05-15 15:33:51 +02:00
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// Encode the information about the null variant in the union
|
|
|
|
// member's name.
|
2015-03-25 17:06:52 -07:00
|
|
|
let null_variant_index = (1 - nndiscr) as usize;
|
2014-09-30 19:11:34 -05:00
|
|
|
let null_variant_name = token::get_name((*self.variants)[null_variant_index].name);
|
2014-12-04 16:44:51 -05:00
|
|
|
let discrfield = discrfield.iter()
|
|
|
|
.skip(1)
|
|
|
|
.map(|x| x.to_string())
|
|
|
|
.collect::<Vec<_>>().connect("$");
|
2014-05-15 15:33:51 +02:00
|
|
|
let union_member_name = format!("RUST$ENCODED$ENUM${}${}",
|
2014-07-07 14:41:18 -07:00
|
|
|
discrfield,
|
2014-05-15 15:33:51 +02:00
|
|
|
null_variant_name);
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// Create the (singleton) list of descriptions of union members.
|
2014-05-15 15:33:51 +02:00
|
|
|
vec![
|
|
|
|
MemberDescription {
|
|
|
|
name: union_member_name,
|
|
|
|
llvm_type: variant_llvm_type,
|
|
|
|
type_metadata: variant_type_metadata,
|
|
|
|
offset: FixedMemberOffset { bytes: 0 },
|
2014-07-30 15:56:42 +02:00
|
|
|
flags: FLAGS_NONE
|
2014-05-15 15:33:51 +02:00
|
|
|
}
|
|
|
|
]
|
|
|
|
},
|
|
|
|
adt::CEnum(..) => cx.sess().span_bug(self.span, "This should be unreachable.")
|
|
|
|
}
|
2013-09-18 18:18:45 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// Creates MemberDescriptions for the fields of a single enum variant.
|
2014-09-29 22:11:30 +03:00
|
|
|
struct VariantMemberDescriptionFactory<'tcx> {
|
|
|
|
args: Vec<(String, Ty<'tcx>)>,
|
2013-09-18 18:18:45 -07:00
|
|
|
discriminant_type_metadata: Option<DIType>,
|
|
|
|
span: Span,
|
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
impl<'tcx> VariantMemberDescriptionFactory<'tcx> {
|
|
|
|
fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
|
|
|
|
-> Vec<MemberDescription> {
|
2014-01-31 12:28:56 -08:00
|
|
|
self.args.iter().enumerate().map(|(i, &(ref name, ty))| {
|
2013-09-18 18:18:45 -07:00
|
|
|
MemberDescription {
|
2014-05-25 03:17:19 -07:00
|
|
|
name: name.to_string(),
|
2013-09-18 18:18:45 -07:00
|
|
|
llvm_type: type_of::type_of(cx, ty),
|
|
|
|
type_metadata: match self.discriminant_type_metadata {
|
|
|
|
Some(metadata) if i == 0 => metadata,
|
|
|
|
_ => type_metadata(cx, ty, self.span)
|
|
|
|
},
|
|
|
|
offset: ComputedMemberOffset,
|
2014-10-02 15:59:22 +02:00
|
|
|
flags: FLAGS_NONE
|
2013-09-18 18:18:45 -07:00
|
|
|
}
|
2013-11-21 15:42:55 -08:00
|
|
|
}).collect()
|
2013-09-18 18:18:45 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-30 09:38:44 -04:00
|
|
|
#[derive(Copy, Clone)]
|
2014-05-15 14:13:33 +02:00
|
|
|
enum EnumDiscriminantInfo {
|
|
|
|
RegularDiscriminant(DIType),
|
2014-12-04 16:44:51 -05:00
|
|
|
OptimizedDiscriminant,
|
2014-05-15 14:13:33 +02:00
|
|
|
NoDiscriminant
|
|
|
|
}
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// Returns a tuple of (1) type_metadata_stub of the variant, (2) the llvm_type
|
|
|
|
// of the variant, and (3) a MemberDescriptionFactory for producing the
|
|
|
|
// descriptions of the fields of the variant. This is a rudimentary version of a
|
|
|
|
// full RecursiveTypeDescription.
|
2014-09-29 22:11:30 +03:00
|
|
|
fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|
|
|
enum_type: Ty<'tcx>,
|
|
|
|
struct_def: &adt::Struct<'tcx>,
|
|
|
|
variant_info: &ty::VariantInfo<'tcx>,
|
|
|
|
discriminant_info: EnumDiscriminantInfo,
|
|
|
|
containing_scope: DIScope,
|
|
|
|
span: Span)
|
|
|
|
-> (DICompositeType, Type, MemberDescriptionFactory<'tcx>) {
|
2014-03-08 21:36:22 +01:00
|
|
|
let variant_llvm_type =
|
2015-01-07 11:58:31 -05:00
|
|
|
Type::struct_(cx, &struct_def.fields
|
2014-03-28 20:42:34 +01:00
|
|
|
.iter()
|
2014-03-15 22:29:34 +02:00
|
|
|
.map(|&t| type_of::type_of(cx, t))
|
2014-03-28 20:42:34 +01:00
|
|
|
.collect::<Vec<_>>()
|
2015-02-20 14:08:14 -05:00
|
|
|
,
|
2014-03-08 21:36:22 +01:00
|
|
|
struct_def.packed);
|
2014-05-15 15:33:51 +02:00
|
|
|
// Could do some consistency checks here: size, align, field count, discr type
|
2013-09-18 18:18:45 -07:00
|
|
|
|
2014-09-30 19:11:34 -05:00
|
|
|
let variant_name = token::get_name(variant_info.name);
|
2015-02-04 21:48:12 +01:00
|
|
|
let variant_name = &variant_name;
|
2014-05-30 17:09:16 +02:00
|
|
|
let unique_type_id = debug_context(cx).type_map
|
|
|
|
.borrow_mut()
|
|
|
|
.get_unique_type_id_of_enum_variant(
|
|
|
|
cx,
|
|
|
|
enum_type,
|
|
|
|
variant_name);
|
|
|
|
|
2013-09-18 18:18:45 -07:00
|
|
|
let metadata_stub = create_struct_stub(cx,
|
|
|
|
variant_llvm_type,
|
2014-05-30 17:09:16 +02:00
|
|
|
variant_name,
|
|
|
|
unique_type_id,
|
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
|
|
|
containing_scope);
|
2013-09-18 18:18:45 -07:00
|
|
|
|
|
|
|
// Get the argument names from the enum variant info
|
2014-03-28 20:42:34 +01:00
|
|
|
let mut arg_names: Vec<_> = match variant_info.arg_names {
|
2014-01-31 12:28:56 -08:00
|
|
|
Some(ref names) => {
|
2014-05-16 10:45:16 -07:00
|
|
|
names.iter()
|
2015-03-23 19:41:35 -05:00
|
|
|
.map(|&name| token::get_name(name).to_string())
|
|
|
|
.collect()
|
2014-01-31 12:28:56 -08:00
|
|
|
}
|
2015-04-06 11:39:51 -07:00
|
|
|
None => {
|
|
|
|
variant_info.args
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.map(|(i, _)| format!("__{}", i))
|
|
|
|
.collect()
|
|
|
|
}
|
2013-09-18 18:18:45 -07:00
|
|
|
};
|
|
|
|
|
2014-10-02 15:59:22 +02:00
|
|
|
// If this is not a univariant enum, there is also the discriminant field.
|
2014-05-15 14:13:33 +02:00
|
|
|
match discriminant_info {
|
2014-10-02 15:59:22 +02:00
|
|
|
RegularDiscriminant(_) => arg_names.insert(0, "RUST$ENUM$DISR".to_string()),
|
2014-05-15 14:13:33 +02:00
|
|
|
_ => { /* do nothing */ }
|
|
|
|
};
|
2013-09-18 18:18:45 -07:00
|
|
|
|
|
|
|
// Build an array of (field name, field type) pairs to be captured in the factory closure.
|
2014-09-13 21:09:25 +03:00
|
|
|
let args: Vec<(String, Ty)> = arg_names.iter()
|
2013-09-18 18:18:45 -07:00
|
|
|
.zip(struct_def.fields.iter())
|
2014-05-25 03:17:19 -07:00
|
|
|
.map(|(s, &t)| (s.to_string(), t))
|
2013-09-18 18:18:45 -07:00
|
|
|
.collect();
|
|
|
|
|
|
|
|
let member_description_factory =
|
2014-05-15 14:13:33 +02:00
|
|
|
VariantMDF(VariantMemberDescriptionFactory {
|
2013-09-18 18:18:45 -07:00
|
|
|
args: args,
|
2014-05-15 14:13:33 +02:00
|
|
|
discriminant_type_metadata: match discriminant_info {
|
2014-06-18 15:07:26 +12:00
|
|
|
RegularDiscriminant(discriminant_type_metadata) => {
|
|
|
|
Some(discriminant_type_metadata)
|
|
|
|
}
|
2014-05-15 14:13:33 +02:00
|
|
|
_ => None
|
|
|
|
},
|
2013-09-18 18:18:45 -07:00
|
|
|
span: span,
|
2014-02-07 00:38:33 +02:00
|
|
|
});
|
2013-09-18 18:18:45 -07:00
|
|
|
|
|
|
|
(metadata_stub, variant_llvm_type, member_description_factory)
|
2013-06-26 16:00:42 +02:00
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|
|
|
enum_type: Ty<'tcx>,
|
|
|
|
enum_def_id: ast::DefId,
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
span: Span)
|
|
|
|
-> RecursiveTypeDescription<'tcx> {
|
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 enum_name = compute_debuginfo_type_name(cx, enum_type, false);
|
2013-07-11 12:51:47 +02:00
|
|
|
|
2014-02-14 07:07:09 +02:00
|
|
|
let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, enum_def_id);
|
2013-09-09 17:58:58 +02:00
|
|
|
let loc = span_start(cx, definition_span);
|
2015-02-20 14:08:14 -05:00
|
|
|
let file_metadata = file_metadata(cx, &loc.file.name);
|
2013-09-09 17:58:58 +02:00
|
|
|
|
2014-03-15 22:29:34 +02:00
|
|
|
let variants = ty::enum_variants(cx.tcx(), enum_def_id);
|
2013-07-11 12:51:47 +02:00
|
|
|
|
2014-03-04 10:02:49 -08:00
|
|
|
let enumerators_metadata: Vec<DIDescriptor> = variants
|
2013-07-11 12:51:47 +02:00
|
|
|
.iter()
|
2013-08-09 20:09:47 -07:00
|
|
|
.map(|v| {
|
2014-11-25 13:28:35 -08:00
|
|
|
let token = token::get_name(v.name);
|
2015-02-17 22:47:40 -08:00
|
|
|
let name = CString::new(token.as_bytes()).unwrap();
|
2014-11-25 13:28:35 -08:00
|
|
|
unsafe {
|
|
|
|
llvm::LLVMDIBuilderCreateEnumerator(
|
|
|
|
DIB(cx),
|
|
|
|
name.as_ptr(),
|
|
|
|
v.disr_val as u64)
|
|
|
|
}
|
2013-07-11 12:51:47 +02:00
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
|
2015-02-01 12:44:15 -05:00
|
|
|
let discriminant_type_metadata = |inttype| {
|
2014-06-18 15:07:26 +12:00
|
|
|
// We can reuse the type of the discriminant for all monomorphized
|
2015-04-24 11:38:53 +12:00
|
|
|
// instances of an enum because it doesn't depend on any type
|
|
|
|
// parameters. The def_id, uniquely identifying the enum's polytype acts
|
|
|
|
// as key in this cache.
|
2014-03-27 15:47:13 +01:00
|
|
|
let cached_discriminant_type_metadata = debug_context(cx).created_enum_disr_types
|
|
|
|
.borrow()
|
2014-11-07 14:35:18 -05:00
|
|
|
.get(&enum_def_id).cloned();
|
2014-03-27 15:47:13 +01:00
|
|
|
match cached_discriminant_type_metadata {
|
|
|
|
Some(discriminant_type_metadata) => discriminant_type_metadata,
|
|
|
|
None => {
|
|
|
|
let discriminant_llvm_type = adt::ll_inttype(cx, inttype);
|
|
|
|
let (discriminant_size, discriminant_align) =
|
|
|
|
size_and_align_of(cx, discriminant_llvm_type);
|
2014-12-25 07:20:48 -05:00
|
|
|
let discriminant_base_type_metadata =
|
|
|
|
type_metadata(cx,
|
|
|
|
adt::ty_of_inttype(cx.tcx(), inttype),
|
|
|
|
codemap::DUMMY_SP);
|
2014-03-27 15:47:13 +01:00
|
|
|
let discriminant_name = get_enum_discriminant_name(cx, enum_def_id);
|
|
|
|
|
2015-02-17 22:47:40 -08:00
|
|
|
let name = CString::new(discriminant_name.as_bytes()).unwrap();
|
2014-11-25 13:28:35 -08:00
|
|
|
let discriminant_type_metadata = unsafe {
|
|
|
|
llvm::LLVMDIBuilderCreateEnumerationType(
|
|
|
|
DIB(cx),
|
|
|
|
containing_scope,
|
|
|
|
name.as_ptr(),
|
|
|
|
UNKNOWN_FILE_METADATA,
|
|
|
|
UNKNOWN_LINE_NUMBER,
|
|
|
|
bytes_to_bits(discriminant_size),
|
|
|
|
bytes_to_bits(discriminant_align),
|
2015-02-01 21:53:25 -05:00
|
|
|
create_DIArray(DIB(cx), &enumerators_metadata),
|
2014-11-25 13:28:35 -08:00
|
|
|
discriminant_base_type_metadata)
|
|
|
|
};
|
2014-03-27 15:47:13 +01:00
|
|
|
|
|
|
|
debug_context(cx).created_enum_disr_types
|
|
|
|
.borrow_mut()
|
|
|
|
.insert(enum_def_id, discriminant_type_metadata);
|
|
|
|
|
|
|
|
discriminant_type_metadata
|
2013-06-30 22:42:30 -07:00
|
|
|
}
|
2014-03-27 15:47:13 +01:00
|
|
|
}
|
2013-07-16 12:17:55 +02:00
|
|
|
};
|
2013-07-11 12:51:47 +02:00
|
|
|
|
|
|
|
let type_rep = adt::represent_type(cx, enum_type);
|
|
|
|
|
2014-05-15 15:33:51 +02:00
|
|
|
let discriminant_type_metadata = match *type_rep {
|
2013-06-30 22:42:30 -07:00
|
|
|
adt::CEnum(inttype, _, _) => {
|
2014-05-15 15:33:51 +02:00
|
|
|
return FinalMetadata(discriminant_type_metadata(inttype))
|
|
|
|
},
|
|
|
|
adt::RawNullablePointer { .. } |
|
|
|
|
adt::StructWrappedNullablePointer { .. } |
|
|
|
|
adt::Univariant(..) => None,
|
2014-06-14 15:55:55 +02:00
|
|
|
adt::General(inttype, _, _) => Some(discriminant_type_metadata(inttype)),
|
2014-05-15 15:33:51 +02:00
|
|
|
};
|
2013-09-11 16:37:43 +02:00
|
|
|
|
2014-05-15 15:33:51 +02:00
|
|
|
let enum_llvm_type = type_of::type_of(cx, enum_type);
|
|
|
|
let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type);
|
2014-05-30 17:09:16 +02:00
|
|
|
|
|
|
|
let unique_type_id_str = debug_context(cx)
|
|
|
|
.type_map
|
|
|
|
.borrow()
|
|
|
|
.get_unique_type_id_as_string(unique_type_id);
|
2014-05-15 15:33:51 +02:00
|
|
|
|
2015-02-17 22:47:40 -08:00
|
|
|
let enum_name = CString::new(enum_name).unwrap();
|
|
|
|
let unique_type_id_str = CString::new(unique_type_id_str.as_bytes()).unwrap();
|
2014-11-25 13:28:35 -08:00
|
|
|
let enum_metadata = unsafe {
|
|
|
|
llvm::LLVMDIBuilderCreateUnionType(
|
|
|
|
DIB(cx),
|
|
|
|
containing_scope,
|
|
|
|
enum_name.as_ptr(),
|
|
|
|
UNKNOWN_FILE_METADATA,
|
|
|
|
UNKNOWN_LINE_NUMBER,
|
|
|
|
bytes_to_bits(enum_type_size),
|
|
|
|
bytes_to_bits(enum_type_align),
|
|
|
|
0, // Flags
|
|
|
|
ptr::null_mut(),
|
|
|
|
0, // RuntimeLang
|
|
|
|
unique_type_id_str.as_ptr())
|
|
|
|
};
|
2014-05-15 15:33:51 +02:00
|
|
|
|
2014-05-30 17:09:16 +02:00
|
|
|
return create_and_register_recursive_type_forward_declaration(
|
|
|
|
cx,
|
|
|
|
enum_type,
|
|
|
|
unique_type_id,
|
|
|
|
enum_metadata,
|
|
|
|
enum_llvm_type,
|
|
|
|
EnumMDF(EnumMemberDescriptionFactory {
|
|
|
|
enum_type: enum_type,
|
2014-05-15 15:33:51 +02:00
|
|
|
type_rep: type_rep.clone(),
|
|
|
|
variants: variants,
|
|
|
|
discriminant_type_metadata: discriminant_type_metadata,
|
|
|
|
containing_scope: containing_scope,
|
|
|
|
file_metadata: file_metadata,
|
|
|
|
span: span,
|
|
|
|
}),
|
2014-05-30 17:09:16 +02:00
|
|
|
);
|
2014-03-27 15:47:13 +01:00
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
fn get_enum_discriminant_name(cx: &CrateContext,
|
|
|
|
def_id: ast::DefId)
|
|
|
|
-> token::InternedString {
|
2014-03-27 15:47:13 +01:00
|
|
|
let name = if def_id.krate == ast::LOCAL_CRATE {
|
2014-09-05 09:18:53 -07:00
|
|
|
cx.tcx().map.get_path_elem(def_id.node).name()
|
2014-03-27 15:47:13 +01:00
|
|
|
} else {
|
2014-09-05 09:18:53 -07:00
|
|
|
csearch::get_item_path(cx.tcx(), def_id).last().unwrap().name()
|
2014-03-27 15:47:13 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
token::get_name(name)
|
|
|
|
}
|
2013-07-11 12:51:47 +02:00
|
|
|
}
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
/// Creates debug information for a composite type, that is, anything that
|
|
|
|
/// results in a LLVM struct.
|
2013-06-28 11:56:35 +02:00
|
|
|
///
|
2013-06-28 17:11:50 +02:00
|
|
|
/// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums.
|
2013-12-19 16:47:15 -08:00
|
|
|
fn composite_type_metadata(cx: &CrateContext,
|
2013-07-16 12:17:55 +02:00
|
|
|
composite_llvm_type: Type,
|
|
|
|
composite_type_name: &str,
|
2014-05-30 17:09:16 +02:00
|
|
|
composite_type_unique_id: UniqueTypeId,
|
2013-09-09 17:58:58 +02:00
|
|
|
member_descriptions: &[MemberDescription],
|
|
|
|
containing_scope: DIScope,
|
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
|
|
|
|
|
|
|
// Ignore source location information as long as it
|
|
|
|
// can't be reconstructed for non-local crates.
|
|
|
|
_file_metadata: DIFile,
|
|
|
|
_definition_span: Span)
|
2013-07-16 12:17:55 +02:00
|
|
|
-> DICompositeType {
|
2013-09-13 16:26:35 +02:00
|
|
|
// Create the (empty) struct metadata node ...
|
|
|
|
let composite_type_metadata = create_struct_stub(cx,
|
|
|
|
composite_llvm_type,
|
|
|
|
composite_type_name,
|
2014-05-30 17:09:16 +02:00
|
|
|
composite_type_unique_id,
|
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
|
|
|
containing_scope);
|
2013-09-13 16:26:35 +02:00
|
|
|
// ... and immediately create and add the member descriptions.
|
2013-09-11 16:37:43 +02:00
|
|
|
set_members_of_composite_type(cx,
|
|
|
|
composite_type_metadata,
|
|
|
|
composite_llvm_type,
|
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
|
|
|
member_descriptions);
|
2013-09-11 16:37:43 +02:00
|
|
|
|
|
|
|
return composite_type_metadata;
|
|
|
|
}
|
|
|
|
|
2013-12-19 16:47:15 -08:00
|
|
|
fn set_members_of_composite_type(cx: &CrateContext,
|
2013-09-11 16:37:43 +02:00
|
|
|
composite_type_metadata: DICompositeType,
|
|
|
|
composite_llvm_type: Type,
|
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
|
|
|
member_descriptions: &[MemberDescription]) {
|
2014-06-18 15:07:26 +12:00
|
|
|
// In some rare cases LLVM metadata uniquing would lead to an existing type
|
2015-04-24 11:38:53 +12:00
|
|
|
// description being used instead of a new one created in
|
|
|
|
// create_struct_stub. This would cause a hard to trace assertion in
|
|
|
|
// DICompositeType::SetTypeArray(). The following check makes sure that we
|
|
|
|
// get a better error message if this should happen again due to some
|
|
|
|
// regression.
|
2013-12-18 19:07:31 -08:00
|
|
|
{
|
|
|
|
let mut composite_types_completed =
|
|
|
|
debug_context(cx).composite_types_completed.borrow_mut();
|
2014-03-20 19:49:20 -07:00
|
|
|
if composite_types_completed.contains(&composite_type_metadata) {
|
2015-04-20 10:19:02 -07:00
|
|
|
cx.sess().bug("debuginfo::set_members_of_composite_type() - \
|
|
|
|
Already completed forward declaration re-encountered.");
|
2013-12-18 19:07:31 -08:00
|
|
|
} else {
|
2014-03-20 19:49:20 -07:00
|
|
|
composite_types_completed.insert(composite_type_metadata);
|
2013-12-18 19:07:31 -08:00
|
|
|
}
|
2013-10-01 12:24:50 +02:00
|
|
|
}
|
|
|
|
|
2014-03-04 10:02:49 -08:00
|
|
|
let member_metadata: Vec<DIDescriptor> = member_descriptions
|
2013-06-28 17:11:50 +02:00
|
|
|
.iter()
|
|
|
|
.enumerate()
|
2013-09-09 17:58:58 +02:00
|
|
|
.map(|(i, member_description)| {
|
|
|
|
let (member_size, member_align) = size_and_align_of(cx, member_description.llvm_type);
|
2013-09-11 16:37:43 +02:00
|
|
|
let member_offset = match member_description.offset {
|
2014-01-30 17:19:19 -05:00
|
|
|
FixedMemberOffset { bytes } => bytes as u64,
|
2013-09-11 16:37:43 +02:00
|
|
|
ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i)
|
|
|
|
};
|
2013-07-16 12:17:55 +02:00
|
|
|
|
2015-02-17 22:47:40 -08:00
|
|
|
let member_name = member_description.name.as_bytes();
|
|
|
|
let member_name = CString::new(member_name).unwrap();
|
2014-11-25 13:28:35 -08:00
|
|
|
unsafe {
|
|
|
|
llvm::LLVMDIBuilderCreateMemberType(
|
|
|
|
DIB(cx),
|
|
|
|
composite_type_metadata,
|
|
|
|
member_name.as_ptr(),
|
|
|
|
UNKNOWN_FILE_METADATA,
|
|
|
|
UNKNOWN_LINE_NUMBER,
|
|
|
|
bytes_to_bits(member_size),
|
|
|
|
bytes_to_bits(member_align),
|
|
|
|
bytes_to_bits(member_offset),
|
|
|
|
member_description.flags,
|
|
|
|
member_description.type_metadata)
|
|
|
|
}
|
2013-07-01 12:10:08 +02:00
|
|
|
})
|
2013-06-28 17:11:50 +02:00
|
|
|
.collect();
|
|
|
|
|
2013-09-11 16:37:43 +02:00
|
|
|
unsafe {
|
2015-02-18 14:48:57 -05:00
|
|
|
let type_array = create_DIArray(DIB(cx), &member_metadata[..]);
|
2015-01-30 19:25:07 +01:00
|
|
|
llvm::LLVMDICompositeTypeSetTypeArray(DIB(cx), composite_type_metadata, type_array);
|
2013-09-11 16:37:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// A convenience wrapper around LLVMDIBuilderCreateStructType(). Does not do any
|
|
|
|
// caching, does not add any fields to the struct. This can be done later with
|
|
|
|
// set_members_of_composite_type().
|
2013-12-19 16:47:15 -08:00
|
|
|
fn create_struct_stub(cx: &CrateContext,
|
2013-09-11 16:37:43 +02:00
|
|
|
struct_llvm_type: Type,
|
|
|
|
struct_type_name: &str,
|
2014-05-30 17:09:16 +02:00
|
|
|
unique_type_id: UniqueTypeId,
|
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
|
|
|
containing_scope: DIScope)
|
2013-09-11 16:37:43 +02:00
|
|
|
-> DICompositeType {
|
|
|
|
let (struct_size, struct_align) = size_and_align_of(cx, struct_llvm_type);
|
|
|
|
|
2014-05-30 17:09:16 +02:00
|
|
|
let unique_type_id_str = debug_context(cx).type_map
|
|
|
|
.borrow()
|
|
|
|
.get_unique_type_id_as_string(unique_type_id);
|
2015-02-17 22:47:40 -08:00
|
|
|
let name = CString::new(struct_type_name).unwrap();
|
|
|
|
let unique_type_id = CString::new(unique_type_id_str.as_bytes()).unwrap();
|
2014-05-30 17:09:16 +02:00
|
|
|
let metadata_stub = unsafe {
|
2014-11-25 13:28:35 -08:00
|
|
|
// LLVMDIBuilderCreateStructType() wants an empty array. A null
|
|
|
|
// pointer will lead to hard to trace and debug LLVM assertions
|
|
|
|
// later on in llvm/lib/IR/Value.cpp.
|
|
|
|
let empty_array = create_DIArray(DIB(cx), &[]);
|
|
|
|
|
|
|
|
llvm::LLVMDIBuilderCreateStructType(
|
|
|
|
DIB(cx),
|
|
|
|
containing_scope,
|
|
|
|
name.as_ptr(),
|
|
|
|
UNKNOWN_FILE_METADATA,
|
|
|
|
UNKNOWN_LINE_NUMBER,
|
|
|
|
bytes_to_bits(struct_size),
|
|
|
|
bytes_to_bits(struct_align),
|
|
|
|
0,
|
|
|
|
ptr::null_mut(),
|
|
|
|
empty_array,
|
|
|
|
0,
|
|
|
|
ptr::null_mut(),
|
|
|
|
unique_type_id.as_ptr())
|
2013-11-21 15:42:55 -08:00
|
|
|
};
|
2014-05-30 17:09:16 +02:00
|
|
|
|
|
|
|
return metadata_stub;
|
2013-02-27 13:35:56 -05:00
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
fn fixed_vec_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
element_type: Ty<'tcx>,
|
2015-01-08 16:50:45 +01:00
|
|
|
len: Option<u64>,
|
2014-09-29 22:11:30 +03:00
|
|
|
span: Span)
|
|
|
|
-> MetadataCreationResult {
|
2013-07-16 12:17:55 +02:00
|
|
|
let element_type_metadata = type_metadata(cx, element_type, span);
|
2014-06-16 14:28:05 +02:00
|
|
|
|
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
|
|
|
return_if_metadata_created_in_meantime!(cx, unique_type_id);
|
2014-06-16 14:28:05 +02:00
|
|
|
|
2013-07-10 18:35:38 +02:00
|
|
|
let element_llvm_type = type_of::type_of(cx, element_type);
|
|
|
|
let (element_type_size, element_type_align) = size_and_align_of(cx, element_llvm_type);
|
2013-06-14 11:38:29 -07:00
|
|
|
|
2015-01-08 16:50:45 +01:00
|
|
|
let (array_size_in_bytes, upper_bound) = match len {
|
|
|
|
Some(len) => (element_type_size * len, len as c_longlong),
|
|
|
|
None => (0, -1)
|
|
|
|
};
|
|
|
|
|
2013-07-16 12:17:55 +02:00
|
|
|
let subrange = unsafe {
|
2015-01-08 16:50:45 +01:00
|
|
|
llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)
|
2013-07-16 12:17:55 +02:00
|
|
|
};
|
2013-06-14 11:38:29 -07:00
|
|
|
|
2014-11-17 21:39:01 +13:00
|
|
|
let subscripts = create_DIArray(DIB(cx), &[subrange]);
|
2014-06-16 14:28:05 +02:00
|
|
|
let metadata = unsafe {
|
2013-07-16 12:17:55 +02:00
|
|
|
llvm::LLVMDIBuilderCreateArrayType(
|
2013-06-20 16:00:59 +02:00
|
|
|
DIB(cx),
|
2015-01-08 16:50:45 +01:00
|
|
|
bytes_to_bits(array_size_in_bytes),
|
2013-07-10 18:35:38 +02:00
|
|
|
bytes_to_bits(element_type_align),
|
|
|
|
element_type_metadata,
|
2013-07-16 12:17:55 +02:00
|
|
|
subscripts)
|
|
|
|
};
|
2014-06-16 14:28:05 +02:00
|
|
|
|
|
|
|
return MetadataCreationResult::new(metadata, false);
|
2013-04-02 16:08:34 -04:00
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
fn vec_slice_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|
|
|
vec_type: Ty<'tcx>,
|
|
|
|
element_type: Ty<'tcx>,
|
|
|
|
unique_type_id: UniqueTypeId,
|
|
|
|
span: Span)
|
|
|
|
-> MetadataCreationResult {
|
2014-06-16 14:28:05 +02:00
|
|
|
let data_ptr_type = ty::mk_ptr(cx.tcx(), ty::mt {
|
|
|
|
ty: element_type,
|
|
|
|
mutbl: ast::MutImmutable
|
|
|
|
});
|
2013-06-19 16:30:35 +02:00
|
|
|
|
2014-06-16 14:28:05 +02:00
|
|
|
let element_type_metadata = type_metadata(cx, data_ptr_type, span);
|
|
|
|
|
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
|
|
|
return_if_metadata_created_in_meantime!(cx, unique_type_id);
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-28 11:56:35 +02:00
|
|
|
let slice_llvm_type = type_of::type_of(cx, vec_type);
|
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 slice_type_name = compute_debuginfo_type_name(cx, vec_type, true);
|
2013-06-28 11:56:35 +02:00
|
|
|
|
|
|
|
let member_llvm_types = slice_llvm_type.field_types();
|
2014-03-08 21:36:22 +01:00
|
|
|
assert!(slice_layout_is_correct(cx,
|
2015-02-18 14:48:57 -05:00
|
|
|
&member_llvm_types[..],
|
2014-03-08 21:36:22 +01:00
|
|
|
element_type));
|
2013-09-09 17:58:58 +02:00
|
|
|
let member_descriptions = [
|
|
|
|
MemberDescription {
|
2014-05-25 03:17:19 -07:00
|
|
|
name: "data_ptr".to_string(),
|
2014-10-14 23:05:01 -07:00
|
|
|
llvm_type: member_llvm_types[0],
|
2014-06-16 14:28:05 +02:00
|
|
|
type_metadata: element_type_metadata,
|
2013-09-11 16:37:43 +02:00
|
|
|
offset: ComputedMemberOffset,
|
2014-10-02 15:59:22 +02:00
|
|
|
flags: FLAGS_NONE
|
2013-09-09 17:58:58 +02:00
|
|
|
},
|
|
|
|
MemberDescription {
|
2014-05-25 03:17:19 -07:00
|
|
|
name: "length".to_string(),
|
2014-10-14 23:05:01 -07:00
|
|
|
llvm_type: member_llvm_types[1],
|
2015-03-25 17:06:52 -07:00
|
|
|
type_metadata: type_metadata(cx, cx.tcx().types.usize, span),
|
2013-09-11 16:37:43 +02:00
|
|
|
offset: ComputedMemberOffset,
|
2014-10-02 15:59:22 +02:00
|
|
|
flags: FLAGS_NONE
|
2013-09-09 17:58:58 +02:00
|
|
|
},
|
|
|
|
];
|
|
|
|
|
|
|
|
assert!(member_descriptions.len() == member_llvm_types.len());
|
|
|
|
|
|
|
|
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-28 11:56:35 +02:00
|
|
|
|
2014-06-16 14:28:05 +02:00
|
|
|
let metadata = composite_type_metadata(cx,
|
|
|
|
slice_llvm_type,
|
2015-02-18 14:48:57 -05:00
|
|
|
&slice_type_name[..],
|
2014-06-16 14:28:05 +02:00
|
|
|
unique_type_id,
|
2014-11-17 21:39:01 +13:00
|
|
|
&member_descriptions,
|
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
|
|
|
UNKNOWN_SCOPE_METADATA,
|
2014-06-16 14:28:05 +02:00
|
|
|
file_metadata,
|
|
|
|
span);
|
|
|
|
return MetadataCreationResult::new(metadata, false);
|
2013-06-28 11:56:35 +02:00
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
fn slice_layout_is_correct<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|
|
|
member_llvm_types: &[Type],
|
|
|
|
element_type: Ty<'tcx>)
|
|
|
|
-> bool {
|
2013-06-28 11:56:35 +02:00
|
|
|
member_llvm_types.len() == 2 &&
|
|
|
|
member_llvm_types[0] == type_of::type_of(cx, element_type).ptr_to() &&
|
2014-09-05 09:18:53 -07:00
|
|
|
member_llvm_types[1] == cx.int_type()
|
2013-06-28 11:56:35 +02:00
|
|
|
}
|
2011-12-11 15:24:47 -05:00
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
fn subroutine_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|
|
|
unique_type_id: UniqueTypeId,
|
2014-12-12 11:28:35 -05:00
|
|
|
signature: &ty::PolyFnSig<'tcx>,
|
2014-09-29 22:11:30 +03:00
|
|
|
span: Span)
|
2015-01-06 05:03:42 -05:00
|
|
|
-> MetadataCreationResult
|
|
|
|
{
|
|
|
|
let signature = ty::erase_late_bound_regions(cx.tcx(), signature);
|
|
|
|
|
|
|
|
let mut signature_metadata: Vec<DIType> = Vec::with_capacity(signature.inputs.len() + 1);
|
2013-08-23 18:45:02 +02:00
|
|
|
|
|
|
|
// return type
|
2015-01-06 05:03:42 -05:00
|
|
|
signature_metadata.push(match signature.output {
|
2014-10-31 10:51:16 +02:00
|
|
|
ty::FnConverging(ret_ty) => match ret_ty.sty {
|
2014-11-04 07:57:21 -05:00
|
|
|
ty::ty_tup(ref tys) if tys.is_empty() => ptr::null_mut(),
|
2014-10-24 21:14:37 +02:00
|
|
|
_ => type_metadata(cx, ret_ty, span)
|
|
|
|
},
|
|
|
|
ty::FnDiverging => diverging_type_metadata(cx)
|
2013-08-23 18:45:02 +02:00
|
|
|
});
|
2013-07-10 18:35:38 +02:00
|
|
|
|
2013-08-23 18:45:02 +02:00
|
|
|
// regular arguments
|
2015-01-31 12:20:46 -05:00
|
|
|
for &argument_type in &signature.inputs {
|
2013-08-23 18:45:02 +02:00
|
|
|
signature_metadata.push(type_metadata(cx, argument_type, span));
|
|
|
|
}
|
2013-06-11 12:41:09 -07:00
|
|
|
|
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
|
|
|
return_if_metadata_created_in_meantime!(cx, unique_type_id);
|
2014-06-16 14:28:05 +02:00
|
|
|
|
|
|
|
return MetadataCreationResult::new(
|
|
|
|
unsafe {
|
|
|
|
llvm::LLVMDIBuilderCreateSubroutineType(
|
|
|
|
DIB(cx),
|
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
|
|
|
UNKNOWN_FILE_METADATA,
|
2015-02-18 14:48:57 -05:00
|
|
|
create_DIArray(DIB(cx), &signature_metadata[..]))
|
2014-06-16 14:28:05 +02:00
|
|
|
},
|
|
|
|
false);
|
2011-12-11 15:24:47 -05:00
|
|
|
}
|
|
|
|
|
2014-08-06 11:59:40 +02:00
|
|
|
// FIXME(1563) This is all a bit of a hack because 'trait pointer' is an ill-
|
|
|
|
// defined concept. For the case of an actual trait pointer (i.e., Box<Trait>,
|
|
|
|
// &Trait), trait_object_type should be the whole thing (e.g, Box<Trait>) and
|
|
|
|
// trait_type should be the actual trait (e.g., Trait). Where the trait is part
|
|
|
|
// of a DST struct, there is no trait_object_type and the results of this
|
|
|
|
// function will be a little bit weird.
|
2014-09-29 22:11:30 +03:00
|
|
|
fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|
|
|
trait_type: Ty<'tcx>,
|
|
|
|
trait_object_type: Option<Ty<'tcx>>,
|
|
|
|
unique_type_id: UniqueTypeId)
|
|
|
|
-> DIType {
|
2014-06-18 15:07:26 +12:00
|
|
|
// The implementation provided here is a stub. It makes sure that the trait
|
|
|
|
// type is assigned the correct name, size, namespace, and source location.
|
|
|
|
// But it does not describe the trait's methods.
|
2014-05-31 18:53:13 -04:00
|
|
|
|
2014-10-31 10:51:16 +02:00
|
|
|
let def_id = match trait_type.sty {
|
2014-12-17 14:16:28 -05:00
|
|
|
ty::ty_trait(ref data) => data.principal_def_id(),
|
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
|
|
|
_ => {
|
2014-08-06 11:59:40 +02:00
|
|
|
let pp_type_name = ppaux::ty_to_string(cx.tcx(), trait_type);
|
2015-01-07 11:58:31 -05:00
|
|
|
cx.sess().bug(&format!("debuginfo: Unexpected trait-object type in \
|
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
|
|
|
trait_pointer_metadata(): {}",
|
2015-02-20 14:08:14 -05:00
|
|
|
&pp_type_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
|
|
|
}
|
|
|
|
};
|
2013-09-11 11:08:44 +02:00
|
|
|
|
2014-08-06 11:59:40 +02:00
|
|
|
let trait_object_type = trait_object_type.unwrap_or(trait_type);
|
|
|
|
let trait_type_name =
|
DST coercions and DST structs
[breaking-change]
1. The internal layout for traits has changed from (vtable, data) to (data, vtable). If you were relying on this in unsafe transmutes, you might get some very weird and apparently unrelated errors. You should not be doing this! Prefer not to do this at all, but if you must, you should use raw::TraitObject rather than hardcoding rustc's internal representation into your code.
2. The minimal type of reference-to-vec-literals (e.g., `&[1, 2, 3]`) is now a fixed size vec (e.g., `&[int, ..3]`) where it used to be an unsized vec (e.g., `&[int]`). If you want the unszied type, you must explicitly give the type (e.g., `let x: &[_] = &[1, 2, 3]`). Note in particular where multiple blocks must have the same type (e.g., if and else clauses, vec elements), the compiler will not coerce to the unsized type without a hint. E.g., `[&[1], &[1, 2]]` used to be a valid expression of type '[&[int]]'. It no longer type checks since the first element now has type `&[int, ..1]` and the second has type &[int, ..2]` which are incompatible.
3. The type of blocks (including functions) must be coercible to the expected type (used to be a subtype). Mostly this makes things more flexible and not less (in particular, in the case of coercing function bodies to the return type). However, in some rare cases, this is less flexible. TBH, I'm not exactly sure of the exact effects. I think the change causes us to resolve inferred type variables slightly earlier which might make us slightly more restrictive. Possibly it only affects blocks with unreachable code. E.g., `if ... { fail!(); "Hello" }` used to type check, it no longer does. The fix is to add a semicolon after the string.
2014-08-04 14:20:11 +02:00
|
|
|
compute_debuginfo_type_name(cx, trait_object_type, false);
|
2013-09-11 11:08:44 +02:00
|
|
|
|
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 (containing_scope, _) = get_namespace_and_span_for_item(cx, def_id);
|
2013-09-11 11:08:44 +02:00
|
|
|
|
DST coercions and DST structs
[breaking-change]
1. The internal layout for traits has changed from (vtable, data) to (data, vtable). If you were relying on this in unsafe transmutes, you might get some very weird and apparently unrelated errors. You should not be doing this! Prefer not to do this at all, but if you must, you should use raw::TraitObject rather than hardcoding rustc's internal representation into your code.
2. The minimal type of reference-to-vec-literals (e.g., `&[1, 2, 3]`) is now a fixed size vec (e.g., `&[int, ..3]`) where it used to be an unsized vec (e.g., `&[int]`). If you want the unszied type, you must explicitly give the type (e.g., `let x: &[_] = &[1, 2, 3]`). Note in particular where multiple blocks must have the same type (e.g., if and else clauses, vec elements), the compiler will not coerce to the unsized type without a hint. E.g., `[&[1], &[1, 2]]` used to be a valid expression of type '[&[int]]'. It no longer type checks since the first element now has type `&[int, ..1]` and the second has type &[int, ..2]` which are incompatible.
3. The type of blocks (including functions) must be coercible to the expected type (used to be a subtype). Mostly this makes things more flexible and not less (in particular, in the case of coercing function bodies to the return type). However, in some rare cases, this is less flexible. TBH, I'm not exactly sure of the exact effects. I think the change causes us to resolve inferred type variables slightly earlier which might make us slightly more restrictive. Possibly it only affects blocks with unreachable code. E.g., `if ... { fail!(); "Hello" }` used to type check, it no longer does. The fix is to add a semicolon after the string.
2014-08-04 14:20:11 +02:00
|
|
|
let trait_llvm_type = type_of::type_of(cx, trait_object_type);
|
2013-09-11 11:08:44 +02:00
|
|
|
|
2014-04-11 09:01:31 +03:00
|
|
|
composite_type_metadata(cx,
|
2014-08-06 11:59:40 +02:00
|
|
|
trait_llvm_type,
|
2015-02-18 14:48:57 -05:00
|
|
|
&trait_type_name[..],
|
2014-05-30 17:09:16 +02:00
|
|
|
unique_type_id,
|
2014-11-17 21:39:01 +13:00
|
|
|
&[],
|
2014-04-11 09:01:31 +03:00
|
|
|
containing_scope,
|
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
|
|
|
UNKNOWN_FILE_METADATA,
|
|
|
|
codemap::DUMMY_SP)
|
2013-09-11 11:08:44 +02:00
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|
|
|
t: Ty<'tcx>,
|
|
|
|
usage_site_span: Span)
|
|
|
|
-> DIType {
|
2014-05-30 17:09:16 +02:00
|
|
|
// Get the unique type id of this type.
|
|
|
|
let unique_type_id = {
|
|
|
|
let mut type_map = debug_context(cx).type_map.borrow_mut();
|
2014-06-18 15:07:26 +12:00
|
|
|
// First, try to find the type in TypeMap. If we have seen it before, we
|
|
|
|
// can exit early here.
|
2014-05-30 17:09:16 +02:00
|
|
|
match type_map.find_metadata_for_type(t) {
|
|
|
|
Some(metadata) => {
|
|
|
|
return metadata;
|
|
|
|
},
|
|
|
|
None => {
|
2014-09-13 21:09:25 +03:00
|
|
|
// The Ty is not in the TypeMap but maybe we have already seen
|
2014-06-18 15:07:26 +12:00
|
|
|
// an equivalent type (e.g. only differing in region arguments).
|
|
|
|
// In order to find out, generate the unique type id and look
|
|
|
|
// that up.
|
2014-05-30 17:09:16 +02:00
|
|
|
let unique_type_id = type_map.get_unique_type_id_of_type(cx, t);
|
|
|
|
match type_map.find_metadata_for_unique_id(unique_type_id) {
|
|
|
|
Some(metadata) => {
|
2014-06-18 15:07:26 +12:00
|
|
|
// There is already an equivalent type in the TypeMap.
|
2014-09-13 21:09:25 +03:00
|
|
|
// Register this Ty as an alias in the cache and
|
2014-06-18 15:07:26 +12:00
|
|
|
// return the cached metadata.
|
2014-05-30 17:09:16 +02:00
|
|
|
type_map.register_type_with_metadata(cx, t, metadata);
|
|
|
|
return metadata;
|
|
|
|
},
|
|
|
|
None => {
|
2014-06-18 15:07:26 +12:00
|
|
|
// There really is no type metadata for this type, so
|
|
|
|
// proceed by creating it.
|
2014-05-30 17:09:16 +02:00
|
|
|
unique_type_id
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2013-07-16 12:17:55 +02:00
|
|
|
|
2014-12-20 00:09:35 -08:00
|
|
|
debug!("type_metadata: {:?}", t);
|
2013-06-28 17:11:50 +02:00
|
|
|
|
2014-10-31 10:51:16 +02:00
|
|
|
let sty = &t.sty;
|
2014-06-16 14:28:05 +02:00
|
|
|
let MetadataCreationResult { metadata, already_stored_in_typemap } = match *sty {
|
2013-06-28 17:11:50 +02:00
|
|
|
ty::ty_bool |
|
2013-09-03 19:24:12 -04:00
|
|
|
ty::ty_char |
|
2013-06-28 17:11:50 +02:00
|
|
|
ty::ty_int(_) |
|
|
|
|
ty::ty_uint(_) |
|
|
|
|
ty::ty_float(_) => {
|
2014-06-16 14:28:05 +02:00
|
|
|
MetadataCreationResult::new(basic_type_metadata(cx, t), false)
|
2014-04-27 10:19:15 +12:00
|
|
|
}
|
2014-11-09 16:14:15 +01:00
|
|
|
ty::ty_tup(ref elements) if elements.is_empty() => {
|
|
|
|
MetadataCreationResult::new(basic_type_metadata(cx, t), false)
|
|
|
|
}
|
2013-07-22 16:18:53 +02:00
|
|
|
ty::ty_enum(def_id, _) => {
|
2014-06-16 14:28:05 +02:00
|
|
|
prepare_enum_metadata(cx, t, def_id, unique_type_id, usage_site_span).finalize(cx)
|
2014-05-30 17:09:16 +02:00
|
|
|
}
|
2015-01-08 16:50:45 +01:00
|
|
|
ty::ty_vec(typ, len) => {
|
|
|
|
fixed_vec_metadata(cx, unique_type_id, typ, len.map(|x| x as u64), usage_site_span)
|
|
|
|
}
|
|
|
|
ty::ty_str => {
|
|
|
|
fixed_vec_metadata(cx, unique_type_id, cx.tcx().types.i8, None, usage_site_span)
|
2014-04-27 10:19:15 +12:00
|
|
|
}
|
DST coercions and DST structs
[breaking-change]
1. The internal layout for traits has changed from (vtable, data) to (data, vtable). If you were relying on this in unsafe transmutes, you might get some very weird and apparently unrelated errors. You should not be doing this! Prefer not to do this at all, but if you must, you should use raw::TraitObject rather than hardcoding rustc's internal representation into your code.
2. The minimal type of reference-to-vec-literals (e.g., `&[1, 2, 3]`) is now a fixed size vec (e.g., `&[int, ..3]`) where it used to be an unsized vec (e.g., `&[int]`). If you want the unszied type, you must explicitly give the type (e.g., `let x: &[_] = &[1, 2, 3]`). Note in particular where multiple blocks must have the same type (e.g., if and else clauses, vec elements), the compiler will not coerce to the unsized type without a hint. E.g., `[&[1], &[1, 2]]` used to be a valid expression of type '[&[int]]'. It no longer type checks since the first element now has type `&[int, ..1]` and the second has type &[int, ..2]` which are incompatible.
3. The type of blocks (including functions) must be coercible to the expected type (used to be a subtype). Mostly this makes things more flexible and not less (in particular, in the case of coercing function bodies to the return type). However, in some rare cases, this is less flexible. TBH, I'm not exactly sure of the exact effects. I think the change causes us to resolve inferred type variables slightly earlier which might make us slightly more restrictive. Possibly it only affects blocks with unreachable code. E.g., `if ... { fail!(); "Hello" }` used to type check, it no longer does. The fix is to add a semicolon after the string.
2014-08-04 14:20:11 +02:00
|
|
|
ty::ty_trait(..) => {
|
|
|
|
MetadataCreationResult::new(
|
2014-08-06 11:59:40 +02:00
|
|
|
trait_pointer_metadata(cx, t, None, unique_type_id),
|
DST coercions and DST structs
[breaking-change]
1. The internal layout for traits has changed from (vtable, data) to (data, vtable). If you were relying on this in unsafe transmutes, you might get some very weird and apparently unrelated errors. You should not be doing this! Prefer not to do this at all, but if you must, you should use raw::TraitObject rather than hardcoding rustc's internal representation into your code.
2. The minimal type of reference-to-vec-literals (e.g., `&[1, 2, 3]`) is now a fixed size vec (e.g., `&[int, ..3]`) where it used to be an unsized vec (e.g., `&[int]`). If you want the unszied type, you must explicitly give the type (e.g., `let x: &[_] = &[1, 2, 3]`). Note in particular where multiple blocks must have the same type (e.g., if and else clauses, vec elements), the compiler will not coerce to the unsized type without a hint. E.g., `[&[1], &[1, 2]]` used to be a valid expression of type '[&[int]]'. It no longer type checks since the first element now has type `&[int, ..1]` and the second has type &[int, ..2]` which are incompatible.
3. The type of blocks (including functions) must be coercible to the expected type (used to be a subtype). Mostly this makes things more flexible and not less (in particular, in the case of coercing function bodies to the return type). However, in some rare cases, this is less flexible. TBH, I'm not exactly sure of the exact effects. I think the change causes us to resolve inferred type variables slightly earlier which might make us slightly more restrictive. Possibly it only affects blocks with unreachable code. E.g., `if ... { fail!(); "Hello" }` used to type check, it no longer does. The fix is to add a semicolon after the string.
2014-08-04 14:20:11 +02:00
|
|
|
false)
|
2014-01-12 02:25:51 +02:00
|
|
|
}
|
DST coercions and DST structs
[breaking-change]
1. The internal layout for traits has changed from (vtable, data) to (data, vtable). If you were relying on this in unsafe transmutes, you might get some very weird and apparently unrelated errors. You should not be doing this! Prefer not to do this at all, but if you must, you should use raw::TraitObject rather than hardcoding rustc's internal representation into your code.
2. The minimal type of reference-to-vec-literals (e.g., `&[1, 2, 3]`) is now a fixed size vec (e.g., `&[int, ..3]`) where it used to be an unsized vec (e.g., `&[int]`). If you want the unszied type, you must explicitly give the type (e.g., `let x: &[_] = &[1, 2, 3]`). Note in particular where multiple blocks must have the same type (e.g., if and else clauses, vec elements), the compiler will not coerce to the unsized type without a hint. E.g., `[&[1], &[1, 2]]` used to be a valid expression of type '[&[int]]'. It no longer type checks since the first element now has type `&[int, ..1]` and the second has type &[int, ..2]` which are incompatible.
3. The type of blocks (including functions) must be coercible to the expected type (used to be a subtype). Mostly this makes things more flexible and not less (in particular, in the case of coercing function bodies to the return type). However, in some rare cases, this is less flexible. TBH, I'm not exactly sure of the exact effects. I think the change causes us to resolve inferred type variables slightly earlier which might make us slightly more restrictive. Possibly it only affects blocks with unreachable code. E.g., `if ... { fail!(); "Hello" }` used to type check, it no longer does. The fix is to add a semicolon after the string.
2014-08-04 14:20:11 +02:00
|
|
|
ty::ty_uniq(ty) | ty::ty_ptr(ty::mt{ty, ..}) | ty::ty_rptr(_, ty::mt{ty, ..}) => {
|
2014-10-31 10:51:16 +02:00
|
|
|
match ty.sty {
|
DST coercions and DST structs
[breaking-change]
1. The internal layout for traits has changed from (vtable, data) to (data, vtable). If you were relying on this in unsafe transmutes, you might get some very weird and apparently unrelated errors. You should not be doing this! Prefer not to do this at all, but if you must, you should use raw::TraitObject rather than hardcoding rustc's internal representation into your code.
2. The minimal type of reference-to-vec-literals (e.g., `&[1, 2, 3]`) is now a fixed size vec (e.g., `&[int, ..3]`) where it used to be an unsized vec (e.g., `&[int]`). If you want the unszied type, you must explicitly give the type (e.g., `let x: &[_] = &[1, 2, 3]`). Note in particular where multiple blocks must have the same type (e.g., if and else clauses, vec elements), the compiler will not coerce to the unsized type without a hint. E.g., `[&[1], &[1, 2]]` used to be a valid expression of type '[&[int]]'. It no longer type checks since the first element now has type `&[int, ..1]` and the second has type &[int, ..2]` which are incompatible.
3. The type of blocks (including functions) must be coercible to the expected type (used to be a subtype). Mostly this makes things more flexible and not less (in particular, in the case of coercing function bodies to the return type). However, in some rare cases, this is less flexible. TBH, I'm not exactly sure of the exact effects. I think the change causes us to resolve inferred type variables slightly earlier which might make us slightly more restrictive. Possibly it only affects blocks with unreachable code. E.g., `if ... { fail!(); "Hello" }` used to type check, it no longer does. The fix is to add a semicolon after the string.
2014-08-04 14:20:11 +02:00
|
|
|
ty::ty_vec(typ, None) => {
|
|
|
|
vec_slice_metadata(cx, t, typ, unique_type_id, usage_site_span)
|
2014-05-30 17:09:16 +02:00
|
|
|
}
|
2014-04-29 13:10:23 +12:00
|
|
|
ty::ty_str => {
|
2014-12-25 07:20:48 -05:00
|
|
|
vec_slice_metadata(cx, t, cx.tcx().types.u8, unique_type_id, usage_site_span)
|
2014-04-27 10:19:15 +12:00
|
|
|
}
|
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
|
|
|
ty::ty_trait(..) => {
|
2014-06-11 17:18:57 +12:00
|
|
|
MetadataCreationResult::new(
|
2014-08-06 11:59:40 +02:00
|
|
|
trait_pointer_metadata(cx, ty, Some(t), unique_type_id),
|
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
|
|
|
false)
|
2014-06-11 17:18:57 +12:00
|
|
|
}
|
2014-04-09 19:15:31 +12:00
|
|
|
_ => {
|
DST coercions and DST structs
[breaking-change]
1. The internal layout for traits has changed from (vtable, data) to (data, vtable). If you were relying on this in unsafe transmutes, you might get some very weird and apparently unrelated errors. You should not be doing this! Prefer not to do this at all, but if you must, you should use raw::TraitObject rather than hardcoding rustc's internal representation into your code.
2. The minimal type of reference-to-vec-literals (e.g., `&[1, 2, 3]`) is now a fixed size vec (e.g., `&[int, ..3]`) where it used to be an unsized vec (e.g., `&[int]`). If you want the unszied type, you must explicitly give the type (e.g., `let x: &[_] = &[1, 2, 3]`). Note in particular where multiple blocks must have the same type (e.g., if and else clauses, vec elements), the compiler will not coerce to the unsized type without a hint. E.g., `[&[1], &[1, 2]]` used to be a valid expression of type '[&[int]]'. It no longer type checks since the first element now has type `&[int, ..1]` and the second has type &[int, ..2]` which are incompatible.
3. The type of blocks (including functions) must be coercible to the expected type (used to be a subtype). Mostly this makes things more flexible and not less (in particular, in the case of coercing function bodies to the return type). However, in some rare cases, this is less flexible. TBH, I'm not exactly sure of the exact effects. I think the change causes us to resolve inferred type variables slightly earlier which might make us slightly more restrictive. Possibly it only affects blocks with unreachable code. E.g., `if ... { fail!(); "Hello" }` used to type check, it no longer does. The fix is to add a semicolon after the string.
2014-08-04 14:20:11 +02:00
|
|
|
let pointee_metadata = type_metadata(cx, ty, usage_site_span);
|
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
|
|
|
|
|
|
|
match debug_context(cx).type_map
|
|
|
|
.borrow()
|
|
|
|
.find_metadata_for_unique_id(unique_type_id) {
|
|
|
|
Some(metadata) => return metadata,
|
|
|
|
None => { /* proceed normally */ }
|
|
|
|
};
|
|
|
|
|
DST coercions and DST structs
[breaking-change]
1. The internal layout for traits has changed from (vtable, data) to (data, vtable). If you were relying on this in unsafe transmutes, you might get some very weird and apparently unrelated errors. You should not be doing this! Prefer not to do this at all, but if you must, you should use raw::TraitObject rather than hardcoding rustc's internal representation into your code.
2. The minimal type of reference-to-vec-literals (e.g., `&[1, 2, 3]`) is now a fixed size vec (e.g., `&[int, ..3]`) where it used to be an unsized vec (e.g., `&[int]`). If you want the unszied type, you must explicitly give the type (e.g., `let x: &[_] = &[1, 2, 3]`). Note in particular where multiple blocks must have the same type (e.g., if and else clauses, vec elements), the compiler will not coerce to the unsized type without a hint. E.g., `[&[1], &[1, 2]]` used to be a valid expression of type '[&[int]]'. It no longer type checks since the first element now has type `&[int, ..1]` and the second has type &[int, ..2]` which are incompatible.
3. The type of blocks (including functions) must be coercible to the expected type (used to be a subtype). Mostly this makes things more flexible and not less (in particular, in the case of coercing function bodies to the return type). However, in some rare cases, this is less flexible. TBH, I'm not exactly sure of the exact effects. I think the change causes us to resolve inferred type variables slightly earlier which might make us slightly more restrictive. Possibly it only affects blocks with unreachable code. E.g., `if ... { fail!(); "Hello" }` used to type check, it no longer does. The fix is to add a semicolon after the string.
2014-08-04 14:20:11 +02:00
|
|
|
MetadataCreationResult::new(pointer_type_metadata(cx, t, pointee_metadata),
|
|
|
|
false)
|
2014-04-09 19:15:31 +12:00
|
|
|
}
|
2014-06-16 14:28:05 +02:00
|
|
|
}
|
2014-04-27 10:19:15 +12:00
|
|
|
}
|
2014-11-26 06:01:28 -05:00
|
|
|
ty::ty_bare_fn(_, ref barefnty) => {
|
2014-06-16 14:28:05 +02:00
|
|
|
subroutine_type_metadata(cx, unique_type_id, &barefnty.sig, usage_site_span)
|
2014-04-27 10:19:15 +12:00
|
|
|
}
|
2015-02-28 19:34:16 -05:00
|
|
|
ty::ty_closure(def_id, substs) => {
|
2015-01-24 22:00:03 +02:00
|
|
|
let typer = NormalizingClosureTyper::new(cx.tcx());
|
|
|
|
let sig = typer.closure_type(def_id, substs).sig;
|
2014-10-05 12:19:22 -07:00
|
|
|
subroutine_type_metadata(cx, unique_type_id, &sig, usage_site_span)
|
|
|
|
}
|
2014-12-03 16:01:29 -08:00
|
|
|
ty::ty_struct(def_id, substs) => {
|
2014-06-16 14:28:05 +02:00
|
|
|
prepare_struct_metadata(cx,
|
|
|
|
t,
|
|
|
|
def_id,
|
|
|
|
substs,
|
|
|
|
unique_type_id,
|
|
|
|
usage_site_span).finalize(cx)
|
2014-04-27 10:19:15 +12:00
|
|
|
}
|
2013-03-20 01:17:42 -04:00
|
|
|
ty::ty_tup(ref elements) => {
|
2014-06-16 14:28:05 +02:00
|
|
|
prepare_tuple_metadata(cx,
|
|
|
|
t,
|
2015-02-18 14:48:57 -05:00
|
|
|
&elements[..],
|
2014-06-16 14:28:05 +02:00
|
|
|
unique_type_id,
|
|
|
|
usage_site_span).finalize(cx)
|
2013-08-16 18:46:29 +02:00
|
|
|
}
|
2014-05-16 10:45:16 -07:00
|
|
|
_ => {
|
2015-01-07 11:58:31 -05:00
|
|
|
cx.sess().bug(&format!("debuginfo: unexpected type in type_metadata: {:?}",
|
2015-02-20 14:08:14 -05:00
|
|
|
sty))
|
2014-05-16 10:45:16 -07:00
|
|
|
}
|
2013-06-14 11:38:29 -07:00
|
|
|
};
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2014-05-30 17:09:16 +02:00
|
|
|
{
|
|
|
|
let mut type_map = debug_context(cx).type_map.borrow_mut();
|
|
|
|
|
2014-06-16 14:28:05 +02:00
|
|
|
if already_stored_in_typemap {
|
2014-05-30 17:09:16 +02:00
|
|
|
// Also make sure that we already have a TypeMap entry entry for the unique type id.
|
2014-06-16 14:28:05 +02:00
|
|
|
let metadata_for_uid = match type_map.find_metadata_for_unique_id(unique_type_id) {
|
|
|
|
Some(metadata) => metadata,
|
|
|
|
None => {
|
2014-06-18 15:07:26 +12:00
|
|
|
let unique_type_id_str =
|
|
|
|
type_map.get_unique_type_id_as_string(unique_type_id);
|
|
|
|
let error_message = format!("Expected type metadata for unique \
|
|
|
|
type id '{}' to already be in \
|
|
|
|
the debuginfo::TypeMap but it \
|
2014-09-13 21:09:25 +03:00
|
|
|
was not. (Ty = {})",
|
2015-02-18 14:48:57 -05:00
|
|
|
&unique_type_id_str[..],
|
2014-06-21 03:39:03 -07:00
|
|
|
ppaux::ty_to_string(cx.tcx(), t));
|
2015-02-18 14:48:57 -05:00
|
|
|
cx.sess().span_bug(usage_site_span, &error_message[..]);
|
2014-06-16 14:28:05 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
match type_map.find_metadata_for_type(t) {
|
|
|
|
Some(metadata) => {
|
|
|
|
if metadata != metadata_for_uid {
|
|
|
|
let unique_type_id_str =
|
|
|
|
type_map.get_unique_type_id_as_string(unique_type_id);
|
2014-09-13 21:09:25 +03:00
|
|
|
let error_message = format!("Mismatch between Ty and \
|
2014-06-18 15:07:26 +12:00
|
|
|
UniqueTypeId maps in \
|
|
|
|
debuginfo::TypeMap. \
|
2014-09-13 21:09:25 +03:00
|
|
|
UniqueTypeId={}, Ty={}",
|
2015-02-18 14:48:57 -05:00
|
|
|
&unique_type_id_str[..],
|
2014-06-21 03:39:03 -07:00
|
|
|
ppaux::ty_to_string(cx.tcx(), t));
|
2015-02-18 14:48:57 -05:00
|
|
|
cx.sess().span_bug(usage_site_span, &error_message[..]);
|
2014-06-16 14:28:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
type_map.register_type_with_metadata(cx, t, metadata);
|
|
|
|
}
|
2014-05-30 17:09:16 +02:00
|
|
|
}
|
|
|
|
} else {
|
2014-06-16 14:28:05 +02:00
|
|
|
type_map.register_type_with_metadata(cx, t, metadata);
|
|
|
|
type_map.register_unique_id_with_metadata(cx, unique_type_id, metadata);
|
2014-05-30 17:09:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-16 14:28:05 +02:00
|
|
|
metadata
|
|
|
|
}
|
|
|
|
|
|
|
|
struct MetadataCreationResult {
|
|
|
|
metadata: DIType,
|
|
|
|
already_stored_in_typemap: bool
|
|
|
|
}
|
|
|
|
|
|
|
|
impl MetadataCreationResult {
|
|
|
|
fn new(metadata: DIType, already_stored_in_typemap: bool) -> MetadataCreationResult {
|
|
|
|
MetadataCreationResult {
|
|
|
|
metadata: metadata,
|
|
|
|
already_stored_in_typemap: already_stored_in_typemap
|
|
|
|
}
|
|
|
|
}
|
2011-12-14 15:14:06 -05:00
|
|
|
}
|
|
|
|
|
2015-03-30 09:38:44 -04:00
|
|
|
#[derive(Copy, Clone, PartialEq)]
|
2014-12-11 13:53:30 +01:00
|
|
|
enum InternalDebugLocation {
|
2015-03-25 17:06:52 -07:00
|
|
|
KnownLocation { scope: DIScope, line: usize, col: usize },
|
2013-08-19 18:23:43 +02:00
|
|
|
UnknownLocation
|
|
|
|
}
|
|
|
|
|
2014-12-11 13:53:30 +01:00
|
|
|
impl InternalDebugLocation {
|
2015-03-25 17:06:52 -07:00
|
|
|
fn new(scope: DIScope, line: usize, col: usize) -> InternalDebugLocation {
|
2013-08-19 18:23:43 +02:00
|
|
|
KnownLocation {
|
|
|
|
scope: scope,
|
|
|
|
line: line,
|
|
|
|
col: col,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-11 13:53:30 +01:00
|
|
|
fn set_debug_location(cx: &CrateContext, debug_location: InternalDebugLocation) {
|
2013-12-18 19:09:14 -08:00
|
|
|
if debug_location == debug_context(cx).current_debug_location.get() {
|
2013-06-14 11:59:49 -07:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-08-19 18:23:43 +02:00
|
|
|
let metadata_node;
|
|
|
|
|
|
|
|
match debug_location {
|
2013-12-13 11:43:41 +01:00
|
|
|
KnownLocation { scope, line, .. } => {
|
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
|
|
|
// Always set the column to zero like Clang and GCC
|
|
|
|
let col = UNKNOWN_COLUMN_NUMBER;
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("setting debug location to {} {}", line, col);
|
2015-01-30 19:25:07 +01:00
|
|
|
|
2013-08-19 18:23:43 +02:00
|
|
|
unsafe {
|
2015-01-30 19:25:07 +01:00
|
|
|
metadata_node = llvm::LLVMDIBuilderCreateDebugLocation(
|
|
|
|
debug_context(cx).llcontext,
|
|
|
|
line as c_uint,
|
|
|
|
col as c_uint,
|
|
|
|
scope,
|
|
|
|
ptr::null_mut());
|
2013-08-19 18:23:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
UnknownLocation => {
|
2013-10-21 13:08:31 -07:00
|
|
|
debug!("clearing debug location ");
|
2014-09-14 20:27:36 -07:00
|
|
|
metadata_node = ptr::null_mut();
|
2013-08-19 18:23:43 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
unsafe {
|
2014-09-05 09:18:53 -07:00
|
|
|
llvm::LLVMSetCurrentDebugLocation(cx.raw_builder(), metadata_node);
|
2013-01-10 21:23:07 -08:00
|
|
|
}
|
2013-08-19 18:23:43 +02:00
|
|
|
|
2013-12-18 19:09:14 -08:00
|
|
|
debug_context(cx).current_debug_location.set(debug_location);
|
2011-11-16 19:30:45 -05:00
|
|
|
}
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
//=-----------------------------------------------------------------------------
|
2013-06-18 13:06:41 +02:00
|
|
|
// Utility Functions
|
2014-06-18 15:07:26 +12:00
|
|
|
//=-----------------------------------------------------------------------------
|
2013-06-14 11:38:29 -07:00
|
|
|
|
2014-07-10 17:01:11 +02:00
|
|
|
fn contains_nodebug_attribute(attributes: &[ast::Attribute]) -> bool {
|
|
|
|
attributes.iter().any(|attr| {
|
|
|
|
let meta_item: &ast::MetaItem = &*attr.node.value;
|
|
|
|
match meta_item.node {
|
2015-02-18 14:48:57 -05:00
|
|
|
ast::MetaWord(ref value) => &value[..] == "no_debug",
|
2014-07-10 17:01:11 +02:00
|
|
|
_ => false
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2013-06-18 13:06:41 +02:00
|
|
|
/// Return codemap::Loc corresponding to the beginning of the span
|
2013-08-31 18:13:04 +02:00
|
|
|
fn span_start(cx: &CrateContext, span: Span) -> codemap::Loc {
|
2014-03-16 20:56:24 +02:00
|
|
|
cx.sess().codemap().lookup_char_pos(span.lo)
|
2013-06-18 13:06:41 +02:00
|
|
|
}
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2014-01-30 17:19:19 -05:00
|
|
|
fn size_and_align_of(cx: &CrateContext, llvm_type: Type) -> (u64, u64) {
|
2014-10-14 23:36:11 +03:00
|
|
|
(machine::llsize_of_alloc(cx, llvm_type), machine::llalign_of_min(cx, llvm_type) as u64)
|
2013-06-18 13:06:41 +02:00
|
|
|
}
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2014-10-14 23:36:11 +03:00
|
|
|
fn bytes_to_bits(bytes: u64) -> u64 {
|
|
|
|
bytes * 8
|
2013-06-20 16:00:59 +02:00
|
|
|
}
|
|
|
|
|
2013-06-18 13:06:41 +02:00
|
|
|
#[inline]
|
2014-09-29 22:11:30 +03:00
|
|
|
fn debug_context<'a, 'tcx>(cx: &'a CrateContext<'a, 'tcx>)
|
|
|
|
-> &'a CrateDebugContext<'tcx> {
|
|
|
|
let debug_context: &'a CrateDebugContext<'tcx> = cx.dbg_cx().as_ref().unwrap();
|
2013-12-18 19:12:47 -08:00
|
|
|
debug_context
|
2011-12-09 11:32:23 -05:00
|
|
|
}
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-18 13:06:41 +02:00
|
|
|
#[inline]
|
2014-07-19 00:45:17 +12:00
|
|
|
#[allow(non_snake_case)]
|
2013-06-18 13:06:41 +02:00
|
|
|
fn DIB(cx: &CrateContext) -> DIBuilderRef {
|
2014-10-14 23:05:01 -07:00
|
|
|
cx.dbg_cx().as_ref().unwrap().builder
|
2011-12-09 11:32:23 -05:00
|
|
|
}
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2013-08-23 18:45:02 +02:00
|
|
|
fn fn_should_be_ignored(fcx: &FunctionContext) -> bool {
|
2014-12-19 11:37:49 +01:00
|
|
|
match fcx.debug_context {
|
|
|
|
FunctionDebugContext::RegularContext(_) => false,
|
2013-08-23 18:45:02 +02:00
|
|
|
_ => true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
fn assert_type_for_node_id(cx: &CrateContext,
|
|
|
|
node_id: ast::NodeId,
|
|
|
|
error_reporting_span: Span) {
|
2015-03-26 10:57:42 +01:00
|
|
|
if !cx.tcx().node_types().contains_key(&node_id) {
|
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
|
|
|
cx.sess().span_bug(error_reporting_span,
|
|
|
|
"debuginfo: Could not find type for node id!");
|
2013-09-11 14:09:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-14 07:07:09 +02:00
|
|
|
fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: ast::DefId)
|
|
|
|
-> (DIScope, Span) {
|
|
|
|
let containing_scope = namespace_for_item(cx, def_id).scope;
|
2014-02-05 22:15:24 +01:00
|
|
|
let definition_span = if def_id.krate == ast::LOCAL_CRATE {
|
2014-09-05 09:18:53 -07:00
|
|
|
cx.tcx().map.span(def_id.node)
|
2013-09-09 17:58:58 +02:00
|
|
|
} else {
|
|
|
|
// For external items there is no span information
|
2014-01-01 15:53:22 +09:00
|
|
|
codemap::DUMMY_SP
|
2013-10-01 12:24:50 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
(containing_scope, definition_span)
|
2013-09-09 17:58:58 +02:00
|
|
|
}
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// This procedure builds the *scope map* for a given function, which maps any
|
|
|
|
// given ast::NodeId in the function's AST to the correct DIScope metadata instance.
|
2013-08-05 11:12:40 +02:00
|
|
|
//
|
2014-06-18 15:07:26 +12:00
|
|
|
// This builder procedure walks the AST in execution order and keeps track of
|
|
|
|
// what belongs to which scope, creating DIScope DIEs along the way, and
|
|
|
|
// introducing *artificial* lexical scope descriptors where necessary. These
|
|
|
|
// artificial scopes allow GDB to correctly handle name shadowing.
|
2014-12-19 11:37:49 +01:00
|
|
|
fn create_scope_map(cx: &CrateContext,
|
|
|
|
args: &[ast::Arg],
|
|
|
|
fn_entry_block: &ast::Block,
|
|
|
|
fn_metadata: DISubprogram,
|
|
|
|
fn_ast_id: ast::NodeId)
|
|
|
|
-> NodeMap<DIScope> {
|
2015-01-16 14:27:43 -08:00
|
|
|
let mut scope_map = NodeMap();
|
2014-12-19 11:37:49 +01:00
|
|
|
|
2014-09-05 09:18:53 -07:00
|
|
|
let def_map = &cx.tcx().def_map;
|
2013-08-05 11:12:40 +02:00
|
|
|
|
|
|
|
struct ScopeStackEntry {
|
|
|
|
scope_metadata: DIScope,
|
2015-03-23 19:41:35 -05:00
|
|
|
name: Option<ast::Name>
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
|
2015-03-23 19:41:35 -05:00
|
|
|
let mut scope_stack = vec!(ScopeStackEntry { scope_metadata: fn_metadata, name: None });
|
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
|
|
|
scope_map.insert(fn_ast_id, fn_metadata);
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// Push argument identifiers onto the stack so arguments integrate nicely
|
|
|
|
// with variable shadowing.
|
2015-01-31 12:20:46 -05:00
|
|
|
for arg in args {
|
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
|
|
|
pat_util::pat_bindings(def_map, &*arg.pat, |_, node_id, _, path1| {
|
2014-06-18 15:07:26 +12:00
|
|
|
scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata,
|
2015-03-23 19:41:35 -05:00
|
|
|
name: Some(path1.node.name) });
|
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
|
|
|
scope_map.insert(node_id, fn_metadata);
|
2013-11-21 15:42:55 -08:00
|
|
|
})
|
2013-08-07 00:13:31 +02:00
|
|
|
}
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// Clang creates a separate scope for function bodies, so let's do this too.
|
2013-12-13 12:40:06 +01:00
|
|
|
with_new_scope(cx,
|
|
|
|
fn_entry_block.span,
|
|
|
|
&mut scope_stack,
|
2014-12-19 11:37:49 +01:00
|
|
|
&mut scope_map,
|
2013-12-13 12:40:06 +01:00
|
|
|
|cx, scope_stack, scope_map| {
|
|
|
|
walk_block(cx, fn_entry_block, scope_stack, scope_map);
|
|
|
|
});
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2014-12-19 11:37:49 +01:00
|
|
|
return scope_map;
|
|
|
|
|
|
|
|
|
2013-08-05 11:12:40 +02:00
|
|
|
// local helper functions for walking the AST.
|
2014-12-09 13:44:51 -05:00
|
|
|
fn with_new_scope<F>(cx: &CrateContext,
|
|
|
|
scope_span: Span,
|
|
|
|
scope_stack: &mut Vec<ScopeStackEntry> ,
|
|
|
|
scope_map: &mut NodeMap<DIScope>,
|
|
|
|
inner_walk: F) where
|
|
|
|
F: FnOnce(&CrateContext, &mut Vec<ScopeStackEntry>, &mut NodeMap<DIScope>),
|
|
|
|
{
|
2013-08-05 11:12:40 +02:00
|
|
|
// Create a new lexical scope and push it onto the stack
|
2014-03-16 20:56:24 +02:00
|
|
|
let loc = cx.sess().codemap().lookup_char_pos(scope_span.lo);
|
2015-02-20 14:08:14 -05:00
|
|
|
let file_metadata = file_metadata(cx, &loc.file.name);
|
2013-12-23 15:08:23 +01:00
|
|
|
let parent_scope = scope_stack.last().unwrap().scope_metadata;
|
2013-08-05 11:12:40 +02:00
|
|
|
|
|
|
|
let scope_metadata = unsafe {
|
|
|
|
llvm::LLVMDIBuilderCreateLexicalBlock(
|
|
|
|
DIB(cx),
|
|
|
|
parent_scope,
|
|
|
|
file_metadata,
|
|
|
|
loc.line as c_uint,
|
2015-01-17 23:49:08 +00:00
|
|
|
loc.col.to_usize() as c_uint)
|
2013-08-05 11:12:40 +02:00
|
|
|
};
|
|
|
|
|
2015-03-23 19:41:35 -05:00
|
|
|
scope_stack.push(ScopeStackEntry { scope_metadata: scope_metadata, name: None });
|
2013-08-05 11:12:40 +02:00
|
|
|
|
|
|
|
inner_walk(cx, scope_stack, scope_map);
|
|
|
|
|
|
|
|
// pop artificial scopes
|
2015-03-23 19:41:35 -05:00
|
|
|
while scope_stack.last().unwrap().name.is_some() {
|
2013-08-05 11:12:40 +02:00
|
|
|
scope_stack.pop();
|
|
|
|
}
|
|
|
|
|
2013-12-23 15:08:23 +01:00
|
|
|
if scope_stack.last().unwrap().scope_metadata != scope_metadata {
|
2014-03-05 16:36:01 +02:00
|
|
|
cx.sess().span_bug(scope_span, "debuginfo: Inconsistency in scope management.");
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
scope_stack.pop();
|
|
|
|
}
|
|
|
|
|
2013-12-19 16:47:15 -08:00
|
|
|
fn walk_block(cx: &CrateContext,
|
2013-08-05 11:12:40 +02:00
|
|
|
block: &ast::Block,
|
2014-03-04 10:02:49 -08:00
|
|
|
scope_stack: &mut Vec<ScopeStackEntry> ,
|
2014-11-10 00:59:56 +02:00
|
|
|
scope_map: &mut NodeMap<DIScope>) {
|
2013-12-23 15:08:23 +01:00
|
|
|
scope_map.insert(block.id, scope_stack.last().unwrap().scope_metadata);
|
2013-08-05 11:12:40 +02:00
|
|
|
|
|
|
|
// The interesting things here are statements and the concluding expression.
|
2015-01-31 12:20:46 -05:00
|
|
|
for statement in &block.stmts {
|
2014-05-16 10:15:33 -07:00
|
|
|
scope_map.insert(ast_util::stmt_id(&**statement),
|
2013-12-23 15:08:23 +01:00
|
|
|
scope_stack.last().unwrap().scope_metadata);
|
2013-08-05 11:12:40 +02:00
|
|
|
|
|
|
|
match statement.node {
|
2014-05-16 10:15:33 -07:00
|
|
|
ast::StmtDecl(ref decl, _) =>
|
|
|
|
walk_decl(cx, &**decl, scope_stack, scope_map),
|
|
|
|
ast::StmtExpr(ref exp, _) |
|
|
|
|
ast::StmtSemi(ref exp, _) =>
|
|
|
|
walk_expr(cx, &**exp, scope_stack, scope_map),
|
2014-06-18 15:07:26 +12:00
|
|
|
ast::StmtMac(..) => () // Ignore macros (which should be expanded anyway).
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-31 12:20:46 -05:00
|
|
|
if let Some(ref exp) = block.expr {
|
2014-05-16 10:15:33 -07:00
|
|
|
walk_expr(cx, &**exp, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-19 16:47:15 -08:00
|
|
|
fn walk_decl(cx: &CrateContext,
|
2013-09-02 03:45:37 +02:00
|
|
|
decl: &ast::Decl,
|
2014-03-04 10:02:49 -08:00
|
|
|
scope_stack: &mut Vec<ScopeStackEntry> ,
|
2014-11-10 00:59:56 +02:00
|
|
|
scope_map: &mut NodeMap<DIScope>) {
|
2013-08-05 11:12:40 +02:00
|
|
|
match *decl {
|
2014-09-07 20:09:06 +03:00
|
|
|
codemap::Spanned { node: ast::DeclLocal(ref local), .. } => {
|
2013-12-23 15:08:23 +01:00
|
|
|
scope_map.insert(local.id, scope_stack.last().unwrap().scope_metadata);
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2014-09-07 20:09:06 +03:00
|
|
|
walk_pattern(cx, &*local.pat, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2015-01-31 12:20:46 -05:00
|
|
|
if let Some(ref exp) = local.init {
|
2014-05-16 10:15:33 -07:00
|
|
|
walk_expr(cx, &**exp, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => ()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-19 16:47:15 -08:00
|
|
|
fn walk_pattern(cx: &CrateContext,
|
2014-09-07 20:09:06 +03:00
|
|
|
pat: &ast::Pat,
|
2014-03-04 10:02:49 -08:00
|
|
|
scope_stack: &mut Vec<ScopeStackEntry> ,
|
2014-11-10 00:59:56 +02:00
|
|
|
scope_map: &mut NodeMap<DIScope>) {
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2014-09-05 09:18:53 -07:00
|
|
|
let def_map = &cx.tcx().def_map;
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// Unfortunately, we cannot just use pat_util::pat_bindings() or
|
|
|
|
// ast_util::walk_pat() here because we have to visit *all* nodes in
|
|
|
|
// order to put them into the scope map. The above functions don't do that.
|
2013-08-05 11:12:40 +02:00
|
|
|
match pat.node {
|
2014-06-30 18:02:14 -07:00
|
|
|
ast::PatIdent(_, ref path1, ref sub_pat_opt) => {
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// Check if this is a binding. If so we need to put it on the
|
|
|
|
// scope stack and maybe introduce an artificial scope
|
2014-05-16 10:15:33 -07:00
|
|
|
if pat_util::pat_is_binding(def_map, &*pat) {
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2015-03-23 19:41:35 -05:00
|
|
|
let name = path1.node.name;
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// LLVM does not properly generate 'DW_AT_start_scope' fields
|
|
|
|
// for variable DIEs. For this reason we have to introduce
|
|
|
|
// an artificial scope at bindings whenever a variable with
|
|
|
|
// the same name is declared in *any* parent scope.
|
2013-08-05 11:12:40 +02:00
|
|
|
//
|
|
|
|
// Otherwise the following error occurs:
|
|
|
|
//
|
|
|
|
// let x = 10;
|
|
|
|
//
|
|
|
|
// do_something(); // 'gdb print x' correctly prints 10
|
|
|
|
//
|
|
|
|
// {
|
2014-06-18 15:07:26 +12:00
|
|
|
// do_something(); // 'gdb print x' prints 0, because it
|
|
|
|
// // already reads the uninitialized 'x'
|
|
|
|
// // from the next line...
|
2013-08-05 11:12:40 +02:00
|
|
|
// let x = 100;
|
|
|
|
// do_something(); // 'gdb print x' correctly prints 100
|
|
|
|
// }
|
|
|
|
|
|
|
|
// Is there already a binding with that name?
|
2013-09-06 23:19:11 -07:00
|
|
|
// N.B.: this comparison must be UNhygienic... because
|
|
|
|
// gdb knows nothing about the context, so any two
|
|
|
|
// variables with the same name will cause the problem.
|
2013-08-05 11:12:40 +02:00
|
|
|
let need_new_scope = scope_stack
|
2013-08-07 00:13:31 +02:00
|
|
|
.iter()
|
2015-03-23 19:41:35 -05:00
|
|
|
.any(|entry| entry.name == Some(name));
|
2013-08-05 11:12:40 +02:00
|
|
|
|
|
|
|
if need_new_scope {
|
|
|
|
// Create a new lexical scope and push it onto the stack
|
2014-03-16 20:56:24 +02:00
|
|
|
let loc = cx.sess().codemap().lookup_char_pos(pat.span.lo);
|
2015-02-20 14:08:14 -05:00
|
|
|
let file_metadata = file_metadata(cx, &loc.file.name);
|
2013-12-23 15:08:23 +01:00
|
|
|
let parent_scope = scope_stack.last().unwrap().scope_metadata;
|
2013-08-05 11:12:40 +02:00
|
|
|
|
|
|
|
let scope_metadata = unsafe {
|
|
|
|
llvm::LLVMDIBuilderCreateLexicalBlock(
|
|
|
|
DIB(cx),
|
|
|
|
parent_scope,
|
|
|
|
file_metadata,
|
|
|
|
loc.line as c_uint,
|
2015-01-17 23:49:08 +00:00
|
|
|
loc.col.to_usize() as c_uint)
|
2013-08-05 11:12:40 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
scope_stack.push(ScopeStackEntry {
|
|
|
|
scope_metadata: scope_metadata,
|
2015-03-23 19:41:35 -05:00
|
|
|
name: Some(name)
|
2013-08-05 11:12:40 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
} else {
|
|
|
|
// Push a new entry anyway so the name can be found
|
2013-12-23 15:08:23 +01:00
|
|
|
let prev_metadata = scope_stack.last().unwrap().scope_metadata;
|
2013-08-05 11:12:40 +02:00
|
|
|
scope_stack.push(ScopeStackEntry {
|
|
|
|
scope_metadata: prev_metadata,
|
2015-03-23 19:41:35 -05:00
|
|
|
name: Some(name)
|
2013-08-05 11:12:40 +02:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-23 15:08:23 +01:00
|
|
|
scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2015-01-31 12:20:46 -05:00
|
|
|
if let Some(ref sub_pat) = *sub_pat_opt {
|
2014-09-07 20:09:06 +03:00
|
|
|
walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-06 17:04:44 +02:00
|
|
|
ast::PatWild(_) => {
|
2013-12-23 15:08:23 +01:00
|
|
|
scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
|
2013-09-02 03:45:37 +02:00
|
|
|
ast::PatEnum(_, ref sub_pats_opt) => {
|
2013-12-23 15:08:23 +01:00
|
|
|
scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2015-01-31 12:20:46 -05:00
|
|
|
if let Some(ref sub_pats) = *sub_pats_opt {
|
|
|
|
for p in sub_pats {
|
2014-09-07 20:09:06 +03:00
|
|
|
walk_pattern(cx, &**p, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-25 10:53:28 -06:00
|
|
|
ast::PatQPath(..) => {
|
|
|
|
scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
|
|
|
|
}
|
|
|
|
|
2013-09-02 03:45:37 +02:00
|
|
|
ast::PatStruct(_, ref field_pats, _) => {
|
2013-12-23 15:08:23 +01:00
|
|
|
scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2014-10-06 13:36:53 +13:00
|
|
|
for &codemap::Spanned {
|
|
|
|
node: ast::FieldPat { pat: ref sub_pat, .. },
|
|
|
|
..
|
|
|
|
} in field_pats.iter() {
|
2014-09-07 20:09:06 +03:00
|
|
|
walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-02 03:45:37 +02:00
|
|
|
ast::PatTup(ref sub_pats) => {
|
2013-12-23 15:08:23 +01:00
|
|
|
scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2015-01-31 12:20:46 -05:00
|
|
|
for sub_pat in sub_pats {
|
2014-09-07 20:09:06 +03:00
|
|
|
walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-05 15:56:25 -08:00
|
|
|
ast::PatBox(ref sub_pat) | ast::PatRegion(ref sub_pat, _) => {
|
2013-12-23 15:08:23 +01:00
|
|
|
scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
|
2014-09-07 20:09:06 +03:00
|
|
|
walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
|
2014-05-16 10:15:33 -07:00
|
|
|
ast::PatLit(ref exp) => {
|
2013-12-23 15:08:23 +01:00
|
|
|
scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
|
2014-05-16 10:15:33 -07:00
|
|
|
walk_expr(cx, &**exp, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
|
2014-05-16 10:15:33 -07:00
|
|
|
ast::PatRange(ref exp1, ref exp2) => {
|
2013-12-23 15:08:23 +01:00
|
|
|
scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
|
2014-05-16 10:15:33 -07:00
|
|
|
walk_expr(cx, &**exp1, scope_stack, scope_map);
|
|
|
|
walk_expr(cx, &**exp2, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
|
2013-09-02 03:45:37 +02:00
|
|
|
ast::PatVec(ref front_sub_pats, ref middle_sub_pats, ref back_sub_pats) => {
|
2013-12-23 15:08:23 +01:00
|
|
|
scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2015-01-31 12:20:46 -05:00
|
|
|
for sub_pat in front_sub_pats {
|
2014-09-07 20:09:06 +03:00
|
|
|
walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
|
2015-01-31 12:20:46 -05:00
|
|
|
if let Some(ref sub_pat) = *middle_sub_pats {
|
2014-09-07 20:09:06 +03:00
|
|
|
walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
|
2015-01-31 12:20:46 -05:00
|
|
|
for sub_pat in back_sub_pats {
|
2014-09-07 20:09:06 +03:00
|
|
|
walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
}
|
2014-05-19 13:29:41 -07:00
|
|
|
|
|
|
|
ast::PatMac(_) => {
|
2014-12-19 11:37:49 +01:00
|
|
|
cx.sess().span_bug(pat.span, "debuginfo::create_scope_map() - \
|
2014-05-19 13:29:41 -07:00
|
|
|
Found unexpanded macro.");
|
|
|
|
}
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-19 16:47:15 -08:00
|
|
|
fn walk_expr(cx: &CrateContext,
|
2013-09-02 03:45:37 +02:00
|
|
|
exp: &ast::Expr,
|
2014-03-04 10:02:49 -08:00
|
|
|
scope_stack: &mut Vec<ScopeStackEntry> ,
|
2014-11-10 00:59:56 +02:00
|
|
|
scope_map: &mut NodeMap<DIScope>) {
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2013-12-23 15:08:23 +01:00
|
|
|
scope_map.insert(exp.id, scope_stack.last().unwrap().scope_metadata);
|
2013-08-05 11:12:40 +02:00
|
|
|
|
|
|
|
match exp.node {
|
2013-09-02 03:45:37 +02:00
|
|
|
ast::ExprLit(_) |
|
|
|
|
ast::ExprBreak(_) |
|
|
|
|
ast::ExprAgain(_) |
|
2015-02-17 19:29:13 +02:00
|
|
|
ast::ExprPath(..) => {}
|
2013-09-02 03:45:37 +02:00
|
|
|
|
2014-05-16 10:15:33 -07:00
|
|
|
ast::ExprCast(ref sub_exp, _) |
|
|
|
|
ast::ExprAddrOf(_, ref sub_exp) |
|
2014-11-23 12:14:35 +01:00
|
|
|
ast::ExprField(ref sub_exp, _) |
|
|
|
|
ast::ExprTupField(ref sub_exp, _) |
|
2014-05-16 10:15:33 -07:00
|
|
|
ast::ExprParen(ref sub_exp) =>
|
|
|
|
walk_expr(cx, &**sub_exp, scope_stack, scope_map),
|
2013-09-02 03:45:37 +02:00
|
|
|
|
2014-05-16 10:15:33 -07:00
|
|
|
ast::ExprBox(ref place, ref sub_expr) => {
|
2014-12-16 14:30:30 +01:00
|
|
|
place.as_ref().map(
|
|
|
|
|e| walk_expr(cx, &**e, scope_stack, scope_map));
|
2014-05-16 10:15:33 -07:00
|
|
|
walk_expr(cx, &**sub_expr, scope_stack, scope_map);
|
2013-12-17 16:46:18 -08:00
|
|
|
}
|
|
|
|
|
2014-09-07 20:09:06 +03:00
|
|
|
ast::ExprRet(ref exp_opt) => match *exp_opt {
|
|
|
|
Some(ref sub_exp) => walk_expr(cx, &**sub_exp, scope_stack, scope_map),
|
2013-08-05 11:12:40 +02:00
|
|
|
None => ()
|
|
|
|
},
|
|
|
|
|
2014-05-16 10:15:33 -07:00
|
|
|
ast::ExprUnary(_, ref sub_exp) => {
|
|
|
|
walk_expr(cx, &**sub_exp, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
|
2014-05-16 10:15:33 -07:00
|
|
|
ast::ExprAssignOp(_, ref lhs, ref rhs) |
|
2014-12-19 11:47:48 +13:00
|
|
|
ast::ExprIndex(ref lhs, ref rhs) |
|
2014-05-16 10:15:33 -07:00
|
|
|
ast::ExprBinary(_, ref lhs, ref rhs) => {
|
|
|
|
walk_expr(cx, &**lhs, scope_stack, scope_map);
|
|
|
|
walk_expr(cx, &**rhs, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
|
2014-12-15 13:17:11 +13:00
|
|
|
ast::ExprRange(ref start, ref end) => {
|
2014-12-18 17:55:04 +13:00
|
|
|
start.as_ref().map(|e| walk_expr(cx, &**e, scope_stack, scope_map));
|
2014-12-15 13:17:11 +13:00
|
|
|
end.as_ref().map(|e| walk_expr(cx, &**e, scope_stack, scope_map));
|
2014-12-13 18:41:02 +13:00
|
|
|
}
|
|
|
|
|
2014-04-04 13:12:18 +03:00
|
|
|
ast::ExprVec(ref init_expressions) |
|
|
|
|
ast::ExprTup(ref init_expressions) => {
|
2015-01-31 12:20:46 -05:00
|
|
|
for ie in init_expressions {
|
2014-05-16 10:15:33 -07:00
|
|
|
walk_expr(cx, &**ie, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-16 10:15:33 -07:00
|
|
|
ast::ExprAssign(ref sub_exp1, ref sub_exp2) |
|
|
|
|
ast::ExprRepeat(ref sub_exp1, ref sub_exp2) => {
|
|
|
|
walk_expr(cx, &**sub_exp1, scope_stack, scope_map);
|
|
|
|
walk_expr(cx, &**sub_exp2, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
|
2014-05-16 10:15:33 -07:00
|
|
|
ast::ExprIf(ref cond_exp, ref then_block, ref opt_else_exp) => {
|
|
|
|
walk_expr(cx, &**cond_exp, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2013-11-21 15:42:55 -08:00
|
|
|
with_new_scope(cx,
|
|
|
|
then_block.span,
|
|
|
|
scope_stack,
|
|
|
|
scope_map,
|
|
|
|
|cx, scope_stack, scope_map| {
|
2014-05-16 10:15:33 -07:00
|
|
|
walk_block(cx, &**then_block, scope_stack, scope_map);
|
2013-11-21 15:42:55 -08:00
|
|
|
});
|
2013-08-05 11:12:40 +02:00
|
|
|
|
|
|
|
match *opt_else_exp {
|
2014-05-16 10:15:33 -07:00
|
|
|
Some(ref else_exp) =>
|
|
|
|
walk_expr(cx, &**else_exp, scope_stack, scope_map),
|
2013-08-05 11:12:40 +02:00
|
|
|
_ => ()
|
|
|
|
}
|
2014-08-24 19:08:48 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
ast::ExprIfLet(..) => {
|
2014-12-19 11:37:49 +01:00
|
|
|
cx.sess().span_bug(exp.span, "debuginfo::create_scope_map() - \
|
2014-08-24 19:08:48 -07:00
|
|
|
Found unexpanded if-let.");
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
|
2014-07-25 20:12:51 -04:00
|
|
|
ast::ExprWhile(ref cond_exp, ref loop_body, _) => {
|
2014-05-16 10:15:33 -07:00
|
|
|
walk_expr(cx, &**cond_exp, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2013-11-21 15:42:55 -08:00
|
|
|
with_new_scope(cx,
|
|
|
|
loop_body.span,
|
|
|
|
scope_stack,
|
|
|
|
scope_map,
|
|
|
|
|cx, scope_stack, scope_map| {
|
2014-05-16 10:15:33 -07:00
|
|
|
walk_block(cx, &**loop_body, scope_stack, scope_map);
|
2013-11-21 15:42:55 -08:00
|
|
|
})
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
|
2014-10-03 00:41:24 -04:00
|
|
|
ast::ExprWhileLet(..) => {
|
2014-12-19 11:37:49 +01:00
|
|
|
cx.sess().span_bug(exp.span, "debuginfo::create_scope_map() - \
|
2014-10-03 00:41:24 -04:00
|
|
|
Found unexpanded while-let.");
|
|
|
|
}
|
|
|
|
|
2015-01-08 18:04:26 -05:00
|
|
|
ast::ExprForLoop(..) => {
|
|
|
|
cx.sess().span_bug(exp.span, "debuginfo::create_scope_map() - \
|
|
|
|
Found unexpanded for loop.");
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
|
2013-09-02 03:45:37 +02:00
|
|
|
ast::ExprMac(_) => {
|
2014-12-19 11:37:49 +01:00
|
|
|
cx.sess().span_bug(exp.span, "debuginfo::create_scope_map() - \
|
2014-03-05 16:36:01 +02:00
|
|
|
Found unexpanded macro.");
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
|
2014-05-16 10:15:33 -07:00
|
|
|
ast::ExprLoop(ref block, _) |
|
|
|
|
ast::ExprBlock(ref block) => {
|
2013-11-21 15:42:55 -08:00
|
|
|
with_new_scope(cx,
|
|
|
|
block.span,
|
|
|
|
scope_stack,
|
|
|
|
scope_map,
|
|
|
|
|cx, scope_stack, scope_map| {
|
2014-05-16 10:15:33 -07:00
|
|
|
walk_block(cx, &**block, scope_stack, scope_map);
|
2013-11-21 15:42:55 -08:00
|
|
|
})
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
|
2015-02-03 11:34:05 -05:00
|
|
|
ast::ExprClosure(_, ref decl, ref block) => {
|
2013-11-21 15:42:55 -08:00
|
|
|
with_new_scope(cx,
|
|
|
|
block.span,
|
|
|
|
scope_stack,
|
|
|
|
scope_map,
|
|
|
|
|cx, scope_stack, scope_map| {
|
2015-01-31 12:20:46 -05:00
|
|
|
for &ast::Arg { pat: ref pattern, .. } in &decl.inputs {
|
2014-09-07 20:09:06 +03:00
|
|
|
walk_pattern(cx, &**pattern, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
|
2014-05-16 10:15:33 -07:00
|
|
|
walk_block(cx, &**block, scope_stack, scope_map);
|
2013-11-21 15:42:55 -08:00
|
|
|
})
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
|
2014-05-16 10:15:33 -07:00
|
|
|
ast::ExprCall(ref fn_exp, ref args) => {
|
|
|
|
walk_expr(cx, &**fn_exp, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2015-01-31 12:20:46 -05:00
|
|
|
for arg_exp in args {
|
2014-05-16 10:15:33 -07:00
|
|
|
walk_expr(cx, &**arg_exp, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-26 16:06:45 +02:00
|
|
|
ast::ExprMethodCall(_, _, ref args) => {
|
2015-01-31 12:20:46 -05:00
|
|
|
for arg_exp in args {
|
2014-05-16 10:15:33 -07:00
|
|
|
walk_expr(cx, &**arg_exp, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-25 14:55:00 -07:00
|
|
|
ast::ExprMatch(ref discriminant_exp, ref arms, _) => {
|
2014-05-16 10:15:33 -07:00
|
|
|
walk_expr(cx, &**discriminant_exp, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
// For each arm we have to first walk the pattern as these might
|
|
|
|
// introduce new artificial scopes. It should be sufficient to
|
|
|
|
// walk only one pattern per arm, as they all must contain the
|
|
|
|
// same binding names.
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2015-01-31 12:20:46 -05:00
|
|
|
for arm_ref in arms {
|
2014-10-14 23:05:01 -07:00
|
|
|
let arm_span = arm_ref.pats[0].span;
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2013-11-21 15:42:55 -08:00
|
|
|
with_new_scope(cx,
|
|
|
|
arm_span,
|
|
|
|
scope_stack,
|
|
|
|
scope_map,
|
|
|
|
|cx, scope_stack, scope_map| {
|
2015-01-31 12:20:46 -05:00
|
|
|
for pat in &arm_ref.pats {
|
2014-09-07 20:09:06 +03:00
|
|
|
walk_pattern(cx, &**pat, scope_stack, scope_map);
|
2013-08-16 18:46:29 +02:00
|
|
|
}
|
2013-08-05 11:12:40 +02:00
|
|
|
|
2015-01-31 12:20:46 -05:00
|
|
|
if let Some(ref guard_exp) = arm_ref.guard {
|
2014-05-16 10:15:33 -07:00
|
|
|
walk_expr(cx, &**guard_exp, scope_stack, scope_map)
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
|
2014-05-16 10:15:33 -07:00
|
|
|
walk_expr(cx, &*arm_ref.body, scope_stack, scope_map);
|
2013-11-21 15:42:55 -08:00
|
|
|
})
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-02 03:45:37 +02:00
|
|
|
ast::ExprStruct(_, ref fields, ref base_exp) => {
|
2015-01-31 12:20:46 -05:00
|
|
|
for &ast::Field { expr: ref exp, .. } in fields {
|
2014-05-16 10:15:33 -07:00
|
|
|
walk_expr(cx, &**exp, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
match *base_exp {
|
2014-05-16 10:15:33 -07:00
|
|
|
Some(ref exp) => walk_expr(cx, &**exp, scope_stack, scope_map),
|
2013-08-05 11:12:40 +02:00
|
|
|
None => ()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-06 13:36:53 +13:00
|
|
|
ast::ExprInlineAsm(ast::InlineAsm { ref inputs,
|
|
|
|
ref outputs,
|
2014-01-09 15:05:33 +02:00
|
|
|
.. }) => {
|
2014-10-01 01:26:04 +03:00
|
|
|
// inputs, outputs: Vec<(String, P<Expr>)>
|
2015-01-31 12:20:46 -05:00
|
|
|
for &(_, ref exp) in inputs {
|
2014-05-16 10:15:33 -07:00
|
|
|
walk_expr(cx, &**exp, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
|
2015-01-31 12:20:46 -05:00
|
|
|
for &(_, ref exp, _) in outputs {
|
2014-05-16 10:15:33 -07:00
|
|
|
walk_expr(cx, &**exp, scope_stack, scope_map);
|
2013-08-05 11:12:40 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-09-06 16:00:08 +02:00
|
|
|
|
|
|
|
|
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
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
// Type Names for Debug Info
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Compute the name of the type as it should be stored in debuginfo. Does not do
|
|
|
|
// any caching, i.e. calling the function twice with the same type will also do
|
|
|
|
// the work twice. The `qualified` parameter only affects the first level of the
|
|
|
|
// type name, further levels (i.e. type parameters) are always fully qualified.
|
2014-09-29 22:11:30 +03:00
|
|
|
fn compute_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|
|
|
t: Ty<'tcx>,
|
|
|
|
qualified: bool)
|
|
|
|
-> String {
|
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 mut result = String::with_capacity(64);
|
|
|
|
push_debuginfo_type_name(cx, t, qualified, &mut result);
|
|
|
|
result
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pushes the name of the type as it should be stored in debuginfo on the
|
|
|
|
// `output` String. See also compute_debuginfo_type_name().
|
2014-09-29 22:11:30 +03:00
|
|
|
fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|
|
|
t: Ty<'tcx>,
|
|
|
|
qualified: bool,
|
|
|
|
output: &mut String) {
|
2014-10-31 10:51:16 +02:00
|
|
|
match t.sty {
|
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
|
|
|
ty::ty_bool => output.push_str("bool"),
|
|
|
|
ty::ty_char => output.push_str("char"),
|
|
|
|
ty::ty_str => output.push_str("str"),
|
2015-03-24 13:26:16 -07:00
|
|
|
ty::ty_int(ast::TyIs) => output.push_str("isize"),
|
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
|
|
|
ty::ty_int(ast::TyI8) => output.push_str("i8"),
|
|
|
|
ty::ty_int(ast::TyI16) => output.push_str("i16"),
|
|
|
|
ty::ty_int(ast::TyI32) => output.push_str("i32"),
|
|
|
|
ty::ty_int(ast::TyI64) => output.push_str("i64"),
|
2015-03-24 13:26:16 -07:00
|
|
|
ty::ty_uint(ast::TyUs) => output.push_str("usize"),
|
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
|
|
|
ty::ty_uint(ast::TyU8) => output.push_str("u8"),
|
|
|
|
ty::ty_uint(ast::TyU16) => output.push_str("u16"),
|
|
|
|
ty::ty_uint(ast::TyU32) => output.push_str("u32"),
|
|
|
|
ty::ty_uint(ast::TyU64) => output.push_str("u64"),
|
|
|
|
ty::ty_float(ast::TyF32) => output.push_str("f32"),
|
|
|
|
ty::ty_float(ast::TyF64) => output.push_str("f64"),
|
2014-12-03 16:01:29 -08:00
|
|
|
ty::ty_struct(def_id, substs) |
|
|
|
|
ty::ty_enum(def_id, substs) => {
|
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
|
|
|
push_item_name(cx, def_id, qualified, output);
|
|
|
|
push_type_params(cx, substs, output);
|
|
|
|
},
|
|
|
|
ty::ty_tup(ref component_types) => {
|
2014-10-14 23:05:01 -07:00
|
|
|
output.push('(');
|
2015-01-31 12:20:46 -05:00
|
|
|
for &component_type in component_types {
|
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
|
|
|
push_debuginfo_type_name(cx, component_type, true, output);
|
|
|
|
output.push_str(", ");
|
|
|
|
}
|
2014-11-09 16:14:15 +01:00
|
|
|
if !component_types.is_empty() {
|
|
|
|
output.pop();
|
|
|
|
output.pop();
|
|
|
|
}
|
2014-10-14 23:05:01 -07:00
|
|
|
output.push(')');
|
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
|
|
|
},
|
|
|
|
ty::ty_uniq(inner_type) => {
|
|
|
|
output.push_str("Box<");
|
|
|
|
push_debuginfo_type_name(cx, inner_type, true, output);
|
2014-10-14 23:05:01 -07:00
|
|
|
output.push('>');
|
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
|
|
|
},
|
|
|
|
ty::ty_ptr(ty::mt { ty: inner_type, mutbl } ) => {
|
2014-10-14 23:05:01 -07:00
|
|
|
output.push('*');
|
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
|
|
|
match mutbl {
|
|
|
|
ast::MutImmutable => output.push_str("const "),
|
|
|
|
ast::MutMutable => output.push_str("mut "),
|
|
|
|
}
|
|
|
|
|
|
|
|
push_debuginfo_type_name(cx, inner_type, true, output);
|
|
|
|
},
|
|
|
|
ty::ty_rptr(_, ty::mt { ty: inner_type, mutbl }) => {
|
2014-10-14 23:05:01 -07:00
|
|
|
output.push('&');
|
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
|
|
|
if mutbl == ast::MutMutable {
|
|
|
|
output.push_str("mut ");
|
|
|
|
}
|
|
|
|
|
|
|
|
push_debuginfo_type_name(cx, inner_type, true, output);
|
|
|
|
},
|
2014-08-06 11:59:40 +02:00
|
|
|
ty::ty_vec(inner_type, optional_length) => {
|
2014-10-14 23:05:01 -07:00
|
|
|
output.push('[');
|
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
|
|
|
push_debuginfo_type_name(cx, inner_type, true, output);
|
|
|
|
|
|
|
|
match optional_length {
|
|
|
|
Some(len) => {
|
2015-02-01 21:53:25 -05:00
|
|
|
output.push_str(&format!("; {}", len));
|
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
|
|
|
}
|
|
|
|
None => { /* nothing to do */ }
|
|
|
|
};
|
|
|
|
|
2014-10-14 23:05:01 -07:00
|
|
|
output.push(']');
|
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
|
|
|
},
|
|
|
|
ty::ty_trait(ref trait_data) => {
|
2015-01-06 05:03:42 -05:00
|
|
|
let principal = ty::erase_late_bound_regions(cx.tcx(), &trait_data.principal);
|
|
|
|
push_item_name(cx, principal.def_id, false, output);
|
|
|
|
push_type_params(cx, principal.substs, output);
|
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
|
|
|
},
|
2014-12-04 14:52:20 -08:00
|
|
|
ty::ty_bare_fn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => {
|
2014-12-09 10:36:46 -05:00
|
|
|
if unsafety == ast::Unsafety::Unsafe {
|
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
|
|
|
output.push_str("unsafe ");
|
|
|
|
}
|
|
|
|
|
|
|
|
if abi != ::syntax::abi::Rust {
|
|
|
|
output.push_str("extern \"");
|
|
|
|
output.push_str(abi.name());
|
|
|
|
output.push_str("\" ");
|
|
|
|
}
|
|
|
|
|
|
|
|
output.push_str("fn(");
|
|
|
|
|
2015-01-06 05:03:42 -05:00
|
|
|
let sig = ty::erase_late_bound_regions(cx.tcx(), sig);
|
2015-03-24 16:54:09 -07:00
|
|
|
if !sig.inputs.is_empty() {
|
2015-01-31 12:20:46 -05:00
|
|
|
for ¶meter_type in &sig.inputs {
|
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
|
|
|
push_debuginfo_type_name(cx, parameter_type, true, output);
|
|
|
|
output.push_str(", ");
|
|
|
|
}
|
2014-10-14 23:05:01 -07:00
|
|
|
output.pop();
|
|
|
|
output.pop();
|
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
|
|
|
}
|
|
|
|
|
2015-01-06 05:03:42 -05:00
|
|
|
if sig.variadic {
|
2015-03-24 16:54:09 -07:00
|
|
|
if !sig.inputs.is_empty() {
|
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
|
|
|
output.push_str(", ...");
|
|
|
|
} else {
|
|
|
|
output.push_str("...");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-14 23:05:01 -07:00
|
|
|
output.push(')');
|
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
|
|
|
|
2015-01-06 05:03:42 -05:00
|
|
|
match sig.output {
|
2014-10-24 21:14:37 +02:00
|
|
|
ty::FnConverging(result_type) if ty::type_is_nil(result_type) => {}
|
|
|
|
ty::FnConverging(result_type) => {
|
|
|
|
output.push_str(" -> ");
|
|
|
|
push_debuginfo_type_name(cx, result_type, true, output);
|
|
|
|
}
|
|
|
|
ty::FnDiverging => {
|
|
|
|
output.push_str(" -> !");
|
|
|
|
}
|
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
|
|
|
}
|
|
|
|
},
|
2015-01-24 22:00:03 +02:00
|
|
|
ty::ty_closure(..) => {
|
2014-05-28 22:26:56 -07:00
|
|
|
output.push_str("closure");
|
|
|
|
}
|
2014-12-17 14:16:28 -05:00
|
|
|
ty::ty_err |
|
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
|
|
|
ty::ty_infer(_) |
|
2015-01-14 12:44:21 -05:00
|
|
|
ty::ty_projection(..) |
|
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
|
|
|
ty::ty_param(_) => {
|
2015-01-07 11:58:31 -05:00
|
|
|
cx.sess().bug(&format!("debuginfo: Trying to create type name for \
|
2015-02-20 14:08:14 -05:00
|
|
|
unexpected type: {}", ppaux::ty_to_string(cx.tcx(), t)));
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn push_item_name(cx: &CrateContext,
|
|
|
|
def_id: ast::DefId,
|
|
|
|
qualified: bool,
|
|
|
|
output: &mut String) {
|
2015-01-31 09:17:50 -05:00
|
|
|
ty::with_path(cx.tcx(), def_id, |path| {
|
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
|
|
|
if qualified {
|
|
|
|
if def_id.krate == ast::LOCAL_CRATE {
|
|
|
|
output.push_str(crate_root_namespace(cx));
|
|
|
|
output.push_str("::");
|
|
|
|
}
|
|
|
|
|
2015-01-25 10:58:43 +00:00
|
|
|
let mut path_element_count = 0;
|
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
|
|
|
for path_element in path {
|
|
|
|
let name = token::get_name(path_element.name());
|
2015-02-04 21:48:12 +01:00
|
|
|
output.push_str(&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
|
|
|
output.push_str("::");
|
|
|
|
path_element_count += 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if path_element_count == 0 {
|
|
|
|
cx.sess().bug("debuginfo: Encountered empty item path!");
|
|
|
|
}
|
|
|
|
|
2014-10-14 23:05:01 -07:00
|
|
|
output.pop();
|
|
|
|
output.pop();
|
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
|
|
|
} else {
|
|
|
|
let name = token::get_name(path.last()
|
|
|
|
.expect("debuginfo: Empty item path?")
|
|
|
|
.name());
|
2015-02-04 21:48:12 +01:00
|
|
|
output.push_str(&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
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pushes the type parameters in the given `Substs` to the output string.
|
|
|
|
// This ignores region parameters, since they can't reliably be
|
|
|
|
// reconstructed for items from non-local crates. For local crates, this
|
|
|
|
// would be possible but with inlining and LTO we have to use the least
|
|
|
|
// common denominator - otherwise we would run into conflicts.
|
2014-09-29 22:11:30 +03:00
|
|
|
fn push_type_params<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
|
|
|
substs: &subst::Substs<'tcx>,
|
|
|
|
output: &mut String) {
|
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
|
|
|
if substs.types.is_empty() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-10-14 23:05:01 -07:00
|
|
|
output.push('<');
|
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
|
|
|
|
|
|
|
for &type_parameter in substs.types.iter() {
|
|
|
|
push_debuginfo_type_name(cx, type_parameter, true, output);
|
|
|
|
output.push_str(", ");
|
|
|
|
}
|
|
|
|
|
2014-10-14 23:05:01 -07:00
|
|
|
output.pop();
|
|
|
|
output.pop();
|
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
|
|
|
|
2014-10-14 23:05:01 -07:00
|
|
|
output.push('>');
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-18 15:07:26 +12:00
|
|
|
//=-----------------------------------------------------------------------------
|
2013-09-06 16:00:08 +02:00
|
|
|
// Namespace Handling
|
2014-06-18 15:07:26 +12:00
|
|
|
//=-----------------------------------------------------------------------------
|
2013-09-06 16:00:08 +02:00
|
|
|
|
2013-09-11 14:19:56 +02:00
|
|
|
struct NamespaceTreeNode {
|
2014-02-14 07:07:09 +02:00
|
|
|
name: ast::Name,
|
2013-09-06 16:00:08 +02:00
|
|
|
scope: DIScope,
|
2014-04-22 02:41:05 +03:00
|
|
|
parent: Option<Weak<NamespaceTreeNode>>,
|
2013-09-06 16:00:08 +02:00
|
|
|
}
|
|
|
|
|
2013-09-11 14:19:56 +02:00
|
|
|
impl NamespaceTreeNode {
|
2014-05-22 16:57:53 -07:00
|
|
|
fn mangled_name_of_contained_item(&self, item_name: &str) -> String {
|
|
|
|
fn fill_nested(node: &NamespaceTreeNode, output: &mut String) {
|
2013-09-06 16:00:08 +02:00
|
|
|
match node.parent {
|
2014-04-22 02:41:05 +03:00
|
|
|
Some(ref parent) => fill_nested(&*parent.upgrade().unwrap(), output),
|
2013-09-06 16:00:08 +02:00
|
|
|
None => {}
|
|
|
|
}
|
2014-02-14 07:07:09 +02:00
|
|
|
let string = token::get_name(node.name);
|
2015-02-20 14:08:14 -05:00
|
|
|
output.push_str(&format!("{}", string.len()));
|
2015-02-04 21:48:12 +01:00
|
|
|
output.push_str(&string);
|
2013-09-06 16:00:08 +02:00
|
|
|
}
|
2014-02-14 07:07:09 +02:00
|
|
|
|
2014-05-22 16:57:53 -07:00
|
|
|
let mut name = String::from_str("_ZN");
|
2014-02-14 07:07:09 +02:00
|
|
|
fill_nested(self, &mut name);
|
2015-02-20 14:08:14 -05:00
|
|
|
name.push_str(&format!("{}", item_name.len()));
|
2014-02-14 07:07:09 +02:00
|
|
|
name.push_str(item_name);
|
2014-10-14 23:05:01 -07:00
|
|
|
name.push('E');
|
2014-05-09 18:45:36 -07:00
|
|
|
name
|
2013-09-06 16:00:08 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
fn crate_root_namespace<'a>(cx: &'a CrateContext) -> &'a str {
|
2015-02-20 14:08:14 -05:00
|
|
|
&cx.link_meta().crate_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
|
|
|
}
|
|
|
|
|
2014-04-22 02:41:05 +03:00
|
|
|
fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTreeNode> {
|
2014-03-15 22:29:34 +02:00
|
|
|
ty::with_path(cx.tcx(), def_id, |path| {
|
2014-02-14 07:07:09 +02:00
|
|
|
// prepend crate name if not already present
|
|
|
|
let krate = if def_id.krate == ast::LOCAL_CRATE {
|
2015-03-23 19:41:35 -05:00
|
|
|
let crate_namespace_name = token::intern(crate_root_namespace(cx));
|
|
|
|
Some(ast_map::PathMod(crate_namespace_name))
|
2014-02-14 07:07:09 +02:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
2014-09-14 20:27:36 -07:00
|
|
|
let mut path = krate.into_iter().chain(path).peekable();
|
2013-10-01 12:24:50 +02:00
|
|
|
|
2014-03-04 10:02:49 -08:00
|
|
|
let mut current_key = Vec::new();
|
2014-04-22 02:41:05 +03:00
|
|
|
let mut parent_node: Option<Rc<NamespaceTreeNode>> = None;
|
2013-09-09 17:58:58 +02:00
|
|
|
|
2014-02-14 07:07:09 +02:00
|
|
|
// Create/Lookup namespace for each element of the path.
|
|
|
|
loop {
|
|
|
|
// Emulate a for loop so we can use peek below.
|
|
|
|
let path_element = match path.next() {
|
|
|
|
Some(e) => e,
|
|
|
|
None => break
|
|
|
|
};
|
|
|
|
// Ignore the name of the item (the last path element).
|
|
|
|
if path.peek().is_none() {
|
|
|
|
break;
|
|
|
|
}
|
2013-09-09 17:58:58 +02:00
|
|
|
|
2014-02-14 07:07:09 +02:00
|
|
|
let name = path_element.name();
|
|
|
|
current_key.push(name);
|
2013-09-09 17:58:58 +02:00
|
|
|
|
2014-03-20 19:49:20 -07:00
|
|
|
let existing_node = debug_context(cx).namespace_map.borrow()
|
2014-11-07 14:35:18 -05:00
|
|
|
.get(¤t_key).cloned();
|
2014-02-14 07:07:09 +02:00
|
|
|
let current_node = match existing_node {
|
|
|
|
Some(existing_node) => existing_node,
|
|
|
|
None => {
|
|
|
|
// create and insert
|
|
|
|
let parent_scope = match parent_node {
|
2014-04-22 02:41:05 +03:00
|
|
|
Some(ref node) => node.scope,
|
2014-09-14 20:27:36 -07:00
|
|
|
None => ptr::null_mut()
|
2014-02-14 07:07:09 +02:00
|
|
|
};
|
|
|
|
let namespace_name = token::get_name(name);
|
2015-02-17 22:47:40 -08:00
|
|
|
let namespace_name = CString::new(namespace_name.as_bytes()).unwrap();
|
2014-11-25 13:28:35 -08:00
|
|
|
let scope = unsafe {
|
|
|
|
llvm::LLVMDIBuilderCreateNameSpace(
|
|
|
|
DIB(cx),
|
|
|
|
parent_scope,
|
|
|
|
namespace_name.as_ptr(),
|
|
|
|
// cannot reconstruct file ...
|
|
|
|
ptr::null_mut(),
|
|
|
|
// ... or line information, but that's not so important.
|
|
|
|
0)
|
|
|
|
};
|
2014-02-14 07:07:09 +02:00
|
|
|
|
2014-04-22 02:41:05 +03:00
|
|
|
let node = Rc::new(NamespaceTreeNode {
|
2014-02-14 07:07:09 +02:00
|
|
|
name: name,
|
|
|
|
scope: scope,
|
2014-04-22 02:41:05 +03:00
|
|
|
parent: parent_node.map(|parent| parent.downgrade()),
|
|
|
|
});
|
2014-02-14 07:07:09 +02:00
|
|
|
|
2014-03-20 19:49:20 -07:00
|
|
|
debug_context(cx).namespace_map.borrow_mut()
|
2014-04-22 02:41:05 +03:00
|
|
|
.insert(current_key.clone(), node.clone());
|
2013-09-09 17:58:58 +02:00
|
|
|
|
2014-02-14 07:07:09 +02:00
|
|
|
node
|
2013-12-18 18:50:49 -08:00
|
|
|
}
|
2014-02-14 07:07:09 +02:00
|
|
|
};
|
2013-09-09 17:58:58 +02:00
|
|
|
|
|
|
|
parent_node = Some(current_node);
|
|
|
|
}
|
|
|
|
|
2014-02-14 07:07:09 +02:00
|
|
|
match parent_node {
|
|
|
|
Some(node) => node,
|
|
|
|
None => {
|
2015-01-07 11:58:31 -05:00
|
|
|
cx.sess().bug(&format!("debuginfo::namespace_for_item(): \
|
2014-12-20 00:09:35 -08:00
|
|
|
path too short for {:?}",
|
2015-02-20 14:08:14 -05:00
|
|
|
def_id));
|
2014-02-14 07:07:09 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
2013-09-06 16:00:08 +02:00
|
|
|
}
|
2014-12-03 14:48:18 -08:00
|
|
|
|
|
|
|
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
// .debug_gdb_scripts binary section
|
|
|
|
//=-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/// Inserts a side-effect free instruction sequence that makes sure that the
|
|
|
|
/// .debug_gdb_scripts global is referenced, so it isn't removed by the linker.
|
|
|
|
pub fn insert_reference_to_gdb_debug_scripts_section_global(ccx: &CrateContext) {
|
|
|
|
if needs_gdb_debug_scripts_section(ccx) {
|
2015-03-18 09:16:08 +03:00
|
|
|
let empty = CString::new("").unwrap();
|
2014-12-03 14:48:18 -08:00
|
|
|
let gdb_debug_scripts_section_global =
|
|
|
|
get_or_insert_gdb_debug_scripts_section_global(ccx);
|
|
|
|
unsafe {
|
|
|
|
let volative_load_instruction =
|
|
|
|
llvm::LLVMBuildLoad(ccx.raw_builder(),
|
|
|
|
gdb_debug_scripts_section_global,
|
|
|
|
empty.as_ptr());
|
|
|
|
llvm::LLVMSetVolatile(volative_load_instruction, llvm::True);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Allocates the global variable responsible for the .debug_gdb_scripts binary
|
|
|
|
/// section.
|
|
|
|
fn get_or_insert_gdb_debug_scripts_section_global(ccx: &CrateContext)
|
|
|
|
-> llvm::ValueRef {
|
2015-03-04 01:08:06 +02:00
|
|
|
let section_var_name = "__rustc_debug_gdb_scripts_section__";
|
2014-12-03 14:48:18 -08:00
|
|
|
|
|
|
|
let section_var = unsafe {
|
2014-11-25 13:28:35 -08:00
|
|
|
llvm::LLVMGetNamedGlobal(ccx.llmod(),
|
|
|
|
section_var_name.as_ptr() as *const _)
|
2014-12-03 14:48:18 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
if section_var == ptr::null_mut() {
|
2014-11-25 13:28:35 -08:00
|
|
|
let section_name = b".debug_gdb_scripts\0";
|
2014-12-03 14:48:18 -08:00
|
|
|
let section_contents = b"\x01gdb_load_rust_pretty_printers.py\0";
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
let llvm_type = Type::array(&Type::i8(ccx),
|
|
|
|
section_contents.len() as u64);
|
2015-03-04 01:08:06 +02:00
|
|
|
|
|
|
|
let section_var = declare::define_global(ccx, section_var_name,
|
|
|
|
llvm_type).unwrap_or_else(||{
|
|
|
|
ccx.sess().bug(&format!("symbol `{}` is already defined", section_var_name))
|
|
|
|
});
|
2014-11-25 13:28:35 -08:00
|
|
|
llvm::LLVMSetSection(section_var, section_name.as_ptr() as *const _);
|
2014-12-03 14:48:18 -08:00
|
|
|
llvm::LLVMSetInitializer(section_var, C_bytes(ccx, section_contents));
|
|
|
|
llvm::LLVMSetGlobalConstant(section_var, llvm::True);
|
|
|
|
llvm::LLVMSetUnnamedAddr(section_var, llvm::True);
|
|
|
|
llvm::SetLinkage(section_var, llvm::Linkage::LinkOnceODRLinkage);
|
|
|
|
// This should make sure that the whole section is not larger than
|
|
|
|
// the string it contains. Otherwise we get a warning from GDB.
|
|
|
|
llvm::LLVMSetAlignment(section_var, 1);
|
|
|
|
section_var
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
section_var
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn needs_gdb_debug_scripts_section(ccx: &CrateContext) -> bool {
|
|
|
|
let omit_gdb_pretty_printer_section =
|
2015-02-01 21:53:25 -05:00
|
|
|
attr::contains_name(&ccx.tcx()
|
|
|
|
.map
|
|
|
|
.krate()
|
|
|
|
.attrs,
|
2014-12-03 14:48:18 -08:00
|
|
|
"omit_gdb_pretty_printer_section");
|
|
|
|
|
|
|
|
!omit_gdb_pretty_printer_section &&
|
|
|
|
!ccx.sess().target.target.options.is_like_osx &&
|
|
|
|
!ccx.sess().target.target.options.is_like_windows &&
|
|
|
|
ccx.sess().opts.debuginfo != NoDebugInfo
|
|
|
|
}
|