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...
64 will generate the following callstack with a naive DFS algorithm:
69 describe(t = Option<@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::session::{FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
131 use lib::llvm::{ModuleRef, ContextRef, ValueRef};
132 use lib::llvm::debuginfo::*;
133 use middle::trans::adt;
134 use middle::trans::common::*;
135 use middle::trans::datum::{Datum, Lvalue};
136 use middle::trans::machine;
137 use middle::trans::type_of;
138 use middle::trans::type_::Type;
141 use middle::pat_util;
144 use std::c_str::{CString, ToCStr};
145 use std::cell::{Cell, RefCell};
146 use collections::HashMap;
147 use collections::HashSet;
148 use std::libc::{c_uint, c_ulonglong, c_longlong};
150 use std::sync::atomics;
152 use syntax::codemap::{Span, Pos};
153 use syntax::{abi, ast, codemap, ast_util, ast_map};
154 use syntax::owned_slice::OwnedSlice;
155 use syntax::parse::token;
156 use syntax::parse::token::special_idents;
158 static DW_LANG_RUST: c_uint = 0x9000;
160 static DW_TAG_auto_variable: c_uint = 0x100;
161 static DW_TAG_arg_variable: c_uint = 0x101;
163 static DW_ATE_boolean: c_uint = 0x02;
164 static DW_ATE_float: c_uint = 0x04;
165 static DW_ATE_signed: c_uint = 0x05;
166 // static DW_ATE_signed_char: c_uint = 0x06;
167 static DW_ATE_unsigned: c_uint = 0x07;
168 static DW_ATE_unsigned_char: c_uint = 0x08;
170 //=-------------------------------------------------------------------------------------------------
171 // Public Interface of debuginfo module
172 //=-------------------------------------------------------------------------------------------------
174 /// A context object for maintaining all state needed by the debuginfo module.
175 pub struct CrateDebugContext {
176 llcontext: ContextRef,
177 builder: DIBuilderRef,
178 current_debug_location: Cell<DebugLocation>,
179 created_files: RefCell<HashMap<~str, DIFile>>,
180 created_types: RefCell<HashMap<uint, DIType>>,
181 namespace_map: RefCell<HashMap<Vec<ast::Name> , @NamespaceTreeNode>>,
182 // This collection is used to assert that composite types (structs, enums, ...) have their
183 // members only set once:
184 composite_types_completed: RefCell<HashSet<DIType>>,
187 impl CrateDebugContext {
188 pub fn new(llmod: ModuleRef) -> CrateDebugContext {
189 debug!("CrateDebugContext::new");
190 let builder = unsafe { llvm::LLVMDIBuilderCreate(llmod) };
191 // DIBuilder inherits context from the module, so we'd better use the same one
192 let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
193 return CrateDebugContext {
194 llcontext: llcontext,
196 current_debug_location: Cell::new(UnknownLocation),
197 created_files: RefCell::new(HashMap::new()),
198 created_types: RefCell::new(HashMap::new()),
199 namespace_map: RefCell::new(HashMap::new()),
200 composite_types_completed: RefCell::new(HashSet::new()),
205 pub enum FunctionDebugContext {
206 priv FunctionDebugContext(~FunctionDebugContextData),
207 priv DebugInfoDisabled,
208 priv FunctionWithoutDebugInfo,
211 impl FunctionDebugContext {
212 fn get_ref<'a>(&'a self, cx: &CrateContext, span: Span) -> &'a FunctionDebugContextData {
214 FunctionDebugContext(~ref data) => data,
215 DebugInfoDisabled => {
216 cx.sess().span_bug(span, FunctionDebugContext::debuginfo_disabled_message());
218 FunctionWithoutDebugInfo => {
219 cx.sess().span_bug(span, FunctionDebugContext::should_be_ignored_message());
224 fn debuginfo_disabled_message() -> &'static str {
225 "debuginfo: Error trying to access FunctionDebugContext although debug info is disabled!"
228 fn should_be_ignored_message() -> &'static str {
229 "debuginfo: Error trying to access FunctionDebugContext for function that should be \
230 ignored by debug info!"
234 struct FunctionDebugContextData {
235 scope_map: RefCell<HashMap<ast::NodeId, DIScope>>,
236 fn_metadata: DISubprogram,
237 argument_counter: Cell<uint>,
238 source_locations_enabled: Cell<bool>,
241 enum VariableAccess<'a> {
242 // The llptr given is an alloca containing the variable's value
243 DirectVariable { alloca: ValueRef },
244 // The llptr given is an alloca containing the start of some pointer chain leading to the
245 // variable's content.
246 IndirectVariable { alloca: ValueRef, address_operations: &'a [ValueRef] }
250 ArgumentVariable(uint /*index*/),
255 /// Create any deferred debug metadata nodes
256 pub fn finalize(cx: &CrateContext) {
257 if cx.dbg_cx.is_none() {
262 compile_unit_metadata(cx);
264 llvm::LLVMDIBuilderFinalize(DIB(cx));
265 llvm::LLVMDIBuilderDispose(DIB(cx));
266 // Debuginfo generation in LLVM by default uses a higher
267 // version of dwarf than OS X currently understands. We can
268 // instruct LLVM to emit an older version of dwarf, however,
269 // for OS X to understand. For more info see #11352
270 // This can be overridden using --llvm-opts -dwarf-version,N.
271 if cx.sess().targ_cfg.os == abi::OsMacos {
272 "Dwarf Version".with_c_str(
273 |s| llvm::LLVMRustAddModuleFlag(cx.llmod, s, 2));
276 // Prevent bitcode readers from deleting the debug info.
277 "Debug Info Version".with_c_str(
278 |s| llvm::LLVMRustAddModuleFlag(cx.llmod, s,
279 llvm::LLVMRustDebugMetadataVersion));
283 /// Creates debug information for the given global variable.
285 /// Adds the created metadata nodes directly to the crate's IR.
286 pub fn create_global_var_metadata(cx: &CrateContext,
287 node_id: ast::NodeId,
289 if cx.dbg_cx.is_none() {
293 let var_item = cx.tcx.map.get(node_id);
295 let (ident, span) = match var_item {
296 ast_map::NodeItem(item) => {
298 ast::ItemStatic(..) => (item.ident, item.span),
299 _ => cx.sess().span_bug(item.span,
300 format!("debuginfo::create_global_var_metadata() -
301 Captured var-id refers to unexpected ast_item
306 _ => cx.sess().bug(format!("debuginfo::create_global_var_metadata() - Captured var-id \
307 refers to unexpected ast_map variant: {:?}",
311 let filename = span_start(cx, span).file.name.clone();
312 let file_metadata = file_metadata(cx, filename);
314 let is_local_to_unit = is_node_local_to_unit(cx, node_id);
315 let loc = span_start(cx, span);
317 let variable_type = ty::node_id_to_type(cx.tcx(), node_id);
318 let type_metadata = type_metadata(cx, variable_type, span);
320 let namespace_node = namespace_for_item(cx, ast_util::local_def(node_id));
321 let var_name = token::get_ident(ident).get().to_str();
322 let linkage_name = namespace_node.mangled_name_of_contained_item(var_name);
323 let var_scope = namespace_node.scope;
325 var_name.with_c_str(|var_name| {
326 linkage_name.with_c_str(|linkage_name| {
328 llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx),
343 /// Creates debug information for the given local variable.
345 /// Adds the created metadata nodes directly to the crate's IR.
346 pub fn create_local_var_metadata(bcx: &Block, local: &ast::Local) {
347 if fn_should_be_ignored(bcx.fcx) {
352 let def_map = cx.tcx.def_map;
354 pat_util::pat_bindings(def_map, local.pat, |_, node_id, span, path_ref| {
355 let var_ident = ast_util::path_to_ident(path_ref);
357 let datum = match bcx.fcx.lllocals.borrow().find_copy(&node_id) {
358 Some(datum) => datum,
360 bcx.sess().span_bug(span,
361 format!("no entry in lllocals table for {:?}",
366 let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
372 DirectVariable { alloca: datum.val },
378 /// Creates debug information for a variable captured in a closure.
380 /// Adds the created metadata nodes directly to the crate's IR.
381 pub fn create_captured_var_metadata(bcx: &Block,
382 node_id: ast::NodeId,
383 env_data_type: ty::t,
384 env_pointer: ValueRef,
386 closure_sigil: ast::Sigil,
388 if fn_should_be_ignored(bcx.fcx) {
394 let ast_item = cx.tcx.map.find(node_id);
396 let variable_ident = match ast_item {
398 cx.sess().span_bug(span, "debuginfo::create_captured_var_metadata: node not found");
400 Some(ast_map::NodeLocal(pat)) | Some(ast_map::NodeArg(pat)) => {
402 ast::PatIdent(_, ref path, _) => {
403 ast_util::path_to_ident(path)
409 "debuginfo::create_captured_var_metadata() - \
410 Captured var-id refers to unexpected \
411 ast_map variant: {:?}",
417 cx.sess().span_bug(span, format!("debuginfo::create_captured_var_metadata() - \
418 Captured var-id refers to unexpected ast_map variant: {:?}", ast_item));
422 let variable_type = node_id_type(bcx, node_id);
423 let scope_metadata = bcx.fcx.debug_context.get_ref(cx, span).fn_metadata;
425 let llvm_env_data_type = type_of::type_of(cx, env_data_type);
426 let byte_offset_of_var_in_env = machine::llelement_offset(cx, llvm_env_data_type, env_index);
428 let address_operations = unsafe {
429 [llvm::LLVMDIBuilderCreateOpDeref(Type::i64(cx).to_ref()),
430 llvm::LLVMDIBuilderCreateOpPlus(Type::i64(cx).to_ref()),
431 C_i64(cx, byte_offset_of_var_in_env as i64),
432 llvm::LLVMDIBuilderCreateOpDeref(Type::i64(cx).to_ref())]
435 let address_op_count = match closure_sigil {
436 ast::BorrowedSigil => {
437 address_operations.len()
439 ast::ManagedSigil | ast::OwnedSigil => {
440 address_operations.len() - 1
444 let variable_access = IndirectVariable {
446 address_operations: address_operations.slice_to(address_op_count)
458 /// Creates debug information for a local variable introduced in the head of a match-statement arm.
460 /// Adds the created metadata nodes directly to the crate's IR.
461 pub fn create_match_binding_metadata(bcx: &Block,
462 variable_ident: ast::Ident,
463 node_id: ast::NodeId,
465 datum: Datum<Lvalue>) {
466 if fn_should_be_ignored(bcx.fcx) {
470 let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
476 DirectVariable { alloca: datum.val },
481 /// Creates debug information for the given function argument.
483 /// Adds the created metadata nodes directly to the crate's IR.
484 pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
485 if fn_should_be_ignored(bcx.fcx) {
492 let def_map = cx.tcx.def_map;
493 let scope_metadata = bcx.fcx.debug_context.get_ref(cx, arg.pat.span).fn_metadata;
495 pat_util::pat_bindings(def_map, arg.pat, |_, node_id, span, path_ref| {
496 let llarg = match bcx.fcx.llargs.borrow().find_copy(&node_id) {
499 bcx.sess().span_bug(span,
500 format!("no entry in llargs table for {:?}",
505 if unsafe { llvm::LLVMIsAAllocaInst(llarg.val) } == ptr::null() {
506 cx.sess().span_bug(span, "debuginfo::create_argument_metadata() - \
507 Referenced variable location is not an alloca!");
510 let argument_ident = ast_util::path_to_ident(path_ref);
512 let argument_index = {
513 let counter = &fcx.debug_context.get_ref(cx, span).argument_counter;
514 let argument_index = counter.get();
515 counter.set(argument_index + 1);
523 DirectVariable { alloca: llarg.val },
524 ArgumentVariable(argument_index),
529 /// Sets the current debug location at the beginning of the span.
531 /// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...). The node_id parameter is used to
532 /// reliably find the correct visibility scope for the code position.
533 pub fn set_source_location(fcx: &FunctionContext,
534 node_id: ast::NodeId,
536 if fn_should_be_ignored(fcx) {
542 debug!("set_source_location: {}", cx.sess().codemap().span_to_str(span));
544 if fcx.debug_context.get_ref(cx, span).source_locations_enabled.get() {
545 let loc = span_start(cx, span);
546 let scope = scope_metadata(fcx, node_id, span);
548 set_debug_location(cx, DebugLocation::new(scope, loc.line, loc.col.to_uint()));
550 set_debug_location(cx, UnknownLocation);
554 /// Clears the current debug location.
556 /// Instructions generated hereafter won't be assigned a source location.
557 pub fn clear_source_location(fcx: &FunctionContext) {
558 if fn_should_be_ignored(fcx) {
562 set_debug_location(fcx.ccx, UnknownLocation);
565 /// Enables emitting source locations for the given functions.
567 /// Since we don't want source locations to be emitted for the function prelude, they are disabled
568 /// when beginning to translate a new function. This functions switches source location emitting on
569 /// and must therefore be called before the first real statement/expression of the function is
571 pub fn start_emitting_source_locations(fcx: &FunctionContext) {
572 match fcx.debug_context {
573 FunctionDebugContext(~ref data) => {
574 data.source_locations_enabled.set(true)
576 _ => { /* safe to ignore */ }
580 /// Creates the function-specific debug context.
582 /// Returns the FunctionDebugContext for the function which holds state needed for debug info
583 /// creation. The function may also return another variant of the FunctionDebugContext enum which
584 /// indicates why no debuginfo should be created for the function.
585 pub fn create_function_debug_context(cx: &CrateContext,
586 fn_ast_id: ast::NodeId,
587 param_substs: Option<@param_substs>,
588 llfn: ValueRef) -> FunctionDebugContext {
589 if cx.sess().opts.debuginfo == NoDebugInfo {
590 return DebugInfoDisabled;
594 return FunctionWithoutDebugInfo;
597 let empty_generics = ast::Generics { lifetimes: Vec::new(), ty_params: OwnedSlice::empty() };
599 let fnitem = cx.tcx.map.get(fn_ast_id);
601 let (ident, fn_decl, generics, top_level_block, span, has_path) = match fnitem {
602 ast_map::NodeItem(ref item) => {
604 ast::ItemFn(fn_decl, _, _, ref generics, top_level_block) => {
605 (item.ident, fn_decl, generics, top_level_block, item.span, true)
608 cx.sess().span_bug(item.span,
609 "create_function_debug_context: item bound to non-function");
613 ast_map::NodeMethod(method) => {
621 ast_map::NodeExpr(ref expr) => {
623 ast::ExprFnBlock(fn_decl, top_level_block) |
624 ast::ExprProc(fn_decl, top_level_block) => {
625 let name = format!("fn{}", token::gensym("fn"));
626 let name = token::str_to_ident(name);
628 // This is not quite right. It should actually inherit the generics of the
629 // enclosing function.
633 // Don't try to lookup the item path:
636 _ => cx.sess().span_bug(expr.span,
637 "create_function_debug_context: expected an expr_fn_block here")
640 ast_map::NodeTraitMethod(trait_method) => {
641 match *trait_method {
642 ast::Provided(method) => {
652 .bug(format!("create_function_debug_context: \
653 unexpected sort of node: {:?}",
658 ast_map::NodeForeignItem(..) |
659 ast_map::NodeVariant(..) |
660 ast_map::NodeStructCtor(..) => {
661 return FunctionWithoutDebugInfo;
663 _ => cx.sess().bug(format!("create_function_debug_context: \
664 unexpected sort of node: {:?}", fnitem))
667 // This can be the case for functions inlined from another crate
668 if span == codemap::DUMMY_SP {
669 return FunctionWithoutDebugInfo;
672 let loc = span_start(cx, span);
673 let file_metadata = file_metadata(cx, loc.file.name);
675 let function_type_metadata = unsafe {
676 let fn_signature = get_function_signature(cx, fn_ast_id, fn_decl, param_substs, span);
677 llvm::LLVMDIBuilderCreateSubroutineType(DIB(cx), file_metadata, fn_signature)
680 // get_template_parameters() will append a `<...>` clause to the function name if necessary.
681 let mut function_name = token::get_ident(ident).get().to_str();
682 let template_parameters = get_template_parameters(cx,
688 // There is no ast_map::Path for ast::ExprFnBlock-type functions. For now, just don't put them
689 // into a namespace. In the future this could be improved somehow (storing a path in the
690 // ast_map, or construct a path using the enclosing function).
691 let (linkage_name, containing_scope) = if has_path {
692 let namespace_node = namespace_for_item(cx, ast_util::local_def(fn_ast_id));
693 let linkage_name = namespace_node.mangled_name_of_contained_item(function_name);
694 let containing_scope = namespace_node.scope;
695 (linkage_name, containing_scope)
697 (function_name.clone(), file_metadata)
700 // Clang sets this parameter to the opening brace of the function's block, so let's do this too.
701 let scope_line = span_start(cx, top_level_block.span).line;
703 let is_local_to_unit = is_node_local_to_unit(cx, fn_ast_id);
705 let fn_metadata = function_name.with_c_str(|function_name| {
706 linkage_name.with_c_str(|linkage_name| {
708 llvm::LLVMDIBuilderCreateFunction(
715 function_type_metadata,
718 scope_line as c_uint,
719 FlagPrototyped as c_uint,
720 cx.sess().opts.optimize != session::No,
728 // Initialize fn debug context (including scope map and namespace map)
729 let fn_debug_context = ~FunctionDebugContextData {
730 scope_map: RefCell::new(HashMap::new()),
731 fn_metadata: fn_metadata,
732 argument_counter: Cell::new(1),
733 source_locations_enabled: Cell::new(false),
736 let arg_pats = fn_decl.inputs.iter().map(|arg_ref| arg_ref.pat).collect::<Vec<_>>();
737 populate_scope_map(cx,
741 &mut *fn_debug_context.scope_map.borrow_mut());
743 // Clear the debug location so we don't assign them in the function prelude
744 set_debug_location(cx, UnknownLocation);
746 return FunctionDebugContext(fn_debug_context);
748 fn get_function_signature(cx: &CrateContext,
749 fn_ast_id: ast::NodeId,
750 fn_decl: &ast::FnDecl,
751 param_substs: Option<@param_substs>,
752 error_span: Span) -> DIArray {
753 if cx.sess().opts.debuginfo == LimitedDebugInfo {
754 return create_DIArray(DIB(cx), []);
757 let mut signature = slice::with_capacity(fn_decl.inputs.len() + 1);
759 // Return type -- llvm::DIBuilder wants this at index 0
760 match fn_decl.output.node {
762 signature.push(ptr::null());
765 assert_type_for_node_id(cx, fn_ast_id, error_span);
767 let return_type = ty::node_id_to_type(cx.tcx(), fn_ast_id);
768 let return_type = match param_substs {
771 ty::subst_tps(cx.tcx(),
772 substs.tys.as_slice(),
778 signature.push(type_metadata(cx, return_type, codemap::DUMMY_SP));
783 for arg in fn_decl.inputs.iter() {
784 assert_type_for_node_id(cx, arg.pat.id, arg.pat.span);
785 let arg_type = ty::node_id_to_type(cx.tcx(), arg.pat.id);
786 let arg_type = match param_substs {
789 ty::subst_tps(cx.tcx(),
790 substs.tys.as_slice(),
796 signature.push(type_metadata(cx, arg_type, codemap::DUMMY_SP));
799 return create_DIArray(DIB(cx), signature);
802 fn get_template_parameters(cx: &CrateContext,
803 generics: &ast::Generics,
804 param_substs: Option<@param_substs>,
805 file_metadata: DIFile,
806 name_to_append_suffix_to: &mut ~str)
808 let self_type = match param_substs {
809 Some(param_substs) => param_substs.self_ty,
813 // Only true for static default methods:
814 let has_self_type = self_type.is_some();
816 if !generics.is_type_parameterized() && !has_self_type {
817 return create_DIArray(DIB(cx), []);
820 name_to_append_suffix_to.push_char('<');
822 // The list to be filled with template parameters:
823 let mut template_params: Vec<DIDescriptor> =
824 Vec::with_capacity(generics.ty_params.len() + 1);
828 let actual_self_type = self_type.unwrap();
829 // Add self type name to <...> clause of function name
830 let actual_self_type_name = ppaux::ty_to_str(cx.tcx(), actual_self_type);
831 name_to_append_suffix_to.push_str(actual_self_type_name);
833 if generics.is_type_parameterized() {
834 name_to_append_suffix_to.push_str(",");
837 // Only create type information if full debuginfo is enabled
838 if cx.sess().opts.debuginfo == FullDebugInfo {
839 let actual_self_type_metadata = type_metadata(cx,
843 let ident = special_idents::type_self;
845 let param_metadata = token::get_ident(ident).get()
848 llvm::LLVMDIBuilderCreateTemplateTypeParameter(
852 actual_self_type_metadata,
859 template_params.push(param_metadata);
863 // Handle other generic parameters
864 let actual_types = match param_substs {
865 Some(param_substs) => ¶m_substs.tys,
867 return create_DIArray(DIB(cx), template_params.as_slice());
871 for (index, &ast::TyParam{ ident: ident, .. }) in generics.ty_params.iter().enumerate() {
872 let actual_type = *actual_types.get(index);
873 // Add actual type name to <...> clause of function name
874 let actual_type_name = ppaux::ty_to_str(cx.tcx(), actual_type);
875 name_to_append_suffix_to.push_str(actual_type_name);
877 if index != generics.ty_params.len() - 1 {
878 name_to_append_suffix_to.push_str(",");
881 // Again, only create type information if full debuginfo is enabled
882 if cx.sess().opts.debuginfo == FullDebugInfo {
883 let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP);
884 let param_metadata = token::get_ident(ident).get()
887 llvm::LLVMDIBuilderCreateTemplateTypeParameter(
891 actual_type_metadata,
897 template_params.push(param_metadata);
901 name_to_append_suffix_to.push_char('>');
903 return create_DIArray(DIB(cx), template_params.as_slice());
907 //=-------------------------------------------------------------------------------------------------
908 // Module-Internal debug info creation functions
909 //=-------------------------------------------------------------------------------------------------
911 fn is_node_local_to_unit(cx: &CrateContext, node_id: ast::NodeId) -> bool
913 // The is_local_to_unit flag indicates whether a function is local to the current compilation
914 // unit (i.e. if it is *static* in the C-sense). The *reachable* set should provide a good
915 // approximation of this, as it contains everything that might leak out of the current crate
916 // (by being externally visible or by being inlined into something externally visible). It might
917 // better to use the `exported_items` set from `driver::CrateAnalysis` in the future, but (atm)
918 // this set is not available in the translation pass.
919 !cx.reachable.contains(&node_id)
922 fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
924 llvm::LLVMDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32)
928 fn compile_unit_metadata(cx: &CrateContext) {
929 let work_dir = &cx.sess().working_dir;
930 let compile_unit_name = match cx.sess().local_crate_source_file {
931 None => fallback_path(cx),
932 Some(ref abs_path) => {
933 if abs_path.is_relative() {
934 cx.sess().warn("debuginfo: Invalid path to crate's local root source file!");
937 match abs_path.path_relative_from(work_dir) {
938 Some(ref p) if p.is_relative() => {
939 // prepend "./" if necessary
940 let dotdot = bytes!("..");
941 let prefix = &[dotdot[0], ::std::path::SEP_BYTE];
942 let mut path_bytes = p.as_vec().to_owned();
944 if path_bytes.slice_to(2) != prefix &&
945 path_bytes.slice_to(2) != dotdot {
946 path_bytes.insert(0, prefix[0]);
947 path_bytes.insert(1, prefix[1]);
950 path_bytes.to_c_str()
952 _ => fallback_path(cx)
958 debug!("compile_unit_metadata: {:?}", compile_unit_name);
959 let producer = format!("rustc version {}", env!("CFG_VERSION"));
961 compile_unit_name.with_ref(|compile_unit_name| {
962 work_dir.as_vec().with_c_str(|work_dir| {
963 producer.with_c_str(|producer| {
964 "".with_c_str(|flags| {
965 "".with_c_str(|split_name| {
967 llvm::LLVMDIBuilderCreateCompileUnit(
968 debug_context(cx).builder,
973 cx.sess().opts.optimize != session::No,
984 fn fallback_path(cx: &CrateContext) -> CString {
985 cx.link_meta.crateid.name.to_c_str()
989 fn declare_local(bcx: &Block,
990 variable_ident: ast::Ident,
991 variable_type: ty::t,
992 scope_metadata: DIScope,
993 variable_access: VariableAccess,
994 variable_kind: VariableKind,
996 let cx: &CrateContext = bcx.ccx();
998 let filename = span_start(cx, span).file.name.clone();
999 let file_metadata = file_metadata(cx, filename);
1001 let name = token::get_ident(variable_ident);
1002 let loc = span_start(cx, span);
1003 let type_metadata = type_metadata(cx, variable_type, span);
1005 let (argument_index, dwarf_tag) = match variable_kind {
1006 ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),
1008 CapturedVariable => (0, DW_TAG_auto_variable)
1011 let (var_alloca, var_metadata) = name.get().with_c_str(|name| {
1012 match variable_access {
1013 DirectVariable { alloca } => (
1016 llvm::LLVMDIBuilderCreateLocalVariable(
1024 cx.sess().opts.optimize != session::No,
1029 IndirectVariable { alloca, address_operations } => (
1032 llvm::LLVMDIBuilderCreateComplexVariable(
1040 address_operations.as_ptr(),
1041 address_operations.len() as c_uint,
1048 set_debug_location(cx, DebugLocation::new(scope_metadata, loc.line, loc.col.to_uint()));
1050 let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
1056 llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr);
1059 match variable_kind {
1060 ArgumentVariable(_) | CapturedVariable => {
1064 .source_locations_enabled
1066 set_debug_location(cx, UnknownLocation);
1068 _ => { /* nothing to do */ }
1072 fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
1073 match debug_context(cx).created_files.borrow().find_equiv(&full_path) {
1074 Some(file_metadata) => return *file_metadata,
1078 debug!("file_metadata: {}", full_path);
1080 // FIXME (#9639): This needs to handle non-utf8 paths
1081 let work_dir = cx.sess().working_dir.as_str().unwrap();
1083 if full_path.starts_with(work_dir) {
1084 full_path.slice(work_dir.len() + 1u, full_path.len())
1090 file_name.with_c_str(|file_name| {
1091 work_dir.with_c_str(|work_dir| {
1093 llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir)
1098 let mut created_files = debug_context(cx).created_files.borrow_mut();
1099 created_files.insert(full_path.to_owned(), file_metadata);
1100 return file_metadata;
1103 /// Finds the scope metadata node for the given AST node.
1104 fn scope_metadata(fcx: &FunctionContext,
1105 node_id: ast::NodeId,
1108 let scope_map = &fcx.debug_context.get_ref(fcx.ccx, span).scope_map;
1109 match scope_map.borrow().find_copy(&node_id) {
1110 Some(scope_metadata) => scope_metadata,
1112 let node = fcx.ccx.tcx.map.get(node_id);
1114 fcx.ccx.sess().span_bug(span,
1115 format!("debuginfo: Could not find scope info for node {:?}", node));
1120 fn basic_type_metadata(cx: &CrateContext, t: ty::t) -> DIType {
1122 debug!("basic_type_metadata: {:?}", ty::get(t));
1124 let (name, encoding) = match ty::get(t).sty {
1125 ty::ty_nil => (~"()", DW_ATE_unsigned),
1126 ty::ty_bot => (~"!", DW_ATE_unsigned),
1127 ty::ty_bool => (~"bool", DW_ATE_boolean),
1128 ty::ty_char => (~"char", DW_ATE_unsigned_char),
1129 ty::ty_int(int_ty) => match int_ty {
1130 ast::TyI => (~"int", DW_ATE_signed),
1131 ast::TyI8 => (~"i8", DW_ATE_signed),
1132 ast::TyI16 => (~"i16", DW_ATE_signed),
1133 ast::TyI32 => (~"i32", DW_ATE_signed),
1134 ast::TyI64 => (~"i64", DW_ATE_signed)
1136 ty::ty_uint(uint_ty) => match uint_ty {
1137 ast::TyU => (~"uint", DW_ATE_unsigned),
1138 ast::TyU8 => (~"u8", DW_ATE_unsigned),
1139 ast::TyU16 => (~"u16", DW_ATE_unsigned),
1140 ast::TyU32 => (~"u32", DW_ATE_unsigned),
1141 ast::TyU64 => (~"u64", DW_ATE_unsigned)
1143 ty::ty_float(float_ty) => match float_ty {
1144 ast::TyF32 => (~"f32", DW_ATE_float),
1145 ast::TyF64 => (~"f64", DW_ATE_float)
1147 _ => cx.sess().bug("debuginfo::basic_type_metadata - t is invalid type")
1150 let llvm_type = type_of::type_of(cx, t);
1151 let (size, align) = size_and_align_of(cx, llvm_type);
1152 let ty_metadata = name.with_c_str(|name| {
1154 llvm::LLVMDIBuilderCreateBasicType(
1157 bytes_to_bits(size),
1158 bytes_to_bits(align),
1166 fn pointer_type_metadata(cx: &CrateContext,
1167 pointer_type: ty::t,
1168 pointee_type_metadata: DIType)
1170 let pointer_llvm_type = type_of::type_of(cx, pointer_type);
1171 let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
1172 let name = ppaux::ty_to_str(cx.tcx(), pointer_type);
1173 let ptr_metadata = name.with_c_str(|name| {
1175 llvm::LLVMDIBuilderCreatePointerType(
1177 pointee_type_metadata,
1178 bytes_to_bits(pointer_size),
1179 bytes_to_bits(pointer_align),
1183 return ptr_metadata;
1186 enum MemberDescriptionFactory {
1187 StructMD(StructMemberDescriptionFactory),
1188 TupleMD(TupleMemberDescriptionFactory),
1189 GeneralMD(GeneralMemberDescriptionFactory),
1190 EnumVariantMD(EnumVariantMemberDescriptionFactory)
1193 impl MemberDescriptionFactory {
1194 fn create_member_descriptions(&self, cx: &CrateContext)
1195 -> Vec<MemberDescription> {
1197 StructMD(ref this) => {
1198 this.create_member_descriptions(cx)
1200 TupleMD(ref this) => {
1201 this.create_member_descriptions(cx)
1203 GeneralMD(ref this) => {
1204 this.create_member_descriptions(cx)
1206 EnumVariantMD(ref this) => {
1207 this.create_member_descriptions(cx)
1213 struct StructMemberDescriptionFactory {
1214 fields: Vec<ty::field> ,
1218 impl StructMemberDescriptionFactory {
1219 fn create_member_descriptions(&self, cx: &CrateContext)
1220 -> Vec<MemberDescription> {
1221 self.fields.iter().map(|field| {
1222 let name = if field.ident.name == special_idents::unnamed_field.name {
1225 token::get_ident(field.ident).get().to_str()
1230 llvm_type: type_of::type_of(cx, field.mt.ty),
1231 type_metadata: type_metadata(cx, field.mt.ty, self.span),
1232 offset: ComputedMemberOffset,
1238 fn prepare_struct_metadata(cx: &CrateContext,
1241 substs: &ty::substs,
1243 -> RecursiveTypeDescription {
1244 let struct_name = ppaux::ty_to_str(cx.tcx(), struct_type);
1245 let struct_llvm_type = type_of::type_of(cx, struct_type);
1247 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id);
1249 let file_name = span_start(cx, definition_span).file.name.clone();
1250 let file_metadata = file_metadata(cx, file_name);
1252 let struct_metadata_stub = create_struct_stub(cx,
1259 let fields = ty::struct_fields(cx.tcx(), def_id, substs);
1261 UnfinishedMetadata {
1262 cache_id: cache_id_for_type(struct_type),
1263 metadata_stub: struct_metadata_stub,
1264 llvm_type: struct_llvm_type,
1265 file_metadata: file_metadata,
1266 member_description_factory: StructMD(StructMemberDescriptionFactory {
1273 enum RecursiveTypeDescription {
1274 UnfinishedMetadata {
1276 metadata_stub: DICompositeType,
1278 file_metadata: DIFile,
1279 member_description_factory: MemberDescriptionFactory,
1281 FinalMetadata(DICompositeType)
1284 impl RecursiveTypeDescription {
1286 fn finalize(&self, cx: &CrateContext) -> DICompositeType {
1288 FinalMetadata(metadata) => metadata,
1289 UnfinishedMetadata {
1294 ref member_description_factory
1296 // Insert the stub into the cache in order to allow recursive references ...
1297 debug_context(cx).created_types.borrow_mut()
1298 .insert(cache_id, metadata_stub);
1300 // ... then create the member descriptions ...
1301 let member_descriptions = member_description_factory.create_member_descriptions(cx);
1303 // ... and attach them to the stub to complete it.
1304 set_members_of_composite_type(cx,
1307 member_descriptions.as_slice(),
1310 return metadata_stub;
1316 struct TupleMemberDescriptionFactory {
1317 component_types: Vec<ty::t> ,
1321 impl TupleMemberDescriptionFactory {
1322 fn create_member_descriptions(&self, cx: &CrateContext)
1323 -> Vec<MemberDescription> {
1324 self.component_types.iter().map(|&component_type| {
1327 llvm_type: type_of::type_of(cx, component_type),
1328 type_metadata: type_metadata(cx, component_type, self.span),
1329 offset: ComputedMemberOffset,
1335 fn prepare_tuple_metadata(cx: &CrateContext,
1337 component_types: &[ty::t],
1339 -> RecursiveTypeDescription {
1340 let tuple_name = ppaux::ty_to_str(cx.tcx(), tuple_type);
1341 let tuple_llvm_type = type_of::type_of(cx, tuple_type);
1343 let loc = span_start(cx, span);
1344 let file_metadata = file_metadata(cx, loc.file.name);
1346 UnfinishedMetadata {
1347 cache_id: cache_id_for_type(tuple_type),
1348 metadata_stub: create_struct_stub(cx,
1354 llvm_type: tuple_llvm_type,
1355 file_metadata: file_metadata,
1356 member_description_factory: TupleMD(TupleMemberDescriptionFactory {
1357 component_types: Vec::from_slice(component_types),
1363 struct GeneralMemberDescriptionFactory {
1364 type_rep: @adt::Repr,
1365 variants: @Vec<@ty::VariantInfo> ,
1366 discriminant_type_metadata: ValueRef,
1367 containing_scope: DIScope,
1368 file_metadata: DIFile,
1372 impl GeneralMemberDescriptionFactory {
1373 fn create_member_descriptions(&self, cx: &CrateContext)
1374 -> Vec<MemberDescription> {
1375 // Capture type_rep, so we don't have to copy the struct_defs array
1376 let struct_defs = match *self.type_rep {
1377 adt::General(_, ref struct_defs) => struct_defs,
1378 _ => cx.sess().bug("unreachable")
1384 .map(|(i, struct_def)| {
1385 let (variant_type_metadata, variant_llvm_type, member_desc_factory) =
1386 describe_enum_variant(cx,
1388 *self.variants.get(i),
1389 Some(self.discriminant_type_metadata),
1390 self.containing_scope,
1394 let member_descriptions =
1395 member_desc_factory.create_member_descriptions(cx);
1397 set_members_of_composite_type(cx,
1398 variant_type_metadata,
1400 member_descriptions.as_slice(),
1405 llvm_type: variant_llvm_type,
1406 type_metadata: variant_type_metadata,
1407 offset: FixedMemberOffset { bytes: 0 },
1413 struct EnumVariantMemberDescriptionFactory {
1414 args: Vec<(~str, ty::t)> ,
1415 discriminant_type_metadata: Option<DIType>,
1419 impl EnumVariantMemberDescriptionFactory {
1420 fn create_member_descriptions(&self, cx: &CrateContext)
1421 -> Vec<MemberDescription> {
1422 self.args.iter().enumerate().map(|(i, &(ref name, ty))| {
1424 name: name.to_str(),
1425 llvm_type: type_of::type_of(cx, ty),
1426 type_metadata: match self.discriminant_type_metadata {
1427 Some(metadata) if i == 0 => metadata,
1428 _ => type_metadata(cx, ty, self.span)
1430 offset: ComputedMemberOffset,
1436 fn describe_enum_variant(cx: &CrateContext,
1437 struct_def: &adt::Struct,
1438 variant_info: &ty::VariantInfo,
1439 discriminant_type_metadata: Option<DIType>,
1440 containing_scope: DIScope,
1441 file_metadata: DIFile,
1443 -> (DICompositeType, Type, MemberDescriptionFactory) {
1444 let variant_llvm_type =
1445 Type::struct_(cx, struct_def.fields
1447 .map(|&t| type_of::type_of(cx, t))
1448 .collect::<Vec<_>>()
1451 // Could some consistency checks here: size, align, field count, discr type
1453 // Find the source code location of the variant's definition
1454 let variant_definition_span = if variant_info.id.krate == ast::LOCAL_CRATE {
1455 cx.tcx.map.span(variant_info.id.node)
1457 // For definitions from other crates we have no location information available.
1461 let metadata_stub = create_struct_stub(cx,
1463 token::get_ident(variant_info.name).get(),
1466 variant_definition_span);
1468 // Get the argument names from the enum variant info
1469 let mut arg_names: Vec<_> = match variant_info.arg_names {
1470 Some(ref names) => {
1471 names.iter().map(|ident| token::get_ident(*ident).get().to_str()).collect()
1473 None => variant_info.args.iter().map(|_| ~"").collect()
1476 // If this is not a univariant enum, there is also the (unnamed) discriminant field
1477 if discriminant_type_metadata.is_some() {
1478 arg_names.insert(0, ~"");
1481 // Build an array of (field name, field type) pairs to be captured in the factory closure.
1482 let args: Vec<(~str, ty::t)> = arg_names.iter()
1483 .zip(struct_def.fields.iter())
1484 .map(|(s, &t)| (s.to_str(), t))
1487 let member_description_factory =
1488 EnumVariantMD(EnumVariantMemberDescriptionFactory {
1490 discriminant_type_metadata: discriminant_type_metadata,
1494 (metadata_stub, variant_llvm_type, member_description_factory)
1497 fn prepare_enum_metadata(cx: &CrateContext,
1499 enum_def_id: ast::DefId,
1501 -> RecursiveTypeDescription {
1502 let enum_name = ppaux::ty_to_str(cx.tcx(), enum_type);
1504 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, enum_def_id);
1505 let loc = span_start(cx, definition_span);
1506 let file_metadata = file_metadata(cx, loc.file.name);
1508 // For empty enums there is an early exit. Just describe it as an empty struct with the
1509 // appropriate type name
1510 if ty::type_is_empty(cx.tcx(), enum_type) {
1511 let empty_type_metadata = composite_type_metadata(cx,
1519 return FinalMetadata(empty_type_metadata);
1522 let variants = ty::enum_variants(cx.tcx(), enum_def_id);
1524 let enumerators_metadata: Vec<DIDescriptor> = variants
1527 token::get_ident(v.name).get().with_c_str(|name| {
1529 llvm::LLVMDIBuilderCreateEnumerator(
1532 v.disr_val as c_ulonglong)
1538 let discriminant_type_metadata = |inttype| {
1539 let discriminant_llvm_type = adt::ll_inttype(cx, inttype);
1540 let (discriminant_size, discriminant_align) = size_and_align_of(cx, discriminant_llvm_type);
1541 let discriminant_base_type_metadata = type_metadata(cx, adt::ty_of_inttype(inttype),
1543 enum_name.with_c_str(|enum_name| {
1545 llvm::LLVMDIBuilderCreateEnumerationType(
1551 bytes_to_bits(discriminant_size),
1552 bytes_to_bits(discriminant_align),
1553 create_DIArray(DIB(cx), enumerators_metadata.as_slice()),
1554 discriminant_base_type_metadata)
1559 let type_rep = adt::represent_type(cx, enum_type);
1561 return match *type_rep {
1562 adt::CEnum(inttype, _, _) => {
1563 FinalMetadata(discriminant_type_metadata(inttype))
1565 adt::Univariant(ref struct_def, _) => {
1566 assert!(variants.len() == 1);
1569 member_description_factory) =
1570 describe_enum_variant(cx,
1577 UnfinishedMetadata {
1578 cache_id: cache_id_for_type(enum_type),
1579 metadata_stub: metadata_stub,
1580 llvm_type: variant_llvm_type,
1581 file_metadata: file_metadata,
1582 member_description_factory: member_description_factory
1585 adt::General(inttype, _) => {
1586 let discriminant_type_metadata = discriminant_type_metadata(inttype);
1587 let enum_llvm_type = type_of::type_of(cx, enum_type);
1588 let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type);
1589 let unique_id = generate_unique_type_id("DI_ENUM_");
1591 let enum_metadata = enum_name.with_c_str(|enum_name| {
1592 unique_id.with_c_str(|unique_id| {
1594 llvm::LLVMDIBuilderCreateUnionType(
1600 bytes_to_bits(enum_type_size),
1601 bytes_to_bits(enum_type_align),
1610 UnfinishedMetadata {
1611 cache_id: cache_id_for_type(enum_type),
1612 metadata_stub: enum_metadata,
1613 llvm_type: enum_llvm_type,
1614 file_metadata: file_metadata,
1615 member_description_factory: GeneralMD(GeneralMemberDescriptionFactory {
1618 discriminant_type_metadata: discriminant_type_metadata,
1619 containing_scope: containing_scope,
1620 file_metadata: file_metadata,
1625 adt::NullablePointer { nonnull: ref struct_def, nndiscr, .. } => {
1628 member_description_factory) =
1629 describe_enum_variant(cx,
1631 *variants.get(nndiscr as uint),
1636 UnfinishedMetadata {
1637 cache_id: cache_id_for_type(enum_type),
1638 metadata_stub: metadata_stub,
1639 llvm_type: variant_llvm_type,
1640 file_metadata: file_metadata,
1641 member_description_factory: member_description_factory
1648 FixedMemberOffset { bytes: uint },
1649 // For ComputedMemberOffset, the offset is read from the llvm type definition
1650 ComputedMemberOffset
1653 struct MemberDescription {
1656 type_metadata: DIType,
1657 offset: MemberOffset,
1660 /// Creates debug information for a composite type, that is, anything that results in a LLVM struct.
1662 /// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums.
1663 fn composite_type_metadata(cx: &CrateContext,
1664 composite_llvm_type: Type,
1665 composite_type_name: &str,
1666 member_descriptions: &[MemberDescription],
1667 containing_scope: DIScope,
1668 file_metadata: DIFile,
1669 definition_span: Span)
1670 -> DICompositeType {
1671 // Create the (empty) struct metadata node ...
1672 let composite_type_metadata = create_struct_stub(cx,
1673 composite_llvm_type,
1674 composite_type_name,
1679 // ... and immediately create and add the member descriptions.
1680 set_members_of_composite_type(cx,
1681 composite_type_metadata,
1682 composite_llvm_type,
1683 member_descriptions,
1687 return composite_type_metadata;
1690 fn set_members_of_composite_type(cx: &CrateContext,
1691 composite_type_metadata: DICompositeType,
1692 composite_llvm_type: Type,
1693 member_descriptions: &[MemberDescription],
1694 file_metadata: DIFile,
1695 definition_span: Span) {
1696 // In some rare cases LLVM metadata uniquing would lead to an existing type description being
1697 // used instead of a new one created in create_struct_stub. This would cause a hard to trace
1698 // assertion in DICompositeType::SetTypeArray(). The following check makes sure that we get a
1699 // better error message if this should happen again due to some regression.
1701 let mut composite_types_completed =
1702 debug_context(cx).composite_types_completed.borrow_mut();
1703 if composite_types_completed.contains(&composite_type_metadata) {
1704 cx.sess().span_bug(definition_span, "debuginfo::set_members_of_composite_type() - \
1705 Already completed forward declaration \
1708 composite_types_completed.insert(composite_type_metadata);
1712 let loc = span_start(cx, definition_span);
1714 let member_metadata: Vec<DIDescriptor> = member_descriptions
1717 .map(|(i, member_description)| {
1718 let (member_size, member_align) = size_and_align_of(cx, member_description.llvm_type);
1719 let member_offset = match member_description.offset {
1720 FixedMemberOffset { bytes } => bytes as u64,
1721 ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i)
1724 member_description.name.with_c_str(|member_name| {
1726 llvm::LLVMDIBuilderCreateMemberType(
1728 composite_type_metadata,
1732 bytes_to_bits(member_size),
1733 bytes_to_bits(member_align),
1734 bytes_to_bits(member_offset),
1736 member_description.type_metadata)
1743 let type_array = create_DIArray(DIB(cx), member_metadata.as_slice());
1744 llvm::LLVMDICompositeTypeSetTypeArray(composite_type_metadata, type_array);
1748 // A convenience wrapper around LLVMDIBuilderCreateStructType(). Does not do any caching, does not
1749 // add any fields to the struct. This can be done later with set_members_of_composite_type().
1750 fn create_struct_stub(cx: &CrateContext,
1751 struct_llvm_type: Type,
1752 struct_type_name: &str,
1753 containing_scope: DIScope,
1754 file_metadata: DIFile,
1755 definition_span: Span)
1756 -> DICompositeType {
1757 let loc = span_start(cx, definition_span);
1758 let (struct_size, struct_align) = size_and_align_of(cx, struct_llvm_type);
1760 // We assign unique IDs to the type stubs so LLVM metadata uniquing does not reuse instances
1761 // where we don't want it.
1762 let unique_id = generate_unique_type_id("DI_STRUCT_");
1765 struct_type_name.with_c_str(|name| {
1766 unique_id.with_c_str(|unique_id| {
1767 // LLVMDIBuilderCreateStructType() wants an empty array. A null pointer will lead to
1768 // hard to trace and debug LLVM assertions later on in llvm/lib/IR/Value.cpp
1769 let empty_array = create_DIArray(DIB(cx), []);
1771 llvm::LLVMDIBuilderCreateStructType(
1777 bytes_to_bits(struct_size),
1778 bytes_to_bits(struct_align),
1790 fn boxed_type_metadata(cx: &CrateContext,
1791 content_type_name: Option<&str>,
1792 content_llvm_type: Type,
1793 content_type_metadata: DIType,
1795 -> DICompositeType {
1796 let box_type_name = match content_type_name {
1797 Some(content_type_name) => format!("Boxed<{}>", content_type_name),
1798 None => ~"BoxedType"
1801 let box_llvm_type = Type::at_box(cx, content_llvm_type);
1802 let member_llvm_types = box_llvm_type.field_types();
1803 assert!(box_layout_is_correct(cx,
1804 member_llvm_types.as_slice(),
1805 content_llvm_type));
1807 let int_type = ty::mk_int();
1808 let nil_pointer_type = ty::mk_nil_ptr(cx.tcx());
1809 let nil_pointer_type_metadata = type_metadata(cx, nil_pointer_type, codemap::DUMMY_SP);
1811 let member_descriptions = [
1814 llvm_type: *member_llvm_types.get(0),
1815 type_metadata: type_metadata(cx, int_type, codemap::DUMMY_SP),
1816 offset: ComputedMemberOffset,
1820 llvm_type: *member_llvm_types.get(1),
1821 type_metadata: nil_pointer_type_metadata,
1822 offset: ComputedMemberOffset,
1826 llvm_type: *member_llvm_types.get(2),
1827 type_metadata: nil_pointer_type_metadata,
1828 offset: ComputedMemberOffset,
1832 llvm_type: *member_llvm_types.get(3),
1833 type_metadata: nil_pointer_type_metadata,
1834 offset: ComputedMemberOffset,
1838 llvm_type: *member_llvm_types.get(4),
1839 type_metadata: content_type_metadata,
1840 offset: ComputedMemberOffset,
1844 let loc = span_start(cx, span);
1845 let file_metadata = file_metadata(cx, loc.file.name);
1847 return composite_type_metadata(
1851 member_descriptions,
1856 // Unfortunately, we cannot assert anything but the correct types here---and not whether the
1857 // 'next' and 'prev' pointers are in the correct order.
1858 fn box_layout_is_correct(cx: &CrateContext,
1859 member_llvm_types: &[Type],
1860 content_llvm_type: Type)
1862 member_llvm_types.len() == 5 &&
1863 member_llvm_types[0] == cx.int_type &&
1864 member_llvm_types[1] == Type::generic_glue_fn(cx).ptr_to() &&
1865 member_llvm_types[2] == Type::i8(cx).ptr_to() &&
1866 member_llvm_types[3] == Type::i8(cx).ptr_to() &&
1867 member_llvm_types[4] == content_llvm_type
1871 fn fixed_vec_metadata(cx: &CrateContext,
1872 element_type: ty::t,
1876 let element_type_metadata = type_metadata(cx, element_type, span);
1877 let element_llvm_type = type_of::type_of(cx, element_type);
1878 let (element_type_size, element_type_align) = size_and_align_of(cx, element_llvm_type);
1880 let subrange = unsafe {
1881 llvm::LLVMDIBuilderGetOrCreateSubrange(
1887 let subscripts = create_DIArray(DIB(cx), [subrange]);
1889 llvm::LLVMDIBuilderCreateArrayType(
1891 bytes_to_bits(element_type_size * (len as u64)),
1892 bytes_to_bits(element_type_align),
1893 element_type_metadata,
1898 fn vec_metadata(cx: &CrateContext,
1899 element_type: ty::t,
1901 -> DICompositeType {
1903 let element_type_metadata = type_metadata(cx, element_type, span);
1904 let element_llvm_type = type_of::type_of(cx, element_type);
1905 let (element_size, element_align) = size_and_align_of(cx, element_llvm_type);
1907 let vec_llvm_type = Type::vec(cx, &element_llvm_type);
1908 let vec_type_name: &str = format!("[{}]", ppaux::ty_to_str(cx.tcx(), element_type));
1910 let member_llvm_types = vec_llvm_type.field_types();
1912 let int_type_metadata = type_metadata(cx, ty::mk_int(), span);
1913 let array_type_metadata = unsafe {
1914 llvm::LLVMDIBuilderCreateArrayType(
1916 bytes_to_bits(element_size),
1917 bytes_to_bits(element_align),
1918 element_type_metadata,
1919 create_DIArray(DIB(cx), [llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, 0)]))
1922 let member_descriptions = [
1925 llvm_type: *member_llvm_types.get(0),
1926 type_metadata: int_type_metadata,
1927 offset: ComputedMemberOffset,
1931 llvm_type: *member_llvm_types.get(1),
1932 type_metadata: int_type_metadata,
1933 offset: ComputedMemberOffset,
1937 llvm_type: *member_llvm_types.get(2),
1938 type_metadata: array_type_metadata,
1939 offset: ComputedMemberOffset,
1943 assert!(member_descriptions.len() == member_llvm_types.len());
1945 let loc = span_start(cx, span);
1946 let file_metadata = file_metadata(cx, loc.file.name);
1948 composite_type_metadata(
1952 member_descriptions,
1958 fn vec_slice_metadata(cx: &CrateContext,
1960 element_type: ty::t,
1962 -> DICompositeType {
1964 debug!("vec_slice_metadata: {:?}", ty::get(vec_type));
1966 let slice_llvm_type = type_of::type_of(cx, vec_type);
1967 let slice_type_name = ppaux::ty_to_str(cx.tcx(), vec_type);
1969 let member_llvm_types = slice_llvm_type.field_types();
1970 assert!(slice_layout_is_correct(cx,
1971 member_llvm_types.as_slice(),
1974 let data_ptr_type = ty::mk_ptr(cx.tcx(), ty::mt {
1976 mutbl: ast::MutImmutable
1979 let member_descriptions = [
1982 llvm_type: *member_llvm_types.get(0),
1983 type_metadata: type_metadata(cx, data_ptr_type, span),
1984 offset: ComputedMemberOffset,
1988 llvm_type: *member_llvm_types.get(1),
1989 type_metadata: type_metadata(cx, ty::mk_uint(), span),
1990 offset: ComputedMemberOffset,
1994 assert!(member_descriptions.len() == member_llvm_types.len());
1996 let loc = span_start(cx, span);
1997 let file_metadata = file_metadata(cx, loc.file.name);
1999 return composite_type_metadata(
2003 member_descriptions,
2008 fn slice_layout_is_correct(cx: &CrateContext,
2009 member_llvm_types: &[Type],
2010 element_type: ty::t)
2012 member_llvm_types.len() == 2 &&
2013 member_llvm_types[0] == type_of::type_of(cx, element_type).ptr_to() &&
2014 member_llvm_types[1] == cx.int_type
2018 fn subroutine_type_metadata(cx: &CrateContext,
2019 signature: &ty::FnSig,
2021 -> DICompositeType {
2022 let loc = span_start(cx, span);
2023 let file_metadata = file_metadata(cx, loc.file.name);
2025 let mut signature_metadata: Vec<DIType> =
2026 Vec::with_capacity(signature.inputs.len() + 1);
2029 signature_metadata.push(match ty::get(signature.output).sty {
2030 ty::ty_nil => ptr::null(),
2031 _ => type_metadata(cx, signature.output, span)
2034 // regular arguments
2035 for &argument_type in signature.inputs.iter() {
2036 signature_metadata.push(type_metadata(cx, argument_type, span));
2040 llvm::LLVMDIBuilderCreateSubroutineType(
2043 create_DIArray(DIB(cx), signature_metadata.as_slice()))
2047 fn trait_metadata(cx: &CrateContext,
2050 substs: &ty::substs,
2051 trait_store: ty::TraitStore,
2052 mutability: ast::Mutability,
2053 _: &ty::BuiltinBounds)
2055 // The implementation provided here is a stub. It makes sure that the trait type is
2056 // assigned the correct name, size, namespace, and source location. But it does not describe
2057 // the trait's methods.
2058 let last = ty::with_path(cx.tcx(), def_id, |mut path| path.last().unwrap());
2059 let ident_string = token::get_name(last.name());
2060 let name = ppaux::trait_store_to_str(cx.tcx(), trait_store) +
2061 ppaux::mutability_to_str(mutability) +
2063 // Add type and region parameters
2064 let name = ppaux::parameterized(cx.tcx(), name, &substs.regions,
2065 substs.tps.as_slice(), def_id, true);
2067 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id);
2069 let file_name = span_start(cx, definition_span).file.name.clone();
2070 let file_metadata = file_metadata(cx, file_name);
2072 let trait_llvm_type = type_of::type_of(cx, trait_type);
2074 return composite_type_metadata(cx,
2083 fn type_metadata(cx: &CrateContext,
2085 usage_site_span: Span)
2087 let cache_id = cache_id_for_type(t);
2089 match debug_context(cx).created_types.borrow().find(&cache_id) {
2090 Some(type_metadata) => return *type_metadata,
2094 fn create_pointer_to_box_metadata(cx: &CrateContext,
2095 pointer_type: ty::t,
2098 let content_type_name: &str = ppaux::ty_to_str(cx.tcx(), type_in_box);
2099 let content_llvm_type = type_of::type_of(cx, type_in_box);
2100 let content_type_metadata = type_metadata(
2105 let box_metadata = boxed_type_metadata(
2107 Some(content_type_name),
2109 content_type_metadata,
2112 pointer_type_metadata(cx, pointer_type, box_metadata)
2115 debug!("type_metadata: {:?}", ty::get(t));
2117 let sty = &ty::get(t).sty;
2118 let type_metadata = match *sty {
2125 ty::ty_float(_) => {
2126 basic_type_metadata(cx, t)
2128 ty::ty_str(ref vstore) => {
2129 let i8_t = ty::mk_i8();
2131 ty::vstore_fixed(len) => {
2132 fixed_vec_metadata(cx, i8_t, len + 1, usage_site_span)
2134 ty::vstore_uniq => {
2135 let vec_metadata = vec_metadata(cx, i8_t, usage_site_span);
2136 pointer_type_metadata(cx, t, vec_metadata)
2138 ty::vstore_slice(_region) => {
2139 vec_slice_metadata(cx, t, i8_t, usage_site_span)
2143 ty::ty_enum(def_id, _) => {
2144 prepare_enum_metadata(cx, t, def_id, usage_site_span).finalize(cx)
2146 ty::ty_box(typ) => {
2147 create_pointer_to_box_metadata(cx, t, typ)
2149 ty::ty_vec(ref mt, ref vstore) => {
2151 ty::vstore_fixed(len) => {
2152 fixed_vec_metadata(cx, mt.ty, len, usage_site_span)
2154 ty::vstore_uniq => {
2155 let vec_metadata = vec_metadata(cx, mt.ty, usage_site_span);
2156 pointer_type_metadata(cx, t, vec_metadata)
2158 ty::vstore_slice(_) => {
2159 vec_slice_metadata(cx, t, mt.ty, usage_site_span)
2163 ty::ty_uniq(typ) => {
2164 let pointee = type_metadata(cx, typ, usage_site_span);
2165 pointer_type_metadata(cx, t, pointee)
2167 ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => {
2168 let pointee = type_metadata(cx, mt.ty, usage_site_span);
2169 pointer_type_metadata(cx, t, pointee)
2171 ty::ty_bare_fn(ref barefnty) => {
2172 subroutine_type_metadata(cx, &barefnty.sig, usage_site_span)
2174 ty::ty_closure(ref closurety) => {
2175 subroutine_type_metadata(cx, &closurety.sig, usage_site_span)
2177 ty::ty_trait(~ty::TyTrait { def_id, ref substs,
2178 store: trait_store, mutability,
2180 trait_metadata(cx, def_id, t, substs, trait_store, mutability, bounds)
2182 ty::ty_struct(def_id, ref substs) => {
2183 if ty::type_is_simd(cx.tcx(), t) {
2184 let element_type = ty::simd_type(cx.tcx(), t);
2185 let len = ty::simd_size(cx.tcx(), t);
2186 fixed_vec_metadata(cx, element_type, len, usage_site_span)
2188 prepare_struct_metadata(cx, t, def_id, substs, usage_site_span).finalize(cx)
2191 ty::ty_tup(ref elements) => {
2192 prepare_tuple_metadata(cx,
2194 elements.as_slice(),
2195 usage_site_span).finalize(cx)
2197 _ => cx.sess().bug(format!("debuginfo: unexpected type in type_metadata: {:?}", sty))
2200 debug_context(cx).created_types.borrow_mut().insert(cache_id, type_metadata);
2205 enum DebugLocation {
2206 KnownLocation { scope: DIScope, line: uint, col: uint },
2210 impl DebugLocation {
2211 fn new(scope: DIScope, line: uint, col: uint) -> DebugLocation {
2220 fn set_debug_location(cx: &CrateContext, debug_location: DebugLocation) {
2221 if debug_location == debug_context(cx).current_debug_location.get() {
2227 match debug_location {
2228 KnownLocation { scope, line, .. } => {
2229 let col = 0; // Always set the column to zero like Clang and GCC
2230 debug!("setting debug location to {} {}", line, col);
2231 let elements = [C_i32(cx, line as i32), C_i32(cx, col as i32), scope, ptr::null()];
2233 metadata_node = llvm::LLVMMDNodeInContext(debug_context(cx).llcontext,
2235 elements.len() as c_uint);
2238 UnknownLocation => {
2239 debug!("clearing debug location ");
2240 metadata_node = ptr::null();
2245 llvm::LLVMSetCurrentDebugLocation(cx.builder.b, metadata_node);
2248 debug_context(cx).current_debug_location.set(debug_location);
2251 //=-------------------------------------------------------------------------------------------------
2252 // Utility Functions
2253 //=-------------------------------------------------------------------------------------------------
2255 fn cache_id_for_type(t: ty::t) -> uint {
2259 // Used to avoid LLVM metadata uniquing problems. See `create_struct_stub()` and
2260 // `prepare_enum_metadata()`.
2261 fn generate_unique_type_id(prefix: &'static str) -> ~str {
2263 static mut unique_id_counter: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;
2264 format!("{}{}", prefix, unique_id_counter.fetch_add(1, atomics::SeqCst))
2268 /// Return codemap::Loc corresponding to the beginning of the span
2269 fn span_start(cx: &CrateContext, span: Span) -> codemap::Loc {
2270 cx.sess().codemap().lookup_char_pos(span.lo)
2273 fn size_and_align_of(cx: &CrateContext, llvm_type: Type) -> (u64, u64) {
2274 (machine::llsize_of_alloc(cx, llvm_type), machine::llalign_of_min(cx, llvm_type))
2277 fn bytes_to_bits(bytes: u64) -> c_ulonglong {
2278 (bytes * 8) as c_ulonglong
2282 fn debug_context<'a>(cx: &'a CrateContext) -> &'a CrateDebugContext {
2283 let debug_context: &'a CrateDebugContext = cx.dbg_cx.get_ref();
2288 fn DIB(cx: &CrateContext) -> DIBuilderRef {
2289 cx.dbg_cx.get_ref().builder
2292 fn fn_should_be_ignored(fcx: &FunctionContext) -> bool {
2293 match fcx.debug_context {
2294 FunctionDebugContext(_) => false,
2299 fn assert_type_for_node_id(cx: &CrateContext, node_id: ast::NodeId, error_span: Span) {
2300 if !cx.tcx.node_types.borrow().contains_key(&(node_id as uint)) {
2301 cx.sess().span_bug(error_span, "debuginfo: Could not find type for node id!");
2305 fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: ast::DefId)
2306 -> (DIScope, Span) {
2307 let containing_scope = namespace_for_item(cx, def_id).scope;
2308 let definition_span = if def_id.krate == ast::LOCAL_CRATE {
2309 cx.tcx.map.span(def_id.node)
2311 // For external items there is no span information
2315 (containing_scope, definition_span)
2318 // This procedure builds the *scope map* for a given function, which maps any given ast::NodeId in
2319 // the function's AST to the correct DIScope metadata instance.
2321 // This builder procedure walks the AST in execution order and keeps track of what belongs to which
2322 // scope, creating DIScope DIEs along the way, and introducing *artificial* lexical scope
2323 // descriptors where necessary. These artificial scopes allow GDB to correctly handle name
2325 fn populate_scope_map(cx: &CrateContext,
2326 arg_pats: &[@ast::Pat],
2327 fn_entry_block: &ast::Block,
2328 fn_metadata: DISubprogram,
2329 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2330 let def_map = cx.tcx.def_map;
2332 struct ScopeStackEntry {
2333 scope_metadata: DIScope,
2334 ident: Option<ast::Ident>
2337 let mut scope_stack = vec!(ScopeStackEntry { scope_metadata: fn_metadata, ident: None });
2339 // Push argument identifiers onto the stack so arguments integrate nicely with variable
2341 for &arg_pat in arg_pats.iter() {
2342 pat_util::pat_bindings(def_map, arg_pat, |_, _, _, path_ref| {
2343 let ident = ast_util::path_to_ident(path_ref);
2344 scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata, ident: Some(ident) });
2348 // Clang creates a separate scope for function bodies, so let's do this too
2350 fn_entry_block.span,
2353 |cx, scope_stack, scope_map| {
2354 walk_block(cx, fn_entry_block, scope_stack, scope_map);
2357 // local helper functions for walking the AST.
2358 fn with_new_scope(cx: &CrateContext,
2360 scope_stack: &mut Vec<ScopeStackEntry> ,
2361 scope_map: &mut HashMap<ast::NodeId, DIScope>,
2362 inner_walk: |&CrateContext,
2363 &mut Vec<ScopeStackEntry> ,
2364 &mut HashMap<ast::NodeId, DIScope>|) {
2365 // Create a new lexical scope and push it onto the stack
2366 let loc = cx.sess().codemap().lookup_char_pos(scope_span.lo);
2367 let file_metadata = file_metadata(cx, loc.file.name);
2368 let parent_scope = scope_stack.last().unwrap().scope_metadata;
2370 let scope_metadata = unsafe {
2371 llvm::LLVMDIBuilderCreateLexicalBlock(
2376 loc.col.to_uint() as c_uint)
2379 scope_stack.push(ScopeStackEntry { scope_metadata: scope_metadata, ident: None });
2381 inner_walk(cx, scope_stack, scope_map);
2383 // pop artificial scopes
2384 while scope_stack.last().unwrap().ident.is_some() {
2388 if scope_stack.last().unwrap().scope_metadata != scope_metadata {
2389 cx.sess().span_bug(scope_span, "debuginfo: Inconsistency in scope management.");
2395 fn walk_block(cx: &CrateContext,
2397 scope_stack: &mut Vec<ScopeStackEntry> ,
2398 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2399 scope_map.insert(block.id, scope_stack.last().unwrap().scope_metadata);
2401 // The interesting things here are statements and the concluding expression.
2402 for statement in block.stmts.iter() {
2403 scope_map.insert(ast_util::stmt_id(*statement),
2404 scope_stack.last().unwrap().scope_metadata);
2406 match statement.node {
2407 ast::StmtDecl(decl, _) => walk_decl(cx, decl, scope_stack, scope_map),
2408 ast::StmtExpr(exp, _) |
2409 ast::StmtSemi(exp, _) => walk_expr(cx, exp, scope_stack, scope_map),
2410 ast::StmtMac(..) => () // ignore macros (which should be expanded anyway)
2414 for exp in block.expr.iter() {
2415 walk_expr(cx, *exp, scope_stack, scope_map);
2419 fn walk_decl(cx: &CrateContext,
2421 scope_stack: &mut Vec<ScopeStackEntry> ,
2422 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2424 codemap::Spanned { node: ast::DeclLocal(local), .. } => {
2425 scope_map.insert(local.id, scope_stack.last().unwrap().scope_metadata);
2427 walk_pattern(cx, local.pat, scope_stack, scope_map);
2429 for exp in local.init.iter() {
2430 walk_expr(cx, *exp, scope_stack, scope_map);
2437 fn walk_pattern(cx: &CrateContext,
2439 scope_stack: &mut Vec<ScopeStackEntry> ,
2440 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2442 let def_map = cx.tcx.def_map;
2444 // Unfortunately, we cannot just use pat_util::pat_bindings() or ast_util::walk_pat() here
2445 // because we have to visit *all* nodes in order to put them into the scope map. The above
2446 // functions don't do that.
2448 ast::PatIdent(_, ref path_ref, ref sub_pat_opt) => {
2450 // Check if this is a binding. If so we need to put it on the scope stack and maybe
2451 // introduce an articial scope
2452 if pat_util::pat_is_binding(def_map, pat) {
2454 let ident = ast_util::path_to_ident(path_ref);
2456 // LLVM does not properly generate 'DW_AT_start_scope' fields for variable DIEs.
2457 // For this reason we have to introduce an artificial scope at bindings whenever
2458 // a variable with the same name is declared in *any* parent scope.
2460 // Otherwise the following error occurs:
2464 // do_something(); // 'gdb print x' correctly prints 10
2467 // do_something(); // 'gdb print x' prints 0, because it already reads the
2468 // // uninitialized 'x' from the next line...
2470 // do_something(); // 'gdb print x' correctly prints 100
2473 // Is there already a binding with that name?
2474 // N.B.: this comparison must be UNhygienic... because
2475 // gdb knows nothing about the context, so any two
2476 // variables with the same name will cause the problem.
2477 let need_new_scope = scope_stack
2479 .any(|entry| entry.ident.iter().any(|i| i.name == ident.name));
2482 // Create a new lexical scope and push it onto the stack
2483 let loc = cx.sess().codemap().lookup_char_pos(pat.span.lo);
2484 let file_metadata = file_metadata(cx, loc.file.name);
2485 let parent_scope = scope_stack.last().unwrap().scope_metadata;
2487 let scope_metadata = unsafe {
2488 llvm::LLVMDIBuilderCreateLexicalBlock(
2493 loc.col.to_uint() as c_uint)
2496 scope_stack.push(ScopeStackEntry {
2497 scope_metadata: scope_metadata,
2502 // Push a new entry anyway so the name can be found
2503 let prev_metadata = scope_stack.last().unwrap().scope_metadata;
2504 scope_stack.push(ScopeStackEntry {
2505 scope_metadata: prev_metadata,
2511 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2513 for &sub_pat in sub_pat_opt.iter() {
2514 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2518 ast::PatWild | ast::PatWildMulti => {
2519 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2522 ast::PatEnum(_, ref sub_pats_opt) => {
2523 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2525 for ref sub_pats in sub_pats_opt.iter() {
2526 for &p in sub_pats.iter() {
2527 walk_pattern(cx, p, scope_stack, scope_map);
2532 ast::PatStruct(_, ref field_pats, _) => {
2533 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2535 for &ast::FieldPat { pat: sub_pat, .. } in field_pats.iter() {
2536 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2540 ast::PatTup(ref sub_pats) => {
2541 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2543 for &sub_pat in sub_pats.iter() {
2544 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2548 ast::PatUniq(sub_pat) | ast::PatRegion(sub_pat) => {
2549 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2550 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2553 ast::PatLit(exp) => {
2554 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2555 walk_expr(cx, exp, scope_stack, scope_map);
2558 ast::PatRange(exp1, exp2) => {
2559 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2560 walk_expr(cx, exp1, scope_stack, scope_map);
2561 walk_expr(cx, exp2, scope_stack, scope_map);
2564 ast::PatVec(ref front_sub_pats, ref middle_sub_pats, ref back_sub_pats) => {
2565 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2567 for &sub_pat in front_sub_pats.iter() {
2568 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2571 for &sub_pat in middle_sub_pats.iter() {
2572 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2575 for &sub_pat in back_sub_pats.iter() {
2576 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2582 fn walk_expr(cx: &CrateContext,
2584 scope_stack: &mut Vec<ScopeStackEntry> ,
2585 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2587 scope_map.insert(exp.id, scope_stack.last().unwrap().scope_metadata);
2593 ast::ExprPath(_) => {}
2595 ast::ExprVstore(sub_exp, _) |
2596 ast::ExprCast(sub_exp, _) |
2597 ast::ExprAddrOf(_, sub_exp) |
2598 ast::ExprField(sub_exp, _, _) |
2599 ast::ExprParen(sub_exp) => walk_expr(cx, sub_exp, scope_stack, scope_map),
2601 ast::ExprBox(place, sub_expr) => {
2602 walk_expr(cx, place, scope_stack, scope_map);
2603 walk_expr(cx, sub_expr, scope_stack, scope_map);
2606 ast::ExprRet(exp_opt) => match exp_opt {
2607 Some(sub_exp) => walk_expr(cx, sub_exp, scope_stack, scope_map),
2611 ast::ExprUnary(_, sub_exp) => {
2612 walk_expr(cx, sub_exp, scope_stack, scope_map);
2615 ast::ExprAssignOp(_, lhs, rhs) |
2616 ast::ExprIndex(lhs, rhs) |
2617 ast::ExprBinary(_, lhs, rhs) => {
2618 walk_expr(cx, lhs, scope_stack, scope_map);
2619 walk_expr(cx, rhs, scope_stack, scope_map);
2622 ast::ExprVec(ref init_expressions, _) |
2623 ast::ExprTup(ref init_expressions) => {
2624 for ie in init_expressions.iter() {
2625 walk_expr(cx, *ie, scope_stack, scope_map);
2629 ast::ExprAssign(sub_exp1, sub_exp2) |
2630 ast::ExprRepeat(sub_exp1, sub_exp2, _) => {
2631 walk_expr(cx, sub_exp1, scope_stack, scope_map);
2632 walk_expr(cx, sub_exp2, scope_stack, scope_map);
2635 ast::ExprIf(cond_exp, then_block, ref opt_else_exp) => {
2636 walk_expr(cx, cond_exp, scope_stack, scope_map);
2642 |cx, scope_stack, scope_map| {
2643 walk_block(cx, then_block, scope_stack, scope_map);
2646 match *opt_else_exp {
2647 Some(else_exp) => walk_expr(cx, else_exp, scope_stack, scope_map),
2652 ast::ExprWhile(cond_exp, loop_body) => {
2653 walk_expr(cx, cond_exp, scope_stack, scope_map);
2659 |cx, scope_stack, scope_map| {
2660 walk_block(cx, loop_body, scope_stack, scope_map);
2664 ast::ExprForLoop(_, _, _, _) => {
2665 cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \
2666 Found unexpanded for-loop.");
2669 ast::ExprMac(_) => {
2670 cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \
2671 Found unexpanded macro.");
2674 ast::ExprLoop(block, _) |
2675 ast::ExprBlock(block) => {
2680 |cx, scope_stack, scope_map| {
2681 walk_block(cx, block, scope_stack, scope_map);
2685 ast::ExprFnBlock(decl, block) |
2686 ast::ExprProc(decl, block) => {
2691 |cx, scope_stack, scope_map| {
2692 for &ast::Arg { pat: pattern, .. } in decl.inputs.iter() {
2693 walk_pattern(cx, pattern, scope_stack, scope_map);
2696 walk_block(cx, block, scope_stack, scope_map);
2700 ast::ExprCall(fn_exp, ref args) => {
2701 walk_expr(cx, fn_exp, scope_stack, scope_map);
2703 for arg_exp in args.iter() {
2704 walk_expr(cx, *arg_exp, scope_stack, scope_map);
2708 ast::ExprMethodCall(_, _, ref args) => {
2709 for arg_exp in args.iter() {
2710 walk_expr(cx, *arg_exp, scope_stack, scope_map);
2714 ast::ExprMatch(discriminant_exp, ref arms) => {
2715 walk_expr(cx, discriminant_exp, scope_stack, scope_map);
2717 // for each arm we have to first walk the pattern as these might introduce new
2718 // artificial scopes. It should be sufficient to walk only one pattern per arm, as
2719 // they all must contain the same binding names
2721 for arm_ref in arms.iter() {
2722 let arm_span = arm_ref.pats.get(0).span;
2728 |cx, scope_stack, scope_map| {
2729 for &pat in arm_ref.pats.iter() {
2730 walk_pattern(cx, pat, scope_stack, scope_map);
2733 for guard_exp in arm_ref.guard.iter() {
2734 walk_expr(cx, *guard_exp, scope_stack, scope_map)
2737 walk_expr(cx, arm_ref.body, scope_stack, scope_map);
2742 ast::ExprStruct(_, ref fields, ref base_exp) => {
2743 for &ast::Field { expr: exp, .. } in fields.iter() {
2744 walk_expr(cx, exp, scope_stack, scope_map);
2748 Some(exp) => walk_expr(cx, exp, scope_stack, scope_map),
2753 ast::ExprInlineAsm(ast::InlineAsm { inputs: ref inputs,
2754 outputs: ref outputs,
2756 // inputs, outputs: ~[(~str, @expr)]
2757 for &(_, exp) in inputs.iter() {
2758 walk_expr(cx, exp, scope_stack, scope_map);
2761 for &(_, exp) in outputs.iter() {
2762 walk_expr(cx, exp, scope_stack, scope_map);
2770 //=-------------------------------------------------------------------------------------------------
2771 // Namespace Handling
2772 //=-------------------------------------------------------------------------------------------------
2774 struct NamespaceTreeNode {
2777 parent: Option<@NamespaceTreeNode>,
2780 impl NamespaceTreeNode {
2781 fn mangled_name_of_contained_item(&self, item_name: &str) -> ~str {
2782 fn fill_nested(node: &NamespaceTreeNode, output: &mut ~str) {
2784 Some(parent) => fill_nested(parent, output),
2787 let string = token::get_name(node.name);
2788 output.push_str(format!("{}", string.get().len()));
2789 output.push_str(string.get());
2792 let mut name = ~"_ZN";
2793 fill_nested(self, &mut name);
2794 name.push_str(format!("{}", item_name.len()));
2795 name.push_str(item_name);
2796 name.push_char('E');
2801 fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> @NamespaceTreeNode {
2802 ty::with_path(cx.tcx(), def_id, |path| {
2803 // prepend crate name if not already present
2804 let krate = if def_id.krate == ast::LOCAL_CRATE {
2805 let crate_namespace_ident = token::str_to_ident(cx.link_meta.crateid.name);
2806 Some(ast_map::PathMod(crate_namespace_ident.name))
2810 let mut path = krate.move_iter().chain(path).peekable();
2812 let mut current_key = Vec::new();
2813 let mut parent_node: Option<@NamespaceTreeNode> = None;
2815 // Create/Lookup namespace for each element of the path.
2817 // Emulate a for loop so we can use peek below.
2818 let path_element = match path.next() {
2822 // Ignore the name of the item (the last path element).
2823 if path.peek().is_none() {
2827 let name = path_element.name();
2828 current_key.push(name);
2830 let existing_node = debug_context(cx).namespace_map.borrow()
2831 .find_copy(¤t_key);
2832 let current_node = match existing_node {
2833 Some(existing_node) => existing_node,
2835 // create and insert
2836 let parent_scope = match parent_node {
2837 Some(node) => node.scope,
2840 let namespace_name = token::get_name(name);
2841 let scope = namespace_name.get().with_c_str(|namespace_name| {
2843 llvm::LLVMDIBuilderCreateNameSpace(
2847 // cannot reconstruct file ...
2849 // ... or line information, but that's not so important.
2854 let node = @NamespaceTreeNode {
2857 parent: parent_node,
2860 debug_context(cx).namespace_map.borrow_mut()
2861 .insert(current_key.clone(), node);
2867 parent_node = Some(current_node);
2873 cx.sess().bug(format!("debuginfo::namespace_for_item(): \
2874 path too short for {:?}", def_id));