debuginfo.rs 30.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

11
use core::prelude::*;
12

13
use driver::session;
P
Patrick Walton 已提交
14
use lib::llvm::ValueRef;
15 16 17 18 19
use lib::llvm::llvm;
use middle::pat_util::*;
use middle::trans::base;
use middle::trans::build::B;
use middle::trans::common::*;
20
use middle::trans::machine;
21 22
use middle::trans::type_of;
use middle::trans;
P
Patrick Walton 已提交
23 24
use middle::ty;
use util::ppaux::ty_to_str;
25

26 27 28
use core::libc;
use core::option;
use core::sys;
29 30
use std::oldmap::HashMap;
use std::oldmap;
31 32 33 34
use syntax::ast::Ty;
use syntax::codemap::{span, CharPos};
use syntax::parse::token::ident_interner;
use syntax::{ast, codemap, ast_util, ast_map};
35

36
const LLVMDebugVersion: int = (9 << 16);
37 38 39 40 41 42 43

const DW_LANG_RUST: int = 0x9000;
const DW_VIRTUALITY_none: int = 0;

const CompileUnitTag: int = 17;
const FileDescriptorTag: int = 41;
const SubprogramTag: int = 46;
44
const SubroutineTag: int = 21;
45 46 47 48 49
const BasicTypeDescriptorTag: int = 36;
const AutoVariableTag: int = 256;
const ArgVariableTag: int = 257;
const ReturnVariableTag: int = 258;
const LexicalBlockTag: int = 11;
50 51 52
const PointerTypeTag: int = 15;
const StructureTypeTag: int = 19;
const MemberTag: int = 13;
J
Josh Matthews 已提交
53 54
const ArrayTypeTag: int = 1;
const SubrangeTag: int = 33;
55 56 57 58 59 60 61

const DW_ATE_boolean: int = 0x02;
const DW_ATE_float: int = 0x04;
const DW_ATE_signed: int = 0x05;
const DW_ATE_signed_char: int = 0x06;
const DW_ATE_unsigned: int = 0x07;
const DW_ATE_unsigned_char: int = 0x08;
62

63 64
fn llstr(s: &str) -> ValueRef {
    do str::as_c_str(s) |sbuf| {
65
        unsafe {
66
            llvm::LLVMMDString(sbuf, s.len() as libc::c_uint)
67
        }
68
    }
69 70
}
fn lltag(lltag: int) -> ValueRef {
71
    lli32(LLVMDebugVersion | lltag)
72 73 74 75
}
fn lli32(val: int) -> ValueRef {
    C_i32(val as i32)
}
76 77 78
fn lli64(val: int) -> ValueRef {
    C_i64(val as i64)
}
79
fn lli1(bval: bool) -> ValueRef {
80
    C_i1(bval)
81
}
82
fn llmdnode(elems: &[ValueRef]) -> ValueRef {
83
    unsafe {
84
        llvm::LLVMMDNode(vec::raw::to_ptr(elems), elems.len() as libc::c_uint)
85
    }
86 87 88 89
}
fn llunused() -> ValueRef {
    lli32(0x0)
}
90 91 92 93
fn llnull() -> ValueRef {
    unsafe {
        cast::reinterpret_cast(&ptr::null::<ValueRef>())
    }
94
}
95

96
fn add_named_metadata(cx: @CrateContext, name: ~str, val: ValueRef) {
B
Brian Anderson 已提交
97
    str::as_c_str(name, |sbuf| {
98 99 100
        unsafe {
            llvm::LLVMAddNamedMetadataOperand(cx.llmod, sbuf, val)
        }
101
    })
102 103 104 105
}

////////////////

106
pub struct DebugContext {
J
Josh Matthews 已提交
107
    llmetadata: metadata_cache,
108
    names: namegen,
109
    crate_file: ~str
110
}
J
Josh Matthews 已提交
111

112 113 114 115 116 117
pub fn mk_ctxt(+crate: ~str, intr: @ident_interner) -> DebugContext {
    DebugContext {
        llmetadata: oldmap::HashMap(),
        names: new_namegen(intr),
        crate_file: crate
    }
118 119
}

120
fn update_cache(cache: metadata_cache, mdtag: int, val: debug_metadata) {
121
    let existing = if cache.contains_key(&mdtag) {
122
        cache.get(&mdtag)
123
    } else {
124
        ~[]
125
    };
126
    cache.insert(mdtag, vec::append_one(existing, val));
127
}
J
Josh Matthews 已提交
128

129 130 131 132
struct Metadata<T> {
    node: ValueRef,
    data: T
}
133

134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
struct FileMetadata {
    path: ~str
}
struct CompileUnitMetadata {
    name: ~str
}
struct SubProgramMetadata {
    id: ast::node_id
}
struct LocalVarMetadata {
    id: ast::node_id
}
struct TyDescMetadata {
    hash: uint
}
L
Luqman Aden 已提交
149
struct BlockMetadata {
150 151 152 153 154 155 156 157 158
    start: codemap::Loc,
    end: codemap::Loc
}
struct ArgumentMetadata {
    id: ast::node_id
}
struct RetvalMetadata {
    id: ast::node_id
}
159

