“dddd9908d537ce2858f37783779c3b88005ff0a8”上不存在“src/librustc/middle/trans/debuginfo.rs”
debuginfo.rs 29.7 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 31 32 33 34
use std::map::HashMap;
use std::map;
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
fn llstr(s: ~str) -> ValueRef {
B
Brian Anderson 已提交
64
    str::as_c_str(s, |sbuf| {
65 66 67
        unsafe {
            llvm::LLVMMDString(sbuf, str::len(s) as libc::c_uint)
        }
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 80 81
fn lli1(bval: bool) -> ValueRef {
    C_bool(bval)
}
82
fn llmdnode(elems: ~[ValueRef]) -> ValueRef {
83 84 85 86
    unsafe {
        llvm::LLVMMDNode(vec::raw::to_ptr(elems),
                         vec::len(elems) as libc::c_uint)
    }
87 88 89 90
}
fn llunused() -> ValueRef {
    lli32(0x0)
}
91 92 93 94
fn llnull() -> ValueRef {
    unsafe {
        cast::reinterpret_cast(&ptr::null::<ValueRef>())
    }
95
}
96

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

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

107
pub type debug_ctxt = {
J
Josh Matthews 已提交
108
    llmetadata: metadata_cache,
109
    names: namegen,
110
    crate_file: ~str
J
Josh Matthews 已提交
111 112
};

113
pub fn mk_ctxt(+crate: ~str, intr: @ident_interner) -> debug_ctxt {
114
    {llmetadata: map::HashMap(),
P
Paul Stansifer 已提交
115
     names: new_namegen(intr),
116 117 118
     crate_file: crate}
}

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

128 129
type metadata<T> = {node: ValueRef, data: T};

130 131
type file_md = {path: ~str};
type compile_unit_md = {name: ~str};
132
type subprogram_md = {id: ast::node_id};
133 134
type local_var_md = {id: ast::node_id};
type tydesc_md = {hash: uint};
135
type block_md = {start: codemap::Loc, end: codemap::Loc};
136 137
type argument_md = {id: ast::node_id};
type retval_md = {id: ast::node_id};
138

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

P
Patrick Walton 已提交
141
enum debug_metadata {
P
Patrick Walton 已提交
142 143 144 145 146 147 148 149
    file_metadata(@metadata<file_md>),
    compile_unit_metadata(@metadata<compile_unit_md>),
    subprogram_metadata(@metadata<subprogram_md>),
    local_var_metadata(@metadata<local_var_md>),
    tydesc_metadata(@metadata<tydesc_md>),
    block_metadata(@metadata<block_md>),
    argument_metadata(@metadata<argument_md>),
    retval_metadata(@metadata<retval_md>),
150 151
}

152 153 154 155 156
fn cast_safely<T: Copy, U>(val: T) -> U {
    unsafe {
        let val2 = val;
        return cast::transmute(move val2);
    }
157 158
}

159 160 161 162 163 164 165 166 167 168 169 170
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)
        }
171 172 173
    }
}

174
fn cached_metadata<T: Copy>(cache: metadata_cache, mdtag: int,
175 176 177 178 179 180 181 182 183
                           eq: fn(md: T) -> bool) -> Option<T> {
    unsafe {
        if cache.contains_key(mdtag) {
            let items = cache.get(mdtag);
            for items.each |item| {
                let md: T = md_from_metadata::<T>(*item);
                if eq(md) {
                    return option::Some(md);
                }
184 185
            }
        }
186
        return option::None;
187 188 189
    }
}

190 191 192 193 194 195 196 197 198 199
fn create_compile_unit(cx: @crate_ctxt) -> @metadata<compile_unit_md> {
    unsafe {
        let cache = get_cache(cx);
        let crate_name = /*bad*/copy (/*bad*/copy cx.dbg_cx).get().crate_file;
        let tg = CompileUnitTag;
        match cached_metadata::<@metadata<compile_unit_md>>(cache, tg,
                            |md| md.data.name == crate_name) {
          option::Some(md) => return md,
          option::None => ()
        }
200

201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
        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),
                             llstr(copy crate_name),
                             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);
        let mdval = @{node: unit_node, data: {name: crate_name}};
        update_cache(cache, tg, compile_unit_metadata(mdval));

        return mdval;
    }
221 222
}

