1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
14 This module serves the purpose of generating debug symbols. We use LLVM's
15 [source level debugging](http://llvm.org/docs/SourceLevelDebugging.html) features for generating
16 the debug information. The general principle is this:
18 Given the right metadata in the LLVM IR, the LLVM code generator is able to create DWARF debug
19 symbols for the given code. The [metadata](http://llvm.org/docs/LangRef.html#metadata-type) is
20 structured much like DWARF *debugging information entries* (DIE), representing type information
21 such as datatype layout, function signatures, block layout, variable location and scope information,
22 etc. It is the purpose of this module to generate correct metadata and insert it into the LLVM IR.
24 As the exact format of metadata trees may change between different LLVM versions, we now use LLVM
25 [DIBuilder](http://llvm.org/docs/doxygen/html/classllvm_1_1DIBuilder.html) to create metadata
26 where possible. This will hopefully ease the adaption of this module to future LLVM versions.
28 The public API of the module is a set of functions that will insert the correct metadata into the
29 LLVM IR when called with the right parameters. The module is thus driven from an outside client with
30 functions like `debuginfo::create_local_var_metadata(bcx: block, local: &ast::local)`.
32 Internally the module will try to reuse already created metadata by utilizing a cache. The way to
33 get a shared metadata node when needed is thus to just call the corresponding function in this
36 let file_metadata = file_metadata(crate_context, path);
38 The function will take care of probing the cache for an existing node for that exact file path.
40 All private state used by the module is stored within either the CrateDebugContext struct (owned by
41 the CrateContext) or the FunctionDebugContext (owned by the FunctionContext).
43 This file consists of three conceptual sections:
44 1. The public interface of the module
45 2. Module-internal metadata creation functions
46 3. Minor utility functions
50 Some kinds of types, such as structs and enums can be recursive. That means that the type definition
51 of some type X refers to some other type which in turn (transitively) refers to X. This introduces
52 cycles into the type referral graph. A naive algorithm doing an on-demand, depth-first traversal of
53 this graph when describing types, can get trapped in an endless loop when it reaches such a cycle.
55 For example, the following simple type for a singly-linked list...
60 tail: Option<Box<List>>,
64 will generate the following callstack with a naive DFS algorithm:
69 describe(t = Option<Box<List>>)
70 describe(t = Box<List>)
71 describe(t = List) // at the beginning again...
75 To break cycles like these, we use "forward declarations". That is, when the algorithm encounters a
76 possibly recursive type (any struct or enum), it immediately creates a type description node and
77 inserts it into the cache *before* describing the members of the type. This type description is just
78 a stub (as type members are not described and added to it yet) but it allows the algorithm to
79 already refer to the type. After the stub is inserted into the cache, the algorithm continues as
80 before. If it now encounters a recursive reference, it will hit the cache and does not try to
81 describe the type anew.
83 This behaviour is encapsulated in the 'RecursiveTypeDescription' enum, which represents a kind of
84 continuation, storing all state needed to continue traversal at the type members after the type has
85 been registered with the cache. (This implementation approach might be a tad over-engineered and
86 may change in the future)
89 ## Source Locations and Line Information
90 In addition to data type descriptions the debugging information must also allow to map machine code
91 locations back to source code locations in order to be useful. This functionality is also handled in
92 this module. The following functions allow to control source mappings:
94 + set_source_location()
95 + clear_source_location()
96 + start_emitting_source_locations()
98 `set_source_location()` allows to set the current source location. All IR instructions created after
99 a call to this function will be linked to the given source location, until another location is
100 specified with `set_source_location()` or the source location is cleared with
101 `clear_source_location()`. In the later case, subsequent IR instruction will not be linked to any
102 source location. As you can see, this is a stateful API (mimicking the one in LLVM), so be careful
103 with source locations set by previous calls. It's probably best to not rely on any specific state
104 being present at a given point in code.
106 One topic that deserves some extra attention is *function prologues*. At the beginning of a
107 function's machine code there are typically a few instructions for loading argument values into
108 allocas and checking if there's enough stack space for the function to execute. This *prologue* is
109 not visible in the source code and LLVM puts a special PROLOGUE END marker into the line table at
110 the first non-prologue instruction of the function. In order to find out where the prologue ends,
111 LLVM looks for the first instruction in the function body that is linked to a source location. So,
112 when generating prologue instructions we have to make sure that we don't emit source location
113 information until the 'real' function body begins. For this reason, source location emission is
114 disabled by default for any new function being translated and is only activated after a call to the
115 third function from the list above, `start_emitting_source_locations()`. This function should be
116 called right before regularly starting to translate the top-level block of the given function.
118 There is one exception to the above rule: `llvm.dbg.declare` instruction must be linked to the
119 source location of the variable being declared. For function parameters these `llvm.dbg.declare`
120 instructions typically occur in the middle of the prologue, however, they are ignored by LLVM's
121 prologue detection. The `create_argument_metadata()` and related functions take care of linking the
122 `llvm.dbg.declare` instructions to the correct source locations even while source location emission
123 is still disabled, so there is no need to do anything special with source location handling here.
129 use driver::config::{FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
131 use lib::llvm::{ModuleRef, ContextRef, ValueRef};
132 use lib::llvm::debuginfo::*;
133 use metadata::csearch;
134 use middle::trans::adt;
135 use middle::trans::common::*;
136 use middle::trans::datum::{Datum, Lvalue};
137 use middle::trans::machine;
138 use middle::trans::type_of;
139 use middle::trans::type_::Type;
142 use middle::pat_util;
145 use std::c_str::{CString, ToCStr};
146 use std::cell::{Cell, RefCell};
147 use std::rc::{Rc, Weak};
148 use collections::HashMap;
149 use collections::HashSet;
150 use libc::{c_uint, c_ulonglong, c_longlong};
152 use std::string::String;
153 use std::sync::atomics;
154 use syntax::codemap::{Span, Pos};
155 use syntax::{abi, ast, codemap, ast_util, ast_map};
156 use syntax::owned_slice::OwnedSlice;
157 use syntax::parse::token;
158 use syntax::parse::token::special_idents;
160 static DW_LANG_RUST: c_uint = 0x9000;
162 static DW_TAG_auto_variable: c_uint = 0x100;
163 static DW_TAG_arg_variable: c_uint = 0x101;
165 static DW_ATE_boolean: c_uint = 0x02;
166 static DW_ATE_float: c_uint = 0x04;
167 static DW_ATE_signed: c_uint = 0x05;
168 // static DW_ATE_signed_char: c_uint = 0x06;
169 static DW_ATE_unsigned: c_uint = 0x07;
170 static DW_ATE_unsigned_char: c_uint = 0x08;
172 //=-------------------------------------------------------------------------------------------------
173 // Public Interface of debuginfo module
174 //=-------------------------------------------------------------------------------------------------
176 /// A context object for maintaining all state needed by the debuginfo module.
177 pub struct CrateDebugContext {
178 llcontext: ContextRef,
179 builder: DIBuilderRef,
180 current_debug_location: Cell<DebugLocation>,
181 created_files: RefCell<HashMap<String, DIFile>>,
182 created_types: RefCell<HashMap<uint, DIType>>,
183 created_enum_disr_types: RefCell<HashMap<ast::DefId, DIType>>,
184 namespace_map: RefCell<HashMap<Vec<ast::Name>, Rc<NamespaceTreeNode>>>,
185 // This collection is used to assert that composite types (structs, enums, ...) have their
186 // members only set once:
187 composite_types_completed: RefCell<HashSet<DIType>>,
190 impl CrateDebugContext {
191 pub fn new(llmod: ModuleRef) -> CrateDebugContext {
192 debug!("CrateDebugContext::new");
193 let builder = unsafe { llvm::LLVMDIBuilderCreate(llmod) };
194 // DIBuilder inherits context from the module, so we'd better use the same one
195 let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
196 return CrateDebugContext {
197 llcontext: llcontext,
199 current_debug_location: Cell::new(UnknownLocation),
200 created_files: RefCell::new(HashMap::new()),
201 created_types: RefCell::new(HashMap::new()),
202 created_enum_disr_types: RefCell::new(HashMap::new()),
203 namespace_map: RefCell::new(HashMap::new()),
204 composite_types_completed: RefCell::new(HashSet::new()),
209 pub struct FunctionDebugContext {
210 repr: FunctionDebugContextRepr,
213 enum FunctionDebugContextRepr {
214 FunctionDebugContext(Box<FunctionDebugContextData>),
216 FunctionWithoutDebugInfo,
219 impl FunctionDebugContext {
220 fn get_ref<'a>(&'a self, cx: &CrateContext, span: Span) -> &'a FunctionDebugContextData {
222 FunctionDebugContext(box ref data) => data,
223 DebugInfoDisabled => {
224 cx.sess().span_bug(span, FunctionDebugContext::debuginfo_disabled_message());
226 FunctionWithoutDebugInfo => {
227 cx.sess().span_bug(span, FunctionDebugContext::should_be_ignored_message());
232 fn debuginfo_disabled_message() -> &'static str {
233 "debuginfo: Error trying to access FunctionDebugContext although debug info is disabled!"
236 fn should_be_ignored_message() -> &'static str {
237 "debuginfo: Error trying to access FunctionDebugContext for function that should be \
238 ignored by debug info!"
242 struct FunctionDebugContextData {
243 scope_map: RefCell<HashMap<ast::NodeId, DIScope>>,
244 fn_metadata: DISubprogram,
245 argument_counter: Cell<uint>,
246 source_locations_enabled: Cell<bool>,
249 enum VariableAccess<'a> {
250 // The llptr given is an alloca containing the variable's value
251 DirectVariable { alloca: ValueRef },
252 // The llptr given is an alloca containing the start of some pointer chain leading to the
253 // variable's content.
254 IndirectVariable { alloca: ValueRef, address_operations: &'a [ValueRef] }
258 ArgumentVariable(uint /*index*/),
263 /// Create any deferred debug metadata nodes
264 pub fn finalize(cx: &CrateContext) {
265 if cx.dbg_cx.is_none() {
270 compile_unit_metadata(cx);
272 llvm::LLVMDIBuilderFinalize(DIB(cx));
273 llvm::LLVMDIBuilderDispose(DIB(cx));
274 // Debuginfo generation in LLVM by default uses a higher
275 // version of dwarf than OS X currently understands. We can
276 // instruct LLVM to emit an older version of dwarf, however,
277 // for OS X to understand. For more info see #11352
278 // This can be overridden using --llvm-opts -dwarf-version,N.
279 if cx.sess().targ_cfg.os == abi::OsMacos {
280 "Dwarf Version".with_c_str(
281 |s| llvm::LLVMRustAddModuleFlag(cx.llmod, s, 2));
283 // FIXME(#13611) this is a kludge fix because the linux bots have
284 // gdb 7.4 which doesn't understand dwarf4, we should
285 // do something more graceful here.
286 "Dwarf Version".with_c_str(
287 |s| llvm::LLVMRustAddModuleFlag(cx.llmod, s, 3));
290 // Prevent bitcode readers from deleting the debug info.
291 "Debug Info Version".with_c_str(
292 |s| llvm::LLVMRustAddModuleFlag(cx.llmod, s,
293 llvm::LLVMRustDebugMetadataVersion));
297 /// Creates debug information for the given global variable.
299 /// Adds the created metadata nodes directly to the crate's IR.
300 pub fn create_global_var_metadata(cx: &CrateContext,
301 node_id: ast::NodeId,
303 if cx.dbg_cx.is_none() {
307 // Don't create debuginfo for globals inlined from other crates. The other crate should already
308 // contain debuginfo for it. More importantly, the global might not even exist in un-inlined
309 // form anywhere which would lead to a linker errors.
310 if cx.external_srcs.borrow().contains_key(&node_id) {
314 let var_item = cx.tcx.map.get(node_id);
316 let (ident, span) = match var_item {
317 ast_map::NodeItem(item) => {
319 ast::ItemStatic(..) => (item.ident, item.span),
323 format!("debuginfo::\
324 create_global_var_metadata() -
325 Captured var-id refers to \
326 unexpected ast_item variant: {:?}",
327 var_item).as_slice())
331 _ => cx.sess().bug(format!("debuginfo::create_global_var_metadata() \
332 - Captured var-id refers to unexpected \
333 ast_map variant: {:?}",
334 var_item).as_slice())
337 let filename = span_start(cx, span).file.name.clone();
338 let file_metadata = file_metadata(cx, filename.as_slice());
340 let is_local_to_unit = is_node_local_to_unit(cx, node_id);
341 let loc = span_start(cx, span);
343 let variable_type = ty::node_id_to_type(cx.tcx(), node_id);
344 let type_metadata = type_metadata(cx, variable_type, span);
346 let namespace_node = namespace_for_item(cx, ast_util::local_def(node_id));
347 let var_name = token::get_ident(ident).get().to_str();
349 namespace_node.mangled_name_of_contained_item(var_name.as_slice());
350 let var_scope = namespace_node.scope;
352 var_name.as_slice().with_c_str(|var_name| {
353 linkage_name.as_slice().with_c_str(|linkage_name| {
355 llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx),
370 /// Creates debug information for the given local variable.
372 /// Adds the created metadata nodes directly to the crate's IR.
373 pub fn create_local_var_metadata(bcx: &Block, local: &ast::Local) {
374 if fn_should_be_ignored(bcx.fcx) {
379 let def_map = &cx.tcx.def_map;
381 pat_util::pat_bindings(def_map, local.pat, |_, node_id, span, path_ref| {
382 let var_ident = ast_util::path_to_ident(path_ref);
384 let datum = match bcx.fcx.lllocals.borrow().find_copy(&node_id) {
385 Some(datum) => datum,
387 bcx.sess().span_bug(span,
388 format!("no entry in lllocals table for {:?}",
389 node_id).as_slice());
393 let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
399 DirectVariable { alloca: datum.val },
405 /// Creates debug information for a variable captured in a closure.
407 /// Adds the created metadata nodes directly to the crate's IR.
408 pub fn create_captured_var_metadata(bcx: &Block,
409 node_id: ast::NodeId,
410 env_data_type: ty::t,
411 env_pointer: ValueRef,
413 closure_store: ty::TraitStore,
415 if fn_should_be_ignored(bcx.fcx) {
421 let ast_item = cx.tcx.map.find(node_id);
423 let variable_ident = match ast_item {
425 cx.sess().span_bug(span, "debuginfo::create_captured_var_metadata: node not found");
427 Some(ast_map::NodeLocal(pat)) | Some(ast_map::NodeArg(pat)) => {
429 ast::PatIdent(_, ref path, _) => {
430 ast_util::path_to_ident(path)
436 "debuginfo::create_captured_var_metadata() - \
437 Captured var-id refers to unexpected \
438 ast_map variant: {:?}",
439 ast_item).as_slice());
446 format!("debuginfo::create_captured_var_metadata() - \
447 Captured var-id refers to unexpected \
448 ast_map variant: {:?}",
449 ast_item).as_slice());
453 let variable_type = node_id_type(bcx, node_id);
454 let scope_metadata = bcx.fcx.debug_context.get_ref(cx, span).fn_metadata;
456 let llvm_env_data_type = type_of::type_of(cx, env_data_type);
457 let byte_offset_of_var_in_env = machine::llelement_offset(cx, llvm_env_data_type, env_index);
459 let address_operations = unsafe {
460 [llvm::LLVMDIBuilderCreateOpDeref(Type::i64(cx).to_ref()),
461 llvm::LLVMDIBuilderCreateOpPlus(Type::i64(cx).to_ref()),
462 C_i64(cx, byte_offset_of_var_in_env as i64),
463 llvm::LLVMDIBuilderCreateOpDeref(Type::i64(cx).to_ref())]
466 let address_op_count = match closure_store {
467 ty::RegionTraitStore(..) => {
468 address_operations.len()
470 ty::UniqTraitStore => {
471 address_operations.len() - 1
475 let variable_access = IndirectVariable {
477 address_operations: address_operations.slice_to(address_op_count)
489 /// Creates debug information for a local variable introduced in the head of a match-statement arm.
491 /// Adds the created metadata nodes directly to the crate's IR.
492 pub fn create_match_binding_metadata(bcx: &Block,
493 variable_ident: ast::Ident,
494 node_id: ast::NodeId,
496 datum: Datum<Lvalue>) {
497 if fn_should_be_ignored(bcx.fcx) {
501 let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
507 DirectVariable { alloca: datum.val },
512 /// Creates debug information for the given function argument.
514 /// Adds the created metadata nodes directly to the crate's IR.
515 pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
516 if fn_should_be_ignored(bcx.fcx) {
523 let def_map = &cx.tcx.def_map;
524 let scope_metadata = bcx.fcx.debug_context.get_ref(cx, arg.pat.span).fn_metadata;
526 pat_util::pat_bindings(def_map, arg.pat, |_, node_id, span, path_ref| {
527 let llarg = match bcx.fcx.llargs.borrow().find_copy(&node_id) {
530 bcx.sess().span_bug(span,
531 format!("no entry in llargs table for {:?}",
532 node_id).as_slice());
536 if unsafe { llvm::LLVMIsAAllocaInst(llarg.val) } == ptr::null() {
537 cx.sess().span_bug(span, "debuginfo::create_argument_metadata() - \
538 Referenced variable location is not an alloca!");
541 let argument_ident = ast_util::path_to_ident(path_ref);
543 let argument_index = {
544 let counter = &fcx.debug_context.get_ref(cx, span).argument_counter;
545 let argument_index = counter.get();
546 counter.set(argument_index + 1);
554 DirectVariable { alloca: llarg.val },
555 ArgumentVariable(argument_index),
560 /// Sets the current debug location at the beginning of the span.
562 /// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...). The node_id parameter is used to
563 /// reliably find the correct visibility scope for the code position.
564 pub fn set_source_location(fcx: &FunctionContext,
565 node_id: ast::NodeId,
567 match fcx.debug_context.repr {
568 DebugInfoDisabled => return,
569 FunctionWithoutDebugInfo => {
570 set_debug_location(fcx.ccx, UnknownLocation);
573 FunctionDebugContext(box ref function_debug_context) => {
576 debug!("set_source_location: {}", cx.sess().codemap().span_to_str(span));
578 if function_debug_context.source_locations_enabled.get() {
579 let loc = span_start(cx, span);
580 let scope = scope_metadata(fcx, node_id, span);
582 set_debug_location(cx, DebugLocation::new(scope, loc.line, loc.col.to_uint()));
584 set_debug_location(cx, UnknownLocation);
590 /// Clears the current debug location.
592 /// Instructions generated hereafter won't be assigned a source location.
593 pub fn clear_source_location(fcx: &FunctionContext) {
594 if fn_should_be_ignored(fcx) {
598 set_debug_location(fcx.ccx, UnknownLocation);
601 /// Enables emitting source locations for the given functions.
603 /// Since we don't want source locations to be emitted for the function prelude, they are disabled
604 /// when beginning to translate a new function. This functions switches source location emitting on
605 /// and must therefore be called before the first real statement/expression of the function is
607 pub fn start_emitting_source_locations(fcx: &FunctionContext) {
608 match fcx.debug_context.repr {
609 FunctionDebugContext(box ref data) => {
610 data.source_locations_enabled.set(true)
612 _ => { /* safe to ignore */ }
616 /// Creates the function-specific debug context.
618 /// Returns the FunctionDebugContext for the function which holds state needed for debug info
619 /// creation. The function may also return another variant of the FunctionDebugContext enum which
620 /// indicates why no debuginfo should be created for the function.
621 pub fn create_function_debug_context(cx: &CrateContext,
622 fn_ast_id: ast::NodeId,
623 param_substs: Option<¶m_substs>,
624 llfn: ValueRef) -> FunctionDebugContext {
625 if cx.sess().opts.debuginfo == NoDebugInfo {
626 return FunctionDebugContext { repr: DebugInfoDisabled };
629 // Clear the debug location so we don't assign them in the function prelude. Do this here
630 // already, in case we do an early exit from this function.
631 set_debug_location(cx, UnknownLocation);
634 return FunctionDebugContext { repr: FunctionWithoutDebugInfo };
637 let empty_generics = ast::Generics { lifetimes: Vec::new(), ty_params: OwnedSlice::empty() };
639 let fnitem = cx.tcx.map.get(fn_ast_id);
641 let (ident, fn_decl, generics, top_level_block, span, has_path) = match fnitem {
642 ast_map::NodeItem(ref item) => {
644 ast::ItemFn(fn_decl, _, _, ref generics, top_level_block) => {
645 (item.ident, fn_decl, generics, top_level_block, item.span, true)
648 cx.sess().span_bug(item.span,
649 "create_function_debug_context: item bound to non-function");
653 ast_map::NodeMethod(ref method) => {
661 ast_map::NodeExpr(ref expr) => {
663 ast::ExprFnBlock(fn_decl, top_level_block) |
664 ast::ExprProc(fn_decl, top_level_block) => {
665 let name = format!("fn{}", token::gensym("fn"));
666 let name = token::str_to_ident(name.as_slice());
668 // This is not quite right. It should actually inherit the generics of the
669 // enclosing function.
673 // Don't try to lookup the item path:
676 _ => cx.sess().span_bug(expr.span,
677 "create_function_debug_context: expected an expr_fn_block here")
680 ast_map::NodeTraitMethod(ref trait_method) => {
681 match **trait_method {
682 ast::Provided(ref method) => {
692 .bug(format!("create_function_debug_context: \
693 unexpected sort of node: {:?}",
698 ast_map::NodeForeignItem(..) |
699 ast_map::NodeVariant(..) |
700 ast_map::NodeStructCtor(..) => {
701 return FunctionDebugContext { repr: FunctionWithoutDebugInfo };
703 _ => cx.sess().bug(format!("create_function_debug_context: \
704 unexpected sort of node: {:?}",
708 // This can be the case for functions inlined from another crate
709 if span == codemap::DUMMY_SP {
710 return FunctionDebugContext { repr: FunctionWithoutDebugInfo };
713 let loc = span_start(cx, span);
714 let file_metadata = file_metadata(cx, loc.file.name.as_slice());
716 let function_type_metadata = unsafe {
717 let fn_signature = get_function_signature(cx, fn_ast_id, fn_decl, param_substs, span);
718 llvm::LLVMDIBuilderCreateSubroutineType(DIB(cx), file_metadata, fn_signature)
721 // get_template_parameters() will append a `<...>` clause to the function name if necessary.
722 let mut function_name = String::from_str(token::get_ident(ident).get());
723 let template_parameters = get_template_parameters(cx,
729 // There is no ast_map::Path for ast::ExprFnBlock-type functions. For now, just don't put them
730 // into a namespace. In the future this could be improved somehow (storing a path in the
731 // ast_map, or construct a path using the enclosing function).
732 let (linkage_name, containing_scope) = if has_path {
733 let namespace_node = namespace_for_item(cx, ast_util::local_def(fn_ast_id));
734 let linkage_name = namespace_node.mangled_name_of_contained_item(
735 function_name.as_slice());
736 let containing_scope = namespace_node.scope;
737 (linkage_name, containing_scope)
739 (function_name.as_slice().to_string(), file_metadata)
742 // Clang sets this parameter to the opening brace of the function's block, so let's do this too.
743 let scope_line = span_start(cx, top_level_block.span).line;
745 let is_local_to_unit = is_node_local_to_unit(cx, fn_ast_id);
747 let fn_metadata = function_name.as_slice().with_c_str(|function_name| {
748 linkage_name.as_slice().with_c_str(|linkage_name| {
750 llvm::LLVMDIBuilderCreateFunction(
757 function_type_metadata,
760 scope_line as c_uint,
761 FlagPrototyped as c_uint,
762 cx.sess().opts.optimize != config::No,
770 // Initialize fn debug context (including scope map and namespace map)
771 let fn_debug_context = box FunctionDebugContextData {
772 scope_map: RefCell::new(HashMap::new()),
773 fn_metadata: fn_metadata,
774 argument_counter: Cell::new(1),
775 source_locations_enabled: Cell::new(false),
778 let arg_pats = fn_decl.inputs.iter().map(|arg_ref| arg_ref.pat).collect::<Vec<_>>();
779 populate_scope_map(cx,
783 &mut *fn_debug_context.scope_map.borrow_mut());
785 return FunctionDebugContext { repr: FunctionDebugContext(fn_debug_context) };
787 fn get_function_signature(cx: &CrateContext,
788 fn_ast_id: ast::NodeId,
789 fn_decl: &ast::FnDecl,
790 param_substs: Option<¶m_substs>,
791 error_span: Span) -> DIArray {
792 if cx.sess().opts.debuginfo == LimitedDebugInfo {
793 return create_DIArray(DIB(cx), []);
796 let mut signature = Vec::with_capacity(fn_decl.inputs.len() + 1);
798 // Return type -- llvm::DIBuilder wants this at index 0
799 match fn_decl.output.node {
801 signature.push(ptr::null());
804 assert_type_for_node_id(cx, fn_ast_id, error_span);
806 let return_type = ty::node_id_to_type(cx.tcx(), fn_ast_id);
807 let return_type = return_type.substp(cx.tcx(), param_substs);
808 signature.push(type_metadata(cx, return_type, codemap::DUMMY_SP));
813 for arg in fn_decl.inputs.iter() {
814 assert_type_for_node_id(cx, arg.pat.id, arg.pat.span);
815 let arg_type = ty::node_id_to_type(cx.tcx(), arg.pat.id);
816 let arg_type = arg_type.substp(cx.tcx(), param_substs);
817 signature.push(type_metadata(cx, arg_type, codemap::DUMMY_SP));
820 return create_DIArray(DIB(cx), signature.as_slice());
823 fn get_template_parameters(cx: &CrateContext,
824 generics: &ast::Generics,
825 param_substs: Option<¶m_substs>,
826 file_metadata: DIFile,
827 name_to_append_suffix_to: &mut String)
829 let self_type = match param_substs {
830 Some(param_substs) => param_substs.substs.self_ty,
834 // Only true for static default methods:
835 let has_self_type = self_type.is_some();
837 if !generics.is_type_parameterized() && !has_self_type {
838 return create_DIArray(DIB(cx), []);
841 name_to_append_suffix_to.push_char('<');
843 // The list to be filled with template parameters:
844 let mut template_params: Vec<DIDescriptor> =
845 Vec::with_capacity(generics.ty_params.len() + 1);
849 let actual_self_type = self_type.unwrap();
850 // Add self type name to <...> clause of function name
851 let actual_self_type_name = ppaux::ty_to_str(cx.tcx(), actual_self_type);
852 name_to_append_suffix_to.push_str(
853 actual_self_type_name.as_slice());
855 if generics.is_type_parameterized() {
856 name_to_append_suffix_to.push_str(",");
859 // Only create type information if full debuginfo is enabled
860 if cx.sess().opts.debuginfo == FullDebugInfo {
861 let actual_self_type_metadata = type_metadata(cx,
865 let ident = special_idents::type_self;
867 let param_metadata = token::get_ident(ident).get()
870 llvm::LLVMDIBuilderCreateTemplateTypeParameter(
874 actual_self_type_metadata,
881 template_params.push(param_metadata);
885 // Handle other generic parameters
886 let actual_types = match param_substs {
887 Some(param_substs) => ¶m_substs.substs.tps,
889 return create_DIArray(DIB(cx), template_params.as_slice());
893 for (index, &ast::TyParam{ ident: ident, .. }) in generics.ty_params.iter().enumerate() {
894 let actual_type = *actual_types.get(index);
895 // Add actual type name to <...> clause of function name
896 let actual_type_name = ppaux::ty_to_str(cx.tcx(), actual_type);
897 name_to_append_suffix_to.push_str(actual_type_name.as_slice());
899 if index != generics.ty_params.len() - 1 {
900 name_to_append_suffix_to.push_str(",");
903 // Again, only create type information if full debuginfo is enabled
904 if cx.sess().opts.debuginfo == FullDebugInfo {
905 let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP);
906 let param_metadata = token::get_ident(ident).get()
909 llvm::LLVMDIBuilderCreateTemplateTypeParameter(
913 actual_type_metadata,
919 template_params.push(param_metadata);
923 name_to_append_suffix_to.push_char('>');
925 return create_DIArray(DIB(cx), template_params.as_slice());
929 //=-------------------------------------------------------------------------------------------------
930 // Module-Internal debug info creation functions
931 //=-------------------------------------------------------------------------------------------------
933 fn is_node_local_to_unit(cx: &CrateContext, node_id: ast::NodeId) -> bool
935 // The is_local_to_unit flag indicates whether a function is local to the current compilation
936 // unit (i.e. if it is *static* in the C-sense). The *reachable* set should provide a good
937 // approximation of this, as it contains everything that might leak out of the current crate
938 // (by being externally visible or by being inlined into something externally visible). It might
939 // better to use the `exported_items` set from `driver::CrateAnalysis` in the future, but (atm)
940 // this set is not available in the translation pass.
941 !cx.reachable.contains(&node_id)
944 fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
946 llvm::LLVMDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32)
950 fn compile_unit_metadata(cx: &CrateContext) {
951 let work_dir = &cx.sess().working_dir;
952 let compile_unit_name = match cx.sess().local_crate_source_file {
953 None => fallback_path(cx),
954 Some(ref abs_path) => {
955 if abs_path.is_relative() {
956 cx.sess().warn("debuginfo: Invalid path to crate's local root source file!");
959 match abs_path.path_relative_from(work_dir) {
960 Some(ref p) if p.is_relative() => {
961 // prepend "./" if necessary
962 let dotdot = bytes!("..");
963 let prefix = &[dotdot[0], ::std::path::SEP_BYTE];
964 let mut path_bytes = Vec::from_slice(p.as_vec());
966 if path_bytes.slice_to(2) != prefix &&
967 path_bytes.slice_to(2) != dotdot {
968 path_bytes.insert(0, prefix[0]);
969 path_bytes.insert(1, prefix[1]);
972 path_bytes.as_slice().to_c_str()
974 _ => fallback_path(cx)
980 debug!("compile_unit_metadata: {:?}", compile_unit_name);
981 let producer = format!("rustc version {}",
982 (option_env!("CFG_VERSION")).expect("CFG_VERSION"));
984 compile_unit_name.with_ref(|compile_unit_name| {
985 work_dir.as_vec().with_c_str(|work_dir| {
986 producer.with_c_str(|producer| {
987 "".with_c_str(|flags| {
988 "".with_c_str(|split_name| {
990 llvm::LLVMDIBuilderCreateCompileUnit(
991 debug_context(cx).builder,
996 cx.sess().opts.optimize != config::No,
1007 fn fallback_path(cx: &CrateContext) -> CString {
1008 cx.link_meta.crateid.name.as_slice().to_c_str()
1012 fn declare_local(bcx: &Block,
1013 variable_ident: ast::Ident,
1014 variable_type: ty::t,
1015 scope_metadata: DIScope,
1016 variable_access: VariableAccess,
1017 variable_kind: VariableKind,
1019 let cx: &CrateContext = bcx.ccx();
1021 let filename = span_start(cx, span).file.name.clone();
1022 let file_metadata = file_metadata(cx, filename.as_slice());
1024 let name = token::get_ident(variable_ident);
1025 let loc = span_start(cx, span);
1026 let type_metadata = type_metadata(cx, variable_type, span);
1028 let (argument_index, dwarf_tag) = match variable_kind {
1029 ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),
1031 CapturedVariable => (0, DW_TAG_auto_variable)
1034 let (var_alloca, var_metadata) = name.get().with_c_str(|name| {
1035 match variable_access {
1036 DirectVariable { alloca } => (
1039 llvm::LLVMDIBuilderCreateLocalVariable(
1047 cx.sess().opts.optimize != config::No,
1052 IndirectVariable { alloca, address_operations } => (
1055 llvm::LLVMDIBuilderCreateComplexVariable(
1063 address_operations.as_ptr(),
1064 address_operations.len() as c_uint,
1071 set_debug_location(cx, DebugLocation::new(scope_metadata, loc.line, loc.col.to_uint()));
1073 let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
1079 llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr);
1082 match variable_kind {
1083 ArgumentVariable(_) | CapturedVariable => {
1087 .source_locations_enabled
1089 set_debug_location(cx, UnknownLocation);
1091 _ => { /* nothing to do */ }
1095 fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
1096 match debug_context(cx).created_files.borrow().find_equiv(&full_path) {
1097 Some(file_metadata) => return *file_metadata,
1101 debug!("file_metadata: {}", full_path);
1103 // FIXME (#9639): This needs to handle non-utf8 paths
1104 let work_dir = cx.sess().working_dir.as_str().unwrap();
1106 if full_path.starts_with(work_dir) {
1107 full_path.slice(work_dir.len() + 1u, full_path.len())
1113 file_name.with_c_str(|file_name| {
1114 work_dir.with_c_str(|work_dir| {
1116 llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir)
1121 let mut created_files = debug_context(cx).created_files.borrow_mut();
1122 created_files.insert(full_path.to_string(), file_metadata);
1123 return file_metadata;
1126 /// Finds the scope metadata node for the given AST node.
1127 fn scope_metadata(fcx: &FunctionContext,
1128 node_id: ast::NodeId,
1131 let scope_map = &fcx.debug_context.get_ref(fcx.ccx, span).scope_map;
1132 match scope_map.borrow().find_copy(&node_id) {
1133 Some(scope_metadata) => scope_metadata,
1135 let node = fcx.ccx.tcx.map.get(node_id);
1137 fcx.ccx.sess().span_bug(span,
1138 format!("debuginfo: Could not find scope info for node {:?}",
1144 fn basic_type_metadata(cx: &CrateContext, t: ty::t) -> DIType {
1146 debug!("basic_type_metadata: {:?}", ty::get(t));
1148 let (name, encoding) = match ty::get(t).sty {
1149 ty::ty_nil => ("()".to_string(), DW_ATE_unsigned),
1150 ty::ty_bot => ("!".to_string(), DW_ATE_unsigned),
1151 ty::ty_bool => ("bool".to_string(), DW_ATE_boolean),
1152 ty::ty_char => ("char".to_string(), DW_ATE_unsigned_char),
1153 ty::ty_int(int_ty) => match int_ty {
1154 ast::TyI => ("int".to_string(), DW_ATE_signed),
1155 ast::TyI8 => ("i8".to_string(), DW_ATE_signed),
1156 ast::TyI16 => ("i16".to_string(), DW_ATE_signed),
1157 ast::TyI32 => ("i32".to_string(), DW_ATE_signed),
1158 ast::TyI64 => ("i64".to_string(), DW_ATE_signed)
1160 ty::ty_uint(uint_ty) => match uint_ty {
1161 ast::TyU => ("uint".to_string(), DW_ATE_unsigned),
1162 ast::TyU8 => ("u8".to_string(), DW_ATE_unsigned),
1163 ast::TyU16 => ("u16".to_string(), DW_ATE_unsigned),
1164 ast::TyU32 => ("u32".to_string(), DW_ATE_unsigned),
1165 ast::TyU64 => ("u64".to_string(), DW_ATE_unsigned)
1167 ty::ty_float(float_ty) => match float_ty {
1168 ast::TyF32 => ("f32".to_string(), DW_ATE_float),
1169 ast::TyF64 => ("f64".to_string(), DW_ATE_float),
1170 ast::TyF128 => ("f128".to_string(), DW_ATE_float)
1172 _ => cx.sess().bug("debuginfo::basic_type_metadata - t is invalid type")
1175 let llvm_type = type_of::type_of(cx, t);
1176 let (size, align) = size_and_align_of(cx, llvm_type);
1177 let ty_metadata = name.with_c_str(|name| {
1179 llvm::LLVMDIBuilderCreateBasicType(
1182 bytes_to_bits(size),
1183 bytes_to_bits(align),
1191 fn pointer_type_metadata(cx: &CrateContext,
1192 pointer_type: ty::t,
1193 pointee_type_metadata: DIType)
1195 let pointer_llvm_type = type_of::type_of(cx, pointer_type);
1196 let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
1197 let name = ppaux::ty_to_str(cx.tcx(), pointer_type);
1198 let ptr_metadata = name.as_slice().with_c_str(|name| {
1200 llvm::LLVMDIBuilderCreatePointerType(
1202 pointee_type_metadata,
1203 bytes_to_bits(pointer_size),
1204 bytes_to_bits(pointer_align),
1208 return ptr_metadata;
1211 enum MemberDescriptionFactory {
1212 StructMD(StructMemberDescriptionFactory),
1213 TupleMD(TupleMemberDescriptionFactory),
1214 GeneralMD(GeneralMemberDescriptionFactory),
1215 EnumVariantMD(EnumVariantMemberDescriptionFactory)
1218 impl MemberDescriptionFactory {
1219 fn create_member_descriptions(&self, cx: &CrateContext)
1220 -> Vec<MemberDescription> {
1222 StructMD(ref this) => {
1223 this.create_member_descriptions(cx)
1225 TupleMD(ref this) => {
1226 this.create_member_descriptions(cx)
1228 GeneralMD(ref this) => {
1229 this.create_member_descriptions(cx)
1231 EnumVariantMD(ref this) => {
1232 this.create_member_descriptions(cx)
1238 struct StructMemberDescriptionFactory {
1239 fields: Vec<ty::field>,
1244 impl StructMemberDescriptionFactory {
1245 fn create_member_descriptions(&self, cx: &CrateContext) -> Vec<MemberDescription> {
1246 if self.fields.len() == 0 {
1250 let field_size = if self.is_simd {
1251 machine::llsize_of_alloc(cx, type_of::type_of(cx, self.fields.get(0).mt.ty))
1256 self.fields.iter().enumerate().map(|(i, field)| {
1257 let name = if field.ident.name == special_idents::unnamed_field.name {
1260 token::get_ident(field.ident).get().to_string()
1263 let offset = if self.is_simd {
1264 assert!(field_size != 0xdeadbeef);
1265 FixedMemberOffset { bytes: i as u64 * field_size }
1267 ComputedMemberOffset
1272 llvm_type: type_of::type_of(cx, field.mt.ty),
1273 type_metadata: type_metadata(cx, field.mt.ty, self.span),
1280 fn prepare_struct_metadata(cx: &CrateContext,
1283 substs: &ty::substs,
1285 -> RecursiveTypeDescription {
1286 let struct_name = ppaux::ty_to_str(cx.tcx(), struct_type);
1287 let struct_llvm_type = type_of::type_of(cx, struct_type);
1289 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id);
1291 let file_name = span_start(cx, definition_span).file.name.clone();
1292 let file_metadata = file_metadata(cx, file_name.as_slice());
1294 let struct_metadata_stub = create_struct_stub(cx,
1296 struct_name.as_slice(),
1301 let fields = ty::struct_fields(cx.tcx(), def_id, substs);
1303 UnfinishedMetadata {
1304 cache_id: cache_id_for_type(struct_type),
1305 metadata_stub: struct_metadata_stub,
1306 llvm_type: struct_llvm_type,
1307 file_metadata: file_metadata,
1308 member_description_factory: StructMD(StructMemberDescriptionFactory {
1310 is_simd: ty::type_is_simd(cx.tcx(), struct_type),
1316 enum RecursiveTypeDescription {
1317 UnfinishedMetadata {
1319 metadata_stub: DICompositeType,
1321 file_metadata: DIFile,
1322 member_description_factory: MemberDescriptionFactory,
1324 FinalMetadata(DICompositeType)
1327 impl RecursiveTypeDescription {
1329 fn finalize(&self, cx: &CrateContext) -> DICompositeType {
1331 FinalMetadata(metadata) => metadata,
1332 UnfinishedMetadata {
1337 ref member_description_factory
1339 // Insert the stub into the cache in order to allow recursive references ...
1340 debug_context(cx).created_types.borrow_mut()
1341 .insert(cache_id, metadata_stub);
1343 // ... then create the member descriptions ...
1344 let member_descriptions = member_description_factory.create_member_descriptions(cx);
1346 // ... and attach them to the stub to complete it.
1347 set_members_of_composite_type(cx,
1350 member_descriptions.as_slice(),
1353 return metadata_stub;
1359 struct TupleMemberDescriptionFactory {
1360 component_types: Vec<ty::t> ,
1364 impl TupleMemberDescriptionFactory {
1365 fn create_member_descriptions(&self, cx: &CrateContext)
1366 -> Vec<MemberDescription> {
1367 self.component_types.iter().map(|&component_type| {
1369 name: "".to_string(),
1370 llvm_type: type_of::type_of(cx, component_type),
1371 type_metadata: type_metadata(cx, component_type, self.span),
1372 offset: ComputedMemberOffset,
1378 fn prepare_tuple_metadata(cx: &CrateContext,
1380 component_types: &[ty::t],
1382 -> RecursiveTypeDescription {
1383 let tuple_name = ppaux::ty_to_str(cx.tcx(), tuple_type);
1384 let tuple_llvm_type = type_of::type_of(cx, tuple_type);
1386 let loc = span_start(cx, span);
1387 let file_metadata = file_metadata(cx, loc.file.name.as_slice());
1389 UnfinishedMetadata {
1390 cache_id: cache_id_for_type(tuple_type),
1391 metadata_stub: create_struct_stub(cx,
1393 tuple_name.as_slice(),
1397 llvm_type: tuple_llvm_type,
1398 file_metadata: file_metadata,
1399 member_description_factory: TupleMD(TupleMemberDescriptionFactory {
1400 component_types: Vec::from_slice(component_types),
1406 struct GeneralMemberDescriptionFactory {
1407 type_rep: Rc<adt::Repr>,
1408 variants: Rc<Vec<Rc<ty::VariantInfo>>>,
1409 discriminant_type_metadata: ValueRef,
1410 containing_scope: DIScope,
1411 file_metadata: DIFile,
1415 impl GeneralMemberDescriptionFactory {
1416 fn create_member_descriptions(&self, cx: &CrateContext)
1417 -> Vec<MemberDescription> {
1418 // Capture type_rep, so we don't have to copy the struct_defs array
1419 let struct_defs = match *self.type_rep {
1420 adt::General(_, ref struct_defs) => struct_defs,
1421 _ => cx.sess().bug("unreachable")
1427 .map(|(i, struct_def)| {
1428 let (variant_type_metadata, variant_llvm_type, member_desc_factory) =
1429 describe_enum_variant(cx,
1431 &**self.variants.get(i),
1432 Some(self.discriminant_type_metadata),
1433 self.containing_scope,
1437 let member_descriptions =
1438 member_desc_factory.create_member_descriptions(cx);
1440 set_members_of_composite_type(cx,
1441 variant_type_metadata,
1443 member_descriptions.as_slice(),
1447 name: "".to_string(),
1448 llvm_type: variant_llvm_type,
1449 type_metadata: variant_type_metadata,
1450 offset: FixedMemberOffset { bytes: 0 },
1456 struct EnumVariantMemberDescriptionFactory {
1457 args: Vec<(String, ty::t)> ,
1458 discriminant_type_metadata: Option<DIType>,
1462 impl EnumVariantMemberDescriptionFactory {
1463 fn create_member_descriptions(&self, cx: &CrateContext)
1464 -> Vec<MemberDescription> {
1465 self.args.iter().enumerate().map(|(i, &(ref name, ty))| {
1467 name: name.to_string(),
1468 llvm_type: type_of::type_of(cx, ty),
1469 type_metadata: match self.discriminant_type_metadata {
1470 Some(metadata) if i == 0 => metadata,
1471 _ => type_metadata(cx, ty, self.span)
1473 offset: ComputedMemberOffset,
1479 fn describe_enum_variant(cx: &CrateContext,
1480 struct_def: &adt::Struct,
1481 variant_info: &ty::VariantInfo,
1482 discriminant_type_metadata: Option<DIType>,
1483 containing_scope: DIScope,
1484 file_metadata: DIFile,
1486 -> (DICompositeType, Type, MemberDescriptionFactory) {
1487 let variant_llvm_type =
1488 Type::struct_(cx, struct_def.fields
1490 .map(|&t| type_of::type_of(cx, t))
1491 .collect::<Vec<_>>()
1494 // Could some consistency checks here: size, align, field count, discr type
1496 // Find the source code location of the variant's definition
1497 let variant_definition_span = if variant_info.id.krate == ast::LOCAL_CRATE {
1498 cx.tcx.map.span(variant_info.id.node)
1500 // For definitions from other crates we have no location information available.
1504 let metadata_stub = create_struct_stub(cx,
1506 token::get_ident(variant_info.name).get(),
1509 variant_definition_span);
1511 // Get the argument names from the enum variant info
1512 let mut arg_names: Vec<_> = match variant_info.arg_names {
1513 Some(ref names) => {
1516 token::get_ident(*ident).get().to_str().into_string()
1519 None => variant_info.args.iter().map(|_| "".to_string()).collect()
1522 // If this is not a univariant enum, there is also the (unnamed) discriminant field
1523 if discriminant_type_metadata.is_some() {
1524 arg_names.insert(0, "".to_string());
1527 // Build an array of (field name, field type) pairs to be captured in the factory closure.
1528 let args: Vec<(String, ty::t)> = arg_names.iter()
1529 .zip(struct_def.fields.iter())
1530 .map(|(s, &t)| (s.to_string(), t))
1533 let member_description_factory =
1534 EnumVariantMD(EnumVariantMemberDescriptionFactory {
1536 discriminant_type_metadata: discriminant_type_metadata,
1540 (metadata_stub, variant_llvm_type, member_description_factory)
1543 fn prepare_enum_metadata(cx: &CrateContext,
1545 enum_def_id: ast::DefId,
1547 -> RecursiveTypeDescription {
1548 let enum_name = ppaux::ty_to_str(cx.tcx(), enum_type);
1550 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, enum_def_id);
1551 let loc = span_start(cx, definition_span);
1552 let file_metadata = file_metadata(cx, loc.file.name.as_slice());
1554 // For empty enums there is an early exit. Just describe it as an empty struct with the
1555 // appropriate type name
1556 if ty::type_is_empty(cx.tcx(), enum_type) {
1557 let empty_type_metadata = composite_type_metadata(
1560 enum_name.as_slice(),
1566 return FinalMetadata(empty_type_metadata);
1569 let variants = ty::enum_variants(cx.tcx(), enum_def_id);
1571 let enumerators_metadata: Vec<DIDescriptor> = variants
1574 token::get_ident(v.name).get().with_c_str(|name| {
1576 llvm::LLVMDIBuilderCreateEnumerator(
1579 v.disr_val as c_ulonglong)
1585 let discriminant_type_metadata = |inttype| {
1586 // We can reuse the type of the discriminant for all monomorphized instances of an enum
1587 // because it doesn't depend on any type parameters. The def_id, uniquely identifying the
1588 // enum's polytype acts as key in this cache.
1589 let cached_discriminant_type_metadata = debug_context(cx).created_enum_disr_types
1591 .find_copy(&enum_def_id);
1592 match cached_discriminant_type_metadata {
1593 Some(discriminant_type_metadata) => discriminant_type_metadata,
1595 let discriminant_llvm_type = adt::ll_inttype(cx, inttype);
1596 let (discriminant_size, discriminant_align) =
1597 size_and_align_of(cx, discriminant_llvm_type);
1598 let discriminant_base_type_metadata = type_metadata(cx,
1599 adt::ty_of_inttype(inttype),
1601 let discriminant_name = get_enum_discriminant_name(cx, enum_def_id);
1603 let discriminant_type_metadata = discriminant_name.get().with_c_str(|name| {
1605 llvm::LLVMDIBuilderCreateEnumerationType(
1611 bytes_to_bits(discriminant_size),
1612 bytes_to_bits(discriminant_align),
1613 create_DIArray(DIB(cx), enumerators_metadata.as_slice()),
1614 discriminant_base_type_metadata)
1618 debug_context(cx).created_enum_disr_types
1620 .insert(enum_def_id, discriminant_type_metadata);
1622 discriminant_type_metadata
1627 let type_rep = adt::represent_type(cx, enum_type);
1629 return match *type_rep {
1630 adt::CEnum(inttype, _, _) => {
1631 FinalMetadata(discriminant_type_metadata(inttype))
1633 adt::Univariant(ref struct_def, _) => {
1634 assert!(variants.len() == 1);
1637 member_description_factory) =
1638 describe_enum_variant(cx,
1645 UnfinishedMetadata {
1646 cache_id: cache_id_for_type(enum_type),
1647 metadata_stub: metadata_stub,
1648 llvm_type: variant_llvm_type,
1649 file_metadata: file_metadata,
1650 member_description_factory: member_description_factory
1653 adt::General(inttype, _) => {
1654 let discriminant_type_metadata = discriminant_type_metadata(inttype);
1655 let enum_llvm_type = type_of::type_of(cx, enum_type);
1656 let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type);
1657 let unique_id = generate_unique_type_id("DI_ENUM_");
1659 let enum_metadata = enum_name.as_slice().with_c_str(|enum_name| {
1660 unique_id.as_slice().with_c_str(|unique_id| {
1662 llvm::LLVMDIBuilderCreateUnionType(
1668 bytes_to_bits(enum_type_size),
1669 bytes_to_bits(enum_type_align),
1678 UnfinishedMetadata {
1679 cache_id: cache_id_for_type(enum_type),
1680 metadata_stub: enum_metadata,
1681 llvm_type: enum_llvm_type,
1682 file_metadata: file_metadata,
1683 member_description_factory: GeneralMD(GeneralMemberDescriptionFactory {
1684 type_rep: type_rep.clone(),
1686 discriminant_type_metadata: discriminant_type_metadata,
1687 containing_scope: containing_scope,
1688 file_metadata: file_metadata,
1693 adt::RawNullablePointer { nnty, .. } => {
1694 FinalMetadata(type_metadata(cx, nnty, span))
1696 adt::StructWrappedNullablePointer { nonnull: ref struct_def, nndiscr, .. } => {
1699 member_description_factory) =
1700 describe_enum_variant(cx,
1702 &**variants.get(nndiscr as uint),
1707 UnfinishedMetadata {
1708 cache_id: cache_id_for_type(enum_type),
1709 metadata_stub: metadata_stub,
1710 llvm_type: variant_llvm_type,
1711 file_metadata: file_metadata,
1712 member_description_factory: member_description_factory
1717 fn get_enum_discriminant_name(cx: &CrateContext, def_id: ast::DefId) -> token::InternedString {
1718 let name = if def_id.krate == ast::LOCAL_CRATE {
1719 cx.tcx.map.get_path_elem(def_id.node).name()
1721 csearch::get_item_path(&cx.tcx, def_id).last().unwrap().name()
1724 token::get_name(name)
1729 FixedMemberOffset { bytes: u64 },
1730 // For ComputedMemberOffset, the offset is read from the llvm type definition
1731 ComputedMemberOffset
1734 struct MemberDescription {
1737 type_metadata: DIType,
1738 offset: MemberOffset,
1741 /// Creates debug information for a composite type, that is, anything that results in a LLVM struct.
1743 /// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums.
1744 fn composite_type_metadata(cx: &CrateContext,
1745 composite_llvm_type: Type,
1746 composite_type_name: &str,
1747 member_descriptions: &[MemberDescription],
1748 containing_scope: DIScope,
1749 file_metadata: DIFile,
1750 definition_span: Span)
1751 -> DICompositeType {
1752 // Create the (empty) struct metadata node ...
1753 let composite_type_metadata = create_struct_stub(cx,
1754 composite_llvm_type,
1755 composite_type_name,
1760 // ... and immediately create and add the member descriptions.
1761 set_members_of_composite_type(cx,
1762 composite_type_metadata,
1763 composite_llvm_type,
1764 member_descriptions,
1768 return composite_type_metadata;
1771 fn set_members_of_composite_type(cx: &CrateContext,
1772 composite_type_metadata: DICompositeType,
1773 composite_llvm_type: Type,
1774 member_descriptions: &[MemberDescription],
1775 file_metadata: DIFile,
1776 definition_span: Span) {
1777 // In some rare cases LLVM metadata uniquing would lead to an existing type description being
1778 // used instead of a new one created in create_struct_stub. This would cause a hard to trace
1779 // assertion in DICompositeType::SetTypeArray(). The following check makes sure that we get a
1780 // better error message if this should happen again due to some regression.
1782 let mut composite_types_completed =
1783 debug_context(cx).composite_types_completed.borrow_mut();
1784 if composite_types_completed.contains(&composite_type_metadata) {
1785 cx.sess().span_bug(definition_span, "debuginfo::set_members_of_composite_type() - \
1786 Already completed forward declaration \
1789 composite_types_completed.insert(composite_type_metadata);
1793 let loc = span_start(cx, definition_span);
1795 let member_metadata: Vec<DIDescriptor> = member_descriptions
1798 .map(|(i, member_description)| {
1799 let (member_size, member_align) = size_and_align_of(cx, member_description.llvm_type);
1800 let member_offset = match member_description.offset {
1801 FixedMemberOffset { bytes } => bytes as u64,
1802 ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i)
1805 member_description.name.as_slice().with_c_str(|member_name| {
1807 llvm::LLVMDIBuilderCreateMemberType(
1809 composite_type_metadata,
1813 bytes_to_bits(member_size),
1814 bytes_to_bits(member_align),
1815 bytes_to_bits(member_offset),
1817 member_description.type_metadata)
1824 let type_array = create_DIArray(DIB(cx), member_metadata.as_slice());
1825 llvm::LLVMDICompositeTypeSetTypeArray(composite_type_metadata, type_array);
1829 // A convenience wrapper around LLVMDIBuilderCreateStructType(). Does not do any caching, does not
1830 // add any fields to the struct. This can be done later with set_members_of_composite_type().
1831 fn create_struct_stub(cx: &CrateContext,
1832 struct_llvm_type: Type,
1833 struct_type_name: &str,
1834 containing_scope: DIScope,
1835 file_metadata: DIFile,
1836 definition_span: Span)
1837 -> DICompositeType {
1838 let loc = span_start(cx, definition_span);
1839 let (struct_size, struct_align) = size_and_align_of(cx, struct_llvm_type);
1841 // We assign unique IDs to the type stubs so LLVM metadata uniquing does not reuse instances
1842 // where we don't want it.
1843 let unique_id = generate_unique_type_id("DI_STRUCT_");
1846 struct_type_name.with_c_str(|name| {
1847 unique_id.as_slice().with_c_str(|unique_id| {
1848 // LLVMDIBuilderCreateStructType() wants an empty array. A null pointer will lead to
1849 // hard to trace and debug LLVM assertions later on in llvm/lib/IR/Value.cpp
1850 let empty_array = create_DIArray(DIB(cx), []);
1852 llvm::LLVMDIBuilderCreateStructType(
1858 bytes_to_bits(struct_size),
1859 bytes_to_bits(struct_align),
1871 fn boxed_type_metadata(cx: &CrateContext,
1872 content_type_name: Option<&str>,
1873 content_llvm_type: Type,
1874 content_type_metadata: DIType,
1876 -> DICompositeType {
1877 let box_type_name = match content_type_name {
1878 Some(content_type_name) => format!("Boxed<{}>", content_type_name),
1879 None => "BoxedType".to_string()
1882 let box_llvm_type = Type::at_box(cx, content_llvm_type);
1883 let member_llvm_types = box_llvm_type.field_types();
1884 assert!(box_layout_is_correct(cx,
1885 member_llvm_types.as_slice(),
1886 content_llvm_type));
1888 let int_type = ty::mk_int();
1889 let nil_pointer_type = ty::mk_nil_ptr(cx.tcx());
1890 let nil_pointer_type_metadata = type_metadata(cx, nil_pointer_type, codemap::DUMMY_SP);
1892 let member_descriptions = [
1894 name: "refcnt".to_string(),
1895 llvm_type: *member_llvm_types.get(0),
1896 type_metadata: type_metadata(cx, int_type, codemap::DUMMY_SP),
1897 offset: ComputedMemberOffset,
1900 name: "drop_glue".to_string(),
1901 llvm_type: *member_llvm_types.get(1),
1902 type_metadata: nil_pointer_type_metadata,
1903 offset: ComputedMemberOffset,
1906 name: "prev".to_string(),
1907 llvm_type: *member_llvm_types.get(2),
1908 type_metadata: nil_pointer_type_metadata,
1909 offset: ComputedMemberOffset,
1912 name: "next".to_string(),
1913 llvm_type: *member_llvm_types.get(3),
1914 type_metadata: nil_pointer_type_metadata,
1915 offset: ComputedMemberOffset,
1918 name: "val".to_string(),
1919 llvm_type: *member_llvm_types.get(4),
1920 type_metadata: content_type_metadata,
1921 offset: ComputedMemberOffset,
1925 let loc = span_start(cx, span);
1926 let file_metadata = file_metadata(cx, loc.file.name.as_slice());
1928 return composite_type_metadata(
1931 box_type_name.as_slice(),
1932 member_descriptions,
1937 // Unfortunately, we cannot assert anything but the correct types here---and not whether the
1938 // 'next' and 'prev' pointers are in the correct order.
1939 fn box_layout_is_correct(cx: &CrateContext,
1940 member_llvm_types: &[Type],
1941 content_llvm_type: Type)
1943 member_llvm_types.len() == 5 &&
1944 member_llvm_types[0] == cx.int_type &&
1945 member_llvm_types[1] == Type::generic_glue_fn(cx).ptr_to() &&
1946 member_llvm_types[2] == Type::i8(cx).ptr_to() &&
1947 member_llvm_types[3] == Type::i8(cx).ptr_to() &&
1948 member_llvm_types[4] == content_llvm_type
1952 fn fixed_vec_metadata(cx: &CrateContext,
1953 element_type: ty::t,
1957 let element_type_metadata = type_metadata(cx, element_type, span);
1958 let element_llvm_type = type_of::type_of(cx, element_type);
1959 let (element_type_size, element_type_align) = size_and_align_of(cx, element_llvm_type);
1961 let subrange = unsafe {
1962 llvm::LLVMDIBuilderGetOrCreateSubrange(
1968 let subscripts = create_DIArray(DIB(cx), [subrange]);
1970 llvm::LLVMDIBuilderCreateArrayType(
1972 bytes_to_bits(element_type_size * (len as u64)),
1973 bytes_to_bits(element_type_align),
1974 element_type_metadata,
1979 fn vec_metadata(cx: &CrateContext,
1980 element_type: ty::t,
1982 -> DICompositeType {
1984 let element_type_metadata = type_metadata(cx, element_type, span);
1985 let element_llvm_type = type_of::type_of(cx, element_type);
1986 let (element_size, element_align) = size_and_align_of(cx, element_llvm_type);
1988 let vec_llvm_type = Type::vec(cx, &element_llvm_type);
1989 let vec_type_name = format!("[{}]",
1990 ppaux::ty_to_str(cx.tcx(), element_type));
1991 let vec_type_name = vec_type_name.as_slice();
1993 let member_llvm_types = vec_llvm_type.field_types();
1995 let int_type_metadata = type_metadata(cx, ty::mk_int(), span);
1996 let array_type_metadata = unsafe {
1997 llvm::LLVMDIBuilderCreateArrayType(
1999 bytes_to_bits(element_size),
2000 bytes_to_bits(element_align),
2001 element_type_metadata,
2002 create_DIArray(DIB(cx), [llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, 0)]))
2005 let member_descriptions = [
2007 name: "fill".to_string(),
2008 llvm_type: *member_llvm_types.get(0),
2009 type_metadata: int_type_metadata,
2010 offset: ComputedMemberOffset,
2013 name: "alloc".to_string(),
2014 llvm_type: *member_llvm_types.get(1),
2015 type_metadata: int_type_metadata,
2016 offset: ComputedMemberOffset,
2019 name: "elements".to_string(),
2020 llvm_type: *member_llvm_types.get(2),
2021 type_metadata: array_type_metadata,
2022 offset: ComputedMemberOffset,
2026 assert!(member_descriptions.len() == member_llvm_types.len());
2028 let loc = span_start(cx, span);
2029 let file_metadata = file_metadata(cx, loc.file.name.as_slice());
2031 composite_type_metadata(
2035 member_descriptions,
2041 fn vec_slice_metadata(cx: &CrateContext,
2043 element_type: ty::t,
2045 -> DICompositeType {
2047 debug!("vec_slice_metadata: {:?}", ty::get(vec_type));
2049 let slice_llvm_type = type_of::type_of(cx, vec_type);
2050 let slice_type_name = ppaux::ty_to_str(cx.tcx(), vec_type);
2052 let member_llvm_types = slice_llvm_type.field_types();
2053 assert!(slice_layout_is_correct(cx,
2054 member_llvm_types.as_slice(),
2057 let data_ptr_type = ty::mk_ptr(cx.tcx(), ty::mt {
2059 mutbl: ast::MutImmutable
2062 let member_descriptions = [
2064 name: "data_ptr".to_string(),
2065 llvm_type: *member_llvm_types.get(0),
2066 type_metadata: type_metadata(cx, data_ptr_type, span),
2067 offset: ComputedMemberOffset,
2070 name: "length".to_string(),
2071 llvm_type: *member_llvm_types.get(1),
2072 type_metadata: type_metadata(cx, ty::mk_uint(), span),
2073 offset: ComputedMemberOffset,
2077 assert!(member_descriptions.len() == member_llvm_types.len());
2079 let loc = span_start(cx, span);
2080 let file_metadata = file_metadata(cx, loc.file.name.as_slice());
2082 return composite_type_metadata(
2085 slice_type_name.as_slice(),
2086 member_descriptions,
2091 fn slice_layout_is_correct(cx: &CrateContext,
2092 member_llvm_types: &[Type],
2093 element_type: ty::t)
2095 member_llvm_types.len() == 2 &&
2096 member_llvm_types[0] == type_of::type_of(cx, element_type).ptr_to() &&
2097 member_llvm_types[1] == cx.int_type
2101 fn subroutine_type_metadata(cx: &CrateContext,
2102 signature: &ty::FnSig,
2104 -> DICompositeType {
2105 let loc = span_start(cx, span);
2106 let file_metadata = file_metadata(cx, loc.file.name.as_slice());
2108 let mut signature_metadata: Vec<DIType> =
2109 Vec::with_capacity(signature.inputs.len() + 1);
2112 signature_metadata.push(match ty::get(signature.output).sty {
2113 ty::ty_nil => ptr::null(),
2114 _ => type_metadata(cx, signature.output, span)
2117 // regular arguments
2118 for &argument_type in signature.inputs.iter() {
2119 signature_metadata.push(type_metadata(cx, argument_type, span));
2123 llvm::LLVMDIBuilderCreateSubroutineType(
2126 create_DIArray(DIB(cx), signature_metadata.as_slice()))
2130 fn trait_metadata(cx: &CrateContext,
2133 substs: &ty::substs,
2134 trait_store: ty::TraitStore,
2135 _: &ty::BuiltinBounds)
2137 // The implementation provided here is a stub. It makes sure that the trait type is
2138 // assigned the correct name, size, namespace, and source location. But it does not describe
2139 // the trait's methods.
2140 let last = ty::with_path(cx.tcx(), def_id, |mut path| path.last().unwrap());
2141 let ident_string = token::get_name(last.name());
2142 let mut name = ppaux::trait_store_to_str(cx.tcx(), trait_store);
2143 name.push_str(ident_string.get());
2144 // Add type and region parameters
2145 let name = ppaux::parameterized(cx.tcx(),
2148 substs.tps.as_slice(),
2152 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id);
2154 let file_name = span_start(cx, definition_span).file.name.clone();
2155 let file_metadata = file_metadata(cx, file_name.as_slice());
2157 let trait_llvm_type = type_of::type_of(cx, trait_type);
2159 composite_type_metadata(cx,
2168 fn type_metadata(cx: &CrateContext,
2170 usage_site_span: Span)
2172 let cache_id = cache_id_for_type(t);
2174 match debug_context(cx).created_types.borrow().find(&cache_id) {
2175 Some(type_metadata) => return *type_metadata,
2179 fn create_pointer_to_box_metadata(cx: &CrateContext,
2180 pointer_type: ty::t,
2183 let content_type_name = ppaux::ty_to_str(cx.tcx(), type_in_box);
2184 let content_type_name = content_type_name.as_slice();
2185 let content_llvm_type = type_of::type_of(cx, type_in_box);
2186 let content_type_metadata = type_metadata(
2191 let box_metadata = boxed_type_metadata(
2193 Some(content_type_name),
2195 content_type_metadata,
2198 pointer_type_metadata(cx, pointer_type, box_metadata)
2201 debug!("type_metadata: {:?}", ty::get(t));
2203 let sty = &ty::get(t).sty;
2204 let type_metadata = match *sty {
2211 ty::ty_float(_) => {
2212 basic_type_metadata(cx, t)
2214 ty::ty_enum(def_id, _) => {
2215 prepare_enum_metadata(cx, t, def_id, usage_site_span).finalize(cx)
2217 ty::ty_box(typ) => {
2218 create_pointer_to_box_metadata(cx, t, typ)
2220 ty::ty_vec(ref mt, Some(len)) => fixed_vec_metadata(cx, mt.ty, len, usage_site_span),
2221 ty::ty_uniq(typ) => {
2222 match ty::get(typ).sty {
2223 ty::ty_vec(ref mt, None) => {
2224 let vec_metadata = vec_metadata(cx, mt.ty, usage_site_span);
2225 pointer_type_metadata(cx, t, vec_metadata)
2228 let i8_t = ty::mk_i8();
2229 let vec_metadata = vec_metadata(cx, i8_t, usage_site_span);
2230 pointer_type_metadata(cx, t, vec_metadata)
2233 let pointee = type_metadata(cx, typ, usage_site_span);
2234 pointer_type_metadata(cx, t, pointee)
2238 ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => {
2239 match ty::get(mt.ty).sty {
2240 ty::ty_vec(ref mt, None) => vec_slice_metadata(cx, t, mt.ty, usage_site_span),
2242 let i8_t = ty::mk_i8();
2243 vec_slice_metadata(cx, t, i8_t, usage_site_span)
2246 let pointee = type_metadata(cx, mt.ty, usage_site_span);
2247 pointer_type_metadata(cx, t, pointee)
2251 ty::ty_bare_fn(ref barefnty) => {
2252 subroutine_type_metadata(cx, &barefnty.sig, usage_site_span)
2254 ty::ty_closure(ref closurety) => {
2255 subroutine_type_metadata(cx, &closurety.sig, usage_site_span)
2257 ty::ty_trait(box ty::TyTrait {
2263 trait_metadata(cx, def_id, t, substs, store, bounds)
2265 ty::ty_struct(def_id, ref substs) => {
2266 prepare_struct_metadata(cx, t, def_id, substs, usage_site_span).finalize(cx)
2268 ty::ty_tup(ref elements) => {
2269 prepare_tuple_metadata(cx,
2271 elements.as_slice(),
2272 usage_site_span).finalize(cx)
2275 cx.sess().bug(format!("debuginfo: unexpected type in \
2276 type_metadata: {:?}",
2281 debug_context(cx).created_types.borrow_mut().insert(cache_id, type_metadata);
2286 enum DebugLocation {
2287 KnownLocation { scope: DIScope, line: uint, col: uint },
2291 impl DebugLocation {
2292 fn new(scope: DIScope, line: uint, col: uint) -> DebugLocation {
2301 fn set_debug_location(cx: &CrateContext, debug_location: DebugLocation) {
2302 if debug_location == debug_context(cx).current_debug_location.get() {
2308 match debug_location {
2309 KnownLocation { scope, line, .. } => {
2310 let col = 0; // Always set the column to zero like Clang and GCC
2311 debug!("setting debug location to {} {}", line, col);
2312 let elements = [C_i32(cx, line as i32), C_i32(cx, col as i32), scope, ptr::null()];
2314 metadata_node = llvm::LLVMMDNodeInContext(debug_context(cx).llcontext,
2316 elements.len() as c_uint);
2319 UnknownLocation => {
2320 debug!("clearing debug location ");
2321 metadata_node = ptr::null();
2326 llvm::LLVMSetCurrentDebugLocation(cx.builder.b, metadata_node);
2329 debug_context(cx).current_debug_location.set(debug_location);
2332 //=-------------------------------------------------------------------------------------------------
2333 // Utility Functions
2334 //=-------------------------------------------------------------------------------------------------
2336 fn cache_id_for_type(t: ty::t) -> uint {
2340 // Used to avoid LLVM metadata uniquing problems. See `create_struct_stub()` and
2341 // `prepare_enum_metadata()`.
2342 fn generate_unique_type_id(prefix: &'static str) -> String {
2344 static mut unique_id_counter: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;
2345 format_strbuf!("{}{}",
2347 unique_id_counter.fetch_add(1, atomics::SeqCst))
2351 /// Return codemap::Loc corresponding to the beginning of the span
2352 fn span_start(cx: &CrateContext, span: Span) -> codemap::Loc {
2353 cx.sess().codemap().lookup_char_pos(span.lo)
2356 fn size_and_align_of(cx: &CrateContext, llvm_type: Type) -> (u64, u64) {
2357 (machine::llsize_of_alloc(cx, llvm_type), machine::llalign_of_min(cx, llvm_type))
2360 fn bytes_to_bits(bytes: u64) -> c_ulonglong {
2361 (bytes * 8) as c_ulonglong
2365 fn debug_context<'a>(cx: &'a CrateContext) -> &'a CrateDebugContext {
2366 let debug_context: &'a CrateDebugContext = cx.dbg_cx.get_ref();
2371 fn DIB(cx: &CrateContext) -> DIBuilderRef {
2372 cx.dbg_cx.get_ref().builder
2375 fn fn_should_be_ignored(fcx: &FunctionContext) -> bool {
2376 match fcx.debug_context.repr {
2377 FunctionDebugContext(_) => false,
2382 fn assert_type_for_node_id(cx: &CrateContext, node_id: ast::NodeId, error_span: Span) {
2383 if !cx.tcx.node_types.borrow().contains_key(&(node_id as uint)) {
2384 cx.sess().span_bug(error_span, "debuginfo: Could not find type for node id!");
2388 fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: ast::DefId)
2389 -> (DIScope, Span) {
2390 let containing_scope = namespace_for_item(cx, def_id).scope;
2391 let definition_span = if def_id.krate == ast::LOCAL_CRATE {
2392 cx.tcx.map.span(def_id.node)
2394 // For external items there is no span information
2398 (containing_scope, definition_span)
2401 // This procedure builds the *scope map* for a given function, which maps any given ast::NodeId in
2402 // the function's AST to the correct DIScope metadata instance.
2404 // This builder procedure walks the AST in execution order and keeps track of what belongs to which
2405 // scope, creating DIScope DIEs along the way, and introducing *artificial* lexical scope
2406 // descriptors where necessary. These artificial scopes allow GDB to correctly handle name
2408 fn populate_scope_map(cx: &CrateContext,
2409 arg_pats: &[@ast::Pat],
2410 fn_entry_block: &ast::Block,
2411 fn_metadata: DISubprogram,
2412 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2413 let def_map = &cx.tcx.def_map;
2415 struct ScopeStackEntry {
2416 scope_metadata: DIScope,
2417 ident: Option<ast::Ident>
2420 let mut scope_stack = vec!(ScopeStackEntry { scope_metadata: fn_metadata, ident: None });
2422 // Push argument identifiers onto the stack so arguments integrate nicely with variable
2424 for &arg_pat in arg_pats.iter() {
2425 pat_util::pat_bindings(def_map, arg_pat, |_, _, _, path_ref| {
2426 let ident = ast_util::path_to_ident(path_ref);
2427 scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata, ident: Some(ident) });
2431 // Clang creates a separate scope for function bodies, so let's do this too
2433 fn_entry_block.span,
2436 |cx, scope_stack, scope_map| {
2437 walk_block(cx, fn_entry_block, scope_stack, scope_map);
2440 // local helper functions for walking the AST.
2441 fn with_new_scope(cx: &CrateContext,
2443 scope_stack: &mut Vec<ScopeStackEntry> ,
2444 scope_map: &mut HashMap<ast::NodeId, DIScope>,
2445 inner_walk: |&CrateContext,
2446 &mut Vec<ScopeStackEntry> ,
2447 &mut HashMap<ast::NodeId, DIScope>|) {
2448 // Create a new lexical scope and push it onto the stack
2449 let loc = cx.sess().codemap().lookup_char_pos(scope_span.lo);
2450 let file_metadata = file_metadata(cx, loc.file.name.as_slice());
2451 let parent_scope = scope_stack.last().unwrap().scope_metadata;
2453 let scope_metadata = unsafe {
2454 llvm::LLVMDIBuilderCreateLexicalBlock(
2459 loc.col.to_uint() as c_uint,
2463 scope_stack.push(ScopeStackEntry { scope_metadata: scope_metadata, ident: None });
2465 inner_walk(cx, scope_stack, scope_map);
2467 // pop artificial scopes
2468 while scope_stack.last().unwrap().ident.is_some() {
2472 if scope_stack.last().unwrap().scope_metadata != scope_metadata {
2473 cx.sess().span_bug(scope_span, "debuginfo: Inconsistency in scope management.");
2479 fn walk_block(cx: &CrateContext,
2481 scope_stack: &mut Vec<ScopeStackEntry> ,
2482 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2483 scope_map.insert(block.id, scope_stack.last().unwrap().scope_metadata);
2485 // The interesting things here are statements and the concluding expression.
2486 for statement in block.stmts.iter() {
2487 scope_map.insert(ast_util::stmt_id(*statement),
2488 scope_stack.last().unwrap().scope_metadata);
2490 match statement.node {
2491 ast::StmtDecl(decl, _) => walk_decl(cx, decl, scope_stack, scope_map),
2492 ast::StmtExpr(exp, _) |
2493 ast::StmtSemi(exp, _) => walk_expr(cx, exp, scope_stack, scope_map),
2494 ast::StmtMac(..) => () // ignore macros (which should be expanded anyway)
2498 for exp in block.expr.iter() {
2499 walk_expr(cx, *exp, scope_stack, scope_map);
2503 fn walk_decl(cx: &CrateContext,
2505 scope_stack: &mut Vec<ScopeStackEntry> ,
2506 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2508 codemap::Spanned { node: ast::DeclLocal(local), .. } => {
2509 scope_map.insert(local.id, scope_stack.last().unwrap().scope_metadata);
2511 walk_pattern(cx, local.pat, scope_stack, scope_map);
2513 for exp in local.init.iter() {
2514 walk_expr(cx, *exp, scope_stack, scope_map);
2521 fn walk_pattern(cx: &CrateContext,
2523 scope_stack: &mut Vec<ScopeStackEntry> ,
2524 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2526 let def_map = &cx.tcx.def_map;
2528 // Unfortunately, we cannot just use pat_util::pat_bindings() or ast_util::walk_pat() here
2529 // because we have to visit *all* nodes in order to put them into the scope map. The above
2530 // functions don't do that.
2532 ast::PatIdent(_, ref path_ref, ref sub_pat_opt) => {
2534 // Check if this is a binding. If so we need to put it on the scope stack and maybe
2535 // introduce an artificial scope
2536 if pat_util::pat_is_binding(def_map, pat) {
2538 let ident = ast_util::path_to_ident(path_ref);
2540 // LLVM does not properly generate 'DW_AT_start_scope' fields for variable DIEs.
2541 // For this reason we have to introduce an artificial scope at bindings whenever
2542 // a variable with the same name is declared in *any* parent scope.
2544 // Otherwise the following error occurs:
2548 // do_something(); // 'gdb print x' correctly prints 10
2551 // do_something(); // 'gdb print x' prints 0, because it already reads the
2552 // // uninitialized 'x' from the next line...
2554 // do_something(); // 'gdb print x' correctly prints 100
2557 // Is there already a binding with that name?
2558 // N.B.: this comparison must be UNhygienic... because
2559 // gdb knows nothing about the context, so any two
2560 // variables with the same name will cause the problem.
2561 let need_new_scope = scope_stack
2563 .any(|entry| entry.ident.iter().any(|i| i.name == ident.name));
2566 // Create a new lexical scope and push it onto the stack
2567 let loc = cx.sess().codemap().lookup_char_pos(pat.span.lo);
2568 let file_metadata = file_metadata(cx,
2572 let parent_scope = scope_stack.last().unwrap().scope_metadata;
2574 let scope_metadata = unsafe {
2575 llvm::LLVMDIBuilderCreateLexicalBlock(
2580 loc.col.to_uint() as c_uint,
2584 scope_stack.push(ScopeStackEntry {
2585 scope_metadata: scope_metadata,
2590 // Push a new entry anyway so the name can be found
2591 let prev_metadata = scope_stack.last().unwrap().scope_metadata;
2592 scope_stack.push(ScopeStackEntry {
2593 scope_metadata: prev_metadata,
2599 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2601 for &sub_pat in sub_pat_opt.iter() {
2602 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2606 ast::PatWild | ast::PatWildMulti => {
2607 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2610 ast::PatEnum(_, ref sub_pats_opt) => {
2611 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2613 for ref sub_pats in sub_pats_opt.iter() {
2614 for &p in sub_pats.iter() {
2615 walk_pattern(cx, p, scope_stack, scope_map);
2620 ast::PatStruct(_, ref field_pats, _) => {
2621 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2623 for &ast::FieldPat { pat: sub_pat, .. } in field_pats.iter() {
2624 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2628 ast::PatTup(ref sub_pats) => {
2629 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2631 for &sub_pat in sub_pats.iter() {
2632 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2636 ast::PatUniq(sub_pat) | ast::PatRegion(sub_pat) => {
2637 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2638 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2641 ast::PatLit(exp) => {
2642 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2643 walk_expr(cx, exp, scope_stack, scope_map);
2646 ast::PatRange(exp1, exp2) => {
2647 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2648 walk_expr(cx, exp1, scope_stack, scope_map);
2649 walk_expr(cx, exp2, scope_stack, scope_map);
2652 ast::PatVec(ref front_sub_pats, ref middle_sub_pats, ref back_sub_pats) => {
2653 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2655 for &sub_pat in front_sub_pats.iter() {
2656 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2659 for &sub_pat in middle_sub_pats.iter() {
2660 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2663 for &sub_pat in back_sub_pats.iter() {
2664 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2670 fn walk_expr(cx: &CrateContext,
2672 scope_stack: &mut Vec<ScopeStackEntry> ,
2673 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2675 scope_map.insert(exp.id, scope_stack.last().unwrap().scope_metadata);
2681 ast::ExprPath(_) => {}
2683 ast::ExprVstore(sub_exp, _) |
2684 ast::ExprCast(sub_exp, _) |
2685 ast::ExprAddrOf(_, sub_exp) |
2686 ast::ExprField(sub_exp, _, _) |
2687 ast::ExprParen(sub_exp) => walk_expr(cx, sub_exp, scope_stack, scope_map),
2689 ast::ExprBox(place, sub_expr) => {
2690 walk_expr(cx, place, scope_stack, scope_map);
2691 walk_expr(cx, sub_expr, scope_stack, scope_map);
2694 ast::ExprRet(exp_opt) => match exp_opt {
2695 Some(sub_exp) => walk_expr(cx, sub_exp, scope_stack, scope_map),
2699 ast::ExprUnary(_, sub_exp) => {
2700 walk_expr(cx, sub_exp, scope_stack, scope_map);
2703 ast::ExprAssignOp(_, lhs, rhs) |
2704 ast::ExprIndex(lhs, rhs) |
2705 ast::ExprBinary(_, lhs, rhs) => {
2706 walk_expr(cx, lhs, scope_stack, scope_map);
2707 walk_expr(cx, rhs, scope_stack, scope_map);
2710 ast::ExprVec(ref init_expressions) |
2711 ast::ExprTup(ref init_expressions) => {
2712 for ie in init_expressions.iter() {
2713 walk_expr(cx, *ie, scope_stack, scope_map);
2717 ast::ExprAssign(sub_exp1, sub_exp2) |
2718 ast::ExprRepeat(sub_exp1, sub_exp2) => {
2719 walk_expr(cx, sub_exp1, scope_stack, scope_map);
2720 walk_expr(cx, sub_exp2, scope_stack, scope_map);
2723 ast::ExprIf(cond_exp, then_block, ref opt_else_exp) => {
2724 walk_expr(cx, cond_exp, scope_stack, scope_map);
2730 |cx, scope_stack, scope_map| {
2731 walk_block(cx, then_block, scope_stack, scope_map);
2734 match *opt_else_exp {
2735 Some(else_exp) => walk_expr(cx, else_exp, scope_stack, scope_map),
2740 ast::ExprWhile(cond_exp, loop_body) => {
2741 walk_expr(cx, cond_exp, scope_stack, scope_map);
2747 |cx, scope_stack, scope_map| {
2748 walk_block(cx, loop_body, scope_stack, scope_map);
2752 ast::ExprForLoop(_, _, _, _) => {
2753 cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \
2754 Found unexpanded for-loop.");
2757 ast::ExprMac(_) => {
2758 cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \
2759 Found unexpanded macro.");
2762 ast::ExprLoop(block, _) |
2763 ast::ExprBlock(block) => {
2768 |cx, scope_stack, scope_map| {
2769 walk_block(cx, block, scope_stack, scope_map);
2773 ast::ExprFnBlock(decl, block) |
2774 ast::ExprProc(decl, block) => {
2779 |cx, scope_stack, scope_map| {
2780 for &ast::Arg { pat: pattern, .. } in decl.inputs.iter() {
2781 walk_pattern(cx, pattern, scope_stack, scope_map);
2784 walk_block(cx, block, scope_stack, scope_map);
2788 ast::ExprCall(fn_exp, ref args) => {
2789 walk_expr(cx, fn_exp, scope_stack, scope_map);
2791 for arg_exp in args.iter() {
2792 walk_expr(cx, *arg_exp, scope_stack, scope_map);
2796 ast::ExprMethodCall(_, _, ref args) => {
2797 for arg_exp in args.iter() {
2798 walk_expr(cx, *arg_exp, scope_stack, scope_map);
2802 ast::ExprMatch(discriminant_exp, ref arms) => {
2803 walk_expr(cx, discriminant_exp, scope_stack, scope_map);
2805 // for each arm we have to first walk the pattern as these might introduce new
2806 // artificial scopes. It should be sufficient to walk only one pattern per arm, as
2807 // they all must contain the same binding names
2809 for arm_ref in arms.iter() {
2810 let arm_span = arm_ref.pats.get(0).span;
2816 |cx, scope_stack, scope_map| {
2817 for &pat in arm_ref.pats.iter() {
2818 walk_pattern(cx, pat, scope_stack, scope_map);
2821 for guard_exp in arm_ref.guard.iter() {
2822 walk_expr(cx, *guard_exp, scope_stack, scope_map)
2825 walk_expr(cx, arm_ref.body, scope_stack, scope_map);
2830 ast::ExprStruct(_, ref fields, ref base_exp) => {
2831 for &ast::Field { expr: exp, .. } in fields.iter() {
2832 walk_expr(cx, exp, scope_stack, scope_map);
2836 Some(exp) => walk_expr(cx, exp, scope_stack, scope_map),
2841 ast::ExprInlineAsm(ast::InlineAsm { inputs: ref inputs,
2842 outputs: ref outputs,
2844 // inputs, outputs: ~[(String, @expr)]
2845 for &(_, exp) in inputs.iter() {
2846 walk_expr(cx, exp, scope_stack, scope_map);
2849 for &(_, exp) in outputs.iter() {
2850 walk_expr(cx, exp, scope_stack, scope_map);
2858 //=-------------------------------------------------------------------------------------------------
2859 // Namespace Handling
2860 //=-------------------------------------------------------------------------------------------------
2862 struct NamespaceTreeNode {
2865 parent: Option<Weak<NamespaceTreeNode>>,
2868 impl NamespaceTreeNode {
2869 fn mangled_name_of_contained_item(&self, item_name: &str) -> String {
2870 fn fill_nested(node: &NamespaceTreeNode, output: &mut String) {
2872 Some(ref parent) => fill_nested(&*parent.upgrade().unwrap(), output),
2875 let string = token::get_name(node.name);
2876 output.push_str(format!("{}", string.get().len()).as_slice());
2877 output.push_str(string.get());
2880 let mut name = String::from_str("_ZN");
2881 fill_nested(self, &mut name);
2882 name.push_str(format!("{}", item_name.len()).as_slice());
2883 name.push_str(item_name);
2884 name.push_char('E');
2889 fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTreeNode> {
2890 ty::with_path(cx.tcx(), def_id, |path| {
2891 // prepend crate name if not already present
2892 let krate = if def_id.krate == ast::LOCAL_CRATE {
2893 let crate_namespace_ident = token::str_to_ident(cx.link_meta
2897 Some(ast_map::PathMod(crate_namespace_ident.name))
2901 let mut path = krate.move_iter().chain(path).peekable();
2903 let mut current_key = Vec::new();
2904 let mut parent_node: Option<Rc<NamespaceTreeNode>> = None;
2906 // Create/Lookup namespace for each element of the path.
2908 // Emulate a for loop so we can use peek below.
2909 let path_element = match path.next() {
2913 // Ignore the name of the item (the last path element).
2914 if path.peek().is_none() {
2918 let name = path_element.name();
2919 current_key.push(name);
2921 let existing_node = debug_context(cx).namespace_map.borrow()
2922 .find_copy(¤t_key);
2923 let current_node = match existing_node {
2924 Some(existing_node) => existing_node,
2926 // create and insert
2927 let parent_scope = match parent_node {
2928 Some(ref node) => node.scope,
2931 let namespace_name = token::get_name(name);
2932 let scope = namespace_name.get().with_c_str(|namespace_name| {
2934 llvm::LLVMDIBuilderCreateNameSpace(
2938 // cannot reconstruct file ...
2940 // ... or line information, but that's not so important.
2945 let node = Rc::new(NamespaceTreeNode {
2948 parent: parent_node.map(|parent| parent.downgrade()),
2951 debug_context(cx).namespace_map.borrow_mut()
2952 .insert(current_key.clone(), node.clone());
2958 parent_node = Some(current_node);
2964 cx.sess().bug(format!("debuginfo::namespace_for_item(): \
2965 path too short for {:?}",
2966 def_id).as_slice());