B
Brian Anderson 已提交
160
type metadata_cache = HashMap<int, ~[debug_metadata]>;
161

P
Patrick Walton 已提交
162
enum debug_metadata {
163 164 165 166 167 168 169 170
    file_metadata(@Metadata<FileMetadata>),
    compile_unit_metadata(@Metadata<CompileUnitMetadata>),
    subprogram_metadata(@Metadata<SubProgramMetadata>),
    local_var_metadata(@Metadata<LocalVarMetadata>),
    tydesc_metadata(@Metadata<TyDescMetadata>),
    block_metadata(@Metadata<BlockMetadata>),
    argument_metadata(@Metadata<ArgumentMetadata>),
    retval_metadata(@Metadata<RetvalMetadata>),
171 172
}

173
fn cast_safely<T:Copy,U>(val: T) -> U {
174 175
    unsafe {
        let val2 = val;
L
Luqman Aden 已提交
176
        return cast::transmute(val2);
177
    }
178 179
}

180 181 182 183 184 185 186 187 188 189 190 191
fn md_from_metadata<T>(val: debug_metadata) -> T {
    unsafe {
        match val {
          file_metadata(md) => cast_safely(md),
          compile_unit_metadata(md) => cast_safely(md),
          subprogram_metadata(md) => cast_safely(md),
          local_var_metadata(md) => cast_safely(md),
          tydesc_metadata(md) => cast_safely(md),
          block_metadata(md) => cast_safely(md),
          argument_metadata(md) => cast_safely(md),
          retval_metadata(md) => cast_safely(md)
        }
192 193 194
    }
}

195
fn cached_metadata<T:Copy>(cache: metadata_cache,
196 197 198
                            mdtag: int,
                            eq_fn: fn(md: T) -> bool)
                         -> Option<T> {
199
    unsafe {
200
        if cache.contains_key(&mdtag) {
201
            let items = cache.get(&mdtag);
202 203
            for items.each |item| {
                let md: T = md_from_metadata::<T>(*item);
204
                if eq_fn(md) {
205 206
                    return option::Some(md);
                }
207 208
            }
        }
209
        return option::None;
210 211 212
    }
}

213
fn create_compile_unit(cx: @CrateContext) -> @Metadata<CompileUnitMetadata> {
214 215 216 217
    unsafe {
        let cache = get_cache(cx);
        let crate_name = /*bad*/copy (/*bad*/copy cx.dbg_cx).get().crate_file;
        let tg = CompileUnitTag;
218
        match cached_metadata::<@Metadata<CompileUnitMetadata>>(cache, tg,
219 220 221 222
                            |md| md.data.name == crate_name) {
          option::Some(md) => return md,
          option::None => ()
        }
223

224 225 226 227 228
        let (_, work_dir) = get_file_path_and_dir(
            cx.sess.working_dir.to_str(), crate_name);
        let unit_metadata = ~[lltag(tg),
                             llunused(),
                             lli32(DW_LANG_RUST),
229
                             llstr(crate_name),
230 231 232 233 234 235 236 237 238
                             llstr(work_dir),
                             llstr(env!("CFG_VERSION")),
                             lli1(true), // deprecated: main compile unit
                             lli1(cx.sess.opts.optimize != session::No),
                             llstr(~""), // flags (???)
                             lli32(0) // runtime version (???)
                            ];
        let unit_node = llmdnode(unit_metadata);
        add_named_metadata(cx, ~"llvm.dbg.cu", unit_node);
239 240 241 242 243 244
        let mdval = @Metadata {
            node: unit_node,
            data: CompileUnitMetadata {
                name: crate_name
            }
        };
245 246 247 248
        update_cache(cache, tg, compile_unit_metadata(mdval));

        return mdval;
    }
249 250
}

251
fn get_cache(cx: @CrateContext) -> metadata_cache {
252
    (/*bad*/copy cx.dbg_cx).get().llmetadata
J
Josh Matthews 已提交
253 254
}

255
fn get_file_path_and_dir(work_dir: &str, full_path: &str) -> (~str, ~str) {
256 257 258 259
    (if str::starts_with(full_path, work_dir) {
        str::slice(full_path, str::len(work_dir) + 1u,
                   str::len(full_path))
    } else {
260 261
        str::from_slice(full_path)
    }, str::from_slice(work_dir))
262 263
}

L
Luqman Aden 已提交
264 265
fn create_file(cx: @CrateContext, +full_path: ~str)
    -> @Metadata<FileMetadata> {
J
Josh Matthews 已提交
266 267
    let cache = get_cache(cx);;
    let tg = FileDescriptorTag;
268
    match cached_metadata::<@Metadata<FileMetadata>>(
B
Brian Anderson 已提交
269
        cache, tg, |md| md.data.path == full_path) {
B
Brian Anderson 已提交
270 271
        option::Some(md) => return md,
        option::None => ()
272
    }
273

274 275 276
    let (file_path, work_dir) =
        get_file_path_and_dir(cx.sess.working_dir.to_str(),
                              full_path);
277
    let unit_node = create_compile_unit(cx).node;
278
    let file_md = ~[lltag(tg),
279 280
                   llstr(file_path),
                   llstr(work_dir),
281
                   unit_node];
282
    let val = llmdnode(file_md);
283 284 285 286 287 288
    let mdval = @Metadata {
        node: val,
        data: FileMetadata {
            path: full_path
        }
    };
J
Josh Matthews 已提交
289
    update_cache(cache, tg, file_metadata(mdval));
B
Brian Anderson 已提交
290
    return mdval;
291 292
}