223
fn get_cache(cx: @crate_ctxt) -> metadata_cache {
224
    (/*bad*/copy cx.dbg_cx).get().llmetadata
J
Josh Matthews 已提交
225 226
}

227
fn get_file_path_and_dir(work_dir: &str, full_path: &str) -> (~str, ~str) {
228 229 230 231
    (if str::starts_with(full_path, work_dir) {
        str::slice(full_path, str::len(work_dir) + 1u,
                   str::len(full_path))
    } else {
232 233
        str::from_slice(full_path)
    }, str::from_slice(work_dir))
234 235
}

236
fn create_file(cx: @crate_ctxt, +full_path: ~str) -> @metadata<file_md> {
J
Josh Matthews 已提交
237 238
    let cache = get_cache(cx);;
    let tg = FileDescriptorTag;
239
    match cached_metadata::<@metadata<file_md>>(
B
Brian Anderson 已提交
240
        cache, tg, |md| md.data.path == full_path) {
B
Brian Anderson 已提交
241 242
        option::Some(md) => return md,
        option::None => ()
243
    }
244

245 246 247
    let (file_path, work_dir) =
        get_file_path_and_dir(cx.sess.working_dir.to_str(),
                              full_path);
248
    let unit_node = create_compile_unit(cx).node;
249
    let file_md = ~[lltag(tg),
250 251
                   llstr(file_path),
                   llstr(work_dir),
252
                   unit_node];
253 254
    let val = llmdnode(file_md);
    let mdval = @{node: val, data: {path: full_path}};
J
Josh Matthews 已提交
255
    update_cache(cache, tg, file_metadata(mdval));
B
Brian Anderson 已提交
256
    return mdval;
257 258
}

259
fn line_from_span(cm: @codemap::CodeMap, sp: span) -> uint {
B
Brian Anderson 已提交
260
    cm.lookup_char_pos(sp.lo).line
J
Josh Matthews 已提交
261 262
}

263
fn create_block(cx: block) -> @metadata<block_md> {
264
    let cache = get_cache(cx.ccx());
265
    let mut cx = cx;
B
Brian Anderson 已提交
266
    while cx.node_info.is_none() {
267
        match cx.parent {
B
Brian Anderson 已提交
268 269
          Some(b) => cx = b,
          None => fail
270 271
        }
    }
B
Brian Anderson 已提交
272
    let sp = cx.node_info.get().span;
273

B
Brian Anderson 已提交
274
    let start = cx.sess().codemap.lookup_char_pos(sp.lo);
275
    let fname = /*bad*/copy start.file.name;
B
Brian Anderson 已提交
276
    let end = cx.sess().codemap.lookup_char_pos(sp.hi);
J
Josh Matthews 已提交
277
    let tg = LexicalBlockTag;
278
    /*match cached_metadata::<@metadata<block_md>>(
J
Josh Matthews 已提交
279
        cache, tg,
280
        {|md| start == md.data.start && end == md.data.end}) {
B
Brian Anderson 已提交
281 282
      option::Some(md) { return md; }
      option::None {}
283
    }*/
284

285
    let parent = match cx.parent {
B
Brian Anderson 已提交
286 287
        None => create_function(cx.fcx).node,
        Some(bcx) => create_block(bcx).node
288
    };
289
    let file_node = create_file(cx.ccx(), fname);
290
    let unique_id = match cache.find(LexicalBlockTag) {
B
Brian Anderson 已提交
291 292
      option::Some(v) => vec::len(v) as int,
      option::None => 0
293
    };
294
    let lldata = ~[lltag(tg),
295
                  parent,
296 297
                  lli32(start.line.to_int()),
                  lli32(start.col.to_int()),
298 299
                  file_node.node,
                  lli32(unique_id)
300
                 ];
301 302 303
    let val = llmdnode(lldata);
    let mdval = @{node: val, data: {start: start, end: end}};
    //update_cache(cache, tg, block_metadata(mdval));
B
Brian Anderson 已提交
304
    return mdval;
305 306
}

307
fn size_and_align_of(cx: @crate_ctxt, t: ty::t) -> (int, int) {
308
    let llty = type_of::type_of(cx, t);
309 310
    (machine::llsize_of_real(cx, llty) as int,
     machine::llalign_of_pref(cx, llty) as int)
311 312
}

