]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/trans/debuginfo.rs
auto merge of #7996 : erickt/rust/cleanup-strs, r=erickt
[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::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 a DebugContext struct, which in turn is
41 contained in the CrateContext.
42
43
44 This file consists of three conceptual sections:
45 1. The public interface of the module
46 2. Module-internal metadata creation functions
47 3. Minor utility functions
48
49 */
50
51
52 use driver::session;
53 use lib::llvm::llvm;
54 use lib::llvm::{ModuleRef, ContextRef};
55 use lib::llvm::debuginfo::*;
56 use middle::trans::common::*;
57 use middle::trans::machine;
58 use middle::trans::type_of;
59 use middle::trans::type_::Type;
60 use middle::trans::adt;
61 use middle::trans;
62 use middle::ty;
63 use util::ppaux::ty_to_str;
64
65 use std::hashmap::HashMap;
66 use std::libc::{c_uint, c_ulonglong, c_longlong};
67 use std::ptr;
68 use std::vec;
69 use syntax::codemap::span;
70 use syntax::{ast, codemap, ast_util, ast_map};
71
72 static DW_LANG_RUST: int = 0x9000;
73
74 static DW_TAG_auto_variable: int = 0x100;
75 static DW_TAG_arg_variable: int = 0x101;
76
77 static DW_ATE_boolean: int = 0x02;
78 static DW_ATE_float: int = 0x04;
79 static DW_ATE_signed: int = 0x05;
80 static DW_ATE_signed_char: int = 0x06;
81 static DW_ATE_unsigned: int = 0x07;
82 static DW_ATE_unsigned_char: int = 0x08;
83
84
85
86
87 //=-------------------------------------------------------------------------------------------------
88 //  Public Interface of debuginfo module
89 //=-------------------------------------------------------------------------------------------------
90
91 /// A context object for maintaining all state needed by the debuginfo module.
92 pub struct DebugContext {
93     crate_file: ~str,
94     llcontext: ContextRef,
95     builder: DIBuilderRef,
96     curr_loc: (uint, uint),
97     created_files: HashMap<~str, DIFile>,
98     created_functions: HashMap<ast::node_id, DISubprogram>,
99     created_blocks: HashMap<ast::node_id, DILexicalBlock>,
100     created_types: HashMap<uint, DIType>
101 }
102
103 impl DebugContext {
104     pub fn new(llmod: ModuleRef, crate: ~str) -> DebugContext {
105         debug!("DebugContext::new");
106         let builder = unsafe { llvm::LLVMDIBuilderCreate(llmod) };
107         // DIBuilder inherits context from the module, so we'd better use the same one
108         let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
109         return DebugContext {
110             crate_file: crate,
111             llcontext: llcontext,
112             builder: builder,
113             curr_loc: (0, 0),
114             created_files: HashMap::new(),
115             created_functions: HashMap::new(),
116             created_blocks: HashMap::new(),
117             created_types: HashMap::new(),
118         };
119     }
120 }
121
122 /// Create any deferred debug metadata nodes
123 pub fn finalize(cx: @mut CrateContext) {
124     debug!("finalize");
125     compile_unit_metadata(cx);
126     unsafe {
127         llvm::LLVMDIBuilderFinalize(DIB(cx));
128         llvm::LLVMDIBuilderDispose(DIB(cx));
129     };
130 }
131
132 /// Creates debug information for the given local variable.
133 ///
134 /// Adds the created metadata nodes directly to the crate's IR.
135 /// The return value should be ignored if called from outside of the debuginfo module.
136 pub fn create_local_var_metadata(bcx: @mut Block, local: @ast::Local) -> DIVariable {
137     let cx = bcx.ccx();
138
139     let ident = match local.pat.node {
140       ast::pat_ident(_, ref pth, _) => ast_util::path_to_ident(pth),
141       // FIXME this should be handled (#2533)
142       _ => {
143         bcx.sess().span_note(local.span, "debuginfo for pattern bindings NYI");
144         return ptr::null();
145       }
146     };
147
148     let name: &str = cx.sess.str_of(ident);
149     debug!("create_local_var_metadata: %s", name);
150
151     let loc = span_start(cx, local.span);
152     let ty = node_id_type(bcx, local.id);
153     let type_metadata = type_metadata(cx, ty, local.ty.span);
154     let file_metadata = file_metadata(cx, loc.file.name);
155
156     let context = match bcx.parent {
157         None => create_function_metadata(bcx.fcx),
158         Some(_) => lexical_block_metadata(bcx)
159     };
160
161     let var_metadata = do name.as_c_str |name| {
162         unsafe {
163             llvm::LLVMDIBuilderCreateLocalVariable(
164                 DIB(cx),
165                 DW_TAG_auto_variable as u32,
166                 context,
167                 name,
168                 file_metadata,
169                 loc.line as c_uint,
170                 type_metadata,
171                 false,
172                 0,
173                 0)
174         }
175     };
176
177     // FIXME(#6814) Should use `pat_util::pat_bindings` for pats like (a, b) etc
178     let llptr = match bcx.fcx.lllocals.find_copy(&local.pat.id) {
179         Some(v) => v,
180         None => {
181             bcx.tcx().sess.span_bug(
182                 local.span,
183                 fmt!("No entry in lllocals table for %?", local.id));
184         }
185     };
186
187     set_debug_location(cx, lexical_block_metadata(bcx), loc.line, loc.col.to_uint());
188     unsafe {
189         let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(DIB(cx), llptr, var_metadata, bcx.llbb);
190         llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr);
191     }
192
193     return var_metadata;
194 }
195
196 /// Creates debug information for the given function argument.
197 ///
198 /// Adds the created metadata nodes directly to the crate's IR.
199 /// The return value should be ignored if called from outside of the debuginfo module.
200 pub fn create_argument_metadata(bcx: @mut Block, arg: &ast::arg, span: span) -> Option<DIVariable> {
201     debug!("create_argument_metadata");
202     if true {
203         // XXX create_argument_metadata disabled for now because "node_id_type(bcx, arg.id)" below
204         // blows up:
205         // "error: internal compiler error: node_id_to_type: no type for node `arg (id=10)`"
206         return None;
207     }
208
209     let fcx = bcx.fcx;
210     let cx = fcx.ccx;
211
212     let loc = span_start(cx, span);
213     if "<intrinsic>" == loc.file.name {
214         return None;
215     }
216
217     let ty = node_id_type(bcx, arg.id);
218     let type_metadata = type_metadata(cx, ty, arg.ty.span);
219     let file_metadata = file_metadata(cx, loc.file.name);
220     let context = create_function_metadata(fcx);
221
222     match arg.pat.node {
223         ast::pat_ident(_, ref path, _) => {
224             // XXX: This is wrong; it should work for multiple bindings.
225             let ident = path.idents.last();
226             let name: &str = cx.sess.str_of(*ident);
227             let var_metadata = do name.as_c_str |name| {
228                 unsafe {
229                     llvm::LLVMDIBuilderCreateLocalVariable(
230                         DIB(cx),
231                         DW_TAG_arg_variable as u32,
232                         context,
233                         name,
234                         file_metadata,
235                         loc.line as c_uint,
236                         type_metadata,
237                         false,
238                         0,
239                         0)
240                     // XXX need to pass in a real argument number
241                 }
242             };
243
244             let llptr = fcx.llargs.get_copy(&arg.id);
245             set_debug_location(cx, lexical_block_metadata(bcx), loc.line, loc.col.to_uint());
246             unsafe {
247                 let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
248                         DIB(cx), llptr, var_metadata, bcx.llbb);
249                 llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr);
250             }
251             return Some(var_metadata);
252         }
253         _ => {
254             return None;
255         }
256     }
257 }
258
259 /// Sets the current debug location at the beginning of the span
260 ///
261 /// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...)
262 pub fn update_source_pos(bcx: @mut Block, span: span) {
263     if !bcx.sess().opts.debuginfo || (*span.lo == 0 && *span.hi == 0) {
264         return;
265     }
266     debug!("update_source_pos: %s", bcx.sess().codemap.span_to_str(span));
267     let loc = span_start(bcx.ccx(), span);
268     set_debug_location(bcx.ccx(), lexical_block_metadata(bcx), loc.line, loc.col.to_uint())
269 }
270
271 /// Creates debug information for the given function.
272 ///
273 /// Adds the created metadata nodes directly to the crate's IR.
274 /// The return value should be ignored if called from outside of the debuginfo module.
275 pub fn create_function_metadata(fcx: &FunctionContext) -> DISubprogram {
276     let cx = fcx.ccx;
277     let span = fcx.span.get();
278
279     let fnitem = cx.tcx.items.get_copy(&fcx.id);
280     let (ident, ret_ty, id) = match fnitem {
281         ast_map::node_item(ref item, _) => {
282             match item.node {
283                 ast::item_fn(ast::fn_decl { output: ref ty, _}, _, _, _, _) => {
284                     (item.ident, ty, item.id)
285                 }
286                 _ => fcx.ccx.sess.span_bug(item.span,
287                                            "create_function_metadata: item bound to non-function")
288             }
289         }
290         ast_map::node_method(
291             @ast::method {
292                 decl: ast::fn_decl { output: ref ty, _ },
293                 id: id,
294                 ident: ident,
295                 _
296             },
297             _,
298             _) => {
299             (ident, ty, id)
300         }
301         ast_map::node_expr(ref expr) => {
302             match expr.node {
303                 ast::expr_fn_block(ref decl, _) => {
304                     let name = gensym_name("fn");
305                     (name, &decl.output, expr.id)
306                 }
307                 _ => fcx.ccx.sess.span_bug(expr.span,
308                         "create_function_metadata: expected an expr_fn_block here")
309             }
310         }
311         ast_map::node_trait_method(
312             @ast::provided(
313                 @ast::method {
314                     decl: ast::fn_decl { output: ref ty, _ },
315                     id: id,
316                     ident: ident,
317                     _
318                 }),
319             _,
320             _) => {
321             (ident, ty, id)
322         }
323         _ => fcx.ccx.sess.bug("create_function_metadata: unexpected sort of node")
324     };
325
326     match dbg_cx(cx).created_functions.find(&id) {
327         Some(fn_metadata) => return *fn_metadata,
328         None => ()
329     }
330
331     debug!("create_function_metadata: %s, %s",
332            cx.sess.str_of(ident),
333            cx.sess.codemap.span_to_str(span));
334
335     let loc = span_start(cx, span);
336     let file_metadata = file_metadata(cx, loc.file.name);
337
338     let return_type_metadata = if cx.sess.opts.extra_debuginfo {
339         match ret_ty.node {
340           ast::ty_nil => ptr::null(),
341           _ => type_metadata(cx, ty::node_id_to_type(cx.tcx, id), ret_ty.span)
342         }
343     } else {
344         ptr::null()
345     };
346
347     let fn_ty = unsafe {
348         llvm::LLVMDIBuilderCreateSubroutineType(
349             DIB(cx),
350             file_metadata,
351             create_DIArray(DIB(cx), [return_type_metadata]))
352     };
353
354     let fn_metadata =
355         do cx.sess.str_of(ident).as_c_str |name| {
356         do cx.sess.str_of(ident).as_c_str |linkage| {
357             unsafe {
358                 llvm::LLVMDIBuilderCreateFunction(
359                     DIB(cx),
360                     file_metadata,
361                     name,
362                     linkage,
363                     file_metadata,
364                     loc.line as c_uint,
365                     fn_ty,
366                     false,
367                     true,
368                     loc.line as c_uint,
369                     FlagPrototyped as c_uint,
370                     cx.sess.opts.optimize != session::No,
371                     fcx.llfn,
372                     ptr::null(),
373                     ptr::null())
374             }
375         }};
376
377     dbg_cx(cx).created_functions.insert(id, fn_metadata);
378     return fn_metadata;
379 }
380
381
382
383
384 //=-------------------------------------------------------------------------------------------------
385 // Module-Internal debug info creation functions
386 //=-------------------------------------------------------------------------------------------------
387
388 fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
389     return unsafe {
390         llvm::LLVMDIBuilderGetOrCreateArray(builder, vec::raw::to_ptr(arr), arr.len() as u32)
391     };
392 }
393
394 fn compile_unit_metadata(cx: @mut CrateContext) {
395     let dcx = dbg_cx(cx);
396     let crate_name: &str = dcx.crate_file;
397
398     debug!("compile_unit_metadata: %?", crate_name);
399
400     let work_dir = cx.sess.working_dir.to_str();
401     let producer = fmt!("rustc version %s", env!("CFG_VERSION"));
402
403     do crate_name.as_c_str |crate_name| {
404     do work_dir.as_c_str |work_dir| {
405     do producer.as_c_str |producer| {
406     do "".as_c_str |flags| {
407     do "".as_c_str |split_name| {
408         unsafe {
409             llvm::LLVMDIBuilderCreateCompileUnit(dcx.builder,
410                 DW_LANG_RUST as c_uint, crate_name, work_dir, producer,
411                 cx.sess.opts.optimize != session::No,
412                 flags, 0, split_name);
413         }
414     }}}}};
415 }
416
417 fn file_metadata(cx: &mut CrateContext, full_path: &str) -> DIFile {
418     match dbg_cx(cx).created_files.find_equiv(&full_path) {
419         Some(file_metadata) => return *file_metadata,
420         None => ()
421     }
422
423     debug!("file_metadata: %s", full_path);
424
425     let work_dir = cx.sess.working_dir.to_str();
426     let file_name =
427         if full_path.starts_with(work_dir) {
428             full_path.slice(work_dir.len() + 1u, full_path.len())
429         } else {
430             full_path
431         };
432
433     let file_metadata =
434         do file_name.as_c_str |file_name| {
435         do work_dir.as_c_str |work_dir| {
436             unsafe {
437                 llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name, work_dir)
438             }
439         }};
440
441     dbg_cx(cx).created_files.insert(full_path.to_owned(), file_metadata);
442     return file_metadata;
443 }
444
445 /// Get or create the lexical block metadata node for the given LLVM basic block.
446 fn lexical_block_metadata(bcx: @mut Block) -> DILexicalBlock {
447     let cx = bcx.ccx();
448     let mut bcx = bcx;
449
450     // Search up the tree of basic blocks until we find one that knows the containing lexical block.
451     while bcx.node_info.is_none() {
452         match bcx.parent {
453             Some(b) => bcx = b,
454             None => cx.sess.bug("debuginfo: Could not find lexical block for LLVM basic block.")
455         }
456     }
457
458     let span = bcx.node_info.get().span;
459     let id = bcx.node_info.get().id;
460
461     // Check whether we already have a cache entry for this node id
462     match dbg_cx(cx).created_blocks.find(&id) {
463         Some(block) => return *block,
464         None => ()
465     }
466
467     debug!("lexical_block_metadata: %s", bcx.sess().codemap.span_to_str(span));
468
469     let parent = match bcx.parent {
470         None => create_function_metadata(bcx.fcx),
471         Some(b) => lexical_block_metadata(b)
472     };
473
474     let loc = span_start(cx, span);
475     let file_metadata = file_metadata(cx, loc.file.name);
476
477     let lexical_block_metadata = unsafe {
478         llvm::LLVMDIBuilderCreateLexicalBlock(
479             DIB(cx),
480             parent,
481             file_metadata,
482             loc.line as c_uint,
483             loc.col.to_uint() as c_uint)
484     };
485
486     dbg_cx(cx).created_blocks.insert(id, lexical_block_metadata);
487
488     return lexical_block_metadata;
489 }
490
491 fn basic_type_metadata(cx: &mut CrateContext, t: ty::t) -> DIType {
492
493     debug!("basic_type_metadata: %?", ty::get(t));
494
495     let (name, encoding) = match ty::get(t).sty {
496         ty::ty_nil | ty::ty_bot => (~"uint", DW_ATE_unsigned),
497         ty::ty_bool => (~"bool", DW_ATE_boolean),
498         ty::ty_int(int_ty) => match int_ty {
499             ast::ty_i => (~"int", DW_ATE_signed),
500             ast::ty_char => (~"char", DW_ATE_signed_char),
501             ast::ty_i8 => (~"i8", DW_ATE_signed),
502             ast::ty_i16 => (~"i16", DW_ATE_signed),
503             ast::ty_i32 => (~"i32", DW_ATE_signed),
504             ast::ty_i64 => (~"i64", DW_ATE_signed)
505         },
506         ty::ty_uint(uint_ty) => match uint_ty {
507             ast::ty_u => (~"uint", DW_ATE_unsigned),
508             ast::ty_u8 => (~"u8", DW_ATE_unsigned),
509             ast::ty_u16 => (~"u16", DW_ATE_unsigned),
510             ast::ty_u32 => (~"u32", DW_ATE_unsigned),
511             ast::ty_u64 => (~"u64", DW_ATE_unsigned)
512         },
513         ty::ty_float(float_ty) => match float_ty {
514             ast::ty_f => (~"float", DW_ATE_float),
515             ast::ty_f32 => (~"f32", DW_ATE_float),
516             ast::ty_f64 => (~"f64", DW_ATE_float)
517         },
518         _ => cx.sess.bug("debuginfo::basic_type_metadata - t is invalid type")
519     };
520
521     let llvm_type = type_of::type_of(cx, t);
522     let (size, align) = size_and_align_of(cx, llvm_type);
523     let ty_metadata = do name.as_c_str |name| {
524         unsafe {
525             llvm::LLVMDIBuilderCreateBasicType(
526                 DIB(cx),
527                 name,
528                 bytes_to_bits(size),
529                 bytes_to_bits(align),
530                 encoding as c_uint)
531         }
532     };
533
534     return ty_metadata;
535 }
536
537 fn pointer_type_metadata(cx: &mut CrateContext,
538                          pointer_type: ty::t,
539                          pointee_type_metadata: DIType)
540                       -> DIType {
541     let pointer_llvm_type = type_of::type_of(cx, pointer_type);
542     let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
543     let name = ty_to_str(cx.tcx, pointer_type);
544     let ptr_metadata = do name.as_c_str |name| {
545         unsafe {
546             llvm::LLVMDIBuilderCreatePointerType(
547                 DIB(cx),
548                 pointee_type_metadata,
549                 bytes_to_bits(pointer_size),
550                 bytes_to_bits(pointer_align),
551                 name)
552         }
553     };
554     return ptr_metadata;
555 }
556
557 fn struct_metadata(cx: &mut CrateContext,
558                    struct_type: ty::t,
559                    fields: ~[ty::field],
560                    span: span)
561                 -> DICompositeType {
562     let struct_name = ty_to_str(cx.tcx, struct_type);
563     debug!("struct_metadata: %s", struct_name);
564
565     let struct_llvm_type = type_of::type_of(cx, struct_type);
566
567     let field_llvm_types = do fields.map |field| { type_of::type_of(cx, field.mt.ty) };
568     let field_names = do fields.map |field| { cx.sess.str_of(field.ident).to_owned() };
569     let field_types_metadata = do fields.map |field| {
570         type_metadata(cx, field.mt.ty, span)
571     };
572
573     return composite_type_metadata(
574         cx,
575         struct_llvm_type,
576         struct_name,
577         field_llvm_types,
578         field_names,
579         field_types_metadata,
580         span);
581 }
582
583 fn tuple_metadata(cx: &mut CrateContext,
584                   tuple_type: ty::t,
585                   component_types: &[ty::t],
586                   span: span)
587                -> DICompositeType {
588
589     let tuple_name = ty_to_str(cx.tcx, tuple_type);
590     let tuple_llvm_type = type_of::type_of(cx, tuple_type);
591
592     let component_names = do component_types.map |_| { ~"" };
593     let component_llvm_types = do component_types.map |it| { type_of::type_of(cx, *it) };
594     let component_types_metadata = do component_types.map |it| {
595         type_metadata(cx, *it, span)
596     };
597
598     return composite_type_metadata(
599         cx,
600         tuple_llvm_type,
601         tuple_name,
602         component_llvm_types,
603         component_names,
604         component_types_metadata,
605         span);
606 }
607
608 fn enum_metadata(cx: &mut CrateContext,
609                  enum_type: ty::t,
610                  enum_def_id: ast::def_id,
611                  // _substs is only needed in the other version. Will go away with new snapshot.
612                  _substs: &ty::substs,
613                  span: span)
614               -> DIType {
615
616     let enum_name = ty_to_str(cx.tcx, enum_type);
617
618     // For empty enums there is an early exit. Just describe it as an empty struct with the
619     // appropriate type name
620     if ty::type_is_empty(cx.tcx, enum_type) {
621         return composite_type_metadata(cx, Type::nil(), enum_name, [], [], [], span);
622     }
623
624     // Prepare some data (llvm type, size, align, ...) about the discriminant. This data will be
625     // needed in all of the following cases.
626     let discriminant_llvm_type = Type::enum_discrim(cx);
627     let (discriminant_size, discriminant_align) = size_and_align_of(cx, discriminant_llvm_type);
628
629     assert!(Type::enum_discrim(cx) == cx.int_type);
630     let discriminant_type_metadata = type_metadata(cx, ty::mk_int(), span);
631
632     let variants: &[@ty::VariantInfo] = *ty::enum_variants(cx.tcx, enum_def_id);
633
634     let enumerators_metadata: ~[DIDescriptor] = variants
635         .iter()
636         .transform(|v| {
637             let name: &str = cx.sess.str_of(v.name);
638             let discriminant_value = v.disr_val as c_ulonglong;
639
640             do name.as_c_str |name| {
641                 unsafe {
642                     llvm::LLVMDIBuilderCreateEnumerator(
643                         DIB(cx),
644                         name,
645                         discriminant_value)
646                 }
647             }
648         })
649         .collect();
650
651     let loc = span_start(cx, span);
652     let file_metadata = file_metadata(cx, loc.file.name);
653
654     let discriminant_type_metadata = do enum_name.as_c_str |enum_name| {
655         unsafe {
656             llvm::LLVMDIBuilderCreateEnumerationType(
657                 DIB(cx),
658                 file_metadata,
659                 enum_name,
660                 file_metadata,
661                 loc.line as c_uint,
662                 bytes_to_bits(discriminant_size),
663                 bytes_to_bits(discriminant_align),
664                 create_DIArray(DIB(cx), enumerators_metadata),
665                 discriminant_type_metadata)
666         }
667     };
668
669     let type_rep = adt::represent_type(cx, enum_type);
670
671     match *type_rep {
672         adt::CEnum(*) => {
673             return discriminant_type_metadata;
674         }
675         adt::Univariant(ref struct_def, _) => {
676             assert!(variants.len() == 1);
677             return adt_struct_metadata(cx, struct_def, variants[0], None, span);
678         }
679         adt::General(ref struct_defs) => {
680             let variants_member_metadata: ~[DIDescriptor] = do struct_defs
681                 .iter()
682                 .enumerate()
683                 .transform |(i, struct_def)| {
684                     let variant_type_metadata = adt_struct_metadata(
685                         cx,
686                         struct_def,
687                         variants[i],
688                         Some(discriminant_type_metadata),
689                         span);
690
691                     do "".as_c_str |name| {
692                         unsafe {
693                             llvm::LLVMDIBuilderCreateMemberType(
694                                 DIB(cx),
695                                 file_metadata,
696                                 name,
697                                 file_metadata,
698                                 loc.line as c_uint,
699                                 bytes_to_bits(struct_def.size as uint),
700                                 bytes_to_bits(struct_def.align as uint),
701                                 bytes_to_bits(0),
702                                 0,
703                                 variant_type_metadata)
704                         }
705                     }
706             }.collect();
707
708             let enum_llvm_type = type_of::type_of(cx, enum_type);
709             let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type);
710
711             return do enum_name.as_c_str |enum_name| {
712                 unsafe {
713                     llvm::LLVMDIBuilderCreateUnionType(
714                     DIB(cx),
715                     file_metadata,
716                     enum_name,
717                     file_metadata,
718                     loc.line as c_uint,
719                     bytes_to_bits(enum_type_size),
720                     bytes_to_bits(enum_type_align),
721                     0, // Flags
722                     create_DIArray(DIB(cx), variants_member_metadata),
723                     0) // RuntimeLang
724             }};
725         }
726         adt::NullablePointer { nonnull: ref struct_def, nndiscr, _ } => {
727             return adt_struct_metadata(cx, struct_def, variants[nndiscr], None, span);
728         }
729     }
730
731     fn adt_struct_metadata(cx: &mut CrateContext,
732                                   struct_def: &adt::Struct,
733                                   variant_info: &ty::VariantInfo,
734                                   discriminant_type_metadata: Option<DIType>,
735                                   span: span)
736                                -> DICompositeType
737     {
738         let arg_llvm_types: ~[Type] = do struct_def.fields.map |&ty| { type_of::type_of(cx, ty) };
739         let arg_metadata: ~[DIType] = do struct_def.fields.iter().enumerate()
740             .transform |(i, &ty)| {
741                 match discriminant_type_metadata {
742                     Some(metadata) if i == 0 => metadata,
743                     _                        => type_metadata(cx, ty, span)
744                 }
745         }.collect();
746
747         let mut arg_names = match variant_info.arg_names {
748             Some(ref names) => do names.map |ident| { cx.sess.str_of(*ident).to_owned() },
749             None => do variant_info.args.map |_| { ~"" }
750         };
751
752         if discriminant_type_metadata.is_some() {
753             arg_names.insert(0, ~"");
754         }
755
756         let variant_llvm_type = Type::struct_(arg_llvm_types, struct_def.packed);
757         let variant_name: &str = cx.sess.str_of(variant_info.name);
758
759         return composite_type_metadata(
760             cx,
761             variant_llvm_type,
762             variant_name,
763             arg_llvm_types,
764             arg_names,
765             arg_metadata,
766             span);
767     }
768 }
769
770 /// Creates debug information for a composite type, that is, anything that results in a LLVM struct.
771 ///
772 /// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums.
773 fn composite_type_metadata(cx: &mut CrateContext,
774                            composite_llvm_type: Type,
775                            composite_type_name: &str,
776                            member_llvm_types: &[Type],
777                            member_names: &[~str],
778                            member_type_metadata: &[DIType],
779                            span: span)
780                         -> DICompositeType {
781
782     let loc = span_start(cx, span);
783     let file_metadata = file_metadata(cx, loc.file.name);
784
785     let (composite_size, composite_align) = size_and_align_of(cx, composite_llvm_type);
786
787     let member_metadata: ~[DIDescriptor] = member_llvm_types
788         .iter()
789         .enumerate()
790         .transform(|(i, &member_llvm_type)| {
791             let (member_size, member_align) = size_and_align_of(cx, member_llvm_type);
792             let member_offset = machine::llelement_offset(cx, composite_llvm_type, i);
793             let member_name: &str = member_names[i];
794
795             do member_name.as_c_str |member_name| {
796                 unsafe {
797                     llvm::LLVMDIBuilderCreateMemberType(
798                         DIB(cx),
799                         file_metadata,
800                         member_name,
801                         file_metadata,
802                         loc.line as c_uint,
803                         bytes_to_bits(member_size),
804                         bytes_to_bits(member_align),
805                         bytes_to_bits(member_offset),
806                         0,
807                         member_type_metadata[i])
808                 }
809             }
810         })
811         .collect();
812
813     return do composite_type_name.as_c_str |name| {
814         unsafe {
815             llvm::LLVMDIBuilderCreateStructType(
816                 DIB(cx),
817                 file_metadata,
818                 name,
819                 file_metadata,
820                 loc.line as c_uint,
821                 bytes_to_bits(composite_size),
822                 bytes_to_bits(composite_align),
823                 0,
824                 ptr::null(),
825                 create_DIArray(DIB(cx), member_metadata),
826                 0,
827                 ptr::null())
828     }
829     };
830 }
831
832 fn boxed_type_metadata(cx: &mut CrateContext,
833                        content_type_name: Option<&str>,
834                        content_llvm_type: Type,
835                        content_type_metadata: DIType,
836                        span: span)
837                     -> DICompositeType {
838
839     let box_type_name = match content_type_name {
840         Some(content_type_name) => fmt!("Boxed<%s>", content_type_name),
841         None                    => ~"BoxedType"
842     };
843
844     let box_llvm_type = Type::box(cx, &content_llvm_type);
845     let member_llvm_types = box_llvm_type.field_types();
846     let member_names = [~"refcnt", ~"tydesc", ~"prev", ~"next", ~"val"];
847
848     assert!(box_layout_is_correct(cx, member_llvm_types, content_llvm_type));
849
850     let int_type = ty::mk_int();
851     let nil_pointer_type = ty::mk_nil_ptr(cx.tcx);
852
853     let member_types_metadata = [
854         type_metadata(cx, int_type, span),
855         type_metadata(cx, nil_pointer_type, span),
856         type_metadata(cx, nil_pointer_type, span),
857         type_metadata(cx, nil_pointer_type, span),
858         content_type_metadata
859     ];
860
861     return composite_type_metadata(
862         cx,
863         box_llvm_type,
864         box_type_name,
865         member_llvm_types,
866         member_names,
867         member_types_metadata,
868         span);
869
870     // Unfortunately, we cannot assert anything but the correct types here---and not whether the
871     // 'next' and 'prev' pointers are in the correct order.
872     fn box_layout_is_correct(cx: &CrateContext,
873                              member_llvm_types: &[Type],
874                              content_llvm_type: Type)
875                           -> bool {
876         member_llvm_types.len() == 5 &&
877         member_llvm_types[0] == cx.int_type &&
878         member_llvm_types[1] == cx.tydesc_type.ptr_to() &&
879         member_llvm_types[2] == Type::i8().ptr_to() &&
880         member_llvm_types[3] == Type::i8().ptr_to() &&
881         member_llvm_types[4] == content_llvm_type
882     }
883 }
884
885 fn fixed_vec_metadata(cx: &mut CrateContext,
886                       element_type: ty::t,
887                       len: uint,
888                       span: span)
889                    -> DIType {
890     let element_type_metadata = type_metadata(cx, element_type, span);
891     let element_llvm_type = type_of::type_of(cx, element_type);
892     let (element_type_size, element_type_align) = size_and_align_of(cx, element_llvm_type);
893
894     let subrange = unsafe {
895         llvm::LLVMDIBuilderGetOrCreateSubrange(
896         DIB(cx),
897         0,
898         len as c_longlong)
899     };
900
901     let subscripts = create_DIArray(DIB(cx), [subrange]);
902     return unsafe {
903         llvm::LLVMDIBuilderCreateArrayType(
904             DIB(cx),
905             bytes_to_bits(element_type_size * len),
906             bytes_to_bits(element_type_align),
907             element_type_metadata,
908             subscripts)
909     };
910 }
911
912 fn vec_metadata(cx: &mut CrateContext,
913                 element_type: ty::t,
914                 span: span)
915              -> DICompositeType {
916
917     let element_type_metadata = type_metadata(cx, element_type, span);
918     let element_llvm_type = type_of::type_of(cx, element_type);
919     let (element_size, element_align) = size_and_align_of(cx, element_llvm_type);
920
921     let vec_llvm_type = Type::vec(cx.sess.targ_cfg.arch, &element_llvm_type);
922     let vec_type_name: &str = fmt!("[%s]", ty_to_str(cx.tcx, element_type));
923
924     let member_llvm_types = vec_llvm_type.field_types();
925     let member_names = &[~"fill", ~"alloc", ~"elements"];
926
927     let int_type_metadata = type_metadata(cx, ty::mk_int(), span);
928     let array_type_metadata = unsafe {
929         llvm::LLVMDIBuilderCreateArrayType(
930             DIB(cx),
931             bytes_to_bits(element_size),
932             bytes_to_bits(element_align),
933             element_type_metadata,
934             create_DIArray(DIB(cx), [llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, 0)]))
935     };
936
937     //                           fill               alloc              elements
938     let member_type_metadata = &[int_type_metadata, int_type_metadata, array_type_metadata];
939
940     return composite_type_metadata(
941         cx,
942         vec_llvm_type,
943         vec_type_name,
944         member_llvm_types,
945         member_names,
946         member_type_metadata,
947         span);
948 }
949
950 fn boxed_vec_metadata(cx: &mut CrateContext,
951                       element_type: ty::t,
952                       span: span)
953                    -> DICompositeType {
954
955     let element_llvm_type = type_of::type_of(cx, element_type);
956     let vec_llvm_type = Type::vec(cx.sess.targ_cfg.arch, &element_llvm_type);
957     let vec_type_name: &str = fmt!("[%s]", ty_to_str(cx.tcx, element_type));
958     let vec_metadata = vec_metadata(cx, element_type, span);
959
960     return boxed_type_metadata(
961         cx,
962         Some(vec_type_name),
963         vec_llvm_type,
964         vec_metadata,
965         span);
966 }
967
968 fn vec_slice_metadata(cx: &mut CrateContext,
969                       vec_type: ty::t,
970                       element_type: ty::t,
971                       span: span)
972                    -> DICompositeType {
973
974     debug!("vec_slice_metadata: %?", ty::get(vec_type));
975
976     let slice_llvm_type = type_of::type_of(cx, vec_type);
977     let slice_type_name = ty_to_str(cx.tcx, vec_type);
978
979     let member_llvm_types = slice_llvm_type.field_types();
980     let member_names = &[~"data_ptr", ~"size_in_bytes"];
981
982     assert!(slice_layout_is_correct(cx, member_llvm_types, element_type));
983
984     let data_ptr_type = ty::mk_ptr(cx.tcx, ty::mt { ty: element_type, mutbl: ast::m_imm });
985
986     let member_type_metadata = &[type_metadata(cx, data_ptr_type, span),
987                                  type_metadata(cx, ty::mk_uint(), span)];
988
989     return composite_type_metadata(
990         cx,
991         slice_llvm_type,
992         slice_type_name,
993         member_llvm_types,
994         member_names,
995         member_type_metadata,
996         span);
997
998     fn slice_layout_is_correct(cx: &mut CrateContext,
999                                member_llvm_types: &[Type],
1000                                element_type: ty::t)
1001                             -> bool {
1002         member_llvm_types.len() == 2 &&
1003         member_llvm_types[0] == type_of::type_of(cx, element_type).ptr_to() &&
1004         member_llvm_types[1] == cx.int_type
1005     }
1006 }
1007
1008 fn bare_fn_metadata(cx: &mut CrateContext,
1009                     _fn_ty: ty::t,
1010                     inputs: ~[ty::t],
1011                     output: ty::t,
1012                     span: span)
1013                  -> DICompositeType {
1014
1015     debug!("bare_fn_metadata: %?", ty::get(_fn_ty));
1016
1017     let loc = span_start(cx, span);
1018     let file_metadata = file_metadata(cx, loc.file.name);
1019
1020     let nil_pointer_type_metadata = type_metadata(cx, ty::mk_nil_ptr(cx.tcx), span);
1021     let output_metadata = type_metadata(cx, output, span);
1022     let output_ptr_metadata = pointer_type_metadata(cx, output, output_metadata);
1023
1024     let inputs_vals = do inputs.map |arg| { type_metadata(cx, *arg, span) };
1025     let members = ~[output_ptr_metadata, nil_pointer_type_metadata] + inputs_vals;
1026
1027     return unsafe {
1028         llvm::LLVMDIBuilderCreateSubroutineType(
1029             DIB(cx),
1030             file_metadata,
1031             create_DIArray(DIB(cx), members))
1032     };
1033 }
1034
1035 fn unimplemented_type_metadata(cx: &mut CrateContext, t: ty::t) -> DIType {
1036     debug!("unimplemented_type_metadata: %?", ty::get(t));
1037
1038     let name = ty_to_str(cx.tcx, t);
1039     let metadata = do fmt!("NYI<%s>", name).as_c_str |name| {
1040         unsafe {
1041             llvm::LLVMDIBuilderCreateBasicType(
1042                 DIB(cx),
1043                 name,
1044                 0_u64,
1045                 8_u64,
1046                 DW_ATE_unsigned as c_uint)
1047             }
1048         };
1049
1050     return metadata;
1051 }
1052
1053 fn type_metadata(cx: &mut CrateContext,
1054                  t: ty::t,
1055                  span: span)
1056               -> DIType {
1057     let type_id = ty::type_id(t);
1058     match dbg_cx(cx).created_types.find(&type_id) {
1059         Some(type_metadata) => return *type_metadata,
1060         None => ()
1061     }
1062
1063     fn create_pointer_to_box_metadata(cx: &mut CrateContext,
1064                                       pointer_type: ty::t,
1065                                       type_in_box: ty::t)
1066                                    -> DIType {
1067
1068         let content_type_name: &str = ty_to_str(cx.tcx, type_in_box);
1069         let content_llvm_type = type_of::type_of(cx, type_in_box);
1070         let content_type_metadata = type_metadata(
1071             cx,
1072             type_in_box,
1073             codemap::dummy_sp());
1074
1075         let box_metadata = boxed_type_metadata(
1076             cx,
1077             Some(content_type_name),
1078             content_llvm_type,
1079             content_type_metadata,
1080             codemap::dummy_sp());
1081
1082         pointer_type_metadata(cx, pointer_type, box_metadata)
1083     }
1084
1085     debug!("type_metadata: %?", ty::get(t));
1086
1087     let sty = &ty::get(t).sty;
1088     let type_metadata = match *sty {
1089         ty::ty_nil      |
1090         ty::ty_bot      |
1091         ty::ty_bool     |
1092         ty::ty_int(_)   |
1093         ty::ty_uint(_)  |
1094         ty::ty_float(_) => {
1095             basic_type_metadata(cx, t)
1096         },
1097         ty::ty_estr(ref vstore) => {
1098             let i8_t = ty::mk_i8();
1099             match *vstore {
1100                 ty::vstore_fixed(len) => {
1101                     fixed_vec_metadata(cx, i8_t, len + 1, span)
1102                 },
1103                 ty::vstore_uniq  => {
1104                     let vec_metadata = vec_metadata(cx, i8_t, span);
1105                     pointer_type_metadata(cx, t, vec_metadata)
1106                 }
1107                 ty::vstore_box => {
1108                     let boxed_vec_metadata = boxed_vec_metadata(cx, i8_t, span);
1109                     pointer_type_metadata(cx, t, boxed_vec_metadata)
1110                 }
1111                 ty::vstore_slice(_region) => {
1112                     vec_slice_metadata(cx, t, i8_t, span)
1113                 }
1114             }
1115         },
1116         ty::ty_enum(def_id, ref substs) => {
1117             enum_metadata(cx, t, def_id, substs, span)
1118         },
1119         ty::ty_box(ref mt) => {
1120             create_pointer_to_box_metadata(cx, t, mt.ty)
1121         },
1122         ty::ty_evec(ref mt, ref vstore) => {
1123             match *vstore {
1124                 ty::vstore_fixed(len) => {
1125                     fixed_vec_metadata(cx, mt.ty, len, span)
1126                 }
1127                 ty::vstore_uniq if ty::type_contents(cx.tcx, mt.ty).contains_managed() => {
1128                     let boxed_vec_metadata = boxed_vec_metadata(cx, mt.ty, span);
1129                     pointer_type_metadata(cx, t, boxed_vec_metadata)
1130                 }
1131                 ty::vstore_uniq => {
1132                     let vec_metadata = vec_metadata(cx, mt.ty, span);
1133                     pointer_type_metadata(cx, t, vec_metadata)
1134                 }
1135                 ty::vstore_box => {
1136                     let boxed_vec_metadata = boxed_vec_metadata(cx, mt.ty, span);
1137                     pointer_type_metadata(cx, t, boxed_vec_metadata)
1138                 }
1139                 ty::vstore_slice(_) => {
1140                     vec_slice_metadata(cx, t, mt.ty, span)
1141                 }
1142             }
1143         },
1144         ty::ty_uniq(ref mt) if ty::type_contents(cx.tcx, mt.ty).contains_managed() => {
1145             create_pointer_to_box_metadata(cx, t, mt.ty)
1146         },
1147         ty::ty_uniq(ref mt)    |
1148         ty::ty_ptr(ref mt)     |
1149         ty::ty_rptr(_, ref mt) => {
1150             let pointee = type_metadata(cx, mt.ty, span);
1151             pointer_type_metadata(cx, t, pointee)
1152         },
1153         ty::ty_bare_fn(ref barefnty) => {
1154             let inputs = barefnty.sig.inputs.map(|a| *a);
1155             let output = barefnty.sig.output;
1156             bare_fn_metadata(cx, t, inputs, output, span)
1157         },
1158         ty::ty_closure(ref _closurety) => {
1159             cx.sess.span_note(span, "debuginfo for closure NYI");
1160             unimplemented_type_metadata(cx, t)
1161         },
1162         ty::ty_trait(_did, ref _substs, ref _vstore, _, _bounds) => {
1163             cx.sess.span_note(span, "debuginfo for trait NYI");
1164             unimplemented_type_metadata(cx, t)
1165         },
1166         ty::ty_struct(did, ref substs) => {
1167             let fields = ty::struct_fields(cx.tcx, did, substs);
1168             struct_metadata(cx, t, fields, span)
1169         },
1170         ty::ty_tup(ref elements) => {
1171             tuple_metadata(cx, t, *elements, span)
1172         },
1173         _ => cx.sess.bug("debuginfo: unexpected type in type_metadata")
1174     };
1175
1176     dbg_cx(cx).created_types.insert(type_id, type_metadata);
1177     return type_metadata;
1178 }
1179
1180 fn set_debug_location(cx: @mut CrateContext, scope: DIScope, line: uint, col: uint) {
1181     if dbg_cx(cx).curr_loc == (line, col) {
1182         return;
1183     }
1184     debug!("setting debug location to %u %u", line, col);
1185     dbg_cx(cx).curr_loc = (line, col);
1186
1187     let elems = ~[C_i32(line as i32), C_i32(col as i32), scope, ptr::null()];
1188     unsafe {
1189         let dbg_loc = llvm::LLVMMDNodeInContext(
1190                 dbg_cx(cx).llcontext,
1191                 vec::raw::to_ptr(elems),
1192                 elems.len() as c_uint);
1193
1194         llvm::LLVMSetCurrentDebugLocation(cx.builder.B, dbg_loc);
1195     }
1196 }
1197
1198
1199 //=-------------------------------------------------------------------------------------------------
1200 //  Utility Functions
1201 //=-------------------------------------------------------------------------------------------------
1202
1203 #[inline]
1204 fn roundup(x: uint, a: uint) -> uint {
1205     ((x + (a - 1)) / a) * a
1206 }
1207
1208 /// Return codemap::Loc corresponding to the beginning of the span
1209 fn span_start(cx: &CrateContext, span: span) -> codemap::Loc {
1210     cx.sess.codemap.lookup_char_pos(span.lo)
1211 }
1212
1213 fn size_and_align_of(cx: &mut CrateContext, llvm_type: Type) -> (uint, uint) {
1214     (machine::llsize_of_alloc(cx, llvm_type), machine::llalign_of_min(cx, llvm_type))
1215 }
1216
1217 fn bytes_to_bits(bytes: uint) -> c_ulonglong {
1218     (bytes * 8) as c_ulonglong
1219 }
1220
1221 #[inline]
1222 fn dbg_cx<'a>(cx: &'a mut CrateContext) -> &'a mut DebugContext {
1223     cx.dbg_cx.get_mut_ref()
1224 }
1225
1226 #[inline]
1227 fn DIB(cx: &CrateContext) -> DIBuilderRef {
1228     cx.dbg_cx.get_ref().builder
1229 }