293
fn line_from_span(cm: @codemap::CodeMap, sp: span) -> uint {
B
Brian Anderson 已提交
294
    cm.lookup_char_pos(sp.lo).line
J
Josh Matthews 已提交
295 296
}

297
fn create_block(cx: block) -> @Metadata<BlockMetadata> {
298
    let cache = get_cache(cx.ccx());
299
    let mut cx = cx;
B
Brian Anderson 已提交
300
    while cx.node_info.is_none() {
301
        match cx.parent {
B
Brian Anderson 已提交
302
          Some(b) => cx = b,
303
          None => fail!()
304 305
        }
    }
B
Brian Anderson 已提交
306
    let sp = cx.node_info.get().span;
307

B
Brian Anderson 已提交
308
    let start = cx.sess().codemap.lookup_char_pos(sp.lo);
309
    let fname = /*bad*/copy start.file.name;
B
Brian Anderson 已提交
310
    let end = cx.sess().codemap.lookup_char_pos(sp.hi);
J
Josh Matthews 已提交
311
    let tg = LexicalBlockTag;
312
    /*match cached_metadata::<@Metadata<BlockMetadata>>(
J
Josh Matthews 已提交
313
        cache, tg,
314
        {|md| start == md.data.start && end == md.data.end}) {
B
Brian Anderson 已提交
315 316
      option::Some(md) { return md; }
      option::None {}
317
    }*/
318

319
    let parent = match cx.parent {
B
Brian Anderson 已提交
320 321
        None => create_function(cx.fcx).node,
        Some(bcx) => create_block(bcx).node
322
    };
323
    let file_node = create_file(cx.ccx(), fname);
324
    let unique_id = match cache.find(&LexicalBlockTag) {
B
Brian Anderson 已提交
325 326
      option::Some(v) => vec::len(v) as int,
      option::None => 0
327
    };
328
    let lldata = ~[lltag(tg),
329
                  parent,
330 331
                  lli32(start.line.to_int()),
                  lli32(start.col.to_int()),
332 333
                  file_node.node,
                  lli32(unique_id)
334
                 ];
335
    let val = llmdnode(lldata);
336 337 338 339 340 341 342
    let mdval = @Metadata {
        node: val,
        data: BlockMetadata {
            start: start,
            end: end
        }
    };
343
    //update_cache(cache, tg, block_metadata(mdval));
B
Brian Anderson 已提交
344
    return mdval;
345 346
}

347
fn size_and_align_of(cx: @CrateContext, t: ty::t) -> (int, int) {
348
    let llty = type_of::type_of(cx, t);
349 350
    (machine::llsize_of_real(cx, llty) as int,
     machine::llalign_of_pref(cx, llty) as int)
351 352
}

353 354
fn create_basic_type(cx: @CrateContext, t: ty::t, span: span)
    -> @Metadata<TyDescMetadata> {
J
Josh Matthews 已提交
355
    let cache = get_cache(cx);
356
    let tg = BasicTypeDescriptorTag;
357
    match cached_metadata::<@Metadata<TyDescMetadata>>(
B
Brian Anderson 已提交
358
        cache, tg, |md| ty::type_id(t) == md.data.hash) {
B
Brian Anderson 已提交
359 360
      option::Some(md) => return md,
      option::None => ()
361
    }
362

363
    let (name, encoding) = (~"uint", DW_ATE_unsigned);
364

365
    let fname = filename_from_span(cx, span);
366
    let file_node = create_file(cx, fname);
367
    let cu_node = create_compile_unit(cx);
368
    let (size, align) = size_and_align_of(cx, t);
369
    let lldata = ~[lltag(tg),
370
                  cu_node.node,
371
                  llstr(name),
372
                  file_node.node,
373 374 375
                  lli32(0), //XXX source line
                  lli64(size * 8),  // size in bits
                  lli64(align * 8), // alignment in bits
376
                  lli64(0), //XXX offset?
377
                  lli32(0), //XXX flags?
378
                  lli32(encoding)];
379
    let llnode = llmdnode(lldata);
380 381 382 383 384 385
    let mdval = @Metadata {
        node: llnode,
        data: TyDescMetadata {
            hash: ty::type_id(t)
        }
    };
386
    update_cache(cache, tg, tydesc_metadata(mdval));
387
    add_named_metadata(cx, ~"llvm.dbg.ty", llnode);
B
Brian Anderson 已提交
388
    return mdval;
389 390
}