313
fn create_basic_type(cx: @crate_ctxt, t: ty::t, span: span)
314
    -> @metadata<tydesc_md> {
J
Josh Matthews 已提交
315
    let cache = get_cache(cx);
316
    let tg = BasicTypeDescriptorTag;
317
    match cached_metadata::<@metadata<tydesc_md>>(
B
Brian Anderson 已提交
318
        cache, tg, |md| ty::type_id(t) == md.data.hash) {
B
Brian Anderson 已提交
319 320
      option::Some(md) => return md,
      option::None => ()
321
    }
322

323
    let (name, encoding) = (~"uint", DW_ATE_unsigned);
324

325
    let fname = filename_from_span(cx, span);
326
    let file_node = create_file(cx, fname);
327
    let cu_node = create_compile_unit(cx);
328
    let (size, align) = size_and_align_of(cx, t);
329
    let lldata = ~[lltag(tg),
330
                  cu_node.node,
331
                  llstr(name),
332
                  file_node.node,
333 334 335
                  lli32(0), //XXX source line
                  lli64(size * 8),  // size in bits
                  lli64(align * 8), // alignment in bits
336
                  lli64(0), //XXX offset?
337
                  lli32(0), //XXX flags?
338
                  lli32(encoding)];
339
    let llnode = llmdnode(lldata);
340
    let mdval = @{node: llnode, data: {hash: ty::type_id(t)}};
341
    update_cache(cache, tg, tydesc_metadata(mdval));
342
    add_named_metadata(cx, ~"llvm.dbg.ty", llnode);
B
Brian Anderson 已提交
343
    return mdval;
344 345
}

346
fn create_pointer_type(cx: @crate_ctxt, t: ty::t, span: span,
347
                       pointee: @metadata<tydesc_md>)
348 349 350
    -> @metadata<tydesc_md> {
    let tg = PointerTypeTag;
    /*let cache = cx.llmetadata;
351
    match cached_metadata::<@metadata<tydesc_md>>(
352
        cache, tg, {|md| ty::hash_ty(t) == ty::hash_ty(md.data.hash)}) {
B
Brian Anderson 已提交
353 354
      option::Some(md) { return md; }
      option::None {}
355
    }*/
356
    let (size, align) = size_and_align_of(cx, t);
357
    let fname = filename_from_span(cx, span);
358 359
    let file_node = create_file(cx, fname);
    //let cu_node = create_compile_unit(cx, fname);
360
    let llnode = create_derived_type(tg, file_node.node, ~"", 0, size * 8,
361
                                     align * 8, 0, pointee.node);
362
    let mdval = @{node: llnode, data: {hash: ty::type_id(t)}};
363
    //update_cache(cache, tg, tydesc_metadata(mdval));
364
    add_named_metadata(cx, ~"llvm.dbg.ty", llnode);
B
Brian Anderson 已提交
365
    return mdval;
366 367
}

J
Josh Matthews 已提交
368 369
type struct_ctxt = {
    file: ValueRef,
370
    name: ~str,
J
Josh Matthews 已提交
371
    line: int,
372
    mut members: ~[ValueRef],
G
Graydon Hoare 已提交
373
    mut total_size: int,
J
Josh Matthews 已提交
374 375 376 377
    align: int
};

fn finish_structure(cx: @struct_ctxt) -> ValueRef {
378 379 380 381 382 383 384 385 386 387 388 389
    return create_composite_type(StructureTypeTag,
                                 /*bad*/copy cx.name,
                                 cx.file,
                                 cx.line,
                                 cx.total_size,
                                 cx.align,
                                 0,
                                 option::None,
                                 option::Some(/*bad*/copy cx.members));
}

fn create_structure(file: @metadata<file_md>, +name: ~str, line: int)
J
Josh Matthews 已提交
390 391 392 393
    -> @struct_ctxt {
    let cx = @{file: file.node,
               name: name,
               line: line,
394
               mut members: ~[],
G
Graydon Hoare 已提交
395
               mut total_size: 0,
J
Josh Matthews 已提交
396
               align: 64 //XXX different alignment per arch?
J
Josh Matthews 已提交
397
              };
B
Brian Anderson 已提交
398
    return cx;
J
Josh Matthews 已提交
399 400
}

