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