391 392 393
fn create_pointer_type(cx: @CrateContext, t: ty::t, span: span,
                       pointee: @Metadata<TyDescMetadata>)
    -> @Metadata<TyDescMetadata> {
394 395
    let tg = PointerTypeTag;
    /*let cache = cx.llmetadata;
396
    match cached_metadata::<@Metadata<TyDescMetadata>>(
397
        cache, tg, {|md| ty::hash_ty(t) == ty::hash_ty(md.data.hash)}) {
B
Brian Anderson 已提交
398 399
      option::Some(md) { return md; }
      option::None {}
400
    }*/
401
    let (size, align) = size_and_align_of(cx, t);
402
    let fname = filename_from_span(cx, span);
403 404
    let file_node = create_file(cx, fname);
    //let cu_node = create_compile_unit(cx, fname);
405
    let llnode = create_derived_type(tg, file_node.node, ~"", 0, size * 8,
406
                                     align * 8, 0, pointee.node);
407 408 409 410 411 412
    let mdval = @Metadata {
        node: llnode,
        data: TyDescMetadata {
            hash: ty::type_id(t)
        }
    };
413
    //update_cache(cache, tg, tydesc_metadata(mdval));
414
    add_named_metadata(cx, ~"llvm.dbg.ty", llnode);
B
Brian Anderson 已提交
415
    return mdval;
416 417
}

418
struct StructCtxt {
J
Josh Matthews 已提交
419
    file: ValueRef,
420
    name: @~str,
J
Josh Matthews 已提交
421
    line: int,
422 423
    members: ~[ValueRef],
    total_size: int,
J
Josh Matthews 已提交
424
    align: int
425
}
J
Josh Matthews 已提交
426

427
fn finish_structure(cx: @mut StructCtxt) -> ValueRef {
428
    return create_composite_type(StructureTypeTag,
429
                                 *cx.name,
430 431 432 433 434
                                 cx.file,
                                 cx.line,
                                 cx.total_size,
                                 cx.align,
                                 0,
435 436
                                 None,
                                 Some(/*bad*/copy cx.members));
437 438
}

439
fn create_structure(file: @Metadata<FileMetadata>, name: @~str, line: int)
440 441 442 443 444 445 446 447 448
                 -> @mut StructCtxt {
    let cx = @mut StructCtxt {
        file: file.node,
        name: name,
        line: line,
        members: ~[],
        total_size: 0,
        align: 64 //XXX different alignment per arch?
    };
B
Brian Anderson 已提交
449
    return cx;
J
Josh Matthews 已提交
450 451
}

452
fn create_derived_type(type_tag: int, file: ValueRef, name: &str, line: int,
453 454
                       size: int, align: int, offset: int, ty: ValueRef)
    -> ValueRef {
455
    let lldata = ~[lltag(type_tag),
456
                  file,
J
Josh Matthews 已提交
457
                  llstr(name),
458
                  file,
J
Josh Matthews 已提交
459
                  lli32(line),
460 461 462
                  lli64(size),
                  lli64(align),
                  lli64(offset),
J
Josh Matthews 已提交
463
                  lli32(0),
464
                  ty];
B
Brian Anderson 已提交
465
    return llmdnode(lldata);
466 467
}

468
fn add_member(cx: @mut StructCtxt,
469
              name: &str,
470 471 472
              line: int,
              size: int,
              align: int,
473
              ty: ValueRef) {
474
    cx.members.push(create_derived_type(MemberTag, cx.file, name, line,
475 476
                                        size * 8, align * 8, cx.total_size,
                                        ty));
J
Josh Matthews 已提交
477 478 479
    cx.total_size += size * 8;
}

480 481
fn create_record(cx: @CrateContext, t: ty::t, fields: ~[ast::ty_field],
                 span: span) -> @Metadata<TyDescMetadata> {
J
Josh Matthews 已提交
482
    let fname = filename_from_span(cx, span);
483
    let file_node = create_file(cx, fname);
J
Josh Matthews 已提交
484
    let scx = create_structure(file_node,
P
Paul Stansifer 已提交
485
                               cx.sess.str_of(
486 487
                                   ((/*bad*/copy cx.dbg_cx).get().names)
                                   (~"rec")),
488
                               line_from_span(cx.sess.codemap,
J
Josh Matthews 已提交
489
                                              span) as int);
B
Brian Anderson 已提交
490
    for fields.each |field| {
491
        let field_t = ty::get_field(cx.tcx, t, field.node.ident).mt.ty;
492
        let ty_md = create_ty(cx, field_t, field.node.mt.ty);
493
        let (size, align) = size_and_align_of(cx, field_t);
494
        add_member(scx, *cx.sess.str_of(field.node.ident),
495
                   line_from_span(cx.sess.codemap, field.span) as int,
J
Josh Matthews 已提交
496 497
                   size as int, align as int, ty_md.node);
    }
498 499 500 501 502 503
    let mdval = @Metadata {
        node: finish_structure(scx),
        data: TyDescMetadata {
            hash: ty::type_id(t)
        }
    };
B
Brian Anderson 已提交
504
    return mdval;
J
Josh Matthews 已提交
505 506
}