401
fn create_derived_type(type_tag: int, file: ValueRef, +name: ~str, line: int,
402 403
                       size: int, align: int, offset: int, ty: ValueRef)
    -> ValueRef {
404
    let lldata = ~[lltag(type_tag),
405
                  file,
J
Josh Matthews 已提交
406
                  llstr(name),
407
                  file,
J
Josh Matthews 已提交
408
                  lli32(line),
409 410 411
                  lli64(size),
                  lli64(align),
                  lli64(offset),
J
Josh Matthews 已提交
412
                  lli32(0),
413
                  ty];
B
Brian Anderson 已提交
414
    return llmdnode(lldata);
415 416
}

417
fn add_member(cx: @struct_ctxt, +name: ~str, line: int, size: int, align: int,
418
              ty: ValueRef) {
419
    cx.members.push(create_derived_type(MemberTag, cx.file, name, line,
J
Josh Matthews 已提交
420
                                       size * 8, align * 8, cx.total_size,
421
                                       ty));
J
Josh Matthews 已提交
422 423 424
    cx.total_size += size * 8;
}

425
fn create_record(cx: @crate_ctxt, t: ty::t, fields: ~[ast::ty_field],
426
                 span: span) -> @metadata<tydesc_md> {
J
Josh Matthews 已提交
427
    let fname = filename_from_span(cx, span);
428
    let file_node = create_file(cx, fname);
J
Josh Matthews 已提交
429
    let scx = create_structure(file_node,
P
Paul Stansifer 已提交
430
                               cx.sess.str_of(
431 432
                                   ((/*bad*/copy cx.dbg_cx).get().names)
                                   (~"rec")),
433
                               line_from_span(cx.sess.codemap,
J
Josh Matthews 已提交
434
                                              span) as int);
B
Brian Anderson 已提交
435
    for fields.each |field| {
436
        let field_t = ty::get_field(cx.tcx, t, field.node.ident).mt.ty;
437
        let ty_md = create_ty(cx, field_t, field.node.mt.ty);
438
        let (size, align) = size_and_align_of(cx, field_t);
P
Paul Stansifer 已提交
439
        add_member(scx, cx.sess.str_of(field.node.ident),
440
                   line_from_span(cx.sess.codemap, field.span) as int,
J
Josh Matthews 已提交
441 442
                   size as int, align as int, ty_md.node);
    }
443
    let mdval = @{node: finish_structure(scx), data:{hash: ty::type_id(t)}};
B
Brian Anderson 已提交
444
    return mdval;
J
Josh Matthews 已提交
445 446
}

447
fn create_boxed_type(cx: @crate_ctxt, outer: ty::t, _inner: ty::t,
448
                     span: span, boxed: @metadata<tydesc_md>)
449
    -> @metadata<tydesc_md> {
450
    //let tg = StructureTypeTag;
451
    /*let cache = cx.llmetadata;
452
    match cached_metadata::<@metadata<tydesc_md>>(
453
        cache, tg, {|md| ty::hash_ty(outer) == ty::hash_ty(md.data.hash)}) {
B
Brian Anderson 已提交
454 455
      option::Some(md) { return md; }
      option::None {}
456 457
    }*/
    let fname = filename_from_span(cx, span);
458 459
    let file_node = create_file(cx, fname);
    //let cu_node = create_compile_unit_metadata(cx, fname);
460
    let uint_t = ty::mk_uint(cx.tcx);
461
    let refcount_type = create_basic_type(cx, uint_t, span);
462
    let scx = create_structure(file_node, ty_to_str(cx.tcx, outer), 0);
463
    add_member(scx, ~"refcnt", 0, sys::size_of::<uint>() as int,
464
               sys::min_align_of::<uint>() as int, refcount_type.node);
465
    add_member(scx, ~"boxed", 0, 8, //XXX member_size_and_align(??)
J
Josh Matthews 已提交
466
               8, //XXX just a guess
J
Josh Matthews 已提交
467 468
               boxed.node);
    let llnode = finish_structure(scx);
469
    let mdval = @{node: llnode, data: {hash: ty::type_id(outer)}};
470
    //update_cache(cache, tg, tydesc_metadata(mdval));
471
    add_named_metadata(cx, ~"llvm.dbg.ty", llnode);
B
Brian Anderson 已提交
472
    return mdval;
473 474
}

475 476
fn create_composite_type(type_tag: int, +name: ~str, file: ValueRef,
                         line: int, size: int, align: int, offset: int,
B
Brian Anderson 已提交
477
                         derived: Option<ValueRef>,
478
                         +members: Option<~[ValueRef]>)
