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 function_name_string = token::get_ident(ident.name);
626 let mut function_name = function_name_string.get().to_owned();
627 let template_parameters = get_template_parameters(cx,
633 // There is no ast_map::Path for ast::ExprFnBlock-type functions. For now, just don't put them
634 // into a namespace. In the future this could be improved somehow (storing a path in the
635 // ast_map, or construct a path using the enclosing function).
636 let (linkage_name, containing_scope) = if has_path {
637 let namespace_node = namespace_for_item(cx, ast_util::local_def(fn_ast_id), span);
638 let linkage_name = namespace_node.mangled_name_of_contained_item(function_name);
639 let containing_scope = namespace_node.scope;
640 (linkage_name, containing_scope)
642 (function_name.clone(), file_metadata)
645 // Clang sets this parameter to the opening brace of the function's block, so let's do this too.
646 let scope_line = span_start(cx, top_level_block.span).line;
648 // The is_local_to_unit flag indicates whether a function is local to the current compilation
649 // unit (i.e. if it is *static* in the C-sense). The *reachable* set should provide a good
650 // approximation of this, as it contains everything that might leak out of the current crate
651 // (by being externally visible or by being inlined into something externally visible). It might
652 // better to use the `exported_items` set from `driver::CrateAnalysis` in the future, but (atm)
653 // this set is not available in the translation pass.
654 let is_local_to_unit = {
655 let reachable = cx.reachable.borrow();
656 !reachable.get().contains(&fn_ast_id)
659 let fn_metadata = function_name.with_c_str(|function_name| {
660 linkage_name.with_c_str(|linkage_name| {
662 llvm::LLVMDIBuilderCreateFunction(
669 function_type_metadata,
672 scope_line as c_uint,
673 FlagPrototyped as c_uint,
674 cx.sess.opts.optimize != session::No,
682 // Initialize fn debug context (including scope map and namespace map)
683 let fn_debug_context = ~FunctionDebugContextData {
684 scope_map: RefCell::new(HashMap::new()),
685 fn_metadata: fn_metadata,
686 argument_counter: Cell::new(1),
687 source_locations_enabled: Cell::new(false),
690 let arg_pats = fn_decl.inputs.map(|arg_ref| arg_ref.pat);
692 let mut scope_map = fn_debug_context.scope_map.borrow_mut();
693 populate_scope_map(cx,
700 // Clear the debug location so we don't assign them in the function prelude
701 set_debug_location(cx, UnknownLocation);
703 return FunctionDebugContext(fn_debug_context);
705 fn get_function_signature(cx: &CrateContext,
706 fn_ast_id: ast::NodeId,
707 fn_decl: &ast::FnDecl,
708 param_substs: Option<@param_substs>,
709 error_span: Span) -> DIArray {
710 if !cx.sess.opts.extra_debuginfo {
711 return create_DIArray(DIB(cx), []);
714 let mut signature = vec::with_capacity(fn_decl.inputs.len() + 1);
716 // Return type -- llvm::DIBuilder wants this at index 0
717 match fn_decl.output.node {
719 signature.push(ptr::null());
722 assert_type_for_node_id(cx, fn_ast_id, error_span);
724 let return_type = ty::node_id_to_type(cx.tcx, fn_ast_id);
725 let return_type = match param_substs {
728 ty::subst_tps(cx.tcx, substs.tys, substs.self_ty, return_type)
732 signature.push(type_metadata(cx, return_type, codemap::DUMMY_SP));
737 for arg in fn_decl.inputs.iter() {
738 assert_type_for_node_id(cx, arg.pat.id, arg.pat.span);
739 let arg_type = ty::node_id_to_type(cx.tcx, arg.pat.id);
740 let arg_type = match param_substs {
743 ty::subst_tps(cx.tcx, substs.tys, substs.self_ty, arg_type)
747 signature.push(type_metadata(cx, arg_type, codemap::DUMMY_SP));
750 return create_DIArray(DIB(cx), signature);
753 fn get_template_parameters(cx: &CrateContext,
754 generics: &ast::Generics,
755 param_substs: Option<@param_substs>,
756 file_metadata: DIFile,
757 name_to_append_suffix_to: &mut ~str)
759 let self_type = match param_substs {
760 Some(param_substs) => param_substs.self_ty,
764 // Only true for static default methods:
765 let has_self_type = self_type.is_some();
767 if !generics.is_type_parameterized() && !has_self_type {
768 return create_DIArray(DIB(cx), []);
771 name_to_append_suffix_to.push_char('<');
773 // The list to be filled with template parameters:
774 let mut template_params: ~[DIDescriptor] = vec::with_capacity(generics.ty_params.len() + 1);
778 let actual_self_type = self_type.unwrap();
779 // Add self type name to <...> clause of function name
780 let actual_self_type_name = ppaux::ty_to_str(cx.tcx, actual_self_type);
781 name_to_append_suffix_to.push_str(actual_self_type_name);
783 if generics.is_type_parameterized() {
784 name_to_append_suffix_to.push_str(",");
787 // Only create type information if extra_debuginfo is enabled
788 if cx.sess.opts.extra_debuginfo {
789 let actual_self_type_metadata = type_metadata(cx,
793 let ident = special_idents::type_self;
795 let param_metadata_string = token::get_ident(ident.name);
796 let param_metadata = param_metadata_string.get()
799 llvm::LLVMDIBuilderCreateTemplateTypeParameter(
803 actual_self_type_metadata,
810 template_params.push(param_metadata);
814 // Handle other generic parameters
815 let actual_types = match param_substs {
816 Some(param_substs) => ¶m_substs.tys,
818 return create_DIArray(DIB(cx), template_params);
822 for (index, &ast::TyParam{ ident: ident, .. }) in generics.ty_params.iter().enumerate() {
823 let actual_type = actual_types[index];
824 // Add actual type name to <...> clause of function name
825 let actual_type_name = ppaux::ty_to_str(cx.tcx, actual_type);
826 name_to_append_suffix_to.push_str(actual_type_name);
828 if index != generics.ty_params.len() - 1 {
829 name_to_append_suffix_to.push_str(",");
832 // Again, only create type information if extra_debuginfo is enabled
833 if cx.sess.opts.extra_debuginfo {
834 let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP);
835 let param_metadata_string = token::get_ident(ident.name);
836 let param_metadata = param_metadata_string.get()
839 llvm::LLVMDIBuilderCreateTemplateTypeParameter(
843 actual_type_metadata,
849 template_params.push(param_metadata);
853 name_to_append_suffix_to.push_char('>');
855 return create_DIArray(DIB(cx), template_params);
859 //=-------------------------------------------------------------------------------------------------
860 // Module-Internal debug info creation functions
861 //=-------------------------------------------------------------------------------------------------
863 fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
865 llvm::LLVMDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32)
869 fn compile_unit_metadata(cx: &CrateContext) {
870 let work_dir = &cx.sess.working_dir;
871 let compile_unit_name = match cx.sess.local_crate_source_file {
872 None => fallback_path(cx),
873 Some(ref abs_path) => {
874 if abs_path.is_relative() {
875 cx.sess.warn("debuginfo: Invalid path to crate's local root source file!");
878 match abs_path.path_relative_from(work_dir) {
879 Some(ref p) if p.is_relative() => {
880 // prepend "./" if necessary
881 let dotdot = bytes!("..");
882 let prefix = &[dotdot[0], ::std::path::SEP_BYTE];
883 let mut path_bytes = p.as_vec().to_owned();
885 if path_bytes.slice_to(2) != prefix &&
886 path_bytes.slice_to(2) != dotdot {
887 path_bytes.insert(0, prefix[0]);
888 path_bytes.insert(1, prefix[1]);
891 path_bytes.to_c_str()
893 _ => fallback_path(cx)
899 debug!("compile_unit_metadata: {:?}", compile_unit_name);
900 let producer = format!("rustc version {}", env!("CFG_VERSION"));
902 compile_unit_name.with_ref(|compile_unit_name| {
903 work_dir.as_vec().with_c_str(|work_dir| {
904 producer.with_c_str(|producer| {
905 "".with_c_str(|flags| {
906 "".with_c_str(|split_name| {
908 llvm::LLVMDIBuilderCreateCompileUnit(
909 debug_context(cx).builder,
914 cx.sess.opts.optimize != session::No,
925 fn fallback_path(cx: &CrateContext) -> CString {
926 cx.link_meta.crateid.name.to_c_str()
930 fn declare_local(bcx: &Block,
931 variable_ident: ast::Ident,
932 variable_type: ty::t,
933 scope_metadata: DIScope,
934 variable_access: VariableAccess,
935 variable_kind: VariableKind,
937 let cx: &CrateContext = bcx.ccx();
939 let filename = span_start(cx, span).file.name.clone();
940 let file_metadata = file_metadata(cx, filename);
942 let variable_ident_string = token::get_ident(variable_ident.name);
943 let name: &str = variable_ident_string.get();
944 let loc = span_start(cx, span);
945 let type_metadata = type_metadata(cx, variable_type, span);
947 let (argument_index, dwarf_tag) = match variable_kind {
948 ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),
950 CapturedVariable => (0, DW_TAG_auto_variable)
953 let (var_alloca, var_metadata) = name.with_c_str(|name| {
954 match variable_access {
955 DirectVariable { alloca } => (
958 llvm::LLVMDIBuilderCreateLocalVariable(
966 cx.sess.opts.optimize != session::No,
971 IndirectVariable { alloca, address_operations } => (
974 llvm::LLVMDIBuilderCreateComplexVariable(
982 address_operations.as_ptr(),
983 address_operations.len() as c_uint,
990 set_debug_location(cx, DebugLocation::new(scope_metadata, loc.line, loc.col.to_uint()));
992 let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
998 llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr);
1001 match variable_kind {
1002 ArgumentVariable(_) | CapturedVariable => {
1006 .source_locations_enabled
1008 set_debug_location(cx, UnknownLocation);
1010 _ => { /* nothing to do */ }
1014 fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
1016 let created_files = debug_context(cx).created_files.borrow();
1017 match created_files.get().find_equiv(&full_path) {
1018 Some(file_metadata) => return *file_metadata,
1023 debug!("file_metadata: {}", full_path);
1025 // FIXME (#9639): This needs to handle non-utf8 paths
1026 let work_dir = cx.sess.working_dir.as_str().unwrap();
1028 if full_path.starts_with(work_dir) {
1029 full_path.slice(work_dir.len() + 1u, full_path.len())
1035 file_name.with_c_str(|file_name| {
1036 work_dir.with_c_str(|work_dir| {
1038 llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir)
1043 let mut created_files = debug_context(cx).created_files.borrow_mut();
1044 created_files.get().insert(full_path.to_owned(), file_metadata);
1045 return file_metadata;
1048 /// Finds the scope metadata node for the given AST node.
1049 fn scope_metadata(fcx: &FunctionContext,
1050 node_id: ast::NodeId,
1053 let scope_map = &fcx.debug_context.get_ref(fcx.ccx, span).scope_map;
1054 let scope_map = scope_map.borrow();
1056 match scope_map.get().find_copy(&node_id) {
1057 Some(scope_metadata) => scope_metadata,
1059 let node = fcx.ccx.tcx.items.get(node_id);
1061 fcx.ccx.sess.span_bug(span,
1062 format!("debuginfo: Could not find scope info for node {:?}", node));
1067 fn basic_type_metadata(cx: &CrateContext, t: ty::t) -> DIType {
1069 debug!("basic_type_metadata: {:?}", ty::get(t));
1071 let (name, encoding) = match ty::get(t).sty {
1072 ty::ty_nil => (~"()", DW_ATE_unsigned),
1073 ty::ty_bot => (~"!", DW_ATE_unsigned),
1074 ty::ty_bool => (~"bool", DW_ATE_boolean),
1075 ty::ty_char => (~"char", DW_ATE_unsigned_char),
1076 ty::ty_int(int_ty) => match int_ty {
1077 ast::TyI => (~"int", DW_ATE_signed),
1078 ast::TyI8 => (~"i8", DW_ATE_signed),
1079 ast::TyI16 => (~"i16", DW_ATE_signed),
1080 ast::TyI32 => (~"i32", DW_ATE_signed),
1081 ast::TyI64 => (~"i64", DW_ATE_signed)
1083 ty::ty_uint(uint_ty) => match uint_ty {
1084 ast::TyU => (~"uint", DW_ATE_unsigned),
1085 ast::TyU8 => (~"u8", DW_ATE_unsigned),
1086 ast::TyU16 => (~"u16", DW_ATE_unsigned),
1087 ast::TyU32 => (~"u32", DW_ATE_unsigned),
1088 ast::TyU64 => (~"u64", DW_ATE_unsigned)
1090 ty::ty_float(float_ty) => match float_ty {
1091 ast::TyF32 => (~"f32", DW_ATE_float),
1092 ast::TyF64 => (~"f64", DW_ATE_float)
1094 _ => cx.sess.bug("debuginfo::basic_type_metadata - t is invalid type")
1097 let llvm_type = type_of::type_of(cx, t);
1098 let (size, align) = size_and_align_of(cx, llvm_type);
1099 let ty_metadata = name.with_c_str(|name| {
1101 llvm::LLVMDIBuilderCreateBasicType(
1104 bytes_to_bits(size),
1105 bytes_to_bits(align),
1113 fn pointer_type_metadata(cx: &CrateContext,
1114 pointer_type: ty::t,
1115 pointee_type_metadata: DIType)
1117 let pointer_llvm_type = type_of::type_of(cx, pointer_type);
1118 let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
1119 let name = ppaux::ty_to_str(cx.tcx, pointer_type);
1120 let ptr_metadata = name.with_c_str(|name| {
1122 llvm::LLVMDIBuilderCreatePointerType(
1124 pointee_type_metadata,
1125 bytes_to_bits(pointer_size),
1126 bytes_to_bits(pointer_align),
1130 return ptr_metadata;
1133 trait MemberDescriptionFactory {
1134 fn create_member_descriptions(&self, cx: &CrateContext)
1135 -> ~[MemberDescription];
1138 struct StructMemberDescriptionFactory {
1139 fields: ~[ty::field],
1143 impl MemberDescriptionFactory for StructMemberDescriptionFactory {
1144 fn create_member_descriptions(&self, cx: &CrateContext)
1145 -> ~[MemberDescription] {
1146 self.fields.map(|field| {
1147 let name = if field.ident.name == special_idents::unnamed_field.name {
1150 let string = token::get_ident(field.ident.name);
1151 string.get().to_str()
1156 llvm_type: type_of::type_of(cx, field.mt.ty),
1157 type_metadata: type_metadata(cx, field.mt.ty, self.span),
1158 offset: ComputedMemberOffset,
1164 fn prepare_struct_metadata(cx: &CrateContext,
1167 substs: &ty::substs,
1169 -> RecursiveTypeDescription {
1170 let struct_name = ppaux::ty_to_str(cx.tcx, struct_type);
1171 let struct_llvm_type = type_of::type_of(cx, struct_type);
1173 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id, span);
1175 let file_name = span_start(cx, definition_span).file.name.clone();
1176 let file_metadata = file_metadata(cx, file_name);
1178 let struct_metadata_stub = create_struct_stub(cx,
1185 let fields = ty::struct_fields(cx.tcx, def_id, substs);
1187 UnfinishedMetadata {
1188 cache_id: cache_id_for_type(struct_type),
1189 metadata_stub: struct_metadata_stub,
1190 llvm_type: struct_llvm_type,
1191 file_metadata: file_metadata,
1192 member_description_factory: @StructMemberDescriptionFactory {
1195 } as @MemberDescriptionFactory,
1199 enum RecursiveTypeDescription {
1200 UnfinishedMetadata {
1202 metadata_stub: DICompositeType,
1204 file_metadata: DIFile,
1205 member_description_factory: @MemberDescriptionFactory,
1207 FinalMetadata(DICompositeType)
1210 impl RecursiveTypeDescription {
1212 fn finalize(&self, cx: &CrateContext) -> DICompositeType {
1214 FinalMetadata(metadata) => metadata,
1215 UnfinishedMetadata {
1220 member_description_factory
1222 // Insert the stub into the cache in order to allow recursive references ...
1224 let mut created_types = debug_context(cx).created_types.borrow_mut();
1225 created_types.get().insert(cache_id, metadata_stub);
1228 // ... then create the member descriptions ...
1229 let member_descriptions = member_description_factory.create_member_descriptions(cx);
1231 // ... and attach them to the stub to complete it.
1232 set_members_of_composite_type(cx,
1235 member_descriptions,
1238 return metadata_stub;
1244 struct TupleMemberDescriptionFactory {
1245 component_types: ~[ty::t],
1249 impl MemberDescriptionFactory for TupleMemberDescriptionFactory {
1250 fn create_member_descriptions(&self, cx: &CrateContext)
1251 -> ~[MemberDescription] {
1252 self.component_types.map(|&component_type| {
1255 llvm_type: type_of::type_of(cx, component_type),
1256 type_metadata: type_metadata(cx, component_type, self.span),
1257 offset: ComputedMemberOffset,
1263 fn prepare_tuple_metadata(cx: &CrateContext,
1265 component_types: &[ty::t],
1267 -> RecursiveTypeDescription {
1268 let tuple_name = ppaux::ty_to_str(cx.tcx, tuple_type);
1269 let tuple_llvm_type = type_of::type_of(cx, tuple_type);
1271 let loc = span_start(cx, span);
1272 let file_metadata = file_metadata(cx, loc.file.name);
1274 UnfinishedMetadata {
1275 cache_id: cache_id_for_type(tuple_type),
1276 metadata_stub: create_struct_stub(cx,
1282 llvm_type: tuple_llvm_type,
1283 file_metadata: file_metadata,
1284 member_description_factory: @TupleMemberDescriptionFactory {
1285 component_types: component_types.to_owned(),
1287 } as @MemberDescriptionFactory
1291 struct GeneralMemberDescriptionFactory {
1292 type_rep: @adt::Repr,
1293 variants: @~[@ty::VariantInfo],
1294 discriminant_type_metadata: ValueRef,
1295 containing_scope: DIScope,
1296 file_metadata: DIFile,
1300 impl MemberDescriptionFactory for GeneralMemberDescriptionFactory {
1301 fn create_member_descriptions(&self, cx: &CrateContext)
1302 -> ~[MemberDescription] {
1303 // Capture type_rep, so we don't have to copy the struct_defs array
1304 let struct_defs = match *self.type_rep {
1305 adt::General(_, ref struct_defs) => struct_defs,
1306 _ => cx.sess.bug("unreachable")
1312 .map(|(i, struct_def)| {
1313 let (variant_type_metadata, variant_llvm_type, member_desc_factory) =
1314 describe_enum_variant(cx,
1317 Some(self.discriminant_type_metadata),
1318 self.containing_scope,
1322 let member_descriptions =
1323 member_desc_factory.create_member_descriptions(cx);
1325 set_members_of_composite_type(cx,
1326 variant_type_metadata,
1328 member_descriptions,
1333 llvm_type: variant_llvm_type,
1334 type_metadata: variant_type_metadata,
1335 offset: FixedMemberOffset { bytes: 0 },
1341 struct EnumVariantMemberDescriptionFactory {
1342 args: ~[(~str, ty::t)],
1343 discriminant_type_metadata: Option<DIType>,
1347 impl MemberDescriptionFactory for EnumVariantMemberDescriptionFactory {
1348 fn create_member_descriptions(&self, cx: &CrateContext)
1349 -> ~[MemberDescription] {
1350 self.args.iter().enumerate().map(|(i, &(ref name, ty))| {
1352 name: name.to_str(),
1353 llvm_type: type_of::type_of(cx, ty),
1354 type_metadata: match self.discriminant_type_metadata {
1355 Some(metadata) if i == 0 => metadata,
1356 _ => type_metadata(cx, ty, self.span)
1358 offset: ComputedMemberOffset,
1364 fn describe_enum_variant(cx: &CrateContext,
1365 struct_def: &adt::Struct,
1366 variant_info: &ty::VariantInfo,
1367 discriminant_type_metadata: Option<DIType>,
1368 containing_scope: DIScope,
1369 file_metadata: DIFile,
1371 -> (DICompositeType, Type, @MemberDescriptionFactory) {
1372 let variant_info_string = token::get_ident(variant_info.name.name);
1373 let variant_name = variant_info_string.get();
1374 let variant_llvm_type = Type::struct_(struct_def.fields.map(|&t| type_of::type_of(cx, t)),
1376 // Could some consistency checks here: size, align, field count, discr type
1378 // Find the source code location of the variant's definition
1379 let variant_definition_span = if variant_info.id.crate == ast::LOCAL_CRATE {
1381 match cx.tcx.items.find(variant_info.id.node) {
1382 Some(ast_map::NodeVariant(ref variant, _, _)) => variant.span,
1384 cx.sess.span_warn(span,
1385 format!("debuginfo::enum_metadata()::\
1386 adt_struct_metadata() - Unexpected node \
1387 type: {:?}. This is a bug.", node));
1393 // For definitions from other crates we have no location information available.
1397 let metadata_stub = create_struct_stub(cx,
1402 variant_definition_span);
1404 // Get the argument names from the enum variant info
1405 let mut arg_names = match variant_info.arg_names {
1406 Some(ref names) => {
1408 let string = token::get_ident(ident.name);
1409 string.get().to_str()
1412 None => variant_info.args.map(|_| ~"")
1415 // If this is not a univariant enum, there is also the (unnamed) discriminant field
1416 if discriminant_type_metadata.is_some() {
1417 arg_names.insert(0, ~"");
1420 // Build an array of (field name, field type) pairs to be captured in the factory closure.
1421 let args: ~[(~str, ty::t)] = arg_names.iter()
1422 .zip(struct_def.fields.iter())
1423 .map(|(s, &t)| (s.to_str(), t))
1426 let member_description_factory =
1427 @EnumVariantMemberDescriptionFactory {
1429 discriminant_type_metadata: discriminant_type_metadata,
1431 } as @MemberDescriptionFactory;
1433 (metadata_stub, variant_llvm_type, member_description_factory)
1436 fn prepare_enum_metadata(cx: &CrateContext,
1438 enum_def_id: ast::DefId,
1440 -> RecursiveTypeDescription {
1441 let enum_name = ppaux::ty_to_str(cx.tcx, enum_type);
1443 let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx,
1446 let loc = span_start(cx, definition_span);
1447 let file_metadata = file_metadata(cx, loc.file.name);
1449 // For empty enums there is an early exit. Just describe it as an empty struct with the
1450 // appropriate type name
1451 if ty::type_is_empty(cx.tcx, enum_type) {
1452 let empty_type_metadata = composite_type_metadata(cx,
1460 return FinalMetadata(empty_type_metadata);
1463 let variants = ty::enum_variants(cx.tcx, enum_def_id);
1465 let enumerators_metadata: ~[DIDescriptor] = variants
1468 let string = token::get_ident(v.name.name);
1469 let name: &str = string.get();
1470 let discriminant_value = v.disr_val as c_ulonglong;
1472 name.with_c_str(|name| {
1474 llvm::LLVMDIBuilderCreateEnumerator(
1483 let discriminant_type_metadata = |inttype| {
1484 let discriminant_llvm_type = adt::ll_inttype(cx, inttype);
1485 let (discriminant_size, discriminant_align) = size_and_align_of(cx, discriminant_llvm_type);
1486 let discriminant_base_type_metadata = type_metadata(cx, adt::ty_of_inttype(inttype),
1488 enum_name.with_c_str(|enum_name| {
1490 llvm::LLVMDIBuilderCreateEnumerationType(
1496 bytes_to_bits(discriminant_size),
1497 bytes_to_bits(discriminant_align),
1498 create_DIArray(DIB(cx), enumerators_metadata),
1499 discriminant_base_type_metadata)
1504 let type_rep = adt::represent_type(cx, enum_type);
1506 return match *type_rep {
1507 adt::CEnum(inttype, _, _) => {
1508 FinalMetadata(discriminant_type_metadata(inttype))
1510 adt::Univariant(ref struct_def, _) => {
1511 assert!(variants.len() == 1);
1514 member_description_factory) = describe_enum_variant(cx,
1521 UnfinishedMetadata {
1522 cache_id: cache_id_for_type(enum_type),
1523 metadata_stub: metadata_stub,
1524 llvm_type: variant_llvm_type,
1525 file_metadata: file_metadata,
1526 member_description_factory: member_description_factory
1529 adt::General(inttype, _) => {
1530 let discriminant_type_metadata = discriminant_type_metadata(inttype);
1531 let enum_llvm_type = type_of::type_of(cx, enum_type);
1532 let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type);
1533 let unique_id = generate_unique_type_id("DI_ENUM_");
1535 let enum_metadata = enum_name.with_c_str(|enum_name| {
1536 unique_id.with_c_str(|unique_id| {
1538 llvm::LLVMDIBuilderCreateUnionType(
1544 bytes_to_bits(enum_type_size),
1545 bytes_to_bits(enum_type_align),
1554 UnfinishedMetadata {
1555 cache_id: cache_id_for_type(enum_type),
1556 metadata_stub: enum_metadata,
1557 llvm_type: enum_llvm_type,
1558 file_metadata: file_metadata,
1559 member_description_factory: @GeneralMemberDescriptionFactory {
1562 discriminant_type_metadata: discriminant_type_metadata,
1563 containing_scope: containing_scope,
1564 file_metadata: file_metadata,
1566 } as @MemberDescriptionFactory,
1569 adt::NullablePointer { nonnull: ref struct_def, nndiscr, .. } => {
1572 member_description_factory) = describe_enum_variant(cx,
1579 UnfinishedMetadata {
1580 cache_id: cache_id_for_type(enum_type),
1581 metadata_stub: metadata_stub,
1582 llvm_type: variant_llvm_type,
1583 file_metadata: file_metadata,
1584 member_description_factory: member_description_factory
1591 FixedMemberOffset { bytes: uint },
1592 // For ComputedMemberOffset, the offset is read from the llvm type definition
1593 ComputedMemberOffset
1596 struct MemberDescription {
1599 type_metadata: DIType,
1600 offset: MemberOffset,
1603 /// Creates debug information for a composite type, that is, anything that results in a LLVM struct.
1605 /// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums.
1606 fn composite_type_metadata(cx: &CrateContext,
1607 composite_llvm_type: Type,
1608 composite_type_name: &str,
1609 member_descriptions: &[MemberDescription],
1610 containing_scope: DIScope,
1611 file_metadata: DIFile,
1612 definition_span: Span)
1613 -> DICompositeType {
1614 // Create the (empty) struct metadata node ...
1615 let composite_type_metadata = create_struct_stub(cx,
1616 composite_llvm_type,
1617 composite_type_name,
1622 // ... and immediately create and add the member descriptions.
1623 set_members_of_composite_type(cx,
1624 composite_type_metadata,
1625 composite_llvm_type,
1626 member_descriptions,
1630 return composite_type_metadata;
1633 fn set_members_of_composite_type(cx: &CrateContext,
1634 composite_type_metadata: DICompositeType,
1635 composite_llvm_type: Type,
1636 member_descriptions: &[MemberDescription],
1637 file_metadata: DIFile,
1638 definition_span: Span) {
1639 // In some rare cases LLVM metadata uniquing would lead to an existing type description being
1640 // used instead of a new one created in create_struct_stub. This would cause a hard to trace
1641 // assertion in DICompositeType::SetTypeArray(). The following check makes sure that we get a
1642 // better error message if this should happen again due to some regression.
1644 let mut composite_types_completed =
1645 debug_context(cx).composite_types_completed.borrow_mut();
1646 if composite_types_completed.get().contains(&composite_type_metadata) {
1647 cx.sess.span_bug(definition_span, "debuginfo::set_members_of_composite_type() - \
1648 Already completed forward declaration \
1651 composite_types_completed.get().insert(composite_type_metadata);
1655 let loc = span_start(cx, definition_span);
1657 let member_metadata: ~[DIDescriptor] = member_descriptions
1660 .map(|(i, member_description)| {
1661 let (member_size, member_align) = size_and_align_of(cx, member_description.llvm_type);
1662 let member_offset = match member_description.offset {
1663 FixedMemberOffset { bytes } => bytes as u64,
1664 ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i)
1667 member_description.name.with_c_str(|member_name| {
1669 llvm::LLVMDIBuilderCreateMemberType(
1671 composite_type_metadata,
1675 bytes_to_bits(member_size),
1676 bytes_to_bits(member_align),
1677 bytes_to_bits(member_offset),
1679 member_description.type_metadata)
1686 let type_array = create_DIArray(DIB(cx), member_metadata);
1687 llvm::LLVMDICompositeTypeSetTypeArray(composite_type_metadata, type_array);
1691 // A convenience wrapper around LLVMDIBuilderCreateStructType(). Does not do any caching, does not
1692 // add any fields to the struct. This can be done later with set_members_of_composite_type().
1693 fn create_struct_stub(cx: &CrateContext,
1694 struct_llvm_type: Type,
1695 struct_type_name: &str,
1696 containing_scope: DIScope,
1697 file_metadata: DIFile,
1698 definition_span: Span)
1699 -> DICompositeType {
1700 let loc = span_start(cx, definition_span);
1701 let (struct_size, struct_align) = size_and_align_of(cx, struct_llvm_type);
1703 // We assign unique IDs to the type stubs so LLVM metadata uniquing does not reuse instances
1704 // where we don't want it.
1705 let unique_id = generate_unique_type_id("DI_STRUCT_");
1708 struct_type_name.with_c_str(|name| {
1709 unique_id.with_c_str(|unique_id| {
1710 // LLVMDIBuilderCreateStructType() wants an empty array. A null pointer will lead to
1711 // hard to trace and debug LLVM assertions later on in llvm/lib/IR/Value.cpp
1712 let empty_array = create_DIArray(DIB(cx), []);
1714 llvm::LLVMDIBuilderCreateStructType(
1720 bytes_to_bits(struct_size),
1721 bytes_to_bits(struct_align),
1733 fn boxed_type_metadata(cx: &CrateContext,
1734 content_type_name: Option<&str>,
1735 content_llvm_type: Type,
1736 content_type_metadata: DIType,
1738 -> DICompositeType {
1739 let box_type_name = match content_type_name {
1740 Some(content_type_name) => format!("Boxed<{}>", content_type_name),
1741 None => ~"BoxedType"
1744 let box_llvm_type = Type::at_box(cx, content_llvm_type);
1745 let member_llvm_types = box_llvm_type.field_types();
1746 assert!(box_layout_is_correct(cx, member_llvm_types, content_llvm_type));
1748 let int_type = ty::mk_int();
1749 let nil_pointer_type = ty::mk_nil_ptr(cx.tcx);
1750 let nil_pointer_type_metadata = type_metadata(cx, nil_pointer_type, codemap::DUMMY_SP);
1752 let member_descriptions = [
1755 llvm_type: member_llvm_types[0],
1756 type_metadata: type_metadata(cx, int_type, codemap::DUMMY_SP),
1757 offset: ComputedMemberOffset,
1761 llvm_type: member_llvm_types[1],
1762 type_metadata: nil_pointer_type_metadata,
1763 offset: ComputedMemberOffset,
1767 llvm_type: member_llvm_types[2],
1768 type_metadata: nil_pointer_type_metadata,
1769 offset: ComputedMemberOffset,
1773 llvm_type: member_llvm_types[3],
1774 type_metadata: nil_pointer_type_metadata,
1775 offset: ComputedMemberOffset,
1779 llvm_type: member_llvm_types[4],
1780 type_metadata: content_type_metadata,
1781 offset: ComputedMemberOffset,
1785 let loc = span_start(cx, span);
1786 let file_metadata = file_metadata(cx, loc.file.name);
1788 return composite_type_metadata(
1792 member_descriptions,
1797 // Unfortunately, we cannot assert anything but the correct types here---and not whether the
1798 // 'next' and 'prev' pointers are in the correct order.
1799 fn box_layout_is_correct(cx: &CrateContext,
1800 member_llvm_types: &[Type],
1801 content_llvm_type: Type)
1803 member_llvm_types.len() == 5 &&
1804 member_llvm_types[0] == cx.int_type &&
1805 member_llvm_types[1] == cx.tydesc_type.ptr_to() &&
1806 member_llvm_types[2] == Type::i8().ptr_to() &&
1807 member_llvm_types[3] == Type::i8().ptr_to() &&
1808 member_llvm_types[4] == content_llvm_type
1812 fn fixed_vec_metadata(cx: &CrateContext,
1813 element_type: ty::t,
1817 let element_type_metadata = type_metadata(cx, element_type, span);
1818 let element_llvm_type = type_of::type_of(cx, element_type);
1819 let (element_type_size, element_type_align) = size_and_align_of(cx, element_llvm_type);
1821 let subrange = unsafe {
1822 llvm::LLVMDIBuilderGetOrCreateSubrange(
1828 let subscripts = create_DIArray(DIB(cx), [subrange]);
1830 llvm::LLVMDIBuilderCreateArrayType(
1832 bytes_to_bits(element_type_size * (len as u64)),
1833 bytes_to_bits(element_type_align),
1834 element_type_metadata,
1839 fn vec_metadata(cx: &CrateContext,
1840 element_type: ty::t,
1842 -> DICompositeType {
1844 let element_type_metadata = type_metadata(cx, element_type, span);
1845 let element_llvm_type = type_of::type_of(cx, element_type);
1846 let (element_size, element_align) = size_and_align_of(cx, element_llvm_type);
1848 let vec_llvm_type = Type::vec(cx.sess.targ_cfg.arch, &element_llvm_type);
1849 let vec_type_name: &str = format!("[{}]", ppaux::ty_to_str(cx.tcx, element_type));
1851 let member_llvm_types = vec_llvm_type.field_types();
1853 let int_type_metadata = type_metadata(cx, ty::mk_int(), span);
1854 let array_type_metadata = unsafe {
1855 llvm::LLVMDIBuilderCreateArrayType(
1857 bytes_to_bits(element_size),
1858 bytes_to_bits(element_align),
1859 element_type_metadata,
1860 create_DIArray(DIB(cx), [llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, 0)]))
1863 let member_descriptions = [
1866 llvm_type: member_llvm_types[0],
1867 type_metadata: int_type_metadata,
1868 offset: ComputedMemberOffset,
1872 llvm_type: member_llvm_types[1],
1873 type_metadata: int_type_metadata,
1874 offset: ComputedMemberOffset,
1878 llvm_type: member_llvm_types[2],
1879 type_metadata: array_type_metadata,
1880 offset: ComputedMemberOffset,
1884 assert!(member_descriptions.len() == member_llvm_types.len());
1886 let loc = span_start(cx, span);
1887 let file_metadata = file_metadata(cx, loc.file.name);
1889 return composite_type_metadata(
1893 member_descriptions,
1899 fn boxed_vec_metadata(cx: &CrateContext,
1900 element_type: ty::t,
1902 -> DICompositeType {
1903 let element_llvm_type = type_of::type_of(cx, element_type);
1904 let vec_llvm_type = Type::vec(cx.sess.targ_cfg.arch, &element_llvm_type);
1905 let vec_type_name: &str = format!("[{}]", ppaux::ty_to_str(cx.tcx, element_type));
1906 let vec_metadata = vec_metadata(cx, element_type, span);
1908 return boxed_type_metadata(
1910 Some(vec_type_name),
1916 fn vec_slice_metadata(cx: &CrateContext,
1918 element_type: ty::t,
1920 -> DICompositeType {
1922 debug!("vec_slice_metadata: {:?}", ty::get(vec_type));
1924 let slice_llvm_type = type_of::type_of(cx, vec_type);
1925 let slice_type_name = ppaux::ty_to_str(cx.tcx, vec_type);
1927 let member_llvm_types = slice_llvm_type.field_types();
1928 assert!(slice_layout_is_correct(cx, member_llvm_types, element_type));
1930 let data_ptr_type = ty::mk_ptr(cx.tcx, ty::mt { ty: element_type, mutbl: ast::MutImmutable });
1932 let member_descriptions = [
1935 llvm_type: member_llvm_types[0],
1936 type_metadata: type_metadata(cx, data_ptr_type, span),
1937 offset: ComputedMemberOffset,
1941 llvm_type: member_llvm_types[1],
1942 type_metadata: type_metadata(cx, ty::mk_uint(), span),
1943 offset: ComputedMemberOffset,
1947 assert!(member_descriptions.len() == member_llvm_types.len());
1949 let loc = span_start(cx, span);
1950 let file_metadata = file_metadata(cx, loc.file.name);
1952 return composite_type_metadata(
1956 member_descriptions,
1961 fn slice_layout_is_correct(cx: &CrateContext,
1962 member_llvm_types: &[Type],
1963 element_type: ty::t)
1965 member_llvm_types.len() == 2 &&
1966 member_llvm_types[0] == type_of::type_of(cx, element_type).ptr_to() &&
1967 member_llvm_types[1] == cx.int_type
1971 fn subroutine_type_metadata(cx: &CrateContext,
1972 signature: &ty::FnSig,
1974 -> DICompositeType {
1975 let loc = span_start(cx, span);
1976 let file_metadata = file_metadata(cx, loc.file.name);
1978 let mut signature_metadata: ~[DIType] = vec::with_capacity(signature.inputs.len() + 1);
1981 signature_metadata.push(match ty::get(signature.output).sty {
1982 ty::ty_nil => ptr::null(),
1983 _ => type_metadata(cx, signature.output, span)
1986 // regular arguments
1987 for &argument_type in signature.inputs.iter() {
1988 signature_metadata.push(type_metadata(cx, argument_type, span));
1992 llvm::LLVMDIBuilderCreateSubroutineType(
1995 create_DIArray(DIB(cx), signature_metadata))
1999 fn trait_metadata(cx: &CrateContext,
2002 substs: &ty::substs,
2003 trait_store: ty::TraitStore,
2004 mutability: ast::Mutability,
2005 _: &ty::BuiltinBounds,
2006 usage_site_span: Span)
2008 // The implementation provided here is a stub. It makes sure that the trait type is
2009 // assigned the correct name, size, namespace, and source location. But it does not describe
2010 // the trait's methods.
2011 let path = ty::item_path(cx.tcx, def_id);
2012 let ident = path.last().unwrap().ident();
2013 let ident_string = token::get_ident(ident.name);
2014 let name = ppaux::trait_store_to_str(cx.tcx, trait_store) +
2015 ppaux::mutability_to_str(mutability) +
2017 // Add type and region parameters
2018 let name = ppaux::parameterized(cx.tcx, name, &substs.regions,
2019 substs.tps, def_id, true);
2021 let (containing_scope, definition_span) =
2022 get_namespace_and_span_for_item(cx, def_id, usage_site_span);
2024 let file_name = span_start(cx, definition_span).file.name.clone();
2025 let file_metadata = file_metadata(cx, file_name);
2027 let trait_llvm_type = type_of::type_of(cx, trait_type);
2029 return composite_type_metadata(cx,
2038 fn type_metadata(cx: &CrateContext,
2040 usage_site_span: Span)
2042 let cache_id = cache_id_for_type(t);
2045 let created_types = debug_context(cx).created_types.borrow();
2046 match created_types.get().find(&cache_id) {
2047 Some(type_metadata) => return *type_metadata,
2052 fn create_pointer_to_box_metadata(cx: &CrateContext,
2053 pointer_type: ty::t,
2056 let content_type_name: &str = ppaux::ty_to_str(cx.tcx, type_in_box);
2057 let content_llvm_type = type_of::type_of(cx, type_in_box);
2058 let content_type_metadata = type_metadata(
2063 let box_metadata = boxed_type_metadata(
2065 Some(content_type_name),
2067 content_type_metadata,
2070 pointer_type_metadata(cx, pointer_type, box_metadata)
2073 debug!("type_metadata: {:?}", ty::get(t));
2075 let sty = &ty::get(t).sty;
2076 let type_metadata = match *sty {
2083 ty::ty_float(_) => {
2084 basic_type_metadata(cx, t)
2086 ty::ty_str(ref vstore) => {
2087 let i8_t = ty::mk_i8();
2089 ty::vstore_fixed(len) => {
2090 fixed_vec_metadata(cx, i8_t, len + 1, usage_site_span)
2092 ty::vstore_uniq => {
2093 let vec_metadata = vec_metadata(cx, i8_t, usage_site_span);
2094 pointer_type_metadata(cx, t, vec_metadata)
2097 let boxed_vec_metadata = boxed_vec_metadata(cx, i8_t, usage_site_span);
2098 pointer_type_metadata(cx, t, boxed_vec_metadata)
2100 ty::vstore_slice(_region) => {
2101 vec_slice_metadata(cx, t, i8_t, usage_site_span)
2105 ty::ty_enum(def_id, _) => {
2106 prepare_enum_metadata(cx, t, def_id, usage_site_span).finalize(cx)
2108 ty::ty_box(typ) => {
2109 create_pointer_to_box_metadata(cx, t, typ)
2111 ty::ty_vec(ref mt, ref vstore) => {
2113 ty::vstore_fixed(len) => {
2114 fixed_vec_metadata(cx, mt.ty, len, usage_site_span)
2116 ty::vstore_uniq => {
2117 let vec_metadata = vec_metadata(cx, mt.ty, usage_site_span);
2118 pointer_type_metadata(cx, t, vec_metadata)
2121 let boxed_vec_metadata = boxed_vec_metadata(cx, mt.ty, usage_site_span);
2122 pointer_type_metadata(cx, t, boxed_vec_metadata)
2124 ty::vstore_slice(_) => {
2125 vec_slice_metadata(cx, t, mt.ty, usage_site_span)
2129 ty::ty_uniq(typ) => {
2130 let pointee = type_metadata(cx, typ, usage_site_span);
2131 pointer_type_metadata(cx, t, pointee)
2133 ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => {
2134 let pointee = type_metadata(cx, mt.ty, usage_site_span);
2135 pointer_type_metadata(cx, t, pointee)
2137 ty::ty_bare_fn(ref barefnty) => {
2138 subroutine_type_metadata(cx, &barefnty.sig, usage_site_span)
2140 ty::ty_closure(ref closurety) => {
2141 subroutine_type_metadata(cx, &closurety.sig, usage_site_span)
2143 ty::ty_trait(def_id, ref substs, trait_store, mutability, ref bounds) => {
2144 trait_metadata(cx, def_id, t, substs, trait_store, mutability, bounds, usage_site_span)
2146 ty::ty_struct(def_id, ref substs) => {
2147 prepare_struct_metadata(cx, t, def_id, substs, usage_site_span).finalize(cx)
2149 ty::ty_tup(ref elements) => {
2150 prepare_tuple_metadata(cx, t, *elements, usage_site_span).finalize(cx)
2152 _ => cx.sess.bug(format!("debuginfo: unexpected type in type_metadata: {:?}", sty))
2155 let mut created_types = debug_context(cx).created_types.borrow_mut();
2156 created_types.get().insert(cache_id, type_metadata);
2161 enum DebugLocation {
2162 KnownLocation { scope: DIScope, line: uint, col: uint },
2166 impl DebugLocation {
2167 fn new(scope: DIScope, line: uint, col: uint) -> DebugLocation {
2176 fn set_debug_location(cx: &CrateContext, debug_location: DebugLocation) {
2177 if debug_location == debug_context(cx).current_debug_location.get() {
2183 match debug_location {
2184 KnownLocation { scope, line, .. } => {
2185 let col = 0; // Always set the column to zero like Clang and GCC
2186 debug!("setting debug location to {} {}", line, col);
2187 let elements = [C_i32(line as i32), C_i32(col as i32), scope, ptr::null()];
2189 metadata_node = llvm::LLVMMDNodeInContext(debug_context(cx).llcontext,
2191 elements.len() as c_uint);
2194 UnknownLocation => {
2195 debug!("clearing debug location ");
2196 metadata_node = ptr::null();
2201 llvm::LLVMSetCurrentDebugLocation(cx.builder.B, metadata_node);
2204 debug_context(cx).current_debug_location.set(debug_location);
2207 //=-------------------------------------------------------------------------------------------------
2208 // Utility Functions
2209 //=-------------------------------------------------------------------------------------------------
2211 fn cache_id_for_type(t: ty::t) -> uint {
2215 // Used to avoid LLVM metadata uniquing problems. See `create_struct_stub()` and
2216 // `prepare_enum_metadata()`.
2217 fn generate_unique_type_id(prefix: &'static str) -> ~str {
2219 static mut unique_id_counter: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;
2220 format!("{}{}", prefix, unique_id_counter.fetch_add(1, atomics::SeqCst))
2224 /// Return codemap::Loc corresponding to the beginning of the span
2225 fn span_start(cx: &CrateContext, span: Span) -> codemap::Loc {
2226 cx.sess.codemap.lookup_char_pos(span.lo)
2229 fn size_and_align_of(cx: &CrateContext, llvm_type: Type) -> (u64, u64) {
2230 (machine::llsize_of_alloc(cx, llvm_type), machine::llalign_of_min(cx, llvm_type))
2233 fn bytes_to_bits(bytes: u64) -> c_ulonglong {
2234 (bytes * 8) as c_ulonglong
2238 fn debug_context<'a>(cx: &'a CrateContext) -> &'a CrateDebugContext {
2239 let debug_context: &'a CrateDebugContext = cx.dbg_cx.get_ref();
2244 fn DIB(cx: &CrateContext) -> DIBuilderRef {
2245 cx.dbg_cx.get_ref().builder
2248 fn fn_should_be_ignored(fcx: &FunctionContext) -> bool {
2249 match fcx.debug_context {
2250 FunctionDebugContext(_) => false,
2255 fn assert_type_for_node_id(cx: &CrateContext, node_id: ast::NodeId, error_span: Span) {
2256 let node_types = cx.tcx.node_types.borrow();
2257 if !node_types.get().contains_key(&(node_id as uint)) {
2258 cx.sess.span_bug(error_span, "debuginfo: Could not find type for node id!");
2262 fn get_namespace_and_span_for_item(cx: &CrateContext,
2265 -> (DIScope, Span) {
2266 let containing_scope = namespace_for_item(cx, def_id, warning_span).scope;
2267 let definition_span = if def_id.crate == ast::LOCAL_CRATE {
2269 let definition_span = match cx.tcx.items.find(def_id.node) {
2270 Some(ast_map::NodeItem(item, _)) => item.span,
2272 cx.sess.span_warn(warning_span,
2273 format!("debuginfo::\
2274 get_namespace_and_span_for_item() \
2275 - Unexpected node type: {:?}", *node));
2282 // For external items there is no span information
2286 (containing_scope, definition_span)
2289 // This procedure builds the *scope map* for a given function, which maps any given ast::NodeId in
2290 // the function's AST to the correct DIScope metadata instance.
2292 // This builder procedure walks the AST in execution order and keeps track of what belongs to which
2293 // scope, creating DIScope DIEs along the way, and introducing *artificial* lexical scope
2294 // descriptors where necessary. These artificial scopes allow GDB to correctly handle name
2296 fn populate_scope_map(cx: &CrateContext,
2297 arg_pats: &[@ast::Pat],
2298 fn_entry_block: &ast::Block,
2299 fn_metadata: DISubprogram,
2300 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2301 let def_map = cx.tcx.def_map;
2303 struct ScopeStackEntry {
2304 scope_metadata: DIScope,
2305 ident: Option<ast::Ident>
2308 let mut scope_stack = ~[ScopeStackEntry { scope_metadata: fn_metadata, ident: None }];
2310 // Push argument identifiers onto the stack so arguments integrate nicely with variable
2312 for &arg_pat in arg_pats.iter() {
2313 pat_util::pat_bindings(def_map, arg_pat, |_, _, _, path_ref| {
2314 let ident = ast_util::path_to_ident(path_ref);
2315 scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata, ident: Some(ident) });
2319 // Clang creates a separate scope for function bodies, so let's do this too
2321 fn_entry_block.span,
2324 |cx, scope_stack, scope_map| {
2325 walk_block(cx, fn_entry_block, scope_stack, scope_map);
2328 // local helper functions for walking the AST.
2329 fn with_new_scope(cx: &CrateContext,
2331 scope_stack: &mut ~[ScopeStackEntry],
2332 scope_map: &mut HashMap<ast::NodeId, DIScope>,
2333 inner_walk: |&CrateContext,
2334 &mut ~[ScopeStackEntry],
2335 &mut HashMap<ast::NodeId, DIScope>|) {
2336 // Create a new lexical scope and push it onto the stack
2337 let loc = cx.sess.codemap.lookup_char_pos(scope_span.lo);
2338 let file_metadata = file_metadata(cx, loc.file.name);
2339 let parent_scope = scope_stack.last().unwrap().scope_metadata;
2341 let scope_metadata = unsafe {
2342 llvm::LLVMDIBuilderCreateLexicalBlock(
2347 loc.col.to_uint() as c_uint)
2350 scope_stack.push(ScopeStackEntry { scope_metadata: scope_metadata, ident: None });
2352 inner_walk(cx, scope_stack, scope_map);
2354 // pop artificial scopes
2355 while scope_stack.last().unwrap().ident.is_some() {
2359 if scope_stack.last().unwrap().scope_metadata != scope_metadata {
2360 cx.sess.span_bug(scope_span, "debuginfo: Inconsistency in scope management.");
2366 fn walk_block(cx: &CrateContext,
2368 scope_stack: &mut ~[ScopeStackEntry],
2369 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2370 scope_map.insert(block.id, scope_stack.last().unwrap().scope_metadata);
2372 // The interesting things here are statements and the concluding expression.
2373 for statement in block.stmts.iter() {
2374 scope_map.insert(ast_util::stmt_id(*statement),
2375 scope_stack.last().unwrap().scope_metadata);
2377 match statement.node {
2378 ast::StmtDecl(decl, _) => walk_decl(cx, decl, scope_stack, scope_map),
2379 ast::StmtExpr(exp, _) |
2380 ast::StmtSemi(exp, _) => walk_expr(cx, exp, scope_stack, scope_map),
2381 ast::StmtMac(..) => () // ignore macros (which should be expanded anyway)
2385 for exp in block.expr.iter() {
2386 walk_expr(cx, *exp, scope_stack, scope_map);
2390 fn walk_decl(cx: &CrateContext,
2392 scope_stack: &mut ~[ScopeStackEntry],
2393 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2395 codemap::Spanned { node: ast::DeclLocal(local), .. } => {
2396 scope_map.insert(local.id, scope_stack.last().unwrap().scope_metadata);
2398 walk_pattern(cx, local.pat, scope_stack, scope_map);
2400 for exp in local.init.iter() {
2401 walk_expr(cx, *exp, scope_stack, scope_map);
2408 fn walk_pattern(cx: &CrateContext,
2410 scope_stack: &mut ~[ScopeStackEntry],
2411 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2413 let def_map = cx.tcx.def_map;
2415 // Unfortunately, we cannot just use pat_util::pat_bindings() or ast_util::walk_pat() here
2416 // because we have to visit *all* nodes in order to put them into the scope map. The above
2417 // functions don't do that.
2419 ast::PatIdent(_, ref path_ref, ref sub_pat_opt) => {
2421 // Check if this is a binding. If so we need to put it on the scope stack and maybe
2422 // introduce an articial scope
2423 if pat_util::pat_is_binding(def_map, pat) {
2425 let ident = ast_util::path_to_ident(path_ref);
2427 // LLVM does not properly generate 'DW_AT_start_scope' fields for variable DIEs.
2428 // For this reason we have to introduce an artificial scope at bindings whenever
2429 // a variable with the same name is declared in *any* parent scope.
2431 // Otherwise the following error occurs:
2435 // do_something(); // 'gdb print x' correctly prints 10
2438 // do_something(); // 'gdb print x' prints 0, because it already reads the
2439 // // uninitialized 'x' from the next line...
2441 // do_something(); // 'gdb print x' correctly prints 100
2444 // Is there already a binding with that name?
2445 // N.B.: this comparison must be UNhygienic... because
2446 // gdb knows nothing about the context, so any two
2447 // variables with the same name will cause the problem.
2448 let need_new_scope = scope_stack
2450 .any(|entry| entry.ident.iter().any(|i| i.name == ident.name));
2453 // Create a new lexical scope and push it onto the stack
2454 let loc = cx.sess.codemap.lookup_char_pos(pat.span.lo);
2455 let file_metadata = file_metadata(cx, loc.file.name);
2456 let parent_scope = scope_stack.last().unwrap().scope_metadata;
2458 let scope_metadata = unsafe {
2459 llvm::LLVMDIBuilderCreateLexicalBlock(
2464 loc.col.to_uint() as c_uint)
2467 scope_stack.push(ScopeStackEntry {
2468 scope_metadata: scope_metadata,
2473 // Push a new entry anyway so the name can be found
2474 let prev_metadata = scope_stack.last().unwrap().scope_metadata;
2475 scope_stack.push(ScopeStackEntry {
2476 scope_metadata: prev_metadata,
2482 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2484 for &sub_pat in sub_pat_opt.iter() {
2485 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2489 ast::PatWild | ast::PatWildMulti => {
2490 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2493 ast::PatEnum(_, ref sub_pats_opt) => {
2494 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2496 for ref sub_pats in sub_pats_opt.iter() {
2497 for &p in sub_pats.iter() {
2498 walk_pattern(cx, p, scope_stack, scope_map);
2503 ast::PatStruct(_, ref field_pats, _) => {
2504 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2506 for &ast::FieldPat { pat: sub_pat, .. } in field_pats.iter() {
2507 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2511 ast::PatTup(ref sub_pats) => {
2512 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2514 for &sub_pat in sub_pats.iter() {
2515 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2519 ast::PatUniq(sub_pat) | ast::PatRegion(sub_pat) => {
2520 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2521 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2524 ast::PatLit(exp) => {
2525 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2526 walk_expr(cx, exp, scope_stack, scope_map);
2529 ast::PatRange(exp1, exp2) => {
2530 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2531 walk_expr(cx, exp1, scope_stack, scope_map);
2532 walk_expr(cx, exp2, scope_stack, scope_map);
2535 ast::PatVec(ref front_sub_pats, ref middle_sub_pats, ref back_sub_pats) => {
2536 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2538 for &sub_pat in front_sub_pats.iter() {
2539 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2542 for &sub_pat in middle_sub_pats.iter() {
2543 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2546 for &sub_pat in back_sub_pats.iter() {
2547 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2553 fn walk_expr(cx: &CrateContext,
2555 scope_stack: &mut ~[ScopeStackEntry],
2556 scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2558 scope_map.insert(exp.id, scope_stack.last().unwrap().scope_metadata);
2565 ast::ExprPath(_) => {}
2567 ast::ExprVstore(sub_exp, _) |
2568 ast::ExprCast(sub_exp, _) |
2569 ast::ExprAddrOf(_, sub_exp) |
2570 ast::ExprField(sub_exp, _, _) |
2571 ast::ExprParen(sub_exp) => walk_expr(cx, sub_exp, scope_stack, scope_map),
2573 ast::ExprBox(place, sub_expr) => {
2574 walk_expr(cx, place, scope_stack, scope_map);
2575 walk_expr(cx, sub_expr, scope_stack, scope_map);
2578 ast::ExprRet(exp_opt) => match exp_opt {
2579 Some(sub_exp) => walk_expr(cx, sub_exp, scope_stack, scope_map),
2583 ast::ExprUnary(node_id, _, sub_exp) => {
2584 scope_map.insert(node_id, scope_stack.last().unwrap().scope_metadata);
2585 walk_expr(cx, sub_exp, scope_stack, scope_map);
2588 ast::ExprAssignOp(node_id, _, lhs, rhs) |
2589 ast::ExprIndex(node_id, lhs, rhs) |
2590 ast::ExprBinary(node_id, _, lhs, rhs) => {
2591 scope_map.insert(node_id, scope_stack.last().unwrap().scope_metadata);
2592 walk_expr(cx, lhs, scope_stack, scope_map);
2593 walk_expr(cx, rhs, scope_stack, scope_map);
2596 ast::ExprVec(ref init_expressions, _) |
2597 ast::ExprTup(ref init_expressions) => {
2598 for ie in init_expressions.iter() {
2599 walk_expr(cx, *ie, scope_stack, scope_map);
2603 ast::ExprAssign(sub_exp1, sub_exp2) |
2604 ast::ExprRepeat(sub_exp1, sub_exp2, _) => {
2605 walk_expr(cx, sub_exp1, scope_stack, scope_map);
2606 walk_expr(cx, sub_exp2, scope_stack, scope_map);
2609 ast::ExprIf(cond_exp, then_block, ref opt_else_exp) => {
2610 walk_expr(cx, cond_exp, scope_stack, scope_map);
2616 |cx, scope_stack, scope_map| {
2617 walk_block(cx, then_block, scope_stack, scope_map);
2620 match *opt_else_exp {
2621 Some(else_exp) => walk_expr(cx, else_exp, scope_stack, scope_map),
2626 ast::ExprWhile(cond_exp, loop_body) => {
2627 walk_expr(cx, cond_exp, scope_stack, scope_map);
2633 |cx, scope_stack, scope_map| {
2634 walk_block(cx, loop_body, scope_stack, scope_map);
2638 ast::ExprForLoop(_, _, _, _) => {
2639 cx.sess.span_bug(exp.span, "debuginfo::populate_scope_map() - \
2640 Found unexpanded for-loop.");
2643 ast::ExprMac(_) => {
2644 cx.sess.span_bug(exp.span, "debuginfo::populate_scope_map() - \
2645 Found unexpanded macro.");
2648 ast::ExprLoop(block, _) |
2649 ast::ExprBlock(block) => {
2654 |cx, scope_stack, scope_map| {
2655 walk_block(cx, block, scope_stack, scope_map);
2659 ast::ExprFnBlock(decl, block) |
2660 ast::ExprProc(decl, block) => {
2665 |cx, scope_stack, scope_map| {
2666 for &ast::Arg { pat: pattern, .. } in decl.inputs.iter() {
2667 walk_pattern(cx, pattern, scope_stack, scope_map);
2670 walk_block(cx, block, scope_stack, scope_map);
2674 ast::ExprCall(fn_exp, ref args, _) => {
2675 walk_expr(cx, fn_exp, scope_stack, scope_map);
2677 for arg_exp in args.iter() {
2678 walk_expr(cx, *arg_exp, scope_stack, scope_map);
2682 ast::ExprMethodCall(node_id, _, _, ref args, _) => {
2683 scope_map.insert(node_id, scope_stack.last().unwrap().scope_metadata);
2685 for arg_exp in args.iter() {
2686 walk_expr(cx, *arg_exp, scope_stack, scope_map);
2690 ast::ExprMatch(discriminant_exp, ref arms) => {
2691 walk_expr(cx, discriminant_exp, scope_stack, scope_map);
2693 // for each arm we have to first walk the pattern as these might introduce new
2694 // artificial scopes. It should be sufficient to walk only one pattern per arm, as
2695 // they all must contain the same binding names
2697 for arm_ref in arms.iter() {
2698 let arm_span = arm_ref.pats[0].span;
2704 |cx, scope_stack, scope_map| {
2705 for &pat in arm_ref.pats.iter() {
2706 walk_pattern(cx, pat, scope_stack, scope_map);
2709 for guard_exp in arm_ref.guard.iter() {
2710 walk_expr(cx, *guard_exp, scope_stack, scope_map)
2713 walk_block(cx, arm_ref.body, scope_stack, scope_map);
2718 ast::ExprStruct(_, ref fields, ref base_exp) => {
2719 for &ast::Field { expr: exp, .. } in fields.iter() {
2720 walk_expr(cx, exp, scope_stack, scope_map);
2724 Some(exp) => walk_expr(cx, exp, scope_stack, scope_map),
2729 ast::ExprInlineAsm(ast::InlineAsm { inputs: ref inputs,
2730 outputs: ref outputs,
2732 // inputs, outputs: ~[(~str, @expr)]
2733 for &(_, exp) in inputs.iter() {
2734 walk_expr(cx, exp, scope_stack, scope_map);
2737 for &(_, exp) in outputs.iter() {
2738 walk_expr(cx, exp, scope_stack, scope_map);
2746 //=-------------------------------------------------------------------------------------------------
2747 // Namespace Handling
2748 //=-------------------------------------------------------------------------------------------------
2750 struct NamespaceTreeNode {
2753 parent: Option<@NamespaceTreeNode>,
2756 impl NamespaceTreeNode {
2757 fn mangled_name_of_contained_item(&self, item_name: &str) -> ~str {
2758 let mut name = ~"_ZN";
2759 fill_nested(self, &mut name);
2761 name.push_str(format!("{}{}", item_name.len(), item_name));
2762 name.push_char('E');
2766 fn fill_nested(node: &NamespaceTreeNode, output: &mut ~str) {
2769 fill_nested(parent, output);
2773 let string = token::get_ident(node.ident.name);
2774 output.push_str(format!("{}{}",
2781 fn namespace_for_item(cx: &CrateContext,
2784 -> @NamespaceTreeNode {
2785 let namespace_path = {
2786 let mut item_path = ty::item_path(cx.tcx, def_id);
2788 if (def_id.crate == ast::LOCAL_CRATE && item_path.len() < 1) ||
2789 (def_id.crate != ast::LOCAL_CRATE && item_path.len() < 2) {
2790 cx.sess.bug(format!("debuginfo::namespace_for_item() - Item path too short: {}",
2791 ast_map::path_to_str(item_path, token::get_ident_interner())));
2794 // remove the name of the item
2797 if def_id.crate == ast::LOCAL_CRATE {
2798 // prepend crate name if not already present
2799 let crate_namespace_ident = token::str_to_ident(cx.link_meta.crateid.name);
2800 item_path.insert(0, ast_map::PathMod(crate_namespace_ident));
2806 let mut current_key = vec::with_capacity(namespace_path.len());
2807 let mut parent_node: Option<@NamespaceTreeNode> = None;
2808 let last_index = namespace_path.len() - 1;
2810 // Create/Lookup namespace for each element of the path.
2811 for (i, &path_element) in namespace_path.iter().enumerate() {
2812 let ident = path_element.ident();
2813 current_key.push(ident);
2815 let existing_node = {
2816 let namespace_map = debug_context(cx).namespace_map.borrow();
2817 namespace_map.get().find_copy(¤t_key)
2819 let current_node = match existing_node {
2820 Some(existing_node) => existing_node,
2822 // create and insert
2823 let parent_scope = match parent_node {
2824 Some(node) => node.scope,
2827 let namespace_name_string = token::get_ident(ident.name);
2828 let namespace_name = namespace_name_string.get();
2830 let namespace_metadata = unsafe {
2831 namespace_name.with_c_str(|namespace_name| {
2832 llvm::LLVMDIBuilderCreateNameSpace(
2836 ptr::null(), // cannot reconstruct file ...
2837 0) // ... or line information, but that's not so important.
2841 let node = @NamespaceTreeNode {
2843 scope: namespace_metadata,
2844 parent: parent_node,
2848 let mut namespace_map = debug_context(cx).namespace_map
2850 namespace_map.get().insert(current_key.clone(), node);
2857 if i == last_index {
2858 return current_node;
2860 parent_node = Some(current_node);
2864 // Should be unreachable:
2865 let error_message = format!("debuginfo::namespace_for_item() - Code path should be \
2866 unreachable. namespace_path was {}",
2867 ast_map::path_to_str(namespace_path, token::get_ident_interner()));
2868 cx.sess.span_bug(warning_span, error_message);