diff options
author | Sanjiv Gupta <sanjiv.gupta@microchip.com> | 2008-05-08 08:54:20 +0000 |
---|---|---|
committer | Sanjiv Gupta <sanjiv.gupta@microchip.com> | 2008-05-08 08:54:20 +0000 |
commit | e8b9f5b8ea60983c4a74cb8b63879616b914b65a (patch) | |
tree | 12fefe9c0746176f5f7dae2f26a3a6c9aa4bbfe8 /lib/CodeGen/CGDebugInfo.cpp | |
parent | 56cf96b3ea9a0027b29e11c47b90719525c13bc6 (diff) |
Added -g command line options to clang for generating source level debug information. This patch currently enables generation of line number debug information (stoppoints) and region begin/end debug information. The new files CGDebugInfo.h and CGDebugInfo.cpp implements the debug info manager class CGDebugInfo.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50848 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGDebugInfo.cpp')
-rw-r--r-- | lib/CodeGen/CGDebugInfo.cpp | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp new file mode 100644 index 0000000000..e0c76d32fb --- /dev/null +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -0,0 +1,171 @@ +//===--- CGDebugInfo.cpp - Emit Debug Information for a Module ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This coordinates the debug information generation while generating code. +// +//===----------------------------------------------------------------------===// + +#include "CGDebugInfo.h" +#include "CodeGenModule.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/Module.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/IRBuilder.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Basic/FileManager.h" +#include "clang/AST/ASTContext.h" +using namespace clang; +using namespace clang::CodeGen; + +CGDebugInfo::CGDebugInfo(CodeGenModule *m) +: M(m) +, CurLoc() +, PrevLoc() +, CompileUnitCache() +, StopPointFn(NULL) +, RegionStartFn(NULL) +, RegionEndFn(NULL) +, RegionStack() +{ + SR = new llvm::DISerializer(); + SR->setModule (&M->getModule()); +} + +CGDebugInfo::~CGDebugInfo() +{ + delete SR; +} + + +/// getCastValueFor - Return a llvm representation for a given debug information +/// descriptor cast to an empty struct pointer. +llvm::Value *CGDebugInfo::getCastValueFor(llvm::DebugInfoDesc *DD) { + return llvm::ConstantExpr::getBitCast(SR->Serialize(DD), + SR->getEmptyStructPtrType()); +} + +/// getOrCreateCompileUnit - Get the compile unit from the cache or create a new +/// one if necessary. +llvm::CompileUnitDesc +*CGDebugInfo::getOrCreateCompileUnit(const SourceLocation Loc) { + + // See if this compile unit has been used before. + llvm::CompileUnitDesc *&Slot = CompileUnitCache[Loc.getFileID()]; + if (Slot) return Slot; + + // Create new compile unit. + // FIXME: Where to free these? + // One way is to iterate over the CompileUnitCache in ~CGDebugInfo. + llvm::CompileUnitDesc *Unit = new llvm::CompileUnitDesc(); + + // Make sure we have an anchor. + if (!CompileUnitAnchor) { + CompileUnitAnchor = new llvm::AnchorDesc(Unit); + } + + // 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(); + + Unit->setAnchor(CompileUnitAnchor); + Unit->setFileName(FileName); + Unit->setDirectory(DirName); + + // Set up producer name. + // FIXME: Do not know how to get clang version yet. + Unit->setProducer("clang"); + + // Set up Language number. + // FIXME: Handle other languages as well. + Unit->setLanguage(llvm::dwarf::DW_LANG_C89); + + // Update cache. + Slot = Unit; + + return Unit; +} + + +void +CGDebugInfo::EmitStopPoint(llvm::Function *Fn, llvm::IRBuilder &Builder) { + + // Don't bother if things are the same as last time. + SourceManager &SM = M->getContext().getSourceManager(); + if (CurLoc == PrevLoc + || (SM.getLineNumber(CurLoc) == SM.getLineNumber(PrevLoc) + && SM.isFromSameFile(CurLoc, PrevLoc))) + return; + if (CurLoc.isInvalid()) return; + + // Update last state. + PrevLoc = CurLoc; + + // Get the appropriate compile unit. + llvm::CompileUnitDesc *Unit = getOrCreateCompileUnit(CurLoc); + + // Lazily construct llvm.dbg.stoppoint function. + if (!StopPointFn) + StopPointFn = llvm::Intrinsic::getDeclaration(&M->getModule(), + llvm::Intrinsic::dbg_stoppoint); + + uint64_t CurLineNo = SM.getLogicalLineNumber(CurLoc); + uint64_t ColumnNo = SM.getLogicalColumnNumber(CurLoc); + + // Invoke llvm.dbg.stoppoint + Builder.CreateCall3(StopPointFn, + llvm::ConstantInt::get(llvm::Type::Int32Ty, CurLineNo), + llvm::ConstantInt::get(llvm::Type::Int32Ty, ColumnNo), + getCastValueFor(Unit), ""); +} + +/// EmitRegionStart- Constructs the debug code for entering a declarative +/// region - "llvm.dbg.region.start.". +void CGDebugInfo::EmitRegionStart(llvm::Function *Fn, llvm::IRBuilder &Builder) +{ + llvm::BlockDesc *Block = new llvm::BlockDesc(); + if (RegionStack.size() > 0) + Block->setContext(RegionStack.back()); + RegionStack.push_back(Block); + + // 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), ""); +} + +/// EmitRegionEnd - Constructs the debug code for exiting a declarative +/// region - "llvm.dbg.region.end." +void CGDebugInfo::EmitRegionEnd(llvm::Function *Fn, llvm::IRBuilder &Builder) +{ + // Lazily construct llvm.dbg.region.end function. + if (!RegionEndFn) + RegionEndFn =llvm::Intrinsic::getDeclaration(&M->getModule(), + llvm::Intrinsic::dbg_region_end); + + // Provide an region stop point. + 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? +} + |