J
Josh Matthews 已提交
479
    -> ValueRef {
480
    let lldata = ~[lltag(type_tag),
J
Josh Matthews 已提交
481 482 483 484 485 486
                  file,
                  llstr(name), // type name
                  file, // source file definition
                  lli32(line), // source line definition
                  lli64(size), // size of members
                  lli64(align), // align
487
                  lli32/*64*/(offset), // offset
J
Josh Matthews 已提交
488
                  lli32(0), // flags
B
Brian Anderson 已提交
489
                  if derived.is_none() {
490 491
                      llnull()
                  } else { // derived from
B
Brian Anderson 已提交
492
                      derived.get()
493
                  },
B
Brian Anderson 已提交
494
                  if members.is_none() {
495 496
                      llnull()
                  } else { //members
B
Brian Anderson 已提交
497
                      llmdnode(members.get())
498
                  },
J
Josh Matthews 已提交
499 500
                  lli32(0),  // runtime language
                  llnull()
501
                 ];
B
Brian Anderson 已提交
502
    return llmdnode(lldata);
J
Josh Matthews 已提交
503 504
}

505
fn create_vec(cx: @crate_ctxt, vec_t: ty::t, elem_t: ty::t,
506
              vec_ty_span: codemap::span, elem_ty: @ast::Ty)
J
Josh Matthews 已提交
507
    -> @metadata<tydesc_md> {
T
Tim Chevalier 已提交
508
    let fname = filename_from_span(cx, vec_ty_span);
509 510
    let file_node = create_file(cx, fname);
    let elem_ty_md = create_ty(cx, elem_t, elem_ty);
511
    let scx = create_structure(file_node, ty_to_str(cx.tcx, vec_t), 0);
512
    let size_t_type = create_basic_type(cx, ty::mk_uint(cx.tcx), vec_ty_span);
513
    add_member(scx, ~"fill", 0, sys::size_of::<libc::size_t>() as int,
514
               sys::min_align_of::<libc::size_t>() as int, size_t_type.node);
515
    add_member(scx, ~"alloc", 0, sys::size_of::<libc::size_t>() as int,
516
               sys::min_align_of::<libc::size_t>() as int, size_t_type.node);
517
    let subrange = llmdnode(~[lltag(SubrangeTag), lli64(0), lli64(0)]);
518
    let (arr_size, arr_align) = size_and_align_of(cx, elem_t);
519
    let data_ptr = create_composite_type(ArrayTypeTag, ~"", file_node.node, 0,
J
Josh Matthews 已提交
520
                                         arr_size, arr_align, 0,
B
Brian Anderson 已提交
521 522
                                         option::Some(elem_ty_md.node),
                                         option::Some(~[subrange]));
523
    add_member(scx, ~"data", 0, 0, // clang says the size should be 0
524
               sys::min_align_of::<u8>() as int, data_ptr);
J
Josh Matthews 已提交
525
    let llnode = finish_structure(scx);
B
Brian Anderson 已提交
526
    return @{node: llnode, data: {hash: ty::type_id(vec_t)}};
J
Josh Matthews 已提交
527 528
}