507 508 509
fn create_boxed_type(cx: @CrateContext, outer: ty::t, _inner: ty::t,
                     span: span, boxed: @Metadata<TyDescMetadata>)
    -> @Metadata<TyDescMetadata> {
510
    //let tg = StructureTypeTag;
511
    /*let cache = cx.llmetadata;
512
    match cached_metadata::<@Metadata<TyDescMetadata>>(
513
        cache, tg, {|md| ty::hash_ty(outer) == ty::hash_ty(md.data.hash)}) {
B
Brian Anderson 已提交
514 515
      option::Some(md) { return md; }
      option::None {}
516 517
    }*/
    let fname = filename_from_span(cx, span);
518 519
    let file_node = create_file(cx, fname);
    //let cu_node = create_compile_unit_metadata(cx, fname);
520
    let uint_t = ty::mk_uint(cx.tcx);
521
    let refcount_type = create_basic_type(cx, uint_t, span);
522 523
    let scx = create_structure(file_node,
                               @/*bad*/ copy ty_to_str(cx.tcx, outer), 0);
524
    add_member(scx, ~"refcnt", 0, sys::size_of::<uint>() as int,
525
               sys::min_align_of::<uint>() as int, refcount_type.node);
526
    add_member(scx, ~"boxed", 0, 8, //XXX member_size_and_align(??)
J
Josh Matthews 已提交
527
               8, //XXX just a guess
J
Josh Matthews 已提交
528 529
               boxed.node);
    let llnode = finish_structure(scx);
530 531 532 533 534 535
    let mdval = @Metadata {
        node: llnode,
        data: TyDescMetadata {
            hash: ty::type_id(outer)
        }
    };
536
    //update_cache(cache, tg, tydesc_metadata(mdval));
537
    add_named_metadata(cx, ~"llvm.dbg.ty", llnode);
B
Brian Anderson 已提交
538
    return mdval;
539 540
}

541
fn create_composite_type(type_tag: int, name: &str, file: ValueRef,
542
                         line: int, size: int, align: int, offset: int,
B
Brian Anderson 已提交
543
                         derived: Option<ValueRef>,
544
                         +members: Option<~[ValueRef]>)
J
Josh Matthews 已提交
545
    -> ValueRef {
546
    let lldata = ~[lltag(type_tag),
J
Josh Matthews 已提交
547 548 549 550 551 552
                  file,
                  llstr(name), // type name
                  file, // source file definition
                  lli32(line), // source line definition
                  lli64(size), // size of members
                  lli64(align), // align
553
                  lli32/*64*/(offset), // offset
J
Josh Matthews 已提交
554
                  lli32(0), // flags
B
Brian Anderson 已提交
555
                  if derived.is_none() {
556 557
                      llnull()
                  } else { // derived from
B
Brian Anderson 已提交
558
                      derived.get()
559
                  },
B
Brian Anderson 已提交
560
                  if members.is_none() {
561 562
                      llnull()
                  } else { //members
B
Brian Anderson 已提交
563
                      llmdnode(members.get())
564
                  },
J
Josh Matthews 已提交
565 566
                  lli32(0),  // runtime language
                  llnull()
567
                 ];
B
Brian Anderson 已提交
568
    return llmdnode(lldata);
J
Josh Matthews 已提交
569 570
}

571
fn create_vec(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t,
572
              vec_ty_span: codemap::span, elem_ty: @ast::Ty)
573
    -> @Metadata<TyDescMetadata> {
T
Tim Chevalier 已提交
574
    let fname = filename_from_span(cx, vec_ty_span);
575 576
    let file_node = create_file(cx, fname);
    let elem_ty_md = create_ty(cx, elem_t, elem_ty);
577 578
    let scx = create_structure(file_node,
                               @/*bad*/ copy ty_to_str(cx.tcx, vec_t), 0);
579
    let size_t_type = create_basic_type(cx, ty::mk_uint(cx.tcx), vec_ty_span);
580
    add_member(scx, ~"fill", 0, sys::size_of::<libc::size_t>() as int,
581
               sys::min_align_of::<libc::size_t>() as int, size_t_type.node);
582
    add_member(scx, ~"alloc", 0, sys::size_of::<libc::size_t>() as int,
583
               sys::min_align_of::<libc::size_t>() as int, size_t_type.node);
584
    let subrange = llmdnode(~[lltag(SubrangeTag), lli64(0), lli64(0)]);
585
    let (arr_size, arr_align) = size_and_align_of(cx, elem_t);
586
    let data_ptr = create_composite_type(ArrayTypeTag, ~"", file_node.node, 0,
J
Josh Matthews 已提交
587
                                         arr_size, arr_align, 0,
588 589
                                         Some(elem_ty_md.node),
                                         Some(~[subrange]));
590
    add_member(scx, ~"data", 0, 0, // clang says the size should be 0
591
               sys::min_align_of::<u8>() as int, data_ptr);
J
Josh Matthews 已提交
592
    let llnode = finish_structure(scx);
593 594 595 596 597 598
    @Metadata {
        node: llnode,
        data: TyDescMetadata {
            hash: ty::type_id(vec_t)
        }
    }
J
Josh Matthews 已提交
599 600
}

