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.
130 use lib::llvm::{ModuleRef, ContextRef, ValueRef};
131 use lib::llvm::debuginfo::*;
132 use middle::trans::adt;
133 use middle::trans::common::*;
134 use middle::trans::datum::{Datum, Lvalue};
135 use middle::trans::machine;
136 use middle::trans::type_of;
137 use middle::trans::type_::Type;
140 use middle::pat_util;
143 use std::c_str::{CString, ToCStr};
144 use std::cell::{Cell, RefCell};
145 use std::hashmap::HashMap;
146 use std::hashmap::HashSet;
147 use std::libc::{c_uint, c_ulonglong, c_longlong};
149 use std::sync::atomics;
151 use syntax::codemap::{Span, Pos};
152 use syntax::{abi, ast, codemap, ast_util, ast_map, opt_vec};
153 use syntax::parse::token;
154 use syntax::parse::token::special_idents;
156 static DW_LANG_RUST: c_uint = 0x9000;
158 static DW_TAG_auto_variable: c_uint = 0x100;
159 static DW_TAG_arg_variable: c_uint = 0x101;
161 static DW_ATE_boolean: c_uint = 0x02;
162 static DW_ATE_float: c_uint = 0x04;
163 static DW_ATE_signed: c_uint = 0x05;
164 // static DW_ATE_signed_char: c_uint = 0x06;
165 static DW_ATE_unsigned: c_uint = 0x07;
166 static DW_ATE_unsigned_char: c_uint = 0x08;
168 //=-------------------------------------------------------------------------------------------------
169 // Public Interface of debuginfo module
170 //=-------------------------------------------------------------------------------------------------
172 /// A context object for maintaining all state needed by the debuginfo module.
173 pub struct CrateDebugContext {
174 priv llcontext: ContextRef,
175 priv builder: DIBuilderRef,
176 priv current_debug_location: Cell<DebugLocation>,
177 priv created_files: RefCell<HashMap<~str, DIFile>>,
178 priv created_types: RefCell<HashMap<uint, DIType>>,
179 priv namespace_map: RefCell<HashMap<~[ast::Ident], @NamespaceTreeNode>>,
180 // This collection is used to assert that composite types (structs, enums, ...) have their
181 // members only set once:
182 priv composite_types_completed: RefCell<HashSet<DIType>>,
185 impl CrateDebugContext {
186 pub fn new(llmod: ModuleRef) -> CrateDebugContext {
187 debug!("CrateDebugContext::new");
188 let builder = unsafe { llvm::LLVMDIBuilderCreate(llmod) };
189 // DIBuilder inherits context from the module, so we'd better use the same one
190 let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
191 return CrateDebugContext {
192 llcontext: llcontext,
194 current_debug_location: Cell::new(UnknownLocation),
195 created_files: RefCell::new(HashMap::new()),
196 created_types: RefCell::new(HashMap::new()),
197 namespace_map: RefCell::new(HashMap::new()),
198 composite_types_completed: RefCell::new(HashSet::new()),
203 pub enum FunctionDebugContext {
204 priv FunctionDebugContext(~FunctionDebugContextData),
205 priv DebugInfoDisabled,
206 priv FunctionWithoutDebugInfo,
209 impl FunctionDebugContext {
210 fn get_ref<'a>(&'a self, cx: &CrateContext, span: Span) -> &'a FunctionDebugContextData {
212 FunctionDebugContext(~ref data) => data,
213 DebugInfoDisabled => {
214 cx.sess.span_bug(span, FunctionDebugContext::debuginfo_disabled_message());
216 FunctionWithoutDebugInfo => {
217 cx.sess.span_bug(span, FunctionDebugContext::should_be_ignored_message());
222 fn debuginfo_disabled_message() -> &'static str {
223 "debuginfo: Error trying to access FunctionDebugContext although debug info is disabled!"
226 fn should_be_ignored_message() -> &'static str {
227 "debuginfo: Error trying to access FunctionDebugContext for function that should be \
228 ignored by debug info!"
232 struct FunctionDebugContextData {
233 scope_map: RefCell<HashMap<ast::NodeId, DIScope>>,
234 fn_metadata: DISubprogram,
235 argument_counter: Cell<uint>,
236 source_locations_enabled: Cell<bool>,
239 enum VariableAccess<'a> {
240 // The llptr given is an alloca containing the variable's value
241 DirectVariable { alloca: ValueRef },
242 // The llptr given is an alloca containing the start of some pointer chain leading to the
243 // variable's content.
244 IndirectVariable { alloca: ValueRef, address_operations: &'a [ValueRef] }
248 ArgumentVariable(uint /*index*/),
253 /// Create any deferred debug metadata nodes
254 pub fn finalize(cx: @CrateContext) {
255 if cx.dbg_cx.is_none() {
260 compile_unit_metadata(cx);
262 llvm::LLVMDIBuilderFinalize(DIB(cx));
263 llvm::LLVMDIBuilderDispose(DIB(cx));
264 // Debuginfo generation in LLVM by default uses a higher
265 // version of dwarf than OS X currently understands. We can
266 // instruct LLVM to emit an older version of dwarf, however,
267 // for OS X to understand. For more info see #11352
268 // This can be overridden using --llvm-opts -dwarf-version,N.
269 if cx.sess.targ_cfg.os == abi::OsMacos {
270 "Dwarf Version".with_c_str(
271 |s| llvm::LLVMRustAddModuleFlag(cx.llmod, s, 2));
274 // Prevent bitcode readers from deleting the debug info.
275 "Debug Info Version".with_c_str(
276 |s| llvm::LLVMRustAddModuleFlag(cx.llmod, s,
277 llvm::LLVMRustDebugMetadataVersion));
281 /// Creates debug information for the given local variable.
283 /// Adds the created metadata nodes directly to the crate's IR.
284 pub fn create_local_var_metadata(bcx: &Block, local: &ast::Local) {
285 if fn_should_be_ignored(bcx.fcx) {
290 let def_map = cx.tcx.def_map;
292 pat_util::pat_bindings(def_map, local.pat, |_, node_id, span, path_ref| {
293 let var_ident = ast_util::path_to_ident(path_ref);
296 let lllocals = bcx.fcx.lllocals.borrow();
297 match lllocals.get().find_copy(&node_id) {
298 Some(datum) => datum,
300 bcx.tcx().sess.span_bug(span,
301 format!("No entry in lllocals table for {:?}",
307 let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
313 DirectVariable { alloca: datum.val },
319 /// Creates debug information for a variable captured in a closure.
321 /// Adds the created metadata nodes directly to the crate's IR.
322 pub fn create_captured_var_metadata(bcx: &Block,
323 node_id: ast::NodeId,
324 env_data_type: ty::t,
325 env_pointer: ValueRef,
327 closure_sigil: ast::Sigil,
329 if fn_should_be_ignored(bcx.fcx) {
335 let ast_item = cx.tcx.items.find(node_id);
337 let variable_ident = match ast_item {
339 cx.sess.span_bug(span, "debuginfo::create_captured_var_metadata() - NodeId not found");
341 Some(ast_map::NodeLocal(pat)) | Some(ast_map::NodeArg(pat)) => {
343 ast::PatIdent(_, ref path, _) => {
344 ast_util::path_to_ident(path)
350 "debuginfo::create_captured_var_metadata() - \
351 Captured var-id refers to unexpected \
352 ast_map variant: {:?}",
358 cx.sess.span_bug(span, format!("debuginfo::create_captured_var_metadata() - \
359 Captured var-id refers to unexpected ast_map variant: {:?}", ast_item));
363 let variable_type = node_id_type(bcx, node_id);
364 let scope_metadata = bcx.fcx.debug_context.get_ref(cx, span).fn_metadata;
366 let llvm_env_data_type = type_of::type_of(cx, env_data_type);
367 let byte_offset_of_var_in_env = machine::llelement_offset(cx, llvm_env_data_type, env_index);
369 let address_operations = unsafe {
370 [llvm::LLVMDIBuilderCreateOpDeref(Type::i64().to_ref()),
371 llvm::LLVMDIBuilderCreateOpPlus(Type::i64().to_ref()),
372 C_i64(byte_offset_of_var_in_env as i64),
373 llvm::LLVMDIBuilderCreateOpDeref(Type::i64().to_ref())]
376 let address_op_count = match closure_sigil {
377 ast::BorrowedSigil => {
378 address_operations.len()
380 ast::ManagedSigil | ast::OwnedSigil => {
381 address_operations.len() - 1
385 let variable_access = IndirectVariable {
387 address_operations: address_operations.slice_to(address_op_count)
399 /// Creates debug information for a local variable introduced in the head of a match-statement arm.
401 /// Adds the created metadata nodes directly to the crate's IR.
402 pub fn create_match_binding_metadata(bcx: &Block,
403 variable_ident: ast::Ident,
404 node_id: ast::NodeId,
406 datum: Datum<Lvalue>) {
407 if fn_should_be_ignored(bcx.fcx) {
411 let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
417 DirectVariable { alloca: datum.val },
422 /// Creates debug information for the given function argument.
424 /// Adds the created metadata nodes directly to the crate's IR.
425 pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
426 if fn_should_be_ignored(bcx.fcx) {
433 let def_map = cx.tcx.def_map;
434 let scope_metadata = bcx.fcx.debug_context.get_ref(cx, arg.pat.span).fn_metadata;
436 pat_util::pat_bindings(def_map, arg.pat, |_, node_id, span, path_ref| {
438 let llargs = bcx.fcx.llargs.borrow();
439 match llargs.get().find_copy(&node_id) {
442 bcx.tcx().sess.span_bug(span,
443 format!("No entry in llargs table for {:?}",
449 if unsafe { llvm::LLVMIsAAllocaInst(llarg.val) } == ptr::null() {
450 cx.sess.span_bug(span, "debuginfo::create_argument_metadata() - \
451 Referenced variable location is not an alloca!");
454 let argument_ident = ast_util::path_to_ident(path_ref);
456 let argument_index = {
457 let counter = &fcx.debug_context.get_ref(cx, span).argument_counter;
458 let argument_index = counter.get();
459 counter.set(argument_index + 1);
467 DirectVariable { alloca: llarg.val },
468 ArgumentVariable(argument_index),
473 /// Sets the current debug location at the beginning of the span.
475 /// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...). The node_id parameter is used to
476 /// reliably find the correct visibility scope for the code position.
477 pub fn set_source_location(fcx: &FunctionContext,
478 node_id: ast::NodeId,
480 if fn_should_be_ignored(fcx) {
486 debug!("set_source_location: {}", cx.sess.codemap.span_to_str(span));
488 if fcx.debug_context.get_ref(cx, span).source_locations_enabled.get() {
489 let loc = span_start(cx, span);
490 let scope = scope_metadata(fcx, node_id, span);
492 set_debug_location(cx, DebugLocation::new(scope, loc.line, loc.col.to_uint()));
494 set_debug_location(cx, UnknownLocation);
498 /// Clears the current debug location.
500 /// Instructions generated hereafter won't be assigned a source location.
501 pub fn clear_source_location(fcx: &FunctionContext) {
502 if fn_should_be_ignored(fcx) {
506 set_debug_location(fcx.ccx, UnknownLocation);
509 /// Enables emitting source locations for the given functions.
511 /// Since we don't want source locations to be emitted for the function prelude, they are disabled
512 /// when beginning to translate a new function. This functions switches source location emitting on
513 /// and must therefore be called before the first real statement/expression of the function is
515 pub fn start_emitting_source_locations(fcx: &FunctionContext) {
516 match fcx.debug_context {
517 FunctionDebugContext(~ref data) => {
518 data.source_locations_enabled.set(true)
520 _ => { /* safe to ignore */ }
524 /// Creates the function-specific debug context.
526 /// Returns the FunctionDebugContext for the function which holds state needed for debug info
527 /// creation. The function may also return another variant of the FunctionDebugContext enum which
528 /// indicates why no debuginfo should be created for the function.
529 pub fn create_function_debug_context(cx: &CrateContext,
530 fn_ast_id: ast::NodeId,
531 param_substs: Option<@param_substs>,
532 llfn: ValueRef) -> FunctionDebugContext {
533 if !cx.sess.opts.debuginfo {
534 return DebugInfoDisabled;
538 return FunctionWithoutDebugInfo;
541 let empty_generics = ast::Generics { lifetimes: opt_vec::Empty, ty_params: opt_vec::Empty };
543 let fnitem = cx.tcx.items.get(fn_ast_id);
545 let (ident, fn_decl, generics, top_level_block, span, has_path) = match fnitem {
546 ast_map::NodeItem(ref item, _) => {
548 ast::ItemFn(fn_decl, _, _, ref generics, top_level_block) => {
549 (item.ident, fn_decl, generics, top_level_block, item.span, true)
552 cx.sess.span_bug(item.span,
553 "create_function_debug_context: item bound to non-function");
557 ast_map::NodeMethod(method, _, _) => {
565 ast_map::NodeExpr(ref expr) => {
567 ast::ExprFnBlock(fn_decl, top_level_block) |
568 ast::ExprProc(fn_decl, top_level_block) => {
569 let name = format!("fn{}", token::gensym("fn"));
570 let name = token::str_to_ident(name);
572 // This is not quite right. It should actually inherit the generics of the
573 // enclosing function.
577 // Don't try to lookup the item path:
580 _ => cx.sess.span_bug(expr.span,
581 "create_function_debug_context: expected an expr_fn_block here")
584 ast_map::NodeTraitMethod(trait_method, _, _) => {
585 match *trait_method {
586 ast::Provided(method) => {
596 .bug(format!("create_function_debug_context: \
597 unexpected sort of node: {:?}",
602 ast_map::NodeForeignItem(..) |
603 ast_map::NodeVariant(..) |
604 ast_map::NodeStructCtor(..) => {
605 return FunctionWithoutDebugInfo;
607 _ => cx.sess.bug(format!("create_function_debug_context: \
608 unexpected sort of node: {:?}", fnitem))
611 // This can be the case for functions inlined from another crate
612 if span == codemap::DUMMY_SP {
613 return FunctionWithoutDebugInfo;
616 let loc = span_start(cx, span);
617 let file_metadata = file_metadata(cx, loc.file.name);
619 let function_type_metadata = unsafe {
620 let fn_signature = get_function_signature(cx, fn_ast_id, fn_decl, param_substs, span);
621 llvm::LLVMDIBuilderCreateSubroutineType(DIB(cx), file_metadata, fn_signature)
624 // get_template_parameters() will append a `<...>` clause to the function name if necessary.
625 let mut function_name = token::ident_to_str(&ident).to_owned();
626 let template_parameters = get_template_parameters(cx,
632 // There is no ast_map::Path for ast::ExprFnBlock-type functions. For now, just don't put them
633 // into a namespace. In the future this could be improved somehow (storing a path in the
634 // ast_map, or construct a path using the enclosing function).
635 let (linkage_name, containing_scope) = if has_path {
636 let namespace_node = namespace_for_item(cx, ast_util::local_def(fn_ast_id), span);
637 let linkage_name = namespace_node.mangled_name_of_contained_item(function_name);
638 let containing_scope = namespace_node.scope;
639 (linkage_name, containing_scope)
641 (function_name.clone(), file_metadata)
644 // Clang sets this parameter to the opening brace of the function's block, so let's do this too.
645 let scope_line = span_start(cx, top_level_block.span).line;
647 // The is_local_to_unit flag indicates whether a function is local to the current compilation
648 // unit (i.e. if it is *static* in the C-sense). The *reachable* set should provide a good
649 // approximation of this, as it contains everything that might leak out of the current crate
650 // (by being externally visible or by being inlined into something externally visible). It might
651 // better to use the `exported_items` set from `driver::CrateAnalysis` in the future, but (atm)
652 // this set is not available in the translation pass.
653 let is_local_to_unit = {
654 let reachable = cx.reachable.borrow();
655 !reachable.get().contains(&fn_ast_id)
658 let fn_metadata = function_name.with_c_str(|function_name| {
659 linkage_name.with_c_str(|linkage_name| {
661 llvm::LLVMDIBuilderCreateFunction(
668 function_type_metadata,
671 scope_line as c_uint,
672 FlagPrototyped as c_uint,
673 cx.sess.opts.optimize != session::No,
681 // Initialize fn debug context (including scope map and namespace map)
682 let fn_debug_context = ~FunctionDebugContextData {
683 scope_map: RefCell::new(HashMap::new()),
684 fn_metadata: fn_metadata,
685 argument_counter: Cell::new(1),
686 source_locations_enabled: Cell::new(false),
689 let arg_pats = fn_decl.inputs.map(|arg_ref| arg_ref.pat);
691 let mut scope_map = fn_debug_context.scope_map.borrow_mut();
692 populate_scope_map(cx,
699 // Clear the debug location so we don't assign them in the function prelude
700 set_debug_location(cx, UnknownLocation);
702 return FunctionDebugContext(fn_debug_context);
704 fn get_function_signature(cx: &CrateContext,
705 fn_ast_id: ast::NodeId,
706 fn_decl: &ast::FnDecl,
707 param_substs: Option<@param_substs>,
708 error_span: Span) -> DIArray {
709 if !cx.sess.opts.extra_debuginfo {
710 return create_DIArray(DIB(cx), []);
713 let mut signature = vec::with_capacity(fn_decl.inputs.len() + 1);
715 // Return type -- llvm::DIBuilder wants this at index 0
716 match fn_decl.output.node {
718 signature.push(ptr::null());
721 assert_type_for_node_id(cx, fn_ast_id, error_span);
723 let return_type = ty::node_id_to_type(cx.tcx, fn_ast_id);
724 let return_type = match param_substs {
727 ty::subst_tps(cx.tcx, substs.tys, substs.self_ty, return_type)
731 signature.push(type_metadata(cx, return_type, codemap::DUMMY_SP));
736 for arg in fn_decl.inputs.iter() {
737 assert_type_for_node_id(cx, arg.pat.id, arg.pat.span);
738 let arg_type = ty::node_id_to_type(cx.tcx, arg.pat.id);
739 let arg_type = match param_substs {
742 ty::subst_tps(cx.tcx, substs.tys, substs.self_ty, arg_type)
746 signature.push(type_metadata(cx, arg_type, codemap::DUMMY_SP));
749 return create_DIArray(DIB(cx), signature);
752 fn get_template_parameters(cx: &CrateContext,
753 generics: &ast::Generics,
754 param_substs: Option<@param_substs>,
755 file_metadata: DIFile,
756 name_to_append_suffix_to: &mut ~str)
758 let self_type = match param_substs {
759 Some(param_substs) => param_substs.self_ty,
763 // Only true for static default methods:
764 let has_self_type = self_type.is_some();
766 if !generics.is_type_parameterized() && !has_self_type {
767 return create_DIArray(DIB(cx), []);
770 name_to_append_suffix_to.push_char('<');
772 // The list to be filled with template parameters:
773 let mut template_params: ~[DIDescriptor] = vec::with_capacity(generics.ty_params.len() + 1);
777 let actual_self_type = self_type.unwrap();
778 // Add self type name to <...> clause of function name
779 let actual_self_type_name = ppaux::ty_to_str(cx.tcx, actual_self_type);
780 name_to_append_suffix_to.push_str(actual_self_type_name);
782 if generics.is_type_parameterized() {
783 name_to_append_suffix_to.push_str(",");
786 // Only create type information if extra_debuginfo is enabled
787 if cx.sess.opts.extra_debuginfo {
788 let actual_self_type_metadata = type_metadata(cx,
792 let ident = special_idents::type_self;
794 let param_metadata = token::ident_to_str(&ident).with_c_str(|name| {
796 llvm::LLVMDIBuilderCreateTemplateTypeParameter(
800 actual_self_type_metadata,
807 template_params.push(param_metadata);
811 // Handle other generic parameters
812 let actual_types = match param_substs {
813 Some(param_substs) => ¶m_substs.tys,
815 return create_DIArray(DIB(cx), template_params);
819 for (index, &ast::TyParam{ ident: ident, .. }) in generics.ty_params.iter().enumerate() {
820 let actual_type = actual_types[index];
821 // Add actual type name to <...> clause of function name
822 let actual_type_name = ppaux::ty_to_str(cx.tcx, actual_type);
823 name_to_append_suffix_to.push_str(actual_type_name);
825 if index != generics.ty_params.len() - 1 {
826 name_to_append_suffix_to.push_str(",");
829 // Again, only create type information if extra_debuginfo is enabled
830 if cx.sess.opts.extra_debuginfo {
831 let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP);
832 let param_metadata = token::ident_to_str(&ident).with_c_str(|name| {
834 llvm::LLVMDIBuilderCreateTemplateTypeParameter(
838 actual_type_metadata,
844 template_params.push(param_metadata);
848 name_to_append_suffix_to.push_char('>');
850 return create_DIArray(DIB(cx), template_params);
854 //=-------------------------------------------------------------------------------------------------
855 // Module-Internal debug info creation functions
856 //=-------------------------------------------------------------------------------------------------
858 fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
860 llvm::LLVMDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32)
864 fn compile_unit_metadata(cx: &CrateContext) {
865 let work_dir = &cx.sess.working_dir;
866 let compile_unit_name = match cx.sess.local_crate_source_file {
867 None => fallback_path(cx),
868 Some(ref abs_path) => {
869 if abs_path.is_relative() {
870 cx.sess.warn("debuginfo: Invalid path to crate's local root source file!");
873 match abs_path.path_relative_from(work_dir) {
874 Some(ref p) if p.is_relative() => {
875 // prepend "./" if necessary
876 let dotdot = bytes!("..");
877 let prefix = &[dotdot[0], ::std::path::SEP_BYTE];
878 let mut path_bytes = p.as_vec().to_owned();
880 if path_bytes.slice_to(2) != prefix &&
881 path_bytes.slice_to(2) != dotdot {
882 path_bytes.insert(0, prefix[0]);
883 path_bytes.insert(1, prefix[1]);
886 path_bytes.to_c_str()
888 _ => fallback_path(cx)
894 debug!("compile_unit_metadata: {:?}", compile_unit_name);
895 let producer = format!("rustc version {}", env!("CFG_VERSION"));
897 compile_unit_name.with_ref(|compile_unit_name| {
898 work_dir.as_vec().with_c_str(|work_dir| {
899 producer.with_c_str(|producer| {
900 "".with_c_str(|flags| {
901 "".with_c_str(|split_name| {
903 llvm::LLVMDIBuilderCreateCompileUnit(
904 debug_context(cx).builder,
909 cx.sess.opts.optimize != session::No,
920 fn fallback_path(cx: &CrateContext) -> CString {
921 cx.link_meta.crateid.name.to_c_str()
925 fn declare_local(bcx: &Block,
926 variable_ident: ast::Ident,
927 variable_type: ty::t,
928 scope_metadata: DIScope,
929 variable_access: VariableAccess,
930 variable_kind: VariableKind,
932 let cx: &CrateContext = bcx.ccx();
934 let filename = span_start(cx, span).file.name.clone();
935 let file_metadata = file_metadata(cx, filename);
937 let name: &str = token::ident_to_str(&variable_ident);
938 let loc = span_start(cx, span);
939 let type_metadata = type_metadata(cx, variable_type, span);
941 let (argument_index, dwarf_tag) = match variable_kind {
942 ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),
944 CapturedVariable => (0, DW_TAG_auto_variable)
947 let (var_alloca, var_metadata) = name.with_c_str(|name| {
948 match variable_access {
949 DirectVariable { alloca } => (
952 llvm::LLVMDIBuilderCreateLocalVariable(
960 cx.sess.opts.optimize != session::No,
965 IndirectVariable { alloca, address_operations } => (
968 llvm::LLVMDIBuilderCreateComplexVariable(
976 address_operations.as_ptr(),
977 address_operations.len() as c_uint,
984 set_debug_location(cx, DebugLocation::new(scope_metadata, loc.line, loc.col.to_uint()));
986 let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
992 llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr);
995 match variable_kind {
996 ArgumentVariable(_) | CapturedVariable => {
1000 .source_locations_enabled
1002 set_debug_location(cx, UnknownLocation);
1004 _ => { /* nothing to do */ }
1008 fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
1010 let created_files = debug_context(cx).created_files.borrow();
1011 match created_files.get().find_equiv(&full_path) {
1012 Some(file_metadata) => return *file_metadata,
1017 debug!("file_metadata: {}", full_path);
1019 // FIXME (#9639): This needs to handle non-utf8 paths
1020 let work_dir = cx.sess.working_dir.as_str().unwrap();
1022 if full_path.starts_with(work_dir) {
1023 full_path.slice(work_dir.len() + 1u, full_path.len())
1029 file_name.with_c_str(|file_name| {
1030 work_dir.with_c_str(|work_dir| {
1032 llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir)
1037 let mut created_files = debug_context(cx).created_files.borrow_mut();
1038 created_files.get().insert(full_path.to_owned(), file_metadata);
1039 return file_metadata;
1042 /// Finds the scope metadata node for the given AST node.
1043 fn scope_metadata(fcx: &FunctionContext,
1044 node_id: ast::NodeId,
1047 let scope_map = &fcx.debug_context.get_ref(fcx.ccx, span).scope_map;
1048 let scope_map = scope_map.borrow();
1050 match scope_map.get().find_copy(&node_id) {
1051 Some(scope_metadata) => scope_metadata,
1053 let node = fcx.ccx.tcx.items.get(node_id);
1055 fcx.ccx.sess.span_bug(span,
1056 format!("debuginfo: Could not find scope info for node {:?}", node));
1061 fn basic_type_metadata(cx: &CrateContext, t: ty::t) -> DIType {
1063 debug!("basic_type_metadata: {:?}", ty::get(t));
1065 let (name, encoding) = match ty::get(t).sty {
1066 ty::ty_nil => (~"()", DW_ATE_unsigned),
1067 ty::ty_bot => (~"!", DW_ATE_unsigned),
1068 ty::ty_bool => (~"bool", DW_ATE_boolean),
1069 ty::ty_char => (~"char", DW_ATE_unsigned_char),
1070 ty::ty_int(int_ty) => match int_ty {
1071 ast::TyI => (~"int", DW_ATE_signed),
1072 ast::TyI8 => (~"i8", DW_ATE_signed),
1073 ast::TyI16 => (~"i16", DW_ATE_signed),
1074 ast::TyI32 => (~"i32", DW_ATE_signed),
1075 ast::TyI64 => (~"i64", DW_ATE_signed)
1077 ty::ty_uint(uint_ty) => match uint_ty {
1078 ast::TyU => (~"uint", DW_ATE_unsigned),
1079 ast::TyU8 => (~"u8", DW_ATE_unsigned),
1080 ast::TyU16 => (~"u16", DW_ATE_unsigned),
1081 ast::TyU32 => (~"u32", DW_ATE_unsigned),
1082 ast::TyU64 => (~"u64", DW_ATE_unsigned)
1084 ty::ty_float(float_ty) => match float_ty {
1085 ast::TyF32 => (~"f32", DW_ATE_float),
1086 ast::TyF64 => (~"f64", DW_ATE_float)
1088 _ => cx.sess.bug("debuginfo::basic_type_metadata - t is invalid type")
1091 let llvm_type = type_of::type_of(cx, t);
1092 let (size, align) = size_and_align_of(cx, llvm_type);
1093 let ty_metadata = name.with_c_str(|name| {
1095 llvm::LLVMDIBuilderCreateBasicType(
1098 bytes_to_bits(size),
1099 bytes_to_bits(align),
1107 fn pointer_type_metadata(cx: &CrateContext,
1108 pointer_type: ty::t,
1109 pointee_type_metadata: DIType)
1111 let pointer_llvm_type = type_of::type_of(cx, pointer_type);
1112 let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
1113 let name = ppaux::ty_to_str(cx.tcx, pointer_type);
1114 let ptr_metadata = name.with_c_str(|name| {
1116 llvm::LLVMDIBuilderCreatePointerType(
1118 pointee_type_metadata,
1119 bytes_to_bits(pointer_size),
1120 bytes_to_bits(pointer_align),
1124 return ptr_metadata;
1127 trait MemberDescriptionFactory {
1128 fn create_member_descriptions(&self, cx: &CrateContext)
1129 -> ~[MemberDescription];
1132 struct StructMemberDescriptionFactory {
1133 fields: ~[ty::field],
1137 impl MemberDescriptionFactory for StructMemberDescriptionFactory {
1138 fn create_member_descriptions(&self, cx: &CrateContext)
1139 -> ~[MemberDescription] {
1140 self.fields.map(|field| {
1141 let name = if field.ident.name == special_idents::unnamed_field.name {
1144 let string = token::get_ident(field.ident.name);
1145 string.get().to_str()
1150 llvm_type: type_of::type_of(cx, field.mt.ty),
1151 type_metadata: type_metadata(cx, field.mt.ty, self.span),
1152 offset: ComputedMemberOffset,
1158 fn prepare_struct_metadata(cx: &CrateContext,
1161 substs: &ty::substs,
1163 -> RecursiveTypeDescription {
1164 let struct_name = ppaux::ty_to_str(cx.tcx, struct_type);
1165 let struct_llvm_type = type_of::type_of(cx, struct_type);
1167 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id, span);
1169 let file_name = span_start(cx, definition_span).file.name.clone();
1170 let file_metadata = file_metadata(cx, file_name);
1172 let struct_metadata_stub = create_struct_stub(cx,
1179 let fields = ty::struct_fields(cx.tcx, def_id, substs);
1181 UnfinishedMetadata {
1182 cache_id: cache_id_for_type(struct_type),
1183 metadata_stub: struct_metadata_stub,
1184 llvm_type: struct_llvm_type,
1185 file_metadata: file_metadata,
1186 member_description_factory: @StructMemberDescriptionFactory {
1189 } as @MemberDescriptionFactory,
1193 enum RecursiveTypeDescription {
1194 UnfinishedMetadata {
1196 metadata_stub: DICompositeType,
1198 file_metadata: DIFile,
1199 member_description_factory: @MemberDescriptionFactory,
1201 FinalMetadata(DICompositeType)
1204 impl RecursiveTypeDescription {
1206 fn finalize(&self, cx: &CrateContext) -> DICompositeType {
1208 FinalMetadata(metadata) => metadata,
1209 UnfinishedMetadata {
1214 member_description_factory
1216 // Insert the stub into the cache in order to allow recursive references ...
1218 let mut created_types = debug_context(cx).created_types.borrow_mut();
1219 created_types.get().insert(cache_id, metadata_stub);
1222 // ... then create the member descriptions ...
1223 let member_descriptions = member_description_factory.create_member_descriptions(cx);
1225 // ... and attach them to the stub to complete it.
1226 set_members_of_composite_type(cx,
1229 member_descriptions,
1232 return metadata_stub;
1238 struct TupleMemberDescriptionFactory {
1239 component_types: ~[ty::t],
1243 impl MemberDescriptionFactory for TupleMemberDescriptionFactory {
1244 fn create_member_descriptions(&self, cx: &CrateContext)
1245 -> ~[MemberDescription] {
1246 self.component_types.map(|&component_type| {
1249 llvm_type: type_of::type_of(cx, component_type),
1250 type_metadata: type_metadata(cx, component_type, self.span),
1251 offset: ComputedMemberOffset,
1257 fn prepare_tuple_metadata(cx: &CrateContext,
1259 component_types: &[ty::t],
1261 -> RecursiveTypeDescription {
1262 let tuple_name = ppaux::ty_to_str(cx.tcx, tuple_type);
1263 let tuple_llvm_type = type_of::type_of(cx, tuple_type);
1265 let loc = span_start(cx, span);
1266 let file_metadata = file_metadata(cx, loc.file.name);
1268 UnfinishedMetadata {
1269 cache_id: cache_id_for_type(tuple_type),
1270 metadata_stub: create_struct_stub(cx,
1276 llvm_type: tuple_llvm_type,
1277 file_metadata: file_metadata,
1278 member_description_factory: @TupleMemberDescriptionFactory {
1279 component_types: component_types.to_owned(),
1281 } as @MemberDescriptionFactory
1285 struct GeneralMemberDescriptionFactory {
1286 type_rep: @adt::Repr,
1287 variants: @~[@ty::VariantInfo],
1288 discriminant_type_metadata: ValueRef,
1289 containing_scope: DIScope,
1290 file_metadata: DIFile,
1294 impl MemberDescriptionFactory for GeneralMemberDescriptionFactory {
1295 fn create_member_descriptions(&self, cx: &CrateContext)
1296 -> ~[MemberDescription] {
1297 // Capture type_rep, so we don't have to copy the struct_defs array
1298 let struct_defs = match *self.type_rep {
1299 adt::General(_, ref struct_defs) => struct_defs,
1300 _ => cx.sess.bug("unreachable")
1306 .map(|(i, struct_def)| {
1307 let (variant_type_metadata, variant_llvm_type, member_desc_factory) =
1308 describe_enum_variant(cx,
1311 Some(self.discriminant_type_metadata),
1312 self.containing_scope,
1316 let member_descriptions =
1317 member_desc_factory.create_member_descriptions(cx);
1319 set_members_of_composite_type(cx,
1320 variant_type_metadata,
1322 member_descriptions,
1327 llvm_type: variant_llvm_type,
1328 type_metadata: variant_type_metadata,
1329 offset: FixedMemberOffset { bytes: 0 },
1335 struct EnumVariantMemberDescriptionFactory {
1336 args: ~[(~str, ty::t)],
1337 discriminant_type_metadata: Option<DIType>,
1341 impl MemberDescriptionFactory for EnumVariantMemberDescriptionFactory {
1342 fn create_member_descriptions(&self, cx: &CrateContext)
1343 -> ~[MemberDescription] {
1344 self.args.iter().enumerate().map(|(i, &(ref name, ty))| {
1346 name: name.to_str(),
1347 llvm_type: type_of::type_of(cx, ty),
1348 type_metadata: match self.discriminant_type_metadata {
1349 Some(metadata) if i == 0 => metadata,
1350 _ => type_metadata(cx, ty, self.span)
1352 offset: ComputedMemberOffset,
1358 fn describe_enum_variant(cx: &CrateContext,
1359 struct_def: &adt::Struct,
1360 variant_info: &ty::VariantInfo,
1361 discriminant_type_metadata: Option<DIType>,
1362 containing_scope: DIScope,
1363 file_metadata: DIFile,
1365 -> (DICompositeType, Type, @MemberDescriptionFactory) {
1366 let variant_name = token::ident_to_str(&variant_info.name);
1367 let variant_llvm_type = Type::struct_(struct_def.fields.map(|&t| type_of::type_of(cx, t)),
1369 // Could some consistency checks here: size, align, field count, discr type
1371 // Find the source code location of the variant's definition
1372 let variant_definition_span = if variant_info.id.crate == ast::LOCAL_CRATE {
1374 match cx.tcx.items.find(variant_info.id.node) {
1375 Some(ast_map::NodeVariant(ref variant, _, _)) => variant.span,
1377 cx.sess.span_warn(span,
1378 format!("debuginfo::enum_metadata()::\
1379 adt_struct_metadata() - Unexpected node \
1380 type: {:?}. This is a bug.", node));
1386 // For definitions from other crates we have no location information available.
1390 let metadata_stub = create_struct_stub(cx,
1395 variant_definition_span);
1397 // Get the argument names from the enum variant info
1398 let mut arg_names = match variant_info.arg_names {
1399 Some(ref names) => {
1401 let string = token::get_ident(ident.name);
1402 string.get().to_str()
1405 None => variant_info.args.map(|_| ~"")
1408 // If this is not a univariant enum, there is also the (unnamed) discriminant field
1409 if discriminant_type_metadata.is_some() {
1410 arg_names.insert(0, ~"");
1413 // Build an array of (field name, field type) pairs to be captured in the factory closure.
1414 let args: ~[(~str, ty::t)] = arg_names.iter()
1415 .zip(struct_def.fields.iter())
1416 .map(|(s, &t)| (s.to_str(), t))
1419 let member_description_factory =
1420 @EnumVariantMemberDescriptionFactory {
1422 discriminant_type_metadata: discriminant_type_metadata,
1424 } as @MemberDescriptionFactory;
1426 (metadata_stub, variant_llvm_type, member_description_factory)
1429 fn prepare_enum_metadata(cx: &CrateContext,
1431 enum_def_id: ast::DefId,
1433 -> RecursiveTypeDescription {
1434 let enum_name = ppaux::ty_to_str(cx.tcx, enum_type);
1436 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx,
1439 let loc = span_start(cx, definition_span);
1440 let file_metadata = file_metadata(cx, loc.file.name);
1442 // For empty enums there is an early exit. Just describe it as an empty struct with the
1443 // appropriate type name
1444 if ty::type_is_empty(cx.tcx, enum_type) {
1445 let empty_type_metadata = composite_type_metadata(cx,
1453 return FinalMetadata(empty_type_metadata);
1456 let variants = ty::enum_variants(cx.tcx, enum_def_id);
1458 let enumerators_metadata: ~[DIDescriptor] = variants
1461 let name: &str = token::ident_to_str(&v.name);
1462 let discriminant_value = v.disr_val as c_ulonglong;
1464 name.with_c_str(|name| {
1466 llvm::LLVMDIBuilderCreateEnumerator(
1475 let discriminant_type_metadata = |inttype| {
1476 let discriminant_llvm_type = adt::ll_inttype(cx, inttype);
1477 let (discriminant_size, discriminant_align) = size_and_align_of(cx, discriminant_llvm_type);
1478 let discriminant_base_type_metadata = type_metadata(cx, adt::ty_of_inttype(inttype),
1480 enum_name.with_c_str(|enum_name| {
1482 llvm::LLVMDIBuilderCreateEnumerationType(
1488 bytes_to_bits(discriminant_size),
1489 bytes_to_bits(discriminant_align),
1490 create_DIArray(DIB(cx), enumerators_metadata),
1491 discriminant_base_type_metadata)
1496 let type_rep = adt::represent_type(cx, enum_type);
1498 return match *type_rep {
1499 adt::CEnum(inttype, _, _) => {
1500 FinalMetadata(discriminant_type_metadata(inttype))
1502 adt::Univariant(ref struct_def, _) => {
1503 assert!(variants.len() == 1);
1506 member_description_factory) = describe_enum_variant(cx,
1513 UnfinishedMetadata {
1514 cache_id: cache_id_for_type(enum_type),
1515 metadata_stub: metadata_stub,
1516 llvm_type: variant_llvm_type,
1517 file_metadata: file_metadata,
1518 member_description_factory: member_description_factory
1521 adt::General(inttype, _) => {
1522 let discriminant_type_metadata = discriminant_type_metadata(inttype);
1523 let enum_llvm_type = type_of::type_of(cx, enum_type);
1524 let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type);
1525 let unique_id = generate_unique_type_id("DI_ENUM_");
1527 let enum_metadata = enum_name.with_c_str(|enum_name| {
1528 unique_id.with_c_str(|unique_id| {
1530 llvm::LLVMDIBuilderCreateUnionType(
1536 bytes_to_bits(enum_type_size),
1537 bytes_to_bits(enum_type_align),
1546 UnfinishedMetadata {
1547 cache_id: cache_id_for_type(enum_type),
1548 metadata_stub: enum_metadata,
1549 llvm_type: enum_llvm_type,
1550 file_metadata: file_metadata,
1551 member_description_factory: @GeneralMemberDescriptionFactory {
1554 discriminant_type_metadata: discriminant_type_metadata,
1555 containing_scope: containing_scope,
1556 file_metadata: file_metadata,
1558 } as @MemberDescriptionFactory,
1561 adt::NullablePointer { nonnull: ref struct_def, nndiscr, .. } => {
1564 member_description_factory) = describe_enum_variant(cx,
1571 UnfinishedMetadata {
1572 cache_id: cache_id_for_type(enum_type),
1573 metadata_stub: metadata_stub,
1574 llvm_type: variant_llvm_type,
1575 file_metadata: file_metadata,
1576 member_description_factory: member_description_factory
1583 FixedMemberOffset { bytes: uint },
1584 // For ComputedMemberOffset, the offset is read from the llvm type definition
1585 ComputedMemberOffset
1588 struct MemberDescription {
1591 type_metadata: DIType,
1592 offset: MemberOffset,
1595 /// Creates debug information for a composite type, that is, anything that results in a LLVM struct.
1597 /// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums.
1598 fn composite_type_metadata(cx: &CrateContext,
1599 composite_llvm_type: Type,
1600 composite_type_name: &str,
1601 member_descriptions: &[MemberDescription],
1602 containing_scope: DIScope,
1603 file_metadata: DIFile,
1604 definition_span: Span)
1605 -> DICompositeType {
1606 // Create the (empty) struct metadata node ...
1607 let composite_type_metadata = create_struct_stub(cx,
1608 composite_llvm_type,
1609 composite_type_name,
1614 // ... and immediately create and add the member descriptions.
1615 set_members_of_composite_type(cx,
1616 composite_type_metadata,
1617 composite_llvm_type,
1618 member_descriptions,
1622 return composite_type_metadata;
1625 fn set_members_of_composite_type(cx: &CrateContext,
1626 composite_type_metadata: DICompositeType,
1627 composite_llvm_type: Type,
1628 member_descriptions: &[MemberDescription],
1629 file_metadata: DIFile,
1630 definition_span: Span) {
1631 // In some rare cases LLVM metadata uniquing would lead to an existing type description being
1632 // used instead of a new one created in create_struct_stub. This would cause a hard to trace
1633 // assertion in DICompositeType::SetTypeArray(). The following check makes sure that we get a
1634 // better error message if this should happen again due to some regression.
1636 let mut composite_types_completed =
1637 debug_context(cx).composite_types_completed.borrow_mut();
1638 if composite_types_completed.get().contains(&composite_type_metadata) {
1639 cx.sess.span_bug(definition_span, "debuginfo::set_members_of_composite_type() - \
1640 Already completed forward declaration \
1643 composite_types_completed.get().insert(composite_type_metadata);
1647 let loc = span_start(cx, definition_span);
1649 let member_metadata: ~[DIDescriptor] = member_descriptions
1652 .map(|(i, member_description)| {
1653 let (member_size, member_align) = size_and_align_of(cx, member_description.llvm_type);
1654 let member_offset = match member_description.offset {
1655 FixedMemberOffset { bytes } => bytes as u64,
1656 ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i)
1659 member_description.name.with_c_str(|member_name| {
1661 llvm::LLVMDIBuilderCreateMemberType(
1663 composite_type_metadata,
1667 bytes_to_bits(member_size),
1668 bytes_to_bits(member_align),
1669 bytes_to_bits(member_offset),
1671 member_description.type_metadata)
1678 let type_array = create_DIArray(DIB(cx), member_metadata);
1679 llvm::LLVMDICompositeTypeSetTypeArray(composite_type_metadata, type_array);
1683 // A convenience wrapper around LLVMDIBuilderCreateStructType(). Does not do any caching, does not
1684 // add any fields to the struct. This can be done later with set_members_of_composite_type().
1685 fn create_struct_stub(cx: &CrateContext,
1686 struct_llvm_type: Type,
1687 struct_type_name: &str,
1688 containing_scope: DIScope,
1689 file_metadata: DIFile,
1690 definition_span: Span)
1691 -> DICompositeType {
1692 let loc = span_start(cx, definition_span);
1693 let (struct_size, struct_align) = size_and_align_of(cx, struct_llvm_type);
1695 // We assign unique IDs to the type stubs so LLVM metadata uniquing does not reuse instances
1696 // where we don't want it.
1697 let unique_id = generate_unique_type_id("DI_STRUCT_");
1700 struct_type_name.with_c_str(|name| {
1701 unique_id.with_c_str(|unique_id| {
1702 // LLVMDIBuilderCreateStructType() wants an empty array. A null pointer will lead to
1703 // hard to trace and debug LLVM assertions later on in llvm/lib/IR/Value.cpp
1704 let empty_array = create_DIArray(DIB(cx), []);
1706 llvm::LLVMDIBuilderCreateStructType(
1712 bytes_to_bits(struct_size),
1713 bytes_to_bits(struct_align),
1725 fn boxed_type_metadata(cx: &CrateContext,
1726 content_type_name: Option<&str>,
1727 content_llvm_type: Type,
1728 content_type_metadata: DIType,
1730 -> DICompositeType {
1731 let box_type_name = match content_type_name {
1732 Some(content_type_name) => format!("Boxed<{}>", content_type_name),
1733 None => ~"BoxedType"
1736 let box_llvm_type = Type::at_box(cx, content_llvm_type);
1737 let member_llvm_types = box_llvm_type.field_types();
1738 assert!(box_layout_is_correct(cx, member_llvm_types, content_llvm_type));
1740 let int_type = ty::mk_int();
1741 let nil_pointer_type = ty::mk_nil_ptr(cx.tcx);
1742 let nil_pointer_type_metadata = type_metadata(cx, nil_pointer_type, codemap::DUMMY_SP);
1744 let member_descriptions = [
1747 llvm_type: member_llvm_types[0],
1748 type_metadata: type_metadata(cx, int_type, codemap::DUMMY_SP),
1749 offset: ComputedMemberOffset,
1753 llvm_type: member_llvm_types[1],
1754 type_metadata: nil_pointer_type_metadata,
1755 offset: ComputedMemberOffset,
1759 llvm_type: member_llvm_types[2],
1760 type_metadata: nil_pointer_type_metadata,
1761 offset: ComputedMemberOffset,
1765 llvm_type: member_llvm_types[3],
1766 type_metadata: nil_pointer_type_metadata,
1767 offset: ComputedMemberOffset,
1771 llvm_type: member_llvm_types[4],
1772 type_metadata: content_type_metadata,
1773 offset: ComputedMemberOffset,
1777 let loc = span_start(cx, span);
1778 let file_metadata = file_metadata(cx, loc.file.name);
1780 return composite_type_metadata(
1784 member_descriptions,
1789 // Unfortunately, we cannot assert anything but the correct types here---and not whether the
1790 // 'next' and 'prev' pointers are in the correct order.
1791 fn box_layout_is_correct(cx: &CrateContext,
1792 member_llvm_types: &[Type],
1793 content_llvm_type: Type)
1795 member_llvm_types.len() == 5 &&
1796 member_llvm_types[0] == cx.int_type &&
1797 member_llvm_types[1] == cx.tydesc_type.ptr_to() &&
1798 member_llvm_types[2] == Type::i8().ptr_to() &&
1799 member_llvm_types[3] == Type::i8().ptr_to() &&
1800 member_llvm_types[4] == content_llvm_type
1804 fn fixed_vec_metadata(cx: &CrateContext,
1805 element_type: ty::t,
1809 let element_type_metadata = type_metadata(cx, element_type, span);
1810 let element_llvm_type = type_of::type_of(cx, element_type);
1811 let (element_type_size, element_type_align) = size_and_align_of(cx, element_llvm_type);
1813 let subrange = unsafe {
1814 llvm::LLVMDIBuilderGetOrCreateSubrange(
1820 let subscripts = create_DIArray(DIB(cx), [subrange]);
1822 llvm::LLVMDIBuilderCreateArrayType(
1824 bytes_to_bits(element_type_size * (len as u64)),
1825 bytes_to_bits(element_type_align),
1826 element_type_metadata,
1831 fn vec_metadata(cx: &CrateContext,
1832 element_type: ty::t,
1834 -> DICompositeType {
1836 let element_type_metadata = type_metadata(cx, element_type, span);
1837 let element_llvm_type = type_of::type_of(cx, element_type);
1838 let (element_size, element_align) = size_and_align_of(cx, element_llvm_type);
1840 let vec_llvm_type = Type::vec(cx.sess.targ_cfg.arch, &element_llvm_type);
1841 let vec_type_name: &str = format!("[{}]", ppaux::ty_to_str(cx.tcx, element_type));
1843 let member_llvm_types = vec_llvm_type.field_types();
1845 let int_type_metadata = type_metadata(cx, ty::mk_int(), span);
1846 let array_type_metadata = unsafe {
1847 llvm::LLVMDIBuilderCreateArrayType(
1849 bytes_to_bits(element_size),
1850 bytes_to_bits(element_align),
1851 element_type_metadata,
1852 create_DIArray(DIB(cx), [llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, 0)]))
1855 let member_descriptions = [
1858 llvm_type: member_llvm_types[0],
1859 type_metadata: int_type_metadata,
1860 offset: ComputedMemberOffset,
1864 llvm_type: member_llvm_types[1],
1865 type_metadata: int_type_metadata,
1866 offset: ComputedMemberOffset,
1870 llvm_type: member_llvm_types[2],
1871 type_metadata: array_type_metadata,
1872 offset: ComputedMemberOffset,
1876 assert!(member_descriptions.len() == member_llvm_types.len());
1878 let loc = span_start(cx, span);
1879 let file_metadata = file_metadata(cx, loc.file.name);
1881 return composite_type_metadata(
1885 member_descriptions,
1891 fn boxed_vec_metadata(cx: &CrateContext,
1892 element_type: ty::t,
1894 -> DICompositeType {
1895 let element_llvm_type = type_of::type_of(cx, element_type);
1896 let vec_llvm_type = Type::vec(cx.sess.targ_cfg.arch, &element_llvm_type);
1897 let vec_type_name: &str = format!("[{}]", ppaux::ty_to_str(cx.tcx, element_type));
1898 let vec_metadata = vec_metadata(cx, element_type, span);
1900 return boxed_type_metadata(
1902 Some(vec_type_name),
1908 fn vec_slice_metadata(cx: &CrateContext,
1910 element_type: ty::t,
1912 -> DICompositeType {
1914 debug!("vec_slice_metadata: {:?}", ty::get(vec_type));
1916 let slice_llvm_type = type_of::type_of(cx, vec_type);
1917 let slice_type_name = ppaux::ty_to_str(cx.tcx, vec_type);
1919 let member_llvm_types = slice_llvm_type.field_types();
1920 assert!(slice_layout_is_correct(cx, member_llvm_types, element_type));
1922 let data_ptr_type = ty::mk_ptr(cx.tcx, ty::mt { ty: element_type, mutbl: ast::MutImmutable });
1924 let member_descriptions = [
1927 llvm_type: member_llvm_types[0],
1928 type_metadata: type_metadata(cx, data_ptr_type, span),
1929 offset: ComputedMemberOffset,
1933 llvm_type: member_llvm_types[1],
1934 type_metadata: type_metadata(cx, ty::mk_uint(), span),
1935 offset: ComputedMemberOffset,
1939 assert!(member_descriptions.len() == member_llvm_types.len());
1941 let loc = span_start(cx, span);
1942 let file_metadata = file_metadata(cx, loc.file.name);
1944 return composite_type_metadata(
1948 member_descriptions,
1953 fn slice_layout_is_correct(cx: &CrateContext,
1954 member_llvm_types: &[Type],
1955 element_type: ty::t)
1957 member_llvm_types.len() == 2 &&
1958 member_llvm_types[0] == type_of::type_of(cx, element_type).ptr_to() &&
1959 member_llvm_types[1] == cx.int_type
1963 fn subroutine_type_metadata(cx: &CrateContext,
1964 signature: &ty::FnSig,
1966 -> DICompositeType {
1967 let loc = span_start(cx, span);
1968 let file_metadata = file_metadata(cx, loc.file.name);
1970 let mut signature_metadata: ~[DIType] = vec::with_capacity(signature.inputs.len() + 1);
1973 signature_metadata.push(match ty::get(signature.output).sty {
1974 ty::ty_nil => ptr::null(),
1975 _ => type_metadata(cx, signature.output, span)
1978 // regular arguments
1979 for &argument_type in signature.inputs.iter() {
1980 signature_metadata.push(type_metadata(cx, argument_type, span));
1984 llvm::LLVMDIBuilderCreateSubroutineType(
1987 create_DIArray(DIB(cx), signature_metadata))
1991 fn trait_metadata(cx: &CrateContext,
1994 substs: &ty::substs,
1995 trait_store: ty::TraitStore,
1996 mutability: ast::Mutability,
1997 _: &ty::BuiltinBounds,
1998 usage_site_span: Span)
2000 // The implementation provided here is a stub. It makes sure that the trait type is
2001 // assigned the correct name, size, namespace, and source location. But it does not describe
2002 // the trait's methods.
2003 let path = ty::item_path(cx.tcx, def_id);
2004 let ident = path.last().unwrap().ident();
2005 let name = ppaux::trait_store_to_str(cx.tcx, trait_store) +
2006 ppaux::mutability_to_str(mutability) +
2007 token::ident_to_str(&ident);
2008 // Add type and region parameters
2009 let name = ppaux::parameterized(cx.tcx, name, &substs.regions,
2010 substs.tps, def_id, true);
2012 let (containing_scope, definition_span) =
2013 get_namespace_and_span_for_item(cx, def_id, usage_site_span);
2015 let file_name = span_start(cx, definition_span).file.name.clone();
2016 let file_metadata = file_metadata(cx, file_name);
2018 let trait_llvm_type = type_of::type_of(cx, trait_type);
2020 return composite_type_metadata(cx,
2029 fn type_metadata(cx: &CrateContext,
2031 usage_site_span: Span)
2033 let cache_id = cache_id_for_type(t);
2036 let created_types = debug_context(cx).created_types.borrow();
2037 match created_types.get().find(&cache_id) {
2038 Some(type_metadata) => return *type_metadata,
2043 fn create_pointer_to_box_metadata(cx: &CrateContext,
2044 pointer_type: ty::t,
2047 let content_type_name: &str = ppaux::ty_to_str(cx.tcx, type_in_box);
2048 let content_llvm_type = type_of::type_of(cx, type_in_box);
2049 let content_type_metadata = type_metadata(
2054 let box_metadata = boxed_type_metadata(
2056 Some(content_type_name),
2058 content_type_metadata,
2061 pointer_type_metadata(cx, pointer_type, box_metadata)
2064 debug!("type_metadata: {:?}", ty::get(t));
2066 let sty = &ty::get(t).sty;
2067 let type_metadata = match *sty {
2074 ty::ty_float(_) => {
2075 basic_type_metadata(cx, t)
2077 ty::ty_str(ref vstore) => {
2078 let i8_t = ty::mk_i8();
2080 ty::vstore_fixed(len) => {
2081 fixed_vec_metadata(cx, i8_t, len + 1, usage_site_span)
2083 ty::vstore_uniq => {
2084 let vec_metadata = vec_metadata(cx, i8_t, usage_site_span);
2085 pointer_type_metadata(cx, t, vec_metadata)
2088 let boxed_vec_metadata = boxed_vec_metadata(cx, i8_t, usage_site_span);
2089 pointer_type_metadata(cx, t, boxed_vec_metadata)
2091 ty::vstore_slice(_region) => {
2092 vec_slice_metadata(cx, t, i8_t, usage_site_span)
2096 ty::ty_enum(def_id, _) => {
2097 prepare_enum_metadata(cx, t, def_id, usage_site_span).finalize(cx)
2099 ty::ty_box(typ) => {
2100 create_pointer_to_box_metadata(cx, t, typ)
2102 ty::ty_vec(ref mt, ref vstore) => {
2104 ty::vstore_fixed(len) => {
2105 fixed_vec_metadata(cx, mt.ty, len, usage_site_span)
2107 ty::vstore_uniq => {
2108 let vec_metadata = vec_metadata(cx, mt.ty, usage_site_span);
2109 pointer_type_metadata(cx, t, vec_metadata)
2112 let boxed_vec_metadata = boxed_vec_metadata(cx, mt.ty, usage_site_span);
2113 pointer_type_metadata(cx, t, boxed_vec_metadata)
2115 ty::vstore_slice(_) => {
2116 vec_slice_metadata(cx, t, mt.ty, usage_site_span)
2120 ty::ty_uniq(typ) => {
2121 let pointee = type_metadata(cx, typ, usage_site_span);
2122 pointer_type_metadata(cx, t, pointee)
2124 ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => {
2125 let pointee = type_metadata(cx, mt.ty, usage_site_span);
2126 pointer_type_metadata(cx, t, pointee)
2128 ty::ty_bare_fn(ref barefnty) => {
2129 subroutine_type_metadata(cx, &barefnty.sig, usage_site_span)
2131 ty::ty_closure(ref closurety) => {
2132 subroutine_type_metadata(cx, &closurety.sig, usage_site_span)
2134 ty::ty_trait(def_id, ref substs, trait_store, mutability, ref bounds) => {
2135 trait_metadata(cx, def_id, t, substs, trait_store, mutability, bounds, usage_site_span)
2137 ty::ty_struct(def_id, ref substs) => {
2138 prepare_struct_metadata(cx, t, def_id, substs, usage_site_span).finalize(cx)
2140 ty::ty_tup(ref elements) => {
2141 prepare_tuple_metadata(cx, t, *elements, usage_site_span).finalize(cx)
2143 _ => cx.sess.bug(format!("debuginfo: unexpected type in type_metadata: {:?}", sty))
2146 let mut created_types = debug_context(cx).created_types.borrow_mut();
2147 created_types.get().insert(cache_id, type_metadata);
2152 enum DebugLocation {
2153 KnownLocation { scope: DIScope, line: uint, col: uint },
2157 impl DebugLocation {
2158 fn new(scope: DIScope, line: uint, col: uint) -> DebugLocation {
2167 fn set_debug_location(cx: &CrateContext, debug_location: DebugLocation) {
2168 if debug_location == debug_context(cx).current_debug_location.get() {
2174 match debug_location {
2175 KnownLocation { scope, line, .. } => {
2176 let col = 0; // Always set the column to zero like Clang and GCC
2177 debug!("setting debug location to {} {}", line, col);
2178 let elements = [C_i32(line as i32), C_i32(col as i32), scope, ptr::null()];
2180 metadata_node = llvm::LLVMMDNodeInContext(debug_context(cx).llcontext,
2182 elements.len() as c_uint);
2185 UnknownLocation => {
2186 debug!("clearing debug location ");
2187 metadata_node = ptr::null();
2192 llvm::LLVMSetCurrentDebugLocation(cx.builder.B, metadata_node);
2195 debug_context(cx).current_debug_location.set(debug_location);
2198 //=-------------------------------------------------------------------------------------------------
2199 // Utility Functions
2200 //=-------------------------------------------------------------------------------------------------
2202 fn cache_id_for_type(t: ty::t) -> uint {
2206 // Used to avoid LLVM metadata uniquing problems. See `create_struct_stub()` and
2207 // `prepare_enum_metadata()`.
2208 fn generate_unique_type_id(prefix: &'static str) -> ~str {
2210 static mut unique_id_counter: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;
2211 format!("{}{}", prefix, unique_id_counter.fetch_add(1, atomics::SeqCst))
2215 /// Return codemap::Loc corresponding to the beginning of the span
2216 fn span_start(cx: &CrateContext, span: Span) -> codemap::Loc {
2217 cx.sess.codemap.lookup_char_pos(span.lo)
2220 fn size_and_align_of(cx: &CrateContext, llvm_type: Type) -> (u64, u64) {
2221 (machine::llsize_of_alloc(cx, llvm_type), machine::llalign_of_min(cx, llvm_type))
2224 fn bytes_to_bits(bytes: u64) -> c_ulonglong {
2225 (bytes * 8) as c_ulonglong
2229 fn debug_context<'a>(cx: &'a CrateContext) -> &'a CrateDebugContext {
2230 let debug_context: &'a CrateDebugContext = cx.dbg_cx.get_ref();
2235 fn DIB(cx: &CrateContext) -> DIBuilderRef {
2236 cx.dbg_cx.get_ref().builder
2239 fn fn_should_be_ignored(fcx: &FunctionContext) -> bool {
2240 match fcx.debug_context {
2241 FunctionDebugContext(_) => false,
2246 fn assert_type_for_node_id(cx: &CrateContext, node_id: ast::NodeId, error_span: Span) {
2247 let node_types = cx.tcx.node_types.borrow();
2248 if !node_types.get().contains_key(&(node_id as uint)) {
2249 cx.sess.span_bug(error_span, "debuginfo: Could not find type for node id!");
2253 fn get_namespace_and_span_for_item(cx: &CrateContext,
2256 -> (DIScope, Span) {
2257 let containing_scope = namespace_for_item(cx, def_id, warning_span).scope;
2258 let definition_span = if def_id.crate == ast::LOCAL_CRATE {
2260 let definition_span = match cx.tcx.items.find(def_id.node) {
2261 Some(ast_map::NodeItem(item, _)) => item.span,
2263 cx.sess.span_warn(warning_span,
2264 format!("debuginfo::\
2265 get_namespace_and_span_for_item() \
2266 - Unexpected node type: {:?}", *node));
2273 // For external items there is no span information
2277 (containing_scope, definition_span)
2280 // This procedure builds the *scope map* for a given function, which maps any given ast::NodeId in
2281 // the function's AST to the correct DIScope metadata instance.
2283 // This builder procedure walks the AST in execution order and keeps track of what belongs to which
2284 // scope, creating DIScope DIEs along the way, and introducing *artificial* lexical scope
2285 // descriptors where necessary. These artificial scopes allow GDB to correctly handle name
2287 fn populate_scope_map(cx: &CrateContext,
2288 arg_pats: &[@ast::Pat],
2289 fn_entry_block: &ast::Block,
2290 fn_metadata: DISubprogram,
2291 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2292 let def_map = cx.tcx.def_map;
2294 struct ScopeStackEntry {
2295 scope_metadata: DIScope,
2296 ident: Option<ast::Ident>
2299 let mut scope_stack = ~[ScopeStackEntry { scope_metadata: fn_metadata, ident: None }];
2301 // Push argument identifiers onto the stack so arguments integrate nicely with variable
2303 for &arg_pat in arg_pats.iter() {
2304 pat_util::pat_bindings(def_map, arg_pat, |_, _, _, path_ref| {
2305 let ident = ast_util::path_to_ident(path_ref);
2306 scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata, ident: Some(ident) });
2310 // Clang creates a separate scope for function bodies, so let's do this too
2312 fn_entry_block.span,
2315 |cx, scope_stack, scope_map| {
2316 walk_block(cx, fn_entry_block, scope_stack, scope_map);
2319 // local helper functions for walking the AST.
2320 fn with_new_scope(cx: &CrateContext,
2322 scope_stack: &mut ~[ScopeStackEntry],
2323 scope_map: &mut HashMap<ast::NodeId, DIScope>,
2324 inner_walk: |&CrateContext,
2325 &mut ~[ScopeStackEntry],
2326 &mut HashMap<ast::NodeId, DIScope>|) {
2327 // Create a new lexical scope and push it onto the stack
2328 let loc = cx.sess.codemap.lookup_char_pos(scope_span.lo);
2329 let file_metadata = file_metadata(cx, loc.file.name);
2330 let parent_scope = scope_stack.last().unwrap().scope_metadata;
2332 let scope_metadata = unsafe {
2333 llvm::LLVMDIBuilderCreateLexicalBlock(
2338 loc.col.to_uint() as c_uint)
2341 scope_stack.push(ScopeStackEntry { scope_metadata: scope_metadata, ident: None });
2343 inner_walk(cx, scope_stack, scope_map);
2345 // pop artificial scopes
2346 while scope_stack.last().unwrap().ident.is_some() {
2350 if scope_stack.last().unwrap().scope_metadata != scope_metadata {
2351 cx.sess.span_bug(scope_span, "debuginfo: Inconsistency in scope management.");
2357 fn walk_block(cx: &CrateContext,
2359 scope_stack: &mut ~[ScopeStackEntry],
2360 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2361 scope_map.insert(block.id, scope_stack.last().unwrap().scope_metadata);
2363 // The interesting things here are statements and the concluding expression.
2364 for statement in block.stmts.iter() {
2365 scope_map.insert(ast_util::stmt_id(*statement),
2366 scope_stack.last().unwrap().scope_metadata);
2368 match statement.node {
2369 ast::StmtDecl(decl, _) => walk_decl(cx, decl, scope_stack, scope_map),
2370 ast::StmtExpr(exp, _) |
2371 ast::StmtSemi(exp, _) => walk_expr(cx, exp, scope_stack, scope_map),
2372 ast::StmtMac(..) => () // ignore macros (which should be expanded anyway)
2376 for exp in block.expr.iter() {
2377 walk_expr(cx, *exp, scope_stack, scope_map);
2381 fn walk_decl(cx: &CrateContext,
2383 scope_stack: &mut ~[ScopeStackEntry],
2384 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2386 codemap::Spanned { node: ast::DeclLocal(local), .. } => {
2387 scope_map.insert(local.id, scope_stack.last().unwrap().scope_metadata);
2389 walk_pattern(cx, local.pat, scope_stack, scope_map);
2391 for exp in local.init.iter() {
2392 walk_expr(cx, *exp, scope_stack, scope_map);
2399 fn walk_pattern(cx: &CrateContext,
2401 scope_stack: &mut ~[ScopeStackEntry],
2402 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2404 let def_map = cx.tcx.def_map;
2406 // Unfortunately, we cannot just use pat_util::pat_bindings() or ast_util::walk_pat() here
2407 // because we have to visit *all* nodes in order to put them into the scope map. The above
2408 // functions don't do that.
2410 ast::PatIdent(_, ref path_ref, ref sub_pat_opt) => {
2412 // Check if this is a binding. If so we need to put it on the scope stack and maybe
2413 // introduce an articial scope
2414 if pat_util::pat_is_binding(def_map, pat) {
2416 let ident = ast_util::path_to_ident(path_ref);
2418 // LLVM does not properly generate 'DW_AT_start_scope' fields for variable DIEs.
2419 // For this reason we have to introduce an artificial scope at bindings whenever
2420 // a variable with the same name is declared in *any* parent scope.
2422 // Otherwise the following error occurs:
2426 // do_something(); // 'gdb print x' correctly prints 10
2429 // do_something(); // 'gdb print x' prints 0, because it already reads the
2430 // // uninitialized 'x' from the next line...
2432 // do_something(); // 'gdb print x' correctly prints 100
2435 // Is there already a binding with that name?
2436 // N.B.: this comparison must be UNhygienic... because
2437 // gdb knows nothing about the context, so any two
2438 // variables with the same name will cause the problem.
2439 let need_new_scope = scope_stack
2441 .any(|entry| entry.ident.iter().any(|i| i.name == ident.name));
2444 // Create a new lexical scope and push it onto the stack
2445 let loc = cx.sess.codemap.lookup_char_pos(pat.span.lo);
2446 let file_metadata = file_metadata(cx, loc.file.name);
2447 let parent_scope = scope_stack.last().unwrap().scope_metadata;
2449 let scope_metadata = unsafe {
2450 llvm::LLVMDIBuilderCreateLexicalBlock(
2455 loc.col.to_uint() as c_uint)
2458 scope_stack.push(ScopeStackEntry {
2459 scope_metadata: scope_metadata,
2464 // Push a new entry anyway so the name can be found
2465 let prev_metadata = scope_stack.last().unwrap().scope_metadata;
2466 scope_stack.push(ScopeStackEntry {
2467 scope_metadata: prev_metadata,
2473 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2475 for &sub_pat in sub_pat_opt.iter() {
2476 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2480 ast::PatWild | ast::PatWildMulti => {
2481 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2484 ast::PatEnum(_, ref sub_pats_opt) => {
2485 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2487 for ref sub_pats in sub_pats_opt.iter() {
2488 for &p in sub_pats.iter() {
2489 walk_pattern(cx, p, scope_stack, scope_map);
2494 ast::PatStruct(_, ref field_pats, _) => {
2495 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2497 for &ast::FieldPat { pat: sub_pat, .. } in field_pats.iter() {
2498 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2502 ast::PatTup(ref sub_pats) => {
2503 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2505 for &sub_pat in sub_pats.iter() {
2506 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2510 ast::PatUniq(sub_pat) | ast::PatRegion(sub_pat) => {
2511 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2512 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2515 ast::PatLit(exp) => {
2516 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2517 walk_expr(cx, exp, scope_stack, scope_map);
2520 ast::PatRange(exp1, exp2) => {
2521 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2522 walk_expr(cx, exp1, scope_stack, scope_map);
2523 walk_expr(cx, exp2, scope_stack, scope_map);
2526 ast::PatVec(ref front_sub_pats, ref middle_sub_pats, ref back_sub_pats) => {
2527 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2529 for &sub_pat in front_sub_pats.iter() {
2530 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2533 for &sub_pat in middle_sub_pats.iter() {
2534 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2537 for &sub_pat in back_sub_pats.iter() {
2538 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2544 fn walk_expr(cx: &CrateContext,
2546 scope_stack: &mut ~[ScopeStackEntry],
2547 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2549 scope_map.insert(exp.id, scope_stack.last().unwrap().scope_metadata);
2556 ast::ExprPath(_) => {}
2558 ast::ExprVstore(sub_exp, _) |
2559 ast::ExprCast(sub_exp, _) |
2560 ast::ExprAddrOf(_, sub_exp) |
2561 ast::ExprField(sub_exp, _, _) |
2562 ast::ExprParen(sub_exp) => walk_expr(cx, sub_exp, scope_stack, scope_map),
2564 ast::ExprBox(place, sub_expr) => {
2565 walk_expr(cx, place, scope_stack, scope_map);
2566 walk_expr(cx, sub_expr, scope_stack, scope_map);
2569 ast::ExprRet(exp_opt) => match exp_opt {
2570 Some(sub_exp) => walk_expr(cx, sub_exp, scope_stack, scope_map),
2574 ast::ExprUnary(node_id, _, sub_exp) => {
2575 scope_map.insert(node_id, scope_stack.last().unwrap().scope_metadata);
2576 walk_expr(cx, sub_exp, scope_stack, scope_map);
2579 ast::ExprAssignOp(node_id, _, lhs, rhs) |
2580 ast::ExprIndex(node_id, lhs, rhs) |
2581 ast::ExprBinary(node_id, _, lhs, rhs) => {
2582 scope_map.insert(node_id, scope_stack.last().unwrap().scope_metadata);
2583 walk_expr(cx, lhs, scope_stack, scope_map);
2584 walk_expr(cx, rhs, scope_stack, scope_map);
2587 ast::ExprVec(ref init_expressions, _) |
2588 ast::ExprTup(ref init_expressions) => {
2589 for ie in init_expressions.iter() {
2590 walk_expr(cx, *ie, scope_stack, scope_map);
2594 ast::ExprAssign(sub_exp1, sub_exp2) |
2595 ast::ExprRepeat(sub_exp1, sub_exp2, _) => {
2596 walk_expr(cx, sub_exp1, scope_stack, scope_map);
2597 walk_expr(cx, sub_exp2, scope_stack, scope_map);
2600 ast::ExprIf(cond_exp, then_block, ref opt_else_exp) => {
2601 walk_expr(cx, cond_exp, scope_stack, scope_map);
2607 |cx, scope_stack, scope_map| {
2608 walk_block(cx, then_block, scope_stack, scope_map);
2611 match *opt_else_exp {
2612 Some(else_exp) => walk_expr(cx, else_exp, scope_stack, scope_map),
2617 ast::ExprWhile(cond_exp, loop_body) => {
2618 walk_expr(cx, cond_exp, scope_stack, scope_map);
2624 |cx, scope_stack, scope_map| {
2625 walk_block(cx, loop_body, scope_stack, scope_map);
2629 ast::ExprForLoop(_, _, _, _) => {
2630 cx.sess.span_bug(exp.span, "debuginfo::populate_scope_map() - \
2631 Found unexpanded for-loop.");
2634 ast::ExprMac(_) => {
2635 cx.sess.span_bug(exp.span, "debuginfo::populate_scope_map() - \
2636 Found unexpanded macro.");
2639 ast::ExprLoop(block, _) |
2640 ast::ExprBlock(block) => {
2645 |cx, scope_stack, scope_map| {
2646 walk_block(cx, block, scope_stack, scope_map);
2650 ast::ExprFnBlock(decl, block) |
2651 ast::ExprProc(decl, block) => {
2656 |cx, scope_stack, scope_map| {
2657 for &ast::Arg { pat: pattern, .. } in decl.inputs.iter() {
2658 walk_pattern(cx, pattern, scope_stack, scope_map);
2661 walk_block(cx, block, scope_stack, scope_map);
2665 ast::ExprCall(fn_exp, ref args, _) => {
2666 walk_expr(cx, fn_exp, scope_stack, scope_map);
2668 for arg_exp in args.iter() {
2669 walk_expr(cx, *arg_exp, scope_stack, scope_map);
2673 ast::ExprMethodCall(node_id, _, _, ref args, _) => {
2674 scope_map.insert(node_id, scope_stack.last().unwrap().scope_metadata);
2676 for arg_exp in args.iter() {
2677 walk_expr(cx, *arg_exp, scope_stack, scope_map);
2681 ast::ExprMatch(discriminant_exp, ref arms) => {
2682 walk_expr(cx, discriminant_exp, scope_stack, scope_map);
2684 // for each arm we have to first walk the pattern as these might introduce new
2685 // artificial scopes. It should be sufficient to walk only one pattern per arm, as
2686 // they all must contain the same binding names
2688 for arm_ref in arms.iter() {
2689 let arm_span = arm_ref.pats[0].span;
2695 |cx, scope_stack, scope_map| {
2696 for &pat in arm_ref.pats.iter() {
2697 walk_pattern(cx, pat, scope_stack, scope_map);
2700 for guard_exp in arm_ref.guard.iter() {
2701 walk_expr(cx, *guard_exp, scope_stack, scope_map)
2704 walk_block(cx, arm_ref.body, scope_stack, scope_map);
2709 ast::ExprStruct(_, ref fields, ref base_exp) => {
2710 for &ast::Field { expr: exp, .. } in fields.iter() {
2711 walk_expr(cx, exp, scope_stack, scope_map);
2715 Some(exp) => walk_expr(cx, exp, scope_stack, scope_map),
2720 ast::ExprInlineAsm(ast::InlineAsm { inputs: ref inputs,
2721 outputs: ref outputs,
2723 // inputs, outputs: ~[(~str, @expr)]
2724 for &(_, exp) in inputs.iter() {
2725 walk_expr(cx, exp, scope_stack, scope_map);
2728 for &(_, exp) in outputs.iter() {
2729 walk_expr(cx, exp, scope_stack, scope_map);
2737 //=-------------------------------------------------------------------------------------------------
2738 // Namespace Handling
2739 //=-------------------------------------------------------------------------------------------------
2741 struct NamespaceTreeNode {
2744 parent: Option<@NamespaceTreeNode>,
2747 impl NamespaceTreeNode {
2748 fn mangled_name_of_contained_item(&self, item_name: &str) -> ~str {
2749 let mut name = ~"_ZN";
2750 fill_nested(self, &mut name);
2752 name.push_str(format!("{}{}", item_name.len(), item_name));
2753 name.push_char('E');
2757 fn fill_nested(node: &NamespaceTreeNode, output: &mut ~str) {
2760 fill_nested(parent, output);
2764 let name = token::ident_to_str(&node.ident);
2765 output.push_str(format!("{}{}", name.len(), name));
2770 fn namespace_for_item(cx: &CrateContext,
2773 -> @NamespaceTreeNode {
2774 let namespace_path = {
2775 let mut item_path = ty::item_path(cx.tcx, def_id);
2777 if (def_id.crate == ast::LOCAL_CRATE && item_path.len() < 1) ||
2778 (def_id.crate != ast::LOCAL_CRATE && item_path.len() < 2) {
2779 cx.sess.bug(format!("debuginfo::namespace_for_item() - Item path too short: {}",
2780 ast_map::path_to_str(item_path, token::get_ident_interner())));
2783 // remove the name of the item
2786 if def_id.crate == ast::LOCAL_CRATE {
2787 // prepend crate name if not already present
2788 let crate_namespace_ident = token::str_to_ident(cx.link_meta.crateid.name);
2789 item_path.insert(0, ast_map::PathMod(crate_namespace_ident));
2795 let mut current_key = vec::with_capacity(namespace_path.len());
2796 let mut parent_node: Option<@NamespaceTreeNode> = None;
2797 let last_index = namespace_path.len() - 1;
2799 // Create/Lookup namespace for each element of the path.
2800 for (i, &path_element) in namespace_path.iter().enumerate() {
2801 let ident = path_element.ident();
2802 current_key.push(ident);
2804 let existing_node = {
2805 let namespace_map = debug_context(cx).namespace_map.borrow();
2806 namespace_map.get().find_copy(¤t_key)
2808 let current_node = match existing_node {
2809 Some(existing_node) => existing_node,
2811 // create and insert
2812 let parent_scope = match parent_node {
2813 Some(node) => node.scope,
2816 let namespace_name = token::ident_to_str(&ident);
2818 let namespace_metadata = unsafe {
2819 namespace_name.with_c_str(|namespace_name| {
2820 llvm::LLVMDIBuilderCreateNameSpace(
2824 ptr::null(), // cannot reconstruct file ...
2825 0) // ... or line information, but that's not so important.
2829 let node = @NamespaceTreeNode {
2831 scope: namespace_metadata,
2832 parent: parent_node,
2836 let mut namespace_map = debug_context(cx).namespace_map
2838 namespace_map.get().insert(current_key.clone(), node);
2845 if i == last_index {
2846 return current_node;
2848 parent_node = Some(current_node);
2852 // Should be unreachable:
2853 let error_message = format!("debuginfo::namespace_for_item() - Code path should be \
2854 unreachable. namespace_path was {}",
2855 ast_map::path_to_str(namespace_path, token::get_ident_interner()));
2856 cx.sess.span_bug(warning_span, error_message);