529
fn create_ty(_cx: @crate_ctxt, _t: ty::t, _ty: @ast::Ty)
J
Josh Matthews 已提交
530
    -> @metadata<tydesc_md> {
J
Josh Matthews 已提交
531
    /*let cache = get_cache(cx);
532
    match cached_metadata::<@metadata<tydesc_md>>(
J
Josh Matthews 已提交
533
        cache, tg, {|md| t == md.data.hash}) {
B
Brian Anderson 已提交
534 535
      option::Some(md) { return md; }
      option::None {}
J
Josh Matthews 已提交
536 537
    }*/

538
    /* FIXME (#2012): disabled this code as part of the patch that moves
539 540 541 542 543 544 545 546 547 548 549 550
     * 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.
     */

    fail;
    /*
551
    fn t_to_ty(cx: crate_ctxt, t: ty::t, span: span) -> @ast::ty {
552
        let ty = match ty::get(t).struct {
553 554 555
          ty::ty_nil { ast::ty_nil }
          ty::ty_bot { ast::ty_bot }
          ty::ty_bool { ast::ty_bool }
556 557 558
          ty::ty_int(t) { ast::ty_int(t) }
          ty::ty_float(t) { ast::ty_float(t) }
          ty::ty_uint(t) { ast::ty_uint(t) }
559
          ty::ty_box(mt) { ast::ty_box({ty: t_to_ty(cx, mt.ty, span),
560
                                        mutbl: mt.mutbl}) }
561
          ty::ty_uniq(mt) { ast::ty_uniq({ty: t_to_ty(cx, mt.ty, span),
562
                                          mutbl: mt.mutbl}) }
J
Josh Matthews 已提交
563
          ty::ty_rec(fields) {
564
            let fs = ~[];
J
Josh Matthews 已提交
565
            for field in fields {
566
                fs.push({node: {ident: field.ident,
J
Josh Matthews 已提交
567
                               mt: {ty: t_to_ty(cx, field.mt.ty, span),
568
                                    mutbl: field.mt.mutbl}},
569
                        span: span});
J
Josh Matthews 已提交
570 571 572
            }
            ast::ty_rec(fs)
          }
J
Josh Matthews 已提交
573
          ty::ty_vec(mt) { ast::ty_vec({ty: t_to_ty(cx, mt.ty, span),
574
                                        mutbl: mt.mutbl}) }
T
Tim Chevalier 已提交
575
          _ {
576
            cx.sess.span_bug(span, "t_to_ty: Can't handle this type");
T
Tim Chevalier 已提交
577
          }
578
        };
B
Brian Anderson 已提交
579
        return @{node: ty, span: span};
580
    }
J
Josh Matthews 已提交
581

582
    match ty.node {
583
      ast::ty_box(mt) {
584
        let inner_t = match ty::get(t).struct {
585
          ty::ty_box(boxed) { boxed.ty }
586
          _ { cx.sess.span_bug(ty.span, "t_to_ty was incoherent"); }
587
        };
588 589
        let md = create_ty(cx, inner_t, mt.ty);
        let box = create_boxed_type(cx, t, inner_t, ty.span, md);
B
Brian Anderson 已提交
590
        return create_pointer_type(cx, t, ty.span, box);
591
      }
592

593
      ast::ty_uniq(mt) {
594
        let inner_t = match ty::get(t).struct {
595
          ty::ty_uniq(boxed) { boxed.ty }
T
Tim Chevalier 已提交
596
          // Hoping we'll have a way to eliminate this check soon.
597
          _ { cx.sess.span_bug(ty.span, "t_to_ty was incoherent"); }
598
        };
599
        let md = create_ty(cx, inner_t, mt.ty);
B
Brian Anderson 已提交
600
        return create_pointer_type(cx, t, ty.span, md);
601
      }
602

603
      ast::ty_infer {
604
        let inferred = t_to_ty(cx, t, ty.span);
B
Brian Anderson 已提交
605
        return create_ty(cx, t, inferred);
606
      }
607

J
Josh Matthews 已提交
608
      ast::ty_rec(fields) {
B
Brian Anderson 已提交
609
        return create_record(cx, t, fields, ty.span);
J
Josh Matthews 已提交
610
      }
611

J
Josh Matthews 已提交
612
      ast::ty_vec(mt) {
613
        let inner_t = ty::sequence_element_type(cx.tcx, t);
T
Tim Chevalier 已提交
614 615
        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 已提交
616
        return create_pointer_type(cx, t, ty.span, v);
J
Josh Matthews 已提交
617
      }
618

619
      ast::ty_path(_, id) {
620
        match cx.tcx.def_map.get(id) {
621
          ast::def_prim_ty(pty) {
B
Brian Anderson 已提交
622
            return create_basic_type(cx, t, pty, ty.span);
623 624 625 626 627 628
          }
          _ {}
        }
      }

      _ {}
629
    };
630
    */
631 632
}

633
fn filename_from_span(cx: @crate_ctxt, sp: codemap::span) -> ~str {
634
    /*bad*/copy cx.sess.codemap.lookup_char_pos(sp.lo).file.name
635 636
}

637
fn create_var(type_tag: int, context: ValueRef, +name: ~str, file: ValueRef,
638
              line: int, ret_ty: ValueRef) -> ValueRef {
639
    let lldata = ~[lltag(type_tag),
640 641 642 643 644 645
                  context,
                  llstr(name),
                  file,
                  lli32(line),
                  ret_ty,
                  lli32(0)
646
                 ];
B
Brian Anderson 已提交
647
    return llmdnode(lldata);
648 649
}

