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 metadata::csearch;
134 use middle::trans::adt;
135 use middle::trans::common::*;
136 use middle::trans::datum::{Datum, Lvalue};
137 use middle::trans::machine;
138 use middle::trans::type_of;
139 use middle::trans::type_::Type;
142 use middle::pat_util;
145 use std::c_str::{CString, ToCStr};
146 use std::cell::{Cell, RefCell};
147 use collections::HashMap;
148 use collections::HashSet;
149 use libc::{c_uint, c_ulonglong, c_longlong};
152 use std::strbuf::StrBuf;
153 use std::sync::atomics;
154 use syntax::codemap::{Span, Pos};
155 use syntax::{abi, ast, codemap, ast_util, ast_map};
156 use syntax::owned_slice::OwnedSlice;
157 use syntax::parse::token;
158 use syntax::parse::token::special_idents;
160 static DW_LANG_RUST: c_uint = 0x9000;
162 static DW_TAG_auto_variable: c_uint = 0x100;
163 static DW_TAG_arg_variable: c_uint = 0x101;
165 static DW_ATE_boolean: c_uint = 0x02;
166 static DW_ATE_float: c_uint = 0x04;
167 static DW_ATE_signed: c_uint = 0x05;
168 // static DW_ATE_signed_char: c_uint = 0x06;
169 static DW_ATE_unsigned: c_uint = 0x07;
170 static DW_ATE_unsigned_char: c_uint = 0x08;
172 //=-------------------------------------------------------------------------------------------------
173 // Public Interface of debuginfo module
174 //=-------------------------------------------------------------------------------------------------
176 /// A context object for maintaining all state needed by the debuginfo module.
177 pub struct CrateDebugContext {
178 llcontext: ContextRef,
179 builder: DIBuilderRef,
180 current_debug_location: Cell<DebugLocation>,
181 created_files: RefCell<HashMap<~str, DIFile>>,
182 created_types: RefCell<HashMap<uint, DIType>>,
183 created_enum_disr_types: RefCell<HashMap<ast::DefId, DIType>>,
184 namespace_map: RefCell<HashMap<Vec<ast::Name> , @NamespaceTreeNode>>,
185 // This collection is used to assert that composite types (structs, enums, ...) have their
186 // members only set once:
187 composite_types_completed: RefCell<HashSet<DIType>>,
190 impl CrateDebugContext {
191 pub fn new(llmod: ModuleRef) -> CrateDebugContext {
192 debug!("CrateDebugContext::new");
193 let builder = unsafe { llvm::LLVMDIBuilderCreate(llmod) };
194 // DIBuilder inherits context from the module, so we'd better use the same one
195 let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
196 return CrateDebugContext {
197 llcontext: llcontext,
199 current_debug_location: Cell::new(UnknownLocation),
200 created_files: RefCell::new(HashMap::new()),
201 created_types: RefCell::new(HashMap::new()),
202 created_enum_disr_types: RefCell::new(HashMap::new()),
203 namespace_map: RefCell::new(HashMap::new()),
204 composite_types_completed: RefCell::new(HashSet::new()),
209 pub enum FunctionDebugContext {
210 priv FunctionDebugContext(~FunctionDebugContextData),
211 priv DebugInfoDisabled,
212 priv FunctionWithoutDebugInfo,
215 impl FunctionDebugContext {
216 fn get_ref<'a>(&'a self, cx: &CrateContext, span: Span) -> &'a FunctionDebugContextData {
218 FunctionDebugContext(~ref data) => data,
219 DebugInfoDisabled => {
220 cx.sess().span_bug(span, FunctionDebugContext::debuginfo_disabled_message());
222 FunctionWithoutDebugInfo => {
223 cx.sess().span_bug(span, FunctionDebugContext::should_be_ignored_message());
228 fn debuginfo_disabled_message() -> &'static str {
229 "debuginfo: Error trying to access FunctionDebugContext although debug info is disabled!"
232 fn should_be_ignored_message() -> &'static str {
233 "debuginfo: Error trying to access FunctionDebugContext for function that should be \
234 ignored by debug info!"
238 struct FunctionDebugContextData {
239 scope_map: RefCell<HashMap<ast::NodeId, DIScope>>,
240 fn_metadata: DISubprogram,
241 argument_counter: Cell<uint>,
242 source_locations_enabled: Cell<bool>,
245 enum VariableAccess<'a> {
246 // The llptr given is an alloca containing the variable's value
247 DirectVariable { alloca: ValueRef },
248 // The llptr given is an alloca containing the start of some pointer chain leading to the
249 // variable's content.
250 IndirectVariable { alloca: ValueRef, address_operations: &'a [ValueRef] }
254 ArgumentVariable(uint /*index*/),
259 /// Create any deferred debug metadata nodes
260 pub fn finalize(cx: &CrateContext) {
261 if cx.dbg_cx.is_none() {
266 compile_unit_metadata(cx);
268 llvm::LLVMDIBuilderFinalize(DIB(cx));
269 llvm::LLVMDIBuilderDispose(DIB(cx));
270 // Debuginfo generation in LLVM by default uses a higher
271 // version of dwarf than OS X currently understands. We can
272 // instruct LLVM to emit an older version of dwarf, however,
273 // for OS X to understand. For more info see #11352
274 // This can be overridden using --llvm-opts -dwarf-version,N.
275 if cx.sess().targ_cfg.os == abi::OsMacos {
276 "Dwarf Version".with_c_str(
277 |s| llvm::LLVMRustAddModuleFlag(cx.llmod, s, 2));
280 // Prevent bitcode readers from deleting the debug info.
281 "Debug Info Version".with_c_str(
282 |s| llvm::LLVMRustAddModuleFlag(cx.llmod, s,
283 llvm::LLVMRustDebugMetadataVersion));
287 /// Creates debug information for the given global variable.
289 /// Adds the created metadata nodes directly to the crate's IR.
290 pub fn create_global_var_metadata(cx: &CrateContext,
291 node_id: ast::NodeId,
293 if cx.dbg_cx.is_none() {
297 // Don't create debuginfo for globals inlined from other crates. The other crate should already
298 // contain debuginfo for it. More importantly, the global might not even exist in un-inlined
299 // form anywhere which would lead to a linker errors.
300 if cx.external_srcs.borrow().contains_key(&node_id) {
304 let var_item = cx.tcx.map.get(node_id);
306 let (ident, span) = match var_item {
307 ast_map::NodeItem(item) => {
309 ast::ItemStatic(..) => (item.ident, item.span),
310 _ => cx.sess().span_bug(item.span,
311 format!("debuginfo::create_global_var_metadata() -
312 Captured var-id refers to unexpected ast_item
317 _ => cx.sess().bug(format!("debuginfo::create_global_var_metadata() - Captured var-id \
318 refers to unexpected ast_map variant: {:?}",
322 let filename = span_start(cx, span).file.name.clone();
323 let file_metadata = file_metadata(cx, filename);
325 let is_local_to_unit = is_node_local_to_unit(cx, node_id);
326 let loc = span_start(cx, span);
328 let variable_type = ty::node_id_to_type(cx.tcx(), node_id);
329 let type_metadata = type_metadata(cx, variable_type, span);
331 let namespace_node = namespace_for_item(cx, ast_util::local_def(node_id));
332 let var_name = token::get_ident(ident).get().to_str();
333 let linkage_name = namespace_node.mangled_name_of_contained_item(var_name);
334 let var_scope = namespace_node.scope;
336 var_name.with_c_str(|var_name| {
337 linkage_name.with_c_str(|linkage_name| {
339 llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx),
354 /// Creates debug information for the given local variable.
356 /// Adds the created metadata nodes directly to the crate's IR.
357 pub fn create_local_var_metadata(bcx: &Block, local: &ast::Local) {
358 if fn_should_be_ignored(bcx.fcx) {
363 let def_map = cx.tcx.def_map;
365 pat_util::pat_bindings(def_map, local.pat, |_, node_id, span, path_ref| {
366 let var_ident = ast_util::path_to_ident(path_ref);
368 let datum = match bcx.fcx.lllocals.borrow().find_copy(&node_id) {
369 Some(datum) => datum,
371 bcx.sess().span_bug(span,
372 format!("no entry in lllocals table for {:?}",
377 let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
383 DirectVariable { alloca: datum.val },
389 /// Creates debug information for a variable captured in a closure.
391 /// Adds the created metadata nodes directly to the crate's IR.
392 pub fn create_captured_var_metadata(bcx: &Block,
393 node_id: ast::NodeId,
394 env_data_type: ty::t,
395 env_pointer: ValueRef,
397 closure_sigil: ast::Sigil,
399 if fn_should_be_ignored(bcx.fcx) {
405 let ast_item = cx.tcx.map.find(node_id);
407 let variable_ident = match ast_item {
409 cx.sess().span_bug(span, "debuginfo::create_captured_var_metadata: node not found");
411 Some(ast_map::NodeLocal(pat)) | Some(ast_map::NodeArg(pat)) => {
413 ast::PatIdent(_, ref path, _) => {
414 ast_util::path_to_ident(path)
420 "debuginfo::create_captured_var_metadata() - \
421 Captured var-id refers to unexpected \
422 ast_map variant: {:?}",
428 cx.sess().span_bug(span, format!("debuginfo::create_captured_var_metadata() - \
429 Captured var-id refers to unexpected ast_map variant: {:?}", ast_item));
433 let variable_type = node_id_type(bcx, node_id);
434 let scope_metadata = bcx.fcx.debug_context.get_ref(cx, span).fn_metadata;
436 let llvm_env_data_type = type_of::type_of(cx, env_data_type);
437 let byte_offset_of_var_in_env = machine::llelement_offset(cx, llvm_env_data_type, env_index);
439 let address_operations = unsafe {
440 [llvm::LLVMDIBuilderCreateOpDeref(Type::i64(cx).to_ref()),
441 llvm::LLVMDIBuilderCreateOpPlus(Type::i64(cx).to_ref()),
442 C_i64(cx, byte_offset_of_var_in_env as i64),
443 llvm::LLVMDIBuilderCreateOpDeref(Type::i64(cx).to_ref())]
446 let address_op_count = match closure_sigil {
447 ast::BorrowedSigil => {
448 address_operations.len()
450 ast::ManagedSigil | ast::OwnedSigil => {
451 address_operations.len() - 1
455 let variable_access = IndirectVariable {
457 address_operations: address_operations.slice_to(address_op_count)
469 /// Creates debug information for a local variable introduced in the head of a match-statement arm.
471 /// Adds the created metadata nodes directly to the crate's IR.
472 pub fn create_match_binding_metadata(bcx: &Block,
473 variable_ident: ast::Ident,
474 node_id: ast::NodeId,
476 datum: Datum<Lvalue>) {
477 if fn_should_be_ignored(bcx.fcx) {
481 let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
487 DirectVariable { alloca: datum.val },
492 /// Creates debug information for the given function argument.
494 /// Adds the created metadata nodes directly to the crate's IR.
495 pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
496 if fn_should_be_ignored(bcx.fcx) {
503 let def_map = cx.tcx.def_map;
504 let scope_metadata = bcx.fcx.debug_context.get_ref(cx, arg.pat.span).fn_metadata;
506 pat_util::pat_bindings(def_map, arg.pat, |_, node_id, span, path_ref| {
507 let llarg = match bcx.fcx.llargs.borrow().find_copy(&node_id) {
510 bcx.sess().span_bug(span,
511 format!("no entry in llargs table for {:?}",
516 if unsafe { llvm::LLVMIsAAllocaInst(llarg.val) } == ptr::null() {
517 cx.sess().span_bug(span, "debuginfo::create_argument_metadata() - \
518 Referenced variable location is not an alloca!");
521 let argument_ident = ast_util::path_to_ident(path_ref);
523 let argument_index = {
524 let counter = &fcx.debug_context.get_ref(cx, span).argument_counter;
525 let argument_index = counter.get();
526 counter.set(argument_index + 1);
534 DirectVariable { alloca: llarg.val },
535 ArgumentVariable(argument_index),
540 /// Sets the current debug location at the beginning of the span.
542 /// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...). The node_id parameter is used to
543 /// reliably find the correct visibility scope for the code position.
544 pub fn set_source_location(fcx: &FunctionContext,
545 node_id: ast::NodeId,
547 match fcx.debug_context {
548 DebugInfoDisabled => return,
549 FunctionWithoutDebugInfo => {
550 set_debug_location(fcx.ccx, UnknownLocation);
553 FunctionDebugContext(~ref function_debug_context) => {
556 debug!("set_source_location: {}", cx.sess().codemap().span_to_str(span));
558 if function_debug_context.source_locations_enabled.get() {
559 let loc = span_start(cx, span);
560 let scope = scope_metadata(fcx, node_id, span);
562 set_debug_location(cx, DebugLocation::new(scope, loc.line, loc.col.to_uint()));
564 set_debug_location(cx, UnknownLocation);
570 /// Clears the current debug location.
572 /// Instructions generated hereafter won't be assigned a source location.
573 pub fn clear_source_location(fcx: &FunctionContext) {
574 if fn_should_be_ignored(fcx) {
578 set_debug_location(fcx.ccx, UnknownLocation);
581 /// Enables emitting source locations for the given functions.
583 /// Since we don't want source locations to be emitted for the function prelude, they are disabled
584 /// when beginning to translate a new function. This functions switches source location emitting on
585 /// and must therefore be called before the first real statement/expression of the function is
587 pub fn start_emitting_source_locations(fcx: &FunctionContext) {
588 match fcx.debug_context {
589 FunctionDebugContext(~ref data) => {
590 data.source_locations_enabled.set(true)
592 _ => { /* safe to ignore */ }
596 /// Creates the function-specific debug context.
598 /// Returns the FunctionDebugContext for the function which holds state needed for debug info
599 /// creation. The function may also return another variant of the FunctionDebugContext enum which
600 /// indicates why no debuginfo should be created for the function.
601 pub fn create_function_debug_context(cx: &CrateContext,
602 fn_ast_id: ast::NodeId,
603 param_substs: Option<@param_substs>,
604 llfn: ValueRef) -> FunctionDebugContext {
605 if cx.sess().opts.debuginfo == NoDebugInfo {
606 return DebugInfoDisabled;
609 // Clear the debug location so we don't assign them in the function prelude. Do this here
610 // already, in case we do an early exit from this function.
611 set_debug_location(cx, UnknownLocation);
614 return FunctionWithoutDebugInfo;
617 let empty_generics = ast::Generics { lifetimes: Vec::new(), ty_params: OwnedSlice::empty() };
619 let fnitem = cx.tcx.map.get(fn_ast_id);
621 let (ident, fn_decl, generics, top_level_block, span, has_path) = match fnitem {
622 ast_map::NodeItem(ref item) => {
624 ast::ItemFn(fn_decl, _, _, ref generics, top_level_block) => {
625 (item.ident, fn_decl, generics, top_level_block, item.span, true)
628 cx.sess().span_bug(item.span,
629 "create_function_debug_context: item bound to non-function");
633 ast_map::NodeMethod(method) => {
641 ast_map::NodeExpr(ref expr) => {
643 ast::ExprFnBlock(fn_decl, top_level_block) |
644 ast::ExprProc(fn_decl, top_level_block) => {
645 let name = format!("fn{}", token::gensym("fn"));
646 let name = token::str_to_ident(name);
648 // This is not quite right. It should actually inherit the generics of the
649 // enclosing function.
653 // Don't try to lookup the item path:
656 _ => cx.sess().span_bug(expr.span,
657 "create_function_debug_context: expected an expr_fn_block here")
660 ast_map::NodeTraitMethod(trait_method) => {
661 match *trait_method {
662 ast::Provided(method) => {
672 .bug(format!("create_function_debug_context: \
673 unexpected sort of node: {:?}",
678 ast_map::NodeForeignItem(..) |
679 ast_map::NodeVariant(..) |
680 ast_map::NodeStructCtor(..) => {
681 return FunctionWithoutDebugInfo;
683 _ => cx.sess().bug(format!("create_function_debug_context: \
684 unexpected sort of node: {:?}", fnitem))
687 // This can be the case for functions inlined from another crate
688 if span == codemap::DUMMY_SP {
689 return FunctionWithoutDebugInfo;
692 let loc = span_start(cx, span);
693 let file_metadata = file_metadata(cx, loc.file.name);
695 let function_type_metadata = unsafe {
696 let fn_signature = get_function_signature(cx, fn_ast_id, fn_decl, param_substs, span);
697 llvm::LLVMDIBuilderCreateSubroutineType(DIB(cx), file_metadata, fn_signature)
700 // get_template_parameters() will append a `<...>` clause to the function name if necessary.
701 let mut function_name = StrBuf::from_str(token::get_ident(ident).get());
702 let template_parameters = get_template_parameters(cx,
708 // There is no ast_map::Path for ast::ExprFnBlock-type functions. For now, just don't put them
709 // into a namespace. In the future this could be improved somehow (storing a path in the
710 // ast_map, or construct a path using the enclosing function).
711 let (linkage_name, containing_scope) = if has_path {
712 let namespace_node = namespace_for_item(cx, ast_util::local_def(fn_ast_id));
713 let linkage_name = namespace_node.mangled_name_of_contained_item(
714 function_name.as_slice());
715 let containing_scope = namespace_node.scope;
716 (linkage_name, containing_scope)
718 (function_name.as_slice().to_owned(), file_metadata)
721 // Clang sets this parameter to the opening brace of the function's block, so let's do this too.
722 let scope_line = span_start(cx, top_level_block.span).line;
724 let is_local_to_unit = is_node_local_to_unit(cx, fn_ast_id);
726 let fn_metadata = function_name.as_slice().with_c_str(|function_name| {
727 linkage_name.with_c_str(|linkage_name| {
729 llvm::LLVMDIBuilderCreateFunction(
736 function_type_metadata,
739 scope_line as c_uint,
740 FlagPrototyped as c_uint,
741 cx.sess().opts.optimize != session::No,
749 // Initialize fn debug context (including scope map and namespace map)
750 let fn_debug_context = ~FunctionDebugContextData {
751 scope_map: RefCell::new(HashMap::new()),
752 fn_metadata: fn_metadata,
753 argument_counter: Cell::new(1),
754 source_locations_enabled: Cell::new(false),
757 let arg_pats = fn_decl.inputs.iter().map(|arg_ref| arg_ref.pat).collect::<Vec<_>>();
758 populate_scope_map(cx,
762 &mut *fn_debug_context.scope_map.borrow_mut());
764 return FunctionDebugContext(fn_debug_context);
766 fn get_function_signature(cx: &CrateContext,
767 fn_ast_id: ast::NodeId,
768 fn_decl: &ast::FnDecl,
769 param_substs: Option<@param_substs>,
770 error_span: Span) -> DIArray {
771 if cx.sess().opts.debuginfo == LimitedDebugInfo {
772 return create_DIArray(DIB(cx), []);
775 let mut signature = slice::with_capacity(fn_decl.inputs.len() + 1);
777 // Return type -- llvm::DIBuilder wants this at index 0
778 match fn_decl.output.node {
780 signature.push(ptr::null());
783 assert_type_for_node_id(cx, fn_ast_id, error_span);
785 let return_type = ty::node_id_to_type(cx.tcx(), fn_ast_id);
786 let return_type = match param_substs {
789 ty::subst_tps(cx.tcx(),
790 substs.tys.as_slice(),
796 signature.push(type_metadata(cx, return_type, codemap::DUMMY_SP));
801 for arg in fn_decl.inputs.iter() {
802 assert_type_for_node_id(cx, arg.pat.id, arg.pat.span);
803 let arg_type = ty::node_id_to_type(cx.tcx(), arg.pat.id);
804 let arg_type = match param_substs {
807 ty::subst_tps(cx.tcx(),
808 substs.tys.as_slice(),
814 signature.push(type_metadata(cx, arg_type, codemap::DUMMY_SP));
817 return create_DIArray(DIB(cx), signature);
820 fn get_template_parameters(cx: &CrateContext,
821 generics: &ast::Generics,
822 param_substs: Option<@param_substs>,
823 file_metadata: DIFile,
824 name_to_append_suffix_to: &mut StrBuf)
826 let self_type = match param_substs {
827 Some(param_substs) => param_substs.self_ty,
831 // Only true for static default methods:
832 let has_self_type = self_type.is_some();
834 if !generics.is_type_parameterized() && !has_self_type {
835 return create_DIArray(DIB(cx), []);
838 name_to_append_suffix_to.push_char('<');
840 // The list to be filled with template parameters:
841 let mut template_params: Vec<DIDescriptor> =
842 Vec::with_capacity(generics.ty_params.len() + 1);
846 let actual_self_type = self_type.unwrap();
847 // Add self type name to <...> clause of function name
848 let actual_self_type_name = ppaux::ty_to_str(cx.tcx(), actual_self_type);
849 name_to_append_suffix_to.push_str(actual_self_type_name);
851 if generics.is_type_parameterized() {
852 name_to_append_suffix_to.push_str(",");
855 // Only create type information if full debuginfo is enabled
856 if cx.sess().opts.debuginfo == FullDebugInfo {
857 let actual_self_type_metadata = type_metadata(cx,
861 let ident = special_idents::type_self;
863 let param_metadata = token::get_ident(ident).get()
866 llvm::LLVMDIBuilderCreateTemplateTypeParameter(
870 actual_self_type_metadata,
877 template_params.push(param_metadata);
881 // Handle other generic parameters
882 let actual_types = match param_substs {
883 Some(param_substs) => ¶m_substs.tys,
885 return create_DIArray(DIB(cx), template_params.as_slice());
889 for (index, &ast::TyParam{ ident: ident, .. }) in generics.ty_params.iter().enumerate() {
890 let actual_type = *actual_types.get(index);
891 // Add actual type name to <...> clause of function name
892 let actual_type_name = ppaux::ty_to_str(cx.tcx(), actual_type);
893 name_to_append_suffix_to.push_str(actual_type_name);
895 if index != generics.ty_params.len() - 1 {
896 name_to_append_suffix_to.push_str(",");
899 // Again, only create type information if full debuginfo is enabled
900 if cx.sess().opts.debuginfo == FullDebugInfo {
901 let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP);
902 let param_metadata = token::get_ident(ident).get()
905 llvm::LLVMDIBuilderCreateTemplateTypeParameter(
909 actual_type_metadata,
915 template_params.push(param_metadata);
919 name_to_append_suffix_to.push_char('>');
921 return create_DIArray(DIB(cx), template_params.as_slice());
925 //=-------------------------------------------------------------------------------------------------
926 // Module-Internal debug info creation functions
927 //=-------------------------------------------------------------------------------------------------
929 fn is_node_local_to_unit(cx: &CrateContext, node_id: ast::NodeId) -> bool
931 // The is_local_to_unit flag indicates whether a function is local to the current compilation
932 // unit (i.e. if it is *static* in the C-sense). The *reachable* set should provide a good
933 // approximation of this, as it contains everything that might leak out of the current crate
934 // (by being externally visible or by being inlined into something externally visible). It might
935 // better to use the `exported_items` set from `driver::CrateAnalysis` in the future, but (atm)
936 // this set is not available in the translation pass.
937 !cx.reachable.contains(&node_id)
940 fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
942 llvm::LLVMDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32)
946 fn compile_unit_metadata(cx: &CrateContext) {
947 let work_dir = &cx.sess().working_dir;
948 let compile_unit_name = match cx.sess().local_crate_source_file {
949 None => fallback_path(cx),
950 Some(ref abs_path) => {
951 if abs_path.is_relative() {
952 cx.sess().warn("debuginfo: Invalid path to crate's local root source file!");
955 match abs_path.path_relative_from(work_dir) {
956 Some(ref p) if p.is_relative() => {
957 // prepend "./" if necessary
958 let dotdot = bytes!("..");
959 let prefix = &[dotdot[0], ::std::path::SEP_BYTE];
960 let mut path_bytes = p.as_vec().to_owned();
962 if path_bytes.slice_to(2) != prefix &&
963 path_bytes.slice_to(2) != dotdot {
964 path_bytes.insert(0, prefix[0]);
965 path_bytes.insert(1, prefix[1]);
968 path_bytes.to_c_str()
970 _ => fallback_path(cx)
976 debug!("compile_unit_metadata: {:?}", compile_unit_name);
977 let producer = format!("rustc version {}", env!("CFG_VERSION"));
979 compile_unit_name.with_ref(|compile_unit_name| {
980 work_dir.as_vec().with_c_str(|work_dir| {
981 producer.with_c_str(|producer| {
982 "".with_c_str(|flags| {
983 "".with_c_str(|split_name| {
985 llvm::LLVMDIBuilderCreateCompileUnit(
986 debug_context(cx).builder,
991 cx.sess().opts.optimize != session::No,
1002 fn fallback_path(cx: &CrateContext) -> CString {
1003 cx.link_meta.crateid.name.to_c_str()
1007 fn declare_local(bcx: &Block,
1008 variable_ident: ast::Ident,
1009 variable_type: ty::t,
1010 scope_metadata: DIScope,
1011 variable_access: VariableAccess,
1012 variable_kind: VariableKind,
1014 let cx: &CrateContext = bcx.ccx();
1016 let filename = span_start(cx, span).file.name.clone();
1017 let file_metadata = file_metadata(cx, filename);
1019 let name = token::get_ident(variable_ident);
1020 let loc = span_start(cx, span);
1021 let type_metadata = type_metadata(cx, variable_type, span);
1023 let (argument_index, dwarf_tag) = match variable_kind {
1024 ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),
1026 CapturedVariable => (0, DW_TAG_auto_variable)
1029 let (var_alloca, var_metadata) = name.get().with_c_str(|name| {
1030 match variable_access {
1031 DirectVariable { alloca } => (
1034 llvm::LLVMDIBuilderCreateLocalVariable(
1042 cx.sess().opts.optimize != session::No,
1047 IndirectVariable { alloca, address_operations } => (
1050 llvm::LLVMDIBuilderCreateComplexVariable(
1058 address_operations.as_ptr(),
1059 address_operations.len() as c_uint,
1066 set_debug_location(cx, DebugLocation::new(scope_metadata, loc.line, loc.col.to_uint()));
1068 let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
1074 llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr);
1077 match variable_kind {
1078 ArgumentVariable(_) | CapturedVariable => {
1082 .source_locations_enabled
1084 set_debug_location(cx, UnknownLocation);
1086 _ => { /* nothing to do */ }
1090 fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
1091 match debug_context(cx).created_files.borrow().find_equiv(&full_path) {
1092 Some(file_metadata) => return *file_metadata,
1096 debug!("file_metadata: {}", full_path);
1098 // FIXME (#9639): This needs to handle non-utf8 paths
1099 let work_dir = cx.sess().working_dir.as_str().unwrap();
1101 if full_path.starts_with(work_dir) {
1102 full_path.slice(work_dir.len() + 1u, full_path.len())
1108 file_name.with_c_str(|file_name| {
1109 work_dir.with_c_str(|work_dir| {
1111 llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir)
1116 let mut created_files = debug_context(cx).created_files.borrow_mut();
1117 created_files.insert(full_path.to_owned(), file_metadata);
1118 return file_metadata;
1121 /// Finds the scope metadata node for the given AST node.
1122 fn scope_metadata(fcx: &FunctionContext,
1123 node_id: ast::NodeId,
1126 let scope_map = &fcx.debug_context.get_ref(fcx.ccx, span).scope_map;
1127 match scope_map.borrow().find_copy(&node_id) {
1128 Some(scope_metadata) => scope_metadata,
1130 let node = fcx.ccx.tcx.map.get(node_id);
1132 fcx.ccx.sess().span_bug(span,
1133 format!("debuginfo: Could not find scope info for node {:?}", node));
1138 fn basic_type_metadata(cx: &CrateContext, t: ty::t) -> DIType {
1140 debug!("basic_type_metadata: {:?}", ty::get(t));
1142 let (name, encoding) = match ty::get(t).sty {
1143 ty::ty_nil => (~"()", DW_ATE_unsigned),
1144 ty::ty_bot => (~"!", DW_ATE_unsigned),
1145 ty::ty_bool => (~"bool", DW_ATE_boolean),
1146 ty::ty_char => (~"char", DW_ATE_unsigned_char),
1147 ty::ty_int(int_ty) => match int_ty {
1148 ast::TyI => (~"int", DW_ATE_signed),
1149 ast::TyI8 => (~"i8", DW_ATE_signed),
1150 ast::TyI16 => (~"i16", DW_ATE_signed),
1151 ast::TyI32 => (~"i32", DW_ATE_signed),
1152 ast::TyI64 => (~"i64", DW_ATE_signed)
1154 ty::ty_uint(uint_ty) => match uint_ty {
1155 ast::TyU => (~"uint", DW_ATE_unsigned),
1156 ast::TyU8 => (~"u8", DW_ATE_unsigned),
1157 ast::TyU16 => (~"u16", DW_ATE_unsigned),
1158 ast::TyU32 => (~"u32", DW_ATE_unsigned),
1159 ast::TyU64 => (~"u64", DW_ATE_unsigned)
1161 ty::ty_float(float_ty) => match float_ty {
1162 ast::TyF32 => (~"f32", DW_ATE_float),
1163 ast::TyF64 => (~"f64", DW_ATE_float)
1165 _ => cx.sess().bug("debuginfo::basic_type_metadata - t is invalid type")
1168 let llvm_type = type_of::type_of(cx, t);
1169 let (size, align) = size_and_align_of(cx, llvm_type);
1170 let ty_metadata = name.with_c_str(|name| {
1172 llvm::LLVMDIBuilderCreateBasicType(
1175 bytes_to_bits(size),
1176 bytes_to_bits(align),
1184 fn pointer_type_metadata(cx: &CrateContext,
1185 pointer_type: ty::t,
1186 pointee_type_metadata: DIType)
1188 let pointer_llvm_type = type_of::type_of(cx, pointer_type);
1189 let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
1190 let name = ppaux::ty_to_str(cx.tcx(), pointer_type);
1191 let ptr_metadata = name.with_c_str(|name| {
1193 llvm::LLVMDIBuilderCreatePointerType(
1195 pointee_type_metadata,
1196 bytes_to_bits(pointer_size),
1197 bytes_to_bits(pointer_align),
1201 return ptr_metadata;
1204 enum MemberDescriptionFactory {
1205 StructMD(StructMemberDescriptionFactory),
1206 TupleMD(TupleMemberDescriptionFactory),
1207 GeneralMD(GeneralMemberDescriptionFactory),
1208 EnumVariantMD(EnumVariantMemberDescriptionFactory)
1211 impl MemberDescriptionFactory {
1212 fn create_member_descriptions(&self, cx: &CrateContext)
1213 -> Vec<MemberDescription> {
1215 StructMD(ref this) => {
1216 this.create_member_descriptions(cx)
1218 TupleMD(ref this) => {
1219 this.create_member_descriptions(cx)
1221 GeneralMD(ref this) => {
1222 this.create_member_descriptions(cx)
1224 EnumVariantMD(ref this) => {
1225 this.create_member_descriptions(cx)
1231 struct StructMemberDescriptionFactory {
1232 fields: Vec<ty::field> ,
1236 impl StructMemberDescriptionFactory {
1237 fn create_member_descriptions(&self, cx: &CrateContext)
1238 -> Vec<MemberDescription> {
1239 self.fields.iter().map(|field| {
1240 let name = if field.ident.name == special_idents::unnamed_field.name {
1243 token::get_ident(field.ident).get().to_str()
1248 llvm_type: type_of::type_of(cx, field.mt.ty),
1249 type_metadata: type_metadata(cx, field.mt.ty, self.span),
1250 offset: ComputedMemberOffset,
1256 fn prepare_struct_metadata(cx: &CrateContext,
1259 substs: &ty::substs,
1261 -> RecursiveTypeDescription {
1262 let struct_name = ppaux::ty_to_str(cx.tcx(), struct_type);
1263 let struct_llvm_type = type_of::type_of(cx, struct_type);
1265 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id);
1267 let file_name = span_start(cx, definition_span).file.name.clone();
1268 let file_metadata = file_metadata(cx, file_name);
1270 let struct_metadata_stub = create_struct_stub(cx,
1277 let fields = ty::struct_fields(cx.tcx(), def_id, substs);
1279 UnfinishedMetadata {
1280 cache_id: cache_id_for_type(struct_type),
1281 metadata_stub: struct_metadata_stub,
1282 llvm_type: struct_llvm_type,
1283 file_metadata: file_metadata,
1284 member_description_factory: StructMD(StructMemberDescriptionFactory {
1291 enum RecursiveTypeDescription {
1292 UnfinishedMetadata {
1294 metadata_stub: DICompositeType,
1296 file_metadata: DIFile,
1297 member_description_factory: MemberDescriptionFactory,
1299 FinalMetadata(DICompositeType)
1302 impl RecursiveTypeDescription {
1304 fn finalize(&self, cx: &CrateContext) -> DICompositeType {
1306 FinalMetadata(metadata) => metadata,
1307 UnfinishedMetadata {
1312 ref member_description_factory
1314 // Insert the stub into the cache in order to allow recursive references ...
1315 debug_context(cx).created_types.borrow_mut()
1316 .insert(cache_id, metadata_stub);
1318 // ... then create the member descriptions ...
1319 let member_descriptions = member_description_factory.create_member_descriptions(cx);
1321 // ... and attach them to the stub to complete it.
1322 set_members_of_composite_type(cx,
1325 member_descriptions.as_slice(),
1328 return metadata_stub;
1334 struct TupleMemberDescriptionFactory {
1335 component_types: Vec<ty::t> ,
1339 impl TupleMemberDescriptionFactory {
1340 fn create_member_descriptions(&self, cx: &CrateContext)
1341 -> Vec<MemberDescription> {
1342 self.component_types.iter().map(|&component_type| {
1345 llvm_type: type_of::type_of(cx, component_type),
1346 type_metadata: type_metadata(cx, component_type, self.span),
1347 offset: ComputedMemberOffset,
1353 fn prepare_tuple_metadata(cx: &CrateContext,
1355 component_types: &[ty::t],
1357 -> RecursiveTypeDescription {
1358 let tuple_name = ppaux::ty_to_str(cx.tcx(), tuple_type);
1359 let tuple_llvm_type = type_of::type_of(cx, tuple_type);
1361 let loc = span_start(cx, span);
1362 let file_metadata = file_metadata(cx, loc.file.name);
1364 UnfinishedMetadata {
1365 cache_id: cache_id_for_type(tuple_type),
1366 metadata_stub: create_struct_stub(cx,
1372 llvm_type: tuple_llvm_type,
1373 file_metadata: file_metadata,
1374 member_description_factory: TupleMD(TupleMemberDescriptionFactory {
1375 component_types: Vec::from_slice(component_types),
1381 struct GeneralMemberDescriptionFactory {
1382 type_rep: @adt::Repr,
1383 variants: @Vec<@ty::VariantInfo> ,
1384 discriminant_type_metadata: ValueRef,
1385 containing_scope: DIScope,
1386 file_metadata: DIFile,
1390 impl GeneralMemberDescriptionFactory {
1391 fn create_member_descriptions(&self, cx: &CrateContext)
1392 -> Vec<MemberDescription> {
1393 // Capture type_rep, so we don't have to copy the struct_defs array
1394 let struct_defs = match *self.type_rep {
1395 adt::General(_, ref struct_defs) => struct_defs,
1396 _ => cx.sess().bug("unreachable")
1402 .map(|(i, struct_def)| {
1403 let (variant_type_metadata, variant_llvm_type, member_desc_factory) =
1404 describe_enum_variant(cx,
1406 *self.variants.get(i),
1407 Some(self.discriminant_type_metadata),
1408 self.containing_scope,
1412 let member_descriptions =
1413 member_desc_factory.create_member_descriptions(cx);
1415 set_members_of_composite_type(cx,
1416 variant_type_metadata,
1418 member_descriptions.as_slice(),
1423 llvm_type: variant_llvm_type,
1424 type_metadata: variant_type_metadata,
1425 offset: FixedMemberOffset { bytes: 0 },
1431 struct EnumVariantMemberDescriptionFactory {
1432 args: Vec<(~str, ty::t)> ,
1433 discriminant_type_metadata: Option<DIType>,
1437 impl EnumVariantMemberDescriptionFactory {
1438 fn create_member_descriptions(&self, cx: &CrateContext)
1439 -> Vec<MemberDescription> {
1440 self.args.iter().enumerate().map(|(i, &(ref name, ty))| {
1442 name: name.to_str(),
1443 llvm_type: type_of::type_of(cx, ty),
1444 type_metadata: match self.discriminant_type_metadata {
1445 Some(metadata) if i == 0 => metadata,
1446 _ => type_metadata(cx, ty, self.span)
1448 offset: ComputedMemberOffset,
1454 fn describe_enum_variant(cx: &CrateContext,
1455 struct_def: &adt::Struct,
1456 variant_info: &ty::VariantInfo,
1457 discriminant_type_metadata: Option<DIType>,
1458 containing_scope: DIScope,
1459 file_metadata: DIFile,
1461 -> (DICompositeType, Type, MemberDescriptionFactory) {
1462 let variant_llvm_type =
1463 Type::struct_(cx, struct_def.fields
1465 .map(|&t| type_of::type_of(cx, t))
1466 .collect::<Vec<_>>()
1469 // Could some consistency checks here: size, align, field count, discr type
1471 // Find the source code location of the variant's definition
1472 let variant_definition_span = if variant_info.id.krate == ast::LOCAL_CRATE {
1473 cx.tcx.map.span(variant_info.id.node)
1475 // For definitions from other crates we have no location information available.
1479 let metadata_stub = create_struct_stub(cx,
1481 token::get_ident(variant_info.name).get(),
1484 variant_definition_span);
1486 // Get the argument names from the enum variant info
1487 let mut arg_names: Vec<_> = match variant_info.arg_names {
1488 Some(ref names) => {
1489 names.iter().map(|ident| token::get_ident(*ident).get().to_str()).collect()
1491 None => variant_info.args.iter().map(|_| ~"").collect()
1494 // If this is not a univariant enum, there is also the (unnamed) discriminant field
1495 if discriminant_type_metadata.is_some() {
1496 arg_names.insert(0, ~"");
1499 // Build an array of (field name, field type) pairs to be captured in the factory closure.
1500 let args: Vec<(~str, ty::t)> = arg_names.iter()
1501 .zip(struct_def.fields.iter())
1502 .map(|(s, &t)| (s.to_str(), t))
1505 let member_description_factory =
1506 EnumVariantMD(EnumVariantMemberDescriptionFactory {
1508 discriminant_type_metadata: discriminant_type_metadata,
1512 (metadata_stub, variant_llvm_type, member_description_factory)
1515 fn prepare_enum_metadata(cx: &CrateContext,
1517 enum_def_id: ast::DefId,
1519 -> RecursiveTypeDescription {
1520 let enum_name = ppaux::ty_to_str(cx.tcx(), enum_type);
1522 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, enum_def_id);
1523 let loc = span_start(cx, definition_span);
1524 let file_metadata = file_metadata(cx, loc.file.name);
1526 // For empty enums there is an early exit. Just describe it as an empty struct with the
1527 // appropriate type name
1528 if ty::type_is_empty(cx.tcx(), enum_type) {
1529 let empty_type_metadata = composite_type_metadata(cx,
1537 return FinalMetadata(empty_type_metadata);
1540 let variants = ty::enum_variants(cx.tcx(), enum_def_id);
1542 let enumerators_metadata: Vec<DIDescriptor> = variants
1545 token::get_ident(v.name).get().with_c_str(|name| {
1547 llvm::LLVMDIBuilderCreateEnumerator(
1550 v.disr_val as c_ulonglong)
1556 let discriminant_type_metadata = |inttype| {
1557 // We can reuse the type of the discriminant for all monomorphized instances of an enum
1558 // because it doesn't depend on any type parameters. The def_id, uniquely identifying the
1559 // enum's polytype acts as key in this cache.
1560 let cached_discriminant_type_metadata = debug_context(cx).created_enum_disr_types
1562 .find_copy(&enum_def_id);
1563 match cached_discriminant_type_metadata {
1564 Some(discriminant_type_metadata) => discriminant_type_metadata,
1566 let discriminant_llvm_type = adt::ll_inttype(cx, inttype);
1567 let (discriminant_size, discriminant_align) =
1568 size_and_align_of(cx, discriminant_llvm_type);
1569 let discriminant_base_type_metadata = type_metadata(cx,
1570 adt::ty_of_inttype(inttype),
1572 let discriminant_name = get_enum_discriminant_name(cx, enum_def_id);
1574 let discriminant_type_metadata = discriminant_name.get().with_c_str(|name| {
1576 llvm::LLVMDIBuilderCreateEnumerationType(
1582 bytes_to_bits(discriminant_size),
1583 bytes_to_bits(discriminant_align),
1584 create_DIArray(DIB(cx), enumerators_metadata.as_slice()),
1585 discriminant_base_type_metadata)
1589 debug_context(cx).created_enum_disr_types
1591 .insert(enum_def_id, discriminant_type_metadata);
1593 discriminant_type_metadata
1598 let type_rep = adt::represent_type(cx, enum_type);
1600 return match *type_rep {
1601 adt::CEnum(inttype, _, _) => {
1602 FinalMetadata(discriminant_type_metadata(inttype))
1604 adt::Univariant(ref struct_def, _) => {
1605 assert!(variants.len() == 1);
1608 member_description_factory) =
1609 describe_enum_variant(cx,
1616 UnfinishedMetadata {
1617 cache_id: cache_id_for_type(enum_type),
1618 metadata_stub: metadata_stub,
1619 llvm_type: variant_llvm_type,
1620 file_metadata: file_metadata,
1621 member_description_factory: member_description_factory
1624 adt::General(inttype, _) => {
1625 let discriminant_type_metadata = discriminant_type_metadata(inttype);
1626 let enum_llvm_type = type_of::type_of(cx, enum_type);
1627 let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type);
1628 let unique_id = generate_unique_type_id("DI_ENUM_");
1630 let enum_metadata = enum_name.with_c_str(|enum_name| {
1631 unique_id.with_c_str(|unique_id| {
1633 llvm::LLVMDIBuilderCreateUnionType(
1639 bytes_to_bits(enum_type_size),
1640 bytes_to_bits(enum_type_align),
1649 UnfinishedMetadata {
1650 cache_id: cache_id_for_type(enum_type),
1651 metadata_stub: enum_metadata,
1652 llvm_type: enum_llvm_type,
1653 file_metadata: file_metadata,
1654 member_description_factory: GeneralMD(GeneralMemberDescriptionFactory {
1657 discriminant_type_metadata: discriminant_type_metadata,
1658 containing_scope: containing_scope,
1659 file_metadata: file_metadata,
1664 adt::NullablePointer { nonnull: ref struct_def, nndiscr, .. } => {
1667 member_description_factory) =
1668 describe_enum_variant(cx,
1670 *variants.get(nndiscr as uint),
1675 UnfinishedMetadata {
1676 cache_id: cache_id_for_type(enum_type),
1677 metadata_stub: metadata_stub,
1678 llvm_type: variant_llvm_type,
1679 file_metadata: file_metadata,
1680 member_description_factory: member_description_factory
1685 fn get_enum_discriminant_name(cx: &CrateContext, def_id: ast::DefId) -> token::InternedString {
1686 let name = if def_id.krate == ast::LOCAL_CRATE {
1687 cx.tcx.map.get_path_elem(def_id.node).name()
1689 csearch::get_item_path(&cx.tcx, def_id).last().unwrap().name()
1692 token::get_name(name)
1697 FixedMemberOffset { bytes: uint },
1698 // For ComputedMemberOffset, the offset is read from the llvm type definition
1699 ComputedMemberOffset
1702 struct MemberDescription {
1705 type_metadata: DIType,
1706 offset: MemberOffset,
1709 /// Creates debug information for a composite type, that is, anything that results in a LLVM struct.
1711 /// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums.
1712 fn composite_type_metadata(cx: &CrateContext,
1713 composite_llvm_type: Type,
1714 composite_type_name: &str,
1715 member_descriptions: &[MemberDescription],
1716 containing_scope: DIScope,
1717 file_metadata: DIFile,
1718 definition_span: Span)
1719 -> DICompositeType {
1720 // Create the (empty) struct metadata node ...
1721 let composite_type_metadata = create_struct_stub(cx,
1722 composite_llvm_type,
1723 composite_type_name,
1728 // ... and immediately create and add the member descriptions.
1729 set_members_of_composite_type(cx,
1730 composite_type_metadata,
1731 composite_llvm_type,
1732 member_descriptions,
1736 return composite_type_metadata;
1739 fn set_members_of_composite_type(cx: &CrateContext,
1740 composite_type_metadata: DICompositeType,
1741 composite_llvm_type: Type,
1742 member_descriptions: &[MemberDescription],
1743 file_metadata: DIFile,
1744 definition_span: Span) {
1745 // In some rare cases LLVM metadata uniquing would lead to an existing type description being
1746 // used instead of a new one created in create_struct_stub. This would cause a hard to trace
1747 // assertion in DICompositeType::SetTypeArray(). The following check makes sure that we get a
1748 // better error message if this should happen again due to some regression.
1750 let mut composite_types_completed =
1751 debug_context(cx).composite_types_completed.borrow_mut();
1752 if composite_types_completed.contains(&composite_type_metadata) {
1753 cx.sess().span_bug(definition_span, "debuginfo::set_members_of_composite_type() - \
1754 Already completed forward declaration \
1757 composite_types_completed.insert(composite_type_metadata);
1761 let loc = span_start(cx, definition_span);
1763 let member_metadata: Vec<DIDescriptor> = member_descriptions
1766 .map(|(i, member_description)| {
1767 let (member_size, member_align) = size_and_align_of(cx, member_description.llvm_type);
1768 let member_offset = match member_description.offset {
1769 FixedMemberOffset { bytes } => bytes as u64,
1770 ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i)
1773 member_description.name.with_c_str(|member_name| {
1775 llvm::LLVMDIBuilderCreateMemberType(
1777 composite_type_metadata,
1781 bytes_to_bits(member_size),
1782 bytes_to_bits(member_align),
1783 bytes_to_bits(member_offset),
1785 member_description.type_metadata)
1792 let type_array = create_DIArray(DIB(cx), member_metadata.as_slice());
1793 llvm::LLVMDICompositeTypeSetTypeArray(composite_type_metadata, type_array);
1797 // A convenience wrapper around LLVMDIBuilderCreateStructType(). Does not do any caching, does not
1798 // add any fields to the struct. This can be done later with set_members_of_composite_type().
1799 fn create_struct_stub(cx: &CrateContext,
1800 struct_llvm_type: Type,
1801 struct_type_name: &str,
1802 containing_scope: DIScope,
1803 file_metadata: DIFile,
1804 definition_span: Span)
1805 -> DICompositeType {
1806 let loc = span_start(cx, definition_span);
1807 let (struct_size, struct_align) = size_and_align_of(cx, struct_llvm_type);
1809 // We assign unique IDs to the type stubs so LLVM metadata uniquing does not reuse instances
1810 // where we don't want it.
1811 let unique_id = generate_unique_type_id("DI_STRUCT_");
1814 struct_type_name.with_c_str(|name| {
1815 unique_id.with_c_str(|unique_id| {
1816 // LLVMDIBuilderCreateStructType() wants an empty array. A null pointer will lead to
1817 // hard to trace and debug LLVM assertions later on in llvm/lib/IR/Value.cpp
1818 let empty_array = create_DIArray(DIB(cx), []);
1820 llvm::LLVMDIBuilderCreateStructType(
1826 bytes_to_bits(struct_size),
1827 bytes_to_bits(struct_align),
1839 fn boxed_type_metadata(cx: &CrateContext,
1840 content_type_name: Option<&str>,
1841 content_llvm_type: Type,
1842 content_type_metadata: DIType,
1844 -> DICompositeType {
1845 let box_type_name = match content_type_name {
1846 Some(content_type_name) => format!("Boxed<{}>", content_type_name),
1847 None => ~"BoxedType"
1850 let box_llvm_type = Type::at_box(cx, content_llvm_type);
1851 let member_llvm_types = box_llvm_type.field_types();
1852 assert!(box_layout_is_correct(cx,
1853 member_llvm_types.as_slice(),
1854 content_llvm_type));
1856 let int_type = ty::mk_int();
1857 let nil_pointer_type = ty::mk_nil_ptr(cx.tcx());
1858 let nil_pointer_type_metadata = type_metadata(cx, nil_pointer_type, codemap::DUMMY_SP);
1860 let member_descriptions = [
1863 llvm_type: *member_llvm_types.get(0),
1864 type_metadata: type_metadata(cx, int_type, codemap::DUMMY_SP),
1865 offset: ComputedMemberOffset,
1869 llvm_type: *member_llvm_types.get(1),
1870 type_metadata: nil_pointer_type_metadata,
1871 offset: ComputedMemberOffset,
1875 llvm_type: *member_llvm_types.get(2),
1876 type_metadata: nil_pointer_type_metadata,
1877 offset: ComputedMemberOffset,
1881 llvm_type: *member_llvm_types.get(3),
1882 type_metadata: nil_pointer_type_metadata,
1883 offset: ComputedMemberOffset,
1887 llvm_type: *member_llvm_types.get(4),
1888 type_metadata: content_type_metadata,
1889 offset: ComputedMemberOffset,
1893 let loc = span_start(cx, span);
1894 let file_metadata = file_metadata(cx, loc.file.name);
1896 return composite_type_metadata(
1900 member_descriptions,
1905 // Unfortunately, we cannot assert anything but the correct types here---and not whether the
1906 // 'next' and 'prev' pointers are in the correct order.
1907 fn box_layout_is_correct(cx: &CrateContext,
1908 member_llvm_types: &[Type],
1909 content_llvm_type: Type)
1911 member_llvm_types.len() == 5 &&
1912 member_llvm_types[0] == cx.int_type &&
1913 member_llvm_types[1] == Type::generic_glue_fn(cx).ptr_to() &&
1914 member_llvm_types[2] == Type::i8(cx).ptr_to() &&
1915 member_llvm_types[3] == Type::i8(cx).ptr_to() &&
1916 member_llvm_types[4] == content_llvm_type
1920 fn fixed_vec_metadata(cx: &CrateContext,
1921 element_type: ty::t,
1925 let element_type_metadata = type_metadata(cx, element_type, span);
1926 let element_llvm_type = type_of::type_of(cx, element_type);
1927 let (element_type_size, element_type_align) = size_and_align_of(cx, element_llvm_type);
1929 let subrange = unsafe {
1930 llvm::LLVMDIBuilderGetOrCreateSubrange(
1936 let subscripts = create_DIArray(DIB(cx), [subrange]);
1938 llvm::LLVMDIBuilderCreateArrayType(
1940 bytes_to_bits(element_type_size * (len as u64)),
1941 bytes_to_bits(element_type_align),
1942 element_type_metadata,
1947 fn vec_metadata(cx: &CrateContext,
1948 element_type: ty::t,
1950 -> DICompositeType {
1952 let element_type_metadata = type_metadata(cx, element_type, span);
1953 let element_llvm_type = type_of::type_of(cx, element_type);
1954 let (element_size, element_align) = size_and_align_of(cx, element_llvm_type);
1956 let vec_llvm_type = Type::vec(cx, &element_llvm_type);
1957 let vec_type_name: &str = format!("[{}]", ppaux::ty_to_str(cx.tcx(), element_type));
1959 let member_llvm_types = vec_llvm_type.field_types();
1961 let int_type_metadata = type_metadata(cx, ty::mk_int(), span);
1962 let array_type_metadata = unsafe {
1963 llvm::LLVMDIBuilderCreateArrayType(
1965 bytes_to_bits(element_size),
1966 bytes_to_bits(element_align),
1967 element_type_metadata,
1968 create_DIArray(DIB(cx), [llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, 0)]))
1971 let member_descriptions = [
1974 llvm_type: *member_llvm_types.get(0),
1975 type_metadata: int_type_metadata,
1976 offset: ComputedMemberOffset,
1980 llvm_type: *member_llvm_types.get(1),
1981 type_metadata: int_type_metadata,
1982 offset: ComputedMemberOffset,
1986 llvm_type: *member_llvm_types.get(2),
1987 type_metadata: array_type_metadata,
1988 offset: ComputedMemberOffset,
1992 assert!(member_descriptions.len() == member_llvm_types.len());
1994 let loc = span_start(cx, span);
1995 let file_metadata = file_metadata(cx, loc.file.name);
1997 composite_type_metadata(
2001 member_descriptions,
2007 fn vec_slice_metadata(cx: &CrateContext,
2009 element_type: ty::t,
2011 -> DICompositeType {
2013 debug!("vec_slice_metadata: {:?}", ty::get(vec_type));
2015 let slice_llvm_type = type_of::type_of(cx, vec_type);
2016 let slice_type_name = ppaux::ty_to_str(cx.tcx(), vec_type);
2018 let member_llvm_types = slice_llvm_type.field_types();
2019 assert!(slice_layout_is_correct(cx,
2020 member_llvm_types.as_slice(),
2023 let data_ptr_type = ty::mk_ptr(cx.tcx(), ty::mt {
2025 mutbl: ast::MutImmutable
2028 let member_descriptions = [
2031 llvm_type: *member_llvm_types.get(0),
2032 type_metadata: type_metadata(cx, data_ptr_type, span),
2033 offset: ComputedMemberOffset,
2037 llvm_type: *member_llvm_types.get(1),
2038 type_metadata: type_metadata(cx, ty::mk_uint(), span),
2039 offset: ComputedMemberOffset,
2043 assert!(member_descriptions.len() == member_llvm_types.len());
2045 let loc = span_start(cx, span);
2046 let file_metadata = file_metadata(cx, loc.file.name);
2048 return composite_type_metadata(
2052 member_descriptions,
2057 fn slice_layout_is_correct(cx: &CrateContext,
2058 member_llvm_types: &[Type],
2059 element_type: ty::t)
2061 member_llvm_types.len() == 2 &&
2062 member_llvm_types[0] == type_of::type_of(cx, element_type).ptr_to() &&
2063 member_llvm_types[1] == cx.int_type
2067 fn subroutine_type_metadata(cx: &CrateContext,
2068 signature: &ty::FnSig,
2070 -> DICompositeType {
2071 let loc = span_start(cx, span);
2072 let file_metadata = file_metadata(cx, loc.file.name);
2074 let mut signature_metadata: Vec<DIType> =
2075 Vec::with_capacity(signature.inputs.len() + 1);
2078 signature_metadata.push(match ty::get(signature.output).sty {
2079 ty::ty_nil => ptr::null(),
2080 _ => type_metadata(cx, signature.output, span)
2083 // regular arguments
2084 for &argument_type in signature.inputs.iter() {
2085 signature_metadata.push(type_metadata(cx, argument_type, span));
2089 llvm::LLVMDIBuilderCreateSubroutineType(
2092 create_DIArray(DIB(cx), signature_metadata.as_slice()))
2096 fn trait_metadata(cx: &CrateContext,
2099 substs: &ty::substs,
2100 trait_store: ty::TraitStore,
2101 mutability: ast::Mutability,
2102 _: &ty::BuiltinBounds)
2104 // The implementation provided here is a stub. It makes sure that the trait type is
2105 // assigned the correct name, size, namespace, and source location. But it does not describe
2106 // the trait's methods.
2107 let last = ty::with_path(cx.tcx(), def_id, |mut path| path.last().unwrap());
2108 let ident_string = token::get_name(last.name());
2109 let name = ppaux::trait_store_to_str(cx.tcx(), trait_store) +
2110 ppaux::mutability_to_str(mutability) +
2112 // Add type and region parameters
2113 let name = ppaux::parameterized(cx.tcx(), name, &substs.regions,
2114 substs.tps.as_slice(), def_id, true);
2116 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id);
2118 let file_name = span_start(cx, definition_span).file.name.clone();
2119 let file_metadata = file_metadata(cx, file_name);
2121 let trait_llvm_type = type_of::type_of(cx, trait_type);
2123 return composite_type_metadata(cx,
2132 fn type_metadata(cx: &CrateContext,
2134 usage_site_span: Span)
2136 let cache_id = cache_id_for_type(t);
2138 match debug_context(cx).created_types.borrow().find(&cache_id) {
2139 Some(type_metadata) => return *type_metadata,
2143 fn create_pointer_to_box_metadata(cx: &CrateContext,
2144 pointer_type: ty::t,
2147 let content_type_name: &str = ppaux::ty_to_str(cx.tcx(), type_in_box);
2148 let content_llvm_type = type_of::type_of(cx, type_in_box);
2149 let content_type_metadata = type_metadata(
2154 let box_metadata = boxed_type_metadata(
2156 Some(content_type_name),
2158 content_type_metadata,
2161 pointer_type_metadata(cx, pointer_type, box_metadata)
2164 debug!("type_metadata: {:?}", ty::get(t));
2166 let sty = &ty::get(t).sty;
2167 let type_metadata = match *sty {
2174 ty::ty_float(_) => {
2175 basic_type_metadata(cx, t)
2177 ty::ty_str(ref vstore) => {
2178 let i8_t = ty::mk_i8();
2180 ty::vstore_fixed(len) => {
2181 fixed_vec_metadata(cx, i8_t, len, usage_site_span)
2183 ty::vstore_uniq => {
2184 let vec_metadata = vec_metadata(cx, i8_t, usage_site_span);
2185 pointer_type_metadata(cx, t, vec_metadata)
2187 ty::vstore_slice(_region) => {
2188 vec_slice_metadata(cx, t, i8_t, usage_site_span)
2192 ty::ty_enum(def_id, _) => {
2193 prepare_enum_metadata(cx, t, def_id, usage_site_span).finalize(cx)
2195 ty::ty_box(typ) => {
2196 create_pointer_to_box_metadata(cx, t, typ)
2198 ty::ty_vec(ref mt, ref vstore) => {
2200 ty::vstore_fixed(len) => {
2201 fixed_vec_metadata(cx, mt.ty, len, usage_site_span)
2203 ty::vstore_uniq => {
2204 let vec_metadata = vec_metadata(cx, mt.ty, usage_site_span);
2205 pointer_type_metadata(cx, t, vec_metadata)
2207 ty::vstore_slice(_) => {
2208 vec_slice_metadata(cx, t, mt.ty, usage_site_span)
2212 ty::ty_uniq(typ) => {
2213 let pointee = type_metadata(cx, typ, usage_site_span);
2214 pointer_type_metadata(cx, t, pointee)
2216 ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => {
2217 let pointee = type_metadata(cx, mt.ty, usage_site_span);
2218 pointer_type_metadata(cx, t, pointee)
2220 ty::ty_bare_fn(ref barefnty) => {
2221 subroutine_type_metadata(cx, &barefnty.sig, usage_site_span)
2223 ty::ty_closure(ref closurety) => {
2224 subroutine_type_metadata(cx, &closurety.sig, usage_site_span)
2226 ty::ty_trait(~ty::TyTrait { def_id, ref substs,
2227 store: trait_store, mutability,
2229 trait_metadata(cx, def_id, t, substs, trait_store, mutability, bounds)
2231 ty::ty_struct(def_id, ref substs) => {
2232 if ty::type_is_simd(cx.tcx(), t) {
2233 let element_type = ty::simd_type(cx.tcx(), t);
2234 let len = ty::simd_size(cx.tcx(), t);
2235 fixed_vec_metadata(cx, element_type, len, usage_site_span)
2237 prepare_struct_metadata(cx, t, def_id, substs, usage_site_span).finalize(cx)
2240 ty::ty_tup(ref elements) => {
2241 prepare_tuple_metadata(cx,
2243 elements.as_slice(),
2244 usage_site_span).finalize(cx)
2246 _ => cx.sess().bug(format!("debuginfo: unexpected type in type_metadata: {:?}", sty))
2249 debug_context(cx).created_types.borrow_mut().insert(cache_id, type_metadata);
2254 enum DebugLocation {
2255 KnownLocation { scope: DIScope, line: uint, col: uint },
2259 impl DebugLocation {
2260 fn new(scope: DIScope, line: uint, col: uint) -> DebugLocation {
2269 fn set_debug_location(cx: &CrateContext, debug_location: DebugLocation) {
2270 if debug_location == debug_context(cx).current_debug_location.get() {
2276 match debug_location {
2277 KnownLocation { scope, line, .. } => {
2278 let col = 0; // Always set the column to zero like Clang and GCC
2279 debug!("setting debug location to {} {}", line, col);
2280 let elements = [C_i32(cx, line as i32), C_i32(cx, col as i32), scope, ptr::null()];
2282 metadata_node = llvm::LLVMMDNodeInContext(debug_context(cx).llcontext,
2284 elements.len() as c_uint);
2287 UnknownLocation => {
2288 debug!("clearing debug location ");
2289 metadata_node = ptr::null();
2294 llvm::LLVMSetCurrentDebugLocation(cx.builder.b, metadata_node);
2297 debug_context(cx).current_debug_location.set(debug_location);
2300 //=-------------------------------------------------------------------------------------------------
2301 // Utility Functions
2302 //=-------------------------------------------------------------------------------------------------
2304 fn cache_id_for_type(t: ty::t) -> uint {
2308 // Used to avoid LLVM metadata uniquing problems. See `create_struct_stub()` and
2309 // `prepare_enum_metadata()`.
2310 fn generate_unique_type_id(prefix: &'static str) -> ~str {
2312 static mut unique_id_counter: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;
2313 format!("{}{}", prefix, unique_id_counter.fetch_add(1, atomics::SeqCst))
2317 /// Return codemap::Loc corresponding to the beginning of the span
2318 fn span_start(cx: &CrateContext, span: Span) -> codemap::Loc {
2319 cx.sess().codemap().lookup_char_pos(span.lo)
2322 fn size_and_align_of(cx: &CrateContext, llvm_type: Type) -> (u64, u64) {
2323 (machine::llsize_of_alloc(cx, llvm_type), machine::llalign_of_min(cx, llvm_type))
2326 fn bytes_to_bits(bytes: u64) -> c_ulonglong {
2327 (bytes * 8) as c_ulonglong
2331 fn debug_context<'a>(cx: &'a CrateContext) -> &'a CrateDebugContext {
2332 let debug_context: &'a CrateDebugContext = cx.dbg_cx.get_ref();
2337 fn DIB(cx: &CrateContext) -> DIBuilderRef {
2338 cx.dbg_cx.get_ref().builder
2341 fn fn_should_be_ignored(fcx: &FunctionContext) -> bool {
2342 match fcx.debug_context {
2343 FunctionDebugContext(_) => false,
2348 fn assert_type_for_node_id(cx: &CrateContext, node_id: ast::NodeId, error_span: Span) {
2349 if !cx.tcx.node_types.borrow().contains_key(&(node_id as uint)) {
2350 cx.sess().span_bug(error_span, "debuginfo: Could not find type for node id!");
2354 fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: ast::DefId)
2355 -> (DIScope, Span) {
2356 let containing_scope = namespace_for_item(cx, def_id).scope;
2357 let definition_span = if def_id.krate == ast::LOCAL_CRATE {
2358 cx.tcx.map.span(def_id.node)
2360 // For external items there is no span information
2364 (containing_scope, definition_span)
2367 // This procedure builds the *scope map* for a given function, which maps any given ast::NodeId in
2368 // the function's AST to the correct DIScope metadata instance.
2370 // This builder procedure walks the AST in execution order and keeps track of what belongs to which
2371 // scope, creating DIScope DIEs along the way, and introducing *artificial* lexical scope
2372 // descriptors where necessary. These artificial scopes allow GDB to correctly handle name
2374 fn populate_scope_map(cx: &CrateContext,
2375 arg_pats: &[@ast::Pat],
2376 fn_entry_block: &ast::Block,
2377 fn_metadata: DISubprogram,
2378 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2379 let def_map = cx.tcx.def_map;
2381 struct ScopeStackEntry {
2382 scope_metadata: DIScope,
2383 ident: Option<ast::Ident>
2386 let mut scope_stack = vec!(ScopeStackEntry { scope_metadata: fn_metadata, ident: None });
2388 // Push argument identifiers onto the stack so arguments integrate nicely with variable
2390 for &arg_pat in arg_pats.iter() {
2391 pat_util::pat_bindings(def_map, arg_pat, |_, _, _, path_ref| {
2392 let ident = ast_util::path_to_ident(path_ref);
2393 scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata, ident: Some(ident) });
2397 // Clang creates a separate scope for function bodies, so let's do this too
2399 fn_entry_block.span,
2402 |cx, scope_stack, scope_map| {
2403 walk_block(cx, fn_entry_block, scope_stack, scope_map);
2406 // local helper functions for walking the AST.
2407 fn with_new_scope(cx: &CrateContext,
2409 scope_stack: &mut Vec<ScopeStackEntry> ,
2410 scope_map: &mut HashMap<ast::NodeId, DIScope>,
2411 inner_walk: |&CrateContext,
2412 &mut Vec<ScopeStackEntry> ,
2413 &mut HashMap<ast::NodeId, DIScope>|) {
2414 // Create a new lexical scope and push it onto the stack
2415 let loc = cx.sess().codemap().lookup_char_pos(scope_span.lo);
2416 let file_metadata = file_metadata(cx, loc.file.name);
2417 let parent_scope = scope_stack.last().unwrap().scope_metadata;
2419 let scope_metadata = unsafe {
2420 llvm::LLVMDIBuilderCreateLexicalBlock(
2425 loc.col.to_uint() as c_uint)
2428 scope_stack.push(ScopeStackEntry { scope_metadata: scope_metadata, ident: None });
2430 inner_walk(cx, scope_stack, scope_map);
2432 // pop artificial scopes
2433 while scope_stack.last().unwrap().ident.is_some() {
2437 if scope_stack.last().unwrap().scope_metadata != scope_metadata {
2438 cx.sess().span_bug(scope_span, "debuginfo: Inconsistency in scope management.");
2444 fn walk_block(cx: &CrateContext,
2446 scope_stack: &mut Vec<ScopeStackEntry> ,
2447 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2448 scope_map.insert(block.id, scope_stack.last().unwrap().scope_metadata);
2450 // The interesting things here are statements and the concluding expression.
2451 for statement in block.stmts.iter() {
2452 scope_map.insert(ast_util::stmt_id(*statement),
2453 scope_stack.last().unwrap().scope_metadata);
2455 match statement.node {
2456 ast::StmtDecl(decl, _) => walk_decl(cx, decl, scope_stack, scope_map),
2457 ast::StmtExpr(exp, _) |
2458 ast::StmtSemi(exp, _) => walk_expr(cx, exp, scope_stack, scope_map),
2459 ast::StmtMac(..) => () // ignore macros (which should be expanded anyway)
2463 for exp in block.expr.iter() {
2464 walk_expr(cx, *exp, scope_stack, scope_map);
2468 fn walk_decl(cx: &CrateContext,
2470 scope_stack: &mut Vec<ScopeStackEntry> ,
2471 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2473 codemap::Spanned { node: ast::DeclLocal(local), .. } => {
2474 scope_map.insert(local.id, scope_stack.last().unwrap().scope_metadata);
2476 walk_pattern(cx, local.pat, scope_stack, scope_map);
2478 for exp in local.init.iter() {
2479 walk_expr(cx, *exp, scope_stack, scope_map);
2486 fn walk_pattern(cx: &CrateContext,
2488 scope_stack: &mut Vec<ScopeStackEntry> ,
2489 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2491 let def_map = cx.tcx.def_map;
2493 // Unfortunately, we cannot just use pat_util::pat_bindings() or ast_util::walk_pat() here
2494 // because we have to visit *all* nodes in order to put them into the scope map. The above
2495 // functions don't do that.
2497 ast::PatIdent(_, ref path_ref, ref sub_pat_opt) => {
2499 // Check if this is a binding. If so we need to put it on the scope stack and maybe
2500 // introduce an articial scope
2501 if pat_util::pat_is_binding(def_map, pat) {
2503 let ident = ast_util::path_to_ident(path_ref);
2505 // LLVM does not properly generate 'DW_AT_start_scope' fields for variable DIEs.
2506 // For this reason we have to introduce an artificial scope at bindings whenever
2507 // a variable with the same name is declared in *any* parent scope.
2509 // Otherwise the following error occurs:
2513 // do_something(); // 'gdb print x' correctly prints 10
2516 // do_something(); // 'gdb print x' prints 0, because it already reads the
2517 // // uninitialized 'x' from the next line...
2519 // do_something(); // 'gdb print x' correctly prints 100
2522 // Is there already a binding with that name?
2523 // N.B.: this comparison must be UNhygienic... because
2524 // gdb knows nothing about the context, so any two
2525 // variables with the same name will cause the problem.
2526 let need_new_scope = scope_stack
2528 .any(|entry| entry.ident.iter().any(|i| i.name == ident.name));
2531 // Create a new lexical scope and push it onto the stack
2532 let loc = cx.sess().codemap().lookup_char_pos(pat.span.lo);
2533 let file_metadata = file_metadata(cx, loc.file.name);
2534 let parent_scope = scope_stack.last().unwrap().scope_metadata;
2536 let scope_metadata = unsafe {
2537 llvm::LLVMDIBuilderCreateLexicalBlock(
2542 loc.col.to_uint() as c_uint)
2545 scope_stack.push(ScopeStackEntry {
2546 scope_metadata: scope_metadata,
2551 // Push a new entry anyway so the name can be found
2552 let prev_metadata = scope_stack.last().unwrap().scope_metadata;
2553 scope_stack.push(ScopeStackEntry {
2554 scope_metadata: prev_metadata,
2560 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2562 for &sub_pat in sub_pat_opt.iter() {
2563 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2567 ast::PatWild | ast::PatWildMulti => {
2568 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2571 ast::PatEnum(_, ref sub_pats_opt) => {
2572 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2574 for ref sub_pats in sub_pats_opt.iter() {
2575 for &p in sub_pats.iter() {
2576 walk_pattern(cx, p, scope_stack, scope_map);
2581 ast::PatStruct(_, ref field_pats, _) => {
2582 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2584 for &ast::FieldPat { pat: sub_pat, .. } in field_pats.iter() {
2585 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2589 ast::PatTup(ref sub_pats) => {
2590 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2592 for &sub_pat in sub_pats.iter() {
2593 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2597 ast::PatUniq(sub_pat) | ast::PatRegion(sub_pat) => {
2598 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2599 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2602 ast::PatLit(exp) => {
2603 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2604 walk_expr(cx, exp, scope_stack, scope_map);
2607 ast::PatRange(exp1, exp2) => {
2608 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2609 walk_expr(cx, exp1, scope_stack, scope_map);
2610 walk_expr(cx, exp2, scope_stack, scope_map);
2613 ast::PatVec(ref front_sub_pats, ref middle_sub_pats, ref back_sub_pats) => {
2614 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2616 for &sub_pat in front_sub_pats.iter() {
2617 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2620 for &sub_pat in middle_sub_pats.iter() {
2621 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2624 for &sub_pat in back_sub_pats.iter() {
2625 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2631 fn walk_expr(cx: &CrateContext,
2633 scope_stack: &mut Vec<ScopeStackEntry> ,
2634 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2636 scope_map.insert(exp.id, scope_stack.last().unwrap().scope_metadata);
2642 ast::ExprPath(_) => {}
2644 ast::ExprVstore(sub_exp, _) |
2645 ast::ExprCast(sub_exp, _) |
2646 ast::ExprAddrOf(_, sub_exp) |
2647 ast::ExprField(sub_exp, _, _) |
2648 ast::ExprParen(sub_exp) => walk_expr(cx, sub_exp, scope_stack, scope_map),
2650 ast::ExprBox(place, sub_expr) => {
2651 walk_expr(cx, place, scope_stack, scope_map);
2652 walk_expr(cx, sub_expr, scope_stack, scope_map);
2655 ast::ExprRet(exp_opt) => match exp_opt {
2656 Some(sub_exp) => walk_expr(cx, sub_exp, scope_stack, scope_map),
2660 ast::ExprUnary(_, sub_exp) => {
2661 walk_expr(cx, sub_exp, scope_stack, scope_map);
2664 ast::ExprAssignOp(_, lhs, rhs) |
2665 ast::ExprIndex(lhs, rhs) |
2666 ast::ExprBinary(_, lhs, rhs) => {
2667 walk_expr(cx, lhs, scope_stack, scope_map);
2668 walk_expr(cx, rhs, scope_stack, scope_map);
2671 ast::ExprVec(ref init_expressions) |
2672 ast::ExprTup(ref init_expressions) => {
2673 for ie in init_expressions.iter() {
2674 walk_expr(cx, *ie, scope_stack, scope_map);
2678 ast::ExprAssign(sub_exp1, sub_exp2) |
2679 ast::ExprRepeat(sub_exp1, sub_exp2) => {
2680 walk_expr(cx, sub_exp1, scope_stack, scope_map);
2681 walk_expr(cx, sub_exp2, scope_stack, scope_map);
2684 ast::ExprIf(cond_exp, then_block, ref opt_else_exp) => {
2685 walk_expr(cx, cond_exp, scope_stack, scope_map);
2691 |cx, scope_stack, scope_map| {
2692 walk_block(cx, then_block, scope_stack, scope_map);
2695 match *opt_else_exp {
2696 Some(else_exp) => walk_expr(cx, else_exp, scope_stack, scope_map),
2701 ast::ExprWhile(cond_exp, loop_body) => {
2702 walk_expr(cx, cond_exp, scope_stack, scope_map);
2708 |cx, scope_stack, scope_map| {
2709 walk_block(cx, loop_body, scope_stack, scope_map);
2713 ast::ExprForLoop(_, _, _, _) => {
2714 cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \
2715 Found unexpanded for-loop.");
2718 ast::ExprMac(_) => {
2719 cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \
2720 Found unexpanded macro.");
2723 ast::ExprLoop(block, _) |
2724 ast::ExprBlock(block) => {
2729 |cx, scope_stack, scope_map| {
2730 walk_block(cx, block, scope_stack, scope_map);
2734 ast::ExprFnBlock(decl, block) |
2735 ast::ExprProc(decl, block) => {
2740 |cx, scope_stack, scope_map| {
2741 for &ast::Arg { pat: pattern, .. } in decl.inputs.iter() {
2742 walk_pattern(cx, pattern, scope_stack, scope_map);
2745 walk_block(cx, block, scope_stack, scope_map);
2749 ast::ExprCall(fn_exp, ref args) => {
2750 walk_expr(cx, fn_exp, scope_stack, scope_map);
2752 for arg_exp in args.iter() {
2753 walk_expr(cx, *arg_exp, scope_stack, scope_map);
2757 ast::ExprMethodCall(_, _, ref args) => {
2758 for arg_exp in args.iter() {
2759 walk_expr(cx, *arg_exp, scope_stack, scope_map);
2763 ast::ExprMatch(discriminant_exp, ref arms) => {
2764 walk_expr(cx, discriminant_exp, scope_stack, scope_map);
2766 // for each arm we have to first walk the pattern as these might introduce new
2767 // artificial scopes. It should be sufficient to walk only one pattern per arm, as
2768 // they all must contain the same binding names
2770 for arm_ref in arms.iter() {
2771 let arm_span = arm_ref.pats.get(0).span;
2777 |cx, scope_stack, scope_map| {
2778 for &pat in arm_ref.pats.iter() {
2779 walk_pattern(cx, pat, scope_stack, scope_map);
2782 for guard_exp in arm_ref.guard.iter() {
2783 walk_expr(cx, *guard_exp, scope_stack, scope_map)
2786 walk_expr(cx, arm_ref.body, scope_stack, scope_map);
2791 ast::ExprStruct(_, ref fields, ref base_exp) => {
2792 for &ast::Field { expr: exp, .. } in fields.iter() {
2793 walk_expr(cx, exp, scope_stack, scope_map);
2797 Some(exp) => walk_expr(cx, exp, scope_stack, scope_map),
2802 ast::ExprInlineAsm(ast::InlineAsm { inputs: ref inputs,
2803 outputs: ref outputs,
2805 // inputs, outputs: ~[(~str, @expr)]
2806 for &(_, exp) in inputs.iter() {
2807 walk_expr(cx, exp, scope_stack, scope_map);
2810 for &(_, exp) in outputs.iter() {
2811 walk_expr(cx, exp, scope_stack, scope_map);
2819 //=-------------------------------------------------------------------------------------------------
2820 // Namespace Handling
2821 //=-------------------------------------------------------------------------------------------------
2823 struct NamespaceTreeNode {
2826 parent: Option<@NamespaceTreeNode>,
2829 impl NamespaceTreeNode {
2830 fn mangled_name_of_contained_item(&self, item_name: &str) -> ~str {
2831 fn fill_nested(node: &NamespaceTreeNode, output: &mut StrBuf) {
2833 Some(parent) => fill_nested(parent, output),
2836 let string = token::get_name(node.name);
2837 output.push_str(format!("{}", string.get().len()));
2838 output.push_str(string.get());
2841 let mut name = StrBuf::from_str("_ZN");
2842 fill_nested(self, &mut name);
2843 name.push_str(format!("{}", item_name.len()));
2844 name.push_str(item_name);
2845 name.push_char('E');
2850 fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> @NamespaceTreeNode {
2851 ty::with_path(cx.tcx(), def_id, |path| {
2852 // prepend crate name if not already present
2853 let krate = if def_id.krate == ast::LOCAL_CRATE {
2854 let crate_namespace_ident = token::str_to_ident(cx.link_meta.crateid.name);
2855 Some(ast_map::PathMod(crate_namespace_ident.name))
2859 let mut path = krate.move_iter().chain(path).peekable();
2861 let mut current_key = Vec::new();
2862 let mut parent_node: Option<@NamespaceTreeNode> = None;
2864 // Create/Lookup namespace for each element of the path.
2866 // Emulate a for loop so we can use peek below.
2867 let path_element = match path.next() {
2871 // Ignore the name of the item (the last path element).
2872 if path.peek().is_none() {
2876 let name = path_element.name();
2877 current_key.push(name);
2879 let existing_node = debug_context(cx).namespace_map.borrow()
2880 .find_copy(¤t_key);
2881 let current_node = match existing_node {
2882 Some(existing_node) => existing_node,
2884 // create and insert
2885 let parent_scope = match parent_node {
2886 Some(node) => node.scope,
2889 let namespace_name = token::get_name(name);
2890 let scope = namespace_name.get().with_c_str(|namespace_name| {
2892 llvm::LLVMDIBuilderCreateNameSpace(
2896 // cannot reconstruct file ...
2898 // ... or line information, but that's not so important.
2903 let node = @NamespaceTreeNode {
2906 parent: parent_node,
2909 debug_context(cx).namespace_map.borrow_mut()
2910 .insert(current_key.clone(), node);
2916 parent_node = Some(current_node);
2922 cx.sess().bug(format!("debuginfo::namespace_for_item(): \
2923 path too short for {:?}", def_id));