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 token::ident_to_str(&field.ident)
1149 llvm_type: type_of::type_of(cx, field.mt.ty),
1150 type_metadata: type_metadata(cx, field.mt.ty, self.span),
1151 offset: ComputedMemberOffset,
1157 fn prepare_struct_metadata(cx: &CrateContext,
1160 substs: &ty::substs,
1162 -> RecursiveTypeDescription {
1163 let struct_name = ppaux::ty_to_str(cx.tcx, struct_type);
1164 let struct_llvm_type = type_of::type_of(cx, struct_type);
1166 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id, span);
1168 let file_name = span_start(cx, definition_span).file.name.clone();
1169 let file_metadata = file_metadata(cx, file_name);
1171 let struct_metadata_stub = create_struct_stub(cx,
1178 let fields = ty::struct_fields(cx.tcx, def_id, substs);
1180 UnfinishedMetadata {
1181 cache_id: cache_id_for_type(struct_type),
1182 metadata_stub: struct_metadata_stub,
1183 llvm_type: struct_llvm_type,
1184 file_metadata: file_metadata,
1185 member_description_factory: @StructMemberDescriptionFactory {
1188 } as @MemberDescriptionFactory,
1192 enum RecursiveTypeDescription {
1193 UnfinishedMetadata {
1195 metadata_stub: DICompositeType,
1197 file_metadata: DIFile,
1198 member_description_factory: @MemberDescriptionFactory,
1200 FinalMetadata(DICompositeType)
1203 impl RecursiveTypeDescription {
1205 fn finalize(&self, cx: &CrateContext) -> DICompositeType {
1207 FinalMetadata(metadata) => metadata,
1208 UnfinishedMetadata {
1213 member_description_factory
1215 // Insert the stub into the cache in order to allow recursive references ...
1217 let mut created_types = debug_context(cx).created_types.borrow_mut();
1218 created_types.get().insert(cache_id, metadata_stub);
1221 // ... then create the member descriptions ...
1222 let member_descriptions = member_description_factory.create_member_descriptions(cx);
1224 // ... and attach them to the stub to complete it.
1225 set_members_of_composite_type(cx,
1228 member_descriptions,
1231 return metadata_stub;
1237 struct TupleMemberDescriptionFactory {
1238 component_types: ~[ty::t],
1242 impl MemberDescriptionFactory for TupleMemberDescriptionFactory {
1243 fn create_member_descriptions(&self, cx: &CrateContext)
1244 -> ~[MemberDescription] {
1245 self.component_types.map(|&component_type| {
1248 llvm_type: type_of::type_of(cx, component_type),
1249 type_metadata: type_metadata(cx, component_type, self.span),
1250 offset: ComputedMemberOffset,
1256 fn prepare_tuple_metadata(cx: &CrateContext,
1258 component_types: &[ty::t],
1260 -> RecursiveTypeDescription {
1261 let tuple_name = ppaux::ty_to_str(cx.tcx, tuple_type);
1262 let tuple_llvm_type = type_of::type_of(cx, tuple_type);
1264 let loc = span_start(cx, span);
1265 let file_metadata = file_metadata(cx, loc.file.name);
1267 UnfinishedMetadata {
1268 cache_id: cache_id_for_type(tuple_type),
1269 metadata_stub: create_struct_stub(cx,
1275 llvm_type: tuple_llvm_type,
1276 file_metadata: file_metadata,
1277 member_description_factory: @TupleMemberDescriptionFactory {
1278 component_types: component_types.to_owned(),
1280 } as @MemberDescriptionFactory
1284 struct GeneralMemberDescriptionFactory {
1285 type_rep: @adt::Repr,
1286 variants: @~[@ty::VariantInfo],
1287 discriminant_type_metadata: ValueRef,
1288 containing_scope: DIScope,
1289 file_metadata: DIFile,
1293 impl MemberDescriptionFactory for GeneralMemberDescriptionFactory {
1294 fn create_member_descriptions(&self, cx: &CrateContext)
1295 -> ~[MemberDescription] {
1296 // Capture type_rep, so we don't have to copy the struct_defs array
1297 let struct_defs = match *self.type_rep {
1298 adt::General(_, ref struct_defs) => struct_defs,
1299 _ => cx.sess.bug("unreachable")
1305 .map(|(i, struct_def)| {
1306 let (variant_type_metadata, variant_llvm_type, member_desc_factory) =
1307 describe_enum_variant(cx,
1310 Some(self.discriminant_type_metadata),
1311 self.containing_scope,
1315 let member_descriptions =
1316 member_desc_factory.create_member_descriptions(cx);
1318 set_members_of_composite_type(cx,
1319 variant_type_metadata,
1321 member_descriptions,
1326 llvm_type: variant_llvm_type,
1327 type_metadata: variant_type_metadata,
1328 offset: FixedMemberOffset { bytes: 0 },
1334 struct EnumVariantMemberDescriptionFactory {
1335 args: ~[(@str, ty::t)],
1336 discriminant_type_metadata: Option<DIType>,
1340 impl MemberDescriptionFactory for EnumVariantMemberDescriptionFactory {
1341 fn create_member_descriptions(&self, cx: &CrateContext)
1342 -> ~[MemberDescription] {
1343 self.args.iter().enumerate().map(|(i, &(name, ty))| {
1346 llvm_type: type_of::type_of(cx, ty),
1347 type_metadata: match self.discriminant_type_metadata {
1348 Some(metadata) if i == 0 => metadata,
1349 _ => type_metadata(cx, ty, self.span)
1351 offset: ComputedMemberOffset,
1357 fn describe_enum_variant(cx: &CrateContext,
1358 struct_def: &adt::Struct,
1359 variant_info: &ty::VariantInfo,
1360 discriminant_type_metadata: Option<DIType>,
1361 containing_scope: DIScope,
1362 file_metadata: DIFile,
1364 -> (DICompositeType, Type, @MemberDescriptionFactory) {
1365 let variant_name = token::ident_to_str(&variant_info.name);
1366 let variant_llvm_type = Type::struct_(struct_def.fields.map(|&t| type_of::type_of(cx, t)),
1368 // Could some consistency checks here: size, align, field count, discr type
1370 // Find the source code location of the variant's definition
1371 let variant_definition_span = if variant_info.id.crate == ast::LOCAL_CRATE {
1373 match cx.tcx.items.find(variant_info.id.node) {
1374 Some(ast_map::NodeVariant(ref variant, _, _)) => variant.span,
1376 cx.sess.span_warn(span,
1377 format!("debuginfo::enum_metadata()::\
1378 adt_struct_metadata() - Unexpected node \
1379 type: {:?}. This is a bug.", node));
1385 // For definitions from other crates we have no location information available.
1389 let metadata_stub = create_struct_stub(cx,
1394 variant_definition_span);
1396 // Get the argument names from the enum variant info
1397 let mut arg_names = match variant_info.arg_names {
1398 Some(ref names) => names.map(|ident| token::ident_to_str(ident)),
1399 None => variant_info.args.map(|_| @"")
1402 // If this is not a univariant enum, there is also the (unnamed) discriminant field
1403 if discriminant_type_metadata.is_some() {
1404 arg_names.insert(0, @"");
1407 // Build an array of (field name, field type) pairs to be captured in the factory closure.
1408 let args: ~[(@str, ty::t)] = arg_names.iter()
1409 .zip(struct_def.fields.iter())
1410 .map(|(&s, &t)| (s, t))
1413 let member_description_factory =
1414 @EnumVariantMemberDescriptionFactory {
1416 discriminant_type_metadata: discriminant_type_metadata,
1418 } as @MemberDescriptionFactory;
1420 (metadata_stub, variant_llvm_type, member_description_factory)
1423 fn prepare_enum_metadata(cx: &CrateContext,
1425 enum_def_id: ast::DefId,
1427 -> RecursiveTypeDescription {
1428 let enum_name = ppaux::ty_to_str(cx.tcx, enum_type);
1430 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx,
1433 let loc = span_start(cx, definition_span);
1434 let file_metadata = file_metadata(cx, loc.file.name);
1436 // For empty enums there is an early exit. Just describe it as an empty struct with the
1437 // appropriate type name
1438 if ty::type_is_empty(cx.tcx, enum_type) {
1439 let empty_type_metadata = composite_type_metadata(cx,
1447 return FinalMetadata(empty_type_metadata);
1450 let variants = ty::enum_variants(cx.tcx, enum_def_id);
1452 let enumerators_metadata: ~[DIDescriptor] = variants
1455 let name: &str = token::ident_to_str(&v.name);
1456 let discriminant_value = v.disr_val as c_ulonglong;
1458 name.with_c_str(|name| {
1460 llvm::LLVMDIBuilderCreateEnumerator(
1469 let discriminant_type_metadata = |inttype| {
1470 let discriminant_llvm_type = adt::ll_inttype(cx, inttype);
1471 let (discriminant_size, discriminant_align) = size_and_align_of(cx, discriminant_llvm_type);
1472 let discriminant_base_type_metadata = type_metadata(cx, adt::ty_of_inttype(inttype),
1474 enum_name.with_c_str(|enum_name| {
1476 llvm::LLVMDIBuilderCreateEnumerationType(
1482 bytes_to_bits(discriminant_size),
1483 bytes_to_bits(discriminant_align),
1484 create_DIArray(DIB(cx), enumerators_metadata),
1485 discriminant_base_type_metadata)
1490 let type_rep = adt::represent_type(cx, enum_type);
1492 return match *type_rep {
1493 adt::CEnum(inttype, _, _) => {
1494 FinalMetadata(discriminant_type_metadata(inttype))
1496 adt::Univariant(ref struct_def, _) => {
1497 assert!(variants.len() == 1);
1500 member_description_factory) = describe_enum_variant(cx,
1507 UnfinishedMetadata {
1508 cache_id: cache_id_for_type(enum_type),
1509 metadata_stub: metadata_stub,
1510 llvm_type: variant_llvm_type,
1511 file_metadata: file_metadata,
1512 member_description_factory: member_description_factory
1515 adt::General(inttype, _) => {
1516 let discriminant_type_metadata = discriminant_type_metadata(inttype);
1517 let enum_llvm_type = type_of::type_of(cx, enum_type);
1518 let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type);
1519 let unique_id = generate_unique_type_id("DI_ENUM_");
1521 let enum_metadata = enum_name.with_c_str(|enum_name| {
1522 unique_id.with_c_str(|unique_id| {
1524 llvm::LLVMDIBuilderCreateUnionType(
1530 bytes_to_bits(enum_type_size),
1531 bytes_to_bits(enum_type_align),
1540 UnfinishedMetadata {
1541 cache_id: cache_id_for_type(enum_type),
1542 metadata_stub: enum_metadata,
1543 llvm_type: enum_llvm_type,
1544 file_metadata: file_metadata,
1545 member_description_factory: @GeneralMemberDescriptionFactory {
1548 discriminant_type_metadata: discriminant_type_metadata,
1549 containing_scope: containing_scope,
1550 file_metadata: file_metadata,
1552 } as @MemberDescriptionFactory,
1555 adt::NullablePointer { nonnull: ref struct_def, nndiscr, .. } => {
1558 member_description_factory) = describe_enum_variant(cx,
1565 UnfinishedMetadata {
1566 cache_id: cache_id_for_type(enum_type),
1567 metadata_stub: metadata_stub,
1568 llvm_type: variant_llvm_type,
1569 file_metadata: file_metadata,
1570 member_description_factory: member_description_factory
1577 FixedMemberOffset { bytes: uint },
1578 // For ComputedMemberOffset, the offset is read from the llvm type definition
1579 ComputedMemberOffset
1582 struct MemberDescription {
1585 type_metadata: DIType,
1586 offset: MemberOffset,
1589 /// Creates debug information for a composite type, that is, anything that results in a LLVM struct.
1591 /// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums.
1592 fn composite_type_metadata(cx: &CrateContext,
1593 composite_llvm_type: Type,
1594 composite_type_name: &str,
1595 member_descriptions: &[MemberDescription],
1596 containing_scope: DIScope,
1597 file_metadata: DIFile,
1598 definition_span: Span)
1599 -> DICompositeType {
1600 // Create the (empty) struct metadata node ...
1601 let composite_type_metadata = create_struct_stub(cx,
1602 composite_llvm_type,
1603 composite_type_name,
1608 // ... and immediately create and add the member descriptions.
1609 set_members_of_composite_type(cx,
1610 composite_type_metadata,
1611 composite_llvm_type,
1612 member_descriptions,
1616 return composite_type_metadata;
1619 fn set_members_of_composite_type(cx: &CrateContext,
1620 composite_type_metadata: DICompositeType,
1621 composite_llvm_type: Type,
1622 member_descriptions: &[MemberDescription],
1623 file_metadata: DIFile,
1624 definition_span: Span) {
1625 // In some rare cases LLVM metadata uniquing would lead to an existing type description being
1626 // used instead of a new one created in create_struct_stub. This would cause a hard to trace
1627 // assertion in DICompositeType::SetTypeArray(). The following check makes sure that we get a
1628 // better error message if this should happen again due to some regression.
1630 let mut composite_types_completed =
1631 debug_context(cx).composite_types_completed.borrow_mut();
1632 if composite_types_completed.get().contains(&composite_type_metadata) {
1633 cx.sess.span_bug(definition_span, "debuginfo::set_members_of_composite_type() - \
1634 Already completed forward declaration \
1637 composite_types_completed.get().insert(composite_type_metadata);
1641 let loc = span_start(cx, definition_span);
1643 let member_metadata: ~[DIDescriptor] = member_descriptions
1646 .map(|(i, member_description)| {
1647 let (member_size, member_align) = size_and_align_of(cx, member_description.llvm_type);
1648 let member_offset = match member_description.offset {
1649 FixedMemberOffset { bytes } => bytes as u64,
1650 ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i)
1653 member_description.name.with_c_str(|member_name| {
1655 llvm::LLVMDIBuilderCreateMemberType(
1657 composite_type_metadata,
1661 bytes_to_bits(member_size),
1662 bytes_to_bits(member_align),
1663 bytes_to_bits(member_offset),
1665 member_description.type_metadata)
1672 let type_array = create_DIArray(DIB(cx), member_metadata);
1673 llvm::LLVMDICompositeTypeSetTypeArray(composite_type_metadata, type_array);
1677 // A convenience wrapper around LLVMDIBuilderCreateStructType(). Does not do any caching, does not
1678 // add any fields to the struct. This can be done later with set_members_of_composite_type().
1679 fn create_struct_stub(cx: &CrateContext,
1680 struct_llvm_type: Type,
1681 struct_type_name: &str,
1682 containing_scope: DIScope,
1683 file_metadata: DIFile,
1684 definition_span: Span)
1685 -> DICompositeType {
1686 let loc = span_start(cx, definition_span);
1687 let (struct_size, struct_align) = size_and_align_of(cx, struct_llvm_type);
1689 // We assign unique IDs to the type stubs so LLVM metadata uniquing does not reuse instances
1690 // where we don't want it.
1691 let unique_id = generate_unique_type_id("DI_STRUCT_");
1694 struct_type_name.with_c_str(|name| {
1695 unique_id.with_c_str(|unique_id| {
1696 // LLVMDIBuilderCreateStructType() wants an empty array. A null pointer will lead to
1697 // hard to trace and debug LLVM assertions later on in llvm/lib/IR/Value.cpp
1698 let empty_array = create_DIArray(DIB(cx), []);
1700 llvm::LLVMDIBuilderCreateStructType(
1706 bytes_to_bits(struct_size),
1707 bytes_to_bits(struct_align),
1719 fn boxed_type_metadata(cx: &CrateContext,
1720 content_type_name: Option<&str>,
1721 content_llvm_type: Type,
1722 content_type_metadata: DIType,
1724 -> DICompositeType {
1725 let box_type_name = match content_type_name {
1726 Some(content_type_name) => format!("Boxed<{}>", content_type_name),
1727 None => ~"BoxedType"
1730 let box_llvm_type = Type::at_box(cx, content_llvm_type);
1731 let member_llvm_types = box_llvm_type.field_types();
1732 assert!(box_layout_is_correct(cx, member_llvm_types, content_llvm_type));
1734 let int_type = ty::mk_int();
1735 let nil_pointer_type = ty::mk_nil_ptr(cx.tcx);
1736 let nil_pointer_type_metadata = type_metadata(cx, nil_pointer_type, codemap::DUMMY_SP);
1738 let member_descriptions = [
1741 llvm_type: member_llvm_types[0],
1742 type_metadata: type_metadata(cx, int_type, codemap::DUMMY_SP),
1743 offset: ComputedMemberOffset,
1747 llvm_type: member_llvm_types[1],
1748 type_metadata: nil_pointer_type_metadata,
1749 offset: ComputedMemberOffset,
1753 llvm_type: member_llvm_types[2],
1754 type_metadata: nil_pointer_type_metadata,
1755 offset: ComputedMemberOffset,
1759 llvm_type: member_llvm_types[3],
1760 type_metadata: nil_pointer_type_metadata,
1761 offset: ComputedMemberOffset,
1765 llvm_type: member_llvm_types[4],
1766 type_metadata: content_type_metadata,
1767 offset: ComputedMemberOffset,
1771 let loc = span_start(cx, span);
1772 let file_metadata = file_metadata(cx, loc.file.name);
1774 return composite_type_metadata(
1778 member_descriptions,
1783 // Unfortunately, we cannot assert anything but the correct types here---and not whether the
1784 // 'next' and 'prev' pointers are in the correct order.
1785 fn box_layout_is_correct(cx: &CrateContext,
1786 member_llvm_types: &[Type],
1787 content_llvm_type: Type)
1789 member_llvm_types.len() == 5 &&
1790 member_llvm_types[0] == cx.int_type &&
1791 member_llvm_types[1] == cx.tydesc_type.ptr_to() &&
1792 member_llvm_types[2] == Type::i8().ptr_to() &&
1793 member_llvm_types[3] == Type::i8().ptr_to() &&
1794 member_llvm_types[4] == content_llvm_type
1798 fn fixed_vec_metadata(cx: &CrateContext,
1799 element_type: ty::t,
1803 let element_type_metadata = type_metadata(cx, element_type, span);
1804 let element_llvm_type = type_of::type_of(cx, element_type);
1805 let (element_type_size, element_type_align) = size_and_align_of(cx, element_llvm_type);
1807 let subrange = unsafe {
1808 llvm::LLVMDIBuilderGetOrCreateSubrange(
1814 let subscripts = create_DIArray(DIB(cx), [subrange]);
1816 llvm::LLVMDIBuilderCreateArrayType(
1818 bytes_to_bits(element_type_size * (len as u64)),
1819 bytes_to_bits(element_type_align),
1820 element_type_metadata,
1825 fn vec_metadata(cx: &CrateContext,
1826 element_type: ty::t,
1828 -> DICompositeType {
1830 let element_type_metadata = type_metadata(cx, element_type, span);
1831 let element_llvm_type = type_of::type_of(cx, element_type);
1832 let (element_size, element_align) = size_and_align_of(cx, element_llvm_type);
1834 let vec_llvm_type = Type::vec(cx.sess.targ_cfg.arch, &element_llvm_type);
1835 let vec_type_name: &str = format!("[{}]", ppaux::ty_to_str(cx.tcx, element_type));
1837 let member_llvm_types = vec_llvm_type.field_types();
1839 let int_type_metadata = type_metadata(cx, ty::mk_int(), span);
1840 let array_type_metadata = unsafe {
1841 llvm::LLVMDIBuilderCreateArrayType(
1843 bytes_to_bits(element_size),
1844 bytes_to_bits(element_align),
1845 element_type_metadata,
1846 create_DIArray(DIB(cx), [llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, 0)]))
1849 let member_descriptions = [
1852 llvm_type: member_llvm_types[0],
1853 type_metadata: int_type_metadata,
1854 offset: ComputedMemberOffset,
1858 llvm_type: member_llvm_types[1],
1859 type_metadata: int_type_metadata,
1860 offset: ComputedMemberOffset,
1864 llvm_type: member_llvm_types[2],
1865 type_metadata: array_type_metadata,
1866 offset: ComputedMemberOffset,
1870 assert!(member_descriptions.len() == member_llvm_types.len());
1872 let loc = span_start(cx, span);
1873 let file_metadata = file_metadata(cx, loc.file.name);
1875 return composite_type_metadata(
1879 member_descriptions,
1885 fn boxed_vec_metadata(cx: &CrateContext,
1886 element_type: ty::t,
1888 -> DICompositeType {
1889 let element_llvm_type = type_of::type_of(cx, element_type);
1890 let vec_llvm_type = Type::vec(cx.sess.targ_cfg.arch, &element_llvm_type);
1891 let vec_type_name: &str = format!("[{}]", ppaux::ty_to_str(cx.tcx, element_type));
1892 let vec_metadata = vec_metadata(cx, element_type, span);
1894 return boxed_type_metadata(
1896 Some(vec_type_name),
1902 fn vec_slice_metadata(cx: &CrateContext,
1904 element_type: ty::t,
1906 -> DICompositeType {
1908 debug!("vec_slice_metadata: {:?}", ty::get(vec_type));
1910 let slice_llvm_type = type_of::type_of(cx, vec_type);
1911 let slice_type_name = ppaux::ty_to_str(cx.tcx, vec_type);
1913 let member_llvm_types = slice_llvm_type.field_types();
1914 assert!(slice_layout_is_correct(cx, member_llvm_types, element_type));
1916 let data_ptr_type = ty::mk_ptr(cx.tcx, ty::mt { ty: element_type, mutbl: ast::MutImmutable });
1918 let member_descriptions = [
1921 llvm_type: member_llvm_types[0],
1922 type_metadata: type_metadata(cx, data_ptr_type, span),
1923 offset: ComputedMemberOffset,
1927 llvm_type: member_llvm_types[1],
1928 type_metadata: type_metadata(cx, ty::mk_uint(), span),
1929 offset: ComputedMemberOffset,
1933 assert!(member_descriptions.len() == member_llvm_types.len());
1935 let loc = span_start(cx, span);
1936 let file_metadata = file_metadata(cx, loc.file.name);
1938 return composite_type_metadata(
1942 member_descriptions,
1947 fn slice_layout_is_correct(cx: &CrateContext,
1948 member_llvm_types: &[Type],
1949 element_type: ty::t)
1951 member_llvm_types.len() == 2 &&
1952 member_llvm_types[0] == type_of::type_of(cx, element_type).ptr_to() &&
1953 member_llvm_types[1] == cx.int_type
1957 fn subroutine_type_metadata(cx: &CrateContext,
1958 signature: &ty::FnSig,
1960 -> DICompositeType {
1961 let loc = span_start(cx, span);
1962 let file_metadata = file_metadata(cx, loc.file.name);
1964 let mut signature_metadata: ~[DIType] = vec::with_capacity(signature.inputs.len() + 1);
1967 signature_metadata.push(match ty::get(signature.output).sty {
1968 ty::ty_nil => ptr::null(),
1969 _ => type_metadata(cx, signature.output, span)
1972 // regular arguments
1973 for &argument_type in signature.inputs.iter() {
1974 signature_metadata.push(type_metadata(cx, argument_type, span));
1978 llvm::LLVMDIBuilderCreateSubroutineType(
1981 create_DIArray(DIB(cx), signature_metadata))
1985 fn trait_metadata(cx: &CrateContext,
1988 substs: &ty::substs,
1989 trait_store: ty::TraitStore,
1990 mutability: ast::Mutability,
1991 _: &ty::BuiltinBounds,
1992 usage_site_span: Span)
1994 // The implementation provided here is a stub. It makes sure that the trait type is
1995 // assigned the correct name, size, namespace, and source location. But it does not describe
1996 // the trait's methods.
1997 let path = ty::item_path(cx.tcx, def_id);
1998 let ident = path.last().unwrap().ident();
1999 let name = ppaux::trait_store_to_str(cx.tcx, trait_store) +
2000 ppaux::mutability_to_str(mutability) +
2001 token::ident_to_str(&ident);
2002 // Add type and region parameters
2003 let name = ppaux::parameterized(cx.tcx, name, &substs.regions,
2004 substs.tps, def_id, true);
2006 let (containing_scope, definition_span) =
2007 get_namespace_and_span_for_item(cx, def_id, usage_site_span);
2009 let file_name = span_start(cx, definition_span).file.name.clone();
2010 let file_metadata = file_metadata(cx, file_name);
2012 let trait_llvm_type = type_of::type_of(cx, trait_type);
2014 return composite_type_metadata(cx,
2023 fn type_metadata(cx: &CrateContext,
2025 usage_site_span: Span)
2027 let cache_id = cache_id_for_type(t);
2030 let created_types = debug_context(cx).created_types.borrow();
2031 match created_types.get().find(&cache_id) {
2032 Some(type_metadata) => return *type_metadata,
2037 fn create_pointer_to_box_metadata(cx: &CrateContext,
2038 pointer_type: ty::t,
2041 let content_type_name: &str = ppaux::ty_to_str(cx.tcx, type_in_box);
2042 let content_llvm_type = type_of::type_of(cx, type_in_box);
2043 let content_type_metadata = type_metadata(
2048 let box_metadata = boxed_type_metadata(
2050 Some(content_type_name),
2052 content_type_metadata,
2055 pointer_type_metadata(cx, pointer_type, box_metadata)
2058 debug!("type_metadata: {:?}", ty::get(t));
2060 let sty = &ty::get(t).sty;
2061 let type_metadata = match *sty {
2068 ty::ty_float(_) => {
2069 basic_type_metadata(cx, t)
2071 ty::ty_str(ref vstore) => {
2072 let i8_t = ty::mk_i8();
2074 ty::vstore_fixed(len) => {
2075 fixed_vec_metadata(cx, i8_t, len + 1, usage_site_span)
2077 ty::vstore_uniq => {
2078 let vec_metadata = vec_metadata(cx, i8_t, usage_site_span);
2079 pointer_type_metadata(cx, t, vec_metadata)
2082 let boxed_vec_metadata = boxed_vec_metadata(cx, i8_t, usage_site_span);
2083 pointer_type_metadata(cx, t, boxed_vec_metadata)
2085 ty::vstore_slice(_region) => {
2086 vec_slice_metadata(cx, t, i8_t, usage_site_span)
2090 ty::ty_enum(def_id, _) => {
2091 prepare_enum_metadata(cx, t, def_id, usage_site_span).finalize(cx)
2093 ty::ty_box(typ) => {
2094 create_pointer_to_box_metadata(cx, t, typ)
2096 ty::ty_vec(ref mt, ref vstore) => {
2098 ty::vstore_fixed(len) => {
2099 fixed_vec_metadata(cx, mt.ty, len, usage_site_span)
2101 ty::vstore_uniq => {
2102 let vec_metadata = vec_metadata(cx, mt.ty, usage_site_span);
2103 pointer_type_metadata(cx, t, vec_metadata)
2106 let boxed_vec_metadata = boxed_vec_metadata(cx, mt.ty, usage_site_span);
2107 pointer_type_metadata(cx, t, boxed_vec_metadata)
2109 ty::vstore_slice(_) => {
2110 vec_slice_metadata(cx, t, mt.ty, usage_site_span)
2114 ty::ty_uniq(typ) => {
2115 let pointee = type_metadata(cx, typ, usage_site_span);
2116 pointer_type_metadata(cx, t, pointee)
2118 ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => {
2119 let pointee = type_metadata(cx, mt.ty, usage_site_span);
2120 pointer_type_metadata(cx, t, pointee)
2122 ty::ty_bare_fn(ref barefnty) => {
2123 subroutine_type_metadata(cx, &barefnty.sig, usage_site_span)
2125 ty::ty_closure(ref closurety) => {
2126 subroutine_type_metadata(cx, &closurety.sig, usage_site_span)
2128 ty::ty_trait(def_id, ref substs, trait_store, mutability, ref bounds) => {
2129 trait_metadata(cx, def_id, t, substs, trait_store, mutability, bounds, usage_site_span)
2131 ty::ty_struct(def_id, ref substs) => {
2132 prepare_struct_metadata(cx, t, def_id, substs, usage_site_span).finalize(cx)
2134 ty::ty_tup(ref elements) => {
2135 prepare_tuple_metadata(cx, t, *elements, usage_site_span).finalize(cx)
2137 _ => cx.sess.bug(format!("debuginfo: unexpected type in type_metadata: {:?}", sty))
2140 let mut created_types = debug_context(cx).created_types.borrow_mut();
2141 created_types.get().insert(cache_id, type_metadata);
2146 enum DebugLocation {
2147 KnownLocation { scope: DIScope, line: uint, col: uint },
2151 impl DebugLocation {
2152 fn new(scope: DIScope, line: uint, col: uint) -> DebugLocation {
2161 fn set_debug_location(cx: &CrateContext, debug_location: DebugLocation) {
2162 if debug_location == debug_context(cx).current_debug_location.get() {
2168 match debug_location {
2169 KnownLocation { scope, line, .. } => {
2170 let col = 0; // Always set the column to zero like Clang and GCC
2171 debug!("setting debug location to {} {}", line, col);
2172 let elements = [C_i32(line as i32), C_i32(col as i32), scope, ptr::null()];
2174 metadata_node = llvm::LLVMMDNodeInContext(debug_context(cx).llcontext,
2176 elements.len() as c_uint);
2179 UnknownLocation => {
2180 debug!("clearing debug location ");
2181 metadata_node = ptr::null();
2186 llvm::LLVMSetCurrentDebugLocation(cx.builder.B, metadata_node);
2189 debug_context(cx).current_debug_location.set(debug_location);
2192 //=-------------------------------------------------------------------------------------------------
2193 // Utility Functions
2194 //=-------------------------------------------------------------------------------------------------
2196 fn cache_id_for_type(t: ty::t) -> uint {
2200 // Used to avoid LLVM metadata uniquing problems. See `create_struct_stub()` and
2201 // `prepare_enum_metadata()`.
2202 fn generate_unique_type_id(prefix: &'static str) -> ~str {
2204 static mut unique_id_counter: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;
2205 format!("{}{}", prefix, unique_id_counter.fetch_add(1, atomics::SeqCst))
2209 /// Return codemap::Loc corresponding to the beginning of the span
2210 fn span_start(cx: &CrateContext, span: Span) -> codemap::Loc {
2211 cx.sess.codemap.lookup_char_pos(span.lo)
2214 fn size_and_align_of(cx: &CrateContext, llvm_type: Type) -> (u64, u64) {
2215 (machine::llsize_of_alloc(cx, llvm_type), machine::llalign_of_min(cx, llvm_type))
2218 fn bytes_to_bits(bytes: u64) -> c_ulonglong {
2219 (bytes * 8) as c_ulonglong
2223 fn debug_context<'a>(cx: &'a CrateContext) -> &'a CrateDebugContext {
2224 let debug_context: &'a CrateDebugContext = cx.dbg_cx.get_ref();
2229 fn DIB(cx: &CrateContext) -> DIBuilderRef {
2230 cx.dbg_cx.get_ref().builder
2233 fn fn_should_be_ignored(fcx: &FunctionContext) -> bool {
2234 match fcx.debug_context {
2235 FunctionDebugContext(_) => false,
2240 fn assert_type_for_node_id(cx: &CrateContext, node_id: ast::NodeId, error_span: Span) {
2241 let node_types = cx.tcx.node_types.borrow();
2242 if !node_types.get().contains_key(&(node_id as uint)) {
2243 cx.sess.span_bug(error_span, "debuginfo: Could not find type for node id!");
2247 fn get_namespace_and_span_for_item(cx: &CrateContext,
2250 -> (DIScope, Span) {
2251 let containing_scope = namespace_for_item(cx, def_id, warning_span).scope;
2252 let definition_span = if def_id.crate == ast::LOCAL_CRATE {
2254 let definition_span = match cx.tcx.items.find(def_id.node) {
2255 Some(ast_map::NodeItem(item, _)) => item.span,
2257 cx.sess.span_warn(warning_span,
2258 format!("debuginfo::\
2259 get_namespace_and_span_for_item() \
2260 - Unexpected node type: {:?}", *node));
2267 // For external items there is no span information
2271 (containing_scope, definition_span)
2274 // This procedure builds the *scope map* for a given function, which maps any given ast::NodeId in
2275 // the function's AST to the correct DIScope metadata instance.
2277 // This builder procedure walks the AST in execution order and keeps track of what belongs to which
2278 // scope, creating DIScope DIEs along the way, and introducing *artificial* lexical scope
2279 // descriptors where necessary. These artificial scopes allow GDB to correctly handle name
2281 fn populate_scope_map(cx: &CrateContext,
2282 arg_pats: &[@ast::Pat],
2283 fn_entry_block: &ast::Block,
2284 fn_metadata: DISubprogram,
2285 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2286 let def_map = cx.tcx.def_map;
2288 struct ScopeStackEntry {
2289 scope_metadata: DIScope,
2290 ident: Option<ast::Ident>
2293 let mut scope_stack = ~[ScopeStackEntry { scope_metadata: fn_metadata, ident: None }];
2295 // Push argument identifiers onto the stack so arguments integrate nicely with variable
2297 for &arg_pat in arg_pats.iter() {
2298 pat_util::pat_bindings(def_map, arg_pat, |_, _, _, path_ref| {
2299 let ident = ast_util::path_to_ident(path_ref);
2300 scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata, ident: Some(ident) });
2304 // Clang creates a separate scope for function bodies, so let's do this too
2306 fn_entry_block.span,
2309 |cx, scope_stack, scope_map| {
2310 walk_block(cx, fn_entry_block, scope_stack, scope_map);
2313 // local helper functions for walking the AST.
2314 fn with_new_scope(cx: &CrateContext,
2316 scope_stack: &mut ~[ScopeStackEntry],
2317 scope_map: &mut HashMap<ast::NodeId, DIScope>,
2318 inner_walk: |&CrateContext,
2319 &mut ~[ScopeStackEntry],
2320 &mut HashMap<ast::NodeId, DIScope>|) {
2321 // Create a new lexical scope and push it onto the stack
2322 let loc = cx.sess.codemap.lookup_char_pos(scope_span.lo);
2323 let file_metadata = file_metadata(cx, loc.file.name);
2324 let parent_scope = scope_stack.last().unwrap().scope_metadata;
2326 let scope_metadata = unsafe {
2327 llvm::LLVMDIBuilderCreateLexicalBlock(
2332 loc.col.to_uint() as c_uint)
2335 scope_stack.push(ScopeStackEntry { scope_metadata: scope_metadata, ident: None });
2337 inner_walk(cx, scope_stack, scope_map);
2339 // pop artificial scopes
2340 while scope_stack.last().unwrap().ident.is_some() {
2344 if scope_stack.last().unwrap().scope_metadata != scope_metadata {
2345 cx.sess.span_bug(scope_span, "debuginfo: Inconsistency in scope management.");
2351 fn walk_block(cx: &CrateContext,
2353 scope_stack: &mut ~[ScopeStackEntry],
2354 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2355 scope_map.insert(block.id, scope_stack.last().unwrap().scope_metadata);
2357 // The interesting things here are statements and the concluding expression.
2358 for statement in block.stmts.iter() {
2359 scope_map.insert(ast_util::stmt_id(*statement),
2360 scope_stack.last().unwrap().scope_metadata);
2362 match statement.node {
2363 ast::StmtDecl(decl, _) => walk_decl(cx, decl, scope_stack, scope_map),
2364 ast::StmtExpr(exp, _) |
2365 ast::StmtSemi(exp, _) => walk_expr(cx, exp, scope_stack, scope_map),
2366 ast::StmtMac(..) => () // ignore macros (which should be expanded anyway)
2370 for exp in block.expr.iter() {
2371 walk_expr(cx, *exp, scope_stack, scope_map);
2375 fn walk_decl(cx: &CrateContext,
2377 scope_stack: &mut ~[ScopeStackEntry],
2378 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2380 codemap::Spanned { node: ast::DeclLocal(local), .. } => {
2381 scope_map.insert(local.id, scope_stack.last().unwrap().scope_metadata);
2383 walk_pattern(cx, local.pat, scope_stack, scope_map);
2385 for exp in local.init.iter() {
2386 walk_expr(cx, *exp, scope_stack, scope_map);
2393 fn walk_pattern(cx: &CrateContext,
2395 scope_stack: &mut ~[ScopeStackEntry],
2396 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2398 let def_map = cx.tcx.def_map;
2400 // Unfortunately, we cannot just use pat_util::pat_bindings() or ast_util::walk_pat() here
2401 // because we have to visit *all* nodes in order to put them into the scope map. The above
2402 // functions don't do that.
2404 ast::PatIdent(_, ref path_ref, ref sub_pat_opt) => {
2406 // Check if this is a binding. If so we need to put it on the scope stack and maybe
2407 // introduce an articial scope
2408 if pat_util::pat_is_binding(def_map, pat) {
2410 let ident = ast_util::path_to_ident(path_ref);
2412 // LLVM does not properly generate 'DW_AT_start_scope' fields for variable DIEs.
2413 // For this reason we have to introduce an artificial scope at bindings whenever
2414 // a variable with the same name is declared in *any* parent scope.
2416 // Otherwise the following error occurs:
2420 // do_something(); // 'gdb print x' correctly prints 10
2423 // do_something(); // 'gdb print x' prints 0, because it already reads the
2424 // // uninitialized 'x' from the next line...
2426 // do_something(); // 'gdb print x' correctly prints 100
2429 // Is there already a binding with that name?
2430 // N.B.: this comparison must be UNhygienic... because
2431 // gdb knows nothing about the context, so any two
2432 // variables with the same name will cause the problem.
2433 let need_new_scope = scope_stack
2435 .any(|entry| entry.ident.iter().any(|i| i.name == ident.name));
2438 // Create a new lexical scope and push it onto the stack
2439 let loc = cx.sess.codemap.lookup_char_pos(pat.span.lo);
2440 let file_metadata = file_metadata(cx, loc.file.name);
2441 let parent_scope = scope_stack.last().unwrap().scope_metadata;
2443 let scope_metadata = unsafe {
2444 llvm::LLVMDIBuilderCreateLexicalBlock(
2449 loc.col.to_uint() as c_uint)
2452 scope_stack.push(ScopeStackEntry {
2453 scope_metadata: scope_metadata,
2458 // Push a new entry anyway so the name can be found
2459 let prev_metadata = scope_stack.last().unwrap().scope_metadata;
2460 scope_stack.push(ScopeStackEntry {
2461 scope_metadata: prev_metadata,
2467 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2469 for &sub_pat in sub_pat_opt.iter() {
2470 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2474 ast::PatWild | ast::PatWildMulti => {
2475 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2478 ast::PatEnum(_, ref sub_pats_opt) => {
2479 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2481 for ref sub_pats in sub_pats_opt.iter() {
2482 for &p in sub_pats.iter() {
2483 walk_pattern(cx, p, scope_stack, scope_map);
2488 ast::PatStruct(_, ref field_pats, _) => {
2489 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2491 for &ast::FieldPat { pat: sub_pat, .. } in field_pats.iter() {
2492 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2496 ast::PatTup(ref sub_pats) => {
2497 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2499 for &sub_pat in sub_pats.iter() {
2500 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2504 ast::PatUniq(sub_pat) | ast::PatRegion(sub_pat) => {
2505 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2506 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2509 ast::PatLit(exp) => {
2510 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2511 walk_expr(cx, exp, scope_stack, scope_map);
2514 ast::PatRange(exp1, exp2) => {
2515 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2516 walk_expr(cx, exp1, scope_stack, scope_map);
2517 walk_expr(cx, exp2, scope_stack, scope_map);
2520 ast::PatVec(ref front_sub_pats, ref middle_sub_pats, ref back_sub_pats) => {
2521 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2523 for &sub_pat in front_sub_pats.iter() {
2524 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2527 for &sub_pat in middle_sub_pats.iter() {
2528 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2531 for &sub_pat in back_sub_pats.iter() {
2532 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2538 fn walk_expr(cx: &CrateContext,
2540 scope_stack: &mut ~[ScopeStackEntry],
2541 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2543 scope_map.insert(exp.id, scope_stack.last().unwrap().scope_metadata);
2550 ast::ExprPath(_) => {}
2552 ast::ExprVstore(sub_exp, _) |
2553 ast::ExprCast(sub_exp, _) |
2554 ast::ExprAddrOf(_, sub_exp) |
2555 ast::ExprField(sub_exp, _, _) |
2556 ast::ExprParen(sub_exp) => walk_expr(cx, sub_exp, scope_stack, scope_map),
2558 ast::ExprBox(place, sub_expr) => {
2559 walk_expr(cx, place, scope_stack, scope_map);
2560 walk_expr(cx, sub_expr, scope_stack, scope_map);
2563 ast::ExprRet(exp_opt) => match exp_opt {
2564 Some(sub_exp) => walk_expr(cx, sub_exp, scope_stack, scope_map),
2568 ast::ExprUnary(node_id, _, sub_exp) => {
2569 scope_map.insert(node_id, scope_stack.last().unwrap().scope_metadata);
2570 walk_expr(cx, sub_exp, scope_stack, scope_map);
2573 ast::ExprAssignOp(node_id, _, lhs, rhs) |
2574 ast::ExprIndex(node_id, lhs, rhs) |
2575 ast::ExprBinary(node_id, _, lhs, rhs) => {
2576 scope_map.insert(node_id, scope_stack.last().unwrap().scope_metadata);
2577 walk_expr(cx, lhs, scope_stack, scope_map);
2578 walk_expr(cx, rhs, scope_stack, scope_map);
2581 ast::ExprVec(ref init_expressions, _) |
2582 ast::ExprTup(ref init_expressions) => {
2583 for ie in init_expressions.iter() {
2584 walk_expr(cx, *ie, scope_stack, scope_map);
2588 ast::ExprAssign(sub_exp1, sub_exp2) |
2589 ast::ExprRepeat(sub_exp1, sub_exp2, _) => {
2590 walk_expr(cx, sub_exp1, scope_stack, scope_map);
2591 walk_expr(cx, sub_exp2, scope_stack, scope_map);
2594 ast::ExprIf(cond_exp, then_block, ref opt_else_exp) => {
2595 walk_expr(cx, cond_exp, scope_stack, scope_map);
2601 |cx, scope_stack, scope_map| {
2602 walk_block(cx, then_block, scope_stack, scope_map);
2605 match *opt_else_exp {
2606 Some(else_exp) => walk_expr(cx, else_exp, scope_stack, scope_map),
2611 ast::ExprWhile(cond_exp, loop_body) => {
2612 walk_expr(cx, cond_exp, scope_stack, scope_map);
2618 |cx, scope_stack, scope_map| {
2619 walk_block(cx, loop_body, scope_stack, scope_map);
2623 ast::ExprForLoop(_, _, _, _) => {
2624 cx.sess.span_bug(exp.span, "debuginfo::populate_scope_map() - \
2625 Found unexpanded for-loop.");
2628 ast::ExprMac(_) => {
2629 cx.sess.span_bug(exp.span, "debuginfo::populate_scope_map() - \
2630 Found unexpanded macro.");
2633 ast::ExprLoop(block, _) |
2634 ast::ExprBlock(block) => {
2639 |cx, scope_stack, scope_map| {
2640 walk_block(cx, block, scope_stack, scope_map);
2644 ast::ExprFnBlock(decl, block) |
2645 ast::ExprProc(decl, block) => {
2650 |cx, scope_stack, scope_map| {
2651 for &ast::Arg { pat: pattern, .. } in decl.inputs.iter() {
2652 walk_pattern(cx, pattern, scope_stack, scope_map);
2655 walk_block(cx, block, scope_stack, scope_map);
2659 ast::ExprCall(fn_exp, ref args, _) => {
2660 walk_expr(cx, fn_exp, scope_stack, scope_map);
2662 for arg_exp in args.iter() {
2663 walk_expr(cx, *arg_exp, scope_stack, scope_map);
2667 ast::ExprMethodCall(node_id, _, _, ref args, _) => {
2668 scope_map.insert(node_id, scope_stack.last().unwrap().scope_metadata);
2670 for arg_exp in args.iter() {
2671 walk_expr(cx, *arg_exp, scope_stack, scope_map);
2675 ast::ExprMatch(discriminant_exp, ref arms) => {
2676 walk_expr(cx, discriminant_exp, scope_stack, scope_map);
2678 // for each arm we have to first walk the pattern as these might introduce new
2679 // artificial scopes. It should be sufficient to walk only one pattern per arm, as
2680 // they all must contain the same binding names
2682 for arm_ref in arms.iter() {
2683 let arm_span = arm_ref.pats[0].span;
2689 |cx, scope_stack, scope_map| {
2690 for &pat in arm_ref.pats.iter() {
2691 walk_pattern(cx, pat, scope_stack, scope_map);
2694 for guard_exp in arm_ref.guard.iter() {
2695 walk_expr(cx, *guard_exp, scope_stack, scope_map)
2698 walk_block(cx, arm_ref.body, scope_stack, scope_map);
2703 ast::ExprStruct(_, ref fields, ref base_exp) => {
2704 for &ast::Field { expr: exp, .. } in fields.iter() {
2705 walk_expr(cx, exp, scope_stack, scope_map);
2709 Some(exp) => walk_expr(cx, exp, scope_stack, scope_map),
2714 ast::ExprInlineAsm(ast::InlineAsm { inputs: ref inputs,
2715 outputs: ref outputs,
2717 // inputs, outputs: ~[(@str, @expr)]
2718 for &(_, exp) in inputs.iter() {
2719 walk_expr(cx, exp, scope_stack, scope_map);
2722 for &(_, exp) in outputs.iter() {
2723 walk_expr(cx, exp, scope_stack, scope_map);
2731 //=-------------------------------------------------------------------------------------------------
2732 // Namespace Handling
2733 //=-------------------------------------------------------------------------------------------------
2735 struct NamespaceTreeNode {
2738 parent: Option<@NamespaceTreeNode>,
2741 impl NamespaceTreeNode {
2742 fn mangled_name_of_contained_item(&self, item_name: &str) -> ~str {
2743 let mut name = ~"_ZN";
2744 fill_nested(self, &mut name);
2746 name.push_str(format!("{}{}", item_name.len(), item_name));
2747 name.push_char('E');
2751 fn fill_nested(node: &NamespaceTreeNode, output: &mut ~str) {
2754 fill_nested(parent, output);
2758 let name = token::ident_to_str(&node.ident);
2759 output.push_str(format!("{}{}", name.len(), name));
2764 fn namespace_for_item(cx: &CrateContext,
2767 -> @NamespaceTreeNode {
2768 let namespace_path = {
2769 let mut item_path = ty::item_path(cx.tcx, def_id);
2771 if (def_id.crate == ast::LOCAL_CRATE && item_path.len() < 1) ||
2772 (def_id.crate != ast::LOCAL_CRATE && item_path.len() < 2) {
2773 cx.sess.bug(format!("debuginfo::namespace_for_item() - Item path too short: {}",
2774 ast_map::path_to_str(item_path, token::get_ident_interner())));
2777 // remove the name of the item
2780 if def_id.crate == ast::LOCAL_CRATE {
2781 // prepend crate name if not already present
2782 let crate_namespace_ident = token::str_to_ident(cx.link_meta.crateid.name);
2783 item_path.insert(0, ast_map::PathMod(crate_namespace_ident));
2789 let mut current_key = vec::with_capacity(namespace_path.len());
2790 let mut parent_node: Option<@NamespaceTreeNode> = None;
2791 let last_index = namespace_path.len() - 1;
2793 // Create/Lookup namespace for each element of the path.
2794 for (i, &path_element) in namespace_path.iter().enumerate() {
2795 let ident = path_element.ident();
2796 current_key.push(ident);
2798 let existing_node = {
2799 let namespace_map = debug_context(cx).namespace_map.borrow();
2800 namespace_map.get().find_copy(¤t_key)
2802 let current_node = match existing_node {
2803 Some(existing_node) => existing_node,
2805 // create and insert
2806 let parent_scope = match parent_node {
2807 Some(node) => node.scope,
2810 let namespace_name = token::ident_to_str(&ident);
2812 let namespace_metadata = unsafe {
2813 namespace_name.with_c_str(|namespace_name| {
2814 llvm::LLVMDIBuilderCreateNameSpace(
2818 ptr::null(), // cannot reconstruct file ...
2819 0) // ... or line information, but that's not so important.
2823 let node = @NamespaceTreeNode {
2825 scope: namespace_metadata,
2826 parent: parent_node,
2830 let mut namespace_map = debug_context(cx).namespace_map
2832 namespace_map.get().insert(current_key.clone(), node);
2839 if i == last_index {
2840 return current_node;
2842 parent_node = Some(current_node);
2846 // Should be unreachable:
2847 let error_message = format!("debuginfo::namespace_for_item() - Code path should be \
2848 unreachable. namespace_path was {}",
2849 ast_map::path_to_str(namespace_path, token::get_ident_interner()));
2850 cx.sess.span_bug(warning_span, error_message);