601 602
fn create_ty(_cx: @CrateContext, _t: ty::t, _ty: @ast::Ty)
    -> @Metadata<TyDescMetadata> {
J
Josh Matthews 已提交
603
    /*let cache = get_cache(cx);
604
    match cached_metadata::<@Metadata<TyDescMetadata>>(
J
Josh Matthews 已提交
605
        cache, tg, {|md| t == md.data.hash}) {
B
Brian Anderson 已提交
606 607
      option::Some(md) { return md; }
      option::None {}
J
Josh Matthews 已提交
608 609
    }*/

610
    /* FIXME (#2012): disabled this code as part of the patch that moves
611 612 613 614 615 616 617 618 619 620
     * recognition of named builtin types into resolve. I tried to fix
     * it, but it seems to already be broken -- it's only called when
     * --xg is given, and compiling with --xg fails on trivial programs.
     *
     * Generating an ast::ty from a ty::t seems like it should not be
     * needed. It is only done to track spans, but you will not get the
     * right spans anyway -- types tend to refer to stuff defined
     * elsewhere, not be self-contained.
     */

621
    fail!();
622
    /*
623
    fn t_to_ty(cx: CrateContext, t: ty::t, span: span) -> @ast::ty {
624
        let ty = match ty::get(t).struct {
625 626 627
          ty::ty_nil { ast::ty_nil }
          ty::ty_bot { ast::ty_bot }
          ty::ty_bool { ast::ty_bool }
628 629 630
          ty::ty_int(t) { ast::ty_int(t) }
          ty::ty_float(t) { ast::ty_float(t) }
          ty::ty_uint(t) { ast::ty_uint(t) }
631
          ty::ty_box(mt) { ast::ty_box({ty: t_to_ty(cx, mt.ty, span),
632
                                        mutbl: mt.mutbl}) }
633
          ty::ty_uniq(mt) { ast::ty_uniq({ty: t_to_ty(cx, mt.ty, span),
634
                                          mutbl: mt.mutbl}) }
J
Josh Matthews 已提交
635
          ty::ty_rec(fields) {
636
            let fs = ~[];
J
Josh Matthews 已提交
637
            for field in fields {
638
                fs.push({node: {ident: field.ident,
J
Josh Matthews 已提交
639
                               mt: {ty: t_to_ty(cx, field.mt.ty, span),
640
                                    mutbl: field.mt.mutbl}},
641
                        span: span});
J
Josh Matthews 已提交
642 643 644
            }
            ast::ty_rec(fs)
          }
J
Josh Matthews 已提交
645
          ty::ty_vec(mt) { ast::ty_vec({ty: t_to_ty(cx, mt.ty, span),
646
                                        mutbl: mt.mutbl}) }
T
Tim Chevalier 已提交
647
          _ {
648
            cx.sess.span_bug(span, "t_to_ty: Can't handle this type");
T
Tim Chevalier 已提交
649
          }
650
        };
B
Brian Anderson 已提交
651
        return @{node: ty, span: span};
652
    }
J
Josh Matthews 已提交
653

654
    match ty.node {
655
      ast::ty_box(mt) {
656
        let inner_t = match ty::get(t).struct {
657
          ty::ty_box(boxed) { boxed.ty }
658
          _ { cx.sess.span_bug(ty.span, "t_to_ty was incoherent"); }
659
        };
660 661
        let md = create_ty(cx, inner_t, mt.ty);
        let box = create_boxed_type(cx, t, inner_t, ty.span, md);
B
Brian Anderson 已提交
662
        return create_pointer_type(cx, t, ty.span, box);
663
      }
664

665
      ast::ty_uniq(mt) {
666
        let inner_t = match ty::get(t).struct {
667
          ty::ty_uniq(boxed) { boxed.ty }
T
Tim Chevalier 已提交
668
          // Hoping we'll have a way to eliminate this check soon.
669
          _ { cx.sess.span_bug(ty.span, "t_to_ty was incoherent"); }
670
        };
671
        let md = create_ty(cx, inner_t, mt.ty);
B
Brian Anderson 已提交
672
        return create_pointer_type(cx, t, ty.span, md);
673
      }
674

675
      ast::ty_infer {
676
        let inferred = t_to_ty(cx, t, ty.span);
B
Brian Anderson 已提交
677
        return create_ty(cx, t, inferred);
678
      }
679

J
Josh Matthews 已提交
680
      ast::ty_rec(fields) {
B
Brian Anderson 已提交
681
        return create_record(cx, t, fields, ty.span);
J
Josh Matthews 已提交
682
      }
683

J
Josh Matthews 已提交
684
      ast::ty_vec(mt) {
685
        let inner_t = ty::sequence_element_type(cx.tcx, t);
T
Tim Chevalier 已提交
686 687
        let inner_ast_t = t_to_ty(cx, inner_t, mt.ty.span);
        let v = create_vec(cx, t, inner_t, ty.span, inner_ast_t);
B
Brian Anderson 已提交
688
        return create_pointer_type(cx, t, ty.span, v);
J
Josh Matthews 已提交
689
      }
690

691
      ast::ty_path(_, id) {
692
        match cx.tcx.def_map.get(id) {
693
          ast::def_prim_ty(pty) {
B
Brian Anderson 已提交
694
            return create_basic_type(cx, t, pty, ty.span);
695 696 697 698 699 700
          }
          _ {}
        }
      }

      _ {}
701
    };
702
    */
703 704
}

705
fn filename_from_span(cx: @CrateContext, sp: codemap::span) -> ~str {
706
    /*bad*/copy cx.sess.codemap.lookup_char_pos(sp.lo).file.name
707 708
}