650
pub fn create_local_var(bcx: block, local: @ast::local)
651 652 653 654 655 656 657 658 659
    -> @metadata<local_var_md> {
    unsafe {
        let cx = bcx.ccx();
        let cache = get_cache(cx);
        let tg = AutoVariableTag;
        match cached_metadata::<@metadata<local_var_md>>(
            cache, tg, |md| md.data.id == local.node.id) {
          option::Some(md) => return md,
          option::None => ()
660 661
        }

662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697
        let name = match local.node.pat.node {
          ast::pat_ident(_, pth, _) => ast_util::path_to_ident(pth),
          // FIXME this should be handled (#2533)
          _ => fail ~"no single variable name for local"
        };
        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
        };
        let mdnode = create_var(tg, context, cx.sess.str_of(name),
                                filemd.node, loc.line as int, tymd.node);
        let mdval = @{node: mdnode, data: {id: local.node.id}};
        update_cache(cache, AutoVariableTag, local_var_metadata(mdval));

        let llptr = match bcx.fcx.lllocals.find(local.node.id) {
          option::Some(local_mem(v)) => v,
          option::Some(_) => {
            bcx.tcx().sess.span_bug(local.span, ~"local is bound to \
                    something weird");
          }
          option::None => {
            match bcx.fcx.lllocals.get(local.node.pat.id) {
              local_imm(v) => v,
              _ => bcx.tcx().sess.span_bug(local.span, ~"local is bound to \
                                                         something weird")
            }
          }
        };
        let declargs = ~[llmdnode(~[llptr]), mdnode];
        trans::build::Call(bcx, cx.intrinsics.get(~"llvm.dbg.declare"),
                           declargs);
        return mdval;
698
    }
699
}
700

701
pub fn create_arg(bcx: block, arg: ast::arg, sp: span)
702 703 704 705 706 707 708 709 710
    -> Option<@metadata<argument_md>> {
    unsafe {
        let fcx = bcx.fcx, cx = fcx.ccx;
        let cache = get_cache(cx);
        let tg = ArgVariableTag;
        match cached_metadata::<@metadata<argument_md>>(
            cache, ArgVariableTag, |md| md.data.id == arg.id) {
          option::Some(md) => return Some(md),
          option::None => ()
711
        }
712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743

        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,
                                        cx.sess.str_of(path.idents.last()),
                                        filemd.node,
                                        loc.line as int,
                                        tymd.node);

                let mdval = @{node: mdnode, data: {id: arg.id}};
                update_cache(cache, tg, argument_metadata(mdval));

                let llptr = match fcx.llargs.get(arg.id) {
                  local_mem(v) | local_imm(v) => v,
                };
                let declargs = ~[llmdnode(~[llptr]), mdnode];
                trans::build::Call(bcx,
                                   cx.intrinsics.get(~"llvm.dbg.declare"),
                                   declargs);
                return Some(mdval);
            }
            _ => {
                return None;
            }
744 745
        }
    }
746 747
}

748
pub fn update_source_pos(cx: block, s: span) {
749
    if !cx.sess().opts.debuginfo {
B
Brian Anderson 已提交
750
        return;
751
    }
752
    let cm = cx.sess().codemap;
753
    let blockmd = create_block(cx);
B
Brian Anderson 已提交
754
    let loc = cm.lookup_char_pos(s.lo);
755 756
    let scopedata = ~[lli32(loc.line.to_int()),
                     lli32(loc.col.to_int()),
757
                     blockmd.node,
758
                     llnull()];
759
    let dbgscope = llmdnode(scopedata);
760 761 762
    unsafe {
        llvm::LLVMSetCurrentDebugLocation(trans::build::B(cx), dbgscope);
    }
763 764
}

