]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/trans/debuginfo.rs
e88319e6d6773fadd3855a053a755ab887a43312
[rust.git] / src / librustc / middle / trans / debuginfo.rs
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.
4 //
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.
10
11 /*!
12 # Debug Info Module
13
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:
17
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.
23
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.
27
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)`.
31
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
34 module:
35
36     let file_metadata = file_metadata(crate_context, path);
37
38 The function will take care of probing the cache for an existing node for that exact file path.
39
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).
42
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
47
48
49 ## Recursive Types
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.
54
55 For example, the following simple type for a singly-linked list...
56
57 ```
58 struct List {
59     value: int,
60     tail: Option<@List>,
61 }
62 ```
63
64 will generate the following callstack with a naive DFS algorithm:
65
66 ```
67 describe(t = List)
68   describe(t = int)
69   describe(t = Option<@List>)
70     describe(t = @List)
71       describe(t = List) // at the beginning again...
72       ...
73 ```
74
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.
82
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)
87
88
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:
93
94 + set_source_location()
95 + clear_source_location()
96 + start_emitting_source_locations()
97
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.
105
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.
117
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.
124
125 */
126
127
128 use driver::session;
129 use driver::session::{FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
130 use lib::llvm::llvm;
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;
139 use middle::trans;
140 use middle::ty;
141 use middle::pat_util;
142 use util::ppaux;
143
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};
149 use std::ptr;
150 use std::sync::atomics;
151 use std::vec;
152 use syntax::codemap::{Span, Pos};
153 use syntax::{abi, ast, codemap, ast_util, ast_map, opt_vec};
154 use syntax::parse::token;
155 use syntax::parse::token::special_idents;
156
157 static DW_LANG_RUST: c_uint = 0x9000;
158
159 static DW_TAG_auto_variable: c_uint = 0x100;
160 static DW_TAG_arg_variable: c_uint = 0x101;
161
162 static DW_ATE_boolean: c_uint = 0x02;
163 static DW_ATE_float: c_uint = 0x04;
164 static DW_ATE_signed: c_uint = 0x05;
165 // static DW_ATE_signed_char: c_uint = 0x06;
166 static DW_ATE_unsigned: c_uint = 0x07;
167 static DW_ATE_unsigned_char: c_uint = 0x08;
168
169 //=-------------------------------------------------------------------------------------------------
170 //  Public Interface of debuginfo module
171 //=-------------------------------------------------------------------------------------------------
172
173 /// A context object for maintaining all state needed by the debuginfo module.
174 pub struct CrateDebugContext {
175     priv llcontext: ContextRef,
176     priv builder: DIBuilderRef,
177     priv current_debug_location: Cell<DebugLocation>,
178     priv created_files: RefCell<HashMap<~str, DIFile>>,
179     priv created_types: RefCell<HashMap<uint, DIType>>,
180     priv namespace_map: RefCell<HashMap<~[ast::Name], @NamespaceTreeNode>>,
181     // This collection is used to assert that composite types (structs, enums, ...) have their
182     // members only set once:
183     priv composite_types_completed: RefCell<HashSet<DIType>>,
184 }
185
186 impl CrateDebugContext {
187     pub fn new(llmod: ModuleRef) -> CrateDebugContext {
188         debug!("CrateDebugContext::new");
189         let builder = unsafe { llvm::LLVMDIBuilderCreate(llmod) };
190         // DIBuilder inherits context from the module, so we'd better use the same one
191         let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
192         return CrateDebugContext {
193             llcontext: llcontext,
194             builder: builder,
195             current_debug_location: Cell::new(UnknownLocation),
196             created_files: RefCell::new(HashMap::new()),
197             created_types: RefCell::new(HashMap::new()),
198             namespace_map: RefCell::new(HashMap::new()),
199             composite_types_completed: RefCell::new(HashSet::new()),
200         };
201     }
202 }
203
204 pub enum FunctionDebugContext {
205     priv FunctionDebugContext(~FunctionDebugContextData),
206     priv DebugInfoDisabled,
207     priv FunctionWithoutDebugInfo,
208 }
209
210 impl FunctionDebugContext {
211     fn get_ref<'a>(&'a self, cx: &CrateContext, span: Span) -> &'a FunctionDebugContextData {
212         match *self {
213             FunctionDebugContext(~ref data) => data,
214             DebugInfoDisabled => {
215                 cx.sess.span_bug(span, FunctionDebugContext::debuginfo_disabled_message());
216             }
217             FunctionWithoutDebugInfo => {
218                 cx.sess.span_bug(span, FunctionDebugContext::should_be_ignored_message());
219             }
220         }
221     }
222
223     fn debuginfo_disabled_message() -> &'static str {
224         "debuginfo: Error trying to access FunctionDebugContext although debug info is disabled!"
225     }
226
227     fn should_be_ignored_message() -> &'static str {
228         "debuginfo: Error trying to access FunctionDebugContext for function that should be \
229          ignored by debug info!"
230     }
231 }
232
233 struct FunctionDebugContextData {
234     scope_map: RefCell<HashMap<ast::NodeId, DIScope>>,
235     fn_metadata: DISubprogram,
236     argument_counter: Cell<uint>,
237     source_locations_enabled: Cell<bool>,
238 }
239
240 enum VariableAccess<'a> {
241     // The llptr given is an alloca containing the variable's value
242     DirectVariable { alloca: ValueRef },
243     // The llptr given is an alloca containing the start of some pointer chain leading to the
244     // variable's content.
245     IndirectVariable { alloca: ValueRef, address_operations: &'a [ValueRef] }
246 }
247
248 enum VariableKind {
249     ArgumentVariable(uint /*index*/),
250     LocalVariable,
251     CapturedVariable,
252 }
253
254 /// Create any deferred debug metadata nodes
255 pub fn finalize(cx: @CrateContext) {
256     if cx.dbg_cx.is_none() {
257         return;
258     }
259
260     debug!("finalize");
261     compile_unit_metadata(cx);
262     unsafe {
263         llvm::LLVMDIBuilderFinalize(DIB(cx));
264         llvm::LLVMDIBuilderDispose(DIB(cx));
265         // Debuginfo generation in LLVM by default uses a higher
266         // version of dwarf than OS X currently understands. We can
267         // instruct LLVM to emit an older version of dwarf, however,
268         // for OS X to understand. For more info see #11352
269         // This can be overridden using --llvm-opts -dwarf-version,N.
270         if cx.sess.targ_cfg.os == abi::OsMacos {
271             "Dwarf Version".with_c_str(
272                 |s| llvm::LLVMRustAddModuleFlag(cx.llmod, s, 2));
273         }
274
275         // Prevent bitcode readers from deleting the debug info.
276         "Debug Info Version".with_c_str(
277             |s| llvm::LLVMRustAddModuleFlag(cx.llmod, s,
278                                             llvm::LLVMRustDebugMetadataVersion));
279     };
280 }
281
282 /// Creates debug information for the given local variable.
283 ///
284 /// Adds the created metadata nodes directly to the crate's IR.
285 pub fn create_local_var_metadata(bcx: &Block, local: &ast::Local) {
286     if fn_should_be_ignored(bcx.fcx) {
287         return;
288     }
289
290     let cx = bcx.ccx();
291     let def_map = cx.tcx.def_map;
292
293     pat_util::pat_bindings(def_map, local.pat, |_, node_id, span, path_ref| {
294         let var_ident = ast_util::path_to_ident(path_ref);
295
296         let datum = {
297             let lllocals = bcx.fcx.lllocals.borrow();
298             match lllocals.get().find_copy(&node_id) {
299                 Some(datum) => datum,
300                 None => {
301                     bcx.tcx().sess.span_bug(span,
302                         format!("no entry in lllocals table for {:?}",
303                                 node_id));
304                 }
305             }
306         };
307
308         let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
309
310         declare_local(bcx,
311                       var_ident,
312                       datum.ty,
313                       scope_metadata,
314                       DirectVariable { alloca: datum.val },
315                       LocalVariable,
316                       span);
317     })
318 }
319
320 /// Creates debug information for a variable captured in a closure.
321 ///
322 /// Adds the created metadata nodes directly to the crate's IR.
323 pub fn create_captured_var_metadata(bcx: &Block,
324                                     node_id: ast::NodeId,
325                                     env_data_type: ty::t,
326                                     env_pointer: ValueRef,
327                                     env_index: uint,
328                                     closure_sigil: ast::Sigil,
329                                     span: Span) {
330     if fn_should_be_ignored(bcx.fcx) {
331         return;
332     }
333
334     let cx = bcx.ccx();
335
336     let ast_item = cx.tcx.map.find(node_id);
337
338     let variable_ident = match ast_item {
339         None => {
340             cx.sess.span_bug(span, "debuginfo::create_captured_var_metadata() - NodeId not found");
341         }
342         Some(ast_map::NodeLocal(pat)) | Some(ast_map::NodeArg(pat)) => {
343             match pat.node {
344                 ast::PatIdent(_, ref path, _) => {
345                     ast_util::path_to_ident(path)
346                 }
347                 _ => {
348                     cx.sess
349                       .span_bug(span,
350                                 format!(
351                                 "debuginfo::create_captured_var_metadata() - \
352                                  Captured var-id refers to unexpected \
353                                  ast_map variant: {:?}",
354                                  ast_item));
355                 }
356             }
357         }
358         _ => {
359             cx.sess.span_bug(span, format!("debuginfo::create_captured_var_metadata() - \
360                 Captured var-id refers to unexpected ast_map variant: {:?}", ast_item));
361         }
362     };
363
364     let variable_type = node_id_type(bcx, node_id);
365     let scope_metadata = bcx.fcx.debug_context.get_ref(cx, span).fn_metadata;
366
367     let llvm_env_data_type = type_of::type_of(cx, env_data_type);
368     let byte_offset_of_var_in_env = machine::llelement_offset(cx, llvm_env_data_type, env_index);
369
370     let address_operations = unsafe {
371         [llvm::LLVMDIBuilderCreateOpDeref(Type::i64().to_ref()),
372          llvm::LLVMDIBuilderCreateOpPlus(Type::i64().to_ref()),
373          C_i64(byte_offset_of_var_in_env as i64),
374          llvm::LLVMDIBuilderCreateOpDeref(Type::i64().to_ref())]
375     };
376
377     let address_op_count = match closure_sigil {
378         ast::BorrowedSigil => {
379             address_operations.len()
380         }
381         ast::ManagedSigil | ast::OwnedSigil => {
382             address_operations.len() - 1
383         }
384     };
385
386     let variable_access = IndirectVariable {
387         alloca: env_pointer,
388         address_operations: address_operations.slice_to(address_op_count)
389     };
390
391     declare_local(bcx,
392                   variable_ident,
393                   variable_type,
394                   scope_metadata,
395                   variable_access,
396                   CapturedVariable,
397                   span);
398 }
399
400 /// Creates debug information for a local variable introduced in the head of a match-statement arm.
401 ///
402 /// Adds the created metadata nodes directly to the crate's IR.
403 pub fn create_match_binding_metadata(bcx: &Block,
404                                      variable_ident: ast::Ident,
405                                      node_id: ast::NodeId,
406                                      span: Span,
407                                      datum: Datum<Lvalue>) {
408     if fn_should_be_ignored(bcx.fcx) {
409         return;
410     }
411
412     let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
413
414     declare_local(bcx,
415                   variable_ident,
416                   datum.ty,
417                   scope_metadata,
418                   DirectVariable { alloca: datum.val },
419                   LocalVariable,
420                   span);
421 }
422
423 /// Creates debug information for the given function argument.
424 ///
425 /// Adds the created metadata nodes directly to the crate's IR.
426 pub fn create_argument_metadata(bcx: &Block, arg: &ast::Arg) {
427     if fn_should_be_ignored(bcx.fcx) {
428         return;
429     }
430
431     let fcx = bcx.fcx;
432     let cx = fcx.ccx;
433
434     let def_map = cx.tcx.def_map;
435     let scope_metadata = bcx.fcx.debug_context.get_ref(cx, arg.pat.span).fn_metadata;
436
437     pat_util::pat_bindings(def_map, arg.pat, |_, node_id, span, path_ref| {
438         let llarg = {
439             let llargs = bcx.fcx.llargs.borrow();
440             match llargs.get().find_copy(&node_id) {
441                 Some(v) => v,
442                 None => {
443                     bcx.tcx().sess.span_bug(span,
444                         format!("no entry in llargs table for {:?}",
445                                 node_id));
446                 }
447             }
448         };
449
450         if unsafe { llvm::LLVMIsAAllocaInst(llarg.val) } == ptr::null() {
451             cx.sess.span_bug(span, "debuginfo::create_argument_metadata() - \
452                                     Referenced variable location is not an alloca!");
453         }
454
455         let argument_ident = ast_util::path_to_ident(path_ref);
456
457         let argument_index = {
458             let counter = &fcx.debug_context.get_ref(cx, span).argument_counter;
459             let argument_index = counter.get();
460             counter.set(argument_index + 1);
461             argument_index
462         };
463
464         declare_local(bcx,
465                       argument_ident,
466                       llarg.ty,
467                       scope_metadata,
468                       DirectVariable { alloca: llarg.val },
469                       ArgumentVariable(argument_index),
470                       span);
471     })
472 }
473
474 /// Sets the current debug location at the beginning of the span.
475 ///
476 /// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...). The node_id parameter is used to
477 /// reliably find the correct visibility scope for the code position.
478 pub fn set_source_location(fcx: &FunctionContext,
479                            node_id: ast::NodeId,
480                            span: Span) {
481     if fn_should_be_ignored(fcx) {
482         return;
483     }
484
485     let cx = fcx.ccx;
486
487     debug!("set_source_location: {}", cx.sess.codemap.span_to_str(span));
488
489     if fcx.debug_context.get_ref(cx, span).source_locations_enabled.get() {
490         let loc = span_start(cx, span);
491         let scope = scope_metadata(fcx, node_id, span);
492
493         set_debug_location(cx, DebugLocation::new(scope, loc.line, loc.col.to_uint()));
494     } else {
495         set_debug_location(cx, UnknownLocation);
496     }
497 }
498
499 /// Clears the current debug location.
500 ///
501 /// Instructions generated hereafter won't be assigned a source location.
502 pub fn clear_source_location(fcx: &FunctionContext) {
503     if fn_should_be_ignored(fcx) {
504         return;
505     }
506
507     set_debug_location(fcx.ccx, UnknownLocation);
508 }
509
510 /// Enables emitting source locations for the given functions.
511 ///
512 /// Since we don't want source locations to be emitted for the function prelude, they are disabled
513 /// when beginning to translate a new function. This functions switches source location emitting on
514 /// and must therefore be called before the first real statement/expression of the function is
515 /// translated.
516 pub fn start_emitting_source_locations(fcx: &FunctionContext) {
517     match fcx.debug_context {
518         FunctionDebugContext(~ref data) => {
519             data.source_locations_enabled.set(true)
520         },
521         _ => { /* safe to ignore */ }
522     }
523 }
524
525 /// Creates the function-specific debug context.
526 ///
527 /// Returns the FunctionDebugContext for the function which holds state needed for debug info
528 /// creation. The function may also return another variant of the FunctionDebugContext enum which
529 /// indicates why no debuginfo should be created for the function.
530 pub fn create_function_debug_context(cx: &CrateContext,
531                                      fn_ast_id: ast::NodeId,
532                                      param_substs: Option<@param_substs>,
533                                      llfn: ValueRef) -> FunctionDebugContext {
534     if cx.sess.opts.debuginfo == NoDebugInfo {
535         return DebugInfoDisabled;
536     }
537
538     if fn_ast_id == -1 {
539         return FunctionWithoutDebugInfo;
540     }
541
542     let empty_generics = ast::Generics { lifetimes: opt_vec::Empty, ty_params: opt_vec::Empty };
543
544     let fnitem = cx.tcx.map.get(fn_ast_id);
545
546     let (ident, fn_decl, generics, top_level_block, span, has_path) = match fnitem {
547         ast_map::NodeItem(ref item) => {
548             match item.node {
549                 ast::ItemFn(fn_decl, _, _, ref generics, top_level_block) => {
550                     (item.ident, fn_decl, generics, top_level_block, item.span, true)
551                 }
552                 _ => {
553                     cx.sess.span_bug(item.span,
554                         "create_function_debug_context: item bound to non-function");
555                 }
556             }
557         }
558         ast_map::NodeMethod(method) => {
559             (method.ident,
560              method.decl,
561              &method.generics,
562              method.body,
563              method.span,
564              true)
565         }
566         ast_map::NodeExpr(ref expr) => {
567             match expr.node {
568                 ast::ExprFnBlock(fn_decl, top_level_block) |
569                 ast::ExprProc(fn_decl, top_level_block) => {
570                     let name = format!("fn{}", token::gensym("fn"));
571                     let name = token::str_to_ident(name);
572                     (name, fn_decl,
573                         // This is not quite right. It should actually inherit the generics of the
574                         // enclosing function.
575                         &empty_generics,
576                         top_level_block,
577                         expr.span,
578                         // Don't try to lookup the item path:
579                         false)
580                 }
581                 _ => cx.sess.span_bug(expr.span,
582                         "create_function_debug_context: expected an expr_fn_block here")
583             }
584         }
585         ast_map::NodeTraitMethod(trait_method) => {
586             match *trait_method {
587                 ast::Provided(method) => {
588                     (method.ident,
589                      method.decl,
590                      &method.generics,
591                      method.body,
592                      method.span,
593                      true)
594                 }
595                 _ => {
596                     cx.sess
597                       .bug(format!("create_function_debug_context: \
598                                     unexpected sort of node: {:?}",
599                                     fnitem))
600                 }
601             }
602         }
603         ast_map::NodeForeignItem(..) |
604         ast_map::NodeVariant(..) |
605         ast_map::NodeStructCtor(..) => {
606             return FunctionWithoutDebugInfo;
607         }
608         _ => cx.sess.bug(format!("create_function_debug_context: \
609                                   unexpected sort of node: {:?}", fnitem))
610     };
611
612     // This can be the case for functions inlined from another crate
613     if span == codemap::DUMMY_SP {
614         return FunctionWithoutDebugInfo;
615     }
616
617     let loc = span_start(cx, span);
618     let file_metadata = file_metadata(cx, loc.file.name);
619
620     let function_type_metadata = unsafe {
621         let fn_signature = get_function_signature(cx, fn_ast_id, fn_decl, param_substs, span);
622         llvm::LLVMDIBuilderCreateSubroutineType(DIB(cx), file_metadata, fn_signature)
623     };
624
625     // get_template_parameters() will append a `<...>` clause to the function name if necessary.
626     let mut function_name = token::get_ident(ident).get().to_str();
627     let template_parameters = get_template_parameters(cx,
628                                                       generics,
629                                                       param_substs,
630                                                       file_metadata,
631                                                       &mut function_name);
632
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));
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)
641     } else {
642         (function_name.clone(), file_metadata)
643     };
644
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;
647
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)
657     };
658
659     let fn_metadata = function_name.with_c_str(|function_name| {
660                           linkage_name.with_c_str(|linkage_name| {
661             unsafe {
662                 llvm::LLVMDIBuilderCreateFunction(
663                     DIB(cx),
664                     containing_scope,
665                     function_name,
666                     linkage_name,
667                     file_metadata,
668                     loc.line as c_uint,
669                     function_type_metadata,
670                     is_local_to_unit,
671                     true,
672                     scope_line as c_uint,
673                     FlagPrototyped as c_uint,
674                     cx.sess.opts.optimize != session::No,
675                     llfn,
676                     template_parameters,
677                     ptr::null())
678             }
679         })
680     });
681
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),
688     };
689
690     let arg_pats = fn_decl.inputs.map(|arg_ref| arg_ref.pat);
691     {
692         let mut scope_map = fn_debug_context.scope_map.borrow_mut();
693         populate_scope_map(cx,
694                            arg_pats.as_slice(),
695                            top_level_block,
696                            fn_metadata,
697                            scope_map.get());
698     }
699
700     // Clear the debug location so we don't assign them in the function prelude
701     set_debug_location(cx, UnknownLocation);
702
703     return FunctionDebugContext(fn_debug_context);
704
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.debuginfo == LimitedDebugInfo {
711             return create_DIArray(DIB(cx), []);
712         }
713
714         let mut signature = vec::with_capacity(fn_decl.inputs.len() + 1);
715
716         // Return type -- llvm::DIBuilder wants this at index 0
717         match fn_decl.output.node {
718             ast::TyNil => {
719                 signature.push(ptr::null());
720             }
721             _ => {
722                 assert_type_for_node_id(cx, fn_ast_id, error_span);
723
724                 let return_type = ty::node_id_to_type(cx.tcx, fn_ast_id);
725                 let return_type = match param_substs {
726                     None => return_type,
727                     Some(substs) => {
728                         ty::subst_tps(cx.tcx, substs.tys, substs.self_ty, return_type)
729                     }
730                 };
731
732                 signature.push(type_metadata(cx, return_type, codemap::DUMMY_SP));
733             }
734         }
735
736         // Arguments types
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 {
741                 None => arg_type,
742                 Some(substs) => {
743                     ty::subst_tps(cx.tcx, substs.tys, substs.self_ty, arg_type)
744                 }
745             };
746
747             signature.push(type_metadata(cx, arg_type, codemap::DUMMY_SP));
748         }
749
750         return create_DIArray(DIB(cx), signature);
751     }
752
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)
758                             -> DIArray {
759         let self_type = match param_substs {
760             Some(param_substs) => param_substs.self_ty,
761             _ => None
762         };
763
764         // Only true for static default methods:
765         let has_self_type = self_type.is_some();
766
767         if !generics.is_type_parameterized() && !has_self_type {
768             return create_DIArray(DIB(cx), []);
769         }
770
771         name_to_append_suffix_to.push_char('<');
772
773         // The list to be filled with template parameters:
774         let mut template_params: ~[DIDescriptor] = vec::with_capacity(generics.ty_params.len() + 1);
775
776         // Handle self type
777         if has_self_type {
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);
782
783             if generics.is_type_parameterized() {
784                 name_to_append_suffix_to.push_str(",");
785             }
786
787             // Only create type information if full debuginfo is enabled
788             if cx.sess.opts.debuginfo == FullDebugInfo {
789                 let actual_self_type_metadata = type_metadata(cx,
790                                                               actual_self_type,
791                                                               codemap::DUMMY_SP);
792
793                 let ident = special_idents::type_self;
794
795                 let param_metadata = token::get_ident(ident).get()
796                                                             .with_c_str(|name| {
797                     unsafe {
798                         llvm::LLVMDIBuilderCreateTemplateTypeParameter(
799                             DIB(cx),
800                             file_metadata,
801                             name,
802                             actual_self_type_metadata,
803                             ptr::null(),
804                             0,
805                             0)
806                     }
807                 });
808
809                 template_params.push(param_metadata);
810             }
811         }
812
813         // Handle other generic parameters
814         let actual_types = match param_substs {
815             Some(param_substs) => &param_substs.tys,
816             None => {
817                 return create_DIArray(DIB(cx), template_params);
818             }
819         };
820
821         for (index, &ast::TyParam{ ident: ident, .. }) in generics.ty_params.iter().enumerate() {
822             let actual_type = actual_types[index];
823             // Add actual type name to <...> clause of function name
824             let actual_type_name = ppaux::ty_to_str(cx.tcx, actual_type);
825             name_to_append_suffix_to.push_str(actual_type_name);
826
827             if index != generics.ty_params.len() - 1 {
828                 name_to_append_suffix_to.push_str(",");
829             }
830
831             // Again, only create type information if full debuginfo is enabled
832             if cx.sess.opts.debuginfo == FullDebugInfo {
833                 let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP);
834                 let param_metadata = token::get_ident(ident).get()
835                                                             .with_c_str(|name| {
836                     unsafe {
837                         llvm::LLVMDIBuilderCreateTemplateTypeParameter(
838                             DIB(cx),
839                             file_metadata,
840                             name,
841                             actual_type_metadata,
842                             ptr::null(),
843                             0,
844                             0)
845                     }
846                 });
847                 template_params.push(param_metadata);
848             }
849         }
850
851         name_to_append_suffix_to.push_char('>');
852
853         return create_DIArray(DIB(cx), template_params);
854     }
855 }
856
857 //=-------------------------------------------------------------------------------------------------
858 // Module-Internal debug info creation functions
859 //=-------------------------------------------------------------------------------------------------
860
861 fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
862     return unsafe {
863         llvm::LLVMDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32)
864     };
865 }
866
867 fn compile_unit_metadata(cx: &CrateContext) {
868     let work_dir = &cx.sess.working_dir;
869     let compile_unit_name = match cx.sess.local_crate_source_file {
870         None => fallback_path(cx),
871         Some(ref abs_path) => {
872             if abs_path.is_relative() {
873                 cx.sess.warn("debuginfo: Invalid path to crate's local root source file!");
874                 fallback_path(cx)
875             } else {
876                 match abs_path.path_relative_from(work_dir) {
877                     Some(ref p) if p.is_relative() => {
878                             // prepend "./" if necessary
879                             let dotdot = bytes!("..");
880                             let prefix = &[dotdot[0], ::std::path::SEP_BYTE];
881                             let mut path_bytes = p.as_vec().to_owned();
882
883                             if path_bytes.slice_to(2) != prefix &&
884                                path_bytes.slice_to(2) != dotdot {
885                                 path_bytes.insert(0, prefix[0]);
886                                 path_bytes.insert(1, prefix[1]);
887                             }
888
889                             path_bytes.to_c_str()
890                         }
891                     _ => fallback_path(cx)
892                 }
893             }
894         }
895     };
896
897     debug!("compile_unit_metadata: {:?}", compile_unit_name);
898     let producer = format!("rustc version {}", env!("CFG_VERSION"));
899
900     compile_unit_name.with_ref(|compile_unit_name| {
901         work_dir.as_vec().with_c_str(|work_dir| {
902             producer.with_c_str(|producer| {
903                 "".with_c_str(|flags| {
904                     "".with_c_str(|split_name| {
905                         unsafe {
906                             llvm::LLVMDIBuilderCreateCompileUnit(
907                                 debug_context(cx).builder,
908                                 DW_LANG_RUST,
909                                 compile_unit_name,
910                                 work_dir,
911                                 producer,
912                                 cx.sess.opts.optimize != session::No,
913                                 flags,
914                                 0,
915                                 split_name);
916                         }
917                     })
918                 })
919             })
920         })
921     });
922
923     fn fallback_path(cx: &CrateContext) -> CString {
924         cx.link_meta.crateid.name.to_c_str()
925     }
926 }
927
928 fn declare_local(bcx: &Block,
929                  variable_ident: ast::Ident,
930                  variable_type: ty::t,
931                  scope_metadata: DIScope,
932                  variable_access: VariableAccess,
933                  variable_kind: VariableKind,
934                  span: Span) {
935     let cx: &CrateContext = bcx.ccx();
936
937     let filename = span_start(cx, span).file.name.clone();
938     let file_metadata = file_metadata(cx, filename);
939
940     let name = token::get_ident(variable_ident);
941     let loc = span_start(cx, span);
942     let type_metadata = type_metadata(cx, variable_type, span);
943
944     let (argument_index, dwarf_tag) = match variable_kind {
945         ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),
946         LocalVariable    |
947         CapturedVariable => (0, DW_TAG_auto_variable)
948     };
949
950     let (var_alloca, var_metadata) = name.get().with_c_str(|name| {
951         match variable_access {
952             DirectVariable { alloca } => (
953                 alloca,
954                 unsafe {
955                     llvm::LLVMDIBuilderCreateLocalVariable(
956                         DIB(cx),
957                         dwarf_tag,
958                         scope_metadata,
959                         name,
960                         file_metadata,
961                         loc.line as c_uint,
962                         type_metadata,
963                         cx.sess.opts.optimize != session::No,
964                         0,
965                         argument_index)
966                 }
967             ),
968             IndirectVariable { alloca, address_operations } => (
969                 alloca,
970                 unsafe {
971                     llvm::LLVMDIBuilderCreateComplexVariable(
972                         DIB(cx),
973                         dwarf_tag,
974                         scope_metadata,
975                         name,
976                         file_metadata,
977                         loc.line as c_uint,
978                         type_metadata,
979                         address_operations.as_ptr(),
980                         address_operations.len() as c_uint,
981                         argument_index)
982                 }
983             )
984         }
985     });
986
987     set_debug_location(cx, DebugLocation::new(scope_metadata, loc.line, loc.col.to_uint()));
988     unsafe {
989         let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
990             DIB(cx),
991             var_alloca,
992             var_metadata,
993             bcx.llbb);
994
995         llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr);
996     }
997
998     match variable_kind {
999         ArgumentVariable(_) | CapturedVariable => {
1000             assert!(!bcx.fcx
1001                         .debug_context
1002                         .get_ref(cx, span)
1003                         .source_locations_enabled
1004                         .get());
1005             set_debug_location(cx, UnknownLocation);
1006         }
1007         _ => { /* nothing to do */ }
1008     }
1009 }
1010
1011 fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
1012     {
1013         let created_files = debug_context(cx).created_files.borrow();
1014         match created_files.get().find_equiv(&full_path) {
1015             Some(file_metadata) => return *file_metadata,
1016             None => ()
1017         }
1018     }
1019
1020     debug!("file_metadata: {}", full_path);
1021
1022     // FIXME (#9639): This needs to handle non-utf8 paths
1023     let work_dir = cx.sess.working_dir.as_str().unwrap();
1024     let file_name =
1025         if full_path.starts_with(work_dir) {
1026             full_path.slice(work_dir.len() + 1u, full_path.len())
1027         } else {
1028             full_path
1029         };
1030
1031     let file_metadata =
1032         file_name.with_c_str(|file_name| {
1033             work_dir.with_c_str(|work_dir| {
1034                 unsafe {
1035                     llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir)
1036                 }
1037             })
1038         });
1039
1040     let mut created_files = debug_context(cx).created_files.borrow_mut();
1041     created_files.get().insert(full_path.to_owned(), file_metadata);
1042     return file_metadata;
1043 }
1044
1045 /// Finds the scope metadata node for the given AST node.
1046 fn scope_metadata(fcx: &FunctionContext,
1047                   node_id: ast::NodeId,
1048                   span: Span)
1049                -> DIScope {
1050     let scope_map = &fcx.debug_context.get_ref(fcx.ccx, span).scope_map;
1051     let scope_map = scope_map.borrow();
1052
1053     match scope_map.get().find_copy(&node_id) {
1054         Some(scope_metadata) => scope_metadata,
1055         None => {
1056             let node = fcx.ccx.tcx.map.get(node_id);
1057
1058             fcx.ccx.sess.span_bug(span,
1059                 format!("debuginfo: Could not find scope info for node {:?}", node));
1060         }
1061     }
1062 }
1063
1064 fn basic_type_metadata(cx: &CrateContext, t: ty::t) -> DIType {
1065
1066     debug!("basic_type_metadata: {:?}", ty::get(t));
1067
1068     let (name, encoding) = match ty::get(t).sty {
1069         ty::ty_nil => (~"()", DW_ATE_unsigned),
1070         ty::ty_bot => (~"!", DW_ATE_unsigned),
1071         ty::ty_bool => (~"bool", DW_ATE_boolean),
1072         ty::ty_char => (~"char", DW_ATE_unsigned_char),
1073         ty::ty_int(int_ty) => match int_ty {
1074             ast::TyI => (~"int", DW_ATE_signed),
1075             ast::TyI8 => (~"i8", DW_ATE_signed),
1076             ast::TyI16 => (~"i16", DW_ATE_signed),
1077             ast::TyI32 => (~"i32", DW_ATE_signed),
1078             ast::TyI64 => (~"i64", DW_ATE_signed)
1079         },
1080         ty::ty_uint(uint_ty) => match uint_ty {
1081             ast::TyU => (~"uint", DW_ATE_unsigned),
1082             ast::TyU8 => (~"u8", DW_ATE_unsigned),
1083             ast::TyU16 => (~"u16", DW_ATE_unsigned),
1084             ast::TyU32 => (~"u32", DW_ATE_unsigned),
1085             ast::TyU64 => (~"u64", DW_ATE_unsigned)
1086         },
1087         ty::ty_float(float_ty) => match float_ty {
1088             ast::TyF32 => (~"f32", DW_ATE_float),
1089             ast::TyF64 => (~"f64", DW_ATE_float)
1090         },
1091         _ => cx.sess.bug("debuginfo::basic_type_metadata - t is invalid type")
1092     };
1093
1094     let llvm_type = type_of::type_of(cx, t);
1095     let (size, align) = size_and_align_of(cx, llvm_type);
1096     let ty_metadata = name.with_c_str(|name| {
1097         unsafe {
1098             llvm::LLVMDIBuilderCreateBasicType(
1099                 DIB(cx),
1100                 name,
1101                 bytes_to_bits(size),
1102                 bytes_to_bits(align),
1103                 encoding)
1104         }
1105     });
1106
1107     return ty_metadata;
1108 }
1109
1110 fn pointer_type_metadata(cx: &CrateContext,
1111                          pointer_type: ty::t,
1112                          pointee_type_metadata: DIType)
1113                       -> DIType {
1114     let pointer_llvm_type = type_of::type_of(cx, pointer_type);
1115     let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
1116     let name = ppaux::ty_to_str(cx.tcx, pointer_type);
1117     let ptr_metadata = name.with_c_str(|name| {
1118         unsafe {
1119             llvm::LLVMDIBuilderCreatePointerType(
1120                 DIB(cx),
1121                 pointee_type_metadata,
1122                 bytes_to_bits(pointer_size),
1123                 bytes_to_bits(pointer_align),
1124                 name)
1125         }
1126     });
1127     return ptr_metadata;
1128 }
1129
1130 enum MemberDescriptionFactory {
1131     StructMD(StructMemberDescriptionFactory),
1132     TupleMD(TupleMemberDescriptionFactory),
1133     GeneralMD(GeneralMemberDescriptionFactory),
1134     EnumVariantMD(EnumVariantMemberDescriptionFactory)
1135 }
1136
1137 impl MemberDescriptionFactory {
1138     fn create_member_descriptions(&self, cx: &CrateContext)
1139                                   -> ~[MemberDescription] {
1140         match *self {
1141             StructMD(ref this) => {
1142                 this.create_member_descriptions(cx)
1143             }
1144             TupleMD(ref this) => {
1145                 this.create_member_descriptions(cx)
1146             }
1147             GeneralMD(ref this) => {
1148                 this.create_member_descriptions(cx)
1149             }
1150             EnumVariantMD(ref this) => {
1151                 this.create_member_descriptions(cx)
1152             }
1153         }
1154     }
1155 }
1156
1157 struct StructMemberDescriptionFactory {
1158     fields: ~[ty::field],
1159     span: Span,
1160 }
1161
1162 impl StructMemberDescriptionFactory {
1163     fn create_member_descriptions(&self, cx: &CrateContext)
1164                                   -> ~[MemberDescription] {
1165         self.fields.map(|field| {
1166             let name = if field.ident.name == special_idents::unnamed_field.name {
1167                 ~""
1168             } else {
1169                 token::get_ident(field.ident).get().to_str()
1170             };
1171
1172             MemberDescription {
1173                 name: name,
1174                 llvm_type: type_of::type_of(cx, field.mt.ty),
1175                 type_metadata: type_metadata(cx, field.mt.ty, self.span),
1176                 offset: ComputedMemberOffset,
1177             }
1178         })
1179     }
1180 }
1181
1182 fn prepare_struct_metadata(cx: &CrateContext,
1183                            struct_type: ty::t,
1184                            def_id: ast::DefId,
1185                            substs: &ty::substs,
1186                            span: Span)
1187                         -> RecursiveTypeDescription {
1188     let struct_name = ppaux::ty_to_str(cx.tcx, struct_type);
1189     let struct_llvm_type = type_of::type_of(cx, struct_type);
1190
1191     let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id);
1192
1193     let file_name = span_start(cx, definition_span).file.name.clone();
1194     let file_metadata = file_metadata(cx, file_name);
1195
1196     let struct_metadata_stub = create_struct_stub(cx,
1197                                                   struct_llvm_type,
1198                                                   struct_name,
1199                                                   containing_scope,
1200                                                   file_metadata,
1201                                                   definition_span);
1202
1203     let fields = ty::struct_fields(cx.tcx, def_id, substs);
1204
1205     UnfinishedMetadata {
1206         cache_id: cache_id_for_type(struct_type),
1207         metadata_stub: struct_metadata_stub,
1208         llvm_type: struct_llvm_type,
1209         file_metadata: file_metadata,
1210         member_description_factory: StructMD(StructMemberDescriptionFactory {
1211             fields: fields,
1212             span: span,
1213         }),
1214     }
1215 }
1216
1217 enum RecursiveTypeDescription {
1218     UnfinishedMetadata {
1219         cache_id: uint,
1220         metadata_stub: DICompositeType,
1221         llvm_type: Type,
1222         file_metadata: DIFile,
1223         member_description_factory: MemberDescriptionFactory,
1224     },
1225     FinalMetadata(DICompositeType)
1226 }
1227
1228 impl RecursiveTypeDescription {
1229
1230     fn finalize(&self, cx: &CrateContext) -> DICompositeType {
1231         match *self {
1232             FinalMetadata(metadata) => metadata,
1233             UnfinishedMetadata {
1234                 cache_id,
1235                 metadata_stub,
1236                 llvm_type,
1237                 file_metadata,
1238                 ref member_description_factory
1239             } => {
1240                 // Insert the stub into the cache in order to allow recursive references ...
1241                 {
1242                     let mut created_types = debug_context(cx).created_types.borrow_mut();
1243                     created_types.get().insert(cache_id, metadata_stub);
1244                 }
1245
1246                 // ... then create the member descriptions ...
1247                 let member_descriptions = member_description_factory.create_member_descriptions(cx);
1248
1249                 // ... and attach them to the stub to complete it.
1250                 set_members_of_composite_type(cx,
1251                                               metadata_stub,
1252                                               llvm_type,
1253                                               member_descriptions,
1254                                               file_metadata,
1255                                               codemap::DUMMY_SP);
1256                 return metadata_stub;
1257             }
1258         }
1259     }
1260 }
1261
1262 struct TupleMemberDescriptionFactory {
1263     component_types: ~[ty::t],
1264     span: Span,
1265 }
1266
1267 impl TupleMemberDescriptionFactory {
1268     fn create_member_descriptions(&self, cx: &CrateContext)
1269                                   -> ~[MemberDescription] {
1270         self.component_types.map(|&component_type| {
1271             MemberDescription {
1272                 name: ~"",
1273                 llvm_type: type_of::type_of(cx, component_type),
1274                 type_metadata: type_metadata(cx, component_type, self.span),
1275                 offset: ComputedMemberOffset,
1276             }
1277         })
1278     }
1279 }
1280
1281 fn prepare_tuple_metadata(cx: &CrateContext,
1282                           tuple_type: ty::t,
1283                           component_types: &[ty::t],
1284                           span: Span)
1285                        -> RecursiveTypeDescription {
1286     let tuple_name = ppaux::ty_to_str(cx.tcx, tuple_type);
1287     let tuple_llvm_type = type_of::type_of(cx, tuple_type);
1288
1289     let loc = span_start(cx, span);
1290     let file_metadata = file_metadata(cx, loc.file.name);
1291
1292     UnfinishedMetadata {
1293         cache_id: cache_id_for_type(tuple_type),
1294         metadata_stub: create_struct_stub(cx,
1295                                           tuple_llvm_type,
1296                                           tuple_name,
1297                                           file_metadata,
1298                                           file_metadata,
1299                                           span),
1300         llvm_type: tuple_llvm_type,
1301         file_metadata: file_metadata,
1302         member_description_factory: TupleMD(TupleMemberDescriptionFactory {
1303             component_types: component_types.to_owned(),
1304             span: span,
1305         })
1306     }
1307 }
1308
1309 struct GeneralMemberDescriptionFactory {
1310     type_rep: @adt::Repr,
1311     variants: @~[@ty::VariantInfo],
1312     discriminant_type_metadata: ValueRef,
1313     containing_scope: DIScope,
1314     file_metadata: DIFile,
1315     span: Span,
1316 }
1317
1318 impl GeneralMemberDescriptionFactory {
1319     fn create_member_descriptions(&self, cx: &CrateContext)
1320                                   -> ~[MemberDescription] {
1321         // Capture type_rep, so we don't have to copy the struct_defs array
1322         let struct_defs = match *self.type_rep {
1323             adt::General(_, ref struct_defs) => struct_defs,
1324             _ => cx.sess.bug("unreachable")
1325         };
1326
1327         struct_defs
1328             .iter()
1329             .enumerate()
1330             .map(|(i, struct_def)| {
1331                 let (variant_type_metadata, variant_llvm_type, member_desc_factory) =
1332                     describe_enum_variant(cx,
1333                                           struct_def,
1334                                           self.variants[i],
1335                                           Some(self.discriminant_type_metadata),
1336                                           self.containing_scope,
1337                                           self.file_metadata,
1338                                           self.span);
1339
1340                 let member_descriptions =
1341                     member_desc_factory.create_member_descriptions(cx);
1342
1343                 set_members_of_composite_type(cx,
1344                                               variant_type_metadata,
1345                                               variant_llvm_type,
1346                                               member_descriptions,
1347                                               self.file_metadata,
1348                                               codemap::DUMMY_SP);
1349                 MemberDescription {
1350                     name: ~"",
1351                     llvm_type: variant_llvm_type,
1352                     type_metadata: variant_type_metadata,
1353                     offset: FixedMemberOffset { bytes: 0 },
1354                 }
1355         }).collect()
1356     }
1357 }
1358
1359 struct EnumVariantMemberDescriptionFactory {
1360     args: ~[(~str, ty::t)],
1361     discriminant_type_metadata: Option<DIType>,
1362     span: Span,
1363 }
1364
1365 impl EnumVariantMemberDescriptionFactory {
1366     fn create_member_descriptions(&self, cx: &CrateContext)
1367                                   -> ~[MemberDescription] {
1368         self.args.iter().enumerate().map(|(i, &(ref name, ty))| {
1369             MemberDescription {
1370                 name: name.to_str(),
1371                 llvm_type: type_of::type_of(cx, ty),
1372                 type_metadata: match self.discriminant_type_metadata {
1373                     Some(metadata) if i == 0 => metadata,
1374                     _ => type_metadata(cx, ty, self.span)
1375                 },
1376                 offset: ComputedMemberOffset,
1377             }
1378         }).collect()
1379     }
1380 }
1381
1382 fn describe_enum_variant(cx: &CrateContext,
1383                          struct_def: &adt::Struct,
1384                          variant_info: &ty::VariantInfo,
1385                          discriminant_type_metadata: Option<DIType>,
1386                          containing_scope: DIScope,
1387                          file_metadata: DIFile,
1388                          span: Span)
1389                       -> (DICompositeType, Type, MemberDescriptionFactory) {
1390     let variant_llvm_type = Type::struct_(struct_def.fields.map(|&t| type_of::type_of(cx, t)),
1391                                           struct_def.packed);
1392     // Could some consistency checks here: size, align, field count, discr type
1393
1394     // Find the source code location of the variant's definition
1395     let variant_definition_span = if variant_info.id.krate == ast::LOCAL_CRATE {
1396         cx.tcx.map.span(variant_info.id.node)
1397     } else {
1398         // For definitions from other crates we have no location information available.
1399         codemap::DUMMY_SP
1400     };
1401
1402     let metadata_stub = create_struct_stub(cx,
1403                                            variant_llvm_type,
1404                                            token::get_ident(variant_info.name).get(),
1405                                            containing_scope,
1406                                            file_metadata,
1407                                            variant_definition_span);
1408
1409     // Get the argument names from the enum variant info
1410     let mut arg_names = match variant_info.arg_names {
1411         Some(ref names) => {
1412             names.map(|ident| token::get_ident(*ident).get().to_str())
1413         }
1414         None => variant_info.args.map(|_| ~"")
1415     };
1416
1417     // If this is not a univariant enum, there is also the (unnamed) discriminant field
1418     if discriminant_type_metadata.is_some() {
1419         arg_names.insert(0, ~"");
1420     }
1421
1422     // Build an array of (field name, field type) pairs to be captured in the factory closure.
1423     let args: ~[(~str, ty::t)] = arg_names.iter()
1424         .zip(struct_def.fields.iter())
1425         .map(|(s, &t)| (s.to_str(), t))
1426         .collect();
1427
1428     let member_description_factory =
1429         EnumVariantMD(EnumVariantMemberDescriptionFactory {
1430             args: args,
1431             discriminant_type_metadata: discriminant_type_metadata,
1432             span: span,
1433         });
1434
1435     (metadata_stub, variant_llvm_type, member_description_factory)
1436 }
1437
1438 fn prepare_enum_metadata(cx: &CrateContext,
1439                          enum_type: ty::t,
1440                          enum_def_id: ast::DefId,
1441                          span: Span)
1442                       -> RecursiveTypeDescription {
1443     let enum_name = ppaux::ty_to_str(cx.tcx, enum_type);
1444
1445     let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, enum_def_id);
1446     let loc = span_start(cx, definition_span);
1447     let file_metadata = file_metadata(cx, loc.file.name);
1448
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,
1453                                                           Type::nil(),
1454                                                           enum_name,
1455                                                           [],
1456                                                           containing_scope,
1457                                                           file_metadata,
1458                                                           definition_span);
1459
1460         return FinalMetadata(empty_type_metadata);
1461     }
1462
1463     let variants = ty::enum_variants(cx.tcx, enum_def_id);
1464
1465     let enumerators_metadata: ~[DIDescriptor] = variants
1466         .iter()
1467         .map(|v| {
1468             token::get_ident(v.name).get().with_c_str(|name| {
1469                 unsafe {
1470                     llvm::LLVMDIBuilderCreateEnumerator(
1471                         DIB(cx),
1472                         name,
1473                         v.disr_val as c_ulonglong)
1474                 }
1475             })
1476         })
1477         .collect();
1478
1479     let discriminant_type_metadata = |inttype| {
1480         let discriminant_llvm_type = adt::ll_inttype(cx, inttype);
1481         let (discriminant_size, discriminant_align) = size_and_align_of(cx, discriminant_llvm_type);
1482         let discriminant_base_type_metadata = type_metadata(cx, adt::ty_of_inttype(inttype),
1483                                                             codemap::DUMMY_SP);
1484         enum_name.with_c_str(|enum_name| {
1485             unsafe {
1486                 llvm::LLVMDIBuilderCreateEnumerationType(
1487                     DIB(cx),
1488                     containing_scope,
1489                     enum_name,
1490                     file_metadata,
1491                     loc.line as c_uint,
1492                     bytes_to_bits(discriminant_size),
1493                     bytes_to_bits(discriminant_align),
1494                     create_DIArray(DIB(cx), enumerators_metadata),
1495                     discriminant_base_type_metadata)
1496             }
1497         })
1498     };
1499
1500     let type_rep = adt::represent_type(cx, enum_type);
1501
1502     return match *type_rep {
1503         adt::CEnum(inttype, _, _) => {
1504             FinalMetadata(discriminant_type_metadata(inttype))
1505         }
1506         adt::Univariant(ref struct_def, _) => {
1507             assert!(variants.len() == 1);
1508             let (metadata_stub,
1509                  variant_llvm_type,
1510                  member_description_factory) = describe_enum_variant(cx,
1511                                                                      struct_def,
1512                                                                      variants[0],
1513                                                                      None,
1514                                                                      containing_scope,
1515                                                                      file_metadata,
1516                                                                      span);
1517             UnfinishedMetadata {
1518                 cache_id: cache_id_for_type(enum_type),
1519                 metadata_stub: metadata_stub,
1520                 llvm_type: variant_llvm_type,
1521                 file_metadata: file_metadata,
1522                 member_description_factory: member_description_factory
1523             }
1524         }
1525         adt::General(inttype, _) => {
1526             let discriminant_type_metadata = discriminant_type_metadata(inttype);
1527             let enum_llvm_type = type_of::type_of(cx, enum_type);
1528             let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type);
1529             let unique_id = generate_unique_type_id("DI_ENUM_");
1530
1531             let enum_metadata = enum_name.with_c_str(|enum_name| {
1532                 unique_id.with_c_str(|unique_id| {
1533                     unsafe {
1534                         llvm::LLVMDIBuilderCreateUnionType(
1535                         DIB(cx),
1536                         containing_scope,
1537                         enum_name,
1538                         file_metadata,
1539                         loc.line as c_uint,
1540                         bytes_to_bits(enum_type_size),
1541                         bytes_to_bits(enum_type_align),
1542                         0, // Flags
1543                         ptr::null(),
1544                         0, // RuntimeLang
1545                         unique_id)
1546                     }
1547                 })
1548             });
1549
1550             UnfinishedMetadata {
1551                 cache_id: cache_id_for_type(enum_type),
1552                 metadata_stub: enum_metadata,
1553                 llvm_type: enum_llvm_type,
1554                 file_metadata: file_metadata,
1555                 member_description_factory: GeneralMD(GeneralMemberDescriptionFactory {
1556                     type_rep: type_rep,
1557                     variants: variants,
1558                     discriminant_type_metadata: discriminant_type_metadata,
1559                     containing_scope: containing_scope,
1560                     file_metadata: file_metadata,
1561                     span: span,
1562                 }),
1563             }
1564         }
1565         adt::NullablePointer { nonnull: ref struct_def, nndiscr, .. } => {
1566             let (metadata_stub,
1567                  variant_llvm_type,
1568                  member_description_factory) = describe_enum_variant(cx,
1569                                                                      struct_def,
1570                                                                      variants[nndiscr],
1571                                                                      None,
1572                                                                      containing_scope,
1573                                                                      file_metadata,
1574                                                                      span);
1575             UnfinishedMetadata {
1576                 cache_id: cache_id_for_type(enum_type),
1577                 metadata_stub: metadata_stub,
1578                 llvm_type: variant_llvm_type,
1579                 file_metadata: file_metadata,
1580                 member_description_factory: member_description_factory
1581             }
1582         }
1583     };
1584 }
1585
1586 enum MemberOffset {
1587     FixedMemberOffset { bytes: uint },
1588     // For ComputedMemberOffset, the offset is read from the llvm type definition
1589     ComputedMemberOffset
1590 }
1591
1592 struct MemberDescription {
1593     name: ~str,
1594     llvm_type: Type,
1595     type_metadata: DIType,
1596     offset: MemberOffset,
1597 }
1598
1599 /// Creates debug information for a composite type, that is, anything that results in a LLVM struct.
1600 ///
1601 /// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums.
1602 fn composite_type_metadata(cx: &CrateContext,
1603                            composite_llvm_type: Type,
1604                            composite_type_name: &str,
1605                            member_descriptions: &[MemberDescription],
1606                            containing_scope: DIScope,
1607                            file_metadata: DIFile,
1608                            definition_span: Span)
1609                         -> DICompositeType {
1610     // Create the (empty) struct metadata node ...
1611     let composite_type_metadata = create_struct_stub(cx,
1612                                                      composite_llvm_type,
1613                                                      composite_type_name,
1614                                                      containing_scope,
1615                                                      file_metadata,
1616                                                      definition_span);
1617
1618     // ... and immediately create and add the member descriptions.
1619     set_members_of_composite_type(cx,
1620                                   composite_type_metadata,
1621                                   composite_llvm_type,
1622                                   member_descriptions,
1623                                   file_metadata,
1624                                   definition_span);
1625
1626     return composite_type_metadata;
1627 }
1628
1629 fn set_members_of_composite_type(cx: &CrateContext,
1630                                  composite_type_metadata: DICompositeType,
1631                                  composite_llvm_type: Type,
1632                                  member_descriptions: &[MemberDescription],
1633                                  file_metadata: DIFile,
1634                                  definition_span: Span) {
1635     // In some rare cases LLVM metadata uniquing would lead to an existing type description being
1636     // used instead of a new one created in create_struct_stub. This would cause a hard to trace
1637     // assertion in DICompositeType::SetTypeArray(). The following check makes sure that we get a
1638     // better error message if this should happen again due to some regression.
1639     {
1640         let mut composite_types_completed =
1641             debug_context(cx).composite_types_completed.borrow_mut();
1642         if composite_types_completed.get().contains(&composite_type_metadata) {
1643             cx.sess.span_bug(definition_span, "debuginfo::set_members_of_composite_type() - \
1644                                                Already completed forward declaration \
1645                                                re-encountered.");
1646         } else {
1647             composite_types_completed.get().insert(composite_type_metadata);
1648         }
1649     }
1650
1651     let loc = span_start(cx, definition_span);
1652
1653     let member_metadata: ~[DIDescriptor] = member_descriptions
1654         .iter()
1655         .enumerate()
1656         .map(|(i, member_description)| {
1657             let (member_size, member_align) = size_and_align_of(cx, member_description.llvm_type);
1658             let member_offset = match member_description.offset {
1659                 FixedMemberOffset { bytes } => bytes as u64,
1660                 ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i)
1661             };
1662
1663             member_description.name.with_c_str(|member_name| {
1664                 unsafe {
1665                     llvm::LLVMDIBuilderCreateMemberType(
1666                         DIB(cx),
1667                         composite_type_metadata,
1668                         member_name,
1669                         file_metadata,
1670                         loc.line as c_uint,
1671                         bytes_to_bits(member_size),
1672                         bytes_to_bits(member_align),
1673                         bytes_to_bits(member_offset),
1674                         0,
1675                         member_description.type_metadata)
1676                 }
1677             })
1678         })
1679         .collect();
1680
1681     unsafe {
1682         let type_array = create_DIArray(DIB(cx), member_metadata);
1683         llvm::LLVMDICompositeTypeSetTypeArray(composite_type_metadata, type_array);
1684     }
1685 }
1686
1687 // A convenience wrapper around LLVMDIBuilderCreateStructType(). Does not do any caching, does not
1688 // add any fields to the struct. This can be done later with set_members_of_composite_type().
1689 fn create_struct_stub(cx: &CrateContext,
1690                       struct_llvm_type: Type,
1691                       struct_type_name: &str,
1692                       containing_scope: DIScope,
1693                       file_metadata: DIFile,
1694                       definition_span: Span)
1695                    -> DICompositeType {
1696     let loc = span_start(cx, definition_span);
1697     let (struct_size, struct_align) = size_and_align_of(cx, struct_llvm_type);
1698
1699     // We assign unique IDs to the type stubs so LLVM metadata uniquing does not reuse instances
1700     // where we don't want it.
1701     let unique_id = generate_unique_type_id("DI_STRUCT_");
1702
1703     return unsafe {
1704         struct_type_name.with_c_str(|name| {
1705             unique_id.with_c_str(|unique_id| {
1706                 // LLVMDIBuilderCreateStructType() wants an empty array. A null pointer will lead to
1707                 // hard to trace and debug LLVM assertions later on in llvm/lib/IR/Value.cpp
1708                 let empty_array = create_DIArray(DIB(cx), []);
1709
1710                 llvm::LLVMDIBuilderCreateStructType(
1711                     DIB(cx),
1712                     containing_scope,
1713                     name,
1714                     file_metadata,
1715                     loc.line as c_uint,
1716                     bytes_to_bits(struct_size),
1717                     bytes_to_bits(struct_align),
1718                     0,
1719                     ptr::null(),
1720                     empty_array,
1721                     0,
1722                     ptr::null(),
1723                     unique_id)
1724             })
1725         })
1726     };
1727 }
1728
1729 fn boxed_type_metadata(cx: &CrateContext,
1730                        content_type_name: Option<&str>,
1731                        content_llvm_type: Type,
1732                        content_type_metadata: DIType,
1733                        span: Span)
1734                     -> DICompositeType {
1735     let box_type_name = match content_type_name {
1736         Some(content_type_name) => format!("Boxed<{}>", content_type_name),
1737         None                    => ~"BoxedType"
1738     };
1739
1740     let box_llvm_type = Type::at_box(cx, content_llvm_type);
1741     let member_llvm_types = box_llvm_type.field_types();
1742     assert!(box_layout_is_correct(cx, member_llvm_types, content_llvm_type));
1743
1744     let int_type = ty::mk_int();
1745     let nil_pointer_type = ty::mk_nil_ptr(cx.tcx);
1746     let nil_pointer_type_metadata = type_metadata(cx, nil_pointer_type, codemap::DUMMY_SP);
1747
1748     let member_descriptions = [
1749         MemberDescription {
1750             name: ~"refcnt",
1751             llvm_type: member_llvm_types[0],
1752             type_metadata: type_metadata(cx, int_type, codemap::DUMMY_SP),
1753             offset: ComputedMemberOffset,
1754         },
1755         MemberDescription {
1756             name: ~"drop_glue",
1757             llvm_type: member_llvm_types[1],
1758             type_metadata: nil_pointer_type_metadata,
1759             offset: ComputedMemberOffset,
1760         },
1761         MemberDescription {
1762             name: ~"prev",
1763             llvm_type: member_llvm_types[2],
1764             type_metadata: nil_pointer_type_metadata,
1765             offset: ComputedMemberOffset,
1766         },
1767         MemberDescription {
1768             name: ~"next",
1769             llvm_type: member_llvm_types[3],
1770             type_metadata: nil_pointer_type_metadata,
1771             offset: ComputedMemberOffset,
1772         },
1773         MemberDescription {
1774             name: ~"val",
1775             llvm_type: member_llvm_types[4],
1776             type_metadata: content_type_metadata,
1777             offset: ComputedMemberOffset,
1778         }
1779     ];
1780
1781     let loc = span_start(cx, span);
1782     let file_metadata = file_metadata(cx, loc.file.name);
1783
1784     return composite_type_metadata(
1785         cx,
1786         box_llvm_type,
1787         box_type_name,
1788         member_descriptions,
1789         file_metadata,
1790         file_metadata,
1791         span);
1792
1793     // Unfortunately, we cannot assert anything but the correct types here---and not whether the
1794     // 'next' and 'prev' pointers are in the correct order.
1795     fn box_layout_is_correct(cx: &CrateContext,
1796                              member_llvm_types: &[Type],
1797                              content_llvm_type: Type)
1798                           -> bool {
1799         member_llvm_types.len() == 5 &&
1800         member_llvm_types[0] == cx.int_type &&
1801         member_llvm_types[1] == Type::generic_glue_fn(cx).ptr_to() &&
1802         member_llvm_types[2] == Type::i8().ptr_to() &&
1803         member_llvm_types[3] == Type::i8().ptr_to() &&
1804         member_llvm_types[4] == content_llvm_type
1805     }
1806 }
1807
1808 fn fixed_vec_metadata(cx: &CrateContext,
1809                       element_type: ty::t,
1810                       len: uint,
1811                       span: Span)
1812                    -> DIType {
1813     let element_type_metadata = type_metadata(cx, element_type, span);
1814     let element_llvm_type = type_of::type_of(cx, element_type);
1815     let (element_type_size, element_type_align) = size_and_align_of(cx, element_llvm_type);
1816
1817     let subrange = unsafe {
1818         llvm::LLVMDIBuilderGetOrCreateSubrange(
1819         DIB(cx),
1820         0,
1821         len as c_longlong)
1822     };
1823
1824     let subscripts = create_DIArray(DIB(cx), [subrange]);
1825     return unsafe {
1826         llvm::LLVMDIBuilderCreateArrayType(
1827             DIB(cx),
1828             bytes_to_bits(element_type_size * (len as u64)),
1829             bytes_to_bits(element_type_align),
1830             element_type_metadata,
1831             subscripts)
1832     };
1833 }
1834
1835 fn vec_metadata(cx: &CrateContext,
1836                 element_type: ty::t,
1837                 span: Span)
1838              -> DICompositeType {
1839
1840     let element_type_metadata = type_metadata(cx, element_type, span);
1841     let element_llvm_type = type_of::type_of(cx, element_type);
1842     let (element_size, element_align) = size_and_align_of(cx, element_llvm_type);
1843
1844     let vec_llvm_type = Type::vec(cx.sess.targ_cfg.arch, &element_llvm_type);
1845     let vec_type_name: &str = format!("[{}]", ppaux::ty_to_str(cx.tcx, element_type));
1846
1847     let member_llvm_types = vec_llvm_type.field_types();
1848
1849     let int_type_metadata = type_metadata(cx, ty::mk_int(), span);
1850     let array_type_metadata = unsafe {
1851         llvm::LLVMDIBuilderCreateArrayType(
1852             DIB(cx),
1853             bytes_to_bits(element_size),
1854             bytes_to_bits(element_align),
1855             element_type_metadata,
1856             create_DIArray(DIB(cx), [llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, 0)]))
1857     };
1858
1859     let member_descriptions = [
1860         MemberDescription {
1861             name: ~"fill",
1862             llvm_type: member_llvm_types[0],
1863             type_metadata: int_type_metadata,
1864             offset: ComputedMemberOffset,
1865         },
1866         MemberDescription {
1867             name: ~"alloc",
1868             llvm_type: member_llvm_types[1],
1869             type_metadata: int_type_metadata,
1870             offset: ComputedMemberOffset,
1871         },
1872         MemberDescription {
1873             name: ~"elements",
1874             llvm_type: member_llvm_types[2],
1875             type_metadata: array_type_metadata,
1876             offset: ComputedMemberOffset,
1877         }
1878     ];
1879
1880     assert!(member_descriptions.len() == member_llvm_types.len());
1881
1882     let loc = span_start(cx, span);
1883     let file_metadata = file_metadata(cx, loc.file.name);
1884
1885     return composite_type_metadata(
1886         cx,
1887         vec_llvm_type,
1888         vec_type_name,
1889         member_descriptions,
1890         file_metadata,
1891         file_metadata,
1892         span);
1893 }
1894
1895 fn vec_slice_metadata(cx: &CrateContext,
1896                       vec_type: ty::t,
1897                       element_type: ty::t,
1898                       span: Span)
1899                    -> DICompositeType {
1900
1901     debug!("vec_slice_metadata: {:?}", ty::get(vec_type));
1902
1903     let slice_llvm_type = type_of::type_of(cx, vec_type);
1904     let slice_type_name = ppaux::ty_to_str(cx.tcx, vec_type);
1905
1906     let member_llvm_types = slice_llvm_type.field_types();
1907     assert!(slice_layout_is_correct(cx, member_llvm_types, element_type));
1908
1909     let data_ptr_type = ty::mk_ptr(cx.tcx, ty::mt { ty: element_type, mutbl: ast::MutImmutable });
1910
1911     let member_descriptions = [
1912         MemberDescription {
1913             name: ~"data_ptr",
1914             llvm_type: member_llvm_types[0],
1915             type_metadata: type_metadata(cx, data_ptr_type, span),
1916             offset: ComputedMemberOffset,
1917         },
1918         MemberDescription {
1919             name: ~"length",
1920             llvm_type: member_llvm_types[1],
1921             type_metadata: type_metadata(cx, ty::mk_uint(), span),
1922             offset: ComputedMemberOffset,
1923         },
1924     ];
1925
1926     assert!(member_descriptions.len() == member_llvm_types.len());
1927
1928     let loc = span_start(cx, span);
1929     let file_metadata = file_metadata(cx, loc.file.name);
1930
1931     return composite_type_metadata(
1932         cx,
1933         slice_llvm_type,
1934         slice_type_name,
1935         member_descriptions,
1936         file_metadata,
1937         file_metadata,
1938         span);
1939
1940     fn slice_layout_is_correct(cx: &CrateContext,
1941                                member_llvm_types: &[Type],
1942                                element_type: ty::t)
1943                             -> bool {
1944         member_llvm_types.len() == 2 &&
1945         member_llvm_types[0] == type_of::type_of(cx, element_type).ptr_to() &&
1946         member_llvm_types[1] == cx.int_type
1947     }
1948 }
1949
1950 fn subroutine_type_metadata(cx: &CrateContext,
1951                             signature: &ty::FnSig,
1952                             span: Span)
1953                          -> DICompositeType {
1954     let loc = span_start(cx, span);
1955     let file_metadata = file_metadata(cx, loc.file.name);
1956
1957     let mut signature_metadata: ~[DIType] = vec::with_capacity(signature.inputs.len() + 1);
1958
1959     // return type
1960     signature_metadata.push(match ty::get(signature.output).sty {
1961         ty::ty_nil => ptr::null(),
1962         _ => type_metadata(cx, signature.output, span)
1963     });
1964
1965     // regular arguments
1966     for &argument_type in signature.inputs.iter() {
1967         signature_metadata.push(type_metadata(cx, argument_type, span));
1968     }
1969
1970     return unsafe {
1971         llvm::LLVMDIBuilderCreateSubroutineType(
1972             DIB(cx),
1973             file_metadata,
1974             create_DIArray(DIB(cx), signature_metadata))
1975     };
1976 }
1977
1978 fn trait_metadata(cx: &CrateContext,
1979                   def_id: ast::DefId,
1980                   trait_type: ty::t,
1981                   substs: &ty::substs,
1982                   trait_store: ty::TraitStore,
1983                   mutability: ast::Mutability,
1984                   _: &ty::BuiltinBounds)
1985                -> DIType {
1986     // The implementation provided here is a stub. It makes sure that the trait type is
1987     // assigned the correct name, size, namespace, and source location. But it does not describe
1988     // the trait's methods.
1989     let last = ty::with_path(cx.tcx, def_id, |mut path| path.last().unwrap());
1990     let ident_string = token::get_name(last.name());
1991     let name = ppaux::trait_store_to_str(cx.tcx, trait_store) +
1992                ppaux::mutability_to_str(mutability) +
1993                ident_string.get();
1994     // Add type and region parameters
1995     let name = ppaux::parameterized(cx.tcx, name, &substs.regions,
1996                                     substs.tps, def_id, true);
1997
1998     let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, def_id);
1999
2000     let file_name = span_start(cx, definition_span).file.name.clone();
2001     let file_metadata = file_metadata(cx, file_name);
2002
2003     let trait_llvm_type = type_of::type_of(cx, trait_type);
2004
2005     return composite_type_metadata(cx,
2006                                    trait_llvm_type,
2007                                    name,
2008                                    [],
2009                                    containing_scope,
2010                                    file_metadata,
2011                                    definition_span);
2012 }
2013
2014 fn type_metadata(cx: &CrateContext,
2015                  t: ty::t,
2016                  usage_site_span: Span)
2017               -> DIType {
2018     let cache_id = cache_id_for_type(t);
2019
2020     {
2021         let created_types = debug_context(cx).created_types.borrow();
2022         match created_types.get().find(&cache_id) {
2023             Some(type_metadata) => return *type_metadata,
2024             None => ()
2025         }
2026     }
2027
2028     fn create_pointer_to_box_metadata(cx: &CrateContext,
2029                                       pointer_type: ty::t,
2030                                       type_in_box: ty::t)
2031                                    -> DIType {
2032         let content_type_name: &str = ppaux::ty_to_str(cx.tcx, type_in_box);
2033         let content_llvm_type = type_of::type_of(cx, type_in_box);
2034         let content_type_metadata = type_metadata(
2035             cx,
2036             type_in_box,
2037             codemap::DUMMY_SP);
2038
2039         let box_metadata = boxed_type_metadata(
2040             cx,
2041             Some(content_type_name),
2042             content_llvm_type,
2043             content_type_metadata,
2044             codemap::DUMMY_SP);
2045
2046         pointer_type_metadata(cx, pointer_type, box_metadata)
2047     }
2048
2049     debug!("type_metadata: {:?}", ty::get(t));
2050
2051     let sty = &ty::get(t).sty;
2052     let type_metadata = match *sty {
2053         ty::ty_nil      |
2054         ty::ty_bot      |
2055         ty::ty_bool     |
2056         ty::ty_char     |
2057         ty::ty_int(_)   |
2058         ty::ty_uint(_)  |
2059         ty::ty_float(_) => {
2060             basic_type_metadata(cx, t)
2061         },
2062         ty::ty_str(ref vstore) => {
2063             let i8_t = ty::mk_i8();
2064             match *vstore {
2065                 ty::vstore_fixed(len) => {
2066                     fixed_vec_metadata(cx, i8_t, len + 1, usage_site_span)
2067                 },
2068                 ty::vstore_uniq  => {
2069                     let vec_metadata = vec_metadata(cx, i8_t, usage_site_span);
2070                     pointer_type_metadata(cx, t, vec_metadata)
2071                 }
2072                 ty::vstore_slice(_region) => {
2073                     vec_slice_metadata(cx, t, i8_t, usage_site_span)
2074                 }
2075             }
2076         },
2077         ty::ty_enum(def_id, _) => {
2078             prepare_enum_metadata(cx, t, def_id, usage_site_span).finalize(cx)
2079         },
2080         ty::ty_box(typ) => {
2081             create_pointer_to_box_metadata(cx, t, typ)
2082         },
2083         ty::ty_vec(ref mt, ref vstore) => {
2084             match *vstore {
2085                 ty::vstore_fixed(len) => {
2086                     fixed_vec_metadata(cx, mt.ty, len, usage_site_span)
2087                 }
2088                 ty::vstore_uniq => {
2089                     let vec_metadata = vec_metadata(cx, mt.ty, usage_site_span);
2090                     pointer_type_metadata(cx, t, vec_metadata)
2091                 }
2092                 ty::vstore_slice(_) => {
2093                     vec_slice_metadata(cx, t, mt.ty, usage_site_span)
2094                 }
2095             }
2096         },
2097         ty::ty_uniq(typ) => {
2098             let pointee = type_metadata(cx, typ, usage_site_span);
2099             pointer_type_metadata(cx, t, pointee)
2100         }
2101         ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => {
2102             let pointee = type_metadata(cx, mt.ty, usage_site_span);
2103             pointer_type_metadata(cx, t, pointee)
2104         },
2105         ty::ty_bare_fn(ref barefnty) => {
2106             subroutine_type_metadata(cx, &barefnty.sig, usage_site_span)
2107         },
2108         ty::ty_closure(ref closurety) => {
2109             subroutine_type_metadata(cx, &closurety.sig, usage_site_span)
2110         },
2111         ty::ty_trait(def_id, ref substs, trait_store, mutability, ref bounds) => {
2112             trait_metadata(cx, def_id, t, substs, trait_store, mutability, bounds)
2113         },
2114         ty::ty_struct(def_id, ref substs) => {
2115             if ty::type_is_simd(cx.tcx, t) {
2116                 let element_type = ty::simd_type(cx.tcx, t);
2117                 let len = ty::simd_size(cx.tcx, t);
2118                 fixed_vec_metadata(cx, element_type, len, usage_site_span)
2119             } else {
2120                 prepare_struct_metadata(cx, t, def_id, substs, usage_site_span).finalize(cx)
2121             }
2122         },
2123         ty::ty_tup(ref elements) => {
2124             prepare_tuple_metadata(cx, t, *elements, usage_site_span).finalize(cx)
2125         }
2126         _ => cx.sess.bug(format!("debuginfo: unexpected type in type_metadata: {:?}", sty))
2127     };
2128
2129     let mut created_types = debug_context(cx).created_types.borrow_mut();
2130     created_types.get().insert(cache_id, type_metadata);
2131     type_metadata
2132 }
2133
2134 #[deriving(Eq)]
2135 enum DebugLocation {
2136     KnownLocation { scope: DIScope, line: uint, col: uint },
2137     UnknownLocation
2138 }
2139
2140 impl DebugLocation {
2141     fn new(scope: DIScope, line: uint, col: uint) -> DebugLocation {
2142         KnownLocation {
2143             scope: scope,
2144             line: line,
2145             col: col,
2146         }
2147     }
2148 }
2149
2150 fn set_debug_location(cx: &CrateContext, debug_location: DebugLocation) {
2151     if debug_location == debug_context(cx).current_debug_location.get() {
2152         return;
2153     }
2154
2155     let metadata_node;
2156
2157     match debug_location {
2158         KnownLocation { scope, line, .. } => {
2159             let col = 0; // Always set the column to zero like Clang and GCC
2160             debug!("setting debug location to {} {}", line, col);
2161             let elements = [C_i32(line as i32), C_i32(col as i32), scope, ptr::null()];
2162             unsafe {
2163                 metadata_node = llvm::LLVMMDNodeInContext(debug_context(cx).llcontext,
2164                                                           elements.as_ptr(),
2165                                                           elements.len() as c_uint);
2166             }
2167         }
2168         UnknownLocation => {
2169             debug!("clearing debug location ");
2170             metadata_node = ptr::null();
2171         }
2172     };
2173
2174     unsafe {
2175         llvm::LLVMSetCurrentDebugLocation(cx.builder.b, metadata_node);
2176     }
2177
2178     debug_context(cx).current_debug_location.set(debug_location);
2179 }
2180
2181 //=-------------------------------------------------------------------------------------------------
2182 //  Utility Functions
2183 //=-------------------------------------------------------------------------------------------------
2184
2185 fn cache_id_for_type(t: ty::t) -> uint {
2186     ty::type_id(t)
2187 }
2188
2189 // Used to avoid LLVM metadata uniquing problems. See `create_struct_stub()` and
2190 // `prepare_enum_metadata()`.
2191 fn generate_unique_type_id(prefix: &'static str) -> ~str {
2192     unsafe {
2193         static mut unique_id_counter: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;
2194         format!("{}{}", prefix, unique_id_counter.fetch_add(1, atomics::SeqCst))
2195     }
2196 }
2197
2198 /// Return codemap::Loc corresponding to the beginning of the span
2199 fn span_start(cx: &CrateContext, span: Span) -> codemap::Loc {
2200     cx.sess.codemap.lookup_char_pos(span.lo)
2201 }
2202
2203 fn size_and_align_of(cx: &CrateContext, llvm_type: Type) -> (u64, u64) {
2204     (machine::llsize_of_alloc(cx, llvm_type), machine::llalign_of_min(cx, llvm_type))
2205 }
2206
2207 fn bytes_to_bits(bytes: u64) -> c_ulonglong {
2208     (bytes * 8) as c_ulonglong
2209 }
2210
2211 #[inline]
2212 fn debug_context<'a>(cx: &'a CrateContext) -> &'a CrateDebugContext {
2213     let debug_context: &'a CrateDebugContext = cx.dbg_cx.get_ref();
2214     debug_context
2215 }
2216
2217 #[inline]
2218 fn DIB(cx: &CrateContext) -> DIBuilderRef {
2219     cx.dbg_cx.get_ref().builder
2220 }
2221
2222 fn fn_should_be_ignored(fcx: &FunctionContext) -> bool {
2223     match fcx.debug_context {
2224         FunctionDebugContext(_) => false,
2225         _ => true
2226     }
2227 }
2228
2229 fn assert_type_for_node_id(cx: &CrateContext, node_id: ast::NodeId, error_span: Span) {
2230     let node_types = cx.tcx.node_types.borrow();
2231     if !node_types.get().contains_key(&(node_id as uint)) {
2232         cx.sess.span_bug(error_span, "debuginfo: Could not find type for node id!");
2233     }
2234 }
2235
2236 fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: ast::DefId)
2237                                    -> (DIScope, Span) {
2238     let containing_scope = namespace_for_item(cx, def_id).scope;
2239     let definition_span = if def_id.krate == ast::LOCAL_CRATE {
2240         cx.tcx.map.span(def_id.node)
2241     } else {
2242         // For external items there is no span information
2243         codemap::DUMMY_SP
2244     };
2245
2246     (containing_scope, definition_span)
2247 }
2248
2249 // This procedure builds the *scope map* for a given function, which maps any given ast::NodeId in
2250 // the function's AST to the correct DIScope metadata instance.
2251 //
2252 // This builder procedure walks the AST in execution order and keeps track of what belongs to which
2253 // scope, creating DIScope DIEs along the way, and introducing *artificial* lexical scope
2254 // descriptors where necessary. These artificial scopes allow GDB to correctly handle name
2255 // shadowing.
2256 fn populate_scope_map(cx: &CrateContext,
2257                       arg_pats: &[@ast::Pat],
2258                       fn_entry_block: &ast::Block,
2259                       fn_metadata: DISubprogram,
2260                       scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2261     let def_map = cx.tcx.def_map;
2262
2263     struct ScopeStackEntry {
2264         scope_metadata: DIScope,
2265         ident: Option<ast::Ident>
2266     }
2267
2268     let mut scope_stack = ~[ScopeStackEntry { scope_metadata: fn_metadata, ident: None }];
2269
2270     // Push argument identifiers onto the stack so arguments integrate nicely with variable
2271     // shadowing.
2272     for &arg_pat in arg_pats.iter() {
2273         pat_util::pat_bindings(def_map, arg_pat, |_, _, _, path_ref| {
2274             let ident = ast_util::path_to_ident(path_ref);
2275             scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata, ident: Some(ident) });
2276         })
2277     }
2278
2279     // Clang creates a separate scope for function bodies, so let's do this too
2280     with_new_scope(cx,
2281                    fn_entry_block.span,
2282                    &mut scope_stack,
2283                    scope_map,
2284                    |cx, scope_stack, scope_map| {
2285         walk_block(cx, fn_entry_block, scope_stack, scope_map);
2286     });
2287
2288     // local helper functions for walking the AST.
2289     fn with_new_scope(cx: &CrateContext,
2290                       scope_span: Span,
2291                       scope_stack: &mut ~[ScopeStackEntry],
2292                       scope_map: &mut HashMap<ast::NodeId, DIScope>,
2293                       inner_walk: |&CrateContext,
2294                                    &mut ~[ScopeStackEntry],
2295                                    &mut HashMap<ast::NodeId, DIScope>|) {
2296         // Create a new lexical scope and push it onto the stack
2297         let loc = cx.sess.codemap.lookup_char_pos(scope_span.lo);
2298         let file_metadata = file_metadata(cx, loc.file.name);
2299         let parent_scope = scope_stack.last().unwrap().scope_metadata;
2300
2301         let scope_metadata = unsafe {
2302             llvm::LLVMDIBuilderCreateLexicalBlock(
2303                 DIB(cx),
2304                 parent_scope,
2305                 file_metadata,
2306                 loc.line as c_uint,
2307                 loc.col.to_uint() as c_uint)
2308         };
2309
2310         scope_stack.push(ScopeStackEntry { scope_metadata: scope_metadata, ident: None });
2311
2312         inner_walk(cx, scope_stack, scope_map);
2313
2314         // pop artificial scopes
2315         while scope_stack.last().unwrap().ident.is_some() {
2316             scope_stack.pop();
2317         }
2318
2319         if scope_stack.last().unwrap().scope_metadata != scope_metadata {
2320             cx.sess.span_bug(scope_span, "debuginfo: Inconsistency in scope management.");
2321         }
2322
2323         scope_stack.pop();
2324     }
2325
2326     fn walk_block(cx: &CrateContext,
2327                   block: &ast::Block,
2328                   scope_stack: &mut ~[ScopeStackEntry],
2329                   scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2330         scope_map.insert(block.id, scope_stack.last().unwrap().scope_metadata);
2331
2332         // The interesting things here are statements and the concluding expression.
2333         for statement in block.stmts.iter() {
2334             scope_map.insert(ast_util::stmt_id(*statement),
2335                              scope_stack.last().unwrap().scope_metadata);
2336
2337             match statement.node {
2338                 ast::StmtDecl(decl, _) => walk_decl(cx, decl, scope_stack, scope_map),
2339                 ast::StmtExpr(exp, _) |
2340                 ast::StmtSemi(exp, _) => walk_expr(cx, exp, scope_stack, scope_map),
2341                 ast::StmtMac(..) => () // ignore macros (which should be expanded anyway)
2342             }
2343         }
2344
2345         for exp in block.expr.iter() {
2346             walk_expr(cx, *exp, scope_stack, scope_map);
2347         }
2348     }
2349
2350     fn walk_decl(cx: &CrateContext,
2351                  decl: &ast::Decl,
2352                  scope_stack: &mut ~[ScopeStackEntry],
2353                  scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2354         match *decl {
2355             codemap::Spanned { node: ast::DeclLocal(local), .. } => {
2356                 scope_map.insert(local.id, scope_stack.last().unwrap().scope_metadata);
2357
2358                 walk_pattern(cx, local.pat, scope_stack, scope_map);
2359
2360                 for exp in local.init.iter() {
2361                     walk_expr(cx, *exp, scope_stack, scope_map);
2362                 }
2363             }
2364             _ => ()
2365         }
2366     }
2367
2368     fn walk_pattern(cx: &CrateContext,
2369                     pat: @ast::Pat,
2370                     scope_stack: &mut ~[ScopeStackEntry],
2371                     scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2372
2373         let def_map = cx.tcx.def_map;
2374
2375         // Unfortunately, we cannot just use pat_util::pat_bindings() or ast_util::walk_pat() here
2376         // because we have to visit *all* nodes in order to put them into the scope map. The above
2377         // functions don't do that.
2378         match pat.node {
2379             ast::PatIdent(_, ref path_ref, ref sub_pat_opt) => {
2380
2381                 // Check if this is a binding. If so we need to put it on the scope stack and maybe
2382                 // introduce an articial scope
2383                 if pat_util::pat_is_binding(def_map, pat) {
2384
2385                     let ident = ast_util::path_to_ident(path_ref);
2386
2387                     // LLVM does not properly generate 'DW_AT_start_scope' fields for variable DIEs.
2388                     // For this reason we have to introduce an artificial scope at bindings whenever
2389                     // a variable with the same name is declared in *any* parent scope.
2390                     //
2391                     // Otherwise the following error occurs:
2392                     //
2393                     // let x = 10;
2394                     //
2395                     // do_something(); // 'gdb print x' correctly prints 10
2396                     //
2397                     // {
2398                     //     do_something(); // 'gdb print x' prints 0, because it already reads the
2399                     //                     // uninitialized 'x' from the next line...
2400                     //     let x = 100;
2401                     //     do_something(); // 'gdb print x' correctly prints 100
2402                     // }
2403
2404                     // Is there already a binding with that name?
2405                     // N.B.: this comparison must be UNhygienic... because
2406                     // gdb knows nothing about the context, so any two
2407                     // variables with the same name will cause the problem.
2408                     let need_new_scope = scope_stack
2409                         .iter()
2410                         .any(|entry| entry.ident.iter().any(|i| i.name == ident.name));
2411
2412                     if need_new_scope {
2413                         // Create a new lexical scope and push it onto the stack
2414                         let loc = cx.sess.codemap.lookup_char_pos(pat.span.lo);
2415                         let file_metadata = file_metadata(cx, loc.file.name);
2416                         let parent_scope = scope_stack.last().unwrap().scope_metadata;
2417
2418                         let scope_metadata = unsafe {
2419                             llvm::LLVMDIBuilderCreateLexicalBlock(
2420                                 DIB(cx),
2421                                 parent_scope,
2422                                 file_metadata,
2423                                 loc.line as c_uint,
2424                                 loc.col.to_uint() as c_uint)
2425                         };
2426
2427                         scope_stack.push(ScopeStackEntry {
2428                             scope_metadata: scope_metadata,
2429                             ident: Some(ident)
2430                         });
2431
2432                     } else {
2433                         // Push a new entry anyway so the name can be found
2434                         let prev_metadata = scope_stack.last().unwrap().scope_metadata;
2435                         scope_stack.push(ScopeStackEntry {
2436                             scope_metadata: prev_metadata,
2437                             ident: Some(ident)
2438                         });
2439                     }
2440                 }
2441
2442                 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2443
2444                 for &sub_pat in sub_pat_opt.iter() {
2445                     walk_pattern(cx, sub_pat, scope_stack, scope_map);
2446                 }
2447             }
2448
2449             ast::PatWild | ast::PatWildMulti => {
2450                 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2451             }
2452
2453             ast::PatEnum(_, ref sub_pats_opt) => {
2454                 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2455
2456                 for ref sub_pats in sub_pats_opt.iter() {
2457                     for &p in sub_pats.iter() {
2458                         walk_pattern(cx, p, scope_stack, scope_map);
2459                     }
2460                 }
2461             }
2462
2463             ast::PatStruct(_, ref field_pats, _) => {
2464                 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2465
2466                 for &ast::FieldPat { pat: sub_pat, .. } in field_pats.iter() {
2467                     walk_pattern(cx, sub_pat, scope_stack, scope_map);
2468                 }
2469             }
2470
2471             ast::PatTup(ref sub_pats) => {
2472                 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2473
2474                 for &sub_pat in sub_pats.iter() {
2475                     walk_pattern(cx, sub_pat, scope_stack, scope_map);
2476                 }
2477             }
2478
2479             ast::PatUniq(sub_pat) | ast::PatRegion(sub_pat) => {
2480                 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2481                 walk_pattern(cx, sub_pat, scope_stack, scope_map);
2482             }
2483
2484             ast::PatLit(exp) => {
2485                 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2486                 walk_expr(cx, exp, scope_stack, scope_map);
2487             }
2488
2489             ast::PatRange(exp1, exp2) => {
2490                 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2491                 walk_expr(cx, exp1, scope_stack, scope_map);
2492                 walk_expr(cx, exp2, scope_stack, scope_map);
2493             }
2494
2495             ast::PatVec(ref front_sub_pats, ref middle_sub_pats, ref back_sub_pats) => {
2496                 scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
2497
2498                 for &sub_pat in front_sub_pats.iter() {
2499                     walk_pattern(cx, sub_pat, scope_stack, scope_map);
2500                 }
2501
2502                 for &sub_pat in middle_sub_pats.iter() {
2503                     walk_pattern(cx, sub_pat, scope_stack, scope_map);
2504                 }
2505
2506                 for &sub_pat in back_sub_pats.iter() {
2507                     walk_pattern(cx, sub_pat, scope_stack, scope_map);
2508                 }
2509             }
2510         }
2511     }
2512
2513     fn walk_expr(cx: &CrateContext,
2514                  exp: &ast::Expr,
2515                  scope_stack: &mut ~[ScopeStackEntry],
2516                  scope_map: &mut HashMap<ast::NodeId, DIScope>) {
2517
2518         scope_map.insert(exp.id, scope_stack.last().unwrap().scope_metadata);
2519
2520         match exp.node {
2521             ast::ExprLogLevel |
2522             ast::ExprLit(_)   |
2523             ast::ExprBreak(_) |
2524             ast::ExprAgain(_) |
2525             ast::ExprPath(_)  => {}
2526
2527             ast::ExprVstore(sub_exp, _)   |
2528             ast::ExprCast(sub_exp, _)     |
2529             ast::ExprAddrOf(_, sub_exp)  |
2530             ast::ExprField(sub_exp, _, _) |
2531             ast::ExprParen(sub_exp)       => walk_expr(cx, sub_exp, scope_stack, scope_map),
2532
2533             ast::ExprBox(place, sub_expr) => {
2534                 walk_expr(cx, place, scope_stack, scope_map);
2535                 walk_expr(cx, sub_expr, scope_stack, scope_map);
2536             }
2537
2538             ast::ExprRet(exp_opt) => match exp_opt {
2539                 Some(sub_exp) => walk_expr(cx, sub_exp, scope_stack, scope_map),
2540                 None => ()
2541             },
2542
2543             ast::ExprUnary(_, sub_exp) => {
2544                 walk_expr(cx, sub_exp, scope_stack, scope_map);
2545             }
2546
2547             ast::ExprAssignOp(_, lhs, rhs) |
2548             ast::ExprIndex(lhs, rhs)        |
2549             ast::ExprBinary(_, lhs, rhs)    => {
2550                 walk_expr(cx, lhs, scope_stack, scope_map);
2551                 walk_expr(cx, rhs, scope_stack, scope_map);
2552             }
2553
2554             ast::ExprVec(ref init_expressions, _) |
2555             ast::ExprTup(ref init_expressions)    => {
2556                 for ie in init_expressions.iter() {
2557                     walk_expr(cx, *ie, scope_stack, scope_map);
2558                 }
2559             }
2560
2561             ast::ExprAssign(sub_exp1, sub_exp2)    |
2562             ast::ExprRepeat(sub_exp1, sub_exp2, _) => {
2563                 walk_expr(cx, sub_exp1, scope_stack, scope_map);
2564                 walk_expr(cx, sub_exp2, scope_stack, scope_map);
2565             }
2566
2567             ast::ExprIf(cond_exp, then_block, ref opt_else_exp) => {
2568                 walk_expr(cx, cond_exp, scope_stack, scope_map);
2569
2570                 with_new_scope(cx,
2571                                then_block.span,
2572                                scope_stack,
2573                                scope_map,
2574                                |cx, scope_stack, scope_map| {
2575                     walk_block(cx, then_block, scope_stack, scope_map);
2576                 });
2577
2578                 match *opt_else_exp {
2579                     Some(else_exp) => walk_expr(cx, else_exp, scope_stack, scope_map),
2580                     _ => ()
2581                 }
2582             }
2583
2584             ast::ExprWhile(cond_exp, loop_body) => {
2585                 walk_expr(cx, cond_exp, scope_stack, scope_map);
2586
2587                 with_new_scope(cx,
2588                                loop_body.span,
2589                                scope_stack,
2590                                scope_map,
2591                                |cx, scope_stack, scope_map| {
2592                     walk_block(cx, loop_body, scope_stack, scope_map);
2593                 })
2594             }
2595
2596             ast::ExprForLoop(_, _, _, _) => {
2597                 cx.sess.span_bug(exp.span, "debuginfo::populate_scope_map() - \
2598                                             Found unexpanded for-loop.");
2599             }
2600
2601             ast::ExprMac(_) => {
2602                 cx.sess.span_bug(exp.span, "debuginfo::populate_scope_map() - \
2603                                             Found unexpanded macro.");
2604             }
2605
2606             ast::ExprLoop(block, _) |
2607             ast::ExprBlock(block)   => {
2608                 with_new_scope(cx,
2609                                block.span,
2610                                scope_stack,
2611                                scope_map,
2612                                |cx, scope_stack, scope_map| {
2613                     walk_block(cx, block, scope_stack, scope_map);
2614                 })
2615             }
2616
2617             ast::ExprFnBlock(decl, block) |
2618             ast::ExprProc(decl, block) => {
2619                 with_new_scope(cx,
2620                                block.span,
2621                                scope_stack,
2622                                scope_map,
2623                                |cx, scope_stack, scope_map| {
2624                     for &ast::Arg { pat: pattern, .. } in decl.inputs.iter() {
2625                         walk_pattern(cx, pattern, scope_stack, scope_map);
2626                     }
2627
2628                     walk_block(cx, block, scope_stack, scope_map);
2629                 })
2630             }
2631
2632             ast::ExprCall(fn_exp, ref args) => {
2633                 walk_expr(cx, fn_exp, scope_stack, scope_map);
2634
2635                 for arg_exp in args.iter() {
2636                     walk_expr(cx, *arg_exp, scope_stack, scope_map);
2637                 }
2638             }
2639
2640             ast::ExprMethodCall(_, _, ref args) => {
2641                 for arg_exp in args.iter() {
2642                     walk_expr(cx, *arg_exp, scope_stack, scope_map);
2643                 }
2644             }
2645
2646             ast::ExprMatch(discriminant_exp, ref arms) => {
2647                 walk_expr(cx, discriminant_exp, scope_stack, scope_map);
2648
2649                 // for each arm we have to first walk the pattern as these might introduce new
2650                 // artificial scopes. It should be sufficient to walk only one pattern per arm, as
2651                 // they all must contain the same binding names
2652
2653                 for arm_ref in arms.iter() {
2654                     let arm_span = arm_ref.pats.get(0).span;
2655
2656                     with_new_scope(cx,
2657                                    arm_span,
2658                                    scope_stack,
2659                                    scope_map,
2660                                    |cx, scope_stack, scope_map| {
2661                         for &pat in arm_ref.pats.iter() {
2662                             walk_pattern(cx, pat, scope_stack, scope_map);
2663                         }
2664
2665                         for guard_exp in arm_ref.guard.iter() {
2666                             walk_expr(cx, *guard_exp, scope_stack, scope_map)
2667                         }
2668
2669                         walk_expr(cx, arm_ref.body, scope_stack, scope_map);
2670                     })
2671                 }
2672             }
2673
2674             ast::ExprStruct(_, ref fields, ref base_exp) => {
2675                 for &ast::Field { expr: exp, .. } in fields.iter() {
2676                     walk_expr(cx, exp, scope_stack, scope_map);
2677                 }
2678
2679                 match *base_exp {
2680                     Some(exp) => walk_expr(cx, exp, scope_stack, scope_map),
2681                     None => ()
2682                 }
2683             }
2684
2685             ast::ExprInlineAsm(ast::InlineAsm { inputs: ref inputs,
2686                                                 outputs: ref outputs,
2687                                                 .. }) => {
2688                 // inputs, outputs: ~[(~str, @expr)]
2689                 for &(_, exp) in inputs.iter() {
2690                     walk_expr(cx, exp, scope_stack, scope_map);
2691                 }
2692
2693                 for &(_, exp) in outputs.iter() {
2694                     walk_expr(cx, exp, scope_stack, scope_map);
2695                 }
2696             }
2697         }
2698     }
2699 }
2700
2701
2702 //=-------------------------------------------------------------------------------------------------
2703 // Namespace Handling
2704 //=-------------------------------------------------------------------------------------------------
2705
2706 struct NamespaceTreeNode {
2707     name: ast::Name,
2708     scope: DIScope,
2709     parent: Option<@NamespaceTreeNode>,
2710 }
2711
2712 impl NamespaceTreeNode {
2713     fn mangled_name_of_contained_item(&self, item_name: &str) -> ~str {
2714         fn fill_nested(node: &NamespaceTreeNode, output: &mut ~str) {
2715             match node.parent {
2716                 Some(parent) => fill_nested(parent, output),
2717                 None => {}
2718             }
2719             let string = token::get_name(node.name);
2720             output.push_str(format!("{}", string.get().len()));
2721             output.push_str(string.get());
2722         }
2723
2724         let mut name = ~"_ZN";
2725         fill_nested(self, &mut name);
2726         name.push_str(format!("{}", item_name.len()));
2727         name.push_str(item_name);
2728         name.push_char('E');
2729         name
2730     }
2731 }
2732
2733 fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> @NamespaceTreeNode {
2734     ty::with_path(cx.tcx, def_id, |path| {
2735         // prepend crate name if not already present
2736         let krate = if def_id.krate == ast::LOCAL_CRATE {
2737             let crate_namespace_ident = token::str_to_ident(cx.link_meta.crateid.name);
2738             Some(ast_map::PathMod(crate_namespace_ident.name))
2739         } else {
2740             None
2741         };
2742         let mut path = krate.move_iter().chain(path).peekable();
2743
2744         let mut current_key = ~[];
2745         let mut parent_node: Option<@NamespaceTreeNode> = None;
2746
2747         // Create/Lookup namespace for each element of the path.
2748         loop {
2749             // Emulate a for loop so we can use peek below.
2750             let path_element = match path.next() {
2751                 Some(e) => e,
2752                 None => break
2753             };
2754             // Ignore the name of the item (the last path element).
2755             if path.peek().is_none() {
2756                 break;
2757             }
2758
2759             let name = path_element.name();
2760             current_key.push(name);
2761
2762             let existing_node = {
2763                 let namespace_map = debug_context(cx).namespace_map.borrow();
2764                 namespace_map.get().find_copy(&current_key)
2765             };
2766             let current_node = match existing_node {
2767                 Some(existing_node) => existing_node,
2768                 None => {
2769                     // create and insert
2770                     let parent_scope = match parent_node {
2771                         Some(node) => node.scope,
2772                         None => ptr::null()
2773                     };
2774                     let namespace_name = token::get_name(name);
2775                     let scope = namespace_name.get().with_c_str(|namespace_name| {
2776                         unsafe {
2777                             llvm::LLVMDIBuilderCreateNameSpace(
2778                                 DIB(cx),
2779                                 parent_scope,
2780                                 namespace_name,
2781                                 // cannot reconstruct file ...
2782                                 ptr::null(),
2783                                 // ... or line information, but that's not so important.
2784                                 0)
2785                         }
2786                     });
2787
2788                     let node = @NamespaceTreeNode {
2789                         name: name,
2790                         scope: scope,
2791                         parent: parent_node,
2792                     };
2793
2794                     {
2795                         let mut namespace_map = debug_context(cx).namespace_map
2796                                                                  .borrow_mut();
2797                         namespace_map.get().insert(current_key.clone(), node);
2798                     }
2799
2800                     node
2801                 }
2802             };
2803
2804             parent_node = Some(current_node);
2805         }
2806
2807         match parent_node {
2808             Some(node) => node,
2809             None => {
2810                 cx.sess.bug(format!("debuginfo::namespace_for_item(): \
2811                     path too short for {:?}", def_id));
2812             }
2813         }
2814     })
2815 }