Skip to content

Commit 10030a3

Browse files
committed
Generate basic debug info for files, functions and compile units.
1 parent fa27724 commit 10030a3

File tree

7 files changed

+222
-3
lines changed

7 files changed

+222
-3
lines changed

src/comp/lib/llvm.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ native mod llvm {
256256

257257
/* Operations on Users */
258258
fn LLVMGetOperand(Val: ValueRef, Index: uint) -> ValueRef;
259+
fn LLVMSetOperand(Val: ValueRef, Index: uint, Op: ValueRef);
259260

260261
/* Operations on constants of any type */
261262
fn LLVMConstNull(Ty: TypeRef) -> ValueRef;
@@ -275,6 +276,8 @@ native mod llvm {
275276
fn LLVMMDNodeInContext(C: ContextRef, Vals: *ValueRef, Count: uint) ->
276277
ValueRef;
277278
fn LLVMMDNode(Vals: *ValueRef, Count: uint) -> ValueRef;
279+
fn LLVMAddNamedMetadataOperand(M: ModuleRef, Str: sbuf, SLen: uint,
280+
Val: ValueRef);
278281

279282
/* Operations on scalar constants */
280283
fn LLVMConstInt(IntTy: TypeRef, N: ULongLong, SignExtend: Bool) ->

src/comp/middle/debuginfo.rs

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
import std::{vec, str, map, option, unsafe};
2+
import std::vec::to_ptr;
3+
import std::map::hashmap;
4+
import lib::llvm::llvm;
5+
import lib::llvm::llvm::{ModuleRef, ValueRef};
6+
import middle::trans_common::*;
7+
import syntax::{ast, codemap};
8+
9+
const LLVMDebugVersion: int = 0x80000;
10+
11+
const DW_LANG_RUST: int = 0x9000;
12+
const DW_VIRTUALITY_none: int = 0;
13+
14+
const CompileUnitTag: int = 17;
15+
const FileDescriptorTag: int = 41;
16+
const SubprogramTag: int = 46;
17+
18+
fn as_buf(s: str) -> str::sbuf {
19+
str::as_buf(s, {|sbuf| sbuf})
20+
}
21+
fn llstr(s: str) -> ValueRef {
22+
llvm::LLVMMDString(as_buf(s), str::byte_len(s))
23+
}
24+
25+
fn lltag(lltag: int) -> ValueRef {
26+
lli32(0x80000 + lltag)
27+
}
28+
fn lli32(val: int) -> ValueRef {
29+
C_i32(val as i32)
30+
}
31+
fn lli1(bval: bool) -> ValueRef {
32+
C_bool(bval)
33+
}
34+
fn llmdnode(elems: [ValueRef]) -> ValueRef unsafe {
35+
llvm::LLVMMDNode(vec::unsafe::to_ptr(elems),
36+
vec::len(elems))
37+
}
38+
fn llunused() -> ValueRef {
39+
lli32(0x0)
40+
}
41+
42+
fn update_cache(cache: metadata_cache, mdtag: int, val: debug_metadata) {
43+
let existing = if cache.contains_key(mdtag) {
44+
cache.get(mdtag)
45+
} else {
46+
[]
47+
};
48+
cache.insert(mdtag, existing + [val]);
49+
}
50+
51+
////////////////
52+
53+
type metadata<T> = {node: ValueRef, data: T};
54+
55+
type file_md = {path: str};
56+
type compile_unit_md = {path: str};
57+
type subprogram_md = {name: str, file: str};
58+
59+
type metadata_cache = hashmap<int, [debug_metadata]>;
60+
61+
tag debug_metadata {
62+
file_metadata(@metadata<file_md>);
63+
compile_unit_metadata(@metadata<compile_unit_md>);
64+
subprogram_metadata(@metadata<subprogram_md>);
65+
}
66+
67+
fn md_from_metadata<T>(val: debug_metadata) -> T unsafe {
68+
alt val {
69+
file_metadata(md) { unsafe::reinterpret_cast(md) }
70+
compile_unit_metadata(md) { unsafe::reinterpret_cast(md) }
71+
subprogram_metadata(md) { unsafe::reinterpret_cast(md) }
72+
}
73+
}
74+
75+
fn cached_metadata<T>(cache: metadata_cache, mdtag: int,
76+
eq: block(md: T) -> bool) -> option::t<T> {
77+
if cache.contains_key(mdtag) {
78+
let items = cache.get(mdtag);
79+
for item in items {
80+
let md: T = md_from_metadata::<T>(item);
81+
if eq(md) {
82+
ret option::some(md);
83+
}
84+
}
85+
}
86+
ret option::none;
87+
}
88+
89+
fn get_compile_unit_metadata(cx: @crate_ctxt, full_path: str)
90+
-> @metadata<compile_unit_md> {
91+
let cache = cx.llmetadata;
92+
alt cached_metadata::<@metadata<compile_unit_md>>(cache, CompileUnitTag,
93+
{|md| md.data.path == full_path}) {
94+
option::some(md) { ret md; }
95+
option::none. {}
96+
}
97+
let sep = str::rindex(full_path, '/' as u8) as uint;
98+
let fname = str::slice(full_path, sep + 1u,
99+
str::byte_len(full_path));
100+
let path = str::slice(full_path, 0u, sep + 1u);
101+
let unit_metadata = [lltag(CompileUnitTag),
102+
llunused(),
103+
lli32(DW_LANG_RUST),
104+
llstr(fname),
105+
llstr(path),
106+
llstr(#env["CFG_VERSION"]),
107+
lli1(false), // main compile unit
108+
lli1(cx.sess.get_opts().optimize != 0u),
109+
llstr(""), // flags (???)
110+
lli32(0) // runtime version (???)
111+
// list of enum types
112+
// list of retained values
113+
// list of subprograms
114+
// list of global variables
115+
];
116+
let unit_node = llmdnode(unit_metadata);
117+
llvm::LLVMAddNamedMetadataOperand(cx.llmod, as_buf("llvm.dbg.cu"),
118+
str::byte_len("llvm.dbg.cu"),
119+
unit_node);
120+
let mdval = @{node: unit_node, data: {path: full_path}};
121+
update_cache(cache, CompileUnitTag, compile_unit_metadata(mdval));
122+
ret mdval;
123+
}
124+
125+
// let kind_id = llvm::LLVMGetMDKindID(as_buf("dbg"),
126+
// str::byte_len("dbg"));
127+
128+
129+
fn get_file_metadata(cx: @crate_ctxt, full_path: str) -> @metadata<file_md> {
130+
let cache = cx.llmetadata;
131+
alt cached_metadata::<@metadata<file_md>>(
132+
cache, FileDescriptorTag, {|md| md.data.path == full_path}) {
133+
option::some(md) { ret md; }
134+
option::none. {}
135+
}
136+
let sep = str::rindex(full_path, '/' as u8) as uint;
137+
let fname = str::slice(full_path, sep + 1u,
138+
str::byte_len(full_path));
139+
let path = str::slice(full_path, 0u, sep + 1u);
140+
let unit_node = get_compile_unit_metadata(cx, path).node;
141+
let file_md = [lltag(FileDescriptorTag),
142+
llstr(fname),
143+
llstr(path),
144+
unit_node];
145+
let val = llmdnode(file_md);
146+
let mdval = @{node: val, data: {path: full_path}};
147+
update_cache(cache, FileDescriptorTag, file_metadata(mdval));
148+
ret mdval;
149+
}
150+
151+
fn get_function_metadata(cx: @crate_ctxt, item: @ast::item,
152+
llfndecl: ValueRef) -> @metadata<subprogram_md> {
153+
let cache = cx.llmetadata;
154+
alt cached_metadata::<@metadata<subprogram_md>>(
155+
cache, SubprogramTag, {|md| md.data.name == item.ident &&
156+
/*sub.path == ??*/ true}) {
157+
option::some(md) { ret md; }
158+
option::none. {}
159+
}
160+
let loc = codemap::lookup_char_pos(cx.sess.get_codemap(),
161+
item.span.lo);
162+
let file_node = get_file_metadata(cx, loc.filename).node;
163+
let fn_metadata = [lltag(SubprogramTag),
164+
llunused(),
165+
file_node,
166+
llstr(item.ident),
167+
llstr(item.ident), //XXX fully-qualified C++ name
168+
llstr(item.ident), //XXX MIPS name?????
169+
file_node,
170+
lli32(loc.line as int),
171+
C_null(T_ptr(T_nil())), // XXX reference to tydesc
172+
lli1(false), //XXX static
173+
lli1(true), // not extern
174+
lli32(DW_VIRTUALITY_none), // virtual-ness
175+
lli32(0i), //index into virt func
176+
C_null(T_ptr(T_nil())), // base type with vtbl
177+
lli1(false), // artificial
178+
lli1(cx.sess.get_opts().optimize != 0u),
179+
llfndecl
180+
//list of template params
181+
//func decl descriptor
182+
//list of func vars
183+
];
184+
let val = llmdnode(fn_metadata);
185+
llvm::LLVMAddNamedMetadataOperand(cx.llmod, as_buf("llvm.dbg.sp"),
186+
str::byte_len("llvm.dbg.sp"),
187+
val);
188+
let mdval = @{node: val, data: {name: item.ident,
189+
file: loc.filename}};
190+
update_cache(cache, SubprogramTag, subprogram_metadata(mdval));
191+
ret mdval;
192+
}

src/comp/middle/trans.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import std::map::{new_int_hash, new_str_hash};
2020
import option::{some, none};
2121
import driver::session;
2222
import front::attr;
23-
import middle::{ty, gc, resolve};
23+
import middle::{ty, gc, resolve, debuginfo};
2424
import middle::freevars::*;
2525
import back::{link, abi, upcall};
2626
import syntax::{ast, ast_util};
@@ -4543,6 +4543,12 @@ fn trans_fn(cx: @local_ctxt, sp: span, f: ast::_fn, llfndecl: ValueRef,
45434543
let do_time = cx.ccx.sess.get_opts().stats;
45444544
let start = do_time ? time::get_time() : {sec: 0u32, usec: 0u32};
45454545
trans_closure(cx, sp, f, llfndecl, ty_self, ty_params, id, {|_fcx|});
4546+
if cx.ccx.sess.get_opts().debuginfo {
4547+
let item = alt option::get(cx.ccx.ast_map.find(id)) {
4548+
ast_map::node_item(item) { item }
4549+
};
4550+
debuginfo::get_function_metadata(cx.ccx, item, llfndecl);
4551+
}
45464552
if do_time {
45474553
let end = time::get_time();
45484554
log_fn_time(cx.ccx, str::connect(cx.path, "::"), start, end);
@@ -5659,7 +5665,8 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
56595665
builder: BuilderRef_res(llvm::LLVMCreateBuilder()),
56605666
shape_cx: shape::mk_ctxt(llmod),
56615667
gc_cx: gc::mk_ctxt(),
5662-
crate_map: crate_map};
5668+
crate_map: crate_map,
5669+
llmetadata: map::new_int_hash()};
56635670
let cx = new_local_ctxt(ccx);
56645671
collect_items(ccx, crate);
56655672
collect_tag_ctors(ccx, crate);

src/comp/middle/trans_common.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ type crate_ctxt =
116116
builder: BuilderRef_res,
117117
shape_cx: shape::ctxt,
118118
gc_cx: gc::ctxt,
119-
crate_map: ValueRef};
119+
crate_map: ValueRef,
120+
llmetadata: debuginfo::metadata_cache};
120121

121122
type local_ctxt =
122123
{path: [str],

src/comp/rustc.rc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ mod middle {
3737
mod freevars;
3838
mod shape;
3939
mod gc;
40+
mod debuginfo;
4041

4142
mod tstate {
4243
mod ck;

src/rustllvm/RustWrapper.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,17 @@ extern "C" LLVMValueRef LLVMGetOrInsertFunction(LLVMModuleRef M,
165165
return wrap(unwrap(M)->getOrInsertFunction(Name,
166166
unwrap<FunctionType>(FunctionTy)));
167167
}
168+
169+
extern "C" LLVMTypeRef LLVMMetadataTypeInContext(LLVMContextRef C) {
170+
return wrap(Type::getMetadataTy(*unwrap(C)));
171+
}
172+
extern "C" LLVMTypeRef LLVMMetadataType(void) {
173+
return LLVMMetadataTypeInContext(LLVMGetGlobalContext());
174+
}
175+
176+
extern "C" void LLVMAddNamedMetadataOperand(LLVMModuleRef M, const char *Str,
177+
unsigned SLen, LLVMValueRef Val)
178+
{
179+
NamedMDNode *N = unwrap(M)->getOrInsertNamedMetadata(StringRef(Str, SLen));
180+
N->addOperand(unwrap<MDNode>(Val));
181+
}

src/rustllvm/rustllvm.def.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,7 @@ LLVMMDNode
487487
LLVMMDNodeInContext
488488
LLVMMDString
489489
LLVMMDStringInContext
490+
LLVMAddNamedMetadataOperand
490491
LLVMModuleCreateWithName
491492
LLVMModuleCreateWithNameInContext
492493
LLVMMoveBasicBlockAfter

0 commit comments

Comments
 (0)