765
pub fn create_function(fcx: fn_ctxt) -> @metadata<subprogram_md> {
766
    let cx = fcx.ccx;
767
    let dbg_cx = (/*bad*/copy cx.dbg_cx).get();
768

P
Paul Stansifer 已提交
769
    debug!("~~");
770
    log(debug, fcx.id);
771

B
Brian Anderson 已提交
772
    let sp = fcx.span.get();
B
Brian Anderson 已提交
773
    log(debug, cx.sess.codemap.span_to_str(sp));
774

775
    let (ident, ret_ty, id) = match cx.tcx.items.get(fcx.id) {
B
Brian Anderson 已提交
776
      ast_map::node_item(item, _) => {
777
        match /*bad*/copy item.node {
778
          ast::item_fn(decl, _, _, _) => {
779
            (item.ident, decl.output, item.id)
780
          }
B
Brian Anderson 已提交
781 782
          _ => fcx.ccx.sess.span_bug(item.span, ~"create_function: item \
                                                  bound to non-function")
783 784
        }
      }
B
Brian Anderson 已提交
785
      ast_map::node_method(method, _, _) => {
786
          (method.ident, method.decl.output, method.id)
787
      }
B
Brian Anderson 已提交
788
      ast_map::node_expr(expr) => {
789
        match /*bad*/copy expr.node {
B
Brian Anderson 已提交
790
          ast::expr_fn(_, decl, _, _) => {
791
            ((dbg_cx.names)(~"fn"), decl.output, expr.id)
792
          }
B
Brian Anderson 已提交
793
          ast::expr_fn_block(decl, _, _) => {
794
            ((dbg_cx.names)(~"fn"), decl.output, expr.id)
795
          }
B
Brian Anderson 已提交
796 797 798
          _ => fcx.ccx.sess.span_bug(expr.span,
                                     ~"create_function: \
                                       expected an expr_fn or fn_block here")
799 800
        }
      }
801
      ast_map::node_dtor(_, _, did, _) => {
802
        ((dbg_cx.names)(~"dtor"), ast_util::dtor_ty(), did.node)
803
      }
B
Brian Anderson 已提交
804 805
      _ => fcx.ccx.sess.bug(~"create_function: unexpected \
                              sort of node")
806
    };
807

808 809
    log(debug, ident);
    log(debug, id);
810

811
    let cache = get_cache(cx);
812
    match cached_metadata::<@metadata<subprogram_md>>(
B
Brian Anderson 已提交
813
        cache, SubprogramTag, |md| md.data.id == id) {
B
Brian Anderson 已提交
814 815
      option::Some(md) => return md,
      option::None => ()
816
    }
817

B
Brian Anderson 已提交
818
    let loc = cx.sess.codemap.lookup_char_pos(sp.lo);
819
    let file_node = create_file(cx, loc.file.name).node;
820
    let ty_node = if cx.sess.opts.extra_debuginfo {
821
        match ret_ty.node {
B
Brian Anderson 已提交
822 823
          ast::ty_nil => llnull(),
          _ => create_ty(cx, ty::node_id_to_type(cx.tcx, id), ret_ty).node
824 825 826
        }
    } else {
        llnull()
827
    };
828
    let sub_node = create_composite_type(SubroutineTag, ~"", file_node, 0, 0,
B
Brian Anderson 已提交
829 830
                                         0, 0, option::None,
                                         option::Some(~[ty_node]));
831

832
    let fn_metadata = ~[lltag(SubprogramTag),
833 834
                       llunused(),
                       file_node,
P
Paul Stansifer 已提交
835 836 837
                       llstr(cx.sess.str_of(ident)),
                        //XXX fully-qualified C++ name:
                       llstr(cx.sess.str_of(ident)),
838
                       llstr(~""), //XXX MIPS name?????
839 840
                       file_node,
                       lli32(loc.line as int),
841
                       sub_node,
842
                       lli1(false), //XXX static (check export)
843
                       lli1(true), // defined in compilation unit
844 845
                       lli32(DW_VIRTUALITY_none), // virtual-ness
                       lli32(0i), //index into virt func
846 847
                       /*llnull()*/ lli32(0), // base type with vtbl
                       lli32(256), // flags
848
                       lli1(cx.sess.opts.optimize != session::No),
849
                       fcx.llfn
850 851 852
                       //list of template params
                       //func decl descriptor
                       //list of func vars
853
                      ];
854
    let val = llmdnode(fn_metadata);
855
    add_named_metadata(cx, ~"llvm.dbg.sp", val);
856
    let mdval = @{node: val, data: {id: id}};
857
    update_cache(cache, SubprogramTag, subprogram_metadata(mdval));
858

B
Brian Anderson 已提交
859
    return mdval;
J
Josh Matthews 已提交
860
}