709
fn create_var(type_tag: int, context: ValueRef, name: &str, file: ValueRef,
710
              line: int, ret_ty: ValueRef) -> ValueRef {
711
    let lldata = ~[lltag(type_tag),
712 713 714 715 716 717
                  context,
                  llstr(name),
                  file,
                  lli32(line),
                  ret_ty,
                  lli32(0)
718
                 ];
B
Brian Anderson 已提交
719
    return llmdnode(lldata);
720 721
}

722
pub fn create_local_var(bcx: block, local: @ast::local)
723
    -> @Metadata<LocalVarMetadata> {
724 725 726 727
    unsafe {
        let cx = bcx.ccx();
        let cache = get_cache(cx);
        let tg = AutoVariableTag;
728
        match cached_metadata::<@Metadata<LocalVarMetadata>>(
729 730 731
            cache, tg, |md| md.data.id == local.node.id) {
          option::Some(md) => return md,
          option::None => ()
732 733
        }

734 735 736
        let name = match local.node.pat.node {
          ast::pat_ident(_, pth, _) => ast_util::path_to_ident(pth),
          // FIXME this should be handled (#2533)
737
          _ => fail!(~"no single variable name for local")
738 739 740 741 742 743 744 745 746
        };
        let loc = cx.sess.codemap.lookup_char_pos(local.span.lo);
        let ty = node_id_type(bcx, local.node.id);
        let tymd = create_ty(cx, ty, local.node.ty);
        let filemd = create_file(cx, /*bad*/copy loc.file.name);
        let context = match bcx.parent {
            None => create_function(bcx.fcx).node,
            Some(_) => create_block(bcx).node
        };
747
        let mdnode = create_var(tg, context, *cx.sess.str_of(name),
748
                                filemd.node, loc.line as int, tymd.node);
749 750 751 752 753 754
        let mdval = @Metadata {
            node: mdnode,
            data: LocalVarMetadata {
                id: local.node.id
            }
        };
755 756
        update_cache(cache, AutoVariableTag, local_var_metadata(mdval));

757
        let llptr = match bcx.fcx.lllocals.find(&local.node.id) {
758 759 760 761 762 763
          option::Some(local_mem(v)) => v,
          option::Some(_) => {
            bcx.tcx().sess.span_bug(local.span, ~"local is bound to \
                    something weird");
          }
          option::None => {
764
            match bcx.fcx.lllocals.get(&local.node.pat.id) {
765 766 767 768 769 770 771
              local_imm(v) => v,
              _ => bcx.tcx().sess.span_bug(local.span, ~"local is bound to \
                                                         something weird")
            }
          }
        };
        let declargs = ~[llmdnode(~[llptr]), mdnode];
772
        trans::build::Call(bcx, cx.intrinsics.get(&~"llvm.dbg.declare"),
773 774
                           declargs);
        return mdval;
775
    }
776
}
777

778
pub fn create_arg(bcx: block, arg: ast::arg, sp: span)
779
    -> Option<@Metadata<ArgumentMetadata>> {
780
    unsafe {
781
        let fcx = bcx.fcx, cx = *fcx.ccx;
782 783
        let cache = get_cache(cx);
        let tg = ArgVariableTag;
784
        match cached_metadata::<@Metadata<ArgumentMetadata>>(
785 786 787
            cache, ArgVariableTag, |md| md.data.id == arg.id) {
          option::Some(md) => return Some(md),
          option::None => ()
788
        }
789 790 791 792 793 794 795 796 797 798 799 800

        let loc = cx.sess.codemap.lookup_char_pos(sp.lo);
        let ty = node_id_type(bcx, arg.id);
        let tymd = create_ty(cx, ty, arg.ty);
        let filemd = create_file(cx, /*bad*/copy loc.file.name);
        let context = create_function(bcx.fcx);

        match arg.pat.node {
            ast::pat_ident(_, path, _) => {
                // XXX: This is wrong; it should work for multiple bindings.
                let mdnode = create_var(tg,
                                        context.node,
801
                                        *cx.sess.str_of(path.idents.last()),
802 803 804 805
                                        filemd.node,
                                        loc.line as int,
                                        tymd.node);

806 807 808 809 810 811
                let mdval = @Metadata {
                    node: mdnode,
                    data: ArgumentMetadata {
                        id: arg.id
                    }
                };
812 813
                update_cache(cache, tg, argument_metadata(mdval));

814
                let llptr = match fcx.llargs.get(&arg.id) {
815 816 817 818
                  local_mem(v) | local_imm(v) => v,
                };
                let declargs = ~[llmdnode(~[llptr]), mdnode];
                trans::build::Call(bcx,
819
                                   cx.intrinsics.get(&~"llvm.dbg.declare"),
820 821 822 823 824 825
                                   declargs);
                return Some(mdval);
            }
            _ => {
                return None;
            }
826 827
        }
    }
828 829
}

