1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
14 This module serves the purpose of generating debug symbols. We use LLVM's
15 [source level debugging](http://llvm.org/docs/SourceLevelDebugging.html) features for generating
16 the debug information. The general principle is this:
18 Given the right metadata in the LLVM IR, the LLVM code generator is able to create DWARF debug
19 symbols for the given code. The [metadata](http://llvm.org/docs/LangRef.html#metadata-type) is
20 structured much like DWARF *debugging information entries* (DIE), representing type information
21 such as datatype layout, function signatures, block layout, variable location and scope information,
22 etc. It is the purpose of this module to generate correct metadata and insert it into the LLVM IR.
24 As the exact format of metadata trees may change between different LLVM versions, we now use LLVM
25 [DIBuilder](http://llvm.org/docs/doxygen/html/classllvm_1_1DIBuilder.html) to create metadata
26 where possible. This will hopefully ease the adaption of this module to future LLVM versions.
28 The public API of the module is a set of functions that will insert the correct metadata into the
29 LLVM IR when called with the right parameters. The module is thus driven from an outside client with
30 functions like `debuginfo::create_local_var_metadata(bcx: block, local: &ast::local)`.
32 Internally the module will try to reuse already created metadata by utilizing a cache. The way to
33 get a shared metadata node when needed is thus to just call the corresponding function in this
36 let file_metadata = file_metadata(crate_context, path);
38 The function will take care of probing the cache for an existing node for that exact file path.
40 All private state used by the module is stored within either the CrateDebugContext struct (owned by
41 the CrateContext) or the FunctionDebugContext (owned by the FunctionContext).
43 This file consists of three conceptual sections:
44 1. The public interface of the module
45 2. Module-internal metadata creation functions
46 3. Minor utility functions
50 Some kinds of types, such as structs and enums can be recursive. That means that the type definition
51 of some type X refers to some other type which in turn (transitively) refers to X. This introduces
52 cycles into the type referral graph. A naive algorithm doing an on-demand, depth-first traversal of
53 this graph when describing types, can get trapped in an endless loop when it reaches such a cycle.
55 For example, the following simple type for a singly-linked list...
64 will generate the following callstack with a naive DFS algorithm:
69 describe(t = Option<@List>)
71 describe(t = List) // at the beginning again...
75 To break cycles like these, we use "forward declarations". That is, when the algorithm encounters a
76 possibly recursive type (any struct or enum), it immediately creates a type description node and
77 inserts it into the cache *before* describing the members of the type. This type description is just
78 a stub (as type members are not described and added to it yet) but it allows the algorithm to
79 already refer to the type. After the stub is inserted into the cache, the algorithm continues as
80 before. If it now encounters a recursive reference, it will hit the cache and does not try to
81 describe the type anew.
83 This behaviour is encapsulated in the 'RecursiveTypeDescription' enum, which represents a kind of
84 continuation, storing all state needed to continue traversal at the type members after the type has
85 been registered with the cache. (This implementation approach might be a tad over-engineered and
86 may change in the future)
89 ## Source Locations and Line Information
90 In addition to data type descriptions the debugging information must also allow to map machine code
91 locations back to source code locations in order to be useful. This functionality is also handled in
92 this module. The following functions allow to control source mappings:
94 + set_source_location()
95 + clear_source_location()
96 + start_emitting_source_locations()
98 `set_source_location()` allows to set the current source location. All IR instructions created after
99 a call to this function will be linked to the given source location, until another location is
100 specified with `set_source_location()` or the source location is cleared with
101 `clear_source_location()`. In the later case, subsequent IR instruction will not be linked to any
102 source location. As you can see, this is a stateful API (mimicking the one in LLVM), so be careful
103 with source locations set by previous calls. It's probably best to not rely on any specific state
104 being present at a given point in code.
106 One topic that deserves some extra attention is *function prologues*. At the beginning of a
107 function's machine code there are typically a few instructions for loading argument values into
108 allocas and checking if there's enough stack space for the function to execute. This *prologue* is
109 not visible in the source code and LLVM puts a special PROLOGUE END marker into the line table at
110 the first non-prologue instruction of the function. In order to find out where the prologue ends,
111 LLVM looks for the first instruction in the function body that is linked to a source location. So,
112 when generating prologue instructions we have to make sure that we don't emit source location
113 information until the 'real' function body begins. For this reason, source location emission is
114 disabled by default for any new function being translated and is only activated after a call to the
115 third function from the list above, `start_emitting_source_locations()`. This function should be
116 called right before regularly starting to translate the top-level block of the given function.
118 There is one exception to the above rule: `llvm.dbg.declare` instruction must be linked to the
119 source location of the variable being declared. For function parameters these `llvm.dbg.declare`
120 instructions typically occur in the middle of the prologue, however, they are ignored by LLVM's
121 prologue detection. The `create_argument_metadata()` and related functions take care of linking the
122 `llvm.dbg.declare` instructions to the correct source locations even while source location emission
123 is still disabled, so there is no need to do anything special with source location handling here.
129 use driver::session::{FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
131 use lib::llvm::{ModuleRef, ContextRef, ValueRef};
132 use lib::llvm::debuginfo::*;
133 use middle::trans::adt;
134 use middle::trans::common::*;
135 use middle::trans::datum::{Datum, Lvalue};
136 use middle::trans::machine;
137 use middle::trans::type_of;
138 use middle::trans::type_::Type;
141 use middle::pat_util;
144 use std::c_str::{CString, ToCStr};
145 use std::cell::{Cell, RefCell};
146 use collections::HashMap;
147 use collections::HashSet;
148 use libc::{c_uint, c_ulonglong, c_longlong};
151 use std::strbuf::StrBuf;
152 use std::sync::atomics;
153 use syntax::codemap::{Span, Pos};
154 use syntax::{abi, ast, codemap, ast_util, ast_map};
155 use syntax::owned_slice::OwnedSlice;
156 use syntax::parse::token;
157 use syntax::parse::token::special_idents;
159 static DW_LANG_RUST: c_uint = 0x9000;
161 static DW_TAG_auto_variable: c_uint = 0x100;
162 static DW_TAG_arg_variable: c_uint = 0x101;
164 static DW_ATE_boolean: c_uint = 0x02;
165 static DW_ATE_float: c_uint = 0x04;
166 static DW_ATE_signed: c_uint = 0x05;
167 // static DW_ATE_signed_char: c_uint = 0x06;
168 static DW_ATE_unsigned: c_uint = 0x07;
169 static DW_ATE_unsigned_char: c_uint = 0x08;
171 //=-------------------------------------------------------------------------------------------------
172 // Public Interface of debuginfo module
173 //=-------------------------------------------------------------------------------------------------
175 /// A context object for maintaining all state needed by the debuginfo module.
176 pub struct CrateDebugContext {
177 llcontext: ContextRef,
178 builder: DIBuilderRef,
179 current_debug_location: Cell<DebugLocation>,
180 created_files: RefCell<HashMap<~str, DIFile>>,
181 created_types: RefCell<HashMap<uint, DIType>>,
182 namespace_map: RefCell<HashMap<Vec<ast::Name> , @NamespaceTreeNode>>,
183 // This collection is used to assert that composite types (structs, enums, ...) have their
184 // members only set once:
185 composite_types_completed: RefCell<HashSet<DIType>>,
188 impl CrateDebugContext {
189 pub fn new(llmod: ModuleRef) -> CrateDebugContext {
190 debug!("CrateDebugContext::new");
191 let builder = unsafe { llvm::LLVMDIBuilderCreate(llmod) };
192 // DIBuilder inherits context from the module, so we'd better use the same one
193 let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
194 return CrateDebugContext {
195 llcontext: llcontext,
197 current_debug_location: Cell::new(UnknownLocation),
198 created_files: RefCell::new(HashMap::new()),
199 created_types: RefCell::new(HashMap::new()),
200 namespace_map: RefCell::new(HashMap::new()),
201 composite_types_completed: RefCell::new(HashSet::new()),
206 pub enum FunctionDebugContext {
207 priv FunctionDebugContext(~FunctionDebugContextData),
208 priv DebugInfoDisabled,
209 priv FunctionWithoutDebugInfo,
212 impl FunctionDebugContext {
213 fn get_ref<'a>(&'a self, cx: &CrateContext, span: Span) -> &'a FunctionDebugContextData {
215 FunctionDebugContext(~ref data) => data,
216 DebugInfoDisabled => {
217 cx.sess().span_bug(span, FunctionDebugContext::debuginfo_disabled_message());
219 FunctionWithoutDebugInfo => {
220 cx.sess().span_bug(span, FunctionDebugContext::should_be_ignored_message());
225 fn debuginfo_disabled_message() -> &'static str {
226 "debuginfo: Error trying to access FunctionDebugContext although debug info is disabled!"
229 fn should_be_ignored_message() -> &'static str {
230 "debuginfo: Error trying to access FunctionDebugContext for function that should be \
231 ignored by debug info!"
235 struct FunctionDebugContextData {
236 scope_map: RefCell<HashMap<ast::NodeId, DIScope>>,
237 fn_metadata: DISubprogram,
238 argument_counter: Cell<uint>,
239 source_locations_enabled: Cell<bool>,
242 enum VariableAccess<'a> {
243 // The llptr given is an alloca containing the variable's value
244 DirectVariable { alloca: ValueRef },
245 // The llptr given is an alloca containing the start of some pointer chain leading to the
246 // variable's content.
247 IndirectVariable { alloca: ValueRef, address_operations: &'a [ValueRef] }
251 ArgumentVariable(uint /*index*/),
256 /// Create any deferred debug metadata nodes
257 pub fn finalize(cx: &CrateContext) {
258 if cx.dbg_cx.is_none() {
263 compile_unit_metadata(cx);
265 llvm::LLVMDIBuilderFinalize(DIB(cx));
266 llvm::LLVMDIBuilderDispose(DIB(cx));
267 // Debuginfo generation in LLVM by default uses a higher
268 // version of dwarf than OS X currently understands. We can
269 // instruct LLVM to emit an older version of dwarf, however,
270 // for OS X to understand. For more info see #11352
271 // This can be overridden using --llvm-opts -dwarf-version,N.
272 if cx.sess().targ_cfg.os == abi::OsMacos {
273 "Dwarf Version".with_c_str(
274 |s| llvm::LLVMRustAddModuleFlag(cx.llmod, s, 2));
277 // Prevent bitcode readers from deleting the debug info.
278 "Debug Info Version".with_c_str(
279 |s| llvm::LLVMRustAddModuleFlag(cx.llmod, s,
280 llvm::LLVMRustDebugMetadataVersion));
284 /// Creates debug information for the given global variable.
286 /// Adds the created metadata nodes directly to the crate's IR.
287 pub fn create_global_var_metadata(cx: &CrateContext,
288 node_id: ast::NodeId,
290 if cx.dbg_cx.is_none() {
294 let var_item = cx.tcx.map.get(node_id);
296 let (ident, span) = match var_item {
297 ast_map::NodeItem(item) => {
299 ast::ItemStatic(..) => (item.ident, item.span),
300 _ => cx.sess().span_bug(item.span,
301 format!("debuginfo::create_global_var_metadata() -
302 Captured var-id refers to unexpected ast_item
307 _ => cx.sess().bug(format!("debuginfo::create_global_var_metadata() - Captured var-id \
308 refers to unexpected ast_map variant: {:?}",
312 let filename = span_start(cx, span).file.name.clone();
313 let file_metadata = file_metadata(cx, filename);
315 let is_local_to_unit = is_node_local_to_unit(cx, node_id);
316 let loc = span_start(cx, span);
318 let variable_type = ty::node_id_to_type(cx.tcx(), node_id);
319 let type_metadata = type_metadata(cx, variable_type, span);
321 let namespace_node = namespace_for_item(cx, ast_util::local_def(node_id));
322 let var_name = token::get_ident(ident).get().to_str();
323 let linkage_name = namespace_node.mangled_name_of_contained_item(var_name);
324 let var_scope = namespace_node.scope;
326 var_name.with_c_str(|var_name| {
327 linkage_name.with_c_str(|linkage_name| {
329 llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx),
344 /// Creates debug information for the given local variable.
346 /// Adds the created metadata nodes directly to the crate's IR.
347 pub fn create_local_var_metadata(bcx: &Block, local: &ast::Local) {
348 if fn_should_be_ignored(bcx.fcx) {
353 let def_map = cx.tcx.def_map;
355 pat_util::pat_bindings(def_map, local.pat, |_, node_id, span, path_ref| {
356 let var_ident = ast_util::path_to_ident(path_ref);
358 let datum = match bcx.fcx.lllocals.borrow().find_copy(&node_id) {
359 Some(datum) => datum,
361 bcx.sess().span_bug(span,
362 format!("no entry in lllocals table for {:?}",
367 let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
373 DirectVariable { alloca: datum.val },
379 /// Creates debug information for a variable captured in a closure.
381 /// Adds the created metadata nodes directly to the crate's IR.
382 pub fn create_captured_var_metadata(bcx: &Block,
383 node_id: ast::NodeId,
384 env_data_type: ty::t,
385 env_pointer: ValueRef,
387 closure_sigil: ast::Sigil,
389 if fn_should_be_ignored(bcx.fcx) {
395 let ast_item = cx.tcx.map.find(node_id);
397 let variable_ident = match ast_item {
399 cx.sess().span_bug(span, "debuginfo::create_captured_var_metadata: node not found");
401 Some(ast_map::NodeLocal(pat)) | Some(ast_map::NodeArg(pat)) => {
403 ast::PatIdent(_, ref path, _) => {
404 ast_util::path_to_ident(path)
410 "debuginfo::create_captured_var_metadata() - \
411 Captured var-id refers to unexpected \
412 ast_map variant: {:?}",
418 cx.sess().span_bug(span, format!("debuginfo::create_captured_var_metadata() - \
419 Captured var-id refers to unexpected ast_map variant: {:?}", ast_item));
423 let variable_type = node_id_type(bcx, node_id);
424 let scope_metadata = bcx.fcx.debug_context.get_ref(cx, span).fn_metadata;
426 let llvm_env_data_type = type_of::type_of(cx, env_data_type);
427 let byte_offset_of_var_in_env = machine::llelement_offset(cx, llvm_env_data_type, env_index);
429 let address_operations = unsafe {
430 [llvm::LLVMDIBuilderCreateOpDeref(Type::i64(cx).to_ref()),
431 llvm::LLVMDIBuilderCreateOpPlus(Type::i64(cx).to_ref()),
432 C_i64(cx, byte_offset_of_var_in_env as i64),
433 llvm::LLVMDIBuilderCreateOpDeref(Type::i64(cx).to_ref())]
436 let address_op_count = match closure_sigil {
437 ast::BorrowedSigil => {
438 address_operations.len()
440 ast::ManagedSigil | ast::OwnedSigil => {
441 address_operations.len() - 1
445 let variable_access = IndirectVariable {
447 address_operations: address_operations.slice_to(address_op_count)
459 /// Creates debug information for a local variable introduced in the head of a match-statement arm.
461 /// Adds the created metadata nodes directly to the crate's IR.
462 pub fn create_match_binding_metadata(bcx: &Block,
463 variable_ident: ast::Ident,
464 node_id: ast::NodeId,
466 datum: Datum<Lvalue>) {
467 if fn_should_be_ignored(bcx.fcx) {
471 let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
477 DirectVariable { alloca: datum.val },
482 /// Creates debug information for the given function argument.
484 /// Adds the created metadata nodes directly to the crate's IR.
485 pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
486 if fn_should_be_ignored(bcx.fcx) {
493 let def_map = cx.tcx.def_map;
494 let scope_metadata = bcx.fcx.debug_context.get_ref(cx, arg.pat.span).fn_metadata;
496 pat_util::pat_bindings(def_map, arg.pat, |_, node_id, span, path_ref| {
497 let llarg = match bcx.fcx.llargs.borrow().find_copy(&node_id) {
500 bcx.sess().span_bug(span,
501 format!("no entry in llargs table for {:?}",
506 if unsafe { llvm::LLVMIsAAllocaInst(llarg.val) } == ptr::null() {
507 cx.sess().span_bug(span, "debuginfo::create_argument_metadata() - \
508 Referenced variable location is not an alloca!");
511 let argument_ident = ast_util::path_to_ident(path_ref);
513 let argument_index = {
514 let counter = &fcx.debug_context.get_ref(cx, span).argument_counter;
515 let argument_index = counter.get();
516 counter.set(argument_index + 1);
524 DirectVariable { alloca: llarg.val },
525 ArgumentVariable(argument_index),
530 /// Sets the current debug location at the beginning of the span.
532 /// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...). The node_id parameter is used to
533 /// reliably find the correct visibility scope for the code position.
534 pub fn set_source_location(fcx: &FunctionContext,
535 node_id: ast::NodeId,
537 if fn_should_be_ignored(fcx) {
543 debug!("set_source_location: {}", cx.sess().codemap().span_to_str(span));
545 if fcx.debug_context.get_ref(cx, span).source_locations_enabled.get() {
546 let loc = span_start(cx, span);
547 let scope = scope_metadata(fcx, node_id, span);
549 set_debug_location(cx, DebugLocation::new(scope, loc.line, loc.col.to_uint()));
551 set_debug_location(cx, UnknownLocation);
555 /// Clears the current debug location.
557 /// Instructions generated hereafter won't be assigned a source location.
558 pub fn clear_source_location(fcx: &FunctionContext) {
559 if fn_should_be_ignored(fcx) {
563 set_debug_location(fcx.ccx, UnknownLocation);
566 /// Enables emitting source locations for the given functions.
568 /// Since we don't want source locations to be emitted for the function prelude, they are disabled
569 /// when beginning to translate a new function. This functions switches source location emitting on
570 /// and must therefore be called before the first real statement/expression of the function is
572 pub fn start_emitting_source_locations(fcx: &FunctionContext) {
573 match fcx.debug_context {
574 FunctionDebugContext(~ref data) => {
575 data.source_locations_enabled.set(true)
577 _ => { /* safe to ignore */ }
581 /// Creates the function-specific debug context.
583 /// Returns the FunctionDebugContext for the function which holds state needed for debug info
584 /// creation. The function may also return another variant of the FunctionDebugContext enum which
585 /// indicates why no debuginfo should be created for the function.
586 pub fn create_function_debug_context(cx: &CrateContext,
587 fn_ast_id: ast::NodeId,
588 param_substs: Option<@param_substs>,
589 llfn: ValueRef) -> FunctionDebugContext {
590 if cx.sess().opts.debuginfo == NoDebugInfo {
591 return DebugInfoDisabled;
595 return FunctionWithoutDebugInfo;
598 let empty_generics = ast::Generics { lifetimes: Vec::new(), ty_params: OwnedSlice::empty() };
600 let fnitem = cx.tcx.map.get(fn_ast_id);
602 let (ident, fn_decl, generics, top_level_block, span, has_path) = match fnitem {
603 ast_map::NodeItem(ref item) => {
605 ast::ItemFn(fn_decl, _, _, ref generics, top_level_block) => {
606 (item.ident, fn_decl, generics, top_level_block, item.span, true)
609 cx.sess().span_bug(item.span,
610 "create_function_debug_context: item bound to non-function");
614 ast_map::NodeMethod(method) => {
622 ast_map::NodeExpr(ref expr) => {
624 ast::ExprFnBlock(fn_decl, top_level_block) |
625 ast::ExprProc(fn_decl, top_level_block) => {
626 let name = format!("fn{}", token::gensym("fn"));
627 let name = token::str_to_ident(name);
629 // This is not quite right. It should actually inherit the generics of the
630 // enclosing function.
634 // Don't try to lookup the item path:
637 _ => cx.sess().span_bug(expr.span,
638 "create_function_debug_context: expected an expr_fn_block here")
641 ast_map::NodeTraitMethod(trait_method) => {
642 match *trait_method {
643 ast::Provided(method) => {
653 .bug(format!("create_function_debug_context: \
654 unexpected sort of node: {:?}",
659 ast_map::NodeForeignItem(..) |
660 ast_map::NodeVariant(..) |
661 ast_map::NodeStructCtor(..) => {
662 return FunctionWithoutDebugInfo;
664 _ => cx.sess().bug(format!("create_function_debug_context: \
665 unexpected sort of node: {:?}", fnitem))
668 // This can be the case for functions inlined from another crate
669 if span == codemap::DUMMY_SP {
670 return FunctionWithoutDebugInfo;
673 let loc = span_start(cx, span);
674 let file_metadata = file_metadata(cx, loc.file.name);
676 let function_type_metadata = unsafe {
677 let fn_signature = get_function_signature(cx, fn_ast_id, fn_decl, param_substs, span);
678 llvm::LLVMDIBuilderCreateSubroutineType(DIB(cx), file_metadata, fn_signature)
681 // get_template_parameters() will append a `<...>` clause to the function name if necessary.
682 let mut function_name = StrBuf::from_str(token::get_ident(ident).get());
683 let template_parameters = get_template_parameters(cx,
689 // There is no ast_map::Path for ast::ExprFnBlock-type functions. For now, just don't put them
690 // into a namespace. In the future this could be improved somehow (storing a path in the
691 // ast_map, or construct a path using the enclosing function).
692 let (linkage_name, containing_scope) = if has_path {
693 let namespace_node = namespace_for_item(cx, ast_util::local_def(fn_ast_id));
694 let linkage_name = namespace_node.mangled_name_of_contained_item(
695 function_name.as_slice());
696 let containing_scope = namespace_node.scope;
697 (linkage_name, containing_scope)
699 (function_name.as_slice().to_owned(), file_metadata)
702 // Clang sets this parameter to the opening brace of the function's block, so let's do this too.
703 let scope_line = span_start(cx, top_level_block.span).line;
705 let is_local_to_unit = is_node_local_to_unit(cx, fn_ast_id);
707 let fn_metadata = function_name.as_slice().with_c_str(|function_name| {
708 linkage_name.with_c_str(|linkage_name| {
710 llvm::LLVMDIBuilderCreateFunction(
717 function_type_metadata,
720 scope_line as c_uint,
721 FlagPrototyped as c_uint,
722 cx.sess().opts.optimize != session::No,
730 // Initialize fn debug context (including scope map and namespace map)
731 let fn_debug_context = ~FunctionDebugContextData {
732 scope_map: RefCell::new(HashMap::new()),
733 fn_metadata: fn_metadata,
734 argument_counter: Cell::new(1),
735 source_locations_enabled: Cell::new(false),
738 let arg_pats = fn_decl.inputs.iter().map(|arg_ref| arg_ref.pat).collect::<Vec<_>>();
739 populate_scope_map(cx,
743 &mut *fn_debug_context.scope_map.borrow_mut());
745 // Clear the debug location so we don't assign them in the function prelude
746 set_debug_location(cx, UnknownLocation);
748 return FunctionDebugContext(fn_debug_context);
750 fn get_function_signature(cx: &CrateContext,
751 fn_ast_id: ast::NodeId,
752 fn_decl: &ast::FnDecl,
753 param_substs: Option<@param_substs>,
754 error_span: Span) -> DIArray {
755 if cx.sess().opts.debuginfo == LimitedDebugInfo {
756 return create_DIArray(DIB(cx), []);
759 let mut signature = slice::with_capacity(fn_decl.inputs.len() + 1);
761 // Return type -- llvm::DIBuilder wants this at index 0
762 match fn_decl.output.node {
764 signature.push(ptr::null());
767 assert_type_for_node_id(cx, fn_ast_id, error_span);
769 let return_type = ty::node_id_to_type(cx.tcx(), fn_ast_id);
770 let return_type = match param_substs {
773 ty::subst_tps(cx.tcx(),
774 substs.tys.as_slice(),
780 signature.push(type_metadata(cx, return_type, codemap::DUMMY_SP));
785 for arg in fn_decl.inputs.iter() {
786 assert_type_for_node_id(cx, arg.pat.id, arg.pat.span);
787 let arg_type = ty::node_id_to_type(cx.tcx(), arg.pat.id);
788 let arg_type = match param_substs {
791 ty::subst_tps(cx.tcx(),
792 substs.tys.as_slice(),
798 signature.push(type_metadata(cx, arg_type, codemap::DUMMY_SP));
801 return create_DIArray(DIB(cx), signature);
804 fn get_template_parameters(cx: &CrateContext,
805 generics: &ast::Generics,
806 param_substs: Option<@param_substs>,
807 file_metadata: DIFile,
808 name_to_append_suffix_to: &mut StrBuf)
810 let self_type = match param_substs {
811 Some(param_substs) => param_substs.self_ty,
815 // Only true for static default methods:
816 let has_self_type = self_type.is_some();
818 if !generics.is_type_parameterized() && !has_self_type {
819 return create_DIArray(DIB(cx), []);
822 name_to_append_suffix_to.push_char('<');
824 // The list to be filled with template parameters:
825 let mut template_params: Vec<DIDescriptor> =
826 Vec::with_capacity(generics.ty_params.len() + 1);
830 let actual_self_type = self_type.unwrap();
831 // Add self type name to <...> clause of function name
832 let actual_self_type_name = ppaux::ty_to_str(cx.tcx(), actual_self_type);
833 name_to_append_suffix_to.push_str(actual_self_type_name);
835 if generics.is_type_parameterized() {
836 name_to_append_suffix_to.push_str(",");
839 // Only create type information if full debuginfo is enabled
840 if cx.sess().opts.debuginfo == FullDebugInfo {
841 let actual_self_type_metadata = type_metadata(cx,
845 let ident = special_idents::type_self;
847 let param_metadata = token::get_ident(ident).get()
850 llvm::LLVMDIBuilderCreateTemplateTypeParameter(
854 actual_self_type_metadata,
861 template_params.push(param_metadata);
865 // Handle other generic parameters
866 let actual_types = match param_substs {
867 Some(param_substs) => ¶m_substs.tys,
869 return create_DIArray(DIB(cx), template_params.as_slice());
873 for (index, &ast::TyParam{ ident: ident, .. }) in generics.ty_params.iter().enumerate() {
874 let actual_type = *actual_types.get(index);
875 // Add actual type name to <...> clause of function name
876 let actual_type_name = ppaux::ty_to_str(cx.tcx(), actual_type);
877 name_to_append_suffix_to.push_str(actual_type_name);
879 if index != generics.ty_params.len() - 1 {
880 name_to_append_suffix_to.push_str(",");
883 // Again, only create type information if full debuginfo is enabled
884 if cx.sess().opts.debuginfo == FullDebugInfo {
885 let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP);
886 let param_metadata = token::get_ident(ident).get()
889 llvm::LLVMDIBuilderCreateTemplateTypeParameter(
893 actual_type_metadata,
899 template_params.push(param_metadata);
903 name_to_append_suffix_to.push_char('>');
905 return create_DIArray(DIB(cx), template_params.as_slice());
909 //=-------------------------------------------------------------------------------------------------
910 // Module-Internal debug info creation functions
911 //=-------------------------------------------------------------------------------------------------
913 fn is_node_local_to_unit(cx: &CrateContext, node_id: ast::NodeId) -> bool
915 // The is_local_to_unit flag indicates whether a function is local to the current compilation
916 // unit (i.e. if it is *static* in the C-sense). The *reachable* set should provide a good
917 // approximation of this, as it contains everything that might leak out of the current crate
918 // (by being externally visible or by being inlined into something externally visible). It might
919 // better to use the `exported_items` set from `driver::CrateAnalysis` in the future, but (atm)
920 // this set is not available in the translation pass.
921 !cx.reachable.contains(&node_id)
924 fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
926 llvm::LLVMDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32)
930 fn compile_unit_metadata(cx: &CrateContext) {
931 let work_dir = &cx.sess().working_dir;
932 let compile_unit_name = match cx.sess().local_crate_source_file {
933 None => fallback_path(cx),
934 Some(ref abs_path) => {
935 if abs_path.is_relative() {
936 cx.sess().warn("debuginfo: Invalid path to crate's local root source file!");
939 match abs_path.path_relative_from(work_dir) {
940 Some(ref p) if p.is_relative() => {
941 // prepend "./" if necessary
942 let dotdot = bytes!("..");
943 let prefix = &[dotdot[0], ::std::path::SEP_BYTE];
944 let mut path_bytes = p.as_vec().to_owned();
946 if path_bytes.slice_to(2) != prefix &&
947 path_bytes.slice_to(2) != dotdot {
948 path_bytes.insert(0, prefix[0]);
949 path_bytes.insert(1, prefix[1]);
952 path_bytes.to_c_str()
954 _ => fallback_path(cx)
960 debug!("compile_unit_metadata: {:?}", compile_unit_name);
961 let producer = format!("rustc version {}", env!("CFG_VERSION"));
963 compile_unit_name.with_ref(|compile_unit_name| {
964 work_dir.as_vec().with_c_str(|work_dir| {
965 producer.with_c_str(|producer| {
966 "".with_c_str(|flags| {
967 "".with_c_str(|split_name| {
969 llvm::LLVMDIBuilderCreateCompileUnit(
970 debug_context(cx).builder,
975 cx.sess().opts.optimize != session::No,
986 fn fallback_path(cx: &CrateContext) -> CString {
987 cx.link_meta.crateid.name.to_c_str()
991 fn declare_local(bcx: &Block,
992 variable_ident: ast::Ident,
993 variable_type: ty::t,
994 scope_metadata: DIScope,
995 variable_access: VariableAccess,
996 variable_kind: VariableKind,
998 let cx: &CrateContext = bcx.ccx();
1000 let filename = span_start(cx, span).file.name.clone();
1001 let file_metadata = file_metadata(cx, filename);
1003 let name = token::get_ident(variable_ident);
1004 let loc = span_start(cx, span);
1005 let type_metadata = type_metadata(cx, variable_type, span);
1007 let (argument_index, dwarf_tag) = match variable_kind {
1008 ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),
1010 CapturedVariable => (0, DW_TAG_auto_variable)
1013 let (var_alloca, var_metadata) = name.get().with_c_str(|name| {
1014 match variable_access {
1015 DirectVariable { alloca } => (
1018 llvm::LLVMDIBuilderCreateLocalVariable(
1026 cx.sess().opts.optimize != session::No,
1031 IndirectVariable { alloca, address_operations } => (
1034 llvm::LLVMDIBuilderCreateComplexVariable(
1042 address_operations.as_ptr(),
1043 address_operations.len() as c_uint,
1050 set_debug_location(cx, DebugLocation::new(scope_metadata, loc.line, loc.col.to_uint()));
1052 let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
1058 llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr);
1061 match variable_kind {
1062 ArgumentVariable(_) | CapturedVariable => {
1066 .source_locations_enabled
1068 set_debug_location(cx, UnknownLocation);
1070 _ => { /* nothing to do */ }
1074 fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
1075 match debug_context(cx).created_files.borrow().find_equiv(&full_path) {
1076 Some(file_metadata) => return *file_metadata,
1080 debug!("file_metadata: {}", full_path);
1082 // FIXME (#9639): This needs to handle non-utf8 paths
1083 let work_dir = cx.sess().working_dir.as_str().unwrap();
1085 if full_path.starts_with(work_dir) {
1086 full_path.slice(work_dir.len() + 1u, full_path.len())
1092 file_name.with_c_str(|file_name| {
1093 work_dir.with_c_str(|work_dir| {
1095 llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir)
1100 let mut created_files = debug_context(cx).created_files.borrow_mut();
1101 created_files.insert(full_path.to_owned(), file_metadata);
1102 return file_metadata;
1105 /// Finds the scope metadata node for the given AST node.
1106 fn scope_metadata(fcx: &FunctionContext,
1107 node_id: ast::NodeId,
1110 let scope_map = &fcx.debug_context.get_ref(fcx.ccx, span).scope_map;
1111 match scope_map.borrow().find_copy(&node_id) {
1112 Some(scope_metadata) => scope_metadata,
1114 let node = fcx.ccx.tcx.map.get(node_id);
1116 fcx.ccx.sess().span_bug(span,
1117 format!("debuginfo: Could not find scope info for node {:?}", node));
1122 fn basic_type_metadata(cx: &CrateContext, t: ty::t) -> DIType {
1124 debug!("basic_type_metadata: {:?}", ty::get(t));
1126 let (name, encoding) = match ty::get(t).sty {
1127 ty::ty_nil => (~"()", DW_ATE_unsigned),
1128 ty::ty_bot => (~"!", DW_ATE_unsigned),
1129 ty::ty_bool => (~"bool", DW_ATE_boolean),
1130 ty::ty_char => (~"char", DW_ATE_unsigned_char),
1131 ty::ty_int(int_ty) => match int_ty {
1132 ast::TyI => (~"int", DW_ATE_signed),
1133 ast::TyI8 => (~"i8", DW_ATE_signed),
1134 ast::TyI16 => (~"i16", DW_ATE_signed),
1135 ast::TyI32 => (~"i32", DW_ATE_signed),
1136 ast::TyI64 => (~"i64", DW_ATE_signed)
1138 ty::ty_uint(uint_ty) => match uint_ty {
1139 ast::TyU => (~"uint", DW_ATE_unsigned),
1140 ast::TyU8 => (~"u8", DW_ATE_unsigned),
1141 ast::TyU16 => (~"u16", DW_ATE_unsigned),
1142 ast::TyU32 => (~"u32", DW_ATE_unsigned),
1143 ast::TyU64 => (~"u64", DW_ATE_unsigned)
1145 ty::ty_float(float_ty) => match float_ty {
1146 ast::TyF32 => (~"f32", DW_ATE_float),
1147 ast::TyF64 => (~"f64", DW_ATE_float)
1149 _ => cx.sess().bug("debuginfo::basic_type_metadata - t is invalid type")
1152 let llvm_type = type_of::type_of(cx, t);
1153 let (size, align) = size_and_align_of(cx, llvm_type);
1154 let ty_metadata = name.with_c_str(|name| {
1156 llvm::LLVMDIBuilderCreateBasicType(
1159 bytes_to_bits(size),
1160 bytes_to_bits(align),
1168 fn pointer_type_metadata(cx: &CrateContext,
1169 pointer_type: ty::t,
1170 pointee_type_metadata: DIType)
1172 let pointer_llvm_type = type_of::type_of(cx, pointer_type);
1173 let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
1174 let name = ppaux::ty_to_str(cx.tcx(), pointer_type);
1175 let ptr_metadata = name.with_c_str(|name| {
1177 llvm::LLVMDIBuilderCreatePointerType(
1179 pointee_type_metadata,
1180 bytes_to_bits(pointer_size),
1181 bytes_to_bits(pointer_align),
1185 return ptr_metadata;
1188 enum MemberDescriptionFactory {
1189 StructMD(StructMemberDescriptionFactory),
1190 TupleMD(TupleMemberDescriptionFactory),
1191 GeneralMD(GeneralMemberDescriptionFactory),
1192 EnumVariantMD(EnumVariantMemberDescriptionFactory)
1195 impl MemberDescriptionFactory {
1196 fn create_member_descriptions(&self, cx: &CrateContext)
1197 -> Vec<MemberDescription> {
1199 StructMD(ref this) => {
1200 this.create_member_descriptions(cx)
1202 TupleMD(ref this) => {
1203 this.create_member_descriptions(cx)
1205 GeneralMD(ref this) => {
1206 this.create_member_descriptions(cx)
1208 EnumVariantMD(ref this) => {
1209 this.create_member_descriptions(cx)
1215 struct StructMemberDescriptionFactory {
1216 fields: Vec<ty::field> ,
1220 impl StructMemberDescriptionFactory {
1221 fn create_member_descriptions(&self, cx: &CrateContext)
1222 -> Vec<MemberDescription> {
1223 self.fields.iter().map(|field| {
1224 let name = if field.ident.name == special_idents::unnamed_field.name {
1227 token::get_ident(field.ident).get().to_str()
1232 llvm_type: type_of::type_of(cx, field.mt.ty),
1233 type_metadata: type_metadata(cx, field.mt.ty, self.span),
1234 offset: ComputedMemberOffset,
1240 fn prepare_struct_metadata(cx: &CrateContext,
1243 substs: &ty::substs,
1245 -> RecursiveTypeDescription {
1246 let struct_name = ppaux::ty_to_str(cx.tcx(), struct_type);
1247 let struct_llvm_type = type_of::type_of(cx, struct_type);
1249 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id);
1251 let file_name = span_start(cx, definition_span).file.name.clone();
1252 let file_metadata = file_metadata(cx, file_name);
1254 let struct_metadata_stub = create_struct_stub(cx,
1261 let fields = ty::struct_fields(cx.tcx(), def_id, substs);
1263 UnfinishedMetadata {
1264 cache_id: cache_id_for_type(struct_type),
1265 metadata_stub: struct_metadata_stub,
1266 llvm_type: struct_llvm_type,
1267 file_metadata: file_metadata,
1268 member_description_factory: StructMD(StructMemberDescriptionFactory {
1275 enum RecursiveTypeDescription {
1276 UnfinishedMetadata {
1278 metadata_stub: DICompositeType,
1280 file_metadata: DIFile,
1281 member_description_factory: MemberDescriptionFactory,
1283 FinalMetadata(DICompositeType)
1286 impl RecursiveTypeDescription {
1288 fn finalize(&self, cx: &CrateContext) -> DICompositeType {
1290 FinalMetadata(metadata) => metadata,
1291 UnfinishedMetadata {
1296 ref member_description_factory
1298 // Insert the stub into the cache in order to allow recursive references ...
1299 debug_context(cx).created_types.borrow_mut()
1300 .insert(cache_id, metadata_stub);
1302 // ... then create the member descriptions ...
1303 let member_descriptions = member_description_factory.create_member_descriptions(cx);
1305 // ... and attach them to the stub to complete it.
1306 set_members_of_composite_type(cx,
1309 member_descriptions.as_slice(),
1312 return metadata_stub;
1318 struct TupleMemberDescriptionFactory {
1319 component_types: Vec<ty::t> ,
1323 impl TupleMemberDescriptionFactory {
1324 fn create_member_descriptions(&self, cx: &CrateContext)
1325 -> Vec<MemberDescription> {
1326 self.component_types.iter().map(|&component_type| {
1329 llvm_type: type_of::type_of(cx, component_type),
1330 type_metadata: type_metadata(cx, component_type, self.span),
1331 offset: ComputedMemberOffset,
1337 fn prepare_tuple_metadata(cx: &CrateContext,
1339 component_types: &[ty::t],
1341 -> RecursiveTypeDescription {
1342 let tuple_name = ppaux::ty_to_str(cx.tcx(), tuple_type);
1343 let tuple_llvm_type = type_of::type_of(cx, tuple_type);
1345 let loc = span_start(cx, span);
1346 let file_metadata = file_metadata(cx, loc.file.name);
1348 UnfinishedMetadata {
1349 cache_id: cache_id_for_type(tuple_type),
1350 metadata_stub: create_struct_stub(cx,
1356 llvm_type: tuple_llvm_type,
1357 file_metadata: file_metadata,
1358 member_description_factory: TupleMD(TupleMemberDescriptionFactory {
1359 component_types: Vec::from_slice(component_types),
1365 struct GeneralMemberDescriptionFactory {
1366 type_rep: @adt::Repr,
1367 variants: @Vec<@ty::VariantInfo> ,
1368 discriminant_type_metadata: ValueRef,
1369 containing_scope: DIScope,
1370 file_metadata: DIFile,
1374 impl GeneralMemberDescriptionFactory {
1375 fn create_member_descriptions(&self, cx: &CrateContext)
1376 -> Vec<MemberDescription> {
1377 // Capture type_rep, so we don't have to copy the struct_defs array
1378 let struct_defs = match *self.type_rep {
1379 adt::General(_, ref struct_defs) => struct_defs,
1380 _ => cx.sess().bug("unreachable")
1386 .map(|(i, struct_def)| {
1387 let (variant_type_metadata, variant_llvm_type, member_desc_factory) =
1388 describe_enum_variant(cx,
1390 *self.variants.get(i),
1391 Some(self.discriminant_type_metadata),
1392 self.containing_scope,
1396 let member_descriptions =
1397 member_desc_factory.create_member_descriptions(cx);
1399 set_members_of_composite_type(cx,
1400 variant_type_metadata,
1402 member_descriptions.as_slice(),
1407 llvm_type: variant_llvm_type,
1408 type_metadata: variant_type_metadata,
1409 offset: FixedMemberOffset { bytes: 0 },
1415 struct EnumVariantMemberDescriptionFactory {
1416 args: Vec<(~str, ty::t)> ,
1417 discriminant_type_metadata: Option<DIType>,
1421 impl EnumVariantMemberDescriptionFactory {
1422 fn create_member_descriptions(&self, cx: &CrateContext)
1423 -> Vec<MemberDescription> {
1424 self.args.iter().enumerate().map(|(i, &(ref name, ty))| {
1426 name: name.to_str(),
1427 llvm_type: type_of::type_of(cx, ty),
1428 type_metadata: match self.discriminant_type_metadata {
1429 Some(metadata) if i == 0 => metadata,
1430 _ => type_metadata(cx, ty, self.span)
1432 offset: ComputedMemberOffset,
1438 fn describe_enum_variant(cx: &CrateContext,
1439 struct_def: &adt::Struct,
1440 variant_info: &ty::VariantInfo,
1441 discriminant_type_metadata: Option<DIType>,
1442 containing_scope: DIScope,
1443 file_metadata: DIFile,
1445 -> (DICompositeType, Type, MemberDescriptionFactory) {
1446 let variant_llvm_type =
1447 Type::struct_(cx, struct_def.fields
1449 .map(|&t| type_of::type_of(cx, t))
1450 .collect::<Vec<_>>()
1453 // Could some consistency checks here: size, align, field count, discr type
1455 // Find the source code location of the variant's definition
1456 let variant_definition_span = if variant_info.id.krate == ast::LOCAL_CRATE {
1457 cx.tcx.map.span(variant_info.id.node)
1459 // For definitions from other crates we have no location information available.
1463 let metadata_stub = create_struct_stub(cx,
1465 token::get_ident(variant_info.name).get(),
1468 variant_definition_span);
1470 // Get the argument names from the enum variant info
1471 let mut arg_names: Vec<_> = match variant_info.arg_names {
1472 Some(ref names) => {
1473 names.iter().map(|ident| token::get_ident(*ident).get().to_str()).collect()
1475 None => variant_info.args.iter().map(|_| ~"").collect()
1478 // If this is not a univariant enum, there is also the (unnamed) discriminant field
1479 if discriminant_type_metadata.is_some() {
1480 arg_names.insert(0, ~"");
1483 // Build an array of (field name, field type) pairs to be captured in the factory closure.
1484 let args: Vec<(~str, ty::t)> = arg_names.iter()
1485 .zip(struct_def.fields.iter())
1486 .map(|(s, &t)| (s.to_str(), t))
1489 let member_description_factory =
1490 EnumVariantMD(EnumVariantMemberDescriptionFactory {
1492 discriminant_type_metadata: discriminant_type_metadata,
1496 (metadata_stub, variant_llvm_type, member_description_factory)
1499 fn prepare_enum_metadata(cx: &CrateContext,
1501 enum_def_id: ast::DefId,
1503 -> RecursiveTypeDescription {
1504 let enum_name = ppaux::ty_to_str(cx.tcx(), enum_type);
1506 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, enum_def_id);
1507 let loc = span_start(cx, definition_span);
1508 let file_metadata = file_metadata(cx, loc.file.name);
1510 // For empty enums there is an early exit. Just describe it as an empty struct with the
1511 // appropriate type name
1512 if ty::type_is_empty(cx.tcx(), enum_type) {
1513 let empty_type_metadata = composite_type_metadata(cx,
1521 return FinalMetadata(empty_type_metadata);
1524 let variants = ty::enum_variants(cx.tcx(), enum_def_id);
1526 let enumerators_metadata: Vec<DIDescriptor> = variants
1529 token::get_ident(v.name).get().with_c_str(|name| {
1531 llvm::LLVMDIBuilderCreateEnumerator(
1534 v.disr_val as c_ulonglong)
1540 let discriminant_type_metadata = |inttype| {
1541 let discriminant_llvm_type = adt::ll_inttype(cx, inttype);
1542 let (discriminant_size, discriminant_align) = size_and_align_of(cx, discriminant_llvm_type);
1543 let discriminant_base_type_metadata = type_metadata(cx, adt::ty_of_inttype(inttype),
1545 enum_name.with_c_str(|enum_name| {
1547 llvm::LLVMDIBuilderCreateEnumerationType(
1553 bytes_to_bits(discriminant_size),
1554 bytes_to_bits(discriminant_align),
1555 create_DIArray(DIB(cx), enumerators_metadata.as_slice()),
1556 discriminant_base_type_metadata)
1561 let type_rep = adt::represent_type(cx, enum_type);
1563 return match *type_rep {
1564 adt::CEnum(inttype, _, _) => {
1565 FinalMetadata(discriminant_type_metadata(inttype))
1567 adt::Univariant(ref struct_def, _) => {
1568 assert!(variants.len() == 1);
1571 member_description_factory) =
1572 describe_enum_variant(cx,
1579 UnfinishedMetadata {
1580 cache_id: cache_id_for_type(enum_type),
1581 metadata_stub: metadata_stub,
1582 llvm_type: variant_llvm_type,
1583 file_metadata: file_metadata,
1584 member_description_factory: member_description_factory
1587 adt::General(inttype, _) => {
1588 let discriminant_type_metadata = discriminant_type_metadata(inttype);
1589 let enum_llvm_type = type_of::type_of(cx, enum_type);
1590 let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type);
1591 let unique_id = generate_unique_type_id("DI_ENUM_");
1593 let enum_metadata = enum_name.with_c_str(|enum_name| {
1594 unique_id.with_c_str(|unique_id| {
1596 llvm::LLVMDIBuilderCreateUnionType(
1602 bytes_to_bits(enum_type_size),
1603 bytes_to_bits(enum_type_align),
1612 UnfinishedMetadata {
1613 cache_id: cache_id_for_type(enum_type),
1614 metadata_stub: enum_metadata,
1615 llvm_type: enum_llvm_type,
1616 file_metadata: file_metadata,
1617 member_description_factory: GeneralMD(GeneralMemberDescriptionFactory {
1620 discriminant_type_metadata: discriminant_type_metadata,
1621 containing_scope: containing_scope,
1622 file_metadata: file_metadata,
1627 adt::NullablePointer { nonnull: ref struct_def, nndiscr, .. } => {
1630 member_description_factory) =
1631 describe_enum_variant(cx,
1633 *variants.get(nndiscr as uint),
1638 UnfinishedMetadata {
1639 cache_id: cache_id_for_type(enum_type),
1640 metadata_stub: metadata_stub,
1641 llvm_type: variant_llvm_type,
1642 file_metadata: file_metadata,
1643 member_description_factory: member_description_factory
1650 FixedMemberOffset { bytes: uint },
1651 // For ComputedMemberOffset, the offset is read from the llvm type definition
1652 ComputedMemberOffset
1655 struct MemberDescription {
1658 type_metadata: DIType,
1659 offset: MemberOffset,
1662 /// Creates debug information for a composite type, that is, anything that results in a LLVM struct.
1664 /// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums.
1665 fn composite_type_metadata(cx: &CrateContext,
1666 composite_llvm_type: Type,
1667 composite_type_name: &str,
1668 member_descriptions: &[MemberDescription],
1669 containing_scope: DIScope,
1670 file_metadata: DIFile,
1671 definition_span: Span)
1672 -> DICompositeType {
1673 // Create the (empty) struct metadata node ...
1674 let composite_type_metadata = create_struct_stub(cx,
1675 composite_llvm_type,
1676 composite_type_name,
1681 // ... and immediately create and add the member descriptions.
1682 set_members_of_composite_type(cx,
1683 composite_type_metadata,
1684 composite_llvm_type,
1685 member_descriptions,
1689 return composite_type_metadata;
1692 fn set_members_of_composite_type(cx: &CrateContext,
1693 composite_type_metadata: DICompositeType,
1694 composite_llvm_type: Type,
1695 member_descriptions: &[MemberDescription],
1696 file_metadata: DIFile,
1697 definition_span: Span) {
1698 // In some rare cases LLVM metadata uniquing would lead to an existing type description being
1699 // used instead of a new one created in create_struct_stub. This would cause a hard to trace
1700 // assertion in DICompositeType::SetTypeArray(). The following check makes sure that we get a
1701 // better error message if this should happen again due to some regression.
1703 let mut composite_types_completed =
1704 debug_context(cx).composite_types_completed.borrow_mut();
1705 if composite_types_completed.contains(&composite_type_metadata) {
1706 cx.sess().span_bug(definition_span, "debuginfo::set_members_of_composite_type() - \
1707 Already completed forward declaration \
1710 composite_types_completed.insert(composite_type_metadata);
1714 let loc = span_start(cx, definition_span);
1716 let member_metadata: Vec<DIDescriptor> = member_descriptions
1719 .map(|(i, member_description)| {
1720 let (member_size, member_align) = size_and_align_of(cx, member_description.llvm_type);
1721 let member_offset = match member_description.offset {
1722 FixedMemberOffset { bytes } => bytes as u64,
1723 ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i)
1726 member_description.name.with_c_str(|member_name| {
1728 llvm::LLVMDIBuilderCreateMemberType(
1730 composite_type_metadata,
1734 bytes_to_bits(member_size),
1735 bytes_to_bits(member_align),
1736 bytes_to_bits(member_offset),
1738 member_description.type_metadata)
1745 let type_array = create_DIArray(DIB(cx), member_metadata.as_slice());
1746 llvm::LLVMDICompositeTypeSetTypeArray(composite_type_metadata, type_array);
1750 // A convenience wrapper around LLVMDIBuilderCreateStructType(). Does not do any caching, does not
1751 // add any fields to the struct. This can be done later with set_members_of_composite_type().
1752 fn create_struct_stub(cx: &CrateContext,
1753 struct_llvm_type: Type,
1754 struct_type_name: &str,
1755 containing_scope: DIScope,
1756 file_metadata: DIFile,
1757 definition_span: Span)
1758 -> DICompositeType {
1759 let loc = span_start(cx, definition_span);
1760 let (struct_size, struct_align) = size_and_align_of(cx, struct_llvm_type);
1762 // We assign unique IDs to the type stubs so LLVM metadata uniquing does not reuse instances
1763 // where we don't want it.
1764 let unique_id = generate_unique_type_id("DI_STRUCT_");
1767 struct_type_name.with_c_str(|name| {
1768 unique_id.with_c_str(|unique_id| {
1769 // LLVMDIBuilderCreateStructType() wants an empty array. A null pointer will lead to
1770 // hard to trace and debug LLVM assertions later on in llvm/lib/IR/Value.cpp
1771 let empty_array = create_DIArray(DIB(cx), []);
1773 llvm::LLVMDIBuilderCreateStructType(
1779 bytes_to_bits(struct_size),
1780 bytes_to_bits(struct_align),
1792 fn boxed_type_metadata(cx: &CrateContext,
1793 content_type_name: Option<&str>,
1794 content_llvm_type: Type,
1795 content_type_metadata: DIType,
1797 -> DICompositeType {
1798 let box_type_name = match content_type_name {
1799 Some(content_type_name) => format!("Boxed<{}>", content_type_name),
1800 None => ~"BoxedType"
1803 let box_llvm_type = Type::at_box(cx, content_llvm_type);
1804 let member_llvm_types = box_llvm_type.field_types();
1805 assert!(box_layout_is_correct(cx,
1806 member_llvm_types.as_slice(),
1807 content_llvm_type));
1809 let int_type = ty::mk_int();
1810 let nil_pointer_type = ty::mk_nil_ptr(cx.tcx());
1811 let nil_pointer_type_metadata = type_metadata(cx, nil_pointer_type, codemap::DUMMY_SP);
1813 let member_descriptions = [
1816 llvm_type: *member_llvm_types.get(0),
1817 type_metadata: type_metadata(cx, int_type, codemap::DUMMY_SP),
1818 offset: ComputedMemberOffset,
1822 llvm_type: *member_llvm_types.get(1),
1823 type_metadata: nil_pointer_type_metadata,
1824 offset: ComputedMemberOffset,
1828 llvm_type: *member_llvm_types.get(2),
1829 type_metadata: nil_pointer_type_metadata,
1830 offset: ComputedMemberOffset,
1834 llvm_type: *member_llvm_types.get(3),
1835 type_metadata: nil_pointer_type_metadata,
1836 offset: ComputedMemberOffset,
1840 llvm_type: *member_llvm_types.get(4),
1841 type_metadata: content_type_metadata,
1842 offset: ComputedMemberOffset,
1846 let loc = span_start(cx, span);
1847 let file_metadata = file_metadata(cx, loc.file.name);
1849 return composite_type_metadata(
1853 member_descriptions,
1858 // Unfortunately, we cannot assert anything but the correct types here---and not whether the
1859 // 'next' and 'prev' pointers are in the correct order.
1860 fn box_layout_is_correct(cx: &CrateContext,
1861 member_llvm_types: &[Type],
1862 content_llvm_type: Type)
1864 member_llvm_types.len() == 5 &&
1865 member_llvm_types[0] == cx.int_type &&
1866 member_llvm_types[1] == Type::generic_glue_fn(cx).ptr_to() &&
1867 member_llvm_types[2] == Type::i8(cx).ptr_to() &&
1868 member_llvm_types[3] == Type::i8(cx).ptr_to() &&
1869 member_llvm_types[4] == content_llvm_type
1873 fn fixed_vec_metadata(cx: &CrateContext,
1874 element_type: ty::t,
1878 let element_type_metadata = type_metadata(cx, element_type, span);
1879 let element_llvm_type = type_of::type_of(cx, element_type);
1880 let (element_type_size, element_type_align) = size_and_align_of(cx, element_llvm_type);
1882 let subrange = unsafe {
1883 llvm::LLVMDIBuilderGetOrCreateSubrange(
1889 let subscripts = create_DIArray(DIB(cx), [subrange]);
1891 llvm::LLVMDIBuilderCreateArrayType(
1893 bytes_to_bits(element_type_size * (len as u64)),
1894 bytes_to_bits(element_type_align),
1895 element_type_metadata,
1900 fn vec_metadata(cx: &CrateContext,
1901 element_type: ty::t,
1903 -> DICompositeType {
1905 let element_type_metadata = type_metadata(cx, element_type, span);
1906 let element_llvm_type = type_of::type_of(cx, element_type);
1907 let (element_size, element_align) = size_and_align_of(cx, element_llvm_type);
1909 let vec_llvm_type = Type::vec(cx, &element_llvm_type);
1910 let vec_type_name: &str = format!("[{}]", ppaux::ty_to_str(cx.tcx(), element_type));
1912 let member_llvm_types = vec_llvm_type.field_types();
1914 let int_type_metadata = type_metadata(cx, ty::mk_int(), span);
1915 let array_type_metadata = unsafe {
1916 llvm::LLVMDIBuilderCreateArrayType(
1918 bytes_to_bits(element_size),
1919 bytes_to_bits(element_align),
1920 element_type_metadata,
1921 create_DIArray(DIB(cx), [llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, 0)]))
1924 let member_descriptions = [
1927 llvm_type: *member_llvm_types.get(0),
1928 type_metadata: int_type_metadata,
1929 offset: ComputedMemberOffset,
1933 llvm_type: *member_llvm_types.get(1),
1934 type_metadata: int_type_metadata,
1935 offset: ComputedMemberOffset,
1939 llvm_type: *member_llvm_types.get(2),
1940 type_metadata: array_type_metadata,
1941 offset: ComputedMemberOffset,
1945 assert!(member_descriptions.len() == member_llvm_types.len());
1947 let loc = span_start(cx, span);
1948 let file_metadata = file_metadata(cx, loc.file.name);
1950 composite_type_metadata(
1954 member_descriptions,
1960 fn vec_slice_metadata(cx: &CrateContext,
1962 element_type: ty::t,
1964 -> DICompositeType {
1966 debug!("vec_slice_metadata: {:?}", ty::get(vec_type));
1968 let slice_llvm_type = type_of::type_of(cx, vec_type);
1969 let slice_type_name = ppaux::ty_to_str(cx.tcx(), vec_type);
1971 let member_llvm_types = slice_llvm_type.field_types();
1972 assert!(slice_layout_is_correct(cx,
1973 member_llvm_types.as_slice(),
1976 let data_ptr_type = ty::mk_ptr(cx.tcx(), ty::mt {
1978 mutbl: ast::MutImmutable
1981 let member_descriptions = [
1984 llvm_type: *member_llvm_types.get(0),
1985 type_metadata: type_metadata(cx, data_ptr_type, span),
1986 offset: ComputedMemberOffset,
1990 llvm_type: *member_llvm_types.get(1),
1991 type_metadata: type_metadata(cx, ty::mk_uint(), span),
1992 offset: ComputedMemberOffset,
1996 assert!(member_descriptions.len() == member_llvm_types.len());
1998 let loc = span_start(cx, span);
1999 let file_metadata = file_metadata(cx, loc.file.name);
2001 return composite_type_metadata(
2005 member_descriptions,
2010 fn slice_layout_is_correct(cx: &CrateContext,
2011 member_llvm_types: &[Type],
2012 element_type: ty::t)
2014 member_llvm_types.len() == 2 &&
2015 member_llvm_types[0] == type_of::type_of(cx, element_type).ptr_to() &&
2016 member_llvm_types[1] == cx.int_type
2020 fn subroutine_type_metadata(cx: &CrateContext,
2021 signature: &ty::FnSig,
2023 -> DICompositeType {
2024 let loc = span_start(cx, span);
2025 let file_metadata = file_metadata(cx, loc.file.name);
2027 let mut signature_metadata: Vec<DIType> =
2028 Vec::with_capacity(signature.inputs.len() + 1);
2031 signature_metadata.push(match ty::get(signature.output).sty {
2032 ty::ty_nil => ptr::null(),
2033 _ => type_metadata(cx, signature.output, span)
2036 // regular arguments
2037 for &argument_type in signature.inputs.iter() {
2038 signature_metadata.push(type_metadata(cx, argument_type, span));
2042 llvm::LLVMDIBuilderCreateSubroutineType(
2045 create_DIArray(DIB(cx), signature_metadata.as_slice()))
2049 fn trait_metadata(cx: &CrateContext,
2052 substs: &ty::substs,
2053 trait_store: ty::TraitStore,
2054 mutability: ast::Mutability,
2055 _: &ty::BuiltinBounds)
2057 // The implementation provided here is a stub. It makes sure that the trait type is
2058 // assigned the correct name, size, namespace, and source location. But it does not describe
2059 // the trait's methods.
2060 let last = ty::with_path(cx.tcx(), def_id, |mut path| path.last().unwrap());
2061 let ident_string = token::get_name(last.name());
2062 let name = ppaux::trait_store_to_str(cx.tcx(), trait_store) +
2063 ppaux::mutability_to_str(mutability) +
2065 // Add type and region parameters
2066 let name = ppaux::parameterized(cx.tcx(), name, &substs.regions,
2067 substs.tps.as_slice(), def_id, true);
2069 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id);
2071 let file_name = span_start(cx, definition_span).file.name.clone();
2072 let file_metadata = file_metadata(cx, file_name);
2074 let trait_llvm_type = type_of::type_of(cx, trait_type);
2076 return composite_type_metadata(cx,
2085 fn type_metadata(cx: &CrateContext,
2087 usage_site_span: Span)
2089 let cache_id = cache_id_for_type(t);
2091 match debug_context(cx).created_types.borrow().find(&cache_id) {
2092 Some(type_metadata) => return *type_metadata,
2096 fn create_pointer_to_box_metadata(cx: &CrateContext,
2097 pointer_type: ty::t,
2100 let content_type_name: &str = ppaux::ty_to_str(cx.tcx(), type_in_box);
2101 let content_llvm_type = type_of::type_of(cx, type_in_box);
2102 let content_type_metadata = type_metadata(
2107 let box_metadata = boxed_type_metadata(
2109 Some(content_type_name),
2111 content_type_metadata,
2114 pointer_type_metadata(cx, pointer_type, box_metadata)
2117 debug!("type_metadata: {:?}", ty::get(t));
2119 let sty = &ty::get(t).sty;
2120 let type_metadata = match *sty {
2127 ty::ty_float(_) => {
2128 basic_type_metadata(cx, t)
2130 ty::ty_str(ref vstore) => {
2131 let i8_t = ty::mk_i8();
2133 ty::vstore_fixed(len) => {
2134 fixed_vec_metadata(cx, i8_t, len, usage_site_span)
2136 ty::vstore_uniq => {
2137 let vec_metadata = vec_metadata(cx, i8_t, usage_site_span);
2138 pointer_type_metadata(cx, t, vec_metadata)
2140 ty::vstore_slice(_region) => {
2141 vec_slice_metadata(cx, t, i8_t, usage_site_span)
2145 ty::ty_enum(def_id, _) => {
2146 prepare_enum_metadata(cx, t, def_id, usage_site_span).finalize(cx)
2148 ty::ty_box(typ) => {
2149 create_pointer_to_box_metadata(cx, t, typ)
2151 ty::ty_vec(ref mt, ref vstore) => {
2153 ty::vstore_fixed(len) => {
2154 fixed_vec_metadata(cx, mt.ty, len, usage_site_span)
2156 ty::vstore_uniq => {
2157 let vec_metadata = vec_metadata(cx, mt.ty, usage_site_span);
2158 pointer_type_metadata(cx, t, vec_metadata)
2160 ty::vstore_slice(_) => {
2161 vec_slice_metadata(cx, t, mt.ty, usage_site_span)
2165 ty::ty_uniq(typ) => {
2166 let pointee = type_metadata(cx, typ, usage_site_span);
2167 pointer_type_metadata(cx, t, pointee)
2169 ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => {
2170 let pointee = type_metadata(cx, mt.ty, usage_site_span);
2171 pointer_type_metadata(cx, t, pointee)
2173 ty::ty_bare_fn(ref barefnty) => {
2174 subroutine_type_metadata(cx, &barefnty.sig, usage_site_span)
2176 ty::ty_closure(ref closurety) => {
2177 subroutine_type_metadata(cx, &closurety.sig, usage_site_span)
2179 ty::ty_trait(~ty::TyTrait { def_id, ref substs,
2180 store: trait_store, mutability,
2182 trait_metadata(cx, def_id, t, substs, trait_store, mutability, bounds)
2184 ty::ty_struct(def_id, ref substs) => {
2185 if ty::type_is_simd(cx.tcx(), t) {
2186 let element_type = ty::simd_type(cx.tcx(), t);
2187 let len = ty::simd_size(cx.tcx(), t);
2188 fixed_vec_metadata(cx, element_type, len, usage_site_span)
2190 prepare_struct_metadata(cx, t, def_id, substs, usage_site_span).finalize(cx)
2193 ty::ty_tup(ref elements) => {
2194 prepare_tuple_metadata(cx,
2196 elements.as_slice(),
2197 usage_site_span).finalize(cx)
2199 _ => cx.sess().bug(format!("debuginfo: unexpected type in type_metadata: {:?}", sty))
2202 debug_context(cx).created_types.borrow_mut().insert(cache_id, type_metadata);
2207 enum DebugLocation {
2208 KnownLocation { scope: DIScope, line: uint, col: uint },
2212 impl DebugLocation {
2213 fn new(scope: DIScope, line: uint, col: uint) -> DebugLocation {
2222 fn set_debug_location(cx: &CrateContext, debug_location: DebugLocation) {
2223 if debug_location == debug_context(cx).current_debug_location.get() {
2229 match debug_location {
2230 KnownLocation { scope, line, .. } => {
2231 let col = 0; // Always set the column to zero like Clang and GCC
2232 debug!("setting debug location to {} {}", line, col);
2233 let elements = [C_i32(cx, line as i32), C_i32(cx, col as i32), scope, ptr::null()];
2235 metadata_node = llvm::LLVMMDNodeInContext(debug_context(cx).llcontext,
2237 elements.len() as c_uint);
2240 UnknownLocation => {
2241 debug!("clearing debug location ");
2242 metadata_node = ptr::null();
2247 llvm::LLVMSetCurrentDebugLocation(cx.builder.b, metadata_node);
2250 debug_context(cx).current_debug_location.set(debug_location);
2253 //=-------------------------------------------------------------------------------------------------
2254 // Utility Functions
2255 //=-------------------------------------------------------------------------------------------------
2257 fn cache_id_for_type(t: ty::t) -> uint {
2261 // Used to avoid LLVM metadata uniquing problems. See `create_struct_stub()` and
2262 // `prepare_enum_metadata()`.
2263 fn generate_unique_type_id(prefix: &'static str) -> ~str {
2265 static mut unique_id_counter: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;
2266 format!("{}{}", prefix, unique_id_counter.fetch_add(1, atomics::SeqCst))
2270 /// Return codemap::Loc corresponding to the beginning of the span
2271 fn span_start(cx: &CrateContext, span: Span) -> codemap::Loc {
2272 cx.sess().codemap().lookup_char_pos(span.lo)
2275 fn size_and_align_of(cx: &CrateContext, llvm_type: Type) -> (u64, u64) {
2276 (machine::llsize_of_alloc(cx, llvm_type), machine::llalign_of_min(cx, llvm_type))
2279 fn bytes_to_bits(bytes: u64) -> c_ulonglong {
2280 (bytes * 8) as c_ulonglong
2284 fn debug_context<'a>(cx: &'a CrateContext) -> &'a CrateDebugContext {
2285 let debug_context: &'a CrateDebugContext = cx.dbg_cx.get_ref();
2290 fn DIB(cx: &CrateContext) -> DIBuilderRef {
2291 cx.dbg_cx.get_ref().builder
2294 fn fn_should_be_ignored(fcx: &FunctionContext) -> bool {
2295 match fcx.debug_context {
2296 FunctionDebugContext(_) => false,
2301 fn assert_type_for_node_id(cx: &CrateContext, node_id: ast::NodeId, error_span: Span) {
2302 if !cx.tcx.node_types.borrow().contains_key(&(node_id as uint)) {
2303 cx.sess().span_bug(error_span, "debuginfo: Could not find type for node id!");
2307 fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: ast::DefId)
2308 -> (DIScope, Span) {
2309 let containing_scope = namespace_for_item(cx, def_id).scope;
2310 let definition_span = if def_id.krate == ast::LOCAL_CRATE {
2311 cx.tcx.map.span(def_id.node)
2313 // For external items there is no span information
2317 (containing_scope, definition_span)
2320 // This procedure builds the *scope map* for a given function, which maps any given ast::NodeId in
2321 // the function's AST to the correct DIScope metadata instance.
2323 // This builder procedure walks the AST in execution order and keeps track of what belongs to which
2324 // scope, creating DIScope DIEs along the way, and introducing *artificial* lexical scope
2325 // descriptors where necessary. These artificial scopes allow GDB to correctly handle name
2327 fn populate_scope_map(cx: &CrateContext,
2328 arg_pats: &[@ast::Pat],
2329 fn_entry_block: &ast::Block,
2330 fn_metadata: DISubprogram,
2331 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2332 let def_map = cx.tcx.def_map;
2334 struct ScopeStackEntry {
2335 scope_metadata: DIScope,
2336 ident: Option<ast::Ident>
2339 let mut scope_stack = vec!(ScopeStackEntry { scope_metadata: fn_metadata, ident: None });
2341 // Push argument identifiers onto the stack so arguments integrate nicely with variable
2343 for &arg_pat in arg_pats.iter() {
2344 pat_util::pat_bindings(def_map, arg_pat, |_, _, _, path_ref| {
2345 let ident = ast_util::path_to_ident(path_ref);
2346 scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata, ident: Some(ident) });
2350 // Clang creates a separate scope for function bodies, so let's do this too
2352 fn_entry_block.span,
2355 |cx, scope_stack, scope_map| {
2356 walk_block(cx, fn_entry_block, scope_stack, scope_map);
2359 // local helper functions for walking the AST.
2360 fn with_new_scope(cx: &CrateContext,
2362 scope_stack: &mut Vec<ScopeStackEntry> ,
2363 scope_map: &mut HashMap<ast::NodeId, DIScope>,
2364 inner_walk: |&CrateContext,
2365 &mut Vec<ScopeStackEntry> ,
2366 &mut HashMap<ast::NodeId, DIScope>|) {
2367 // Create a new lexical scope and push it onto the stack
2368 let loc = cx.sess().codemap().lookup_char_pos(scope_span.lo);
2369 let file_metadata = file_metadata(cx, loc.file.name);
2370 let parent_scope = scope_stack.last().unwrap().scope_metadata;
2372 let scope_metadata = unsafe {
2373 llvm::LLVMDIBuilderCreateLexicalBlock(
2378 loc.col.to_uint() as c_uint)
2381 scope_stack.push(ScopeStackEntry { scope_metadata: scope_metadata, ident: None });
2383 inner_walk(cx, scope_stack, scope_map);
2385 // pop artificial scopes
2386 while scope_stack.last().unwrap().ident.is_some() {
2390 if scope_stack.last().unwrap().scope_metadata != scope_metadata {
2391 cx.sess().span_bug(scope_span, "debuginfo: Inconsistency in scope management.");
2397 fn walk_block(cx: &CrateContext,
2399 scope_stack: &mut Vec<ScopeStackEntry> ,
2400 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2401 scope_map.insert(block.id, scope_stack.last().unwrap().scope_metadata);
2403 // The interesting things here are statements and the concluding expression.
2404 for statement in block.stmts.iter() {
2405 scope_map.insert(ast_util::stmt_id(*statement),
2406 scope_stack.last().unwrap().scope_metadata);
2408 match statement.node {
2409 ast::StmtDecl(decl, _) => walk_decl(cx, decl, scope_stack, scope_map),
2410 ast::StmtExpr(exp, _) |
2411 ast::StmtSemi(exp, _) => walk_expr(cx, exp, scope_stack, scope_map),
2412 ast::StmtMac(..) => () // ignore macros (which should be expanded anyway)
2416 for exp in block.expr.iter() {
2417 walk_expr(cx, *exp, scope_stack, scope_map);
2421 fn walk_decl(cx: &CrateContext,
2423 scope_stack: &mut Vec<ScopeStackEntry> ,
2424 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2426 codemap::Spanned { node: ast::DeclLocal(local), .. } => {
2427 scope_map.insert(local.id, scope_stack.last().unwrap().scope_metadata);
2429 walk_pattern(cx, local.pat, scope_stack, scope_map);
2431 for exp in local.init.iter() {
2432 walk_expr(cx, *exp, scope_stack, scope_map);
2439 fn walk_pattern(cx: &CrateContext,
2441 scope_stack: &mut Vec<ScopeStackEntry> ,
2442 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2444 let def_map = cx.tcx.def_map;
2446 // Unfortunately, we cannot just use pat_util::pat_bindings() or ast_util::walk_pat() here
2447 // because we have to visit *all* nodes in order to put them into the scope map. The above
2448 // functions don't do that.
2450 ast::PatIdent(_, ref path_ref, ref sub_pat_opt) => {
2452 // Check if this is a binding. If so we need to put it on the scope stack and maybe
2453 // introduce an articial scope
2454 if pat_util::pat_is_binding(def_map, pat) {
2456 let ident = ast_util::path_to_ident(path_ref);
2458 // LLVM does not properly generate 'DW_AT_start_scope' fields for variable DIEs.
2459 // For this reason we have to introduce an artificial scope at bindings whenever
2460 // a variable with the same name is declared in *any* parent scope.
2462 // Otherwise the following error occurs:
2466 // do_something(); // 'gdb print x' correctly prints 10
2469 // do_something(); // 'gdb print x' prints 0, because it already reads the
2470 // // uninitialized 'x' from the next line...
2472 // do_something(); // 'gdb print x' correctly prints 100
2475 // Is there already a binding with that name?
2476 // N.B.: this comparison must be UNhygienic... because
2477 // gdb knows nothing about the context, so any two
2478 // variables with the same name will cause the problem.
2479 let need_new_scope = scope_stack
2481 .any(|entry| entry.ident.iter().any(|i| i.name == ident.name));
2484 // Create a new lexical scope and push it onto the stack
2485 let loc = cx.sess().codemap().lookup_char_pos(pat.span.lo);
2486 let file_metadata = file_metadata(cx, loc.file.name);
2487 let parent_scope = scope_stack.last().unwrap().scope_metadata;
2489 let scope_metadata = unsafe {
2490 llvm::LLVMDIBuilderCreateLexicalBlock(
2495 loc.col.to_uint() as c_uint)
2498 scope_stack.push(ScopeStackEntry {
2499 scope_metadata: scope_metadata,
2504 // Push a new entry anyway so the name can be found
2505 let prev_metadata = scope_stack.last().unwrap().scope_metadata;
2506 scope_stack.push(ScopeStackEntry {
2507 scope_metadata: prev_metadata,
2513 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2515 for &sub_pat in sub_pat_opt.iter() {
2516 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2520 ast::PatWild | ast::PatWildMulti => {
2521 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2524 ast::PatEnum(_, ref sub_pats_opt) => {
2525 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2527 for ref sub_pats in sub_pats_opt.iter() {
2528 for &p in sub_pats.iter() {
2529 walk_pattern(cx, p, scope_stack, scope_map);
2534 ast::PatStruct(_, ref field_pats, _) => {
2535 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2537 for &ast::FieldPat { pat: sub_pat, .. } in field_pats.iter() {
2538 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2542 ast::PatTup(ref sub_pats) => {
2543 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2545 for &sub_pat in sub_pats.iter() {
2546 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2550 ast::PatUniq(sub_pat) | ast::PatRegion(sub_pat) => {
2551 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2552 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2555 ast::PatLit(exp) => {
2556 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2557 walk_expr(cx, exp, scope_stack, scope_map);
2560 ast::PatRange(exp1, exp2) => {
2561 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2562 walk_expr(cx, exp1, scope_stack, scope_map);
2563 walk_expr(cx, exp2, scope_stack, scope_map);
2566 ast::PatVec(ref front_sub_pats, ref middle_sub_pats, ref back_sub_pats) => {
2567 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2569 for &sub_pat in front_sub_pats.iter() {
2570 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2573 for &sub_pat in middle_sub_pats.iter() {
2574 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2577 for &sub_pat in back_sub_pats.iter() {
2578 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2584 fn walk_expr(cx: &CrateContext,
2586 scope_stack: &mut Vec<ScopeStackEntry> ,
2587 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2589 scope_map.insert(exp.id, scope_stack.last().unwrap().scope_metadata);
2595 ast::ExprPath(_) => {}
2597 ast::ExprVstore(sub_exp, _) |
2598 ast::ExprCast(sub_exp, _) |
2599 ast::ExprAddrOf(_, sub_exp) |
2600 ast::ExprField(sub_exp, _, _) |
2601 ast::ExprParen(sub_exp) => walk_expr(cx, sub_exp, scope_stack, scope_map),
2603 ast::ExprBox(place, sub_expr) => {
2604 walk_expr(cx, place, scope_stack, scope_map);
2605 walk_expr(cx, sub_expr, scope_stack, scope_map);
2608 ast::ExprRet(exp_opt) => match exp_opt {
2609 Some(sub_exp) => walk_expr(cx, sub_exp, scope_stack, scope_map),
2613 ast::ExprUnary(_, sub_exp) => {
2614 walk_expr(cx, sub_exp, scope_stack, scope_map);
2617 ast::ExprAssignOp(_, lhs, rhs) |
2618 ast::ExprIndex(lhs, rhs) |
2619 ast::ExprBinary(_, lhs, rhs) => {
2620 walk_expr(cx, lhs, scope_stack, scope_map);
2621 walk_expr(cx, rhs, scope_stack, scope_map);
2624 ast::ExprVec(ref init_expressions) |
2625 ast::ExprTup(ref init_expressions) => {
2626 for ie in init_expressions.iter() {
2627 walk_expr(cx, *ie, scope_stack, scope_map);
2631 ast::ExprAssign(sub_exp1, sub_exp2) |
2632 ast::ExprRepeat(sub_exp1, sub_exp2) => {
2633 walk_expr(cx, sub_exp1, scope_stack, scope_map);
2634 walk_expr(cx, sub_exp2, scope_stack, scope_map);
2637 ast::ExprIf(cond_exp, then_block, ref opt_else_exp) => {
2638 walk_expr(cx, cond_exp, scope_stack, scope_map);
2644 |cx, scope_stack, scope_map| {
2645 walk_block(cx, then_block, scope_stack, scope_map);
2648 match *opt_else_exp {
2649 Some(else_exp) => walk_expr(cx, else_exp, scope_stack, scope_map),
2654 ast::ExprWhile(cond_exp, loop_body) => {
2655 walk_expr(cx, cond_exp, scope_stack, scope_map);
2661 |cx, scope_stack, scope_map| {
2662 walk_block(cx, loop_body, scope_stack, scope_map);
2666 ast::ExprForLoop(_, _, _, _) => {
2667 cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \
2668 Found unexpanded for-loop.");
2671 ast::ExprMac(_) => {
2672 cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \
2673 Found unexpanded macro.");
2676 ast::ExprLoop(block, _) |
2677 ast::ExprBlock(block) => {
2682 |cx, scope_stack, scope_map| {
2683 walk_block(cx, block, scope_stack, scope_map);
2687 ast::ExprFnBlock(decl, block) |
2688 ast::ExprProc(decl, block) => {
2693 |cx, scope_stack, scope_map| {
2694 for &ast::Arg { pat: pattern, .. } in decl.inputs.iter() {
2695 walk_pattern(cx, pattern, scope_stack, scope_map);
2698 walk_block(cx, block, scope_stack, scope_map);
2702 ast::ExprCall(fn_exp, ref args) => {
2703 walk_expr(cx, fn_exp, scope_stack, scope_map);
2705 for arg_exp in args.iter() {
2706 walk_expr(cx, *arg_exp, scope_stack, scope_map);
2710 ast::ExprMethodCall(_, _, ref args) => {
2711 for arg_exp in args.iter() {
2712 walk_expr(cx, *arg_exp, scope_stack, scope_map);
2716 ast::ExprMatch(discriminant_exp, ref arms) => {
2717 walk_expr(cx, discriminant_exp, scope_stack, scope_map);
2719 // for each arm we have to first walk the pattern as these might introduce new
2720 // artificial scopes. It should be sufficient to walk only one pattern per arm, as
2721 // they all must contain the same binding names
2723 for arm_ref in arms.iter() {
2724 let arm_span = arm_ref.pats.get(0).span;
2730 |cx, scope_stack, scope_map| {
2731 for &pat in arm_ref.pats.iter() {
2732 walk_pattern(cx, pat, scope_stack, scope_map);
2735 for guard_exp in arm_ref.guard.iter() {
2736 walk_expr(cx, *guard_exp, scope_stack, scope_map)
2739 walk_expr(cx, arm_ref.body, scope_stack, scope_map);
2744 ast::ExprStruct(_, ref fields, ref base_exp) => {
2745 for &ast::Field { expr: exp, .. } in fields.iter() {
2746 walk_expr(cx, exp, scope_stack, scope_map);
2750 Some(exp) => walk_expr(cx, exp, scope_stack, scope_map),
2755 ast::ExprInlineAsm(ast::InlineAsm { inputs: ref inputs,
2756 outputs: ref outputs,
2758 // inputs, outputs: ~[(~str, @expr)]
2759 for &(_, exp) in inputs.iter() {
2760 walk_expr(cx, exp, scope_stack, scope_map);
2763 for &(_, exp) in outputs.iter() {
2764 walk_expr(cx, exp, scope_stack, scope_map);
2772 //=-------------------------------------------------------------------------------------------------
2773 // Namespace Handling
2774 //=-------------------------------------------------------------------------------------------------
2776 struct NamespaceTreeNode {
2779 parent: Option<@NamespaceTreeNode>,
2782 impl NamespaceTreeNode {
2783 fn mangled_name_of_contained_item(&self, item_name: &str) -> ~str {
2784 fn fill_nested(node: &NamespaceTreeNode, output: &mut StrBuf) {
2786 Some(parent) => fill_nested(parent, output),
2789 let string = token::get_name(node.name);
2790 output.push_str(format!("{}", string.get().len()));
2791 output.push_str(string.get());
2794 let mut name = StrBuf::from_str("_ZN");
2795 fill_nested(self, &mut name);
2796 name.push_str(format!("{}", item_name.len()));
2797 name.push_str(item_name);
2798 name.push_char('E');
2803 fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> @NamespaceTreeNode {
2804 ty::with_path(cx.tcx(), def_id, |path| {
2805 // prepend crate name if not already present
2806 let krate = if def_id.krate == ast::LOCAL_CRATE {
2807 let crate_namespace_ident = token::str_to_ident(cx.link_meta.crateid.name);
2808 Some(ast_map::PathMod(crate_namespace_ident.name))
2812 let mut path = krate.move_iter().chain(path).peekable();
2814 let mut current_key = Vec::new();
2815 let mut parent_node: Option<@NamespaceTreeNode> = None;
2817 // Create/Lookup namespace for each element of the path.
2819 // Emulate a for loop so we can use peek below.
2820 let path_element = match path.next() {
2824 // Ignore the name of the item (the last path element).
2825 if path.peek().is_none() {
2829 let name = path_element.name();
2830 current_key.push(name);
2832 let existing_node = debug_context(cx).namespace_map.borrow()
2833 .find_copy(¤t_key);
2834 let current_node = match existing_node {
2835 Some(existing_node) => existing_node,
2837 // create and insert
2838 let parent_scope = match parent_node {
2839 Some(node) => node.scope,
2842 let namespace_name = token::get_name(name);
2843 let scope = namespace_name.get().with_c_str(|namespace_name| {
2845 llvm::LLVMDIBuilderCreateNameSpace(
2849 // cannot reconstruct file ...
2851 // ... or line information, but that's not so important.
2856 let node = @NamespaceTreeNode {
2859 parent: parent_node,
2862 debug_context(cx).namespace_map.borrow_mut()
2863 .insert(current_key.clone(), node);
2869 parent_node = Some(current_node);
2875 cx.sess().bug(format!("debuginfo::namespace_for_item(): \
2876 path too short for {:?}", def_id));