1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
14 This module serves the purpose of generating debug symbols. We use LLVM's
15 [source level debugging](http://llvm.org/docs/SourceLevelDebugging.html) features for generating
16 the debug information. The general principle is this:
18 Given the right metadata in the LLVM IR, the LLVM code generator is able to create DWARF debug
19 symbols for the given code. The [metadata](http://llvm.org/docs/LangRef.html#metadata-type) is
20 structured much like DWARF *debugging information entries* (DIE), representing type information
21 such as datatype layout, function signatures, block layout, variable location and scope information,
22 etc. It is the purpose of this module to generate correct metadata and insert it into the LLVM IR.
24 As the exact format of metadata trees may change between different LLVM versions, we now use LLVM
25 [DIBuilder](http://llvm.org/docs/doxygen/html/classllvm_1_1DIBuilder.html) to create metadata
26 where possible. This will hopefully ease the adaption of this module to future LLVM versions.
28 The public API of the module is a set of functions that will insert the correct metadata into the
29 LLVM IR when called with the right parameters. The module is thus driven from an outside client with
30 functions like `debuginfo::create_local_var_metadata(bcx: block, local: &ast::local)`.
32 Internally the module will try to reuse already created metadata by utilizing a cache. The way to
33 get a shared metadata node when needed is thus to just call the corresponding function in this
36 let file_metadata = file_metadata(crate_context, path);
38 The function will take care of probing the cache for an existing node for that exact file path.
40 All private state used by the module is stored within either the CrateDebugContext struct (owned by
41 the CrateContext) or the FunctionDebugContext (owned by the FunctionContext).
43 This file consists of three conceptual sections:
44 1. The public interface of the module
45 2. Module-internal metadata creation functions
46 3. Minor utility functions
50 Some kinds of types, such as structs and enums can be recursive. That means that the type definition
51 of some type X refers to some other type which in turn (transitively) refers to X. This introduces
52 cycles into the type referral graph. A naive algorithm doing an on-demand, depth-first traversal of
53 this graph when describing types, can get trapped in an endless loop when it reaches such a cycle.
55 For example, the following simple type for a singly-linked list...
64 will generate the following callstack with a naive DFS algorithm:
69 describe(t = Option<@List>)
71 describe(t = List) // at the beginning again...
75 To break cycles like these, we use "forward declarations". That is, when the algorithm encounters a
76 possibly recursive type (any struct or enum), it immediately creates a type description node and
77 inserts it into the cache *before* describing the members of the type. This type description is just
78 a stub (as type members are not described and added to it yet) but it allows the algorithm to
79 already refer to the type. After the stub is inserted into the cache, the algorithm continues as
80 before. If it now encounters a recursive reference, it will hit the cache and does not try to
81 describe the type anew.
83 This behaviour is encapsulated in the 'RecursiveTypeDescription' enum, which represents a kind of
84 continuation, storing all state needed to continue traversal at the type members after the type has
85 been registered with the cache. (This implementation approach might be a tad over-engineered and
86 may change in the future)
89 ## Source Locations and Line Information
90 In addition to data type descriptions the debugging information must also allow to map machine code
91 locations back to source code locations in order to be useful. This functionality is also handled in
92 this module. The following functions allow to control source mappings:
94 + set_source_location()
95 + clear_source_location()
96 + start_emitting_source_locations()
98 `set_source_location()` allows to set the current source location. All IR instructions created after
99 a call to this function will be linked to the given source location, until another location is
100 specified with `set_source_location()` or the source location is cleared with
101 `clear_source_location()`. In the later case, subsequent IR instruction will not be linked to any
102 source location. As you can see, this is a stateful API (mimicking the one in LLVM), so be careful
103 with source locations set by previous calls. It's probably best to not rely on any specific state
104 being present at a given point in code.
106 One topic that deserves some extra attention is *function prologues*. At the beginning of a
107 function's machine code there are typically a few instructions for loading argument values into
108 allocas and checking if there's enough stack space for the function to execute. This *prologue* is
109 not visible in the source code and LLVM puts a special PROLOGUE END marker into the line table at
110 the first non-prologue instruction of the function. In order to find out where the prologue ends,
111 LLVM looks for the first instruction in the function body that is linked to a source location. So,
112 when generating prologue instructions we have to make sure that we don't emit source location
113 information until the 'real' function body begins. For this reason, source location emission is
114 disabled by default for any new function being translated and is only activated after a call to the
115 third function from the list above, `start_emitting_source_locations()`. This function should be
116 called right before regularly starting to translate the top-level block of the given function.
118 There is one exception to the above rule: `llvm.dbg.declare` instruction must be linked to the
119 source location of the variable being declared. For function parameters these `llvm.dbg.declare`
120 instructions typically occur in the middle of the prologue, however, they are ignored by LLVM's
121 prologue detection. The `create_argument_metadata()` and related functions take care of linking the
122 `llvm.dbg.declare` instructions to the correct source locations even while source location emission
123 is still disabled, so there is no need to do anything special with source location handling here.
129 use driver::session::{FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
131 use lib::llvm::{ModuleRef, ContextRef, ValueRef};
132 use lib::llvm::debuginfo::*;
133 use middle::trans::adt;
134 use middle::trans::common::*;
135 use middle::trans::datum::{Datum, Lvalue};
136 use middle::trans::machine;
137 use middle::trans::type_of;
138 use middle::trans::type_::Type;
141 use middle::pat_util;
144 use std::c_str::{CString, ToCStr};
145 use std::cell::{Cell, RefCell};
146 use collections::HashMap;
147 use collections::HashSet;
148 use std::libc::{c_uint, c_ulonglong, c_longlong};
150 use std::sync::atomics;
152 use syntax::codemap::{Span, Pos};
153 use syntax::{abi, ast, codemap, ast_util, ast_map};
154 use syntax::owned_slice::OwnedSlice;
155 use syntax::parse::token;
156 use syntax::parse::token::special_idents;
158 static DW_LANG_RUST: c_uint = 0x9000;
160 static DW_TAG_auto_variable: c_uint = 0x100;
161 static DW_TAG_arg_variable: c_uint = 0x101;
163 static DW_ATE_boolean: c_uint = 0x02;
164 static DW_ATE_float: c_uint = 0x04;
165 static DW_ATE_signed: c_uint = 0x05;
166 // static DW_ATE_signed_char: c_uint = 0x06;
167 static DW_ATE_unsigned: c_uint = 0x07;
168 static DW_ATE_unsigned_char: c_uint = 0x08;
170 //=-------------------------------------------------------------------------------------------------
171 // Public Interface of debuginfo module
172 //=-------------------------------------------------------------------------------------------------
174 /// A context object for maintaining all state needed by the debuginfo module.
175 pub struct CrateDebugContext {
176 priv llcontext: ContextRef,
177 priv builder: DIBuilderRef,
178 priv current_debug_location: Cell<DebugLocation>,
179 priv created_files: RefCell<HashMap<~str, DIFile>>,
180 priv created_types: RefCell<HashMap<uint, DIType>>,
181 priv namespace_map: RefCell<HashMap<Vec<ast::Name> , @NamespaceTreeNode>>,
182 // This collection is used to assert that composite types (structs, enums, ...) have their
183 // members only set once:
184 priv composite_types_completed: RefCell<HashSet<DIType>>,
187 impl CrateDebugContext {
188 pub fn new(llmod: ModuleRef) -> CrateDebugContext {
189 debug!("CrateDebugContext::new");
190 let builder = unsafe { llvm::LLVMDIBuilderCreate(llmod) };
191 // DIBuilder inherits context from the module, so we'd better use the same one
192 let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
193 return CrateDebugContext {
194 llcontext: llcontext,
196 current_debug_location: Cell::new(UnknownLocation),
197 created_files: RefCell::new(HashMap::new()),
198 created_types: RefCell::new(HashMap::new()),
199 namespace_map: RefCell::new(HashMap::new()),
200 composite_types_completed: RefCell::new(HashSet::new()),
205 pub enum FunctionDebugContext {
206 priv FunctionDebugContext(~FunctionDebugContextData),
207 priv DebugInfoDisabled,
208 priv FunctionWithoutDebugInfo,
211 impl FunctionDebugContext {
212 fn get_ref<'a>(&'a self, cx: &CrateContext, span: Span) -> &'a FunctionDebugContextData {
214 FunctionDebugContext(~ref data) => data,
215 DebugInfoDisabled => {
216 cx.sess().span_bug(span, FunctionDebugContext::debuginfo_disabled_message());
218 FunctionWithoutDebugInfo => {
219 cx.sess().span_bug(span, FunctionDebugContext::should_be_ignored_message());
224 fn debuginfo_disabled_message() -> &'static str {
225 "debuginfo: Error trying to access FunctionDebugContext although debug info is disabled!"
228 fn should_be_ignored_message() -> &'static str {
229 "debuginfo: Error trying to access FunctionDebugContext for function that should be \
230 ignored by debug info!"
234 struct FunctionDebugContextData {
235 scope_map: RefCell<HashMap<ast::NodeId, DIScope>>,
236 fn_metadata: DISubprogram,
237 argument_counter: Cell<uint>,
238 source_locations_enabled: Cell<bool>,
241 enum VariableAccess<'a> {
242 // The llptr given is an alloca containing the variable's value
243 DirectVariable { alloca: ValueRef },
244 // The llptr given is an alloca containing the start of some pointer chain leading to the
245 // variable's content.
246 IndirectVariable { alloca: ValueRef, address_operations: &'a [ValueRef] }
250 ArgumentVariable(uint /*index*/),
255 /// Create any deferred debug metadata nodes
256 pub fn finalize(cx: &CrateContext) {
257 if cx.dbg_cx.is_none() {
262 compile_unit_metadata(cx);
264 llvm::LLVMDIBuilderFinalize(DIB(cx));
265 llvm::LLVMDIBuilderDispose(DIB(cx));
266 // Debuginfo generation in LLVM by default uses a higher
267 // version of dwarf than OS X currently understands. We can
268 // instruct LLVM to emit an older version of dwarf, however,
269 // for OS X to understand. For more info see #11352
270 // This can be overridden using --llvm-opts -dwarf-version,N.
271 if cx.sess().targ_cfg.os == abi::OsMacos {
272 "Dwarf Version".with_c_str(
273 |s| llvm::LLVMRustAddModuleFlag(cx.llmod, s, 2));
276 // Prevent bitcode readers from deleting the debug info.
277 "Debug Info Version".with_c_str(
278 |s| llvm::LLVMRustAddModuleFlag(cx.llmod, s,
279 llvm::LLVMRustDebugMetadataVersion));
283 /// Creates debug information for the given local variable.
285 /// Adds the created metadata nodes directly to the crate's IR.
286 pub fn create_local_var_metadata(bcx: &Block, local: &ast::Local) {
287 if fn_should_be_ignored(bcx.fcx) {
292 let def_map = cx.tcx.def_map;
294 pat_util::pat_bindings(def_map, local.pat, |_, node_id, span, path_ref| {
295 let var_ident = ast_util::path_to_ident(path_ref);
297 let datum = match bcx.fcx.lllocals.borrow().find_copy(&node_id) {
298 Some(datum) => datum,
300 bcx.sess().span_bug(span,
301 format!("no entry in lllocals table for {:?}",
306 let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
312 DirectVariable { alloca: datum.val },
318 /// Creates debug information for a variable captured in a closure.
320 /// Adds the created metadata nodes directly to the crate's IR.
321 pub fn create_captured_var_metadata(bcx: &Block,
322 node_id: ast::NodeId,
323 env_data_type: ty::t,
324 env_pointer: ValueRef,
326 closure_sigil: ast::Sigil,
328 if fn_should_be_ignored(bcx.fcx) {
334 let ast_item = cx.tcx.map.find(node_id);
336 let variable_ident = match ast_item {
338 cx.sess().span_bug(span, "debuginfo::create_captured_var_metadata: node not found");
340 Some(ast_map::NodeLocal(pat)) | Some(ast_map::NodeArg(pat)) => {
342 ast::PatIdent(_, ref path, _) => {
343 ast_util::path_to_ident(path)
349 "debuginfo::create_captured_var_metadata() - \
350 Captured var-id refers to unexpected \
351 ast_map variant: {:?}",
357 cx.sess().span_bug(span, format!("debuginfo::create_captured_var_metadata() - \
358 Captured var-id refers to unexpected ast_map variant: {:?}", ast_item));
362 let variable_type = node_id_type(bcx, node_id);
363 let scope_metadata = bcx.fcx.debug_context.get_ref(cx, span).fn_metadata;
365 let llvm_env_data_type = type_of::type_of(cx, env_data_type);
366 let byte_offset_of_var_in_env = machine::llelement_offset(cx, llvm_env_data_type, env_index);
368 let address_operations = unsafe {
369 [llvm::LLVMDIBuilderCreateOpDeref(Type::i64(cx).to_ref()),
370 llvm::LLVMDIBuilderCreateOpPlus(Type::i64(cx).to_ref()),
371 C_i64(cx, byte_offset_of_var_in_env as i64),
372 llvm::LLVMDIBuilderCreateOpDeref(Type::i64(cx).to_ref())]
375 let address_op_count = match closure_sigil {
376 ast::BorrowedSigil => {
377 address_operations.len()
379 ast::ManagedSigil | ast::OwnedSigil => {
380 address_operations.len() - 1
384 let variable_access = IndirectVariable {
386 address_operations: address_operations.slice_to(address_op_count)
398 /// Creates debug information for a local variable introduced in the head of a match-statement arm.
400 /// Adds the created metadata nodes directly to the crate's IR.
401 pub fn create_match_binding_metadata(bcx: &Block,
402 variable_ident: ast::Ident,
403 node_id: ast::NodeId,
405 datum: Datum<Lvalue>) {
406 if fn_should_be_ignored(bcx.fcx) {
410 let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
416 DirectVariable { alloca: datum.val },
421 /// Creates debug information for the given function argument.
423 /// Adds the created metadata nodes directly to the crate's IR.
424 pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
425 if fn_should_be_ignored(bcx.fcx) {
432 let def_map = cx.tcx.def_map;
433 let scope_metadata = bcx.fcx.debug_context.get_ref(cx, arg.pat.span).fn_metadata;
435 pat_util::pat_bindings(def_map, arg.pat, |_, node_id, span, path_ref| {
436 let llarg = match bcx.fcx.llargs.borrow().find_copy(&node_id) {
439 bcx.sess().span_bug(span,
440 format!("no entry in llargs table for {:?}",
445 if unsafe { llvm::LLVMIsAAllocaInst(llarg.val) } == ptr::null() {
446 cx.sess().span_bug(span, "debuginfo::create_argument_metadata() - \
447 Referenced variable location is not an alloca!");
450 let argument_ident = ast_util::path_to_ident(path_ref);
452 let argument_index = {
453 let counter = &fcx.debug_context.get_ref(cx, span).argument_counter;
454 let argument_index = counter.get();
455 counter.set(argument_index + 1);
463 DirectVariable { alloca: llarg.val },
464 ArgumentVariable(argument_index),
469 /// Sets the current debug location at the beginning of the span.
471 /// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...). The node_id parameter is used to
472 /// reliably find the correct visibility scope for the code position.
473 pub fn set_source_location(fcx: &FunctionContext,
474 node_id: ast::NodeId,
476 if fn_should_be_ignored(fcx) {
482 debug!("set_source_location: {}", cx.sess().codemap().span_to_str(span));
484 if fcx.debug_context.get_ref(cx, span).source_locations_enabled.get() {
485 let loc = span_start(cx, span);
486 let scope = scope_metadata(fcx, node_id, span);
488 set_debug_location(cx, DebugLocation::new(scope, loc.line, loc.col.to_uint()));
490 set_debug_location(cx, UnknownLocation);
494 /// Clears the current debug location.
496 /// Instructions generated hereafter won't be assigned a source location.
497 pub fn clear_source_location(fcx: &FunctionContext) {
498 if fn_should_be_ignored(fcx) {
502 set_debug_location(fcx.ccx, UnknownLocation);
505 /// Enables emitting source locations for the given functions.
507 /// Since we don't want source locations to be emitted for the function prelude, they are disabled
508 /// when beginning to translate a new function. This functions switches source location emitting on
509 /// and must therefore be called before the first real statement/expression of the function is
511 pub fn start_emitting_source_locations(fcx: &FunctionContext) {
512 match fcx.debug_context {
513 FunctionDebugContext(~ref data) => {
514 data.source_locations_enabled.set(true)
516 _ => { /* safe to ignore */ }
520 /// Creates the function-specific debug context.
522 /// Returns the FunctionDebugContext for the function which holds state needed for debug info
523 /// creation. The function may also return another variant of the FunctionDebugContext enum which
524 /// indicates why no debuginfo should be created for the function.
525 pub fn create_function_debug_context(cx: &CrateContext,
526 fn_ast_id: ast::NodeId,
527 param_substs: Option<@param_substs>,
528 llfn: ValueRef) -> FunctionDebugContext {
529 if cx.sess().opts.debuginfo == NoDebugInfo {
530 return DebugInfoDisabled;
534 return FunctionWithoutDebugInfo;
537 let empty_generics = ast::Generics { lifetimes: Vec::new(), ty_params: OwnedSlice::empty() };
539 let fnitem = cx.tcx.map.get(fn_ast_id);
541 let (ident, fn_decl, generics, top_level_block, span, has_path) = match fnitem {
542 ast_map::NodeItem(ref item) => {
544 ast::ItemFn(fn_decl, _, _, ref generics, top_level_block) => {
545 (item.ident, fn_decl, generics, top_level_block, item.span, true)
548 cx.sess().span_bug(item.span,
549 "create_function_debug_context: item bound to non-function");
553 ast_map::NodeMethod(method) => {
561 ast_map::NodeExpr(ref expr) => {
563 ast::ExprFnBlock(fn_decl, top_level_block) |
564 ast::ExprProc(fn_decl, top_level_block) => {
565 let name = format!("fn{}", token::gensym("fn"));
566 let name = token::str_to_ident(name);
568 // This is not quite right. It should actually inherit the generics of the
569 // enclosing function.
573 // Don't try to lookup the item path:
576 _ => cx.sess().span_bug(expr.span,
577 "create_function_debug_context: expected an expr_fn_block here")
580 ast_map::NodeTraitMethod(trait_method) => {
581 match *trait_method {
582 ast::Provided(method) => {
592 .bug(format!("create_function_debug_context: \
593 unexpected sort of node: {:?}",
598 ast_map::NodeForeignItem(..) |
599 ast_map::NodeVariant(..) |
600 ast_map::NodeStructCtor(..) => {
601 return FunctionWithoutDebugInfo;
603 _ => cx.sess().bug(format!("create_function_debug_context: \
604 unexpected sort of node: {:?}", fnitem))
607 // This can be the case for functions inlined from another crate
608 if span == codemap::DUMMY_SP {
609 return FunctionWithoutDebugInfo;
612 let loc = span_start(cx, span);
613 let file_metadata = file_metadata(cx, loc.file.name);
615 let function_type_metadata = unsafe {
616 let fn_signature = get_function_signature(cx, fn_ast_id, fn_decl, param_substs, span);
617 llvm::LLVMDIBuilderCreateSubroutineType(DIB(cx), file_metadata, fn_signature)
620 // get_template_parameters() will append a `<...>` clause to the function name if necessary.
621 let mut function_name = token::get_ident(ident).get().to_str();
622 let template_parameters = get_template_parameters(cx,
628 // There is no ast_map::Path for ast::ExprFnBlock-type functions. For now, just don't put them
629 // into a namespace. In the future this could be improved somehow (storing a path in the
630 // ast_map, or construct a path using the enclosing function).
631 let (linkage_name, containing_scope) = if has_path {
632 let namespace_node = namespace_for_item(cx, ast_util::local_def(fn_ast_id));
633 let linkage_name = namespace_node.mangled_name_of_contained_item(function_name);
634 let containing_scope = namespace_node.scope;
635 (linkage_name, containing_scope)
637 (function_name.clone(), file_metadata)
640 // Clang sets this parameter to the opening brace of the function's block, so let's do this too.
641 let scope_line = span_start(cx, top_level_block.span).line;
643 // The is_local_to_unit flag indicates whether a function is local to the current compilation
644 // unit (i.e. if it is *static* in the C-sense). The *reachable* set should provide a good
645 // approximation of this, as it contains everything that might leak out of the current crate
646 // (by being externally visible or by being inlined into something externally visible). It might
647 // better to use the `exported_items` set from `driver::CrateAnalysis` in the future, but (atm)
648 // this set is not available in the translation pass.
649 let is_local_to_unit = !cx.reachable.contains(&fn_ast_id);
651 let fn_metadata = function_name.with_c_str(|function_name| {
652 linkage_name.with_c_str(|linkage_name| {
654 llvm::LLVMDIBuilderCreateFunction(
661 function_type_metadata,
664 scope_line as c_uint,
665 FlagPrototyped as c_uint,
666 cx.sess().opts.optimize != session::No,
674 // Initialize fn debug context (including scope map and namespace map)
675 let fn_debug_context = ~FunctionDebugContextData {
676 scope_map: RefCell::new(HashMap::new()),
677 fn_metadata: fn_metadata,
678 argument_counter: Cell::new(1),
679 source_locations_enabled: Cell::new(false),
682 let arg_pats = fn_decl.inputs.map(|arg_ref| arg_ref.pat);
683 populate_scope_map(cx,
687 &mut *fn_debug_context.scope_map.borrow_mut());
689 // Clear the debug location so we don't assign them in the function prelude
690 set_debug_location(cx, UnknownLocation);
692 return FunctionDebugContext(fn_debug_context);
694 fn get_function_signature(cx: &CrateContext,
695 fn_ast_id: ast::NodeId,
696 fn_decl: &ast::FnDecl,
697 param_substs: Option<@param_substs>,
698 error_span: Span) -> DIArray {
699 if cx.sess().opts.debuginfo == LimitedDebugInfo {
700 return create_DIArray(DIB(cx), []);
703 let mut signature = slice::with_capacity(fn_decl.inputs.len() + 1);
705 // Return type -- llvm::DIBuilder wants this at index 0
706 match fn_decl.output.node {
708 signature.push(ptr::null());
711 assert_type_for_node_id(cx, fn_ast_id, error_span);
713 let return_type = ty::node_id_to_type(cx.tcx(), fn_ast_id);
714 let return_type = match param_substs {
717 ty::subst_tps(cx.tcx(),
718 substs.tys.as_slice(),
724 signature.push(type_metadata(cx, return_type, codemap::DUMMY_SP));
729 for arg in fn_decl.inputs.iter() {
730 assert_type_for_node_id(cx, arg.pat.id, arg.pat.span);
731 let arg_type = ty::node_id_to_type(cx.tcx(), arg.pat.id);
732 let arg_type = match param_substs {
735 ty::subst_tps(cx.tcx(),
736 substs.tys.as_slice(),
742 signature.push(type_metadata(cx, arg_type, codemap::DUMMY_SP));
745 return create_DIArray(DIB(cx), signature);
748 fn get_template_parameters(cx: &CrateContext,
749 generics: &ast::Generics,
750 param_substs: Option<@param_substs>,
751 file_metadata: DIFile,
752 name_to_append_suffix_to: &mut ~str)
754 let self_type = match param_substs {
755 Some(param_substs) => param_substs.self_ty,
759 // Only true for static default methods:
760 let has_self_type = self_type.is_some();
762 if !generics.is_type_parameterized() && !has_self_type {
763 return create_DIArray(DIB(cx), []);
766 name_to_append_suffix_to.push_char('<');
768 // The list to be filled with template parameters:
769 let mut template_params: Vec<DIDescriptor> =
770 Vec::with_capacity(generics.ty_params.len() + 1);
774 let actual_self_type = self_type.unwrap();
775 // Add self type name to <...> clause of function name
776 let actual_self_type_name = ppaux::ty_to_str(cx.tcx(), actual_self_type);
777 name_to_append_suffix_to.push_str(actual_self_type_name);
779 if generics.is_type_parameterized() {
780 name_to_append_suffix_to.push_str(",");
783 // Only create type information if full debuginfo is enabled
784 if cx.sess().opts.debuginfo == FullDebugInfo {
785 let actual_self_type_metadata = type_metadata(cx,
789 let ident = special_idents::type_self;
791 let param_metadata = token::get_ident(ident).get()
794 llvm::LLVMDIBuilderCreateTemplateTypeParameter(
798 actual_self_type_metadata,
805 template_params.push(param_metadata);
809 // Handle other generic parameters
810 let actual_types = match param_substs {
811 Some(param_substs) => ¶m_substs.tys,
813 return create_DIArray(DIB(cx), template_params.as_slice());
817 for (index, &ast::TyParam{ ident: ident, .. }) in generics.ty_params.iter().enumerate() {
818 let actual_type = *actual_types.get(index);
819 // Add actual type name to <...> clause of function name
820 let actual_type_name = ppaux::ty_to_str(cx.tcx(), actual_type);
821 name_to_append_suffix_to.push_str(actual_type_name);
823 if index != generics.ty_params.len() - 1 {
824 name_to_append_suffix_to.push_str(",");
827 // Again, only create type information if full debuginfo is enabled
828 if cx.sess().opts.debuginfo == FullDebugInfo {
829 let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP);
830 let param_metadata = token::get_ident(ident).get()
833 llvm::LLVMDIBuilderCreateTemplateTypeParameter(
837 actual_type_metadata,
843 template_params.push(param_metadata);
847 name_to_append_suffix_to.push_char('>');
849 return create_DIArray(DIB(cx), template_params.as_slice());
853 //=-------------------------------------------------------------------------------------------------
854 // Module-Internal debug info creation functions
855 //=-------------------------------------------------------------------------------------------------
857 fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
859 llvm::LLVMDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32)
863 fn compile_unit_metadata(cx: &CrateContext) {
864 let work_dir = &cx.sess().working_dir;
865 let compile_unit_name = match cx.sess().local_crate_source_file {
866 None => fallback_path(cx),
867 Some(ref abs_path) => {
868 if abs_path.is_relative() {
869 cx.sess().warn("debuginfo: Invalid path to crate's local root source file!");
872 match abs_path.path_relative_from(work_dir) {
873 Some(ref p) if p.is_relative() => {
874 // prepend "./" if necessary
875 let dotdot = bytes!("..");
876 let prefix = &[dotdot[0], ::std::path::SEP_BYTE];
877 let mut path_bytes = p.as_vec().to_owned();
879 if path_bytes.slice_to(2) != prefix &&
880 path_bytes.slice_to(2) != dotdot {
881 path_bytes.insert(0, prefix[0]);
882 path_bytes.insert(1, prefix[1]);
885 path_bytes.to_c_str()
887 _ => fallback_path(cx)
893 debug!("compile_unit_metadata: {:?}", compile_unit_name);
894 let producer = format!("rustc version {}", env!("CFG_VERSION"));
896 compile_unit_name.with_ref(|compile_unit_name| {
897 work_dir.as_vec().with_c_str(|work_dir| {
898 producer.with_c_str(|producer| {
899 "".with_c_str(|flags| {
900 "".with_c_str(|split_name| {
902 llvm::LLVMDIBuilderCreateCompileUnit(
903 debug_context(cx).builder,
908 cx.sess().opts.optimize != session::No,
919 fn fallback_path(cx: &CrateContext) -> CString {
920 cx.link_meta.crateid.name.to_c_str()
924 fn declare_local(bcx: &Block,
925 variable_ident: ast::Ident,
926 variable_type: ty::t,
927 scope_metadata: DIScope,
928 variable_access: VariableAccess,
929 variable_kind: VariableKind,
931 let cx: &CrateContext = bcx.ccx();
933 let filename = span_start(cx, span).file.name.clone();
934 let file_metadata = file_metadata(cx, filename);
936 let name = token::get_ident(variable_ident);
937 let loc = span_start(cx, span);
938 let type_metadata = type_metadata(cx, variable_type, span);
940 let (argument_index, dwarf_tag) = match variable_kind {
941 ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),
943 CapturedVariable => (0, DW_TAG_auto_variable)
946 let (var_alloca, var_metadata) = name.get().with_c_str(|name| {
947 match variable_access {
948 DirectVariable { alloca } => (
951 llvm::LLVMDIBuilderCreateLocalVariable(
959 cx.sess().opts.optimize != session::No,
964 IndirectVariable { alloca, address_operations } => (
967 llvm::LLVMDIBuilderCreateComplexVariable(
975 address_operations.as_ptr(),
976 address_operations.len() as c_uint,
983 set_debug_location(cx, DebugLocation::new(scope_metadata, loc.line, loc.col.to_uint()));
985 let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
991 llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr);
994 match variable_kind {
995 ArgumentVariable(_) | CapturedVariable => {
999 .source_locations_enabled
1001 set_debug_location(cx, UnknownLocation);
1003 _ => { /* nothing to do */ }
1007 fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
1008 match debug_context(cx).created_files.borrow().find_equiv(&full_path) {
1009 Some(file_metadata) => return *file_metadata,
1013 debug!("file_metadata: {}", full_path);
1015 // FIXME (#9639): This needs to handle non-utf8 paths
1016 let work_dir = cx.sess().working_dir.as_str().unwrap();
1018 if full_path.starts_with(work_dir) {
1019 full_path.slice(work_dir.len() + 1u, full_path.len())
1025 file_name.with_c_str(|file_name| {
1026 work_dir.with_c_str(|work_dir| {
1028 llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir)
1033 let mut created_files = debug_context(cx).created_files.borrow_mut();
1034 created_files.insert(full_path.to_owned(), file_metadata);
1035 return file_metadata;
1038 /// Finds the scope metadata node for the given AST node.
1039 fn scope_metadata(fcx: &FunctionContext,
1040 node_id: ast::NodeId,
1043 let scope_map = &fcx.debug_context.get_ref(fcx.ccx, span).scope_map;
1044 match scope_map.borrow().find_copy(&node_id) {
1045 Some(scope_metadata) => scope_metadata,
1047 let node = fcx.ccx.tcx.map.get(node_id);
1049 fcx.ccx.sess().span_bug(span,
1050 format!("debuginfo: Could not find scope info for node {:?}", node));
1055 fn basic_type_metadata(cx: &CrateContext, t: ty::t) -> DIType {
1057 debug!("basic_type_metadata: {:?}", ty::get(t));
1059 let (name, encoding) = match ty::get(t).sty {
1060 ty::ty_nil => (~"()", DW_ATE_unsigned),
1061 ty::ty_bot => (~"!", DW_ATE_unsigned),
1062 ty::ty_bool => (~"bool", DW_ATE_boolean),
1063 ty::ty_char => (~"char", DW_ATE_unsigned_char),
1064 ty::ty_int(int_ty) => match int_ty {
1065 ast::TyI => (~"int", DW_ATE_signed),
1066 ast::TyI8 => (~"i8", DW_ATE_signed),
1067 ast::TyI16 => (~"i16", DW_ATE_signed),
1068 ast::TyI32 => (~"i32", DW_ATE_signed),
1069 ast::TyI64 => (~"i64", DW_ATE_signed)
1071 ty::ty_uint(uint_ty) => match uint_ty {
1072 ast::TyU => (~"uint", DW_ATE_unsigned),
1073 ast::TyU8 => (~"u8", DW_ATE_unsigned),
1074 ast::TyU16 => (~"u16", DW_ATE_unsigned),
1075 ast::TyU32 => (~"u32", DW_ATE_unsigned),
1076 ast::TyU64 => (~"u64", DW_ATE_unsigned)
1078 ty::ty_float(float_ty) => match float_ty {
1079 ast::TyF32 => (~"f32", DW_ATE_float),
1080 ast::TyF64 => (~"f64", DW_ATE_float)
1082 _ => cx.sess().bug("debuginfo::basic_type_metadata - t is invalid type")
1085 let llvm_type = type_of::type_of(cx, t);
1086 let (size, align) = size_and_align_of(cx, llvm_type);
1087 let ty_metadata = name.with_c_str(|name| {
1089 llvm::LLVMDIBuilderCreateBasicType(
1092 bytes_to_bits(size),
1093 bytes_to_bits(align),
1101 fn pointer_type_metadata(cx: &CrateContext,
1102 pointer_type: ty::t,
1103 pointee_type_metadata: DIType)
1105 let pointer_llvm_type = type_of::type_of(cx, pointer_type);
1106 let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
1107 let name = ppaux::ty_to_str(cx.tcx(), pointer_type);
1108 let ptr_metadata = name.with_c_str(|name| {
1110 llvm::LLVMDIBuilderCreatePointerType(
1112 pointee_type_metadata,
1113 bytes_to_bits(pointer_size),
1114 bytes_to_bits(pointer_align),
1118 return ptr_metadata;
1121 enum MemberDescriptionFactory {
1122 StructMD(StructMemberDescriptionFactory),
1123 TupleMD(TupleMemberDescriptionFactory),
1124 GeneralMD(GeneralMemberDescriptionFactory),
1125 EnumVariantMD(EnumVariantMemberDescriptionFactory)
1128 impl MemberDescriptionFactory {
1129 fn create_member_descriptions(&self, cx: &CrateContext)
1130 -> Vec<MemberDescription> {
1132 StructMD(ref this) => {
1133 this.create_member_descriptions(cx)
1135 TupleMD(ref this) => {
1136 this.create_member_descriptions(cx)
1138 GeneralMD(ref this) => {
1139 this.create_member_descriptions(cx)
1141 EnumVariantMD(ref this) => {
1142 this.create_member_descriptions(cx)
1148 struct StructMemberDescriptionFactory {
1149 fields: Vec<ty::field> ,
1153 impl StructMemberDescriptionFactory {
1154 fn create_member_descriptions(&self, cx: &CrateContext)
1155 -> Vec<MemberDescription> {
1156 self.fields.map(|field| {
1157 let name = if field.ident.name == special_idents::unnamed_field.name {
1160 token::get_ident(field.ident).get().to_str()
1165 llvm_type: type_of::type_of(cx, field.mt.ty),
1166 type_metadata: type_metadata(cx, field.mt.ty, self.span),
1167 offset: ComputedMemberOffset,
1173 fn prepare_struct_metadata(cx: &CrateContext,
1176 substs: &ty::substs,
1178 -> RecursiveTypeDescription {
1179 let struct_name = ppaux::ty_to_str(cx.tcx(), struct_type);
1180 let struct_llvm_type = type_of::type_of(cx, struct_type);
1182 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id);
1184 let file_name = span_start(cx, definition_span).file.name.clone();
1185 let file_metadata = file_metadata(cx, file_name);
1187 let struct_metadata_stub = create_struct_stub(cx,
1194 let fields = ty::struct_fields(cx.tcx(), def_id, substs);
1196 UnfinishedMetadata {
1197 cache_id: cache_id_for_type(struct_type),
1198 metadata_stub: struct_metadata_stub,
1199 llvm_type: struct_llvm_type,
1200 file_metadata: file_metadata,
1201 member_description_factory: StructMD(StructMemberDescriptionFactory {
1208 enum RecursiveTypeDescription {
1209 UnfinishedMetadata {
1211 metadata_stub: DICompositeType,
1213 file_metadata: DIFile,
1214 member_description_factory: MemberDescriptionFactory,
1216 FinalMetadata(DICompositeType)
1219 impl RecursiveTypeDescription {
1221 fn finalize(&self, cx: &CrateContext) -> DICompositeType {
1223 FinalMetadata(metadata) => metadata,
1224 UnfinishedMetadata {
1229 ref member_description_factory
1231 // Insert the stub into the cache in order to allow recursive references ...
1232 debug_context(cx).created_types.borrow_mut()
1233 .insert(cache_id, metadata_stub);
1235 // ... then create the member descriptions ...
1236 let member_descriptions = member_description_factory.create_member_descriptions(cx);
1238 // ... and attach them to the stub to complete it.
1239 set_members_of_composite_type(cx,
1242 member_descriptions.as_slice(),
1245 return metadata_stub;
1251 struct TupleMemberDescriptionFactory {
1252 component_types: Vec<ty::t> ,
1256 impl TupleMemberDescriptionFactory {
1257 fn create_member_descriptions(&self, cx: &CrateContext)
1258 -> Vec<MemberDescription> {
1259 self.component_types.map(|&component_type| {
1262 llvm_type: type_of::type_of(cx, component_type),
1263 type_metadata: type_metadata(cx, component_type, self.span),
1264 offset: ComputedMemberOffset,
1270 fn prepare_tuple_metadata(cx: &CrateContext,
1272 component_types: &[ty::t],
1274 -> RecursiveTypeDescription {
1275 let tuple_name = ppaux::ty_to_str(cx.tcx(), tuple_type);
1276 let tuple_llvm_type = type_of::type_of(cx, tuple_type);
1278 let loc = span_start(cx, span);
1279 let file_metadata = file_metadata(cx, loc.file.name);
1281 UnfinishedMetadata {
1282 cache_id: cache_id_for_type(tuple_type),
1283 metadata_stub: create_struct_stub(cx,
1289 llvm_type: tuple_llvm_type,
1290 file_metadata: file_metadata,
1291 member_description_factory: TupleMD(TupleMemberDescriptionFactory {
1292 component_types: Vec::from_slice(component_types),
1298 struct GeneralMemberDescriptionFactory {
1299 type_rep: @adt::Repr,
1300 variants: @Vec<@ty::VariantInfo> ,
1301 discriminant_type_metadata: ValueRef,
1302 containing_scope: DIScope,
1303 file_metadata: DIFile,
1307 impl GeneralMemberDescriptionFactory {
1308 fn create_member_descriptions(&self, cx: &CrateContext)
1309 -> Vec<MemberDescription> {
1310 // Capture type_rep, so we don't have to copy the struct_defs array
1311 let struct_defs = match *self.type_rep {
1312 adt::General(_, ref struct_defs) => struct_defs,
1313 _ => cx.sess().bug("unreachable")
1319 .map(|(i, struct_def)| {
1320 let (variant_type_metadata, variant_llvm_type, member_desc_factory) =
1321 describe_enum_variant(cx,
1323 *self.variants.get(i),
1324 Some(self.discriminant_type_metadata),
1325 self.containing_scope,
1329 let member_descriptions =
1330 member_desc_factory.create_member_descriptions(cx);
1332 set_members_of_composite_type(cx,
1333 variant_type_metadata,
1335 member_descriptions.as_slice(),
1340 llvm_type: variant_llvm_type,
1341 type_metadata: variant_type_metadata,
1342 offset: FixedMemberOffset { bytes: 0 },
1348 struct EnumVariantMemberDescriptionFactory {
1349 args: Vec<(~str, ty::t)> ,
1350 discriminant_type_metadata: Option<DIType>,
1354 impl EnumVariantMemberDescriptionFactory {
1355 fn create_member_descriptions(&self, cx: &CrateContext)
1356 -> Vec<MemberDescription> {
1357 self.args.iter().enumerate().map(|(i, &(ref name, ty))| {
1359 name: name.to_str(),
1360 llvm_type: type_of::type_of(cx, ty),
1361 type_metadata: match self.discriminant_type_metadata {
1362 Some(metadata) if i == 0 => metadata,
1363 _ => type_metadata(cx, ty, self.span)
1365 offset: ComputedMemberOffset,
1371 fn describe_enum_variant(cx: &CrateContext,
1372 struct_def: &adt::Struct,
1373 variant_info: &ty::VariantInfo,
1374 discriminant_type_metadata: Option<DIType>,
1375 containing_scope: DIScope,
1376 file_metadata: DIFile,
1378 -> (DICompositeType, Type, MemberDescriptionFactory) {
1379 let variant_llvm_type =
1380 Type::struct_(cx, struct_def.fields
1381 .map(|&t| type_of::type_of(cx, t))
1384 // Could some consistency checks here: size, align, field count, discr type
1386 // Find the source code location of the variant's definition
1387 let variant_definition_span = if variant_info.id.krate == ast::LOCAL_CRATE {
1388 cx.tcx.map.span(variant_info.id.node)
1390 // For definitions from other crates we have no location information available.
1394 let metadata_stub = create_struct_stub(cx,
1396 token::get_ident(variant_info.name).get(),
1399 variant_definition_span);
1401 // Get the argument names from the enum variant info
1402 let mut arg_names = match variant_info.arg_names {
1403 Some(ref names) => {
1404 names.map(|ident| token::get_ident(*ident).get().to_str())
1406 None => variant_info.args.map(|_| ~"")
1409 // If this is not a univariant enum, there is also the (unnamed) discriminant field
1410 if discriminant_type_metadata.is_some() {
1411 arg_names.insert(0, ~"");
1414 // Build an array of (field name, field type) pairs to be captured in the factory closure.
1415 let args: Vec<(~str, ty::t)> = arg_names.iter()
1416 .zip(struct_def.fields.iter())
1417 .map(|(s, &t)| (s.to_str(), t))
1420 let member_description_factory =
1421 EnumVariantMD(EnumVariantMemberDescriptionFactory {
1423 discriminant_type_metadata: discriminant_type_metadata,
1427 (metadata_stub, variant_llvm_type, member_description_factory)
1430 fn prepare_enum_metadata(cx: &CrateContext,
1432 enum_def_id: ast::DefId,
1434 -> RecursiveTypeDescription {
1435 let enum_name = ppaux::ty_to_str(cx.tcx(), enum_type);
1437 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, enum_def_id);
1438 let loc = span_start(cx, definition_span);
1439 let file_metadata = file_metadata(cx, loc.file.name);
1441 // For empty enums there is an early exit. Just describe it as an empty struct with the
1442 // appropriate type name
1443 if ty::type_is_empty(cx.tcx(), enum_type) {
1444 let empty_type_metadata = composite_type_metadata(cx,
1452 return FinalMetadata(empty_type_metadata);
1455 let variants = ty::enum_variants(cx.tcx(), enum_def_id);
1457 let enumerators_metadata: Vec<DIDescriptor> = variants
1460 token::get_ident(v.name).get().with_c_str(|name| {
1462 llvm::LLVMDIBuilderCreateEnumerator(
1465 v.disr_val as c_ulonglong)
1471 let discriminant_type_metadata = |inttype| {
1472 let discriminant_llvm_type = adt::ll_inttype(cx, inttype);
1473 let (discriminant_size, discriminant_align) = size_and_align_of(cx, discriminant_llvm_type);
1474 let discriminant_base_type_metadata = type_metadata(cx, adt::ty_of_inttype(inttype),
1476 enum_name.with_c_str(|enum_name| {
1478 llvm::LLVMDIBuilderCreateEnumerationType(
1484 bytes_to_bits(discriminant_size),
1485 bytes_to_bits(discriminant_align),
1486 create_DIArray(DIB(cx), enumerators_metadata.as_slice()),
1487 discriminant_base_type_metadata)
1492 let type_rep = adt::represent_type(cx, enum_type);
1494 return match *type_rep {
1495 adt::CEnum(inttype, _, _) => {
1496 FinalMetadata(discriminant_type_metadata(inttype))
1498 adt::Univariant(ref struct_def, _) => {
1499 assert!(variants.len() == 1);
1502 member_description_factory) =
1503 describe_enum_variant(cx,
1510 UnfinishedMetadata {
1511 cache_id: cache_id_for_type(enum_type),
1512 metadata_stub: metadata_stub,
1513 llvm_type: variant_llvm_type,
1514 file_metadata: file_metadata,
1515 member_description_factory: member_description_factory
1518 adt::General(inttype, _) => {
1519 let discriminant_type_metadata = discriminant_type_metadata(inttype);
1520 let enum_llvm_type = type_of::type_of(cx, enum_type);
1521 let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type);
1522 let unique_id = generate_unique_type_id("DI_ENUM_");
1524 let enum_metadata = enum_name.with_c_str(|enum_name| {
1525 unique_id.with_c_str(|unique_id| {
1527 llvm::LLVMDIBuilderCreateUnionType(
1533 bytes_to_bits(enum_type_size),
1534 bytes_to_bits(enum_type_align),
1543 UnfinishedMetadata {
1544 cache_id: cache_id_for_type(enum_type),
1545 metadata_stub: enum_metadata,
1546 llvm_type: enum_llvm_type,
1547 file_metadata: file_metadata,
1548 member_description_factory: GeneralMD(GeneralMemberDescriptionFactory {
1551 discriminant_type_metadata: discriminant_type_metadata,
1552 containing_scope: containing_scope,
1553 file_metadata: file_metadata,
1558 adt::NullablePointer { nonnull: ref struct_def, nndiscr, .. } => {
1561 member_description_factory) =
1562 describe_enum_variant(cx,
1564 *variants.get(nndiscr as uint),
1569 UnfinishedMetadata {
1570 cache_id: cache_id_for_type(enum_type),
1571 metadata_stub: metadata_stub,
1572 llvm_type: variant_llvm_type,
1573 file_metadata: file_metadata,
1574 member_description_factory: member_description_factory
1581 FixedMemberOffset { bytes: uint },
1582 // For ComputedMemberOffset, the offset is read from the llvm type definition
1583 ComputedMemberOffset
1586 struct MemberDescription {
1589 type_metadata: DIType,
1590 offset: MemberOffset,
1593 /// Creates debug information for a composite type, that is, anything that results in a LLVM struct.
1595 /// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums.
1596 fn composite_type_metadata(cx: &CrateContext,
1597 composite_llvm_type: Type,
1598 composite_type_name: &str,
1599 member_descriptions: &[MemberDescription],
1600 containing_scope: DIScope,
1601 file_metadata: DIFile,
1602 definition_span: Span)
1603 -> DICompositeType {
1604 // Create the (empty) struct metadata node ...
1605 let composite_type_metadata = create_struct_stub(cx,
1606 composite_llvm_type,
1607 composite_type_name,
1612 // ... and immediately create and add the member descriptions.
1613 set_members_of_composite_type(cx,
1614 composite_type_metadata,
1615 composite_llvm_type,
1616 member_descriptions,
1620 return composite_type_metadata;
1623 fn set_members_of_composite_type(cx: &CrateContext,
1624 composite_type_metadata: DICompositeType,
1625 composite_llvm_type: Type,
1626 member_descriptions: &[MemberDescription],
1627 file_metadata: DIFile,
1628 definition_span: Span) {
1629 // In some rare cases LLVM metadata uniquing would lead to an existing type description being
1630 // used instead of a new one created in create_struct_stub. This would cause a hard to trace
1631 // assertion in DICompositeType::SetTypeArray(). The following check makes sure that we get a
1632 // better error message if this should happen again due to some regression.
1634 let mut composite_types_completed =
1635 debug_context(cx).composite_types_completed.borrow_mut();
1636 if composite_types_completed.contains(&composite_type_metadata) {
1637 cx.sess().span_bug(definition_span, "debuginfo::set_members_of_composite_type() - \
1638 Already completed forward declaration \
1641 composite_types_completed.insert(composite_type_metadata);
1645 let loc = span_start(cx, definition_span);
1647 let member_metadata: Vec<DIDescriptor> = member_descriptions
1650 .map(|(i, member_description)| {
1651 let (member_size, member_align) = size_and_align_of(cx, member_description.llvm_type);
1652 let member_offset = match member_description.offset {
1653 FixedMemberOffset { bytes } => bytes as u64,
1654 ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i)
1657 member_description.name.with_c_str(|member_name| {
1659 llvm::LLVMDIBuilderCreateMemberType(
1661 composite_type_metadata,
1665 bytes_to_bits(member_size),
1666 bytes_to_bits(member_align),
1667 bytes_to_bits(member_offset),
1669 member_description.type_metadata)
1676 let type_array = create_DIArray(DIB(cx), member_metadata.as_slice());
1677 llvm::LLVMDICompositeTypeSetTypeArray(composite_type_metadata, type_array);
1681 // A convenience wrapper around LLVMDIBuilderCreateStructType(). Does not do any caching, does not
1682 // add any fields to the struct. This can be done later with set_members_of_composite_type().
1683 fn create_struct_stub(cx: &CrateContext,
1684 struct_llvm_type: Type,
1685 struct_type_name: &str,
1686 containing_scope: DIScope,
1687 file_metadata: DIFile,
1688 definition_span: Span)
1689 -> DICompositeType {
1690 let loc = span_start(cx, definition_span);
1691 let (struct_size, struct_align) = size_and_align_of(cx, struct_llvm_type);
1693 // We assign unique IDs to the type stubs so LLVM metadata uniquing does not reuse instances
1694 // where we don't want it.
1695 let unique_id = generate_unique_type_id("DI_STRUCT_");
1698 struct_type_name.with_c_str(|name| {
1699 unique_id.with_c_str(|unique_id| {
1700 // LLVMDIBuilderCreateStructType() wants an empty array. A null pointer will lead to
1701 // hard to trace and debug LLVM assertions later on in llvm/lib/IR/Value.cpp
1702 let empty_array = create_DIArray(DIB(cx), []);
1704 llvm::LLVMDIBuilderCreateStructType(
1710 bytes_to_bits(struct_size),
1711 bytes_to_bits(struct_align),
1723 fn boxed_type_metadata(cx: &CrateContext,
1724 content_type_name: Option<&str>,
1725 content_llvm_type: Type,
1726 content_type_metadata: DIType,
1728 -> DICompositeType {
1729 let box_type_name = match content_type_name {
1730 Some(content_type_name) => format!("Boxed<{}>", content_type_name),
1731 None => ~"BoxedType"
1734 let box_llvm_type = Type::at_box(cx, content_llvm_type);
1735 let member_llvm_types = box_llvm_type.field_types();
1736 assert!(box_layout_is_correct(cx,
1737 member_llvm_types.as_slice(),
1738 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.get(0),
1748 type_metadata: type_metadata(cx, int_type, codemap::DUMMY_SP),
1749 offset: ComputedMemberOffset,
1753 llvm_type: *member_llvm_types.get(1),
1754 type_metadata: nil_pointer_type_metadata,
1755 offset: ComputedMemberOffset,
1759 llvm_type: *member_llvm_types.get(2),
1760 type_metadata: nil_pointer_type_metadata,
1761 offset: ComputedMemberOffset,
1765 llvm_type: *member_llvm_types.get(3),
1766 type_metadata: nil_pointer_type_metadata,
1767 offset: ComputedMemberOffset,
1771 llvm_type: *member_llvm_types.get(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] == Type::generic_glue_fn(cx).ptr_to() &&
1798 member_llvm_types[2] == Type::i8(cx).ptr_to() &&
1799 member_llvm_types[3] == Type::i8(cx).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, &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.get(0),
1859 type_metadata: int_type_metadata,
1860 offset: ComputedMemberOffset,
1864 llvm_type: *member_llvm_types.get(1),
1865 type_metadata: int_type_metadata,
1866 offset: ComputedMemberOffset,
1870 llvm_type: *member_llvm_types.get(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 composite_type_metadata(
1885 member_descriptions,
1891 fn vec_slice_metadata(cx: &CrateContext,
1893 element_type: ty::t,
1895 -> DICompositeType {
1897 debug!("vec_slice_metadata: {:?}", ty::get(vec_type));
1899 let slice_llvm_type = type_of::type_of(cx, vec_type);
1900 let slice_type_name = ppaux::ty_to_str(cx.tcx(), vec_type);
1902 let member_llvm_types = slice_llvm_type.field_types();
1903 assert!(slice_layout_is_correct(cx,
1904 member_llvm_types.as_slice(),
1907 let data_ptr_type = ty::mk_ptr(cx.tcx(), ty::mt {
1909 mutbl: ast::MutImmutable
1912 let member_descriptions = [
1915 llvm_type: *member_llvm_types.get(0),
1916 type_metadata: type_metadata(cx, data_ptr_type, span),
1917 offset: ComputedMemberOffset,
1921 llvm_type: *member_llvm_types.get(1),
1922 type_metadata: type_metadata(cx, ty::mk_uint(), span),
1923 offset: ComputedMemberOffset,
1927 assert!(member_descriptions.len() == member_llvm_types.len());
1929 let loc = span_start(cx, span);
1930 let file_metadata = file_metadata(cx, loc.file.name);
1932 return composite_type_metadata(
1936 member_descriptions,
1941 fn slice_layout_is_correct(cx: &CrateContext,
1942 member_llvm_types: &[Type],
1943 element_type: ty::t)
1945 member_llvm_types.len() == 2 &&
1946 member_llvm_types[0] == type_of::type_of(cx, element_type).ptr_to() &&
1947 member_llvm_types[1] == cx.int_type
1951 fn subroutine_type_metadata(cx: &CrateContext,
1952 signature: &ty::FnSig,
1954 -> DICompositeType {
1955 let loc = span_start(cx, span);
1956 let file_metadata = file_metadata(cx, loc.file.name);
1958 let mut signature_metadata: Vec<DIType> =
1959 Vec::with_capacity(signature.inputs.len() + 1);
1962 signature_metadata.push(match ty::get(signature.output).sty {
1963 ty::ty_nil => ptr::null(),
1964 _ => type_metadata(cx, signature.output, span)
1967 // regular arguments
1968 for &argument_type in signature.inputs.iter() {
1969 signature_metadata.push(type_metadata(cx, argument_type, span));
1973 llvm::LLVMDIBuilderCreateSubroutineType(
1976 create_DIArray(DIB(cx), signature_metadata.as_slice()))
1980 fn trait_metadata(cx: &CrateContext,
1983 substs: &ty::substs,
1984 trait_store: ty::TraitStore,
1985 mutability: ast::Mutability,
1986 _: &ty::BuiltinBounds)
1988 // The implementation provided here is a stub. It makes sure that the trait type is
1989 // assigned the correct name, size, namespace, and source location. But it does not describe
1990 // the trait's methods.
1991 let last = ty::with_path(cx.tcx(), def_id, |mut path| path.last().unwrap());
1992 let ident_string = token::get_name(last.name());
1993 let name = ppaux::trait_store_to_str(cx.tcx(), trait_store) +
1994 ppaux::mutability_to_str(mutability) +
1996 // Add type and region parameters
1997 let name = ppaux::parameterized(cx.tcx(), name, &substs.regions,
1998 substs.tps.as_slice(), def_id, true);
2000 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id);
2002 let file_name = span_start(cx, definition_span).file.name.clone();
2003 let file_metadata = file_metadata(cx, file_name);
2005 let trait_llvm_type = type_of::type_of(cx, trait_type);
2007 return composite_type_metadata(cx,
2016 fn type_metadata(cx: &CrateContext,
2018 usage_site_span: Span)
2020 let cache_id = cache_id_for_type(t);
2022 match debug_context(cx).created_types.borrow().find(&cache_id) {
2023 Some(type_metadata) => return *type_metadata,
2027 fn create_pointer_to_box_metadata(cx: &CrateContext,
2028 pointer_type: ty::t,
2031 let content_type_name: &str = ppaux::ty_to_str(cx.tcx(), type_in_box);
2032 let content_llvm_type = type_of::type_of(cx, type_in_box);
2033 let content_type_metadata = type_metadata(
2038 let box_metadata = boxed_type_metadata(
2040 Some(content_type_name),
2042 content_type_metadata,
2045 pointer_type_metadata(cx, pointer_type, box_metadata)
2048 debug!("type_metadata: {:?}", ty::get(t));
2050 let sty = &ty::get(t).sty;
2051 let type_metadata = match *sty {
2058 ty::ty_float(_) => {
2059 basic_type_metadata(cx, t)
2061 ty::ty_str(ref vstore) => {
2062 let i8_t = ty::mk_i8();
2064 ty::vstore_fixed(len) => {
2065 fixed_vec_metadata(cx, i8_t, len + 1, usage_site_span)
2067 ty::vstore_uniq => {
2068 let vec_metadata = vec_metadata(cx, i8_t, usage_site_span);
2069 pointer_type_metadata(cx, t, vec_metadata)
2071 ty::vstore_slice(_region) => {
2072 vec_slice_metadata(cx, t, i8_t, usage_site_span)
2076 ty::ty_enum(def_id, _) => {
2077 prepare_enum_metadata(cx, t, def_id, usage_site_span).finalize(cx)
2079 ty::ty_box(typ) => {
2080 create_pointer_to_box_metadata(cx, t, typ)
2082 ty::ty_vec(ref mt, ref vstore) => {
2084 ty::vstore_fixed(len) => {
2085 fixed_vec_metadata(cx, mt.ty, len, usage_site_span)
2087 ty::vstore_uniq => {
2088 let vec_metadata = vec_metadata(cx, mt.ty, usage_site_span);
2089 pointer_type_metadata(cx, t, vec_metadata)
2091 ty::vstore_slice(_) => {
2092 vec_slice_metadata(cx, t, mt.ty, usage_site_span)
2096 ty::ty_uniq(typ) => {
2097 let pointee = type_metadata(cx, typ, usage_site_span);
2098 pointer_type_metadata(cx, t, pointee)
2100 ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => {
2101 let pointee = type_metadata(cx, mt.ty, usage_site_span);
2102 pointer_type_metadata(cx, t, pointee)
2104 ty::ty_bare_fn(ref barefnty) => {
2105 subroutine_type_metadata(cx, &barefnty.sig, usage_site_span)
2107 ty::ty_closure(ref closurety) => {
2108 subroutine_type_metadata(cx, &closurety.sig, usage_site_span)
2110 ty::ty_trait(~ty::TyTrait { def_id, ref substs,
2111 store: trait_store, mutability,
2113 trait_metadata(cx, def_id, t, substs, trait_store, mutability, bounds)
2115 ty::ty_struct(def_id, ref substs) => {
2116 if ty::type_is_simd(cx.tcx(), t) {
2117 let element_type = ty::simd_type(cx.tcx(), t);
2118 let len = ty::simd_size(cx.tcx(), t);
2119 fixed_vec_metadata(cx, element_type, len, usage_site_span)
2121 prepare_struct_metadata(cx, t, def_id, substs, usage_site_span).finalize(cx)
2124 ty::ty_tup(ref elements) => {
2125 prepare_tuple_metadata(cx,
2127 elements.as_slice(),
2128 usage_site_span).finalize(cx)
2130 _ => cx.sess().bug(format!("debuginfo: unexpected type in type_metadata: {:?}", sty))
2133 debug_context(cx).created_types.borrow_mut().insert(cache_id, type_metadata);
2138 enum DebugLocation {
2139 KnownLocation { scope: DIScope, line: uint, col: uint },
2143 impl DebugLocation {
2144 fn new(scope: DIScope, line: uint, col: uint) -> DebugLocation {
2153 fn set_debug_location(cx: &CrateContext, debug_location: DebugLocation) {
2154 if debug_location == debug_context(cx).current_debug_location.get() {
2160 match debug_location {
2161 KnownLocation { scope, line, .. } => {
2162 let col = 0; // Always set the column to zero like Clang and GCC
2163 debug!("setting debug location to {} {}", line, col);
2164 let elements = [C_i32(cx, line as i32), C_i32(cx, col as i32), scope, ptr::null()];
2166 metadata_node = llvm::LLVMMDNodeInContext(debug_context(cx).llcontext,
2168 elements.len() as c_uint);
2171 UnknownLocation => {
2172 debug!("clearing debug location ");
2173 metadata_node = ptr::null();
2178 llvm::LLVMSetCurrentDebugLocation(cx.builder.b, metadata_node);
2181 debug_context(cx).current_debug_location.set(debug_location);
2184 //=-------------------------------------------------------------------------------------------------
2185 // Utility Functions
2186 //=-------------------------------------------------------------------------------------------------
2188 fn cache_id_for_type(t: ty::t) -> uint {
2192 // Used to avoid LLVM metadata uniquing problems. See `create_struct_stub()` and
2193 // `prepare_enum_metadata()`.
2194 fn generate_unique_type_id(prefix: &'static str) -> ~str {
2196 static mut unique_id_counter: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;
2197 format!("{}{}", prefix, unique_id_counter.fetch_add(1, atomics::SeqCst))
2201 /// Return codemap::Loc corresponding to the beginning of the span
2202 fn span_start(cx: &CrateContext, span: Span) -> codemap::Loc {
2203 cx.sess().codemap().lookup_char_pos(span.lo)
2206 fn size_and_align_of(cx: &CrateContext, llvm_type: Type) -> (u64, u64) {
2207 (machine::llsize_of_alloc(cx, llvm_type), machine::llalign_of_min(cx, llvm_type))
2210 fn bytes_to_bits(bytes: u64) -> c_ulonglong {
2211 (bytes * 8) as c_ulonglong
2215 fn debug_context<'a>(cx: &'a CrateContext) -> &'a CrateDebugContext {
2216 let debug_context: &'a CrateDebugContext = cx.dbg_cx.get_ref();
2221 fn DIB(cx: &CrateContext) -> DIBuilderRef {
2222 cx.dbg_cx.get_ref().builder
2225 fn fn_should_be_ignored(fcx: &FunctionContext) -> bool {
2226 match fcx.debug_context {
2227 FunctionDebugContext(_) => false,
2232 fn assert_type_for_node_id(cx: &CrateContext, node_id: ast::NodeId, error_span: Span) {
2233 if !cx.tcx.node_types.borrow().contains_key(&(node_id as uint)) {
2234 cx.sess().span_bug(error_span, "debuginfo: Could not find type for node id!");
2238 fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: ast::DefId)
2239 -> (DIScope, Span) {
2240 let containing_scope = namespace_for_item(cx, def_id).scope;
2241 let definition_span = if def_id.krate == ast::LOCAL_CRATE {
2242 cx.tcx.map.span(def_id.node)
2244 // For external items there is no span information
2248 (containing_scope, definition_span)
2251 // This procedure builds the *scope map* for a given function, which maps any given ast::NodeId in
2252 // the function's AST to the correct DIScope metadata instance.
2254 // This builder procedure walks the AST in execution order and keeps track of what belongs to which
2255 // scope, creating DIScope DIEs along the way, and introducing *artificial* lexical scope
2256 // descriptors where necessary. These artificial scopes allow GDB to correctly handle name
2258 fn populate_scope_map(cx: &CrateContext,
2259 arg_pats: &[@ast::Pat],
2260 fn_entry_block: &ast::Block,
2261 fn_metadata: DISubprogram,
2262 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2263 let def_map = cx.tcx.def_map;
2265 struct ScopeStackEntry {
2266 scope_metadata: DIScope,
2267 ident: Option<ast::Ident>
2270 let mut scope_stack = vec!(ScopeStackEntry { scope_metadata: fn_metadata, ident: None });
2272 // Push argument identifiers onto the stack so arguments integrate nicely with variable
2274 for &arg_pat in arg_pats.iter() {
2275 pat_util::pat_bindings(def_map, arg_pat, |_, _, _, path_ref| {
2276 let ident = ast_util::path_to_ident(path_ref);
2277 scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata, ident: Some(ident) });
2281 // Clang creates a separate scope for function bodies, so let's do this too
2283 fn_entry_block.span,
2286 |cx, scope_stack, scope_map| {
2287 walk_block(cx, fn_entry_block, scope_stack, scope_map);
2290 // local helper functions for walking the AST.
2291 fn with_new_scope(cx: &CrateContext,
2293 scope_stack: &mut Vec<ScopeStackEntry> ,
2294 scope_map: &mut HashMap<ast::NodeId, DIScope>,
2295 inner_walk: |&CrateContext,
2296 &mut Vec<ScopeStackEntry> ,
2297 &mut HashMap<ast::NodeId, DIScope>|) {
2298 // Create a new lexical scope and push it onto the stack
2299 let loc = cx.sess().codemap().lookup_char_pos(scope_span.lo);
2300 let file_metadata = file_metadata(cx, loc.file.name);
2301 let parent_scope = scope_stack.last().unwrap().scope_metadata;
2303 let scope_metadata = unsafe {
2304 llvm::LLVMDIBuilderCreateLexicalBlock(
2309 loc.col.to_uint() as c_uint)
2312 scope_stack.push(ScopeStackEntry { scope_metadata: scope_metadata, ident: None });
2314 inner_walk(cx, scope_stack, scope_map);
2316 // pop artificial scopes
2317 while scope_stack.last().unwrap().ident.is_some() {
2321 if scope_stack.last().unwrap().scope_metadata != scope_metadata {
2322 cx.sess().span_bug(scope_span, "debuginfo: Inconsistency in scope management.");
2328 fn walk_block(cx: &CrateContext,
2330 scope_stack: &mut Vec<ScopeStackEntry> ,
2331 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2332 scope_map.insert(block.id, scope_stack.last().unwrap().scope_metadata);
2334 // The interesting things here are statements and the concluding expression.
2335 for statement in block.stmts.iter() {
2336 scope_map.insert(ast_util::stmt_id(*statement),
2337 scope_stack.last().unwrap().scope_metadata);
2339 match statement.node {
2340 ast::StmtDecl(decl, _) => walk_decl(cx, decl, scope_stack, scope_map),
2341 ast::StmtExpr(exp, _) |
2342 ast::StmtSemi(exp, _) => walk_expr(cx, exp, scope_stack, scope_map),
2343 ast::StmtMac(..) => () // ignore macros (which should be expanded anyway)
2347 for exp in block.expr.iter() {
2348 walk_expr(cx, *exp, scope_stack, scope_map);
2352 fn walk_decl(cx: &CrateContext,
2354 scope_stack: &mut Vec<ScopeStackEntry> ,
2355 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2357 codemap::Spanned { node: ast::DeclLocal(local), .. } => {
2358 scope_map.insert(local.id, scope_stack.last().unwrap().scope_metadata);
2360 walk_pattern(cx, local.pat, scope_stack, scope_map);
2362 for exp in local.init.iter() {
2363 walk_expr(cx, *exp, scope_stack, scope_map);
2370 fn walk_pattern(cx: &CrateContext,
2372 scope_stack: &mut Vec<ScopeStackEntry> ,
2373 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2375 let def_map = cx.tcx.def_map;
2377 // Unfortunately, we cannot just use pat_util::pat_bindings() or ast_util::walk_pat() here
2378 // because we have to visit *all* nodes in order to put them into the scope map. The above
2379 // functions don't do that.
2381 ast::PatIdent(_, ref path_ref, ref sub_pat_opt) => {
2383 // Check if this is a binding. If so we need to put it on the scope stack and maybe
2384 // introduce an articial scope
2385 if pat_util::pat_is_binding(def_map, pat) {
2387 let ident = ast_util::path_to_ident(path_ref);
2389 // LLVM does not properly generate 'DW_AT_start_scope' fields for variable DIEs.
2390 // For this reason we have to introduce an artificial scope at bindings whenever
2391 // a variable with the same name is declared in *any* parent scope.
2393 // Otherwise the following error occurs:
2397 // do_something(); // 'gdb print x' correctly prints 10
2400 // do_something(); // 'gdb print x' prints 0, because it already reads the
2401 // // uninitialized 'x' from the next line...
2403 // do_something(); // 'gdb print x' correctly prints 100
2406 // Is there already a binding with that name?
2407 // N.B.: this comparison must be UNhygienic... because
2408 // gdb knows nothing about the context, so any two
2409 // variables with the same name will cause the problem.
2410 let need_new_scope = scope_stack
2412 .any(|entry| entry.ident.iter().any(|i| i.name == ident.name));
2415 // Create a new lexical scope and push it onto the stack
2416 let loc = cx.sess().codemap().lookup_char_pos(pat.span.lo);
2417 let file_metadata = file_metadata(cx, loc.file.name);
2418 let parent_scope = scope_stack.last().unwrap().scope_metadata;
2420 let scope_metadata = unsafe {
2421 llvm::LLVMDIBuilderCreateLexicalBlock(
2426 loc.col.to_uint() as c_uint)
2429 scope_stack.push(ScopeStackEntry {
2430 scope_metadata: scope_metadata,
2435 // Push a new entry anyway so the name can be found
2436 let prev_metadata = scope_stack.last().unwrap().scope_metadata;
2437 scope_stack.push(ScopeStackEntry {
2438 scope_metadata: prev_metadata,
2444 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2446 for &sub_pat in sub_pat_opt.iter() {
2447 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2451 ast::PatWild | ast::PatWildMulti => {
2452 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2455 ast::PatEnum(_, ref sub_pats_opt) => {
2456 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2458 for ref sub_pats in sub_pats_opt.iter() {
2459 for &p in sub_pats.iter() {
2460 walk_pattern(cx, p, scope_stack, scope_map);
2465 ast::PatStruct(_, ref field_pats, _) => {
2466 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2468 for &ast::FieldPat { pat: sub_pat, .. } in field_pats.iter() {
2469 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2473 ast::PatTup(ref sub_pats) => {
2474 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2476 for &sub_pat in sub_pats.iter() {
2477 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2481 ast::PatUniq(sub_pat) | ast::PatRegion(sub_pat) => {
2482 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2483 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2486 ast::PatLit(exp) => {
2487 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2488 walk_expr(cx, exp, scope_stack, scope_map);
2491 ast::PatRange(exp1, exp2) => {
2492 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2493 walk_expr(cx, exp1, scope_stack, scope_map);
2494 walk_expr(cx, exp2, scope_stack, scope_map);
2497 ast::PatVec(ref front_sub_pats, ref middle_sub_pats, ref back_sub_pats) => {
2498 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2500 for &sub_pat in front_sub_pats.iter() {
2501 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2504 for &sub_pat in middle_sub_pats.iter() {
2505 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2508 for &sub_pat in back_sub_pats.iter() {
2509 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2515 fn walk_expr(cx: &CrateContext,
2517 scope_stack: &mut Vec<ScopeStackEntry> ,
2518 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2520 scope_map.insert(exp.id, scope_stack.last().unwrap().scope_metadata);
2526 ast::ExprPath(_) => {}
2528 ast::ExprVstore(sub_exp, _) |
2529 ast::ExprCast(sub_exp, _) |
2530 ast::ExprAddrOf(_, sub_exp) |
2531 ast::ExprField(sub_exp, _, _) |
2532 ast::ExprParen(sub_exp) => walk_expr(cx, sub_exp, scope_stack, scope_map),
2534 ast::ExprBox(place, sub_expr) => {
2535 walk_expr(cx, place, scope_stack, scope_map);
2536 walk_expr(cx, sub_expr, scope_stack, scope_map);
2539 ast::ExprRet(exp_opt) => match exp_opt {
2540 Some(sub_exp) => walk_expr(cx, sub_exp, scope_stack, scope_map),
2544 ast::ExprUnary(_, sub_exp) => {
2545 walk_expr(cx, sub_exp, scope_stack, scope_map);
2548 ast::ExprAssignOp(_, lhs, rhs) |
2549 ast::ExprIndex(lhs, rhs) |
2550 ast::ExprBinary(_, lhs, rhs) => {
2551 walk_expr(cx, lhs, scope_stack, scope_map);
2552 walk_expr(cx, rhs, scope_stack, scope_map);
2555 ast::ExprVec(ref init_expressions, _) |
2556 ast::ExprTup(ref init_expressions) => {
2557 for ie in init_expressions.iter() {
2558 walk_expr(cx, *ie, scope_stack, scope_map);
2562 ast::ExprAssign(sub_exp1, sub_exp2) |
2563 ast::ExprRepeat(sub_exp1, sub_exp2, _) => {
2564 walk_expr(cx, sub_exp1, scope_stack, scope_map);
2565 walk_expr(cx, sub_exp2, scope_stack, scope_map);
2568 ast::ExprIf(cond_exp, then_block, ref opt_else_exp) => {
2569 walk_expr(cx, cond_exp, scope_stack, scope_map);
2575 |cx, scope_stack, scope_map| {
2576 walk_block(cx, then_block, scope_stack, scope_map);
2579 match *opt_else_exp {
2580 Some(else_exp) => walk_expr(cx, else_exp, scope_stack, scope_map),
2585 ast::ExprWhile(cond_exp, loop_body) => {
2586 walk_expr(cx, cond_exp, scope_stack, scope_map);
2592 |cx, scope_stack, scope_map| {
2593 walk_block(cx, loop_body, scope_stack, scope_map);
2597 ast::ExprForLoop(_, _, _, _) => {
2598 cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \
2599 Found unexpanded for-loop.");
2602 ast::ExprMac(_) => {
2603 cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \
2604 Found unexpanded macro.");
2607 ast::ExprLoop(block, _) |
2608 ast::ExprBlock(block) => {
2613 |cx, scope_stack, scope_map| {
2614 walk_block(cx, block, scope_stack, scope_map);
2618 ast::ExprFnBlock(decl, block) |
2619 ast::ExprProc(decl, block) => {
2624 |cx, scope_stack, scope_map| {
2625 for &ast::Arg { pat: pattern, .. } in decl.inputs.iter() {
2626 walk_pattern(cx, pattern, scope_stack, scope_map);
2629 walk_block(cx, block, scope_stack, scope_map);
2633 ast::ExprCall(fn_exp, ref args) => {
2634 walk_expr(cx, fn_exp, scope_stack, scope_map);
2636 for arg_exp in args.iter() {
2637 walk_expr(cx, *arg_exp, scope_stack, scope_map);
2641 ast::ExprMethodCall(_, _, ref args) => {
2642 for arg_exp in args.iter() {
2643 walk_expr(cx, *arg_exp, scope_stack, scope_map);
2647 ast::ExprMatch(discriminant_exp, ref arms) => {
2648 walk_expr(cx, discriminant_exp, scope_stack, scope_map);
2650 // for each arm we have to first walk the pattern as these might introduce new
2651 // artificial scopes. It should be sufficient to walk only one pattern per arm, as
2652 // they all must contain the same binding names
2654 for arm_ref in arms.iter() {
2655 let arm_span = arm_ref.pats.get(0).span;
2661 |cx, scope_stack, scope_map| {
2662 for &pat in arm_ref.pats.iter() {
2663 walk_pattern(cx, pat, scope_stack, scope_map);
2666 for guard_exp in arm_ref.guard.iter() {
2667 walk_expr(cx, *guard_exp, scope_stack, scope_map)
2670 walk_expr(cx, arm_ref.body, scope_stack, scope_map);
2675 ast::ExprStruct(_, ref fields, ref base_exp) => {
2676 for &ast::Field { expr: exp, .. } in fields.iter() {
2677 walk_expr(cx, exp, scope_stack, scope_map);
2681 Some(exp) => walk_expr(cx, exp, scope_stack, scope_map),
2686 ast::ExprInlineAsm(ast::InlineAsm { inputs: ref inputs,
2687 outputs: ref outputs,
2689 // inputs, outputs: ~[(~str, @expr)]
2690 for &(_, exp) in inputs.iter() {
2691 walk_expr(cx, exp, scope_stack, scope_map);
2694 for &(_, exp) in outputs.iter() {
2695 walk_expr(cx, exp, scope_stack, scope_map);
2703 //=-------------------------------------------------------------------------------------------------
2704 // Namespace Handling
2705 //=-------------------------------------------------------------------------------------------------
2707 struct NamespaceTreeNode {
2710 parent: Option<@NamespaceTreeNode>,
2713 impl NamespaceTreeNode {
2714 fn mangled_name_of_contained_item(&self, item_name: &str) -> ~str {
2715 fn fill_nested(node: &NamespaceTreeNode, output: &mut ~str) {
2717 Some(parent) => fill_nested(parent, output),
2720 let string = token::get_name(node.name);
2721 output.push_str(format!("{}", string.get().len()));
2722 output.push_str(string.get());
2725 let mut name = ~"_ZN";
2726 fill_nested(self, &mut name);
2727 name.push_str(format!("{}", item_name.len()));
2728 name.push_str(item_name);
2729 name.push_char('E');
2734 fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> @NamespaceTreeNode {
2735 ty::with_path(cx.tcx(), def_id, |path| {
2736 // prepend crate name if not already present
2737 let krate = if def_id.krate == ast::LOCAL_CRATE {
2738 let crate_namespace_ident = token::str_to_ident(cx.link_meta.crateid.name);
2739 Some(ast_map::PathMod(crate_namespace_ident.name))
2743 let mut path = krate.move_iter().chain(path).peekable();
2745 let mut current_key = Vec::new();
2746 let mut parent_node: Option<@NamespaceTreeNode> = None;
2748 // Create/Lookup namespace for each element of the path.
2750 // Emulate a for loop so we can use peek below.
2751 let path_element = match path.next() {
2755 // Ignore the name of the item (the last path element).
2756 if path.peek().is_none() {
2760 let name = path_element.name();
2761 current_key.push(name);
2763 let existing_node = debug_context(cx).namespace_map.borrow()
2764 .find_copy(¤t_key);
2765 let current_node = match existing_node {
2766 Some(existing_node) => existing_node,
2768 // create and insert
2769 let parent_scope = match parent_node {
2770 Some(node) => node.scope,
2773 let namespace_name = token::get_name(name);
2774 let scope = namespace_name.get().with_c_str(|namespace_name| {
2776 llvm::LLVMDIBuilderCreateNameSpace(
2780 // cannot reconstruct file ...
2782 // ... or line information, but that's not so important.
2787 let node = @NamespaceTreeNode {
2790 parent: parent_node,
2793 debug_context(cx).namespace_map.borrow_mut()
2794 .insert(current_key.clone(), node);
2800 parent_node = Some(current_node);
2806 cx.sess().bug(format!("debuginfo::namespace_for_item(): \
2807 path too short for {:?}", def_id));