forked from OSchip/llvm-project
Make debugging information usable. This is barebones, but it makes -g
actually work (instead of crashing llc), and there's enough info emitted to get line number information in gdb. This should hopefully be helpful for debugging non-working programs. I got rid of the begin/endregion calls because the implementation wasn't working; someone who knows the debugging info a bit better might try to add it. I really have no clue how a compiler is supposed to emit them. This commit shouldn't have any effect without -g. llvm-svn: 51404
This commit is contained in:
parent
c7460b1011
commit
1763075b9c
|
@ -36,9 +36,12 @@ CGDebugInfo::CGDebugInfo(CodeGenModule *m)
|
|||
, PrevLoc()
|
||||
, CompileUnitCache()
|
||||
, StopPointFn(NULL)
|
||||
, CompileUnitAnchor(NULL)
|
||||
, SubProgramAnchor(NULL)
|
||||
, RegionStartFn(NULL)
|
||||
, RegionEndFn(NULL)
|
||||
, RegionStack()
|
||||
, FuncStartFn(NULL)
|
||||
, CurFuncDesc(NULL)
|
||||
{
|
||||
SR = new llvm::DISerializer();
|
||||
SR->setModule (&M->getModule());
|
||||
|
@ -47,6 +50,19 @@ CGDebugInfo::CGDebugInfo(CodeGenModule *m)
|
|||
CGDebugInfo::~CGDebugInfo()
|
||||
{
|
||||
delete SR;
|
||||
// Clean up allocated debug info; we can't do this until after the
|
||||
// serializer is destroyed because it caches pointers to
|
||||
// the debug info
|
||||
delete CompileUnitAnchor;
|
||||
delete SubProgramAnchor;
|
||||
// Clean up compile unit descriptions
|
||||
std::map<unsigned, llvm::CompileUnitDesc *>::iterator MI;
|
||||
for (MI = CompileUnitCache.begin(); MI != CompileUnitCache.end(); ++MI)
|
||||
delete MI->second;
|
||||
// Clean up misc allocations
|
||||
std::vector<llvm::DebugInfoDesc*>::iterator VI;
|
||||
for (VI = DebugAllocationList.begin(); VI != DebugAllocationList.end(); ++VI)
|
||||
delete *VI;
|
||||
}
|
||||
|
||||
|
||||
|
@ -79,8 +95,14 @@ llvm::CompileUnitDesc
|
|||
// Get source file information.
|
||||
SourceManager &SM = M->getContext().getSourceManager();
|
||||
const FileEntry *FE = SM.getFileEntryForLoc(Loc);
|
||||
const char *FileName = FE->getName();
|
||||
const char *DirName = FE->getDir()->getName();
|
||||
const char *FileName, *DirName;
|
||||
if (FE) {
|
||||
FileName = FE->getName();
|
||||
DirName = FE->getDir()->getName();
|
||||
} else {
|
||||
FileName = SM.getSourceName(Loc);
|
||||
DirName = "";
|
||||
}
|
||||
|
||||
Unit->setAnchor(CompileUnitAnchor);
|
||||
Unit->setFileName(FileName);
|
||||
|
@ -103,6 +125,7 @@ llvm::CompileUnitDesc
|
|||
|
||||
void
|
||||
CGDebugInfo::EmitStopPoint(llvm::Function *Fn, llvm::IRBuilder &Builder) {
|
||||
if (CurLoc.isInvalid() || CurLoc.isMacroID()) return;
|
||||
|
||||
// Don't bother if things are the same as last time.
|
||||
SourceManager &SM = M->getContext().getSourceManager();
|
||||
|
@ -110,7 +133,6 @@ CGDebugInfo::EmitStopPoint(llvm::Function *Fn, llvm::IRBuilder &Builder) {
|
|||
|| (SM.getLineNumber(CurLoc) == SM.getLineNumber(PrevLoc)
|
||||
&& SM.isFromSameFile(CurLoc, PrevLoc)))
|
||||
return;
|
||||
if (CurLoc.isInvalid()) return;
|
||||
|
||||
// Update last state.
|
||||
PrevLoc = CurLoc;
|
||||
|
@ -135,25 +157,35 @@ CGDebugInfo::EmitStopPoint(llvm::Function *Fn, llvm::IRBuilder &Builder) {
|
|||
|
||||
/// EmitRegionStart- Constructs the debug code for entering a declarative
|
||||
/// region - "llvm.dbg.region.start.".
|
||||
void CGDebugInfo::EmitRegionStart(llvm::Function *Fn, llvm::IRBuilder &Builder)
|
||||
void CGDebugInfo::EmitFunctionStart(llvm::Function *Fn, llvm::IRBuilder &Builder)
|
||||
{
|
||||
llvm::BlockDesc *Block = new llvm::BlockDesc();
|
||||
if (RegionStack.size() > 0)
|
||||
Block->setContext(RegionStack.back());
|
||||
RegionStack.push_back(Block);
|
||||
// Get the appropriate compile unit.
|
||||
llvm::CompileUnitDesc *Unit = getOrCreateCompileUnit(CurLoc);
|
||||
|
||||
// Lazily construct llvm.dbg.region.start function.
|
||||
if (!RegionStartFn)
|
||||
RegionStartFn = llvm::Intrinsic::getDeclaration(&M->getModule(),
|
||||
llvm::Intrinsic::dbg_region_start);
|
||||
|
||||
// Call llvm.dbg.func.start.
|
||||
Builder.CreateCall(RegionStartFn, getCastValueFor(Block), "");
|
||||
llvm::SubprogramDesc* Block = new llvm::SubprogramDesc;
|
||||
DebugAllocationList.push_back(Block);
|
||||
Block->setFile(Unit);
|
||||
Block->setContext(Unit);
|
||||
if (!SubProgramAnchor) {
|
||||
SubProgramAnchor = new llvm::AnchorDesc(Block);
|
||||
SR->Serialize(SubProgramAnchor);
|
||||
}
|
||||
Block->setAnchor(SubProgramAnchor);
|
||||
Block->setName(Fn->getName());
|
||||
Block->setFullName(Fn->getName());
|
||||
Block->setIsDefinition(true);
|
||||
SourceManager &SM = M->getContext().getSourceManager();
|
||||
Block->setLine(SM.getLogicalLineNumber(CurLoc));
|
||||
CurFuncDesc = getCastValueFor(Block);
|
||||
if (!FuncStartFn)
|
||||
FuncStartFn = llvm::Intrinsic::getDeclaration(&M->getModule(),
|
||||
llvm::Intrinsic::dbg_func_start);
|
||||
Builder.CreateCall(FuncStartFn, CurFuncDesc);
|
||||
}
|
||||
|
||||
/// EmitRegionEnd - Constructs the debug code for exiting a declarative
|
||||
/// region - "llvm.dbg.region.end."
|
||||
void CGDebugInfo::EmitRegionEnd(llvm::Function *Fn, llvm::IRBuilder &Builder)
|
||||
void CGDebugInfo::EmitFunctionEnd(llvm::Function *Fn, llvm::IRBuilder &Builder)
|
||||
{
|
||||
// Lazily construct llvm.dbg.region.end function.
|
||||
if (!RegionEndFn)
|
||||
|
@ -164,8 +196,6 @@ void CGDebugInfo::EmitRegionEnd(llvm::Function *Fn, llvm::IRBuilder &Builder)
|
|||
EmitStopPoint(Fn, Builder);
|
||||
|
||||
// Call llvm.dbg.func.end.
|
||||
Builder.CreateCall(RegionEndFn, getCastValueFor(RegionStack.back()), "");
|
||||
RegionStack.pop_back();
|
||||
// FIXME: Free here the memory created for BlockDesc in RegionStart?
|
||||
Builder.CreateCall(RegionEndFn, CurFuncDesc, "");
|
||||
}
|
||||
|
||||
|
|
|
@ -45,12 +45,23 @@ private:
|
|||
|
||||
/// CompileUnitCache - Cache of previously constructed CompileUnits.
|
||||
std::map<unsigned, llvm::CompileUnitDesc *> CompileUnitCache;
|
||||
std::vector<llvm::DebugInfoDesc*> DebugAllocationList;
|
||||
|
||||
llvm::Function *StopPointFn;
|
||||
llvm::AnchorDesc *CompileUnitAnchor;
|
||||
llvm::AnchorDesc *SubProgramAnchor;
|
||||
llvm::Function *RegionStartFn;
|
||||
llvm::Function *RegionEndFn;
|
||||
std::vector<llvm::DebugInfoDesc *> RegionStack;
|
||||
llvm::Function *FuncStartFn;
|
||||
llvm::Value *CurFuncDesc;
|
||||
|
||||
/// getOrCreateCompileUnit - Get the compile unit from the cache or create a
|
||||
/// new one if necessary.
|
||||
llvm::CompileUnitDesc *getOrCreateCompileUnit(SourceLocation loc);
|
||||
|
||||
/// getCastValueFor - Return a llvm representation for a given debug
|
||||
/// information descriptor cast to an empty struct pointer.
|
||||
llvm::Value *getCastValueFor(llvm::DebugInfoDesc *DD);
|
||||
|
||||
public:
|
||||
CGDebugInfo(CodeGenModule *m);
|
||||
|
@ -62,21 +73,13 @@ public:
|
|||
/// source line.
|
||||
void EmitStopPoint(llvm::Function *Fn, llvm::IRBuilder &Builder);
|
||||
|
||||
/// EmitRegionStart - Emit a call to llvm.dbg.region.start to indicate start
|
||||
/// EmitFunctionStart - Emit a call to llvm.dbg.func.start to indicate start
|
||||
/// of a new block.
|
||||
void EmitRegionStart(llvm::Function *Fn, llvm::IRBuilder &Builder);
|
||||
void EmitFunctionStart(llvm::Function *Fn, llvm::IRBuilder &Builder);
|
||||
|
||||
/// EmitRegionEnd - Emit call to llvm.dbg.region.end to indicate end of a
|
||||
/// EmitFunctionEnd - Emit call to llvm.dbg.region.end to indicate end of a
|
||||
/// block.
|
||||
void EmitRegionEnd(llvm::Function *Fn, llvm::IRBuilder &Builder);
|
||||
|
||||
/// getOrCreateCompileUnit - Get the compile unit from the cache or create a
|
||||
/// new one if necessary.
|
||||
llvm::CompileUnitDesc *getOrCreateCompileUnit(SourceLocation loc);
|
||||
|
||||
/// getCastValueFor - Return a llvm representation for a given debug
|
||||
/// information descriptor cast to an empty struct pointer.
|
||||
llvm::Value *getCastValueFor(llvm::DebugInfoDesc *DD);
|
||||
void EmitFunctionEnd(llvm::Function *Fn, llvm::IRBuilder &Builder);
|
||||
};
|
||||
} // namespace CodeGen
|
||||
} // namespace clang
|
||||
|
|
|
@ -87,26 +87,11 @@ RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast,
|
|||
llvm::Value *AggLoc, bool isAggVol) {
|
||||
// FIXME: handle vla's etc.
|
||||
if (S.body_empty() || !isa<Expr>(S.body_back())) GetLast = false;
|
||||
|
||||
CGDebugInfo *DI = CGM.getDebugInfo();
|
||||
if (DI) {
|
||||
if (S.getLBracLoc().isValid()) {
|
||||
DI->setLocation(S.getLBracLoc());
|
||||
}
|
||||
DI->EmitRegionStart(CurFn, Builder);
|
||||
}
|
||||
|
||||
for (CompoundStmt::const_body_iterator I = S.body_begin(),
|
||||
E = S.body_end()-GetLast; I != E; ++I)
|
||||
EmitStmt(*I);
|
||||
|
||||
if (DI) {
|
||||
if (S.getRBracLoc().isValid()) {
|
||||
DI->setLocation(S.getRBracLoc());
|
||||
}
|
||||
DI->EmitRegionEnd(CurFn, Builder);
|
||||
}
|
||||
|
||||
if (!GetLast)
|
||||
return RValue::get(0);
|
||||
|
||||
|
@ -383,6 +368,15 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
|
|||
EmitAggExpr(RV, SRetPtr, false);
|
||||
}
|
||||
|
||||
CGDebugInfo *DI = CGM.getDebugInfo();
|
||||
if (DI) {
|
||||
CompoundStmt* body = cast<CompoundStmt>(CurFuncDecl->getBody());
|
||||
if (body->getRBracLoc().isValid()) {
|
||||
DI->setLocation(body->getRBracLoc());
|
||||
}
|
||||
DI->EmitFunctionEnd(CurFn, Builder);
|
||||
}
|
||||
|
||||
if (RetValue) {
|
||||
Builder.CreateRet(RetValue);
|
||||
} else {
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "CodeGenFunction.h"
|
||||
#include "CodeGenModule.h"
|
||||
#include "CGDebugInfo.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "clang/AST/AST.h"
|
||||
#include "llvm/CallingConv.h"
|
||||
|
@ -197,7 +198,16 @@ void CodeGenFunction::GenerateCode(const FunctionDecl *FD) {
|
|||
EntryBB);
|
||||
|
||||
Builder.SetInsertPoint(EntryBB);
|
||||
|
||||
|
||||
CGDebugInfo *DI = CGM.getDebugInfo();
|
||||
if (DI) {
|
||||
CompoundStmt* body = cast<CompoundStmt>(CurFuncDecl->getBody());
|
||||
if (body->getLBracLoc().isValid()) {
|
||||
DI->setLocation(body->getLBracLoc());
|
||||
}
|
||||
DI->EmitFunctionStart(CurFn, Builder);
|
||||
}
|
||||
|
||||
// Emit allocs for param decls. Give the LLVM Argument nodes names.
|
||||
llvm::Function::arg_iterator AI = CurFn->arg_begin();
|
||||
|
||||
|
@ -221,6 +231,15 @@ void CodeGenFunction::GenerateCode(const FunctionDecl *FD) {
|
|||
if (isDummyBlock(BB))
|
||||
BB->eraseFromParent();
|
||||
else {
|
||||
CGDebugInfo *DI = CGM.getDebugInfo();
|
||||
if (DI) {
|
||||
CompoundStmt* body = cast<CompoundStmt>(CurFuncDecl->getBody());
|
||||
if (body->getRBracLoc().isValid()) {
|
||||
DI->setLocation(body->getRBracLoc());
|
||||
}
|
||||
DI->EmitFunctionEnd(CurFn, Builder);
|
||||
}
|
||||
|
||||
// FIXME: if this is C++ main, this should return 0.
|
||||
if (CurFn->getReturnType() == llvm::Type::VoidTy)
|
||||
Builder.CreateRetVoid();
|
||||
|
|
Loading…
Reference in New Issue