2013-06-14 11:59:49 -07:00
|
|
|
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
2012-12-03 16:48:01 -08:00
|
|
|
// 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.
|
|
|
|
|
2013-05-17 15:28:44 -07:00
|
|
|
use core::prelude::*;
|
2013-01-07 14:16:52 -08:00
|
|
|
|
2012-12-13 13:05:22 -08:00
|
|
|
use driver::session;
|
|
|
|
use lib::llvm::llvm;
|
2013-06-14 11:38:29 -07:00
|
|
|
use lib::llvm::{ValueRef, ModuleRef, ContextRef};
|
|
|
|
use lib::llvm::debuginfo::*;
|
2012-12-13 13:05:22 -08:00
|
|
|
use middle::trans::common::*;
|
2013-01-30 11:46:19 -08:00
|
|
|
use middle::trans::machine;
|
2012-12-23 17:41:37 -05:00
|
|
|
use middle::trans::type_of;
|
|
|
|
use middle::trans;
|
2012-09-04 11:54:36 -07:00
|
|
|
use middle::ty;
|
|
|
|
use util::ppaux::ty_to_str;
|
2012-12-13 13:05:22 -08:00
|
|
|
|
2013-04-03 09:28:36 -04:00
|
|
|
use core::hashmap::HashMap;
|
2012-12-23 17:41:37 -05:00
|
|
|
use core::libc;
|
2013-06-14 11:38:29 -07:00
|
|
|
use core::libc::c_uint;
|
2013-06-14 12:23:42 -07:00
|
|
|
use core::cmp;
|
2013-06-11 00:57:25 -07:00
|
|
|
use core::ptr;
|
2013-06-14 11:38:29 -07:00
|
|
|
use core::str::as_c_str;
|
2013-06-11 00:57:25 -07:00
|
|
|
use core::sys;
|
|
|
|
use core::vec;
|
2013-03-26 16:38:07 -04:00
|
|
|
use syntax::codemap::span;
|
2012-12-13 13:05:22 -08:00
|
|
|
use syntax::{ast, codemap, ast_util, ast_map};
|
2011-11-10 00:55:09 -05:00
|
|
|
|
2013-06-14 11:59:49 -07:00
|
|
|
static DW_LANG_RUST: int = 0x9000;
|
2011-11-10 00:55:09 -05:00
|
|
|
|
2013-03-22 14:00:15 -07:00
|
|
|
static CompileUnitTag: int = 17;
|
|
|
|
static FileDescriptorTag: int = 41;
|
|
|
|
static SubprogramTag: int = 46;
|
|
|
|
static SubroutineTag: int = 21;
|
|
|
|
static BasicTypeDescriptorTag: int = 36;
|
|
|
|
static AutoVariableTag: int = 256;
|
|
|
|
static ArgVariableTag: int = 257;
|
|
|
|
static ReturnVariableTag: int = 258;
|
|
|
|
static LexicalBlockTag: int = 11;
|
|
|
|
static PointerTypeTag: int = 15;
|
|
|
|
static StructureTypeTag: int = 19;
|
|
|
|
static MemberTag: int = 13;
|
|
|
|
static ArrayTypeTag: int = 1;
|
|
|
|
static SubrangeTag: int = 33;
|
2011-11-15 21:11:22 -05:00
|
|
|
|
2013-03-22 14:00:15 -07:00
|
|
|
static DW_ATE_boolean: int = 0x02;
|
|
|
|
static DW_ATE_float: int = 0x04;
|
|
|
|
static DW_ATE_signed: int = 0x05;
|
|
|
|
static DW_ATE_signed_char: int = 0x06;
|
|
|
|
static DW_ATE_unsigned: int = 0x07;
|
|
|
|
static DW_ATE_unsigned_char: int = 0x08;
|
2011-11-10 00:55:09 -05:00
|
|
|
|
|
|
|
////////////////
|
|
|
|
|
2013-06-11 00:57:25 -07:00
|
|
|
pub type DebugContext = @mut _DebugContext;
|
|
|
|
|
|
|
|
struct _DebugContext {
|
2012-03-21 18:56:20 -04:00
|
|
|
names: namegen,
|
2013-06-14 11:38:29 -07:00
|
|
|
crate_file: ~str,
|
2013-06-14 11:59:49 -07:00
|
|
|
llcontext: ContextRef,
|
2013-06-14 11:38:29 -07:00
|
|
|
builder: DIBuilderRef,
|
2013-06-10 16:28:10 -07:00
|
|
|
curr_loc: (uint, uint),
|
2013-06-11 00:57:25 -07:00
|
|
|
created_files: HashMap<~str, DIFile>,
|
|
|
|
created_functions: HashMap<ast::node_id, DISubprogram>,
|
|
|
|
created_blocks: HashMap<ast::node_id, DILexicalBlock>,
|
|
|
|
created_types: HashMap<uint, DIType>
|
2013-06-14 11:38:29 -07:00
|
|
|
}
|
|
|
|
|
2013-06-14 11:59:49 -07:00
|
|
|
/// Create new DebugContext
|
2013-06-10 18:34:51 -07:00
|
|
|
pub fn mk_ctxt(llmod: ModuleRef, crate: ~str) -> DebugContext {
|
2013-06-14 11:38:29 -07:00
|
|
|
debug!("mk_ctxt");
|
2013-06-11 00:57:25 -07:00
|
|
|
let builder = unsafe { llvm::LLVMDIBuilderCreate(llmod) };
|
2013-06-14 11:59:49 -07:00
|
|
|
// DIBuilder inherits context from the module, so we'd better use the same one
|
|
|
|
let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
|
2013-06-11 00:57:25 -07:00
|
|
|
let dcx = @mut _DebugContext {
|
2013-06-10 18:34:51 -07:00
|
|
|
names: new_namegen(),
|
2013-06-14 11:38:29 -07:00
|
|
|
crate_file: crate,
|
2013-06-14 11:59:49 -07:00
|
|
|
llcontext: llcontext,
|
2013-06-14 11:38:29 -07:00
|
|
|
builder: builder,
|
2013-06-10 16:28:10 -07:00
|
|
|
curr_loc: (0, 0),
|
2013-06-11 00:57:25 -07:00
|
|
|
created_files: HashMap::new(),
|
|
|
|
created_functions: HashMap::new(),
|
|
|
|
created_blocks: HashMap::new(),
|
|
|
|
created_types: HashMap::new(),
|
|
|
|
};
|
|
|
|
return dcx;
|
2011-12-14 15:14:06 -05:00
|
|
|
}
|
2011-12-09 11:32:23 -05:00
|
|
|
|
2013-06-14 11:38:29 -07:00
|
|
|
#[inline(always)]
|
2013-06-14 11:59:49 -07:00
|
|
|
fn dbg_cx(cx: &CrateContext) -> DebugContext {
|
2013-06-11 00:57:25 -07:00
|
|
|
return cx.dbg_cx.get();
|
2013-02-19 02:40:42 -05:00
|
|
|
}
|
2011-11-10 00:55:09 -05:00
|
|
|
|
2013-06-14 11:59:49 -07:00
|
|
|
/// Create any deferred debug metadata nodes
|
2013-06-14 11:38:29 -07:00
|
|
|
pub fn finalize(cx: @CrateContext) {
|
|
|
|
debug!("finalize");
|
|
|
|
create_compile_unit(cx);
|
2013-06-11 00:57:25 -07:00
|
|
|
let dcx = dbg_cx(cx);
|
2013-06-11 12:41:09 -07:00
|
|
|
unsafe {
|
2013-06-11 00:57:25 -07:00
|
|
|
llvm::LLVMDIBuilderFinalize(dcx.builder);
|
|
|
|
llvm::LLVMDIBuilderDispose(dcx.builder);
|
2013-06-14 11:38:29 -07:00
|
|
|
};
|
2011-11-10 00:55:09 -05:00
|
|
|
}
|
|
|
|
|
2013-06-14 11:59:49 -07:00
|
|
|
fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
|
|
|
|
return unsafe {
|
|
|
|
llvm::LLVMDIBuilderGetOrCreateArray(builder, vec::raw::to_ptr(arr), arr.len() as u32)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2013-06-14 11:38:29 -07:00
|
|
|
fn create_compile_unit(cx: @CrateContext) {
|
2013-06-11 00:57:25 -07:00
|
|
|
let crate_name: &str = dbg_cx(cx).crate_file;
|
2013-06-10 18:34:51 -07:00
|
|
|
let work_dir = cx.sess.working_dir.to_str();
|
2013-06-14 11:38:29 -07:00
|
|
|
let producer = fmt!("rustc version %s", env!("CFG_VERSION"));
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-14 11:38:29 -07:00
|
|
|
do as_c_str(crate_name) |crate_name| {
|
|
|
|
do as_c_str(work_dir) |work_dir| {
|
|
|
|
do as_c_str(producer) |producer| {
|
|
|
|
do as_c_str("") |flags| {
|
|
|
|
do as_c_str("") |split_name| { unsafe {
|
2013-06-11 00:57:25 -07:00
|
|
|
llvm::LLVMDIBuilderCreateCompileUnit(dbg_cx(cx).builder,
|
2013-06-11 12:41:09 -07:00
|
|
|
DW_LANG_RUST as c_uint, crate_name, work_dir, producer,
|
2013-06-14 11:38:29 -07:00
|
|
|
cx.sess.opts.optimize != session::No,
|
|
|
|
flags, 0, split_name);
|
|
|
|
}}}}}};
|
|
|
|
}
|
|
|
|
|
|
|
|
fn create_file(cx: @CrateContext, full_path: &str) -> DIFile {
|
2013-06-11 00:57:25 -07:00
|
|
|
let dcx = dbg_cx(cx);
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-10 18:34:51 -07:00
|
|
|
match dcx.created_files.find_equiv(&full_path) {
|
2013-06-14 11:38:29 -07:00
|
|
|
Some(file_md) => return *file_md,
|
|
|
|
None => ()
|
2011-11-10 00:55:09 -05:00
|
|
|
}
|
2011-12-14 15:14:06 -05:00
|
|
|
|
2013-06-14 11:38:29 -07:00
|
|
|
debug!("create_file: %s", full_path);
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-10 18:34:51 -07:00
|
|
|
let work_dir = cx.sess.working_dir.to_str();
|
2013-06-11 12:41:09 -07:00
|
|
|
let file_name =
|
2013-06-10 18:34:51 -07:00
|
|
|
if full_path.starts_with(work_dir) {
|
|
|
|
full_path.slice(work_dir.len() + 1u, full_path.len())
|
|
|
|
} else {
|
|
|
|
full_path
|
|
|
|
};
|
2013-06-11 12:41:09 -07:00
|
|
|
|
|
|
|
let file_md =
|
2013-06-10 18:34:51 -07:00
|
|
|
do as_c_str(file_name) |file_name| {
|
2013-06-14 11:38:29 -07:00
|
|
|
do as_c_str(work_dir) |work_dir| { unsafe {
|
2013-06-10 18:34:51 -07:00
|
|
|
llvm::LLVMDIBuilderCreateFile(dcx.builder, file_name, work_dir)
|
2013-06-14 11:38:29 -07:00
|
|
|
}}};
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-11 00:57:25 -07:00
|
|
|
dcx.created_files.insert(full_path.to_owned(), file_md);
|
2013-06-14 11:38:29 -07:00
|
|
|
return file_md;
|
2011-11-10 00:55:09 -05:00
|
|
|
}
|
|
|
|
|
2013-06-14 11:59:49 -07:00
|
|
|
/// Return codemap::Loc corresponding to the beginning of the span
|
2013-06-10 18:34:51 -07:00
|
|
|
fn span_start(cx: @CrateContext, span: span) -> codemap::Loc {
|
|
|
|
return cx.sess.codemap.lookup_char_pos(span.lo);
|
2011-12-09 11:32:23 -05:00
|
|
|
}
|
|
|
|
|
2013-06-14 11:38:29 -07:00
|
|
|
fn create_block(bcx: block) -> DILexicalBlock {
|
|
|
|
let mut bcx = bcx;
|
2013-06-11 00:57:25 -07:00
|
|
|
let cx = bcx.ccx();
|
2013-06-11 12:41:09 -07:00
|
|
|
let dcx = dbg_cx(cx);
|
|
|
|
|
2013-06-14 11:38:29 -07:00
|
|
|
while bcx.node_info.is_none() {
|
|
|
|
match bcx.parent {
|
|
|
|
Some(b) => bcx = b,
|
2013-02-11 19:26:38 -08:00
|
|
|
None => fail!()
|
2012-01-28 20:49:21 +01:00
|
|
|
}
|
|
|
|
}
|
2013-06-10 18:34:51 -07:00
|
|
|
let span = bcx.node_info.get().span;
|
2013-06-14 11:38:29 -07:00
|
|
|
let id = bcx.node_info.get().id;
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-11 00:57:25 -07:00
|
|
|
match dcx.created_blocks.find(&id) {
|
2013-06-14 11:38:29 -07:00
|
|
|
Some(block) => return *block,
|
|
|
|
None => ()
|
|
|
|
}
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-10 18:34:51 -07:00
|
|
|
debug!("create_block: %s", bcx.sess().codemap.span_to_str(span));
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-14 11:38:29 -07:00
|
|
|
let parent = match bcx.parent {
|
|
|
|
None => create_function(bcx.fcx),
|
|
|
|
Some(b) => create_block(b)
|
2012-01-28 20:49:21 +01:00
|
|
|
};
|
2013-06-10 18:34:51 -07:00
|
|
|
let cx = bcx.ccx();
|
|
|
|
let loc = span_start(cx, span);
|
|
|
|
let file_md = create_file(cx, loc.file.name);
|
2013-06-11 12:41:09 -07:00
|
|
|
|
|
|
|
let block_md = unsafe {
|
2013-06-14 11:38:29 -07:00
|
|
|
llvm::LLVMDIBuilderCreateLexicalBlock(
|
2013-06-11 12:41:09 -07:00
|
|
|
dcx.builder,
|
|
|
|
parent, file_md,
|
|
|
|
loc.line as c_uint, loc.col.to_uint() as c_uint)
|
2013-02-19 02:40:42 -05:00
|
|
|
};
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-11 00:57:25 -07:00
|
|
|
dcx.created_blocks.insert(id, block_md);
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-14 11:38:29 -07:00
|
|
|
return block_md;
|
2011-11-15 21:11:22 -05:00
|
|
|
}
|
|
|
|
|
2013-06-14 11:38:29 -07:00
|
|
|
fn size_and_align_of(cx: @CrateContext, t: ty::t) -> (uint, uint) {
|
2012-03-13 15:35:29 +01:00
|
|
|
let llty = type_of::type_of(cx, t);
|
2013-06-14 12:23:42 -07:00
|
|
|
(machine::llsize_of_real(cx, llty), machine::llalign_of_min(cx, llty))
|
2011-12-07 16:08:25 -05:00
|
|
|
}
|
|
|
|
|
2013-06-14 11:59:49 -07:00
|
|
|
fn create_basic_type(cx: @CrateContext, t: ty::t, _span: span) -> DIType{
|
2013-06-11 12:41:09 -07:00
|
|
|
let dcx = dbg_cx(cx);
|
2013-06-14 11:38:29 -07:00
|
|
|
let ty_id = ty::type_id(t);
|
2013-06-11 00:57:25 -07:00
|
|
|
match dcx.created_types.find(&ty_id) {
|
2013-06-14 11:38:29 -07:00
|
|
|
Some(ty_md) => return *ty_md,
|
|
|
|
None => ()
|
2011-11-15 21:11:22 -05:00
|
|
|
}
|
2013-06-11 12:41:09 -07:00
|
|
|
|
|
|
|
debug!("create_basic_type: %?", ty::get(t));
|
2013-06-14 11:38:29 -07:00
|
|
|
|
2013-02-27 13:35:56 -05:00
|
|
|
let (name, encoding) = match ty::get(t).sty {
|
|
|
|
ty::ty_nil | ty::ty_bot => (~"uint", DW_ATE_unsigned),
|
|
|
|
ty::ty_bool => (~"bool", DW_ATE_boolean),
|
|
|
|
ty::ty_int(int_ty) => match int_ty {
|
|
|
|
ast::ty_i => (~"int", DW_ATE_signed),
|
|
|
|
ast::ty_char => (~"char", DW_ATE_signed_char),
|
|
|
|
ast::ty_i8 => (~"i8", DW_ATE_signed),
|
|
|
|
ast::ty_i16 => (~"i16", DW_ATE_signed),
|
|
|
|
ast::ty_i32 => (~"i32", DW_ATE_signed),
|
|
|
|
ast::ty_i64 => (~"i64", DW_ATE_signed)
|
|
|
|
},
|
|
|
|
ty::ty_uint(uint_ty) => match uint_ty {
|
|
|
|
ast::ty_u => (~"uint", DW_ATE_unsigned),
|
|
|
|
ast::ty_u8 => (~"u8", DW_ATE_unsigned),
|
2013-04-08 23:59:00 +02:00
|
|
|
ast::ty_u16 => (~"u16", DW_ATE_unsigned),
|
2013-02-27 13:35:56 -05:00
|
|
|
ast::ty_u32 => (~"u32", DW_ATE_unsigned),
|
|
|
|
ast::ty_u64 => (~"u64", DW_ATE_unsigned)
|
|
|
|
},
|
|
|
|
ty::ty_float(float_ty) => match float_ty {
|
|
|
|
ast::ty_f => (~"float", DW_ATE_float),
|
|
|
|
ast::ty_f32 => (~"f32", DW_ATE_float),
|
|
|
|
ast::ty_f64 => (~"f64", DW_ATE_float)
|
|
|
|
},
|
2013-06-14 11:38:29 -07:00
|
|
|
_ => cx.sess.bug(~"debuginfo::create_basic_type - t is invalid type")
|
2013-02-27 13:35:56 -05:00
|
|
|
};
|
2011-12-14 15:14:06 -05:00
|
|
|
|
2012-03-13 15:35:29 +01:00
|
|
|
let (size, align) = size_and_align_of(cx, t);
|
2013-06-14 11:38:29 -07:00
|
|
|
let ty_md = do as_c_str(name) |name| { unsafe {
|
|
|
|
llvm::LLVMDIBuilderCreateBasicType(
|
2013-06-11 12:41:09 -07:00
|
|
|
dcx.builder, name,
|
2013-06-14 11:38:29 -07:00
|
|
|
size * 8 as u64, align * 8 as u64, encoding as c_uint)
|
|
|
|
}};
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-11 00:57:25 -07:00
|
|
|
dcx.created_types.insert(ty_id, ty_md);
|
2013-06-14 11:38:29 -07:00
|
|
|
return ty_md;
|
2011-12-07 16:08:25 -05:00
|
|
|
}
|
|
|
|
|
2013-06-14 11:59:49 -07:00
|
|
|
fn create_pointer_type(cx: @CrateContext, t: ty::t, _span: span, pointee: DIType) -> DIType {
|
2012-03-13 15:35:29 +01:00
|
|
|
let (size, align) = size_and_align_of(cx, t);
|
2013-04-08 23:08:10 -04:00
|
|
|
let name = ty_to_str(cx.tcx, t);
|
2013-06-14 11:38:29 -07:00
|
|
|
let ptr_md = do as_c_str(name) |name| { unsafe {
|
2013-06-11 12:41:09 -07:00
|
|
|
llvm::LLVMDIBuilderCreatePointerType(dbg_cx(cx).builder,
|
2013-06-14 11:38:29 -07:00
|
|
|
pointee, size * 8 as u64, align * 8 as u64, name)
|
|
|
|
}};
|
|
|
|
return ptr_md;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct StructContext {
|
|
|
|
cx: @CrateContext,
|
|
|
|
file: DIFile,
|
|
|
|
name: ~str,
|
|
|
|
line: uint,
|
|
|
|
members: ~[DIDerivedType],
|
|
|
|
total_size: uint,
|
|
|
|
align: uint
|
|
|
|
}
|
|
|
|
|
|
|
|
impl StructContext {
|
|
|
|
fn create(cx: @CrateContext, file: DIFile, name: ~str, line: uint) -> ~StructContext {
|
2013-06-14 12:23:42 -07:00
|
|
|
debug!("StructContext::create: %s", name);
|
2013-06-14 11:38:29 -07:00
|
|
|
let scx = ~StructContext {
|
|
|
|
cx: cx,
|
|
|
|
file: file,
|
|
|
|
name: name,
|
|
|
|
line: line,
|
|
|
|
members: ~[],
|
|
|
|
total_size: 0,
|
2013-06-14 12:23:42 -07:00
|
|
|
align: 1
|
2013-06-14 11:38:29 -07:00
|
|
|
};
|
|
|
|
return scx;
|
|
|
|
}
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-14 11:38:29 -07:00
|
|
|
fn add_member(&mut self, name: &str, line: uint, size: uint, align: uint, ty: DIType) {
|
2013-06-14 11:59:49 -07:00
|
|
|
debug!("StructContext(%s)::add_member: %s, size=%u, align=%u",
|
|
|
|
self.name, name, size, align);
|
2013-06-14 12:23:42 -07:00
|
|
|
let offset = roundup(self.total_size, align);
|
2013-06-14 11:38:29 -07:00
|
|
|
let mem_t = do as_c_str(name) |name| { unsafe {
|
2013-06-11 12:41:09 -07:00
|
|
|
llvm::LLVMDIBuilderCreateMemberType(dbg_cx(self.cx).builder,
|
|
|
|
ptr::null(), name, self.file, line as c_uint,
|
2013-06-14 12:23:42 -07:00
|
|
|
size * 8 as u64, align * 8 as u64, offset * 8 as u64,
|
2013-06-14 11:38:29 -07:00
|
|
|
0, ty)
|
|
|
|
}};
|
|
|
|
self.members.push(mem_t);
|
2013-06-14 12:23:42 -07:00
|
|
|
self.total_size = offset + size;
|
|
|
|
// struct alignment is the max alignment of its' members
|
|
|
|
self.align = cmp::max(self.align, align);
|
2013-06-14 11:38:29 -07:00
|
|
|
}
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-14 11:38:29 -07:00
|
|
|
fn finalize(&self) -> DICompositeType {
|
2013-06-14 11:59:49 -07:00
|
|
|
debug!("StructContext(%s)::finalize: total_size=%u, align=%u",
|
|
|
|
self.name, self.total_size, self.align);
|
2013-06-11 00:57:25 -07:00
|
|
|
let dcx = dbg_cx(self.cx);
|
|
|
|
let members_md = create_DIArray(dcx.builder, self.members);
|
2013-06-11 12:41:09 -07:00
|
|
|
|
|
|
|
let struct_md =
|
2013-06-14 11:38:29 -07:00
|
|
|
do as_c_str(self.name) |name| { unsafe {
|
|
|
|
llvm::LLVMDIBuilderCreateStructType(
|
2013-06-14 12:23:42 -07:00
|
|
|
dcx.builder, self.file, name,
|
2013-06-14 11:38:29 -07:00
|
|
|
self.file, self.line as c_uint,
|
2013-06-14 12:23:42 -07:00
|
|
|
self.total_size * 8 as u64, self.align * 8 as u64, 0, ptr::null(),
|
2013-06-14 11:38:29 -07:00
|
|
|
members_md, 0, ptr::null())
|
|
|
|
}};
|
|
|
|
return struct_md;
|
|
|
|
}
|
2011-12-09 11:32:23 -05:00
|
|
|
}
|
|
|
|
|
2013-06-14 12:23:42 -07:00
|
|
|
#[inline(always)]
|
2013-06-14 11:59:49 -07:00
|
|
|
fn roundup(x: uint, a: uint) -> uint {
|
|
|
|
((x + (a - 1)) / a) * a
|
2013-06-14 12:23:42 -07:00
|
|
|
}
|
|
|
|
|
2013-06-14 11:38:29 -07:00
|
|
|
fn create_struct(cx: @CrateContext, t: ty::t, fields: ~[ty::field], span: span) -> DICompositeType {
|
2013-06-10 18:34:51 -07:00
|
|
|
let loc = span_start(cx, span);
|
|
|
|
let file_md = create_file(cx, loc.file.name);
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-10 18:34:51 -07:00
|
|
|
let mut scx = StructContext::create(cx, file_md, ty_to_str(cx.tcx, t), loc.line);
|
2013-02-27 13:35:56 -05:00
|
|
|
for fields.each |field| {
|
|
|
|
let field_t = field.mt.ty;
|
|
|
|
let ty_md = create_ty(cx, field_t, span);
|
|
|
|
let (size, align) = size_and_align_of(cx, field_t);
|
2013-06-14 11:38:29 -07:00
|
|
|
scx.add_member(cx.sess.str_of(field.ident),
|
2013-06-10 18:34:51 -07:00
|
|
|
loc.line, size, align, ty_md);
|
2013-02-27 13:35:56 -05:00
|
|
|
}
|
2013-06-14 11:38:29 -07:00
|
|
|
return scx.finalize();
|
2013-02-27 13:35:56 -05:00
|
|
|
}
|
|
|
|
|
2013-06-14 11:38:29 -07:00
|
|
|
// returns (void* type as a ValueRef, size in bytes, align in bytes)
|
2013-06-11 00:57:25 -07:00
|
|
|
fn voidptr(cx: @CrateContext) -> (DIDerivedType, uint, uint) {
|
2013-06-14 11:38:29 -07:00
|
|
|
let size = sys::size_of::<ValueRef>();
|
|
|
|
let align = sys::min_align_of::<ValueRef>();
|
2013-06-11 00:57:25 -07:00
|
|
|
let vp = do as_c_str("*void") |name| { unsafe {
|
2013-06-11 12:41:09 -07:00
|
|
|
llvm::LLVMDIBuilderCreatePointerType(dbg_cx(cx).builder, ptr::null(),
|
2013-06-11 00:57:25 -07:00
|
|
|
size*8 as u64, align*8 as u64, name)
|
|
|
|
}};
|
2013-06-14 11:38:29 -07:00
|
|
|
return (vp, size, align);
|
|
|
|
}
|
|
|
|
|
2013-06-14 11:59:49 -07:00
|
|
|
fn create_tuple(cx: @CrateContext, _t: ty::t, elements: &[ty::t], span: span) -> DICompositeType {
|
2013-06-11 00:57:25 -07:00
|
|
|
let dcx = dbg_cx(cx);
|
2013-06-10 18:34:51 -07:00
|
|
|
let loc = span_start(cx, span);
|
|
|
|
let file_md = create_file(cx, loc.file.name);
|
2013-06-14 11:38:29 -07:00
|
|
|
|
|
|
|
let name = (cx.sess.str_of((dcx.names)("tuple"))).to_owned();
|
|
|
|
let mut scx = StructContext::create(cx, file_md, name, loc.line);
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-02-27 13:35:56 -05:00
|
|
|
for elements.each |element| {
|
|
|
|
let ty_md = create_ty(cx, *element, span);
|
|
|
|
let (size, align) = size_and_align_of(cx, *element);
|
2013-06-10 18:34:51 -07:00
|
|
|
scx.add_member("", loc.line, size, align, ty_md);
|
2013-02-27 13:35:56 -05:00
|
|
|
}
|
2013-06-14 11:38:29 -07:00
|
|
|
return scx.finalize();
|
2013-03-29 17:14:08 -04:00
|
|
|
}
|
|
|
|
|
2013-06-14 11:38:29 -07:00
|
|
|
fn create_boxed_type(cx: @CrateContext, contents: ty::t,
|
|
|
|
span: span, boxed: DIType) -> DICompositeType {
|
2013-06-10 18:34:51 -07:00
|
|
|
let loc = span_start(cx, span);
|
|
|
|
let file_md = create_file(cx, loc.file.name);
|
2013-04-22 20:19:05 -07:00
|
|
|
let int_t = ty::mk_int();
|
2013-04-02 16:08:34 -04:00
|
|
|
let refcount_type = create_basic_type(cx, int_t, span);
|
2013-03-29 17:14:08 -04:00
|
|
|
let name = ty_to_str(cx.tcx, contents);
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-14 11:38:29 -07:00
|
|
|
let mut scx = StructContext::create(cx, file_md, fmt!("box<%s>", name), 0);
|
|
|
|
scx.add_member("refcnt", 0, sys::size_of::<uint>(),
|
|
|
|
sys::min_align_of::<uint>(), refcount_type);
|
2013-03-29 17:14:08 -04:00
|
|
|
// the tydesc and other pointers should be irrelevant to the
|
|
|
|
// debugger, so treat them as void* types
|
2013-06-11 00:57:25 -07:00
|
|
|
let (vp, vpsize, vpalign) = voidptr(cx);
|
2013-06-14 11:38:29 -07:00
|
|
|
scx.add_member("tydesc", 0, vpsize, vpalign, vp);
|
|
|
|
scx.add_member("prev", 0, vpsize, vpalign, vp);
|
|
|
|
scx.add_member("next", 0, vpsize, vpalign, vp);
|
2013-03-29 17:14:08 -04:00
|
|
|
let (size, align) = size_and_align_of(cx, contents);
|
2013-06-14 11:38:29 -07:00
|
|
|
scx.add_member("boxed", 0, size, align, boxed);
|
|
|
|
return scx.finalize();
|
2011-12-11 15:24:47 -05:00
|
|
|
}
|
|
|
|
|
2013-06-14 11:59:49 -07:00
|
|
|
fn create_fixed_vec(cx: @CrateContext, _vec_t: ty::t, elem_t: ty::t,
|
2013-06-14 11:38:29 -07:00
|
|
|
len: uint, span: span) -> DIType {
|
2013-06-11 00:57:25 -07:00
|
|
|
let dcx = dbg_cx(cx);
|
2013-06-14 11:38:29 -07:00
|
|
|
let elem_ty_md = create_ty(cx, elem_t, span);
|
2013-04-02 16:08:34 -04:00
|
|
|
let (size, align) = size_and_align_of(cx, elem_t);
|
2013-06-14 11:38:29 -07:00
|
|
|
|
2013-06-11 12:41:09 -07:00
|
|
|
let subrange = unsafe {
|
2013-06-14 12:23:42 -07:00
|
|
|
llvm::LLVMDIBuilderGetOrCreateSubrange(dcx.builder, 0_i64, len as i64) };
|
2013-06-14 11:38:29 -07:00
|
|
|
|
2013-06-11 00:57:25 -07:00
|
|
|
let subscripts = create_DIArray(dcx.builder, [subrange]);
|
2013-06-11 12:41:09 -07:00
|
|
|
return unsafe {
|
2013-06-14 12:23:42 -07:00
|
|
|
llvm::LLVMDIBuilderCreateArrayType(dcx.builder,
|
|
|
|
size * len * 8 as u64, align * 8 as u64, elem_ty_md, subscripts)
|
2013-06-14 11:38:29 -07:00
|
|
|
};
|
2013-04-02 16:08:34 -04:00
|
|
|
}
|
|
|
|
|
2013-06-14 11:38:29 -07:00
|
|
|
fn create_boxed_vec(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t,
|
2013-06-10 18:34:51 -07:00
|
|
|
vec_ty_span: span) -> DICompositeType {
|
2013-06-11 00:57:25 -07:00
|
|
|
let dcx = dbg_cx(cx);
|
2013-06-10 18:34:51 -07:00
|
|
|
let loc = span_start(cx, vec_ty_span);
|
|
|
|
let file_md = create_file(cx, loc.file.name);
|
2013-02-27 13:35:56 -05:00
|
|
|
let elem_ty_md = create_ty(cx, elem_t, vec_ty_span);
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-14 11:38:29 -07:00
|
|
|
let mut vec_scx = StructContext::create(cx, file_md, ty_to_str(cx.tcx, vec_t), 0);
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-04-22 20:19:05 -07:00
|
|
|
let size_t_type = create_basic_type(cx, ty::mk_uint(), vec_ty_span);
|
2013-06-14 11:38:29 -07:00
|
|
|
vec_scx.add_member("fill", 0, sys::size_of::<libc::size_t>(),
|
|
|
|
sys::min_align_of::<libc::size_t>(), size_t_type);
|
|
|
|
vec_scx.add_member("alloc", 0, sys::size_of::<libc::size_t>(),
|
|
|
|
sys::min_align_of::<libc::size_t>(), size_t_type);
|
2013-06-11 00:57:25 -07:00
|
|
|
let subrange = unsafe { llvm::LLVMDIBuilderGetOrCreateSubrange(dcx.builder, 0_i64, 0_i64) };
|
2012-03-13 15:35:29 +01:00
|
|
|
let (arr_size, arr_align) = size_and_align_of(cx, elem_t);
|
2013-04-02 16:08:34 -04:00
|
|
|
let name = fmt!("[%s]", ty_to_str(cx.tcx, elem_t));
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-11 00:57:25 -07:00
|
|
|
let subscripts = create_DIArray(dcx.builder, [subrange]);
|
2013-06-14 12:23:42 -07:00
|
|
|
let data_ptr = unsafe { llvm::LLVMDIBuilderCreateArrayType(dcx.builder,
|
|
|
|
arr_size * 8 as u64, arr_align * 8 as u64, elem_ty_md, subscripts) };
|
2013-06-14 11:38:29 -07:00
|
|
|
vec_scx.add_member("data", 0, 0, // clang says the size should be 0
|
|
|
|
sys::min_align_of::<u8>(), data_ptr);
|
|
|
|
let vec_md = vec_scx.finalize();
|
|
|
|
|
|
|
|
let mut box_scx = StructContext::create(cx, file_md, fmt!("box<%s>", name), 0);
|
2013-04-22 20:19:05 -07:00
|
|
|
let int_t = ty::mk_int();
|
2013-04-02 16:08:34 -04:00
|
|
|
let refcount_type = create_basic_type(cx, int_t, vec_ty_span);
|
2013-06-14 11:38:29 -07:00
|
|
|
box_scx.add_member("refcnt", 0, sys::size_of::<uint>(),
|
|
|
|
sys::min_align_of::<uint>(), refcount_type);
|
2013-06-11 00:57:25 -07:00
|
|
|
let (vp, vpsize, vpalign) = voidptr(cx);
|
2013-06-14 11:38:29 -07:00
|
|
|
box_scx.add_member("tydesc", 0, vpsize, vpalign, vp);
|
|
|
|
box_scx.add_member("prev", 0, vpsize, vpalign, vp);
|
|
|
|
box_scx.add_member("next", 0, vpsize, vpalign, vp);
|
|
|
|
let size = 2 * sys::size_of::<int>();
|
|
|
|
let align = sys::min_align_of::<int>();
|
|
|
|
box_scx.add_member("boxed", 0, size, align, vec_md);
|
|
|
|
let mdval = box_scx.finalize();
|
2013-04-02 16:08:34 -04:00
|
|
|
return mdval;
|
|
|
|
}
|
|
|
|
|
2013-06-14 11:38:29 -07:00
|
|
|
fn create_vec_slice(cx: @CrateContext, vec_t: ty::t, elem_t: ty::t, span: span) -> DICompositeType {
|
2013-06-10 18:34:51 -07:00
|
|
|
let loc = span_start(cx, span);
|
|
|
|
let file_md = create_file(cx, loc.file.name);
|
2013-04-02 16:08:34 -04:00
|
|
|
let elem_ty_md = create_ty(cx, elem_t, span);
|
2013-04-22 20:19:05 -07:00
|
|
|
let uint_type = create_basic_type(cx, ty::mk_uint(), span);
|
2013-04-02 16:08:34 -04:00
|
|
|
let elem_ptr = create_pointer_type(cx, elem_t, span, elem_ty_md);
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-14 11:38:29 -07:00
|
|
|
let mut scx = StructContext::create(cx, file_md, ty_to_str(cx.tcx, vec_t), 0);
|
2013-06-11 00:57:25 -07:00
|
|
|
let (_, ptr_size, ptr_align) = voidptr(cx);
|
2013-06-14 11:38:29 -07:00
|
|
|
scx.add_member("vec", 0, ptr_size, ptr_align, elem_ptr);
|
|
|
|
scx.add_member("length", 0, sys::size_of::<uint>(),
|
|
|
|
sys::min_align_of::<uint>(), uint_type);
|
|
|
|
return scx.finalize();
|
2011-12-11 15:24:47 -05:00
|
|
|
}
|
|
|
|
|
2013-06-14 11:59:49 -07:00
|
|
|
fn create_fn_ty(cx: @CrateContext, _fn_ty: ty::t, inputs: ~[ty::t], output: ty::t,
|
2013-06-14 11:38:29 -07:00
|
|
|
span: span) -> DICompositeType {
|
2013-06-11 00:57:25 -07:00
|
|
|
let dcx = dbg_cx(cx);
|
2013-06-10 18:34:51 -07:00
|
|
|
let loc = span_start(cx, span);
|
|
|
|
let file_md = create_file(cx, loc.file.name);
|
2013-06-11 00:57:25 -07:00
|
|
|
let (vp, _, _) = voidptr(cx);
|
2013-04-08 23:08:10 -04:00
|
|
|
let output_md = create_ty(cx, output, span);
|
|
|
|
let output_ptr_md = create_pointer_type(cx, output, span, output_md);
|
2013-06-14 11:38:29 -07:00
|
|
|
let inputs_vals = do inputs.map |arg| { create_ty(cx, *arg, span) };
|
|
|
|
let members = ~[output_ptr_md, vp] + inputs_vals;
|
2013-06-11 12:41:09 -07:00
|
|
|
|
|
|
|
return unsafe {
|
|
|
|
llvm::LLVMDIBuilderCreateSubroutineType(dcx.builder, file_md,
|
|
|
|
create_DIArray(dcx.builder, members))
|
2013-04-08 23:08:10 -04:00
|
|
|
};
|
2011-12-11 15:24:47 -05:00
|
|
|
}
|
|
|
|
|
2013-06-14 12:08:59 -07:00
|
|
|
fn create_unimpl_ty(cx: @CrateContext, t: ty::t) -> DIType {
|
|
|
|
let dcx = dbg_cx(cx);
|
|
|
|
let name = ty_to_str(cx.tcx, t);
|
|
|
|
let md = do as_c_str(fmt!("NYI<%s>", name)) |name| { unsafe {
|
|
|
|
llvm::LLVMDIBuilderCreateBasicType(
|
2013-06-14 11:59:49 -07:00
|
|
|
dcx.builder, name,
|
2013-06-14 12:08:59 -07:00
|
|
|
0_u64, 8_u64, DW_ATE_unsigned as c_uint)
|
|
|
|
}};
|
|
|
|
return md;
|
|
|
|
}
|
|
|
|
|
2013-06-14 11:38:29 -07:00
|
|
|
fn create_ty(cx: @CrateContext, t: ty::t, span: span) -> DIType {
|
2013-06-11 12:41:09 -07:00
|
|
|
let dcx = dbg_cx(cx);
|
2013-06-14 11:38:29 -07:00
|
|
|
let ty_id = ty::type_id(t);
|
2013-06-11 00:57:25 -07:00
|
|
|
match dcx.created_types.find(&ty_id) {
|
2013-06-14 11:38:29 -07:00
|
|
|
Some(ty_md) => return *ty_md,
|
|
|
|
None => ()
|
|
|
|
}
|
|
|
|
|
2013-02-27 13:35:56 -05:00
|
|
|
debug!("create_ty: %?", ty::get(t));
|
2011-12-09 11:32:23 -05:00
|
|
|
|
2013-02-27 13:35:56 -05:00
|
|
|
let sty = copy ty::get(t).sty;
|
2013-06-14 11:38:29 -07:00
|
|
|
let ty_md = match sty {
|
2013-02-27 13:35:56 -05:00
|
|
|
ty::ty_nil | ty::ty_bot | ty::ty_bool | ty::ty_int(_) | ty::ty_uint(_)
|
|
|
|
| ty::ty_float(_) => create_basic_type(cx, t, span),
|
2013-04-02 16:08:34 -04:00
|
|
|
ty::ty_estr(ref vstore) => {
|
2013-04-22 20:19:05 -07:00
|
|
|
let i8_t = ty::mk_i8();
|
2013-04-02 16:08:34 -04:00
|
|
|
match *vstore {
|
|
|
|
ty::vstore_fixed(len) => {
|
2013-06-14 11:38:29 -07:00
|
|
|
create_fixed_vec(cx, t, i8_t, len + 1, span)
|
2013-04-02 16:08:34 -04:00
|
|
|
},
|
|
|
|
ty::vstore_uniq | ty::vstore_box => {
|
|
|
|
let box_md = create_boxed_vec(cx, t, i8_t, span);
|
|
|
|
create_pointer_type(cx, t, span, box_md)
|
|
|
|
}
|
|
|
|
ty::vstore_slice(_region) => {
|
|
|
|
create_vec_slice(cx, t, i8_t, span)
|
|
|
|
}
|
|
|
|
}
|
2013-02-27 13:35:56 -05:00
|
|
|
},
|
2013-03-20 01:17:42 -04:00
|
|
|
ty::ty_enum(_did, ref _substs) => {
|
2013-06-14 12:08:59 -07:00
|
|
|
cx.sess.span_note(span, "debuginfo for enum NYI");
|
|
|
|
create_unimpl_ty(cx, t)
|
2012-02-06 15:29:56 +01:00
|
|
|
}
|
2013-03-29 17:14:08 -04:00
|
|
|
ty::ty_box(ref mt) | ty::ty_uniq(ref mt) => {
|
|
|
|
let boxed = create_ty(cx, mt.ty, span);
|
|
|
|
let box_md = create_boxed_type(cx, mt.ty, span, boxed);
|
|
|
|
create_pointer_type(cx, t, span, box_md)
|
2013-02-27 13:35:56 -05:00
|
|
|
},
|
2013-04-02 16:08:34 -04:00
|
|
|
ty::ty_evec(ref mt, ref vstore) => {
|
|
|
|
match *vstore {
|
|
|
|
ty::vstore_fixed(len) => {
|
2013-06-14 11:38:29 -07:00
|
|
|
create_fixed_vec(cx, t, mt.ty, len, span)
|
2013-04-02 16:08:34 -04:00
|
|
|
},
|
|
|
|
ty::vstore_uniq | ty::vstore_box => {
|
|
|
|
let box_md = create_boxed_vec(cx, t, mt.ty, span);
|
|
|
|
create_pointer_type(cx, t, span, box_md)
|
|
|
|
},
|
|
|
|
ty::vstore_slice(_region) => {
|
|
|
|
create_vec_slice(cx, t, mt.ty, span)
|
|
|
|
}
|
|
|
|
}
|
2013-02-27 13:35:56 -05:00
|
|
|
},
|
2013-03-20 01:17:42 -04:00
|
|
|
ty::ty_ptr(ref mt) => {
|
2013-02-27 13:35:56 -05:00
|
|
|
let pointee = create_ty(cx, mt.ty, span);
|
|
|
|
create_pointer_type(cx, t, span, pointee)
|
|
|
|
},
|
2013-03-20 01:17:42 -04:00
|
|
|
ty::ty_rptr(ref _region, ref _mt) => {
|
2013-06-14 12:08:59 -07:00
|
|
|
cx.sess.span_note(span, "debuginfo for rptr NYI");
|
|
|
|
create_unimpl_ty(cx, t)
|
2013-02-27 13:35:56 -05:00
|
|
|
},
|
2013-04-08 23:08:10 -04:00
|
|
|
ty::ty_bare_fn(ref barefnty) => {
|
2013-04-26 19:13:38 -07:00
|
|
|
let inputs = barefnty.sig.inputs.map(|a| *a);
|
2013-04-08 23:08:10 -04:00
|
|
|
let output = barefnty.sig.output;
|
|
|
|
create_fn_ty(cx, t, inputs, output, span)
|
2013-02-27 13:35:56 -05:00
|
|
|
},
|
2013-03-20 01:17:42 -04:00
|
|
|
ty::ty_closure(ref _closurety) => {
|
2013-06-14 12:08:59 -07:00
|
|
|
cx.sess.span_note(span, "debuginfo for closure NYI");
|
|
|
|
create_unimpl_ty(cx, t)
|
2013-02-27 13:35:56 -05:00
|
|
|
},
|
2013-04-02 03:40:57 -04:00
|
|
|
ty::ty_trait(_did, ref _substs, ref _vstore, _) => {
|
2013-06-14 12:08:59 -07:00
|
|
|
cx.sess.span_note(span, "debuginfo for trait NYI");
|
|
|
|
create_unimpl_ty(cx, t)
|
2013-02-27 13:35:56 -05:00
|
|
|
},
|
2013-03-20 01:17:42 -04:00
|
|
|
ty::ty_struct(did, ref substs) => {
|
|
|
|
let fields = ty::struct_fields(cx.tcx, did, substs);
|
2013-02-27 13:35:56 -05:00
|
|
|
create_struct(cx, t, fields, span)
|
|
|
|
},
|
2013-03-20 01:17:42 -04:00
|
|
|
ty::ty_tup(ref elements) => {
|
|
|
|
create_tuple(cx, t, *elements, span)
|
2013-02-27 13:35:56 -05:00
|
|
|
},
|
2013-06-14 11:38:29 -07:00
|
|
|
_ => cx.sess.bug(~"debuginfo: unexpected type in create_ty")
|
|
|
|
};
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-11 00:57:25 -07:00
|
|
|
dcx.created_types.insert(ty_id, ty_md);
|
2013-06-14 11:38:29 -07:00
|
|
|
return ty_md;
|
2011-12-14 15:14:06 -05:00
|
|
|
}
|
|
|
|
|
2013-06-14 11:38:29 -07:00
|
|
|
pub fn create_local_var(bcx: block, local: @ast::local) -> DIVariable {
|
2013-04-09 02:07:50 -04:00
|
|
|
let cx = bcx.ccx();
|
2013-06-11 00:57:25 -07:00
|
|
|
let dcx = dbg_cx(cx);
|
2013-04-09 02:07:50 -04:00
|
|
|
|
2013-06-11 00:57:25 -07:00
|
|
|
let ident = match local.node.pat.node {
|
2013-04-09 02:07:50 -04:00
|
|
|
ast::pat_ident(_, pth, _) => ast_util::path_to_ident(pth),
|
|
|
|
// FIXME this should be handled (#2533)
|
2013-06-14 12:08:59 -07:00
|
|
|
_ => {
|
|
|
|
bcx.sess().span_note(local.span, "debuginfo for pattern bindings NYI");
|
|
|
|
return ptr::null();
|
|
|
|
}
|
2013-04-09 02:07:50 -04:00
|
|
|
};
|
2013-06-14 11:38:29 -07:00
|
|
|
let name: &str = cx.sess.str_of(ident);
|
|
|
|
debug!("create_local_var: %s", name);
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-14 11:38:29 -07:00
|
|
|
let loc = span_start(cx, local.span);
|
2013-04-09 02:07:50 -04:00
|
|
|
let ty = node_id_type(bcx, local.node.id);
|
|
|
|
let tymd = create_ty(cx, ty, local.node.ty.span);
|
2013-06-11 00:57:25 -07:00
|
|
|
let filemd = create_file(cx, loc.file.name);
|
2013-04-09 02:07:50 -04:00
|
|
|
let context = match bcx.parent {
|
2013-06-14 11:38:29 -07:00
|
|
|
None => create_function(bcx.fcx),
|
|
|
|
Some(_) => create_block(bcx)
|
2013-04-09 02:07:50 -04:00
|
|
|
};
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-11 00:57:25 -07:00
|
|
|
let var_md = do as_c_str(name) |name| { unsafe {
|
|
|
|
llvm::LLVMDIBuilderCreateLocalVariable(
|
|
|
|
dcx.builder, AutoVariableTag as u32,
|
2013-06-11 12:41:09 -07:00
|
|
|
context, name, filemd,
|
2013-06-11 00:57:25 -07:00
|
|
|
loc.line as c_uint, tymd, false, 0, 0)
|
2013-06-14 11:38:29 -07:00
|
|
|
}};
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-11 00:57:25 -07:00
|
|
|
// FIXME(#6814) Should use `pat_util::pat_bindings` for pats like (a, b) etc
|
|
|
|
let llptr = match bcx.fcx.lllocals.find_copy(&local.node.pat.id) {
|
|
|
|
Some(v) => v,
|
|
|
|
None => {
|
|
|
|
bcx.tcx().sess.span_bug(
|
|
|
|
local.span,
|
|
|
|
fmt!("No entry in lllocals table for %?", local.node.id));
|
2013-04-09 02:07:50 -04:00
|
|
|
}
|
|
|
|
};
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-14 11:59:49 -07:00
|
|
|
set_debug_location(cx, create_block(bcx), loc.line, loc.col.to_uint());
|
2013-06-11 00:57:25 -07:00
|
|
|
unsafe {
|
2013-06-10 16:28:10 -07:00
|
|
|
let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(dcx.builder, llptr, var_md, bcx.llbb);
|
|
|
|
llvm::LLVMSetInstDebugLocation(trans::build::B(bcx), instr);
|
2013-06-14 11:38:29 -07:00
|
|
|
}
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-11 00:57:25 -07:00
|
|
|
return var_md;
|
|
|
|
}
|
2011-12-14 15:14:06 -05:00
|
|
|
|
2013-06-10 18:34:51 -07:00
|
|
|
pub fn create_arg(bcx: block, arg: ast::arg, span: span) -> Option<DIVariable> {
|
2013-06-14 11:38:29 -07:00
|
|
|
debug!("create_arg");
|
2013-06-11 12:41:09 -07:00
|
|
|
if true {
|
2013-06-14 11:59:49 -07:00
|
|
|
// XXX create_arg disabled for now because "node_id_type(bcx, arg.id)" below blows
|
2013-06-11 12:41:09 -07:00
|
|
|
// up: "error: internal compiler error: node_id_to_type: no type for node `arg (id=10)`"
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
|
|
|
let fcx = bcx.fcx;
|
|
|
|
let cx = *fcx.ccx;
|
2013-06-11 00:57:25 -07:00
|
|
|
let dcx = dbg_cx(cx);
|
2013-01-23 11:43:58 -08:00
|
|
|
|
2013-06-10 18:34:51 -07:00
|
|
|
let loc = span_start(cx, span);
|
2013-06-13 03:02:55 +10:00
|
|
|
if "<intrinsic>" == loc.file.name {
|
2013-04-09 02:07:50 -04:00
|
|
|
return None;
|
|
|
|
}
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-04-09 02:07:50 -04:00
|
|
|
let ty = node_id_type(bcx, arg.id);
|
|
|
|
let tymd = create_ty(cx, ty, arg.ty.span);
|
2013-06-11 00:57:25 -07:00
|
|
|
let filemd = create_file(cx, loc.file.name);
|
2013-04-09 02:07:50 -04:00
|
|
|
let context = create_function(bcx.fcx);
|
|
|
|
|
|
|
|
match arg.pat.node {
|
|
|
|
ast::pat_ident(_, path, _) => {
|
|
|
|
// XXX: This is wrong; it should work for multiple bindings.
|
2013-06-14 11:38:29 -07:00
|
|
|
let ident = path.idents.last();
|
|
|
|
let name: &str = cx.sess.str_of(*ident);
|
|
|
|
let mdnode = do as_c_str(name) |name| { unsafe {
|
2013-06-11 12:41:09 -07:00
|
|
|
llvm::LLVMDIBuilderCreateLocalVariable(dcx.builder,
|
|
|
|
ArgVariableTag as u32, context, name,
|
2013-06-14 11:38:29 -07:00
|
|
|
filemd, loc.line as c_uint, tymd, false, 0, 0)
|
2013-06-14 11:59:49 -07:00
|
|
|
// XXX need to pass in a real argument number
|
2013-06-14 11:38:29 -07:00
|
|
|
}};
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-11 00:57:25 -07:00
|
|
|
let llptr = fcx.llargs.get_copy(&arg.id);
|
2013-06-14 11:59:49 -07:00
|
|
|
set_debug_location(cx, create_block(bcx), loc.line, loc.col.to_uint());
|
2013-06-11 00:57:25 -07:00
|
|
|
unsafe {
|
2013-06-14 11:59:49 -07:00
|
|
|
let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
|
|
|
|
dcx.builder, llptr, mdnode, bcx.llbb);
|
|
|
|
llvm::LLVMSetInstDebugLocation(trans::build::B(bcx), instr);
|
2013-06-11 00:57:25 -07:00
|
|
|
}
|
2013-06-14 11:38:29 -07:00
|
|
|
return Some(mdnode);
|
2013-02-27 13:35:56 -05:00
|
|
|
}
|
2013-04-09 02:07:50 -04:00
|
|
|
_ => {
|
|
|
|
return None;
|
2012-11-06 18:41:06 -08:00
|
|
|
}
|
|
|
|
}
|
2011-12-06 00:05:22 -05:00
|
|
|
}
|
|
|
|
|
2013-06-14 11:59:49 -07:00
|
|
|
fn set_debug_location(cx: @CrateContext, scope: DIScope, line: uint, col: uint) {
|
|
|
|
let dcx = dbg_cx(cx);
|
|
|
|
if dcx.curr_loc == (line, col) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
debug!("setting debug location to %u %u", line, col);
|
|
|
|
dcx.curr_loc = (line, col);
|
|
|
|
|
|
|
|
let elems = ~[C_i32(line as i32), C_i32(col as i32), scope, ptr::null()];
|
2013-01-10 21:23:07 -08:00
|
|
|
unsafe {
|
2013-06-14 11:59:49 -07:00
|
|
|
let dbg_loc = llvm::LLVMMDNodeInContext(
|
|
|
|
dcx.llcontext, vec::raw::to_ptr(elems),
|
|
|
|
elems.len() as libc::c_uint);
|
|
|
|
llvm::LLVMSetCurrentDebugLocation(cx.builder.B, dbg_loc);
|
2013-01-10 21:23:07 -08:00
|
|
|
}
|
2011-11-16 19:30:45 -05:00
|
|
|
}
|
|
|
|
|
2013-06-14 11:59:49 -07:00
|
|
|
/// Set current debug location at the beginning of the span
|
2013-06-10 18:34:51 -07:00
|
|
|
pub fn update_source_pos(bcx: block, span: span) {
|
|
|
|
if !bcx.sess().opts.debuginfo || (*span.lo == 0 && *span.hi == 0) {
|
2013-06-11 00:57:25 -07:00
|
|
|
return;
|
|
|
|
}
|
2013-06-10 18:34:51 -07:00
|
|
|
debug!("update_source_pos: %s", bcx.sess().codemap.span_to_str(span));
|
2013-06-14 11:59:49 -07:00
|
|
|
let loc = span_start(bcx.ccx(), span);
|
|
|
|
set_debug_location(bcx.ccx(), create_block(bcx), loc.line, loc.col.to_uint())
|
2013-06-14 11:38:29 -07:00
|
|
|
}
|
2013-03-16 11:11:31 -07:00
|
|
|
|
2013-06-14 11:38:29 -07:00
|
|
|
pub fn create_function(fcx: fn_ctxt) -> DISubprogram {
|
|
|
|
let cx = *fcx.ccx;
|
2013-06-11 12:41:09 -07:00
|
|
|
let dcx = dbg_cx(cx);
|
2013-03-16 11:11:31 -07:00
|
|
|
let fcx = &mut *fcx;
|
2013-06-10 18:34:51 -07:00
|
|
|
let span = fcx.span.get();
|
2011-11-15 21:11:22 -05:00
|
|
|
|
2013-05-05 12:17:59 -04:00
|
|
|
let (ident, ret_ty, id) = match cx.tcx.items.get_copy(&fcx.id) {
|
2012-08-03 19:59:04 -07:00
|
|
|
ast_map::node_item(item, _) => {
|
2013-03-20 01:17:42 -04:00
|
|
|
match item.node {
|
2013-03-13 22:25:28 -04:00
|
|
|
ast::item_fn(ref decl, _, _, _, _) => {
|
2013-01-22 15:13:23 -08:00
|
|
|
(item.ident, decl.output, item.id)
|
2011-12-18 23:32:38 -05:00
|
|
|
}
|
2013-05-03 01:28:53 +09:00
|
|
|
_ => fcx.ccx.sess.span_bug(item.span, "create_function: item bound to non-function")
|
2011-12-18 23:32:38 -05:00
|
|
|
}
|
|
|
|
}
|
2012-08-03 19:59:04 -07:00
|
|
|
ast_map::node_method(method, _, _) => {
|
2013-01-22 15:13:23 -08:00
|
|
|
(method.ident, method.decl.output, method.id)
|
2012-01-13 17:28:06 -05:00
|
|
|
}
|
2012-08-03 19:59:04 -07:00
|
|
|
ast_map::node_expr(expr) => {
|
2013-03-20 01:17:42 -04:00
|
|
|
match expr.node {
|
|
|
|
ast::expr_fn_block(ref decl, _) => {
|
2013-06-11 00:57:25 -07:00
|
|
|
((dcx.names)("fn"), decl.output, expr.id)
|
2011-12-20 11:03:21 -08:00
|
|
|
}
|
2012-08-03 19:59:04 -07:00
|
|
|
_ => fcx.ccx.sess.span_bug(expr.span,
|
2013-05-03 01:28:53 +09:00
|
|
|
"create_function: expected an expr_fn_block here")
|
2011-12-18 23:32:38 -05:00
|
|
|
}
|
|
|
|
}
|
2013-05-03 01:28:53 +09:00
|
|
|
_ => fcx.ccx.sess.bug("create_function: unexpected sort of node")
|
2011-12-18 23:32:38 -05:00
|
|
|
};
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-11 00:57:25 -07:00
|
|
|
match dcx.created_functions.find(&id) {
|
2013-06-14 11:38:29 -07:00
|
|
|
Some(fn_md) => return *fn_md,
|
|
|
|
None => ()
|
2012-01-28 20:49:21 +01:00
|
|
|
}
|
2012-01-28 11:50:26 -05:00
|
|
|
|
2013-06-14 11:38:29 -07:00
|
|
|
debug!("create_function: %s, %s", cx.sess.str_of(ident), cx.sess.codemap.span_to_str(span));
|
|
|
|
|
2013-06-10 18:34:51 -07:00
|
|
|
let loc = span_start(cx, span);
|
2013-06-14 11:38:29 -07:00
|
|
|
let file_md = create_file(cx, loc.file.name);
|
|
|
|
|
|
|
|
let ret_ty_md = if cx.sess.opts.extra_debuginfo {
|
2012-08-06 12:34:08 -07:00
|
|
|
match ret_ty.node {
|
2013-06-14 11:38:29 -07:00
|
|
|
ast::ty_nil => ptr::null(),
|
2013-02-27 13:35:56 -05:00
|
|
|
_ => create_ty(cx, ty::node_id_to_type(cx.tcx, id),
|
2013-06-14 11:38:29 -07:00
|
|
|
ret_ty.span)
|
2011-12-14 15:47:05 -05:00
|
|
|
}
|
|
|
|
} else {
|
2013-06-14 11:38:29 -07:00
|
|
|
ptr::null()
|
2011-11-15 21:11:22 -05:00
|
|
|
};
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-14 11:38:29 -07:00
|
|
|
let fn_ty = unsafe {
|
2013-06-11 00:57:25 -07:00
|
|
|
llvm::LLVMDIBuilderCreateSubroutineType(dcx.builder,
|
|
|
|
file_md, create_DIArray(dcx.builder, [ret_ty_md]))
|
2013-06-14 11:38:29 -07:00
|
|
|
};
|
2013-06-11 12:41:09 -07:00
|
|
|
|
|
|
|
let fn_md =
|
2013-06-14 11:38:29 -07:00
|
|
|
do as_c_str(cx.sess.str_of(ident)) |name| {
|
|
|
|
do as_c_str(cx.sess.str_of(ident)) |linkage| { unsafe {
|
|
|
|
llvm::LLVMDIBuilderCreateFunction(
|
2013-06-11 12:41:09 -07:00
|
|
|
dcx.builder,
|
|
|
|
file_md,
|
|
|
|
name, linkage,
|
|
|
|
file_md, loc.line as c_uint,
|
|
|
|
fn_ty, false, true,
|
|
|
|
loc.line as c_uint,
|
2013-06-14 11:38:29 -07:00
|
|
|
FlagPrototyped as c_uint,
|
2013-06-11 12:41:09 -07:00
|
|
|
cx.sess.opts.optimize != session::No,
|
2013-06-14 11:38:29 -07:00
|
|
|
fcx.llfn, ptr::null(), ptr::null())
|
|
|
|
}}};
|
2013-06-11 12:41:09 -07:00
|
|
|
|
2013-06-11 00:57:25 -07:00
|
|
|
dcx.created_functions.insert(id, fn_md);
|
2013-06-14 11:38:29 -07:00
|
|
|
return fn_md;
|
2011-12-09 11:32:23 -05:00
|
|
|
}
|