From 1763075b9c4709b311b99b611694c58513d9dcd8 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Thu, 22 May 2008 01:40:10 +0000 Subject: [PATCH] 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 --- clang/lib/CodeGen/CGDebugInfo.cpp | 70 +++++++++++++++++++-------- clang/lib/CodeGen/CGDebugInfo.h | 29 ++++++----- clang/lib/CodeGen/CGStmt.cpp | 24 ++++----- clang/lib/CodeGen/CodeGenFunction.cpp | 21 +++++++- 4 files changed, 95 insertions(+), 49 deletions(-) diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 9cceb5ce0a35..abe1699fe8dc 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -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::iterator MI; + for (MI = CompileUnitCache.begin(); MI != CompileUnitCache.end(); ++MI) + delete MI->second; + // Clean up misc allocations + std::vector::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, ""); } diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index 2097a1d2f06c..ca933021a6dc 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -45,12 +45,23 @@ private: /// CompileUnitCache - Cache of previously constructed CompileUnits. std::map CompileUnitCache; + std::vector DebugAllocationList; llvm::Function *StopPointFn; llvm::AnchorDesc *CompileUnitAnchor; + llvm::AnchorDesc *SubProgramAnchor; llvm::Function *RegionStartFn; llvm::Function *RegionEndFn; - std::vector 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 diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 2e36c5b70458..0148ab0d842a 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -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(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(CurFuncDecl->getBody()); + if (body->getRBracLoc().isValid()) { + DI->setLocation(body->getRBracLoc()); + } + DI->EmitFunctionEnd(CurFn, Builder); + } + if (RetValue) { Builder.CreateRet(RetValue); } else { diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index e4332f6e7fbf..b17572ce478b 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -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(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(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();