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, opt_vec};
154 use syntax::parse::token;
155 use syntax::parse::token::special_idents;
157 static DW_LANG_RUST: c_uint = 0x9000;
159 static DW_TAG_auto_variable: c_uint = 0x100;
160 static DW_TAG_arg_variable: c_uint = 0x101;
162 static DW_ATE_boolean: c_uint = 0x02;
163 static DW_ATE_float: c_uint = 0x04;
164 static DW_ATE_signed: c_uint = 0x05;
165 // static DW_ATE_signed_char: c_uint = 0x06;
166 static DW_ATE_unsigned: c_uint = 0x07;
167 static DW_ATE_unsigned_char: c_uint = 0x08;
169 //=-------------------------------------------------------------------------------------------------
170 // Public Interface of debuginfo module
171 //=-------------------------------------------------------------------------------------------------
173 /// A context object for maintaining all state needed by the debuginfo module.
174 pub struct CrateDebugContext {
175 priv llcontext: ContextRef,
176 priv builder: DIBuilderRef,
177 priv current_debug_location: Cell<DebugLocation>,
178 priv created_files: RefCell<HashMap<~str, DIFile>>,
179 priv created_types: RefCell<HashMap<uint, DIType>>,
180 priv namespace_map: RefCell<HashMap<~[ast::Name], @NamespaceTreeNode>>,
181 // This collection is used to assert that composite types (structs, enums, ...) have their
182 // members only set once:
183 priv composite_types_completed: RefCell<HashSet<DIType>>,
186 impl CrateDebugContext {
187 pub fn new(llmod: ModuleRef) -> CrateDebugContext {
188 debug!("CrateDebugContext::new");
189 let builder = unsafe { llvm::LLVMDIBuilderCreate(llmod) };
190 // DIBuilder inherits context from the module, so we'd better use the same one
191 let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
192 return CrateDebugContext {
193 llcontext: llcontext,
195 current_debug_location: Cell::new(UnknownLocation),
196 created_files: RefCell::new(HashMap::new()),
197 created_types: RefCell::new(HashMap::new()),
198 namespace_map: RefCell::new(HashMap::new()),
199 composite_types_completed: RefCell::new(HashSet::new()),
204 pub enum FunctionDebugContext {
205 priv FunctionDebugContext(~FunctionDebugContextData),
206 priv DebugInfoDisabled,
207 priv FunctionWithoutDebugInfo,
210 impl FunctionDebugContext {
211 fn get_ref<'a>(&'a self, cx: &CrateContext, span: Span) -> &'a FunctionDebugContextData {
213 FunctionDebugContext(~ref data) => data,
214 DebugInfoDisabled => {
215 cx.sess.span_bug(span, FunctionDebugContext::debuginfo_disabled_message());
217 FunctionWithoutDebugInfo => {
218 cx.sess.span_bug(span, FunctionDebugContext::should_be_ignored_message());
223 fn debuginfo_disabled_message() -> &'static str {
224 "debuginfo: Error trying to access FunctionDebugContext although debug info is disabled!"
227 fn should_be_ignored_message() -> &'static str {
228 "debuginfo: Error trying to access FunctionDebugContext for function that should be \
229 ignored by debug info!"
233 struct FunctionDebugContextData {
234 scope_map: RefCell<HashMap<ast::NodeId, DIScope>>,
235 fn_metadata: DISubprogram,
236 argument_counter: Cell<uint>,
237 source_locations_enabled: Cell<bool>,
240 enum VariableAccess<'a> {
241 // The llptr given is an alloca containing the variable's value
242 DirectVariable { alloca: ValueRef },
243 // The llptr given is an alloca containing the start of some pointer chain leading to the
244 // variable's content.
245 IndirectVariable { alloca: ValueRef, address_operations: &'a [ValueRef] }
249 ArgumentVariable(uint /*index*/),
254 /// Create any deferred debug metadata nodes
255 pub fn finalize(cx: @CrateContext) {
256 if cx.dbg_cx.is_none() {
261 compile_unit_metadata(cx);
263 llvm::LLVMDIBuilderFinalize(DIB(cx));
264 llvm::LLVMDIBuilderDispose(DIB(cx));
265 // Debuginfo generation in LLVM by default uses a higher
266 // version of dwarf than OS X currently understands. We can
267 // instruct LLVM to emit an older version of dwarf, however,
268 // for OS X to understand. For more info see #11352
269 // This can be overridden using --llvm-opts -dwarf-version,N.
270 if cx.sess.targ_cfg.os == abi::OsMacos {
271 "Dwarf Version".with_c_str(
272 |s| llvm::LLVMRustAddModuleFlag(cx.llmod, s, 2));
275 // Prevent bitcode readers from deleting the debug info.
276 "Debug Info Version".with_c_str(
277 |s| llvm::LLVMRustAddModuleFlag(cx.llmod, s,
278 llvm::LLVMRustDebugMetadataVersion));
282 /// Creates debug information for the given local variable.
284 /// Adds the created metadata nodes directly to the crate's IR.
285 pub fn create_local_var_metadata(bcx: &Block, local: &ast::Local) {
286 if fn_should_be_ignored(bcx.fcx) {
291 let def_map = cx.tcx.def_map;
293 pat_util::pat_bindings(def_map, local.pat, |_, node_id, span, path_ref| {
294 let var_ident = ast_util::path_to_ident(path_ref);
297 let lllocals = bcx.fcx.lllocals.borrow();
298 match lllocals.get().find_copy(&node_id) {
299 Some(datum) => datum,
301 bcx.tcx().sess.span_bug(span,
302 format!("no entry in lllocals table for {:?}",
308 let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
314 DirectVariable { alloca: datum.val },
320 /// Creates debug information for a variable captured in a closure.
322 /// Adds the created metadata nodes directly to the crate's IR.
323 pub fn create_captured_var_metadata(bcx: &Block,
324 node_id: ast::NodeId,
325 env_data_type: ty::t,
326 env_pointer: ValueRef,
328 closure_sigil: ast::Sigil,
330 if fn_should_be_ignored(bcx.fcx) {
336 let ast_item = cx.tcx.map.find(node_id);
338 let variable_ident = match ast_item {
340 cx.sess.span_bug(span, "debuginfo::create_captured_var_metadata() - NodeId not found");
342 Some(ast_map::NodeLocal(pat)) | Some(ast_map::NodeArg(pat)) => {
344 ast::PatIdent(_, ref path, _) => {
345 ast_util::path_to_ident(path)
351 "debuginfo::create_captured_var_metadata() - \
352 Captured var-id refers to unexpected \
353 ast_map variant: {:?}",
359 cx.sess.span_bug(span, format!("debuginfo::create_captured_var_metadata() - \
360 Captured var-id refers to unexpected ast_map variant: {:?}", ast_item));
364 let variable_type = node_id_type(bcx, node_id);
365 let scope_metadata = bcx.fcx.debug_context.get_ref(cx, span).fn_metadata;
367 let llvm_env_data_type = type_of::type_of(cx, env_data_type);
368 let byte_offset_of_var_in_env = machine::llelement_offset(cx, llvm_env_data_type, env_index);
370 let address_operations = unsafe {
371 [llvm::LLVMDIBuilderCreateOpDeref(Type::i64().to_ref()),
372 llvm::LLVMDIBuilderCreateOpPlus(Type::i64().to_ref()),
373 C_i64(byte_offset_of_var_in_env as i64),
374 llvm::LLVMDIBuilderCreateOpDeref(Type::i64().to_ref())]
377 let address_op_count = match closure_sigil {
378 ast::BorrowedSigil => {
379 address_operations.len()
381 ast::ManagedSigil | ast::OwnedSigil => {
382 address_operations.len() - 1
386 let variable_access = IndirectVariable {
388 address_operations: address_operations.slice_to(address_op_count)
400 /// Creates debug information for a local variable introduced in the head of a match-statement arm.
402 /// Adds the created metadata nodes directly to the crate's IR.
403 pub fn create_match_binding_metadata(bcx: &Block,
404 variable_ident: ast::Ident,
405 node_id: ast::NodeId,
407 datum: Datum<Lvalue>) {
408 if fn_should_be_ignored(bcx.fcx) {
412 let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
418 DirectVariable { alloca: datum.val },
423 /// Creates debug information for the given function argument.
425 /// Adds the created metadata nodes directly to the crate's IR.
426 pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
427 if fn_should_be_ignored(bcx.fcx) {
434 let def_map = cx.tcx.def_map;
435 let scope_metadata = bcx.fcx.debug_context.get_ref(cx, arg.pat.span).fn_metadata;
437 pat_util::pat_bindings(def_map, arg.pat, |_, node_id, span, path_ref| {
439 let llargs = bcx.fcx.llargs.borrow();
440 match llargs.get().find_copy(&node_id) {
443 bcx.tcx().sess.span_bug(span,
444 format!("no entry in llargs table for {:?}",
450 if unsafe { llvm::LLVMIsAAllocaInst(llarg.val) } == ptr::null() {
451 cx.sess.span_bug(span, "debuginfo::create_argument_metadata() - \
452 Referenced variable location is not an alloca!");
455 let argument_ident = ast_util::path_to_ident(path_ref);
457 let argument_index = {
458 let counter = &fcx.debug_context.get_ref(cx, span).argument_counter;
459 let argument_index = counter.get();
460 counter.set(argument_index + 1);
468 DirectVariable { alloca: llarg.val },
469 ArgumentVariable(argument_index),
474 /// Sets the current debug location at the beginning of the span.
476 /// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...). The node_id parameter is used to
477 /// reliably find the correct visibility scope for the code position.
478 pub fn set_source_location(fcx: &FunctionContext,
479 node_id: ast::NodeId,
481 if fn_should_be_ignored(fcx) {
487 debug!("set_source_location: {}", cx.sess.codemap.span_to_str(span));
489 if fcx.debug_context.get_ref(cx, span).source_locations_enabled.get() {
490 let loc = span_start(cx, span);
491 let scope = scope_metadata(fcx, node_id, span);
493 set_debug_location(cx, DebugLocation::new(scope, loc.line, loc.col.to_uint()));
495 set_debug_location(cx, UnknownLocation);
499 /// Clears the current debug location.
501 /// Instructions generated hereafter won't be assigned a source location.
502 pub fn clear_source_location(fcx: &FunctionContext) {
503 if fn_should_be_ignored(fcx) {
507 set_debug_location(fcx.ccx, UnknownLocation);
510 /// Enables emitting source locations for the given functions.
512 /// Since we don't want source locations to be emitted for the function prelude, they are disabled
513 /// when beginning to translate a new function. This functions switches source location emitting on
514 /// and must therefore be called before the first real statement/expression of the function is
516 pub fn start_emitting_source_locations(fcx: &FunctionContext) {
517 match fcx.debug_context {
518 FunctionDebugContext(~ref data) => {
519 data.source_locations_enabled.set(true)
521 _ => { /* safe to ignore */ }
525 /// Creates the function-specific debug context.
527 /// Returns the FunctionDebugContext for the function which holds state needed for debug info
528 /// creation. The function may also return another variant of the FunctionDebugContext enum which
529 /// indicates why no debuginfo should be created for the function.
530 pub fn create_function_debug_context(cx: &CrateContext,
531 fn_ast_id: ast::NodeId,
532 param_substs: Option<@param_substs>,
533 llfn: ValueRef) -> FunctionDebugContext {
534 if cx.sess.opts.debuginfo == NoDebugInfo {
535 return DebugInfoDisabled;
539 return FunctionWithoutDebugInfo;
542 let empty_generics = ast::Generics { lifetimes: opt_vec::Empty, ty_params: opt_vec::Empty };
544 let fnitem = cx.tcx.map.get(fn_ast_id);
546 let (ident, fn_decl, generics, top_level_block, span, has_path) = match fnitem {
547 ast_map::NodeItem(ref item) => {
549 ast::ItemFn(fn_decl, _, _, ref generics, top_level_block) => {
550 (item.ident, fn_decl, generics, top_level_block, item.span, true)
553 cx.sess.span_bug(item.span,
554 "create_function_debug_context: item bound to non-function");
558 ast_map::NodeMethod(method) => {
566 ast_map::NodeExpr(ref expr) => {
568 ast::ExprFnBlock(fn_decl, top_level_block) |
569 ast::ExprProc(fn_decl, top_level_block) => {
570 let name = format!("fn{}", token::gensym("fn"));
571 let name = token::str_to_ident(name);
573 // This is not quite right. It should actually inherit the generics of the
574 // enclosing function.
578 // Don't try to lookup the item path:
581 _ => cx.sess.span_bug(expr.span,
582 "create_function_debug_context: expected an expr_fn_block here")
585 ast_map::NodeTraitMethod(trait_method) => {
586 match *trait_method {
587 ast::Provided(method) => {
597 .bug(format!("create_function_debug_context: \
598 unexpected sort of node: {:?}",
603 ast_map::NodeForeignItem(..) |
604 ast_map::NodeVariant(..) |
605 ast_map::NodeStructCtor(..) => {
606 return FunctionWithoutDebugInfo;
608 _ => cx.sess.bug(format!("create_function_debug_context: \
609 unexpected sort of node: {:?}", fnitem))
612 // This can be the case for functions inlined from another crate
613 if span == codemap::DUMMY_SP {
614 return FunctionWithoutDebugInfo;
617 let loc = span_start(cx, span);
618 let file_metadata = file_metadata(cx, loc.file.name);
620 let function_type_metadata = unsafe {
621 let fn_signature = get_function_signature(cx, fn_ast_id, fn_decl, param_substs, span);
622 llvm::LLVMDIBuilderCreateSubroutineType(DIB(cx), file_metadata, fn_signature)
625 // get_template_parameters() will append a `<...>` clause to the function name if necessary.
626 let mut function_name = token::get_ident(ident).get().to_str();
627 let template_parameters = get_template_parameters(cx,
633 // There is no ast_map::Path for ast::ExprFnBlock-type functions. For now, just don't put them
634 // into a namespace. In the future this could be improved somehow (storing a path in the
635 // ast_map, or construct a path using the enclosing function).
636 let (linkage_name, containing_scope) = if has_path {
637 let namespace_node = namespace_for_item(cx, ast_util::local_def(fn_ast_id));
638 let linkage_name = namespace_node.mangled_name_of_contained_item(function_name);
639 let containing_scope = namespace_node.scope;
640 (linkage_name, containing_scope)
642 (function_name.clone(), file_metadata)
645 // Clang sets this parameter to the opening brace of the function's block, so let's do this too.
646 let scope_line = span_start(cx, top_level_block.span).line;
648 // The is_local_to_unit flag indicates whether a function is local to the current compilation
649 // unit (i.e. if it is *static* in the C-sense). The *reachable* set should provide a good
650 // approximation of this, as it contains everything that might leak out of the current crate
651 // (by being externally visible or by being inlined into something externally visible). It might
652 // better to use the `exported_items` set from `driver::CrateAnalysis` in the future, but (atm)
653 // this set is not available in the translation pass.
654 let is_local_to_unit = {
655 let reachable = cx.reachable.borrow();
656 !reachable.get().contains(&fn_ast_id)
659 let fn_metadata = function_name.with_c_str(|function_name| {
660 linkage_name.with_c_str(|linkage_name| {
662 llvm::LLVMDIBuilderCreateFunction(
669 function_type_metadata,
672 scope_line as c_uint,
673 FlagPrototyped as c_uint,
674 cx.sess.opts.optimize != session::No,
682 // Initialize fn debug context (including scope map and namespace map)
683 let fn_debug_context = ~FunctionDebugContextData {
684 scope_map: RefCell::new(HashMap::new()),
685 fn_metadata: fn_metadata,
686 argument_counter: Cell::new(1),
687 source_locations_enabled: Cell::new(false),
690 let arg_pats = fn_decl.inputs.map(|arg_ref| arg_ref.pat);
692 let mut scope_map = fn_debug_context.scope_map.borrow_mut();
693 populate_scope_map(cx,
700 // Clear the debug location so we don't assign them in the function prelude
701 set_debug_location(cx, UnknownLocation);
703 return FunctionDebugContext(fn_debug_context);
705 fn get_function_signature(cx: &CrateContext,
706 fn_ast_id: ast::NodeId,
707 fn_decl: &ast::FnDecl,
708 param_substs: Option<@param_substs>,
709 error_span: Span) -> DIArray {
710 if cx.sess.opts.debuginfo == LimitedDebugInfo {
711 return create_DIArray(DIB(cx), []);
714 let mut signature = vec::with_capacity(fn_decl.inputs.len() + 1);
716 // Return type -- llvm::DIBuilder wants this at index 0
717 match fn_decl.output.node {
719 signature.push(ptr::null());
722 assert_type_for_node_id(cx, fn_ast_id, error_span);
724 let return_type = ty::node_id_to_type(cx.tcx, fn_ast_id);
725 let return_type = match param_substs {
728 ty::subst_tps(cx.tcx, substs.tys, substs.self_ty, return_type)
732 signature.push(type_metadata(cx, return_type, codemap::DUMMY_SP));
737 for arg in fn_decl.inputs.iter() {
738 assert_type_for_node_id(cx, arg.pat.id, arg.pat.span);
739 let arg_type = ty::node_id_to_type(cx.tcx, arg.pat.id);
740 let arg_type = match param_substs {
743 ty::subst_tps(cx.tcx, substs.tys, substs.self_ty, arg_type)
747 signature.push(type_metadata(cx, arg_type, codemap::DUMMY_SP));
750 return create_DIArray(DIB(cx), signature);
753 fn get_template_parameters(cx: &CrateContext,
754 generics: &ast::Generics,
755 param_substs: Option<@param_substs>,
756 file_metadata: DIFile,
757 name_to_append_suffix_to: &mut ~str)
759 let self_type = match param_substs {
760 Some(param_substs) => param_substs.self_ty,
764 // Only true for static default methods:
765 let has_self_type = self_type.is_some();
767 if !generics.is_type_parameterized() && !has_self_type {
768 return create_DIArray(DIB(cx), []);
771 name_to_append_suffix_to.push_char('<');
773 // The list to be filled with template parameters:
774 let mut template_params: ~[DIDescriptor] = vec::with_capacity(generics.ty_params.len() + 1);
778 let actual_self_type = self_type.unwrap();
779 // Add self type name to <...> clause of function name
780 let actual_self_type_name = ppaux::ty_to_str(cx.tcx, actual_self_type);
781 name_to_append_suffix_to.push_str(actual_self_type_name);
783 if generics.is_type_parameterized() {
784 name_to_append_suffix_to.push_str(",");
787 // Only create type information if full debuginfo is enabled
788 if cx.sess.opts.debuginfo == FullDebugInfo {
789 let actual_self_type_metadata = type_metadata(cx,
793 let ident = special_idents::type_self;
795 let param_metadata = token::get_ident(ident).get()
798 llvm::LLVMDIBuilderCreateTemplateTypeParameter(
802 actual_self_type_metadata,
809 template_params.push(param_metadata);
813 // Handle other generic parameters
814 let actual_types = match param_substs {
815 Some(param_substs) => ¶m_substs.tys,
817 return create_DIArray(DIB(cx), template_params);
821 for (index, &ast::TyParam{ ident: ident, .. }) in generics.ty_params.iter().enumerate() {
822 let actual_type = actual_types[index];
823 // Add actual type name to <...> clause of function name
824 let actual_type_name = ppaux::ty_to_str(cx.tcx, actual_type);
825 name_to_append_suffix_to.push_str(actual_type_name);
827 if index != generics.ty_params.len() - 1 {
828 name_to_append_suffix_to.push_str(",");
831 // Again, only create type information if full debuginfo is enabled
832 if cx.sess.opts.debuginfo == FullDebugInfo {
833 let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP);
834 let param_metadata = token::get_ident(ident).get()
837 llvm::LLVMDIBuilderCreateTemplateTypeParameter(
841 actual_type_metadata,
847 template_params.push(param_metadata);
851 name_to_append_suffix_to.push_char('>');
853 return create_DIArray(DIB(cx), template_params);
857 //=-------------------------------------------------------------------------------------------------
858 // Module-Internal debug info creation functions
859 //=-------------------------------------------------------------------------------------------------
861 fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
863 llvm::LLVMDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32)
867 fn compile_unit_metadata(cx: &CrateContext) {
868 let work_dir = &cx.sess.working_dir;
869 let compile_unit_name = match cx.sess.local_crate_source_file {
870 None => fallback_path(cx),
871 Some(ref abs_path) => {
872 if abs_path.is_relative() {
873 cx.sess.warn("debuginfo: Invalid path to crate's local root source file!");
876 match abs_path.path_relative_from(work_dir) {
877 Some(ref p) if p.is_relative() => {
878 // prepend "./" if necessary
879 let dotdot = bytes!("..");
880 let prefix = &[dotdot[0], ::std::path::SEP_BYTE];
881 let mut path_bytes = p.as_vec().to_owned();
883 if path_bytes.slice_to(2) != prefix &&
884 path_bytes.slice_to(2) != dotdot {
885 path_bytes.insert(0, prefix[0]);
886 path_bytes.insert(1, prefix[1]);
889 path_bytes.to_c_str()
891 _ => fallback_path(cx)
897 debug!("compile_unit_metadata: {:?}", compile_unit_name);
898 let producer = format!("rustc version {}", env!("CFG_VERSION"));
900 compile_unit_name.with_ref(|compile_unit_name| {
901 work_dir.as_vec().with_c_str(|work_dir| {
902 producer.with_c_str(|producer| {
903 "".with_c_str(|flags| {
904 "".with_c_str(|split_name| {
906 llvm::LLVMDIBuilderCreateCompileUnit(
907 debug_context(cx).builder,
912 cx.sess.opts.optimize != session::No,
923 fn fallback_path(cx: &CrateContext) -> CString {
924 cx.link_meta.crateid.name.to_c_str()
928 fn declare_local(bcx: &Block,
929 variable_ident: ast::Ident,
930 variable_type: ty::t,
931 scope_metadata: DIScope,
932 variable_access: VariableAccess,
933 variable_kind: VariableKind,
935 let cx: &CrateContext = bcx.ccx();
937 let filename = span_start(cx, span).file.name.clone();
938 let file_metadata = file_metadata(cx, filename);
940 let name = token::get_ident(variable_ident);
941 let loc = span_start(cx, span);
942 let type_metadata = type_metadata(cx, variable_type, span);
944 let (argument_index, dwarf_tag) = match variable_kind {
945 ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),
947 CapturedVariable => (0, DW_TAG_auto_variable)
950 let (var_alloca, var_metadata) = name.get().with_c_str(|name| {
951 match variable_access {
952 DirectVariable { alloca } => (
955 llvm::LLVMDIBuilderCreateLocalVariable(
963 cx.sess.opts.optimize != session::No,
968 IndirectVariable { alloca, address_operations } => (
971 llvm::LLVMDIBuilderCreateComplexVariable(
979 address_operations.as_ptr(),
980 address_operations.len() as c_uint,
987 set_debug_location(cx, DebugLocation::new(scope_metadata, loc.line, loc.col.to_uint()));
989 let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
995 llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr);
998 match variable_kind {
999 ArgumentVariable(_) | CapturedVariable => {
1003 .source_locations_enabled
1005 set_debug_location(cx, UnknownLocation);
1007 _ => { /* nothing to do */ }
1011 fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
1013 let created_files = debug_context(cx).created_files.borrow();
1014 match created_files.get().find_equiv(&full_path) {
1015 Some(file_metadata) => return *file_metadata,
1020 debug!("file_metadata: {}", full_path);
1022 // FIXME (#9639): This needs to handle non-utf8 paths
1023 let work_dir = cx.sess.working_dir.as_str().unwrap();
1025 if full_path.starts_with(work_dir) {
1026 full_path.slice(work_dir.len() + 1u, full_path.len())
1032 file_name.with_c_str(|file_name| {
1033 work_dir.with_c_str(|work_dir| {
1035 llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir)
1040 let mut created_files = debug_context(cx).created_files.borrow_mut();
1041 created_files.get().insert(full_path.to_owned(), file_metadata);
1042 return file_metadata;
1045 /// Finds the scope metadata node for the given AST node.
1046 fn scope_metadata(fcx: &FunctionContext,
1047 node_id: ast::NodeId,
1050 let scope_map = &fcx.debug_context.get_ref(fcx.ccx, span).scope_map;
1051 let scope_map = scope_map.borrow();
1053 match scope_map.get().find_copy(&node_id) {
1054 Some(scope_metadata) => scope_metadata,
1056 let node = fcx.ccx.tcx.map.get(node_id);
1058 fcx.ccx.sess.span_bug(span,
1059 format!("debuginfo: Could not find scope info for node {:?}", node));
1064 fn basic_type_metadata(cx: &CrateContext, t: ty::t) -> DIType {
1066 debug!("basic_type_metadata: {:?}", ty::get(t));
1068 let (name, encoding) = match ty::get(t).sty {
1069 ty::ty_nil => (~"()", DW_ATE_unsigned),
1070 ty::ty_bot => (~"!", DW_ATE_unsigned),
1071 ty::ty_bool => (~"bool", DW_ATE_boolean),
1072 ty::ty_char => (~"char", DW_ATE_unsigned_char),
1073 ty::ty_int(int_ty) => match int_ty {
1074 ast::TyI => (~"int", DW_ATE_signed),
1075 ast::TyI8 => (~"i8", DW_ATE_signed),
1076 ast::TyI16 => (~"i16", DW_ATE_signed),
1077 ast::TyI32 => (~"i32", DW_ATE_signed),
1078 ast::TyI64 => (~"i64", DW_ATE_signed)
1080 ty::ty_uint(uint_ty) => match uint_ty {
1081 ast::TyU => (~"uint", DW_ATE_unsigned),
1082 ast::TyU8 => (~"u8", DW_ATE_unsigned),
1083 ast::TyU16 => (~"u16", DW_ATE_unsigned),
1084 ast::TyU32 => (~"u32", DW_ATE_unsigned),
1085 ast::TyU64 => (~"u64", DW_ATE_unsigned)
1087 ty::ty_float(float_ty) => match float_ty {
1088 ast::TyF32 => (~"f32", DW_ATE_float),
1089 ast::TyF64 => (~"f64", DW_ATE_float)
1091 _ => cx.sess.bug("debuginfo::basic_type_metadata - t is invalid type")
1094 let llvm_type = type_of::type_of(cx, t);
1095 let (size, align) = size_and_align_of(cx, llvm_type);
1096 let ty_metadata = name.with_c_str(|name| {
1098 llvm::LLVMDIBuilderCreateBasicType(
1101 bytes_to_bits(size),
1102 bytes_to_bits(align),
1110 fn pointer_type_metadata(cx: &CrateContext,
1111 pointer_type: ty::t,
1112 pointee_type_metadata: DIType)
1114 let pointer_llvm_type = type_of::type_of(cx, pointer_type);
1115 let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
1116 let name = ppaux::ty_to_str(cx.tcx, pointer_type);
1117 let ptr_metadata = name.with_c_str(|name| {
1119 llvm::LLVMDIBuilderCreatePointerType(
1121 pointee_type_metadata,
1122 bytes_to_bits(pointer_size),
1123 bytes_to_bits(pointer_align),
1127 return ptr_metadata;
1130 enum MemberDescriptionFactory {
1131 StructMD(StructMemberDescriptionFactory),
1132 TupleMD(TupleMemberDescriptionFactory),
1133 GeneralMD(GeneralMemberDescriptionFactory),
1134 EnumVariantMD(EnumVariantMemberDescriptionFactory)
1137 impl MemberDescriptionFactory {
1138 fn create_member_descriptions(&self, cx: &CrateContext)
1139 -> ~[MemberDescription] {
1141 StructMD(ref this) => {
1142 this.create_member_descriptions(cx)
1144 TupleMD(ref this) => {
1145 this.create_member_descriptions(cx)
1147 GeneralMD(ref this) => {
1148 this.create_member_descriptions(cx)
1150 EnumVariantMD(ref this) => {
1151 this.create_member_descriptions(cx)
1157 struct StructMemberDescriptionFactory {
1158 fields: ~[ty::field],
1162 impl StructMemberDescriptionFactory {
1163 fn create_member_descriptions(&self, cx: &CrateContext)
1164 -> ~[MemberDescription] {
1165 self.fields.map(|field| {
1166 let name = if field.ident.name == special_idents::unnamed_field.name {
1169 token::get_ident(field.ident).get().to_str()
1174 llvm_type: type_of::type_of(cx, field.mt.ty),
1175 type_metadata: type_metadata(cx, field.mt.ty, self.span),
1176 offset: ComputedMemberOffset,
1182 fn prepare_struct_metadata(cx: &CrateContext,
1185 substs: &ty::substs,
1187 -> RecursiveTypeDescription {
1188 let struct_name = ppaux::ty_to_str(cx.tcx, struct_type);
1189 let struct_llvm_type = type_of::type_of(cx, struct_type);
1191 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id);
1193 let file_name = span_start(cx, definition_span).file.name.clone();
1194 let file_metadata = file_metadata(cx, file_name);
1196 let struct_metadata_stub = create_struct_stub(cx,
1203 let fields = ty::struct_fields(cx.tcx, def_id, substs);
1205 UnfinishedMetadata {
1206 cache_id: cache_id_for_type(struct_type),
1207 metadata_stub: struct_metadata_stub,
1208 llvm_type: struct_llvm_type,
1209 file_metadata: file_metadata,
1210 member_description_factory: StructMD(StructMemberDescriptionFactory {
1217 enum RecursiveTypeDescription {
1218 UnfinishedMetadata {
1220 metadata_stub: DICompositeType,
1222 file_metadata: DIFile,
1223 member_description_factory: MemberDescriptionFactory,
1225 FinalMetadata(DICompositeType)
1228 impl RecursiveTypeDescription {
1230 fn finalize(&self, cx: &CrateContext) -> DICompositeType {
1232 FinalMetadata(metadata) => metadata,
1233 UnfinishedMetadata {
1238 ref member_description_factory
1240 // Insert the stub into the cache in order to allow recursive references ...
1242 let mut created_types = debug_context(cx).created_types.borrow_mut();
1243 created_types.get().insert(cache_id, metadata_stub);
1246 // ... then create the member descriptions ...
1247 let member_descriptions = member_description_factory.create_member_descriptions(cx);
1249 // ... and attach them to the stub to complete it.
1250 set_members_of_composite_type(cx,
1253 member_descriptions,
1256 return metadata_stub;
1262 struct TupleMemberDescriptionFactory {
1263 component_types: ~[ty::t],
1267 impl TupleMemberDescriptionFactory {
1268 fn create_member_descriptions(&self, cx: &CrateContext)
1269 -> ~[MemberDescription] {
1270 self.component_types.map(|&component_type| {
1273 llvm_type: type_of::type_of(cx, component_type),
1274 type_metadata: type_metadata(cx, component_type, self.span),
1275 offset: ComputedMemberOffset,
1281 fn prepare_tuple_metadata(cx: &CrateContext,
1283 component_types: &[ty::t],
1285 -> RecursiveTypeDescription {
1286 let tuple_name = ppaux::ty_to_str(cx.tcx, tuple_type);
1287 let tuple_llvm_type = type_of::type_of(cx, tuple_type);
1289 let loc = span_start(cx, span);
1290 let file_metadata = file_metadata(cx, loc.file.name);
1292 UnfinishedMetadata {
1293 cache_id: cache_id_for_type(tuple_type),
1294 metadata_stub: create_struct_stub(cx,
1300 llvm_type: tuple_llvm_type,
1301 file_metadata: file_metadata,
1302 member_description_factory: TupleMD(TupleMemberDescriptionFactory {
1303 component_types: component_types.to_owned(),
1309 struct GeneralMemberDescriptionFactory {
1310 type_rep: @adt::Repr,
1311 variants: @~[@ty::VariantInfo],
1312 discriminant_type_metadata: ValueRef,
1313 containing_scope: DIScope,
1314 file_metadata: DIFile,
1318 impl GeneralMemberDescriptionFactory {
1319 fn create_member_descriptions(&self, cx: &CrateContext)
1320 -> ~[MemberDescription] {
1321 // Capture type_rep, so we don't have to copy the struct_defs array
1322 let struct_defs = match *self.type_rep {
1323 adt::General(_, ref struct_defs) => struct_defs,
1324 _ => cx.sess.bug("unreachable")
1330 .map(|(i, struct_def)| {
1331 let (variant_type_metadata, variant_llvm_type, member_desc_factory) =
1332 describe_enum_variant(cx,
1335 Some(self.discriminant_type_metadata),
1336 self.containing_scope,
1340 let member_descriptions =
1341 member_desc_factory.create_member_descriptions(cx);
1343 set_members_of_composite_type(cx,
1344 variant_type_metadata,
1346 member_descriptions,
1351 llvm_type: variant_llvm_type,
1352 type_metadata: variant_type_metadata,
1353 offset: FixedMemberOffset { bytes: 0 },
1359 struct EnumVariantMemberDescriptionFactory {
1360 args: ~[(~str, ty::t)],
1361 discriminant_type_metadata: Option<DIType>,
1365 impl EnumVariantMemberDescriptionFactory {
1366 fn create_member_descriptions(&self, cx: &CrateContext)
1367 -> ~[MemberDescription] {
1368 self.args.iter().enumerate().map(|(i, &(ref name, ty))| {
1370 name: name.to_str(),
1371 llvm_type: type_of::type_of(cx, ty),
1372 type_metadata: match self.discriminant_type_metadata {
1373 Some(metadata) if i == 0 => metadata,
1374 _ => type_metadata(cx, ty, self.span)
1376 offset: ComputedMemberOffset,
1382 fn describe_enum_variant(cx: &CrateContext,
1383 struct_def: &adt::Struct,
1384 variant_info: &ty::VariantInfo,
1385 discriminant_type_metadata: Option<DIType>,
1386 containing_scope: DIScope,
1387 file_metadata: DIFile,
1389 -> (DICompositeType, Type, MemberDescriptionFactory) {
1390 let variant_llvm_type = Type::struct_(struct_def.fields.map(|&t| type_of::type_of(cx, t)),
1392 // Could some consistency checks here: size, align, field count, discr type
1394 // Find the source code location of the variant's definition
1395 let variant_definition_span = if variant_info.id.krate == ast::LOCAL_CRATE {
1396 cx.tcx.map.span(variant_info.id.node)
1398 // For definitions from other crates we have no location information available.
1402 let metadata_stub = create_struct_stub(cx,
1404 token::get_ident(variant_info.name).get(),
1407 variant_definition_span);
1409 // Get the argument names from the enum variant info
1410 let mut arg_names = match variant_info.arg_names {
1411 Some(ref names) => {
1412 names.map(|ident| token::get_ident(*ident).get().to_str())
1414 None => variant_info.args.map(|_| ~"")
1417 // If this is not a univariant enum, there is also the (unnamed) discriminant field
1418 if discriminant_type_metadata.is_some() {
1419 arg_names.insert(0, ~"");
1422 // Build an array of (field name, field type) pairs to be captured in the factory closure.
1423 let args: ~[(~str, ty::t)] = arg_names.iter()
1424 .zip(struct_def.fields.iter())
1425 .map(|(s, &t)| (s.to_str(), t))
1428 let member_description_factory =
1429 EnumVariantMD(EnumVariantMemberDescriptionFactory {
1431 discriminant_type_metadata: discriminant_type_metadata,
1435 (metadata_stub, variant_llvm_type, member_description_factory)
1438 fn prepare_enum_metadata(cx: &CrateContext,
1440 enum_def_id: ast::DefId,
1442 -> RecursiveTypeDescription {
1443 let enum_name = ppaux::ty_to_str(cx.tcx, enum_type);
1445 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, enum_def_id);
1446 let loc = span_start(cx, definition_span);
1447 let file_metadata = file_metadata(cx, loc.file.name);
1449 // For empty enums there is an early exit. Just describe it as an empty struct with the
1450 // appropriate type name
1451 if ty::type_is_empty(cx.tcx, enum_type) {
1452 let empty_type_metadata = composite_type_metadata(cx,
1460 return FinalMetadata(empty_type_metadata);
1463 let variants = ty::enum_variants(cx.tcx, enum_def_id);
1465 let enumerators_metadata: ~[DIDescriptor] = variants
1468 token::get_ident(v.name).get().with_c_str(|name| {
1470 llvm::LLVMDIBuilderCreateEnumerator(
1473 v.disr_val as c_ulonglong)
1479 let discriminant_type_metadata = |inttype| {
1480 let discriminant_llvm_type = adt::ll_inttype(cx, inttype);
1481 let (discriminant_size, discriminant_align) = size_and_align_of(cx, discriminant_llvm_type);
1482 let discriminant_base_type_metadata = type_metadata(cx, adt::ty_of_inttype(inttype),
1484 enum_name.with_c_str(|enum_name| {
1486 llvm::LLVMDIBuilderCreateEnumerationType(
1492 bytes_to_bits(discriminant_size),
1493 bytes_to_bits(discriminant_align),
1494 create_DIArray(DIB(cx), enumerators_metadata),
1495 discriminant_base_type_metadata)
1500 let type_rep = adt::represent_type(cx, enum_type);
1502 return match *type_rep {
1503 adt::CEnum(inttype, _, _) => {
1504 FinalMetadata(discriminant_type_metadata(inttype))
1506 adt::Univariant(ref struct_def, _) => {
1507 assert!(variants.len() == 1);
1510 member_description_factory) = describe_enum_variant(cx,
1517 UnfinishedMetadata {
1518 cache_id: cache_id_for_type(enum_type),
1519 metadata_stub: metadata_stub,
1520 llvm_type: variant_llvm_type,
1521 file_metadata: file_metadata,
1522 member_description_factory: member_description_factory
1525 adt::General(inttype, _) => {
1526 let discriminant_type_metadata = discriminant_type_metadata(inttype);
1527 let enum_llvm_type = type_of::type_of(cx, enum_type);
1528 let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type);
1529 let unique_id = generate_unique_type_id("DI_ENUM_");
1531 let enum_metadata = enum_name.with_c_str(|enum_name| {
1532 unique_id.with_c_str(|unique_id| {
1534 llvm::LLVMDIBuilderCreateUnionType(
1540 bytes_to_bits(enum_type_size),
1541 bytes_to_bits(enum_type_align),
1550 UnfinishedMetadata {
1551 cache_id: cache_id_for_type(enum_type),
1552 metadata_stub: enum_metadata,
1553 llvm_type: enum_llvm_type,
1554 file_metadata: file_metadata,
1555 member_description_factory: GeneralMD(GeneralMemberDescriptionFactory {
1558 discriminant_type_metadata: discriminant_type_metadata,
1559 containing_scope: containing_scope,
1560 file_metadata: file_metadata,
1565 adt::NullablePointer { nonnull: ref struct_def, nndiscr, .. } => {
1568 member_description_factory) = describe_enum_variant(cx,
1575 UnfinishedMetadata {
1576 cache_id: cache_id_for_type(enum_type),
1577 metadata_stub: metadata_stub,
1578 llvm_type: variant_llvm_type,
1579 file_metadata: file_metadata,
1580 member_description_factory: member_description_factory
1587 FixedMemberOffset { bytes: uint },
1588 // For ComputedMemberOffset, the offset is read from the llvm type definition
1589 ComputedMemberOffset
1592 struct MemberDescription {
1595 type_metadata: DIType,
1596 offset: MemberOffset,
1599 /// Creates debug information for a composite type, that is, anything that results in a LLVM struct.
1601 /// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums.
1602 fn composite_type_metadata(cx: &CrateContext,
1603 composite_llvm_type: Type,
1604 composite_type_name: &str,
1605 member_descriptions: &[MemberDescription],
1606 containing_scope: DIScope,
1607 file_metadata: DIFile,
1608 definition_span: Span)
1609 -> DICompositeType {
1610 // Create the (empty) struct metadata node ...
1611 let composite_type_metadata = create_struct_stub(cx,
1612 composite_llvm_type,
1613 composite_type_name,
1618 // ... and immediately create and add the member descriptions.
1619 set_members_of_composite_type(cx,
1620 composite_type_metadata,
1621 composite_llvm_type,
1622 member_descriptions,
1626 return composite_type_metadata;
1629 fn set_members_of_composite_type(cx: &CrateContext,
1630 composite_type_metadata: DICompositeType,
1631 composite_llvm_type: Type,
1632 member_descriptions: &[MemberDescription],
1633 file_metadata: DIFile,
1634 definition_span: Span) {
1635 // In some rare cases LLVM metadata uniquing would lead to an existing type description being
1636 // used instead of a new one created in create_struct_stub. This would cause a hard to trace
1637 // assertion in DICompositeType::SetTypeArray(). The following check makes sure that we get a
1638 // better error message if this should happen again due to some regression.
1640 let mut composite_types_completed =
1641 debug_context(cx).composite_types_completed.borrow_mut();
1642 if composite_types_completed.get().contains(&composite_type_metadata) {
1643 cx.sess.span_bug(definition_span, "debuginfo::set_members_of_composite_type() - \
1644 Already completed forward declaration \
1647 composite_types_completed.get().insert(composite_type_metadata);
1651 let loc = span_start(cx, definition_span);
1653 let member_metadata: ~[DIDescriptor] = member_descriptions
1656 .map(|(i, member_description)| {
1657 let (member_size, member_align) = size_and_align_of(cx, member_description.llvm_type);
1658 let member_offset = match member_description.offset {
1659 FixedMemberOffset { bytes } => bytes as u64,
1660 ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i)
1663 member_description.name.with_c_str(|member_name| {
1665 llvm::LLVMDIBuilderCreateMemberType(
1667 composite_type_metadata,
1671 bytes_to_bits(member_size),
1672 bytes_to_bits(member_align),
1673 bytes_to_bits(member_offset),
1675 member_description.type_metadata)
1682 let type_array = create_DIArray(DIB(cx), member_metadata);
1683 llvm::LLVMDICompositeTypeSetTypeArray(composite_type_metadata, type_array);
1687 // A convenience wrapper around LLVMDIBuilderCreateStructType(). Does not do any caching, does not
1688 // add any fields to the struct. This can be done later with set_members_of_composite_type().
1689 fn create_struct_stub(cx: &CrateContext,
1690 struct_llvm_type: Type,
1691 struct_type_name: &str,
1692 containing_scope: DIScope,
1693 file_metadata: DIFile,
1694 definition_span: Span)
1695 -> DICompositeType {
1696 let loc = span_start(cx, definition_span);
1697 let (struct_size, struct_align) = size_and_align_of(cx, struct_llvm_type);
1699 // We assign unique IDs to the type stubs so LLVM metadata uniquing does not reuse instances
1700 // where we don't want it.
1701 let unique_id = generate_unique_type_id("DI_STRUCT_");
1704 struct_type_name.with_c_str(|name| {
1705 unique_id.with_c_str(|unique_id| {
1706 // LLVMDIBuilderCreateStructType() wants an empty array. A null pointer will lead to
1707 // hard to trace and debug LLVM assertions later on in llvm/lib/IR/Value.cpp
1708 let empty_array = create_DIArray(DIB(cx), []);
1710 llvm::LLVMDIBuilderCreateStructType(
1716 bytes_to_bits(struct_size),
1717 bytes_to_bits(struct_align),
1729 fn boxed_type_metadata(cx: &CrateContext,
1730 content_type_name: Option<&str>,
1731 content_llvm_type: Type,
1732 content_type_metadata: DIType,
1734 -> DICompositeType {
1735 let box_type_name = match content_type_name {
1736 Some(content_type_name) => format!("Boxed<{}>", content_type_name),
1737 None => ~"BoxedType"
1740 let box_llvm_type = Type::at_box(cx, content_llvm_type);
1741 let member_llvm_types = box_llvm_type.field_types();
1742 assert!(box_layout_is_correct(cx, member_llvm_types, content_llvm_type));
1744 let int_type = ty::mk_int();
1745 let nil_pointer_type = ty::mk_nil_ptr(cx.tcx);
1746 let nil_pointer_type_metadata = type_metadata(cx, nil_pointer_type, codemap::DUMMY_SP);
1748 let member_descriptions = [
1751 llvm_type: member_llvm_types[0],
1752 type_metadata: type_metadata(cx, int_type, codemap::DUMMY_SP),
1753 offset: ComputedMemberOffset,
1757 llvm_type: member_llvm_types[1],
1758 type_metadata: nil_pointer_type_metadata,
1759 offset: ComputedMemberOffset,
1763 llvm_type: member_llvm_types[2],
1764 type_metadata: nil_pointer_type_metadata,
1765 offset: ComputedMemberOffset,
1769 llvm_type: member_llvm_types[3],
1770 type_metadata: nil_pointer_type_metadata,
1771 offset: ComputedMemberOffset,
1775 llvm_type: member_llvm_types[4],
1776 type_metadata: content_type_metadata,
1777 offset: ComputedMemberOffset,
1781 let loc = span_start(cx, span);
1782 let file_metadata = file_metadata(cx, loc.file.name);
1784 return composite_type_metadata(
1788 member_descriptions,
1793 // Unfortunately, we cannot assert anything but the correct types here---and not whether the
1794 // 'next' and 'prev' pointers are in the correct order.
1795 fn box_layout_is_correct(cx: &CrateContext,
1796 member_llvm_types: &[Type],
1797 content_llvm_type: Type)
1799 member_llvm_types.len() == 5 &&
1800 member_llvm_types[0] == cx.int_type &&
1801 member_llvm_types[1] == Type::generic_glue_fn(cx).ptr_to() &&
1802 member_llvm_types[2] == Type::i8().ptr_to() &&
1803 member_llvm_types[3] == Type::i8().ptr_to() &&
1804 member_llvm_types[4] == content_llvm_type
1808 fn fixed_vec_metadata(cx: &CrateContext,
1809 element_type: ty::t,
1813 let element_type_metadata = type_metadata(cx, element_type, span);
1814 let element_llvm_type = type_of::type_of(cx, element_type);
1815 let (element_type_size, element_type_align) = size_and_align_of(cx, element_llvm_type);
1817 let subrange = unsafe {
1818 llvm::LLVMDIBuilderGetOrCreateSubrange(
1824 let subscripts = create_DIArray(DIB(cx), [subrange]);
1826 llvm::LLVMDIBuilderCreateArrayType(
1828 bytes_to_bits(element_type_size * (len as u64)),
1829 bytes_to_bits(element_type_align),
1830 element_type_metadata,
1835 fn vec_metadata(cx: &CrateContext,
1836 element_type: ty::t,
1838 -> DICompositeType {
1840 let element_type_metadata = type_metadata(cx, element_type, span);
1841 let element_llvm_type = type_of::type_of(cx, element_type);
1842 let (element_size, element_align) = size_and_align_of(cx, element_llvm_type);
1844 let vec_llvm_type = Type::vec(cx.sess.targ_cfg.arch, &element_llvm_type);
1845 let vec_type_name: &str = format!("[{}]", ppaux::ty_to_str(cx.tcx, element_type));
1847 let member_llvm_types = vec_llvm_type.field_types();
1849 let int_type_metadata = type_metadata(cx, ty::mk_int(), span);
1850 let array_type_metadata = unsafe {
1851 llvm::LLVMDIBuilderCreateArrayType(
1853 bytes_to_bits(element_size),
1854 bytes_to_bits(element_align),
1855 element_type_metadata,
1856 create_DIArray(DIB(cx), [llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, 0)]))
1859 let member_descriptions = [
1862 llvm_type: member_llvm_types[0],
1863 type_metadata: int_type_metadata,
1864 offset: ComputedMemberOffset,
1868 llvm_type: member_llvm_types[1],
1869 type_metadata: int_type_metadata,
1870 offset: ComputedMemberOffset,
1874 llvm_type: member_llvm_types[2],
1875 type_metadata: array_type_metadata,
1876 offset: ComputedMemberOffset,
1880 assert!(member_descriptions.len() == member_llvm_types.len());
1882 let loc = span_start(cx, span);
1883 let file_metadata = file_metadata(cx, loc.file.name);
1885 return composite_type_metadata(
1889 member_descriptions,
1895 fn vec_slice_metadata(cx: &CrateContext,
1897 element_type: ty::t,
1899 -> DICompositeType {
1901 debug!("vec_slice_metadata: {:?}", ty::get(vec_type));
1903 let slice_llvm_type = type_of::type_of(cx, vec_type);
1904 let slice_type_name = ppaux::ty_to_str(cx.tcx, vec_type);
1906 let member_llvm_types = slice_llvm_type.field_types();
1907 assert!(slice_layout_is_correct(cx, member_llvm_types, element_type));
1909 let data_ptr_type = ty::mk_ptr(cx.tcx, ty::mt { ty: element_type, mutbl: ast::MutImmutable });
1911 let member_descriptions = [
1914 llvm_type: member_llvm_types[0],
1915 type_metadata: type_metadata(cx, data_ptr_type, span),
1916 offset: ComputedMemberOffset,
1920 llvm_type: member_llvm_types[1],
1921 type_metadata: type_metadata(cx, ty::mk_uint(), span),
1922 offset: ComputedMemberOffset,
1926 assert!(member_descriptions.len() == member_llvm_types.len());
1928 let loc = span_start(cx, span);
1929 let file_metadata = file_metadata(cx, loc.file.name);
1931 return composite_type_metadata(
1935 member_descriptions,
1940 fn slice_layout_is_correct(cx: &CrateContext,
1941 member_llvm_types: &[Type],
1942 element_type: ty::t)
1944 member_llvm_types.len() == 2 &&
1945 member_llvm_types[0] == type_of::type_of(cx, element_type).ptr_to() &&
1946 member_llvm_types[1] == cx.int_type
1950 fn subroutine_type_metadata(cx: &CrateContext,
1951 signature: &ty::FnSig,
1953 -> DICompositeType {
1954 let loc = span_start(cx, span);
1955 let file_metadata = file_metadata(cx, loc.file.name);
1957 let mut signature_metadata: ~[DIType] = vec::with_capacity(signature.inputs.len() + 1);
1960 signature_metadata.push(match ty::get(signature.output).sty {
1961 ty::ty_nil => ptr::null(),
1962 _ => type_metadata(cx, signature.output, span)
1965 // regular arguments
1966 for &argument_type in signature.inputs.iter() {
1967 signature_metadata.push(type_metadata(cx, argument_type, span));
1971 llvm::LLVMDIBuilderCreateSubroutineType(
1974 create_DIArray(DIB(cx), signature_metadata))
1978 fn trait_metadata(cx: &CrateContext,
1981 substs: &ty::substs,
1982 trait_store: ty::TraitStore,
1983 mutability: ast::Mutability,
1984 _: &ty::BuiltinBounds)
1986 // The implementation provided here is a stub. It makes sure that the trait type is
1987 // assigned the correct name, size, namespace, and source location. But it does not describe
1988 // the trait's methods.
1989 let last = ty::with_path(cx.tcx, def_id, |mut path| path.last().unwrap());
1990 let ident_string = token::get_name(last.name());
1991 let name = ppaux::trait_store_to_str(cx.tcx, trait_store) +
1992 ppaux::mutability_to_str(mutability) +
1994 // Add type and region parameters
1995 let name = ppaux::parameterized(cx.tcx, name, &substs.regions,
1996 substs.tps, def_id, true);
1998 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id);
2000 let file_name = span_start(cx, definition_span).file.name.clone();
2001 let file_metadata = file_metadata(cx, file_name);
2003 let trait_llvm_type = type_of::type_of(cx, trait_type);
2005 return composite_type_metadata(cx,
2014 fn type_metadata(cx: &CrateContext,
2016 usage_site_span: Span)
2018 let cache_id = cache_id_for_type(t);
2021 let created_types = debug_context(cx).created_types.borrow();
2022 match created_types.get().find(&cache_id) {
2023 Some(type_metadata) => return *type_metadata,
2028 fn create_pointer_to_box_metadata(cx: &CrateContext,
2029 pointer_type: ty::t,
2032 let content_type_name: &str = ppaux::ty_to_str(cx.tcx, type_in_box);
2033 let content_llvm_type = type_of::type_of(cx, type_in_box);
2034 let content_type_metadata = type_metadata(
2039 let box_metadata = boxed_type_metadata(
2041 Some(content_type_name),
2043 content_type_metadata,
2046 pointer_type_metadata(cx, pointer_type, box_metadata)
2049 debug!("type_metadata: {:?}", ty::get(t));
2051 let sty = &ty::get(t).sty;
2052 let type_metadata = match *sty {
2059 ty::ty_float(_) => {
2060 basic_type_metadata(cx, t)
2062 ty::ty_str(ref vstore) => {
2063 let i8_t = ty::mk_i8();
2065 ty::vstore_fixed(len) => {
2066 fixed_vec_metadata(cx, i8_t, len + 1, usage_site_span)
2068 ty::vstore_uniq => {
2069 let vec_metadata = vec_metadata(cx, i8_t, usage_site_span);
2070 pointer_type_metadata(cx, t, vec_metadata)
2072 ty::vstore_slice(_region) => {
2073 vec_slice_metadata(cx, t, i8_t, usage_site_span)
2077 ty::ty_enum(def_id, _) => {
2078 prepare_enum_metadata(cx, t, def_id, usage_site_span).finalize(cx)
2080 ty::ty_box(typ) => {
2081 create_pointer_to_box_metadata(cx, t, typ)
2083 ty::ty_vec(ref mt, ref vstore) => {
2085 ty::vstore_fixed(len) => {
2086 fixed_vec_metadata(cx, mt.ty, len, usage_site_span)
2088 ty::vstore_uniq => {
2089 let vec_metadata = vec_metadata(cx, mt.ty, usage_site_span);
2090 pointer_type_metadata(cx, t, vec_metadata)
2092 ty::vstore_slice(_) => {
2093 vec_slice_metadata(cx, t, mt.ty, usage_site_span)
2097 ty::ty_uniq(typ) => {
2098 let pointee = type_metadata(cx, typ, usage_site_span);
2099 pointer_type_metadata(cx, t, pointee)
2101 ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => {
2102 let pointee = type_metadata(cx, mt.ty, usage_site_span);
2103 pointer_type_metadata(cx, t, pointee)
2105 ty::ty_bare_fn(ref barefnty) => {
2106 subroutine_type_metadata(cx, &barefnty.sig, usage_site_span)
2108 ty::ty_closure(ref closurety) => {
2109 subroutine_type_metadata(cx, &closurety.sig, usage_site_span)
2111 ty::ty_trait(def_id, ref substs, trait_store, mutability, ref bounds) => {
2112 trait_metadata(cx, def_id, t, substs, trait_store, mutability, bounds)
2114 ty::ty_struct(def_id, ref substs) => {
2115 if ty::type_is_simd(cx.tcx, t) {
2116 let element_type = ty::simd_type(cx.tcx, t);
2117 let len = ty::simd_size(cx.tcx, t);
2118 fixed_vec_metadata(cx, element_type, len, usage_site_span)
2120 prepare_struct_metadata(cx, t, def_id, substs, usage_site_span).finalize(cx)
2123 ty::ty_tup(ref elements) => {
2124 prepare_tuple_metadata(cx, t, *elements, usage_site_span).finalize(cx)
2126 _ => cx.sess.bug(format!("debuginfo: unexpected type in type_metadata: {:?}", sty))
2129 let mut created_types = debug_context(cx).created_types.borrow_mut();
2130 created_types.get().insert(cache_id, type_metadata);
2135 enum DebugLocation {
2136 KnownLocation { scope: DIScope, line: uint, col: uint },
2140 impl DebugLocation {
2141 fn new(scope: DIScope, line: uint, col: uint) -> DebugLocation {
2150 fn set_debug_location(cx: &CrateContext, debug_location: DebugLocation) {
2151 if debug_location == debug_context(cx).current_debug_location.get() {
2157 match debug_location {
2158 KnownLocation { scope, line, .. } => {
2159 let col = 0; // Always set the column to zero like Clang and GCC
2160 debug!("setting debug location to {} {}", line, col);
2161 let elements = [C_i32(line as i32), C_i32(col as i32), scope, ptr::null()];
2163 metadata_node = llvm::LLVMMDNodeInContext(debug_context(cx).llcontext,
2165 elements.len() as c_uint);
2168 UnknownLocation => {
2169 debug!("clearing debug location ");
2170 metadata_node = ptr::null();
2175 llvm::LLVMSetCurrentDebugLocation(cx.builder.b, metadata_node);
2178 debug_context(cx).current_debug_location.set(debug_location);
2181 //=-------------------------------------------------------------------------------------------------
2182 // Utility Functions
2183 //=-------------------------------------------------------------------------------------------------
2185 fn cache_id_for_type(t: ty::t) -> uint {
2189 // Used to avoid LLVM metadata uniquing problems. See `create_struct_stub()` and
2190 // `prepare_enum_metadata()`.
2191 fn generate_unique_type_id(prefix: &'static str) -> ~str {
2193 static mut unique_id_counter: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;
2194 format!("{}{}", prefix, unique_id_counter.fetch_add(1, atomics::SeqCst))
2198 /// Return codemap::Loc corresponding to the beginning of the span
2199 fn span_start(cx: &CrateContext, span: Span) -> codemap::Loc {
2200 cx.sess.codemap.lookup_char_pos(span.lo)
2203 fn size_and_align_of(cx: &CrateContext, llvm_type: Type) -> (u64, u64) {
2204 (machine::llsize_of_alloc(cx, llvm_type), machine::llalign_of_min(cx, llvm_type))
2207 fn bytes_to_bits(bytes: u64) -> c_ulonglong {
2208 (bytes * 8) as c_ulonglong
2212 fn debug_context<'a>(cx: &'a CrateContext) -> &'a CrateDebugContext {
2213 let debug_context: &'a CrateDebugContext = cx.dbg_cx.get_ref();
2218 fn DIB(cx: &CrateContext) -> DIBuilderRef {
2219 cx.dbg_cx.get_ref().builder
2222 fn fn_should_be_ignored(fcx: &FunctionContext) -> bool {
2223 match fcx.debug_context {
2224 FunctionDebugContext(_) => false,
2229 fn assert_type_for_node_id(cx: &CrateContext, node_id: ast::NodeId, error_span: Span) {
2230 let node_types = cx.tcx.node_types.borrow();
2231 if !node_types.get().contains_key(&(node_id as uint)) {
2232 cx.sess.span_bug(error_span, "debuginfo: Could not find type for node id!");
2236 fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: ast::DefId)
2237 -> (DIScope, Span) {
2238 let containing_scope = namespace_for_item(cx, def_id).scope;
2239 let definition_span = if def_id.krate == ast::LOCAL_CRATE {
2240 cx.tcx.map.span(def_id.node)
2242 // For external items there is no span information
2246 (containing_scope, definition_span)
2249 // This procedure builds the *scope map* for a given function, which maps any given ast::NodeId in
2250 // the function's AST to the correct DIScope metadata instance.
2252 // This builder procedure walks the AST in execution order and keeps track of what belongs to which
2253 // scope, creating DIScope DIEs along the way, and introducing *artificial* lexical scope
2254 // descriptors where necessary. These artificial scopes allow GDB to correctly handle name
2256 fn populate_scope_map(cx: &CrateContext,
2257 arg_pats: &[@ast::Pat],
2258 fn_entry_block: &ast::Block,
2259 fn_metadata: DISubprogram,
2260 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2261 let def_map = cx.tcx.def_map;
2263 struct ScopeStackEntry {
2264 scope_metadata: DIScope,
2265 ident: Option<ast::Ident>
2268 let mut scope_stack = ~[ScopeStackEntry { scope_metadata: fn_metadata, ident: None }];
2270 // Push argument identifiers onto the stack so arguments integrate nicely with variable
2272 for &arg_pat in arg_pats.iter() {
2273 pat_util::pat_bindings(def_map, arg_pat, |_, _, _, path_ref| {
2274 let ident = ast_util::path_to_ident(path_ref);
2275 scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata, ident: Some(ident) });
2279 // Clang creates a separate scope for function bodies, so let's do this too
2281 fn_entry_block.span,
2284 |cx, scope_stack, scope_map| {
2285 walk_block(cx, fn_entry_block, scope_stack, scope_map);
2288 // local helper functions for walking the AST.
2289 fn with_new_scope(cx: &CrateContext,
2291 scope_stack: &mut ~[ScopeStackEntry],
2292 scope_map: &mut HashMap<ast::NodeId, DIScope>,
2293 inner_walk: |&CrateContext,
2294 &mut ~[ScopeStackEntry],
2295 &mut HashMap<ast::NodeId, DIScope>|) {
2296 // Create a new lexical scope and push it onto the stack
2297 let loc = cx.sess.codemap.lookup_char_pos(scope_span.lo);
2298 let file_metadata = file_metadata(cx, loc.file.name);
2299 let parent_scope = scope_stack.last().unwrap().scope_metadata;
2301 let scope_metadata = unsafe {
2302 llvm::LLVMDIBuilderCreateLexicalBlock(
2307 loc.col.to_uint() as c_uint)
2310 scope_stack.push(ScopeStackEntry { scope_metadata: scope_metadata, ident: None });
2312 inner_walk(cx, scope_stack, scope_map);
2314 // pop artificial scopes
2315 while scope_stack.last().unwrap().ident.is_some() {
2319 if scope_stack.last().unwrap().scope_metadata != scope_metadata {
2320 cx.sess.span_bug(scope_span, "debuginfo: Inconsistency in scope management.");
2326 fn walk_block(cx: &CrateContext,
2328 scope_stack: &mut ~[ScopeStackEntry],
2329 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2330 scope_map.insert(block.id, scope_stack.last().unwrap().scope_metadata);
2332 // The interesting things here are statements and the concluding expression.
2333 for statement in block.stmts.iter() {
2334 scope_map.insert(ast_util::stmt_id(*statement),
2335 scope_stack.last().unwrap().scope_metadata);
2337 match statement.node {
2338 ast::StmtDecl(decl, _) => walk_decl(cx, decl, scope_stack, scope_map),
2339 ast::StmtExpr(exp, _) |
2340 ast::StmtSemi(exp, _) => walk_expr(cx, exp, scope_stack, scope_map),
2341 ast::StmtMac(..) => () // ignore macros (which should be expanded anyway)
2345 for exp in block.expr.iter() {
2346 walk_expr(cx, *exp, scope_stack, scope_map);
2350 fn walk_decl(cx: &CrateContext,
2352 scope_stack: &mut ~[ScopeStackEntry],
2353 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2355 codemap::Spanned { node: ast::DeclLocal(local), .. } => {
2356 scope_map.insert(local.id, scope_stack.last().unwrap().scope_metadata);
2358 walk_pattern(cx, local.pat, scope_stack, scope_map);
2360 for exp in local.init.iter() {
2361 walk_expr(cx, *exp, scope_stack, scope_map);
2368 fn walk_pattern(cx: &CrateContext,
2370 scope_stack: &mut ~[ScopeStackEntry],
2371 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2373 let def_map = cx.tcx.def_map;
2375 // Unfortunately, we cannot just use pat_util::pat_bindings() or ast_util::walk_pat() here
2376 // because we have to visit *all* nodes in order to put them into the scope map. The above
2377 // functions don't do that.
2379 ast::PatIdent(_, ref path_ref, ref sub_pat_opt) => {
2381 // Check if this is a binding. If so we need to put it on the scope stack and maybe
2382 // introduce an articial scope
2383 if pat_util::pat_is_binding(def_map, pat) {
2385 let ident = ast_util::path_to_ident(path_ref);
2387 // LLVM does not properly generate 'DW_AT_start_scope' fields for variable DIEs.
2388 // For this reason we have to introduce an artificial scope at bindings whenever
2389 // a variable with the same name is declared in *any* parent scope.
2391 // Otherwise the following error occurs:
2395 // do_something(); // 'gdb print x' correctly prints 10
2398 // do_something(); // 'gdb print x' prints 0, because it already reads the
2399 // // uninitialized 'x' from the next line...
2401 // do_something(); // 'gdb print x' correctly prints 100
2404 // Is there already a binding with that name?
2405 // N.B.: this comparison must be UNhygienic... because
2406 // gdb knows nothing about the context, so any two
2407 // variables with the same name will cause the problem.
2408 let need_new_scope = scope_stack
2410 .any(|entry| entry.ident.iter().any(|i| i.name == ident.name));
2413 // Create a new lexical scope and push it onto the stack
2414 let loc = cx.sess.codemap.lookup_char_pos(pat.span.lo);
2415 let file_metadata = file_metadata(cx, loc.file.name);
2416 let parent_scope = scope_stack.last().unwrap().scope_metadata;
2418 let scope_metadata = unsafe {
2419 llvm::LLVMDIBuilderCreateLexicalBlock(
2424 loc.col.to_uint() as c_uint)
2427 scope_stack.push(ScopeStackEntry {
2428 scope_metadata: scope_metadata,
2433 // Push a new entry anyway so the name can be found
2434 let prev_metadata = scope_stack.last().unwrap().scope_metadata;
2435 scope_stack.push(ScopeStackEntry {
2436 scope_metadata: prev_metadata,
2442 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2444 for &sub_pat in sub_pat_opt.iter() {
2445 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2449 ast::PatWild | ast::PatWildMulti => {
2450 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2453 ast::PatEnum(_, ref sub_pats_opt) => {
2454 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2456 for ref sub_pats in sub_pats_opt.iter() {
2457 for &p in sub_pats.iter() {
2458 walk_pattern(cx, p, scope_stack, scope_map);
2463 ast::PatStruct(_, ref field_pats, _) => {
2464 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2466 for &ast::FieldPat { pat: sub_pat, .. } in field_pats.iter() {
2467 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2471 ast::PatTup(ref sub_pats) => {
2472 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2474 for &sub_pat in sub_pats.iter() {
2475 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2479 ast::PatUniq(sub_pat) | ast::PatRegion(sub_pat) => {
2480 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2481 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2484 ast::PatLit(exp) => {
2485 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2486 walk_expr(cx, exp, scope_stack, scope_map);
2489 ast::PatRange(exp1, exp2) => {
2490 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2491 walk_expr(cx, exp1, scope_stack, scope_map);
2492 walk_expr(cx, exp2, scope_stack, scope_map);
2495 ast::PatVec(ref front_sub_pats, ref middle_sub_pats, ref back_sub_pats) => {
2496 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2498 for &sub_pat in front_sub_pats.iter() {
2499 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2502 for &sub_pat in middle_sub_pats.iter() {
2503 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2506 for &sub_pat in back_sub_pats.iter() {
2507 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2513 fn walk_expr(cx: &CrateContext,
2515 scope_stack: &mut ~[ScopeStackEntry],
2516 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2518 scope_map.insert(exp.id, scope_stack.last().unwrap().scope_metadata);
2525 ast::ExprPath(_) => {}
2527 ast::ExprVstore(sub_exp, _) |
2528 ast::ExprCast(sub_exp, _) |
2529 ast::ExprAddrOf(_, sub_exp) |
2530 ast::ExprField(sub_exp, _, _) |
2531 ast::ExprParen(sub_exp) => walk_expr(cx, sub_exp, scope_stack, scope_map),
2533 ast::ExprBox(place, sub_expr) => {
2534 walk_expr(cx, place, scope_stack, scope_map);
2535 walk_expr(cx, sub_expr, scope_stack, scope_map);
2538 ast::ExprRet(exp_opt) => match exp_opt {
2539 Some(sub_exp) => walk_expr(cx, sub_exp, scope_stack, scope_map),
2543 ast::ExprUnary(_, sub_exp) => {
2544 walk_expr(cx, sub_exp, scope_stack, scope_map);
2547 ast::ExprAssignOp(_, lhs, rhs) |
2548 ast::ExprIndex(lhs, rhs) |
2549 ast::ExprBinary(_, lhs, rhs) => {
2550 walk_expr(cx, lhs, scope_stack, scope_map);
2551 walk_expr(cx, rhs, scope_stack, scope_map);
2554 ast::ExprVec(ref init_expressions, _) |
2555 ast::ExprTup(ref init_expressions) => {
2556 for ie in init_expressions.iter() {
2557 walk_expr(cx, *ie, scope_stack, scope_map);
2561 ast::ExprAssign(sub_exp1, sub_exp2) |
2562 ast::ExprRepeat(sub_exp1, sub_exp2, _) => {
2563 walk_expr(cx, sub_exp1, scope_stack, scope_map);
2564 walk_expr(cx, sub_exp2, scope_stack, scope_map);
2567 ast::ExprIf(cond_exp, then_block, ref opt_else_exp) => {
2568 walk_expr(cx, cond_exp, scope_stack, scope_map);
2574 |cx, scope_stack, scope_map| {
2575 walk_block(cx, then_block, scope_stack, scope_map);
2578 match *opt_else_exp {
2579 Some(else_exp) => walk_expr(cx, else_exp, scope_stack, scope_map),
2584 ast::ExprWhile(cond_exp, loop_body) => {
2585 walk_expr(cx, cond_exp, scope_stack, scope_map);
2591 |cx, scope_stack, scope_map| {
2592 walk_block(cx, loop_body, scope_stack, scope_map);
2596 ast::ExprForLoop(_, _, _, _) => {
2597 cx.sess.span_bug(exp.span, "debuginfo::populate_scope_map() - \
2598 Found unexpanded for-loop.");
2601 ast::ExprMac(_) => {
2602 cx.sess.span_bug(exp.span, "debuginfo::populate_scope_map() - \
2603 Found unexpanded macro.");
2606 ast::ExprLoop(block, _) |
2607 ast::ExprBlock(block) => {
2612 |cx, scope_stack, scope_map| {
2613 walk_block(cx, block, scope_stack, scope_map);
2617 ast::ExprFnBlock(decl, block) |
2618 ast::ExprProc(decl, block) => {
2623 |cx, scope_stack, scope_map| {
2624 for &ast::Arg { pat: pattern, .. } in decl.inputs.iter() {
2625 walk_pattern(cx, pattern, scope_stack, scope_map);
2628 walk_block(cx, block, scope_stack, scope_map);
2632 ast::ExprCall(fn_exp, ref args) => {
2633 walk_expr(cx, fn_exp, scope_stack, scope_map);
2635 for arg_exp in args.iter() {
2636 walk_expr(cx, *arg_exp, scope_stack, scope_map);
2640 ast::ExprMethodCall(_, _, ref args) => {
2641 for arg_exp in args.iter() {
2642 walk_expr(cx, *arg_exp, scope_stack, scope_map);
2646 ast::ExprMatch(discriminant_exp, ref arms) => {
2647 walk_expr(cx, discriminant_exp, scope_stack, scope_map);
2649 // for each arm we have to first walk the pattern as these might introduce new
2650 // artificial scopes. It should be sufficient to walk only one pattern per arm, as
2651 // they all must contain the same binding names
2653 for arm_ref in arms.iter() {
2654 let arm_span = arm_ref.pats.get(0).span;
2660 |cx, scope_stack, scope_map| {
2661 for &pat in arm_ref.pats.iter() {
2662 walk_pattern(cx, pat, scope_stack, scope_map);
2665 for guard_exp in arm_ref.guard.iter() {
2666 walk_expr(cx, *guard_exp, scope_stack, scope_map)
2669 walk_expr(cx, arm_ref.body, scope_stack, scope_map);
2674 ast::ExprStruct(_, ref fields, ref base_exp) => {
2675 for &ast::Field { expr: exp, .. } in fields.iter() {
2676 walk_expr(cx, exp, scope_stack, scope_map);
2680 Some(exp) => walk_expr(cx, exp, scope_stack, scope_map),
2685 ast::ExprInlineAsm(ast::InlineAsm { inputs: ref inputs,
2686 outputs: ref outputs,
2688 // inputs, outputs: ~[(~str, @expr)]
2689 for &(_, exp) in inputs.iter() {
2690 walk_expr(cx, exp, scope_stack, scope_map);
2693 for &(_, exp) in outputs.iter() {
2694 walk_expr(cx, exp, scope_stack, scope_map);
2702 //=-------------------------------------------------------------------------------------------------
2703 // Namespace Handling
2704 //=-------------------------------------------------------------------------------------------------
2706 struct NamespaceTreeNode {
2709 parent: Option<@NamespaceTreeNode>,
2712 impl NamespaceTreeNode {
2713 fn mangled_name_of_contained_item(&self, item_name: &str) -> ~str {
2714 fn fill_nested(node: &NamespaceTreeNode, output: &mut ~str) {
2716 Some(parent) => fill_nested(parent, output),
2719 let string = token::get_name(node.name);
2720 output.push_str(format!("{}", string.get().len()));
2721 output.push_str(string.get());
2724 let mut name = ~"_ZN";
2725 fill_nested(self, &mut name);
2726 name.push_str(format!("{}", item_name.len()));
2727 name.push_str(item_name);
2728 name.push_char('E');
2733 fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> @NamespaceTreeNode {
2734 ty::with_path(cx.tcx, def_id, |path| {
2735 // prepend crate name if not already present
2736 let krate = if def_id.krate == ast::LOCAL_CRATE {
2737 let crate_namespace_ident = token::str_to_ident(cx.link_meta.crateid.name);
2738 Some(ast_map::PathMod(crate_namespace_ident.name))
2742 let mut path = krate.move_iter().chain(path).peekable();
2744 let mut current_key = ~[];
2745 let mut parent_node: Option<@NamespaceTreeNode> = None;
2747 // Create/Lookup namespace for each element of the path.
2749 // Emulate a for loop so we can use peek below.
2750 let path_element = match path.next() {
2754 // Ignore the name of the item (the last path element).
2755 if path.peek().is_none() {
2759 let name = path_element.name();
2760 current_key.push(name);
2762 let existing_node = {
2763 let namespace_map = debug_context(cx).namespace_map.borrow();
2764 namespace_map.get().find_copy(¤t_key)
2766 let current_node = match existing_node {
2767 Some(existing_node) => existing_node,
2769 // create and insert
2770 let parent_scope = match parent_node {
2771 Some(node) => node.scope,
2774 let namespace_name = token::get_name(name);
2775 let scope = namespace_name.get().with_c_str(|namespace_name| {
2777 llvm::LLVMDIBuilderCreateNameSpace(
2781 // cannot reconstruct file ...
2783 // ... or line information, but that's not so important.
2788 let node = @NamespaceTreeNode {
2791 parent: parent_node,
2795 let mut namespace_map = debug_context(cx).namespace_map
2797 namespace_map.get().insert(current_key.clone(), node);
2804 parent_node = Some(current_node);
2810 cx.sess.bug(format!("debuginfo::namespace_for_item(): \
2811 path too short for {:?}", def_id));