aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGDebugInfo.cpp
diff options
context:
space:
mode:
authorSanjiv Gupta <sanjiv.gupta@microchip.com>2008-05-08 08:54:20 +0000
committerSanjiv Gupta <sanjiv.gupta@microchip.com>2008-05-08 08:54:20 +0000
commite8b9f5b8ea60983c4a74cb8b63879616b914b65a (patch)
tree12fefe9c0746176f5f7dae2f26a3a6c9aa4bbfe8 /lib/CodeGen/CGDebugInfo.cpp
parent56cf96b3ea9a0027b29e11c47b90719525c13bc6 (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.cpp171
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?
+}
+