830
pub fn update_source_pos(cx: block, s: span) {
831
    if !cx.sess().opts.debuginfo {
B
Brian Anderson 已提交
832
        return;
833
    }
834
    let cm = cx.sess().codemap;
835
    let blockmd = create_block(cx);
B
Brian Anderson 已提交
836
    let loc = cm.lookup_char_pos(s.lo);
837 838
    let scopedata = ~[lli32(loc.line.to_int()),
                     lli32(loc.col.to_int()),
839
                     blockmd.node,
840
                     llnull()];
841
    let dbgscope = llmdnode(scopedata);
842 843 844
    unsafe {
        llvm::LLVMSetCurrentDebugLocation(trans::build::B(cx), dbgscope);
    }
845 846
}

847
pub fn create_function(fcx: fn_ctxt) -> @Metadata<SubProgramMetadata> {
848
    let cx = *fcx.ccx;
849
    let dbg_cx = (/*bad*/copy cx.dbg_cx).get();
850

P
Paul Stansifer 已提交
851
    debug!("~~");
852
    log(debug, fcx.id);
853

B
Brian Anderson 已提交
854
    let sp = fcx.span.get();
B
Brian Anderson 已提交
855
    log(debug, cx.sess.codemap.span_to_str(sp));
856

857
    let (ident, ret_ty, id) = match cx.tcx.items.get(&fcx.id) {
B
Brian Anderson 已提交
858
      ast_map::node_item(item, _) => {
859
        match /*bad*/copy item.node {
860
          ast::item_fn(decl, _, _, _) => {
861
            (item.ident, decl.output, item.id)
862
          }
B
Brian Anderson 已提交
863 864
          _ => fcx.ccx.sess.span_bug(item.span, ~"create_function: item \
                                                  bound to non-function")
865 866
        }
      }
B
Brian Anderson 已提交
867
      ast_map::node_method(method, _, _) => {
868
          (method.ident, method.decl.output, method.id)
869
      }
B
Brian Anderson 已提交
870
      ast_map::node_expr(expr) => {
871
        match /*bad*/copy expr.node {
872
          ast::expr_fn(_, decl, _, _) => {
873
            ((dbg_cx.names)(~"fn"), decl.output, expr.id)
874
          }
875
          ast::expr_fn_block(decl, _) => {
876
            ((dbg_cx.names)(~"fn"), decl.output, expr.id)
877
          }
B
Brian Anderson 已提交
878 879 880
          _ => fcx.ccx.sess.span_bug(expr.span,
                                     ~"create_function: \
                                       expected an expr_fn or fn_block here")
881 882
        }
      }
883
      ast_map::node_dtor(_, _, did, _) => {
884
        ((dbg_cx.names)(~"dtor"), ast_util::dtor_ty(), did.node)
885
      }
B
Brian Anderson 已提交
886 887
      _ => fcx.ccx.sess.bug(~"create_function: unexpected \
                              sort of node")
888
    };
889

890 891
    log(debug, ident);
    log(debug, id);
892

893
    let cache = get_cache(cx);
894
    match cached_metadata::<@Metadata<SubProgramMetadata>>(
B
Brian Anderson 已提交
895
        cache, SubprogramTag, |md| md.data.id == id) {
B
Brian Anderson 已提交
896 897
      option::Some(md) => return md,
      option::None => ()
898
    }
899

B
Brian Anderson 已提交
900
    let loc = cx.sess.codemap.lookup_char_pos(sp.lo);
901
    let file_node = create_file(cx, copy loc.file.name).node;
902
    let ty_node = if cx.sess.opts.extra_debuginfo {
903
        match ret_ty.node {
B
Brian Anderson 已提交
904 905
          ast::ty_nil => llnull(),
          _ => create_ty(cx, ty::node_id_to_type(cx.tcx, id), ret_ty).node
906 907 908
        }
    } else {
        llnull()
909
    };
910
    let sub_node = create_composite_type(SubroutineTag, ~"", file_node, 0, 0,
B
Brian Anderson 已提交
911 912
                                         0, 0, option::None,
                                         option::Some(~[ty_node]));
913

914
    let fn_metadata = ~[lltag(SubprogramTag),
915 916
                       llunused(),
                       file_node,
917
                       llstr(*cx.sess.str_of(ident)),
P
Paul Stansifer 已提交
918
                        //XXX fully-qualified C++ name:
919
                       llstr(*cx.sess.str_of(ident)),
920
                       llstr(~""), //XXX MIPS name?????
921 922
                       file_node,
                       lli32(loc.line as int),
923
                       sub_node,
924
                       lli1(false), //XXX static (check export)
925
                       lli1(true), // defined in compilation unit
926 927
                       lli32(DW_VIRTUALITY_none), // virtual-ness
                       lli32(0i), //index into virt func
928 929
                       /*llnull()*/ lli32(0), // base type with vtbl
                       lli32(256), // flags
930
                       lli1(cx.sess.opts.optimize != session::No),
931
                       fcx.llfn
932 933 934
                       //list of template params
                       //func decl descriptor
                       //list of func vars
935
                      ];
936
    let val = llmdnode(fn_metadata);
937
    add_named_metadata(cx, ~"llvm.dbg.sp", val);
938 939 940 941 942 943
    let mdval = @Metadata {
        node: val,
        data: SubProgramMetadata {
            id: id
        }
    };
944
    update_cache(cache, SubprogramTag, subprogram_metadata(mdval));
945

B
Brian Anderson 已提交
946
    return mdval;
J
Josh Matthews 已提交
947
}