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.
llvm-svn: 50848
This commit is contained in:
171
clang/lib/CodeGen/CGDebugInfo.cpp
Normal file
171
clang/lib/CodeGen/CGDebugInfo.cpp
Normal file
@@ -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?
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user