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 std::rc::{Rc, Weak};
148 use collections::HashMap;
149 use collections::HashSet;
150 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>, Rc<NamespaceTreeNode>>>,
185 // This collection is used to assert that composite types (structs, enums, ...) have their
186 // members only set once:
187 composite_types_completed: RefCell<HashSet<DIType>>,
190 impl CrateDebugContext {
191 pub fn new(llmod: ModuleRef) -> CrateDebugContext {
192 debug!("CrateDebugContext::new");
193 let builder = unsafe { llvm::LLVMDIBuilderCreate(llmod) };
194 // DIBuilder inherits context from the module, so we'd better use the same one
195 let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
196 return CrateDebugContext {
197 llcontext: llcontext,
199 current_debug_location: Cell::new(UnknownLocation),
200 created_files: RefCell::new(HashMap::new()),
201 created_types: RefCell::new(HashMap::new()),
202 created_enum_disr_types: RefCell::new(HashMap::new()),
203 namespace_map: RefCell::new(HashMap::new()),
204 composite_types_completed: RefCell::new(HashSet::new()),
209 pub struct FunctionDebugContext {
210 repr: FunctionDebugContextRepr,
213 enum FunctionDebugContextRepr {
214 FunctionDebugContext(~FunctionDebugContextData),
216 FunctionWithoutDebugInfo,
219 impl FunctionDebugContext {
220 fn get_ref<'a>(&'a self, cx: &CrateContext, span: Span) -> &'a FunctionDebugContextData {
222 FunctionDebugContext(~ref data) => data,
223 DebugInfoDisabled => {
224 cx.sess().span_bug(span, FunctionDebugContext::debuginfo_disabled_message());
226 FunctionWithoutDebugInfo => {
227 cx.sess().span_bug(span, FunctionDebugContext::should_be_ignored_message());
232 fn debuginfo_disabled_message() -> &'static str {
233 "debuginfo: Error trying to access FunctionDebugContext although debug info is disabled!"
236 fn should_be_ignored_message() -> &'static str {
237 "debuginfo: Error trying to access FunctionDebugContext for function that should be \
238 ignored by debug info!"
242 struct FunctionDebugContextData {
243 scope_map: RefCell<HashMap<ast::NodeId, DIScope>>,
244 fn_metadata: DISubprogram,
245 argument_counter: Cell<uint>,
246 source_locations_enabled: Cell<bool>,
249 enum VariableAccess<'a> {
250 // The llptr given is an alloca containing the variable's value
251 DirectVariable { alloca: ValueRef },
252 // The llptr given is an alloca containing the start of some pointer chain leading to the
253 // variable's content.
254 IndirectVariable { alloca: ValueRef, address_operations: &'a [ValueRef] }
258 ArgumentVariable(uint /*index*/),
263 /// Create any deferred debug metadata nodes
264 pub fn finalize(cx: &CrateContext) {
265 if cx.dbg_cx.is_none() {
270 compile_unit_metadata(cx);
272 llvm::LLVMDIBuilderFinalize(DIB(cx));
273 llvm::LLVMDIBuilderDispose(DIB(cx));
274 // Debuginfo generation in LLVM by default uses a higher
275 // version of dwarf than OS X currently understands. We can
276 // instruct LLVM to emit an older version of dwarf, however,
277 // for OS X to understand. For more info see #11352
278 // This can be overridden using --llvm-opts -dwarf-version,N.
279 if cx.sess().targ_cfg.os == abi::OsMacos {
280 "Dwarf Version".with_c_str(
281 |s| llvm::LLVMRustAddModuleFlag(cx.llmod, s, 2));
283 // FIXME(#13611) this is a kludge fix because the linux bots have
284 // gdb 7.4 which doesn't understand dwarf4, we should
285 // do something more graceful here.
286 "Dwarf Version".with_c_str(
287 |s| llvm::LLVMRustAddModuleFlag(cx.llmod, s, 3));
290 // Prevent bitcode readers from deleting the debug info.
291 "Debug Info Version".with_c_str(
292 |s| llvm::LLVMRustAddModuleFlag(cx.llmod, s,
293 llvm::LLVMRustDebugMetadataVersion));
297 /// Creates debug information for the given global variable.
299 /// Adds the created metadata nodes directly to the crate's IR.
300 pub fn create_global_var_metadata(cx: &CrateContext,
301 node_id: ast::NodeId,
303 if cx.dbg_cx.is_none() {
307 // Don't create debuginfo for globals inlined from other crates. The other crate should already
308 // contain debuginfo for it. More importantly, the global might not even exist in un-inlined
309 // form anywhere which would lead to a linker errors.
310 if cx.external_srcs.borrow().contains_key(&node_id) {
314 let var_item = cx.tcx.map.get(node_id);
316 let (ident, span) = match var_item {
317 ast_map::NodeItem(item) => {
319 ast::ItemStatic(..) => (item.ident, item.span),
320 _ => cx.sess().span_bug(item.span,
321 format!("debuginfo::create_global_var_metadata() -
322 Captured var-id refers to unexpected ast_item
327 _ => cx.sess().bug(format!("debuginfo::create_global_var_metadata() - Captured var-id \
328 refers to unexpected ast_map variant: {:?}",
332 let filename = span_start(cx, span).file.name.clone();
333 let file_metadata = file_metadata(cx, filename);
335 let is_local_to_unit = is_node_local_to_unit(cx, node_id);
336 let loc = span_start(cx, span);
338 let variable_type = ty::node_id_to_type(cx.tcx(), node_id);
339 let type_metadata = type_metadata(cx, variable_type, span);
341 let namespace_node = namespace_for_item(cx, ast_util::local_def(node_id));
342 let var_name = token::get_ident(ident).get().to_str();
343 let linkage_name = namespace_node.mangled_name_of_contained_item(var_name);
344 let var_scope = namespace_node.scope;
346 var_name.with_c_str(|var_name| {
347 linkage_name.with_c_str(|linkage_name| {
349 llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx),
364 /// Creates debug information for the given local variable.
366 /// Adds the created metadata nodes directly to the crate's IR.
367 pub fn create_local_var_metadata(bcx: &Block, local: &ast::Local) {
368 if fn_should_be_ignored(bcx.fcx) {
373 let def_map = &cx.tcx.def_map;
375 pat_util::pat_bindings(def_map, local.pat, |_, node_id, span, path_ref| {
376 let var_ident = ast_util::path_to_ident(path_ref);
378 let datum = match bcx.fcx.lllocals.borrow().find_copy(&node_id) {
379 Some(datum) => datum,
381 bcx.sess().span_bug(span,
382 format!("no entry in lllocals table for {:?}",
387 let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
393 DirectVariable { alloca: datum.val },
399 /// Creates debug information for a variable captured in a closure.
401 /// Adds the created metadata nodes directly to the crate's IR.
402 pub fn create_captured_var_metadata(bcx: &Block,
403 node_id: ast::NodeId,
404 env_data_type: ty::t,
405 env_pointer: ValueRef,
407 closure_store: ty::TraitStore,
409 if fn_should_be_ignored(bcx.fcx) {
415 let ast_item = cx.tcx.map.find(node_id);
417 let variable_ident = match ast_item {
419 cx.sess().span_bug(span, "debuginfo::create_captured_var_metadata: node not found");
421 Some(ast_map::NodeLocal(pat)) | Some(ast_map::NodeArg(pat)) => {
423 ast::PatIdent(_, ref path, _) => {
424 ast_util::path_to_ident(path)
430 "debuginfo::create_captured_var_metadata() - \
431 Captured var-id refers to unexpected \
432 ast_map variant: {:?}",
438 cx.sess().span_bug(span, format!("debuginfo::create_captured_var_metadata() - \
439 Captured var-id refers to unexpected ast_map variant: {:?}", ast_item));
443 let variable_type = node_id_type(bcx, node_id);
444 let scope_metadata = bcx.fcx.debug_context.get_ref(cx, span).fn_metadata;
446 let llvm_env_data_type = type_of::type_of(cx, env_data_type);
447 let byte_offset_of_var_in_env = machine::llelement_offset(cx, llvm_env_data_type, env_index);
449 let address_operations = unsafe {
450 [llvm::LLVMDIBuilderCreateOpDeref(Type::i64(cx).to_ref()),
451 llvm::LLVMDIBuilderCreateOpPlus(Type::i64(cx).to_ref()),
452 C_i64(cx, byte_offset_of_var_in_env as i64),
453 llvm::LLVMDIBuilderCreateOpDeref(Type::i64(cx).to_ref())]
456 let address_op_count = match closure_store {
457 ty::RegionTraitStore(..) => {
458 address_operations.len()
460 ty::UniqTraitStore => {
461 address_operations.len() - 1
465 let variable_access = IndirectVariable {
467 address_operations: address_operations.slice_to(address_op_count)
479 /// Creates debug information for a local variable introduced in the head of a match-statement arm.
481 /// Adds the created metadata nodes directly to the crate's IR.
482 pub fn create_match_binding_metadata(bcx: &Block,
483 variable_ident: ast::Ident,
484 node_id: ast::NodeId,
486 datum: Datum<Lvalue>) {
487 if fn_should_be_ignored(bcx.fcx) {
491 let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
497 DirectVariable { alloca: datum.val },
502 /// Creates debug information for the given function argument.
504 /// Adds the created metadata nodes directly to the crate's IR.
505 pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
506 if fn_should_be_ignored(bcx.fcx) {
513 let def_map = &cx.tcx.def_map;
514 let scope_metadata = bcx.fcx.debug_context.get_ref(cx, arg.pat.span).fn_metadata;
516 pat_util::pat_bindings(def_map, arg.pat, |_, node_id, span, path_ref| {
517 let llarg = match bcx.fcx.llargs.borrow().find_copy(&node_id) {
520 bcx.sess().span_bug(span,
521 format!("no entry in llargs table for {:?}",
526 if unsafe { llvm::LLVMIsAAllocaInst(llarg.val) } == ptr::null() {
527 cx.sess().span_bug(span, "debuginfo::create_argument_metadata() - \
528 Referenced variable location is not an alloca!");
531 let argument_ident = ast_util::path_to_ident(path_ref);
533 let argument_index = {
534 let counter = &fcx.debug_context.get_ref(cx, span).argument_counter;
535 let argument_index = counter.get();
536 counter.set(argument_index + 1);
544 DirectVariable { alloca: llarg.val },
545 ArgumentVariable(argument_index),
550 /// Sets the current debug location at the beginning of the span.
552 /// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...). The node_id parameter is used to
553 /// reliably find the correct visibility scope for the code position.
554 pub fn set_source_location(fcx: &FunctionContext,
555 node_id: ast::NodeId,
557 match fcx.debug_context.repr {
558 DebugInfoDisabled => return,
559 FunctionWithoutDebugInfo => {
560 set_debug_location(fcx.ccx, UnknownLocation);
563 FunctionDebugContext(~ref function_debug_context) => {
566 debug!("set_source_location: {}", cx.sess().codemap().span_to_str(span));
568 if function_debug_context.source_locations_enabled.get() {
569 let loc = span_start(cx, span);
570 let scope = scope_metadata(fcx, node_id, span);
572 set_debug_location(cx, DebugLocation::new(scope, loc.line, loc.col.to_uint()));
574 set_debug_location(cx, UnknownLocation);
580 /// Clears the current debug location.
582 /// Instructions generated hereafter won't be assigned a source location.
583 pub fn clear_source_location(fcx: &FunctionContext) {
584 if fn_should_be_ignored(fcx) {
588 set_debug_location(fcx.ccx, UnknownLocation);
591 /// Enables emitting source locations for the given functions.
593 /// Since we don't want source locations to be emitted for the function prelude, they are disabled
594 /// when beginning to translate a new function. This functions switches source location emitting on
595 /// and must therefore be called before the first real statement/expression of the function is
597 pub fn start_emitting_source_locations(fcx: &FunctionContext) {
598 match fcx.debug_context.repr {
599 FunctionDebugContext(~ref data) => {
600 data.source_locations_enabled.set(true)
602 _ => { /* safe to ignore */ }
606 /// Creates the function-specific debug context.
608 /// Returns the FunctionDebugContext for the function which holds state needed for debug info
609 /// creation. The function may also return another variant of the FunctionDebugContext enum which
610 /// indicates why no debuginfo should be created for the function.
611 pub fn create_function_debug_context(cx: &CrateContext,
612 fn_ast_id: ast::NodeId,
613 param_substs: Option<¶m_substs>,
614 llfn: ValueRef) -> FunctionDebugContext {
615 if cx.sess().opts.debuginfo == NoDebugInfo {
616 return FunctionDebugContext { repr: DebugInfoDisabled };
619 // Clear the debug location so we don't assign them in the function prelude. Do this here
620 // already, in case we do an early exit from this function.
621 set_debug_location(cx, UnknownLocation);
624 return FunctionDebugContext { repr: FunctionWithoutDebugInfo };
627 let empty_generics = ast::Generics { lifetimes: Vec::new(), ty_params: OwnedSlice::empty() };
629 let fnitem = cx.tcx.map.get(fn_ast_id);
631 let (ident, fn_decl, generics, top_level_block, span, has_path) = match fnitem {
632 ast_map::NodeItem(ref item) => {
634 ast::ItemFn(fn_decl, _, _, ref generics, top_level_block) => {
635 (item.ident, fn_decl, generics, top_level_block, item.span, true)
638 cx.sess().span_bug(item.span,
639 "create_function_debug_context: item bound to non-function");
643 ast_map::NodeMethod(ref method) => {
651 ast_map::NodeExpr(ref expr) => {
653 ast::ExprFnBlock(fn_decl, top_level_block) |
654 ast::ExprProc(fn_decl, top_level_block) => {
655 let name = format!("fn{}", token::gensym("fn"));
656 let name = token::str_to_ident(name);
658 // This is not quite right. It should actually inherit the generics of the
659 // enclosing function.
663 // Don't try to lookup the item path:
666 _ => cx.sess().span_bug(expr.span,
667 "create_function_debug_context: expected an expr_fn_block here")
670 ast_map::NodeTraitMethod(ref trait_method) => {
671 match **trait_method {
672 ast::Provided(ref method) => {
682 .bug(format!("create_function_debug_context: \
683 unexpected sort of node: {:?}",
688 ast_map::NodeForeignItem(..) |
689 ast_map::NodeVariant(..) |
690 ast_map::NodeStructCtor(..) => {
691 return FunctionDebugContext { repr: FunctionWithoutDebugInfo };
693 _ => cx.sess().bug(format!("create_function_debug_context: \
694 unexpected sort of node: {:?}", fnitem))
697 // This can be the case for functions inlined from another crate
698 if span == codemap::DUMMY_SP {
699 return FunctionDebugContext { repr: FunctionWithoutDebugInfo };
702 let loc = span_start(cx, span);
703 let file_metadata = file_metadata(cx, loc.file.name);
705 let function_type_metadata = unsafe {
706 let fn_signature = get_function_signature(cx, fn_ast_id, fn_decl, param_substs, span);
707 llvm::LLVMDIBuilderCreateSubroutineType(DIB(cx), file_metadata, fn_signature)
710 // get_template_parameters() will append a `<...>` clause to the function name if necessary.
711 let mut function_name = StrBuf::from_str(token::get_ident(ident).get());
712 let template_parameters = get_template_parameters(cx,
718 // There is no ast_map::Path for ast::ExprFnBlock-type functions. For now, just don't put them
719 // into a namespace. In the future this could be improved somehow (storing a path in the
720 // ast_map, or construct a path using the enclosing function).
721 let (linkage_name, containing_scope) = if has_path {
722 let namespace_node = namespace_for_item(cx, ast_util::local_def(fn_ast_id));
723 let linkage_name = namespace_node.mangled_name_of_contained_item(
724 function_name.as_slice());
725 let containing_scope = namespace_node.scope;
726 (linkage_name, containing_scope)
728 (function_name.as_slice().to_owned(), file_metadata)
731 // Clang sets this parameter to the opening brace of the function's block, so let's do this too.
732 let scope_line = span_start(cx, top_level_block.span).line;
734 let is_local_to_unit = is_node_local_to_unit(cx, fn_ast_id);
736 let fn_metadata = function_name.as_slice().with_c_str(|function_name| {
737 linkage_name.with_c_str(|linkage_name| {
739 llvm::LLVMDIBuilderCreateFunction(
746 function_type_metadata,
749 scope_line as c_uint,
750 FlagPrototyped as c_uint,
751 cx.sess().opts.optimize != session::No,
759 // Initialize fn debug context (including scope map and namespace map)
760 let fn_debug_context = box FunctionDebugContextData {
761 scope_map: RefCell::new(HashMap::new()),
762 fn_metadata: fn_metadata,
763 argument_counter: Cell::new(1),
764 source_locations_enabled: Cell::new(false),
767 let arg_pats = fn_decl.inputs.iter().map(|arg_ref| arg_ref.pat).collect::<Vec<_>>();
768 populate_scope_map(cx,
772 &mut *fn_debug_context.scope_map.borrow_mut());
774 return FunctionDebugContext { repr: FunctionDebugContext(fn_debug_context) };
776 fn get_function_signature(cx: &CrateContext,
777 fn_ast_id: ast::NodeId,
778 fn_decl: &ast::FnDecl,
779 param_substs: Option<¶m_substs>,
780 error_span: Span) -> DIArray {
781 if cx.sess().opts.debuginfo == LimitedDebugInfo {
782 return create_DIArray(DIB(cx), []);
785 let mut signature = Vec::with_capacity(fn_decl.inputs.len() + 1);
787 // Return type -- llvm::DIBuilder wants this at index 0
788 match fn_decl.output.node {
790 signature.push(ptr::null());
793 assert_type_for_node_id(cx, fn_ast_id, error_span);
795 let return_type = ty::node_id_to_type(cx.tcx(), fn_ast_id);
796 let return_type = match param_substs {
799 ty::subst_tps(cx.tcx(),
800 substs.tys.as_slice(),
806 signature.push(type_metadata(cx, return_type, codemap::DUMMY_SP));
811 for arg in fn_decl.inputs.iter() {
812 assert_type_for_node_id(cx, arg.pat.id, arg.pat.span);
813 let arg_type = ty::node_id_to_type(cx.tcx(), arg.pat.id);
814 let arg_type = match param_substs {
817 ty::subst_tps(cx.tcx(),
818 substs.tys.as_slice(),
824 signature.push(type_metadata(cx, arg_type, codemap::DUMMY_SP));
827 return create_DIArray(DIB(cx), signature.as_slice());
830 fn get_template_parameters(cx: &CrateContext,
831 generics: &ast::Generics,
832 param_substs: Option<¶m_substs>,
833 file_metadata: DIFile,
834 name_to_append_suffix_to: &mut StrBuf)
836 let self_type = match param_substs {
837 Some(param_substs) => param_substs.self_ty,
841 // Only true for static default methods:
842 let has_self_type = self_type.is_some();
844 if !generics.is_type_parameterized() && !has_self_type {
845 return create_DIArray(DIB(cx), []);
848 name_to_append_suffix_to.push_char('<');
850 // The list to be filled with template parameters:
851 let mut template_params: Vec<DIDescriptor> =
852 Vec::with_capacity(generics.ty_params.len() + 1);
856 let actual_self_type = self_type.unwrap();
857 // Add self type name to <...> clause of function name
858 let actual_self_type_name = ppaux::ty_to_str(cx.tcx(), actual_self_type);
859 name_to_append_suffix_to.push_str(actual_self_type_name);
861 if generics.is_type_parameterized() {
862 name_to_append_suffix_to.push_str(",");
865 // Only create type information if full debuginfo is enabled
866 if cx.sess().opts.debuginfo == FullDebugInfo {
867 let actual_self_type_metadata = type_metadata(cx,
871 let ident = special_idents::type_self;
873 let param_metadata = token::get_ident(ident).get()
876 llvm::LLVMDIBuilderCreateTemplateTypeParameter(
880 actual_self_type_metadata,
887 template_params.push(param_metadata);
891 // Handle other generic parameters
892 let actual_types = match param_substs {
893 Some(param_substs) => ¶m_substs.tys,
895 return create_DIArray(DIB(cx), template_params.as_slice());
899 for (index, &ast::TyParam{ ident: ident, .. }) in generics.ty_params.iter().enumerate() {
900 let actual_type = *actual_types.get(index);
901 // Add actual type name to <...> clause of function name
902 let actual_type_name = ppaux::ty_to_str(cx.tcx(), actual_type);
903 name_to_append_suffix_to.push_str(actual_type_name);
905 if index != generics.ty_params.len() - 1 {
906 name_to_append_suffix_to.push_str(",");
909 // Again, only create type information if full debuginfo is enabled
910 if cx.sess().opts.debuginfo == FullDebugInfo {
911 let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP);
912 let param_metadata = token::get_ident(ident).get()
915 llvm::LLVMDIBuilderCreateTemplateTypeParameter(
919 actual_type_metadata,
925 template_params.push(param_metadata);
929 name_to_append_suffix_to.push_char('>');
931 return create_DIArray(DIB(cx), template_params.as_slice());
935 //=-------------------------------------------------------------------------------------------------
936 // Module-Internal debug info creation functions
937 //=-------------------------------------------------------------------------------------------------
939 fn is_node_local_to_unit(cx: &CrateContext, node_id: ast::NodeId) -> bool
941 // The is_local_to_unit flag indicates whether a function is local to the current compilation
942 // unit (i.e. if it is *static* in the C-sense). The *reachable* set should provide a good
943 // approximation of this, as it contains everything that might leak out of the current crate
944 // (by being externally visible or by being inlined into something externally visible). It might
945 // better to use the `exported_items` set from `driver::CrateAnalysis` in the future, but (atm)
946 // this set is not available in the translation pass.
947 !cx.reachable.contains(&node_id)
950 fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
952 llvm::LLVMDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32)
956 fn compile_unit_metadata(cx: &CrateContext) {
957 let work_dir = &cx.sess().working_dir;
958 let compile_unit_name = match cx.sess().local_crate_source_file {
959 None => fallback_path(cx),
960 Some(ref abs_path) => {
961 if abs_path.is_relative() {
962 cx.sess().warn("debuginfo: Invalid path to crate's local root source file!");
965 match abs_path.path_relative_from(work_dir) {
966 Some(ref p) if p.is_relative() => {
967 // prepend "./" if necessary
968 let dotdot = bytes!("..");
969 let prefix = &[dotdot[0], ::std::path::SEP_BYTE];
970 let mut path_bytes = Vec::from_slice(p.as_vec());
972 if path_bytes.slice_to(2) != prefix &&
973 path_bytes.slice_to(2) != dotdot {
974 path_bytes.insert(0, prefix[0]);
975 path_bytes.insert(1, prefix[1]);
978 path_bytes.as_slice().to_c_str()
980 _ => fallback_path(cx)
986 debug!("compile_unit_metadata: {:?}", compile_unit_name);
987 let producer = format!("rustc version {}",
988 (option_env!("CFG_VERSION")).expect("CFG_VERSION"));
990 compile_unit_name.with_ref(|compile_unit_name| {
991 work_dir.as_vec().with_c_str(|work_dir| {
992 producer.with_c_str(|producer| {
993 "".with_c_str(|flags| {
994 "".with_c_str(|split_name| {
996 llvm::LLVMDIBuilderCreateCompileUnit(
997 debug_context(cx).builder,
1002 cx.sess().opts.optimize != session::No,
1013 fn fallback_path(cx: &CrateContext) -> CString {
1014 cx.link_meta.crateid.name.to_c_str()
1018 fn declare_local(bcx: &Block,
1019 variable_ident: ast::Ident,
1020 variable_type: ty::t,
1021 scope_metadata: DIScope,
1022 variable_access: VariableAccess,
1023 variable_kind: VariableKind,
1025 let cx: &CrateContext = bcx.ccx();
1027 let filename = span_start(cx, span).file.name.clone();
1028 let file_metadata = file_metadata(cx, filename);
1030 let name = token::get_ident(variable_ident);
1031 let loc = span_start(cx, span);
1032 let type_metadata = type_metadata(cx, variable_type, span);
1034 let (argument_index, dwarf_tag) = match variable_kind {
1035 ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),
1037 CapturedVariable => (0, DW_TAG_auto_variable)
1040 let (var_alloca, var_metadata) = name.get().with_c_str(|name| {
1041 match variable_access {
1042 DirectVariable { alloca } => (
1045 llvm::LLVMDIBuilderCreateLocalVariable(
1053 cx.sess().opts.optimize != session::No,
1058 IndirectVariable { alloca, address_operations } => (
1061 llvm::LLVMDIBuilderCreateComplexVariable(
1069 address_operations.as_ptr(),
1070 address_operations.len() as c_uint,
1077 set_debug_location(cx, DebugLocation::new(scope_metadata, loc.line, loc.col.to_uint()));
1079 let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
1085 llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr);
1088 match variable_kind {
1089 ArgumentVariable(_) | CapturedVariable => {
1093 .source_locations_enabled
1095 set_debug_location(cx, UnknownLocation);
1097 _ => { /* nothing to do */ }
1101 fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
1102 match debug_context(cx).created_files.borrow().find_equiv(&full_path) {
1103 Some(file_metadata) => return *file_metadata,
1107 debug!("file_metadata: {}", full_path);
1109 // FIXME (#9639): This needs to handle non-utf8 paths
1110 let work_dir = cx.sess().working_dir.as_str().unwrap();
1112 if full_path.starts_with(work_dir) {
1113 full_path.slice(work_dir.len() + 1u, full_path.len())
1119 file_name.with_c_str(|file_name| {
1120 work_dir.with_c_str(|work_dir| {
1122 llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir)
1127 let mut created_files = debug_context(cx).created_files.borrow_mut();
1128 created_files.insert(full_path.to_owned(), file_metadata);
1129 return file_metadata;
1132 /// Finds the scope metadata node for the given AST node.
1133 fn scope_metadata(fcx: &FunctionContext,
1134 node_id: ast::NodeId,
1137 let scope_map = &fcx.debug_context.get_ref(fcx.ccx, span).scope_map;
1138 match scope_map.borrow().find_copy(&node_id) {
1139 Some(scope_metadata) => scope_metadata,
1141 let node = fcx.ccx.tcx.map.get(node_id);
1143 fcx.ccx.sess().span_bug(span,
1144 format!("debuginfo: Could not find scope info for node {:?}", node));
1149 fn basic_type_metadata(cx: &CrateContext, t: ty::t) -> DIType {
1151 debug!("basic_type_metadata: {:?}", ty::get(t));
1153 let (name, encoding) = match ty::get(t).sty {
1154 ty::ty_nil => ("()".to_owned(), DW_ATE_unsigned),
1155 ty::ty_bot => ("!".to_owned(), DW_ATE_unsigned),
1156 ty::ty_bool => ("bool".to_owned(), DW_ATE_boolean),
1157 ty::ty_char => ("char".to_owned(), DW_ATE_unsigned_char),
1158 ty::ty_int(int_ty) => match int_ty {
1159 ast::TyI => ("int".to_owned(), DW_ATE_signed),
1160 ast::TyI8 => ("i8".to_owned(), DW_ATE_signed),
1161 ast::TyI16 => ("i16".to_owned(), DW_ATE_signed),
1162 ast::TyI32 => ("i32".to_owned(), DW_ATE_signed),
1163 ast::TyI64 => ("i64".to_owned(), DW_ATE_signed)
1165 ty::ty_uint(uint_ty) => match uint_ty {
1166 ast::TyU => ("uint".to_owned(), DW_ATE_unsigned),
1167 ast::TyU8 => ("u8".to_owned(), DW_ATE_unsigned),
1168 ast::TyU16 => ("u16".to_owned(), DW_ATE_unsigned),
1169 ast::TyU32 => ("u32".to_owned(), DW_ATE_unsigned),
1170 ast::TyU64 => ("u64".to_owned(), DW_ATE_unsigned)
1172 ty::ty_float(float_ty) => match float_ty {
1173 ast::TyF32 => ("f32".to_owned(), DW_ATE_float),
1174 ast::TyF64 => ("f64".to_owned(), DW_ATE_float),
1175 ast::TyF128 => ("f128".to_owned(), DW_ATE_float)
1177 _ => cx.sess().bug("debuginfo::basic_type_metadata - t is invalid type")
1180 let llvm_type = type_of::type_of(cx, t);
1181 let (size, align) = size_and_align_of(cx, llvm_type);
1182 let ty_metadata = name.with_c_str(|name| {
1184 llvm::LLVMDIBuilderCreateBasicType(
1187 bytes_to_bits(size),
1188 bytes_to_bits(align),
1196 fn pointer_type_metadata(cx: &CrateContext,
1197 pointer_type: ty::t,
1198 pointee_type_metadata: DIType)
1200 let pointer_llvm_type = type_of::type_of(cx, pointer_type);
1201 let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
1202 let name = ppaux::ty_to_str(cx.tcx(), pointer_type);
1203 let ptr_metadata = name.with_c_str(|name| {
1205 llvm::LLVMDIBuilderCreatePointerType(
1207 pointee_type_metadata,
1208 bytes_to_bits(pointer_size),
1209 bytes_to_bits(pointer_align),
1213 return ptr_metadata;
1216 enum MemberDescriptionFactory {
1217 StructMD(StructMemberDescriptionFactory),
1218 TupleMD(TupleMemberDescriptionFactory),
1219 GeneralMD(GeneralMemberDescriptionFactory),
1220 EnumVariantMD(EnumVariantMemberDescriptionFactory)
1223 impl MemberDescriptionFactory {
1224 fn create_member_descriptions(&self, cx: &CrateContext)
1225 -> Vec<MemberDescription> {
1227 StructMD(ref this) => {
1228 this.create_member_descriptions(cx)
1230 TupleMD(ref this) => {
1231 this.create_member_descriptions(cx)
1233 GeneralMD(ref this) => {
1234 this.create_member_descriptions(cx)
1236 EnumVariantMD(ref this) => {
1237 this.create_member_descriptions(cx)
1243 struct StructMemberDescriptionFactory {
1244 fields: Vec<ty::field> ,
1248 impl StructMemberDescriptionFactory {
1249 fn create_member_descriptions(&self, cx: &CrateContext)
1250 -> Vec<MemberDescription> {
1251 self.fields.iter().map(|field| {
1252 let name = if field.ident.name == special_idents::unnamed_field.name {
1255 token::get_ident(field.ident).get().to_str()
1260 llvm_type: type_of::type_of(cx, field.mt.ty),
1261 type_metadata: type_metadata(cx, field.mt.ty, self.span),
1262 offset: ComputedMemberOffset,
1268 fn prepare_struct_metadata(cx: &CrateContext,
1271 substs: &ty::substs,
1273 -> RecursiveTypeDescription {
1274 let struct_name = ppaux::ty_to_str(cx.tcx(), struct_type);
1275 let struct_llvm_type = type_of::type_of(cx, struct_type);
1277 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id);
1279 let file_name = span_start(cx, definition_span).file.name.clone();
1280 let file_metadata = file_metadata(cx, file_name);
1282 let struct_metadata_stub = create_struct_stub(cx,
1289 let fields = ty::struct_fields(cx.tcx(), def_id, substs);
1291 UnfinishedMetadata {
1292 cache_id: cache_id_for_type(struct_type),
1293 metadata_stub: struct_metadata_stub,
1294 llvm_type: struct_llvm_type,
1295 file_metadata: file_metadata,
1296 member_description_factory: StructMD(StructMemberDescriptionFactory {
1303 enum RecursiveTypeDescription {
1304 UnfinishedMetadata {
1306 metadata_stub: DICompositeType,
1308 file_metadata: DIFile,
1309 member_description_factory: MemberDescriptionFactory,
1311 FinalMetadata(DICompositeType)
1314 impl RecursiveTypeDescription {
1316 fn finalize(&self, cx: &CrateContext) -> DICompositeType {
1318 FinalMetadata(metadata) => metadata,
1319 UnfinishedMetadata {
1324 ref member_description_factory
1326 // Insert the stub into the cache in order to allow recursive references ...
1327 debug_context(cx).created_types.borrow_mut()
1328 .insert(cache_id, metadata_stub);
1330 // ... then create the member descriptions ...
1331 let member_descriptions = member_description_factory.create_member_descriptions(cx);
1333 // ... and attach them to the stub to complete it.
1334 set_members_of_composite_type(cx,
1337 member_descriptions.as_slice(),
1340 return metadata_stub;
1346 struct TupleMemberDescriptionFactory {
1347 component_types: Vec<ty::t> ,
1351 impl TupleMemberDescriptionFactory {
1352 fn create_member_descriptions(&self, cx: &CrateContext)
1353 -> Vec<MemberDescription> {
1354 self.component_types.iter().map(|&component_type| {
1356 name: "".to_owned(),
1357 llvm_type: type_of::type_of(cx, component_type),
1358 type_metadata: type_metadata(cx, component_type, self.span),
1359 offset: ComputedMemberOffset,
1365 fn prepare_tuple_metadata(cx: &CrateContext,
1367 component_types: &[ty::t],
1369 -> RecursiveTypeDescription {
1370 let tuple_name = ppaux::ty_to_str(cx.tcx(), tuple_type);
1371 let tuple_llvm_type = type_of::type_of(cx, tuple_type);
1373 let loc = span_start(cx, span);
1374 let file_metadata = file_metadata(cx, loc.file.name);
1376 UnfinishedMetadata {
1377 cache_id: cache_id_for_type(tuple_type),
1378 metadata_stub: create_struct_stub(cx,
1384 llvm_type: tuple_llvm_type,
1385 file_metadata: file_metadata,
1386 member_description_factory: TupleMD(TupleMemberDescriptionFactory {
1387 component_types: Vec::from_slice(component_types),
1393 struct GeneralMemberDescriptionFactory {
1394 type_rep: Rc<adt::Repr>,
1395 variants: Rc<Vec<Rc<ty::VariantInfo>>>,
1396 discriminant_type_metadata: ValueRef,
1397 containing_scope: DIScope,
1398 file_metadata: DIFile,
1402 impl GeneralMemberDescriptionFactory {
1403 fn create_member_descriptions(&self, cx: &CrateContext)
1404 -> Vec<MemberDescription> {
1405 // Capture type_rep, so we don't have to copy the struct_defs array
1406 let struct_defs = match *self.type_rep {
1407 adt::General(_, ref struct_defs) => struct_defs,
1408 _ => cx.sess().bug("unreachable")
1414 .map(|(i, struct_def)| {
1415 let (variant_type_metadata, variant_llvm_type, member_desc_factory) =
1416 describe_enum_variant(cx,
1418 &**self.variants.get(i),
1419 Some(self.discriminant_type_metadata),
1420 self.containing_scope,
1424 let member_descriptions =
1425 member_desc_factory.create_member_descriptions(cx);
1427 set_members_of_composite_type(cx,
1428 variant_type_metadata,
1430 member_descriptions.as_slice(),
1434 name: "".to_owned(),
1435 llvm_type: variant_llvm_type,
1436 type_metadata: variant_type_metadata,
1437 offset: FixedMemberOffset { bytes: 0 },
1443 struct EnumVariantMemberDescriptionFactory {
1444 args: Vec<(~str, ty::t)> ,
1445 discriminant_type_metadata: Option<DIType>,
1449 impl EnumVariantMemberDescriptionFactory {
1450 fn create_member_descriptions(&self, cx: &CrateContext)
1451 -> Vec<MemberDescription> {
1452 self.args.iter().enumerate().map(|(i, &(ref name, ty))| {
1454 name: name.to_str(),
1455 llvm_type: type_of::type_of(cx, ty),
1456 type_metadata: match self.discriminant_type_metadata {
1457 Some(metadata) if i == 0 => metadata,
1458 _ => type_metadata(cx, ty, self.span)
1460 offset: ComputedMemberOffset,
1466 fn describe_enum_variant(cx: &CrateContext,
1467 struct_def: &adt::Struct,
1468 variant_info: &ty::VariantInfo,
1469 discriminant_type_metadata: Option<DIType>,
1470 containing_scope: DIScope,
1471 file_metadata: DIFile,
1473 -> (DICompositeType, Type, MemberDescriptionFactory) {
1474 let variant_llvm_type =
1475 Type::struct_(cx, struct_def.fields
1477 .map(|&t| type_of::type_of(cx, t))
1478 .collect::<Vec<_>>()
1481 // Could some consistency checks here: size, align, field count, discr type
1483 // Find the source code location of the variant's definition
1484 let variant_definition_span = if variant_info.id.krate == ast::LOCAL_CRATE {
1485 cx.tcx.map.span(variant_info.id.node)
1487 // For definitions from other crates we have no location information available.
1491 let metadata_stub = create_struct_stub(cx,
1493 token::get_ident(variant_info.name).get(),
1496 variant_definition_span);
1498 // Get the argument names from the enum variant info
1499 let mut arg_names: Vec<_> = match variant_info.arg_names {
1500 Some(ref names) => {
1501 names.iter().map(|ident| token::get_ident(*ident).get().to_str()).collect()
1503 None => variant_info.args.iter().map(|_| "".to_owned()).collect()
1506 // If this is not a univariant enum, there is also the (unnamed) discriminant field
1507 if discriminant_type_metadata.is_some() {
1508 arg_names.insert(0, "".to_owned());
1511 // Build an array of (field name, field type) pairs to be captured in the factory closure.
1512 let args: Vec<(~str, ty::t)> = arg_names.iter()
1513 .zip(struct_def.fields.iter())
1514 .map(|(s, &t)| (s.to_str(), t))
1517 let member_description_factory =
1518 EnumVariantMD(EnumVariantMemberDescriptionFactory {
1520 discriminant_type_metadata: discriminant_type_metadata,
1524 (metadata_stub, variant_llvm_type, member_description_factory)
1527 fn prepare_enum_metadata(cx: &CrateContext,
1529 enum_def_id: ast::DefId,
1531 -> RecursiveTypeDescription {
1532 let enum_name = ppaux::ty_to_str(cx.tcx(), enum_type);
1534 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, enum_def_id);
1535 let loc = span_start(cx, definition_span);
1536 let file_metadata = file_metadata(cx, loc.file.name);
1538 // For empty enums there is an early exit. Just describe it as an empty struct with the
1539 // appropriate type name
1540 if ty::type_is_empty(cx.tcx(), enum_type) {
1541 let empty_type_metadata = composite_type_metadata(cx,
1549 return FinalMetadata(empty_type_metadata);
1552 let variants = ty::enum_variants(cx.tcx(), enum_def_id);
1554 let enumerators_metadata: Vec<DIDescriptor> = variants
1557 token::get_ident(v.name).get().with_c_str(|name| {
1559 llvm::LLVMDIBuilderCreateEnumerator(
1562 v.disr_val as c_ulonglong)
1568 let discriminant_type_metadata = |inttype| {
1569 // We can reuse the type of the discriminant for all monomorphized instances of an enum
1570 // because it doesn't depend on any type parameters. The def_id, uniquely identifying the
1571 // enum's polytype acts as key in this cache.
1572 let cached_discriminant_type_metadata = debug_context(cx).created_enum_disr_types
1574 .find_copy(&enum_def_id);
1575 match cached_discriminant_type_metadata {
1576 Some(discriminant_type_metadata) => discriminant_type_metadata,
1578 let discriminant_llvm_type = adt::ll_inttype(cx, inttype);
1579 let (discriminant_size, discriminant_align) =
1580 size_and_align_of(cx, discriminant_llvm_type);
1581 let discriminant_base_type_metadata = type_metadata(cx,
1582 adt::ty_of_inttype(inttype),
1584 let discriminant_name = get_enum_discriminant_name(cx, enum_def_id);
1586 let discriminant_type_metadata = discriminant_name.get().with_c_str(|name| {
1588 llvm::LLVMDIBuilderCreateEnumerationType(
1594 bytes_to_bits(discriminant_size),
1595 bytes_to_bits(discriminant_align),
1596 create_DIArray(DIB(cx), enumerators_metadata.as_slice()),
1597 discriminant_base_type_metadata)
1601 debug_context(cx).created_enum_disr_types
1603 .insert(enum_def_id, discriminant_type_metadata);
1605 discriminant_type_metadata
1610 let type_rep = adt::represent_type(cx, enum_type);
1612 return match *type_rep {
1613 adt::CEnum(inttype, _, _) => {
1614 FinalMetadata(discriminant_type_metadata(inttype))
1616 adt::Univariant(ref struct_def, _) => {
1617 assert!(variants.len() == 1);
1620 member_description_factory) =
1621 describe_enum_variant(cx,
1628 UnfinishedMetadata {
1629 cache_id: cache_id_for_type(enum_type),
1630 metadata_stub: metadata_stub,
1631 llvm_type: variant_llvm_type,
1632 file_metadata: file_metadata,
1633 member_description_factory: member_description_factory
1636 adt::General(inttype, _) => {
1637 let discriminant_type_metadata = discriminant_type_metadata(inttype);
1638 let enum_llvm_type = type_of::type_of(cx, enum_type);
1639 let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type);
1640 let unique_id = generate_unique_type_id("DI_ENUM_");
1642 let enum_metadata = enum_name.with_c_str(|enum_name| {
1643 unique_id.with_c_str(|unique_id| {
1645 llvm::LLVMDIBuilderCreateUnionType(
1651 bytes_to_bits(enum_type_size),
1652 bytes_to_bits(enum_type_align),
1661 UnfinishedMetadata {
1662 cache_id: cache_id_for_type(enum_type),
1663 metadata_stub: enum_metadata,
1664 llvm_type: enum_llvm_type,
1665 file_metadata: file_metadata,
1666 member_description_factory: GeneralMD(GeneralMemberDescriptionFactory {
1667 type_rep: type_rep.clone(),
1669 discriminant_type_metadata: discriminant_type_metadata,
1670 containing_scope: containing_scope,
1671 file_metadata: file_metadata,
1676 adt::NullablePointer { nonnull: ref struct_def, nndiscr, .. } => {
1679 member_description_factory) =
1680 describe_enum_variant(cx,
1682 &**variants.get(nndiscr as uint),
1687 UnfinishedMetadata {
1688 cache_id: cache_id_for_type(enum_type),
1689 metadata_stub: metadata_stub,
1690 llvm_type: variant_llvm_type,
1691 file_metadata: file_metadata,
1692 member_description_factory: member_description_factory
1697 fn get_enum_discriminant_name(cx: &CrateContext, def_id: ast::DefId) -> token::InternedString {
1698 let name = if def_id.krate == ast::LOCAL_CRATE {
1699 cx.tcx.map.get_path_elem(def_id.node).name()
1701 csearch::get_item_path(&cx.tcx, def_id).last().unwrap().name()
1704 token::get_name(name)
1709 FixedMemberOffset { bytes: uint },
1710 // For ComputedMemberOffset, the offset is read from the llvm type definition
1711 ComputedMemberOffset
1714 struct MemberDescription {
1717 type_metadata: DIType,
1718 offset: MemberOffset,
1721 /// Creates debug information for a composite type, that is, anything that results in a LLVM struct.
1723 /// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums.
1724 fn composite_type_metadata(cx: &CrateContext,
1725 composite_llvm_type: Type,
1726 composite_type_name: &str,
1727 member_descriptions: &[MemberDescription],
1728 containing_scope: DIScope,
1729 file_metadata: DIFile,
1730 definition_span: Span)
1731 -> DICompositeType {
1732 // Create the (empty) struct metadata node ...
1733 let composite_type_metadata = create_struct_stub(cx,
1734 composite_llvm_type,
1735 composite_type_name,
1740 // ... and immediately create and add the member descriptions.
1741 set_members_of_composite_type(cx,
1742 composite_type_metadata,
1743 composite_llvm_type,
1744 member_descriptions,
1748 return composite_type_metadata;
1751 fn set_members_of_composite_type(cx: &CrateContext,
1752 composite_type_metadata: DICompositeType,
1753 composite_llvm_type: Type,
1754 member_descriptions: &[MemberDescription],
1755 file_metadata: DIFile,
1756 definition_span: Span) {
1757 // In some rare cases LLVM metadata uniquing would lead to an existing type description being
1758 // used instead of a new one created in create_struct_stub. This would cause a hard to trace
1759 // assertion in DICompositeType::SetTypeArray(). The following check makes sure that we get a
1760 // better error message if this should happen again due to some regression.
1762 let mut composite_types_completed =
1763 debug_context(cx).composite_types_completed.borrow_mut();
1764 if composite_types_completed.contains(&composite_type_metadata) {
1765 cx.sess().span_bug(definition_span, "debuginfo::set_members_of_composite_type() - \
1766 Already completed forward declaration \
1769 composite_types_completed.insert(composite_type_metadata);
1773 let loc = span_start(cx, definition_span);
1775 let member_metadata: Vec<DIDescriptor> = member_descriptions
1778 .map(|(i, member_description)| {
1779 let (member_size, member_align) = size_and_align_of(cx, member_description.llvm_type);
1780 let member_offset = match member_description.offset {
1781 FixedMemberOffset { bytes } => bytes as u64,
1782 ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i)
1785 member_description.name.with_c_str(|member_name| {
1787 llvm::LLVMDIBuilderCreateMemberType(
1789 composite_type_metadata,
1793 bytes_to_bits(member_size),
1794 bytes_to_bits(member_align),
1795 bytes_to_bits(member_offset),
1797 member_description.type_metadata)
1804 let type_array = create_DIArray(DIB(cx), member_metadata.as_slice());
1805 llvm::LLVMDICompositeTypeSetTypeArray(composite_type_metadata, type_array);
1809 // A convenience wrapper around LLVMDIBuilderCreateStructType(). Does not do any caching, does not
1810 // add any fields to the struct. This can be done later with set_members_of_composite_type().
1811 fn create_struct_stub(cx: &CrateContext,
1812 struct_llvm_type: Type,
1813 struct_type_name: &str,
1814 containing_scope: DIScope,
1815 file_metadata: DIFile,
1816 definition_span: Span)
1817 -> DICompositeType {
1818 let loc = span_start(cx, definition_span);
1819 let (struct_size, struct_align) = size_and_align_of(cx, struct_llvm_type);
1821 // We assign unique IDs to the type stubs so LLVM metadata uniquing does not reuse instances
1822 // where we don't want it.
1823 let unique_id = generate_unique_type_id("DI_STRUCT_");
1826 struct_type_name.with_c_str(|name| {
1827 unique_id.with_c_str(|unique_id| {
1828 // LLVMDIBuilderCreateStructType() wants an empty array. A null pointer will lead to
1829 // hard to trace and debug LLVM assertions later on in llvm/lib/IR/Value.cpp
1830 let empty_array = create_DIArray(DIB(cx), []);
1832 llvm::LLVMDIBuilderCreateStructType(
1838 bytes_to_bits(struct_size),
1839 bytes_to_bits(struct_align),
1851 fn boxed_type_metadata(cx: &CrateContext,
1852 content_type_name: Option<&str>,
1853 content_llvm_type: Type,
1854 content_type_metadata: DIType,
1856 -> DICompositeType {
1857 let box_type_name = match content_type_name {
1858 Some(content_type_name) => format!("Boxed<{}>", content_type_name),
1859 None => "BoxedType".to_owned()
1862 let box_llvm_type = Type::at_box(cx, content_llvm_type);
1863 let member_llvm_types = box_llvm_type.field_types();
1864 assert!(box_layout_is_correct(cx,
1865 member_llvm_types.as_slice(),
1866 content_llvm_type));
1868 let int_type = ty::mk_int();
1869 let nil_pointer_type = ty::mk_nil_ptr(cx.tcx());
1870 let nil_pointer_type_metadata = type_metadata(cx, nil_pointer_type, codemap::DUMMY_SP);
1872 let member_descriptions = [
1874 name: "refcnt".to_owned(),
1875 llvm_type: *member_llvm_types.get(0),
1876 type_metadata: type_metadata(cx, int_type, codemap::DUMMY_SP),
1877 offset: ComputedMemberOffset,
1880 name: "drop_glue".to_owned(),
1881 llvm_type: *member_llvm_types.get(1),
1882 type_metadata: nil_pointer_type_metadata,
1883 offset: ComputedMemberOffset,
1886 name: "prev".to_owned(),
1887 llvm_type: *member_llvm_types.get(2),
1888 type_metadata: nil_pointer_type_metadata,
1889 offset: ComputedMemberOffset,
1892 name: "next".to_owned(),
1893 llvm_type: *member_llvm_types.get(3),
1894 type_metadata: nil_pointer_type_metadata,
1895 offset: ComputedMemberOffset,
1898 name: "val".to_owned(),
1899 llvm_type: *member_llvm_types.get(4),
1900 type_metadata: content_type_metadata,
1901 offset: ComputedMemberOffset,
1905 let loc = span_start(cx, span);
1906 let file_metadata = file_metadata(cx, loc.file.name);
1908 return composite_type_metadata(
1912 member_descriptions,
1917 // Unfortunately, we cannot assert anything but the correct types here---and not whether the
1918 // 'next' and 'prev' pointers are in the correct order.
1919 fn box_layout_is_correct(cx: &CrateContext,
1920 member_llvm_types: &[Type],
1921 content_llvm_type: Type)
1923 member_llvm_types.len() == 5 &&
1924 member_llvm_types[0] == cx.int_type &&
1925 member_llvm_types[1] == Type::generic_glue_fn(cx).ptr_to() &&
1926 member_llvm_types[2] == Type::i8(cx).ptr_to() &&
1927 member_llvm_types[3] == Type::i8(cx).ptr_to() &&
1928 member_llvm_types[4] == content_llvm_type
1932 fn fixed_vec_metadata(cx: &CrateContext,
1933 element_type: ty::t,
1937 let element_type_metadata = type_metadata(cx, element_type, span);
1938 let element_llvm_type = type_of::type_of(cx, element_type);
1939 let (element_type_size, element_type_align) = size_and_align_of(cx, element_llvm_type);
1941 let subrange = unsafe {
1942 llvm::LLVMDIBuilderGetOrCreateSubrange(
1948 let subscripts = create_DIArray(DIB(cx), [subrange]);
1950 llvm::LLVMDIBuilderCreateArrayType(
1952 bytes_to_bits(element_type_size * (len as u64)),
1953 bytes_to_bits(element_type_align),
1954 element_type_metadata,
1959 fn vec_metadata(cx: &CrateContext,
1960 element_type: ty::t,
1962 -> DICompositeType {
1964 let element_type_metadata = type_metadata(cx, element_type, span);
1965 let element_llvm_type = type_of::type_of(cx, element_type);
1966 let (element_size, element_align) = size_and_align_of(cx, element_llvm_type);
1968 let vec_llvm_type = Type::vec(cx, &element_llvm_type);
1969 let vec_type_name: &str = format!("[{}]", ppaux::ty_to_str(cx.tcx(), element_type));
1971 let member_llvm_types = vec_llvm_type.field_types();
1973 let int_type_metadata = type_metadata(cx, ty::mk_int(), span);
1974 let array_type_metadata = unsafe {
1975 llvm::LLVMDIBuilderCreateArrayType(
1977 bytes_to_bits(element_size),
1978 bytes_to_bits(element_align),
1979 element_type_metadata,
1980 create_DIArray(DIB(cx), [llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, 0)]))
1983 let member_descriptions = [
1985 name: "fill".to_owned(),
1986 llvm_type: *member_llvm_types.get(0),
1987 type_metadata: int_type_metadata,
1988 offset: ComputedMemberOffset,
1991 name: "alloc".to_owned(),
1992 llvm_type: *member_llvm_types.get(1),
1993 type_metadata: int_type_metadata,
1994 offset: ComputedMemberOffset,
1997 name: "elements".to_owned(),
1998 llvm_type: *member_llvm_types.get(2),
1999 type_metadata: array_type_metadata,
2000 offset: ComputedMemberOffset,
2004 assert!(member_descriptions.len() == member_llvm_types.len());
2006 let loc = span_start(cx, span);
2007 let file_metadata = file_metadata(cx, loc.file.name);
2009 composite_type_metadata(
2013 member_descriptions,
2019 fn vec_slice_metadata(cx: &CrateContext,
2021 element_type: ty::t,
2023 -> DICompositeType {
2025 debug!("vec_slice_metadata: {:?}", ty::get(vec_type));
2027 let slice_llvm_type = type_of::type_of(cx, vec_type);
2028 let slice_type_name = ppaux::ty_to_str(cx.tcx(), vec_type);
2030 let member_llvm_types = slice_llvm_type.field_types();
2031 assert!(slice_layout_is_correct(cx,
2032 member_llvm_types.as_slice(),
2035 let data_ptr_type = ty::mk_ptr(cx.tcx(), ty::mt {
2037 mutbl: ast::MutImmutable
2040 let member_descriptions = [
2042 name: "data_ptr".to_owned(),
2043 llvm_type: *member_llvm_types.get(0),
2044 type_metadata: type_metadata(cx, data_ptr_type, span),
2045 offset: ComputedMemberOffset,
2048 name: "length".to_owned(),
2049 llvm_type: *member_llvm_types.get(1),
2050 type_metadata: type_metadata(cx, ty::mk_uint(), span),
2051 offset: ComputedMemberOffset,
2055 assert!(member_descriptions.len() == member_llvm_types.len());
2057 let loc = span_start(cx, span);
2058 let file_metadata = file_metadata(cx, loc.file.name);
2060 return composite_type_metadata(
2064 member_descriptions,
2069 fn slice_layout_is_correct(cx: &CrateContext,
2070 member_llvm_types: &[Type],
2071 element_type: ty::t)
2073 member_llvm_types.len() == 2 &&
2074 member_llvm_types[0] == type_of::type_of(cx, element_type).ptr_to() &&
2075 member_llvm_types[1] == cx.int_type
2079 fn subroutine_type_metadata(cx: &CrateContext,
2080 signature: &ty::FnSig,
2082 -> DICompositeType {
2083 let loc = span_start(cx, span);
2084 let file_metadata = file_metadata(cx, loc.file.name);
2086 let mut signature_metadata: Vec<DIType> =
2087 Vec::with_capacity(signature.inputs.len() + 1);
2090 signature_metadata.push(match ty::get(signature.output).sty {
2091 ty::ty_nil => ptr::null(),
2092 _ => type_metadata(cx, signature.output, span)
2095 // regular arguments
2096 for &argument_type in signature.inputs.iter() {
2097 signature_metadata.push(type_metadata(cx, argument_type, span));
2101 llvm::LLVMDIBuilderCreateSubroutineType(
2104 create_DIArray(DIB(cx), signature_metadata.as_slice()))
2108 fn trait_metadata(cx: &CrateContext,
2111 substs: &ty::substs,
2112 trait_store: ty::TraitStore,
2113 _: &ty::BuiltinBounds)
2115 // The implementation provided here is a stub. It makes sure that the trait type is
2116 // assigned the correct name, size, namespace, and source location. But it does not describe
2117 // the trait's methods.
2118 let last = ty::with_path(cx.tcx(), def_id, |mut path| path.last().unwrap());
2119 let ident_string = token::get_name(last.name());
2120 let name = ppaux::trait_store_to_str(cx.tcx(), trait_store) +
2122 // Add type and region parameters
2123 let name = ppaux::parameterized(cx.tcx(), name, &substs.regions,
2124 substs.tps.as_slice(), def_id, true);
2126 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id);
2128 let file_name = span_start(cx, definition_span).file.name.clone();
2129 let file_metadata = file_metadata(cx, file_name);
2131 let trait_llvm_type = type_of::type_of(cx, trait_type);
2133 composite_type_metadata(cx,
2142 fn type_metadata(cx: &CrateContext,
2144 usage_site_span: Span)
2146 let cache_id = cache_id_for_type(t);
2148 match debug_context(cx).created_types.borrow().find(&cache_id) {
2149 Some(type_metadata) => return *type_metadata,
2153 fn create_pointer_to_box_metadata(cx: &CrateContext,
2154 pointer_type: ty::t,
2157 let content_type_name: &str = ppaux::ty_to_str(cx.tcx(), type_in_box);
2158 let content_llvm_type = type_of::type_of(cx, type_in_box);
2159 let content_type_metadata = type_metadata(
2164 let box_metadata = boxed_type_metadata(
2166 Some(content_type_name),
2168 content_type_metadata,
2171 pointer_type_metadata(cx, pointer_type, box_metadata)
2174 debug!("type_metadata: {:?}", ty::get(t));
2176 let sty = &ty::get(t).sty;
2177 let type_metadata = match *sty {
2184 ty::ty_float(_) => {
2185 basic_type_metadata(cx, t)
2187 ty::ty_enum(def_id, _) => {
2188 prepare_enum_metadata(cx, t, def_id, usage_site_span).finalize(cx)
2190 ty::ty_box(typ) => {
2191 create_pointer_to_box_metadata(cx, t, typ)
2193 ty::ty_vec(ref mt, Some(len)) => fixed_vec_metadata(cx, mt.ty, len, usage_site_span),
2194 ty::ty_uniq(typ) => {
2195 match ty::get(typ).sty {
2196 ty::ty_vec(ref mt, None) => {
2197 let vec_metadata = vec_metadata(cx, mt.ty, usage_site_span);
2198 pointer_type_metadata(cx, t, vec_metadata)
2201 let i8_t = ty::mk_i8();
2202 let vec_metadata = vec_metadata(cx, i8_t, usage_site_span);
2203 pointer_type_metadata(cx, t, vec_metadata)
2206 let pointee = type_metadata(cx, typ, usage_site_span);
2207 pointer_type_metadata(cx, t, pointee)
2211 ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => {
2212 match ty::get(mt.ty).sty {
2213 ty::ty_vec(ref mt, None) => vec_slice_metadata(cx, t, mt.ty, usage_site_span),
2215 let i8_t = ty::mk_i8();
2216 vec_slice_metadata(cx, t, i8_t, usage_site_span)
2219 let pointee = type_metadata(cx, mt.ty, usage_site_span);
2220 pointer_type_metadata(cx, t, pointee)
2224 ty::ty_bare_fn(ref barefnty) => {
2225 subroutine_type_metadata(cx, &barefnty.sig, usage_site_span)
2227 ty::ty_closure(ref closurety) => {
2228 subroutine_type_metadata(cx, &closurety.sig, usage_site_span)
2230 ty::ty_trait(~ty::TyTrait { def_id, ref substs, store, ref bounds }) => {
2231 trait_metadata(cx, def_id, t, substs, store, bounds)
2233 ty::ty_struct(def_id, ref substs) => {
2234 if ty::type_is_simd(cx.tcx(), t) {
2235 let element_type = ty::simd_type(cx.tcx(), t);
2236 let len = ty::simd_size(cx.tcx(), t);
2237 fixed_vec_metadata(cx, element_type, len, usage_site_span)
2239 prepare_struct_metadata(cx, t, def_id, substs, usage_site_span).finalize(cx)
2242 ty::ty_tup(ref elements) => {
2243 prepare_tuple_metadata(cx,
2245 elements.as_slice(),
2246 usage_site_span).finalize(cx)
2248 _ => cx.sess().bug(format!("debuginfo: unexpected type in type_metadata: {:?}", sty))
2251 debug_context(cx).created_types.borrow_mut().insert(cache_id, type_metadata);
2256 enum DebugLocation {
2257 KnownLocation { scope: DIScope, line: uint, col: uint },
2261 impl DebugLocation {
2262 fn new(scope: DIScope, line: uint, col: uint) -> DebugLocation {
2271 fn set_debug_location(cx: &CrateContext, debug_location: DebugLocation) {
2272 if debug_location == debug_context(cx).current_debug_location.get() {
2278 match debug_location {
2279 KnownLocation { scope, line, .. } => {
2280 let col = 0; // Always set the column to zero like Clang and GCC
2281 debug!("setting debug location to {} {}", line, col);
2282 let elements = [C_i32(cx, line as i32), C_i32(cx, col as i32), scope, ptr::null()];
2284 metadata_node = llvm::LLVMMDNodeInContext(debug_context(cx).llcontext,
2286 elements.len() as c_uint);
2289 UnknownLocation => {
2290 debug!("clearing debug location ");
2291 metadata_node = ptr::null();
2296 llvm::LLVMSetCurrentDebugLocation(cx.builder.b, metadata_node);
2299 debug_context(cx).current_debug_location.set(debug_location);
2302 //=-------------------------------------------------------------------------------------------------
2303 // Utility Functions
2304 //=-------------------------------------------------------------------------------------------------
2306 fn cache_id_for_type(t: ty::t) -> uint {
2310 // Used to avoid LLVM metadata uniquing problems. See `create_struct_stub()` and
2311 // `prepare_enum_metadata()`.
2312 fn generate_unique_type_id(prefix: &'static str) -> ~str {
2314 static mut unique_id_counter: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;
2315 format!("{}{}", prefix, unique_id_counter.fetch_add(1, atomics::SeqCst))
2319 /// Return codemap::Loc corresponding to the beginning of the span
2320 fn span_start(cx: &CrateContext, span: Span) -> codemap::Loc {
2321 cx.sess().codemap().lookup_char_pos(span.lo)
2324 fn size_and_align_of(cx: &CrateContext, llvm_type: Type) -> (u64, u64) {
2325 (machine::llsize_of_alloc(cx, llvm_type), machine::llalign_of_min(cx, llvm_type))
2328 fn bytes_to_bits(bytes: u64) -> c_ulonglong {
2329 (bytes * 8) as c_ulonglong
2333 fn debug_context<'a>(cx: &'a CrateContext) -> &'a CrateDebugContext {
2334 let debug_context: &'a CrateDebugContext = cx.dbg_cx.get_ref();
2339 fn DIB(cx: &CrateContext) -> DIBuilderRef {
2340 cx.dbg_cx.get_ref().builder
2343 fn fn_should_be_ignored(fcx: &FunctionContext) -> bool {
2344 match fcx.debug_context.repr {
2345 FunctionDebugContext(_) => false,
2350 fn assert_type_for_node_id(cx: &CrateContext, node_id: ast::NodeId, error_span: Span) {
2351 if !cx.tcx.node_types.borrow().contains_key(&(node_id as uint)) {
2352 cx.sess().span_bug(error_span, "debuginfo: Could not find type for node id!");
2356 fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: ast::DefId)
2357 -> (DIScope, Span) {
2358 let containing_scope = namespace_for_item(cx, def_id).scope;
2359 let definition_span = if def_id.krate == ast::LOCAL_CRATE {
2360 cx.tcx.map.span(def_id.node)
2362 // For external items there is no span information
2366 (containing_scope, definition_span)
2369 // This procedure builds the *scope map* for a given function, which maps any given ast::NodeId in
2370 // the function's AST to the correct DIScope metadata instance.
2372 // This builder procedure walks the AST in execution order and keeps track of what belongs to which
2373 // scope, creating DIScope DIEs along the way, and introducing *artificial* lexical scope
2374 // descriptors where necessary. These artificial scopes allow GDB to correctly handle name
2376 fn populate_scope_map(cx: &CrateContext,
2377 arg_pats: &[@ast::Pat],
2378 fn_entry_block: &ast::Block,
2379 fn_metadata: DISubprogram,
2380 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2381 let def_map = &cx.tcx.def_map;
2383 struct ScopeStackEntry {
2384 scope_metadata: DIScope,
2385 ident: Option<ast::Ident>
2388 let mut scope_stack = vec!(ScopeStackEntry { scope_metadata: fn_metadata, ident: None });
2390 // Push argument identifiers onto the stack so arguments integrate nicely with variable
2392 for &arg_pat in arg_pats.iter() {
2393 pat_util::pat_bindings(def_map, arg_pat, |_, _, _, path_ref| {
2394 let ident = ast_util::path_to_ident(path_ref);
2395 scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata, ident: Some(ident) });
2399 // Clang creates a separate scope for function bodies, so let's do this too
2401 fn_entry_block.span,
2404 |cx, scope_stack, scope_map| {
2405 walk_block(cx, fn_entry_block, scope_stack, scope_map);
2408 // local helper functions for walking the AST.
2409 fn with_new_scope(cx: &CrateContext,
2411 scope_stack: &mut Vec<ScopeStackEntry> ,
2412 scope_map: &mut HashMap<ast::NodeId, DIScope>,
2413 inner_walk: |&CrateContext,
2414 &mut Vec<ScopeStackEntry> ,
2415 &mut HashMap<ast::NodeId, DIScope>|) {
2416 // Create a new lexical scope and push it onto the stack
2417 let loc = cx.sess().codemap().lookup_char_pos(scope_span.lo);
2418 let file_metadata = file_metadata(cx, loc.file.name);
2419 let parent_scope = scope_stack.last().unwrap().scope_metadata;
2421 let scope_metadata = unsafe {
2422 llvm::LLVMDIBuilderCreateLexicalBlock(
2427 loc.col.to_uint() as c_uint,
2431 scope_stack.push(ScopeStackEntry { scope_metadata: scope_metadata, ident: None });
2433 inner_walk(cx, scope_stack, scope_map);
2435 // pop artificial scopes
2436 while scope_stack.last().unwrap().ident.is_some() {
2440 if scope_stack.last().unwrap().scope_metadata != scope_metadata {
2441 cx.sess().span_bug(scope_span, "debuginfo: Inconsistency in scope management.");
2447 fn walk_block(cx: &CrateContext,
2449 scope_stack: &mut Vec<ScopeStackEntry> ,
2450 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2451 scope_map.insert(block.id, scope_stack.last().unwrap().scope_metadata);
2453 // The interesting things here are statements and the concluding expression.
2454 for statement in block.stmts.iter() {
2455 scope_map.insert(ast_util::stmt_id(*statement),
2456 scope_stack.last().unwrap().scope_metadata);
2458 match statement.node {
2459 ast::StmtDecl(decl, _) => walk_decl(cx, decl, scope_stack, scope_map),
2460 ast::StmtExpr(exp, _) |
2461 ast::StmtSemi(exp, _) => walk_expr(cx, exp, scope_stack, scope_map),
2462 ast::StmtMac(..) => () // ignore macros (which should be expanded anyway)
2466 for exp in block.expr.iter() {
2467 walk_expr(cx, *exp, scope_stack, scope_map);
2471 fn walk_decl(cx: &CrateContext,
2473 scope_stack: &mut Vec<ScopeStackEntry> ,
2474 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2476 codemap::Spanned { node: ast::DeclLocal(local), .. } => {
2477 scope_map.insert(local.id, scope_stack.last().unwrap().scope_metadata);
2479 walk_pattern(cx, local.pat, scope_stack, scope_map);
2481 for exp in local.init.iter() {
2482 walk_expr(cx, *exp, scope_stack, scope_map);
2489 fn walk_pattern(cx: &CrateContext,
2491 scope_stack: &mut Vec<ScopeStackEntry> ,
2492 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2494 let def_map = &cx.tcx.def_map;
2496 // Unfortunately, we cannot just use pat_util::pat_bindings() or ast_util::walk_pat() here
2497 // because we have to visit *all* nodes in order to put them into the scope map. The above
2498 // functions don't do that.
2500 ast::PatIdent(_, ref path_ref, ref sub_pat_opt) => {
2502 // Check if this is a binding. If so we need to put it on the scope stack and maybe
2503 // introduce an artificial scope
2504 if pat_util::pat_is_binding(def_map, pat) {
2506 let ident = ast_util::path_to_ident(path_ref);
2508 // LLVM does not properly generate 'DW_AT_start_scope' fields for variable DIEs.
2509 // For this reason we have to introduce an artificial scope at bindings whenever
2510 // a variable with the same name is declared in *any* parent scope.
2512 // Otherwise the following error occurs:
2516 // do_something(); // 'gdb print x' correctly prints 10
2519 // do_something(); // 'gdb print x' prints 0, because it already reads the
2520 // // uninitialized 'x' from the next line...
2522 // do_something(); // 'gdb print x' correctly prints 100
2525 // Is there already a binding with that name?
2526 // N.B.: this comparison must be UNhygienic... because
2527 // gdb knows nothing about the context, so any two
2528 // variables with the same name will cause the problem.
2529 let need_new_scope = scope_stack
2531 .any(|entry| entry.ident.iter().any(|i| i.name == ident.name));
2534 // Create a new lexical scope and push it onto the stack
2535 let loc = cx.sess().codemap().lookup_char_pos(pat.span.lo);
2536 let file_metadata = file_metadata(cx, loc.file.name);
2537 let parent_scope = scope_stack.last().unwrap().scope_metadata;
2539 let scope_metadata = unsafe {
2540 llvm::LLVMDIBuilderCreateLexicalBlock(
2545 loc.col.to_uint() as c_uint,
2549 scope_stack.push(ScopeStackEntry {
2550 scope_metadata: scope_metadata,
2555 // Push a new entry anyway so the name can be found
2556 let prev_metadata = scope_stack.last().unwrap().scope_metadata;
2557 scope_stack.push(ScopeStackEntry {
2558 scope_metadata: prev_metadata,
2564 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2566 for &sub_pat in sub_pat_opt.iter() {
2567 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2571 ast::PatWild | ast::PatWildMulti => {
2572 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2575 ast::PatEnum(_, ref sub_pats_opt) => {
2576 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2578 for ref sub_pats in sub_pats_opt.iter() {
2579 for &p in sub_pats.iter() {
2580 walk_pattern(cx, p, scope_stack, scope_map);
2585 ast::PatStruct(_, ref field_pats, _) => {
2586 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2588 for &ast::FieldPat { pat: sub_pat, .. } in field_pats.iter() {
2589 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2593 ast::PatTup(ref sub_pats) => {
2594 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2596 for &sub_pat in sub_pats.iter() {
2597 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2601 ast::PatUniq(sub_pat) | ast::PatRegion(sub_pat) => {
2602 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2603 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2606 ast::PatLit(exp) => {
2607 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2608 walk_expr(cx, exp, scope_stack, scope_map);
2611 ast::PatRange(exp1, exp2) => {
2612 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2613 walk_expr(cx, exp1, scope_stack, scope_map);
2614 walk_expr(cx, exp2, scope_stack, scope_map);
2617 ast::PatVec(ref front_sub_pats, ref middle_sub_pats, ref back_sub_pats) => {
2618 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2620 for &sub_pat in front_sub_pats.iter() {
2621 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2624 for &sub_pat in middle_sub_pats.iter() {
2625 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2628 for &sub_pat in back_sub_pats.iter() {
2629 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2635 fn walk_expr(cx: &CrateContext,
2637 scope_stack: &mut Vec<ScopeStackEntry> ,
2638 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2640 scope_map.insert(exp.id, scope_stack.last().unwrap().scope_metadata);
2646 ast::ExprPath(_) => {}
2648 ast::ExprVstore(sub_exp, _) |
2649 ast::ExprCast(sub_exp, _) |
2650 ast::ExprAddrOf(_, sub_exp) |
2651 ast::ExprField(sub_exp, _, _) |
2652 ast::ExprParen(sub_exp) => walk_expr(cx, sub_exp, scope_stack, scope_map),
2654 ast::ExprBox(place, sub_expr) => {
2655 walk_expr(cx, place, scope_stack, scope_map);
2656 walk_expr(cx, sub_expr, scope_stack, scope_map);
2659 ast::ExprRet(exp_opt) => match exp_opt {
2660 Some(sub_exp) => walk_expr(cx, sub_exp, scope_stack, scope_map),
2664 ast::ExprUnary(_, sub_exp) => {
2665 walk_expr(cx, sub_exp, scope_stack, scope_map);
2668 ast::ExprAssignOp(_, lhs, rhs) |
2669 ast::ExprIndex(lhs, rhs) |
2670 ast::ExprBinary(_, lhs, rhs) => {
2671 walk_expr(cx, lhs, scope_stack, scope_map);
2672 walk_expr(cx, rhs, scope_stack, scope_map);
2675 ast::ExprVec(ref init_expressions) |
2676 ast::ExprTup(ref init_expressions) => {
2677 for ie in init_expressions.iter() {
2678 walk_expr(cx, *ie, scope_stack, scope_map);
2682 ast::ExprAssign(sub_exp1, sub_exp2) |
2683 ast::ExprRepeat(sub_exp1, sub_exp2) => {
2684 walk_expr(cx, sub_exp1, scope_stack, scope_map);
2685 walk_expr(cx, sub_exp2, scope_stack, scope_map);
2688 ast::ExprIf(cond_exp, then_block, ref opt_else_exp) => {
2689 walk_expr(cx, cond_exp, scope_stack, scope_map);
2695 |cx, scope_stack, scope_map| {
2696 walk_block(cx, then_block, scope_stack, scope_map);
2699 match *opt_else_exp {
2700 Some(else_exp) => walk_expr(cx, else_exp, scope_stack, scope_map),
2705 ast::ExprWhile(cond_exp, loop_body) => {
2706 walk_expr(cx, cond_exp, scope_stack, scope_map);
2712 |cx, scope_stack, scope_map| {
2713 walk_block(cx, loop_body, scope_stack, scope_map);
2717 ast::ExprForLoop(_, _, _, _) => {
2718 cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \
2719 Found unexpanded for-loop.");
2722 ast::ExprMac(_) => {
2723 cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \
2724 Found unexpanded macro.");
2727 ast::ExprLoop(block, _) |
2728 ast::ExprBlock(block) => {
2733 |cx, scope_stack, scope_map| {
2734 walk_block(cx, block, scope_stack, scope_map);
2738 ast::ExprFnBlock(decl, block) |
2739 ast::ExprProc(decl, block) => {
2744 |cx, scope_stack, scope_map| {
2745 for &ast::Arg { pat: pattern, .. } in decl.inputs.iter() {
2746 walk_pattern(cx, pattern, scope_stack, scope_map);
2749 walk_block(cx, block, scope_stack, scope_map);
2753 ast::ExprCall(fn_exp, ref args) => {
2754 walk_expr(cx, fn_exp, scope_stack, scope_map);
2756 for arg_exp in args.iter() {
2757 walk_expr(cx, *arg_exp, scope_stack, scope_map);
2761 ast::ExprMethodCall(_, _, ref args) => {
2762 for arg_exp in args.iter() {
2763 walk_expr(cx, *arg_exp, scope_stack, scope_map);
2767 ast::ExprMatch(discriminant_exp, ref arms) => {
2768 walk_expr(cx, discriminant_exp, scope_stack, scope_map);
2770 // for each arm we have to first walk the pattern as these might introduce new
2771 // artificial scopes. It should be sufficient to walk only one pattern per arm, as
2772 // they all must contain the same binding names
2774 for arm_ref in arms.iter() {
2775 let arm_span = arm_ref.pats.get(0).span;
2781 |cx, scope_stack, scope_map| {
2782 for &pat in arm_ref.pats.iter() {
2783 walk_pattern(cx, pat, scope_stack, scope_map);
2786 for guard_exp in arm_ref.guard.iter() {
2787 walk_expr(cx, *guard_exp, scope_stack, scope_map)
2790 walk_expr(cx, arm_ref.body, scope_stack, scope_map);
2795 ast::ExprStruct(_, ref fields, ref base_exp) => {
2796 for &ast::Field { expr: exp, .. } in fields.iter() {
2797 walk_expr(cx, exp, scope_stack, scope_map);
2801 Some(exp) => walk_expr(cx, exp, scope_stack, scope_map),
2806 ast::ExprInlineAsm(ast::InlineAsm { inputs: ref inputs,
2807 outputs: ref outputs,
2809 // inputs, outputs: ~[(~str, @expr)]
2810 for &(_, exp) in inputs.iter() {
2811 walk_expr(cx, exp, scope_stack, scope_map);
2814 for &(_, exp) in outputs.iter() {
2815 walk_expr(cx, exp, scope_stack, scope_map);
2823 //=-------------------------------------------------------------------------------------------------
2824 // Namespace Handling
2825 //=-------------------------------------------------------------------------------------------------
2827 struct NamespaceTreeNode {
2830 parent: Option<Weak<NamespaceTreeNode>>,
2833 impl NamespaceTreeNode {
2834 fn mangled_name_of_contained_item(&self, item_name: &str) -> ~str {
2835 fn fill_nested(node: &NamespaceTreeNode, output: &mut StrBuf) {
2837 Some(ref parent) => fill_nested(&*parent.upgrade().unwrap(), output),
2840 let string = token::get_name(node.name);
2841 output.push_str(format!("{}", string.get().len()));
2842 output.push_str(string.get());
2845 let mut name = StrBuf::from_str("_ZN");
2846 fill_nested(self, &mut name);
2847 name.push_str(format!("{}", item_name.len()));
2848 name.push_str(item_name);
2849 name.push_char('E');
2854 fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTreeNode> {
2855 ty::with_path(cx.tcx(), def_id, |path| {
2856 // prepend crate name if not already present
2857 let krate = if def_id.krate == ast::LOCAL_CRATE {
2858 let crate_namespace_ident = token::str_to_ident(cx.link_meta.crateid.name);
2859 Some(ast_map::PathMod(crate_namespace_ident.name))
2863 let mut path = krate.move_iter().chain(path).peekable();
2865 let mut current_key = Vec::new();
2866 let mut parent_node: Option<Rc<NamespaceTreeNode>> = None;
2868 // Create/Lookup namespace for each element of the path.
2870 // Emulate a for loop so we can use peek below.
2871 let path_element = match path.next() {
2875 // Ignore the name of the item (the last path element).
2876 if path.peek().is_none() {
2880 let name = path_element.name();
2881 current_key.push(name);
2883 let existing_node = debug_context(cx).namespace_map.borrow()
2884 .find_copy(¤t_key);
2885 let current_node = match existing_node {
2886 Some(existing_node) => existing_node,
2888 // create and insert
2889 let parent_scope = match parent_node {
2890 Some(ref node) => node.scope,
2893 let namespace_name = token::get_name(name);
2894 let scope = namespace_name.get().with_c_str(|namespace_name| {
2896 llvm::LLVMDIBuilderCreateNameSpace(
2900 // cannot reconstruct file ...
2902 // ... or line information, but that's not so important.
2907 let node = Rc::new(NamespaceTreeNode {
2910 parent: parent_node.map(|parent| parent.downgrade()),
2913 debug_context(cx).namespace_map.borrow_mut()
2914 .insert(current_key.clone(), node.clone());
2920 parent_node = Some(current_node);
2926 cx.sess().bug(format!("debuginfo::namespace_for_item(): \
2927 path too short for {:?}", def_id));