auto merge of #7134 : vadimcn/rust/DIBuilder, r=jdm

This commit fixes rustc's debug info generation and turns debug-info tests back on.

The old generator used to write out LLVM metadata directly, however it seems that debug metadata format is not stable and keeps changing from release to release.  So I wrapped LLVM's official debug info API - the DIBuilder class, and now rustc will use that.

One bit of old functionality that still doesn't work, is debug info for function arguments.  Someone more familiar with the compiler guts will need to look into that.

Also, unfortunately, debug info is still won't work on Windows,- due to a LLVM bug (http://llvm.org/bugs/show_bug.cgi?id=16249).

Resolves issues #5836, #5848, #6814
This commit is contained in:
bors 2013-06-17 14:01:35 -07:00
commit 4bf074cc66
13 changed files with 954 additions and 756 deletions

View file

@ -23,7 +23,7 @@ fn target_env(lib_path: &str, prog: &str) -> ~[(~str,~str)] {
assert!(prog.ends_with(".exe"));
let aux_path = prog.slice(0u, prog.len() - 4u).to_owned() + ".libaux";
env = do vec::map(env) |pair| {
env = do env.map() |pair| {
let (k,v) = copy *pair;
if k == ~"PATH" { (~"PATH", v + ";" + lib_path + ";" + aux_path) }
else { (k,v) }

View file

@ -224,13 +224,50 @@ pub type SectionIteratorRef = *SectionIterator_opaque;
pub enum Pass_opaque {}
pub type PassRef = *Pass_opaque;
pub mod debuginfo {
use super::{ValueRef};
pub enum DIBuilder_opaque {}
pub type DIBuilderRef = *DIBuilder_opaque;
pub type DIDescriptor = ValueRef;
pub type DIScope = DIDescriptor;
pub type DILocation = DIDescriptor;
pub type DIFile = DIScope;
pub type DILexicalBlock = DIScope;
pub type DISubprogram = DIScope;
pub type DIType = DIDescriptor;
pub type DIBasicType = DIType;
pub type DIDerivedType = DIType;
pub type DICompositeType = DIDerivedType;
pub type DIVariable = DIDescriptor;
pub type DIArray = DIDescriptor;
pub type DISubrange = DIDescriptor;
pub enum DIDescriptorFlags {
FlagPrivate = 1 << 0,
FlagProtected = 1 << 1,
FlagFwdDecl = 1 << 2,
FlagAppleBlock = 1 << 3,
FlagBlockByrefStruct = 1 << 4,
FlagVirtual = 1 << 5,
FlagArtificial = 1 << 6,
FlagExplicit = 1 << 7,
FlagPrototyped = 1 << 8,
FlagObjcClassComplete = 1 << 9,
FlagObjectPointer = 1 << 10,
FlagVector = 1 << 11,
FlagStaticMember = 1 << 12
}
}
pub mod llvm {
use super::{AtomicBinOp, AtomicOrdering, BasicBlockRef, ExecutionEngineRef};
use super::{Bool, BuilderRef, ContextRef, MemoryBufferRef, ModuleRef};
use super::{ObjectFileRef, Opcode, PassManagerRef, PassManagerBuilderRef};
use super::{SectionIteratorRef, TargetDataRef, TypeKind, TypeRef, UseRef};
use super::{ValueRef,PassRef};
use super::{ValueRef, PassRef};
use super::debuginfo::*;
use core::libc::{c_char, c_int, c_longlong, c_ushort, c_uint, c_ulonglong};
#[link_args = "-Lrustllvm -lrustllvm"]
@ -929,6 +966,12 @@ pub mod llvm {
#[fast_ffi]
pub unsafe fn LLVMDeleteBasicBlock(BB: BasicBlockRef);
#[fast_ffi]
pub unsafe fn LLVMMoveBasicBlockAfter(BB: BasicBlockRef, MoveAfter: BasicBlockRef);
#[fast_ffi]
pub unsafe fn LLVMMoveBasicBlockBefore(BB: BasicBlockRef, MoveBefore: BasicBlockRef);
/* Operations on instructions */
#[fast_ffi]
pub unsafe fn LLVMGetInstructionParent(Inst: ValueRef)
@ -1885,6 +1928,164 @@ pub mod llvm {
AlignStack: Bool, Dialect: c_uint)
-> ValueRef;
#[fast_ffi]
pub unsafe fn LLVMDIBuilderCreate(M: ModuleRef) -> DIBuilderRef;
#[fast_ffi]
pub unsafe fn LLVMDIBuilderDispose(Builder: DIBuilderRef);
#[fast_ffi]
pub unsafe fn LLVMDIBuilderFinalize(Builder: DIBuilderRef);
#[fast_ffi]
pub unsafe fn LLVMDIBuilderCreateCompileUnit(
Builder: DIBuilderRef,
Lang: c_uint,
File: *c_char,
Dir: *c_char,
Producer: *c_char,
isOptimized: bool,
Flags: *c_char,
RuntimeVer: c_uint,
SplitName: *c_char);
#[fast_ffi]
pub unsafe fn LLVMDIBuilderCreateFile(
Builder: DIBuilderRef,
Filename: *c_char,
Directory: *c_char) -> DIFile;
#[fast_ffi]
pub unsafe fn LLVMDIBuilderCreateSubroutineType(
Builder: DIBuilderRef,
File: DIFile,
ParameterTypes: DIArray) -> DICompositeType;
#[fast_ffi]
pub unsafe fn LLVMDIBuilderCreateFunction(
Builder: DIBuilderRef,
Scope: DIDescriptor,
Name: *c_char,
LinkageName: *c_char,
File: DIFile,
LineNo: c_uint,
Ty: DIType,
isLocalToUnit: bool,
isDefinition: bool,
ScopeLine: c_uint,
Flags: c_uint,
isOptimized: bool,
Fn: ValueRef,
TParam: ValueRef,
Decl: ValueRef) -> DISubprogram;
#[fast_ffi]
pub unsafe fn LLVMDIBuilderCreateBasicType(
Builder: DIBuilderRef,
Name: *c_char,
SizeInBits: c_ulonglong,
AlignInBits: c_ulonglong,
Encoding: c_uint) -> DIBasicType;
#[fast_ffi]
pub unsafe fn LLVMDIBuilderCreatePointerType(
Builder: DIBuilderRef,
PointeeTy: DIType,
SizeInBits: c_ulonglong,
AlignInBits: c_ulonglong,
Name: *c_char) -> DIDerivedType;
#[fast_ffi]
pub unsafe fn LLVMDIBuilderCreateStructType(
Builder: DIBuilderRef,
Scope: DIDescriptor,
Name: *c_char,
File: DIFile,
LineNumber: c_uint,
SizeInBits: c_ulonglong,
AlignInBits: c_ulonglong,
Flags: c_uint,
DerivedFrom: DIType,
Elements: DIArray,
RunTimeLang: c_uint,
VTableHolder: ValueRef) -> DICompositeType;
#[fast_ffi]
pub unsafe fn LLVMDIBuilderCreateMemberType(
Builder: DIBuilderRef,
Scope: DIDescriptor,
Name: *c_char,
File: DIFile,
LineNo: c_uint,
SizeInBits: c_ulonglong,
AlignInBits: c_ulonglong,
OffsetInBits: c_ulonglong,
Flags: c_uint,
Ty: DIType) -> DIDerivedType;
#[fast_ffi]
pub unsafe fn LLVMDIBuilderCreateLexicalBlock(
Builder: DIBuilderRef,
Scope: DIDescriptor,
File: DIFile,
Line: c_uint,
Col: c_uint) -> DILexicalBlock;
#[fast_ffi]
pub unsafe fn LLVMDIBuilderCreateLocalVariable(
Builder: DIBuilderRef,
Tag: c_uint,
Scope: DIDescriptor,
Name: *c_char,
File: DIFile,
LineNo: c_uint,
Ty: DIType,
AlwaysPreserve: bool,
Flags: c_uint,
ArgNo: c_uint) -> DIVariable;
#[fast_ffi]
pub unsafe fn LLVMDIBuilderCreateArrayType(
Builder: DIBuilderRef,
Size: c_ulonglong,
AlignInBits: c_ulonglong,
Ty: DIType,
Subscripts: DIArray) -> DIType;
#[fast_ffi]
pub unsafe fn LLVMDIBuilderCreateVectorType(
Builder: DIBuilderRef,
Size: c_ulonglong,
AlignInBits: c_ulonglong,
Ty: DIType,
Subscripts: DIArray) -> DIType;
#[fast_ffi]
pub unsafe fn LLVMDIBuilderGetOrCreateSubrange(
Builder: DIBuilderRef,
Lo: c_longlong,
Count: c_longlong) -> DISubrange;
#[fast_ffi]
pub unsafe fn LLVMDIBuilderGetOrCreateArray(
Builder: DIBuilderRef,
Ptr: *DIDescriptor,
Count: c_uint) -> DIArray;
#[fast_ffi]
pub unsafe fn LLVMDIBuilderInsertDeclareAtEnd(
Builder: DIBuilderRef,
Val: ValueRef,
VarInfo: DIVariable,
InsertAtEnd: BasicBlockRef) -> ValueRef;
#[fast_ffi]
pub unsafe fn LLVMDIBuilderInsertDeclareBefore(
Builder: DIBuilderRef,
Val: ValueRef,
VarInfo: DIVariable,
InsertBefore: ValueRef) -> ValueRef;
}
}

View file

@ -1908,6 +1908,12 @@ pub fn trans_closure(ccx: @mut CrateContext,
finish(bcx);
cleanup_and_Br(bcx, bcx_top, fcx.llreturn);
// Put return block after all other blocks.
// This somewhat improves single-stepping experience in debugger.
unsafe {
llvm::LLVMMoveBasicBlockAfter(fcx.llreturn, bcx.llbb);
}
// Insert the mandatory first few basic blocks before lltop.
finish_fn(fcx, lltop);
}
@ -3102,6 +3108,9 @@ pub fn trans_crate(sess: session::Session,
fill_crate_map(ccx, ccx.crate_map);
glue::emit_tydescs(ccx);
write_abi_version(ccx);
if ccx.sess.opts.debuginfo {
debuginfo::finalize(ccx);
}
// Translate the metadata.
write_metadata(ccx, crate);

View file

@ -148,7 +148,7 @@ impl CrateContext {
lib::llvm::associate_type(tn, @"tydesc", tydesc_type);
let crate_map = decl_crate_map(sess, link_meta, llmod);
let dbg_cx = if sess.opts.debuginfo {
Some(debuginfo::mk_ctxt(name.to_owned()))
Some(debuginfo::DebugContext::new(llmod, name.to_owned()))
} else {
None
};

File diff suppressed because it is too large Load diff

View file

@ -560,3 +560,228 @@ extern "C" bool LLVMRustStartMultithreading() {
assert(lock.release());
return ret;
}
typedef DIBuilder* DIBuilderRef;
template<typename DIT>
DIT unwrapDI(LLVMValueRef ref) {
return DIT(ref ? unwrap<MDNode>(ref) : NULL);
}
extern "C" DIBuilderRef LLVMDIBuilderCreate(LLVMModuleRef M) {
return new DIBuilder(*unwrap(M));
}
extern "C" void LLVMDIBuilderDispose(DIBuilderRef Builder) {
delete Builder;
}
extern "C" void LLVMDIBuilderFinalize(DIBuilderRef Builder) {
Builder->finalize();
}
extern "C" void LLVMDIBuilderCreateCompileUnit(
DIBuilderRef Builder,
unsigned Lang,
const char* File,
const char* Dir,
const char* Producer,
bool isOptimized,
const char* Flags,
unsigned RuntimeVer,
const char* SplitName) {
Builder->createCompileUnit(Lang, File, Dir, Producer, isOptimized,
Flags, RuntimeVer, SplitName);
}
extern "C" LLVMValueRef LLVMDIBuilderCreateFile(
DIBuilderRef Builder,
const char* Filename,
const char* Directory) {
return wrap(Builder->createFile(Filename, Directory));
}
extern "C" LLVMValueRef LLVMDIBuilderCreateSubroutineType(
DIBuilderRef Builder,
LLVMValueRef File,
LLVMValueRef ParameterTypes) {
return wrap(Builder->createSubroutineType(
unwrapDI<DIFile>(File),
unwrapDI<DIArray>(ParameterTypes)));
}
extern "C" LLVMValueRef LLVMDIBuilderCreateFunction(
DIBuilderRef Builder,
LLVMValueRef Scope,
const char* Name,
const char* LinkageName,
LLVMValueRef File,
unsigned LineNo,
LLVMValueRef Ty,
bool isLocalToUnit,
bool isDefinition,
unsigned ScopeLine,
unsigned Flags,
bool isOptimized,
LLVMValueRef Fn,
LLVMValueRef TParam,
LLVMValueRef Decl) {
return wrap(Builder->createFunction(
unwrapDI<DIScope>(Scope), Name, LinkageName,
unwrapDI<DIFile>(File), LineNo,
unwrapDI<DIType>(Ty), isLocalToUnit, isDefinition, ScopeLine,
Flags, isOptimized,
unwrap<Function>(Fn),
unwrapDI<MDNode*>(TParam),
unwrapDI<MDNode*>(Decl)));
}
extern "C" LLVMValueRef LLVMDIBuilderCreateBasicType(
DIBuilderRef Builder,
const char* Name,
uint64_t SizeInBits,
uint64_t AlignInBits,
unsigned Encoding) {
return wrap(Builder->createBasicType(
Name, SizeInBits,
AlignInBits, Encoding));
}
extern "C" LLVMValueRef LLVMDIBuilderCreatePointerType(
DIBuilderRef Builder,
LLVMValueRef PointeeTy,
uint64_t SizeInBits,
uint64_t AlignInBits,
const char* Name) {
return wrap(Builder->createPointerType(
unwrapDI<DIType>(PointeeTy), SizeInBits, AlignInBits, Name));
}
extern "C" LLVMValueRef LLVMDIBuilderCreateStructType(
DIBuilderRef Builder,
LLVMValueRef Scope,
const char* Name,
LLVMValueRef File,
unsigned LineNumber,
uint64_t SizeInBits,
uint64_t AlignInBits,
unsigned Flags,
LLVMValueRef DerivedFrom,
LLVMValueRef Elements,
unsigned RunTimeLang,
LLVMValueRef VTableHolder) {
return wrap(Builder->createStructType(
unwrapDI<DIDescriptor>(Scope), Name,
unwrapDI<DIFile>(File), LineNumber,
SizeInBits, AlignInBits, Flags,
unwrapDI<DIType>(DerivedFrom),
unwrapDI<DIArray>(Elements), RunTimeLang,
unwrapDI<MDNode*>(VTableHolder)));
}
extern "C" LLVMValueRef LLVMDIBuilderCreateMemberType(
DIBuilderRef Builder,
LLVMValueRef Scope,
const char* Name,
LLVMValueRef File,
unsigned LineNo,
uint64_t SizeInBits,
uint64_t AlignInBits,
uint64_t OffsetInBits,
unsigned Flags,
LLVMValueRef Ty) {
return wrap(Builder->createMemberType(
unwrapDI<DIDescriptor>(Scope), Name,
unwrapDI<DIFile>(File), LineNo,
SizeInBits, AlignInBits, OffsetInBits, Flags,
unwrapDI<DIType>(Ty)));
}
extern "C" LLVMValueRef LLVMDIBuilderCreateLexicalBlock(
DIBuilderRef Builder,
LLVMValueRef Scope,
LLVMValueRef File,
unsigned Line,
unsigned Col) {
return wrap(Builder->createLexicalBlock(
unwrapDI<DIDescriptor>(Scope),
unwrapDI<DIFile>(File), Line, Col));
}
extern "C" LLVMValueRef LLVMDIBuilderCreateLocalVariable(
DIBuilderRef Builder,
unsigned Tag,
LLVMValueRef Scope,
const char* Name,
LLVMValueRef File,
unsigned LineNo,
LLVMValueRef Ty,
bool AlwaysPreserve,
unsigned Flags,
unsigned ArgNo) {
return wrap(Builder->createLocalVariable(Tag,
unwrapDI<DIDescriptor>(Scope), Name,
unwrapDI<DIFile>(File),
LineNo,
unwrapDI<DIType>(Ty), AlwaysPreserve, Flags, ArgNo));
}
extern "C" LLVMValueRef LLVMDIBuilderCreateArrayType(
DIBuilderRef Builder,
uint64_t Size,
uint64_t AlignInBits,
LLVMValueRef Ty,
LLVMValueRef Subscripts) {
return wrap(Builder->createArrayType(Size, AlignInBits,
unwrapDI<DIType>(Ty),
unwrapDI<DIArray>(Subscripts)));
}
extern "C" LLVMValueRef LLVMDIBuilderCreateVectorType(
DIBuilderRef Builder,
uint64_t Size,
uint64_t AlignInBits,
LLVMValueRef Ty,
LLVMValueRef Subscripts) {
return wrap(Builder->createVectorType(Size, AlignInBits,
unwrapDI<DIType>(Ty),
unwrapDI<DIArray>(Subscripts)));
}
extern "C" LLVMValueRef LLVMDIBuilderGetOrCreateSubrange(
DIBuilderRef Builder,
int64_t Lo,
int64_t Count) {
return wrap(Builder->getOrCreateSubrange(Lo, Count));
}
extern "C" LLVMValueRef LLVMDIBuilderGetOrCreateArray(
DIBuilderRef Builder,
LLVMValueRef* Ptr,
unsigned Count) {
return wrap(Builder->getOrCreateArray(
ArrayRef<Value*>(reinterpret_cast<Value**>(Ptr), Count)));
}
extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(
DIBuilderRef Builder,
LLVMValueRef Val,
LLVMValueRef VarInfo,
LLVMBasicBlockRef InsertAtEnd) {
return wrap(Builder->insertDeclare(
unwrap(Val),
unwrapDI<DIVariable>(VarInfo),
unwrap(InsertAtEnd)));
}
extern "C" LLVMValueRef LLVMDIBuilderInsertDeclareBefore(
DIBuilderRef Builder,
LLVMValueRef Val,
LLVMValueRef VarInfo,
LLVMValueRef InsertBefore) {
return wrap(Builder->insertDeclare(
unwrap(Val),
unwrapDI<DIVariable>(VarInfo),
unwrap<Instruction>(InsertBefore)));
}

View file

@ -588,3 +588,22 @@ LLVMInlineAsm
LLVMInitializePasses
LLVMAddPass
LLVMCreatePass
LLVMDIBuilderCreate
LLVMDIBuilderDispose
LLVMDIBuilderFinalize
LLVMDIBuilderCreateCompileUnit
LLVMDIBuilderCreateLocalVariable
LLVMDIBuilderCreateFunction
LLVMDIBuilderCreateFile
LLVMDIBuilderCreateLexicalBlock
LLVMDIBuilderCreateBasicType
LLVMDIBuilderCreatePointerType
LLVMDIBuilderCreateMemberType
LLVMDIBuilderCreateStructType
LLVMDIBuilderGetOrCreateSubrange
LLVMDIBuilderCreateArrayType
LLVMDIBuilderCreateVectorType
LLVMDIBuilderCreateSubroutineType
LLVMDIBuilderGetOrCreateArray
LLVMDIBuilderInsertDeclareAtEnd
LLVMDIBuilderInsertDeclareBefore

View file

@ -43,6 +43,8 @@
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Instrumentation.h"
#include "llvm/Transforms/Vectorize.h"
#include "llvm/DebugInfo.h"
#include "llvm/DIBuilder.h"
#include "llvm-c/Core.h"
#include "llvm-c/BitReader.h"
#include "llvm-c/ExecutionEngine.h"

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// xfail-test
// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
// Caveats - gdb prints any 8-bit value (meaning rust i8 and u8 values)
// as its numerical value along with its associated ASCII char, there
@ -17,8 +17,9 @@
// its numerical value.
// compile-flags:-Z extra-debug-info
// debugger:break 67
// debugger:break _zzz
// debugger:run
// debugger:finish
// debugger:print b
// check:$1 = false
// debugger:print i
@ -66,5 +67,7 @@ fn main() {
let f: float = 1.5;
let f32: f32 = 2.5;
let f64: f64 = 3.5;
let _z = ();
_zzz();
}
fn _zzz() {()}

View file

@ -8,12 +8,13 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// xfail-test
// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
// compile-flags:-Z extra-debug-info
// debugger:set print pretty off
// debugger:break 29
// debugger:break _zzz
// debugger:run
// debugger:finish
// debugger:print a->boxed
// check:$1 = 1
// debugger:print b->boxed
@ -28,5 +29,7 @@ fn main() {
let b = ~(2, 3.5);
let c = @4;
let d = @false;
let _z = 0;
_zzz();
}
fn _zzz() {()}

View file

@ -8,12 +8,13 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// xfail-test
// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
// compile-flags:-Z extra-debug-info
// debugger:set print pretty off
// debugger:break 29
// debugger:break _zzz
// debugger:run
// debugger:finish
// debugger:print pair
// check:$1 = {x = 1, y = 2}
// debugger:print pair.x
@ -28,5 +29,7 @@ struct Pair {
fn main() {
let pair = Pair { x: 1, y: 2 };
let _z = ();
_zzz();
}
fn _zzz() {()}

View file

@ -8,16 +8,19 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// xfail-test
// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
// compile-flags:-Z extra-debug-info
// debugger:set print pretty off
// debugger:break 20
// debugger:break _zzz
// debugger:run
// debugger:finish
// debugger:print t
// check:$1 = {4, 5.5, true}
fn main() {
let t = (4, 5.5, true);
let _z = ();
_zzz();
}
fn _zzz() {()}

View file

@ -8,12 +8,13 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// xfail-test
// xfail-win32 Broken because of LLVM bug: http://llvm.org/bugs/show_bug.cgi?id=16249
// compile-flags:-Z extra-debug-info
// debugger:set print pretty off
// debugger:break 29
// debugger:break _zzz
// debugger:run
// debugger:finish
// debugger:print a
// check:$1 = {1, 2, 3}
// debugger:print b.vec[0]
@ -28,5 +29,7 @@ fn main() {
let b = &[4, 5, 6];
let c = @[7, 8, 9];
let d = ~[10, 11, 12];
let _z = 0;
_zzz();
}
fn _zzz() {()}