USEDLIBS = clangCodeGen.a clangAnalysis.a clangRewrite.a clangSEMA.a \
clangAST.a clangParse.a clangLex.a clangBasic.a \
LLVMCore.a LLVMSupport.a LLVMSystem.a \
- LLVMBitWriter.a LLVMBitReader.a LLVMTarget.a
+ LLVMBitWriter.a LLVMBitReader.a LLVMCodeGen.a LLVMTarget.a
llvm::cl::value_desc("path"),
llvm::cl::desc("Specify output file (for --serialize, this is a directory)"));
+//===----------------------------------------------------------------------===//
+// Code Generator Options
+//===----------------------------------------------------------------------===//
+static llvm::cl::opt<bool>
+GenerateDebugInfo("g",
+ llvm::cl::desc("Generate source level debug information"));
+
//===----------------------------------------------------------------------===//
// Diagnostic Options
//===----------------------------------------------------------------------===//
case EmitLLVM:
case EmitBC:
DestModule = new llvm::Module(InFile);
- return CreateLLVMCodeGen(Diag, LangOpts, DestModule);
+ return CreateLLVMCodeGen(Diag, LangOpts, DestModule, GenerateDebugInfo);
case SerializeAST:
// FIXME: Allow user to tailor where the file is written.
class ASTConsumer;
ASTConsumer *CreateLLVMCodeGen(Diagnostic &Diags, const LangOptions &Features,
- llvm::Module *&DestModule);
+ llvm::Module *&DestModule,
+ bool GenerateDebugInfo);
}
#endif
--- /dev/null
+//===--- 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?
+}
+
--- /dev/null
+//===--- CGDebugInfo.h - DebugInfo for LLVM CodeGen -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the source level debug info generator for llvm translation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CLANG_CODEGEN_CGDEBUGINFO_H
+#define CLANG_CODEGEN_CGDEBUGINFO_H
+
+#include "clang/Basic/SourceLocation.h"
+#include <map>
+#include <vector>
+
+
+namespace llvm {
+ class Function;
+ class IRBuilder;
+ class DISerializer;
+ class CompileUnitDesc;
+ class BasicBlock;
+ class AnchorDesc;
+ class DebugInfoDesc;
+ class Value;
+}
+
+namespace clang {
+namespace CodeGen {
+ class CodeGenModule;
+
+/// DebugInfo - This class gathers all debug information during compilation and
+/// is responsible for emitting to llvm globals or pass directly to the backend.
+class CGDebugInfo {
+private:
+ CodeGenModule *M;
+ llvm::DISerializer *SR;
+ SourceLocation CurLoc;
+ SourceLocation PrevLoc;
+
+ /// CompileUnitCache - Cache of previously constructed CompileUnits.
+ std::map<unsigned, llvm::CompileUnitDesc *> CompileUnitCache;
+
+ llvm::Function *StopPointFn;
+ llvm::AnchorDesc *CompileUnitAnchor;
+ llvm::Function *RegionStartFn;
+ llvm::Function *RegionEndFn;
+ std::vector<llvm::DebugInfoDesc *> RegionStack;
+
+public:
+ CGDebugInfo(CodeGenModule *m);
+ ~CGDebugInfo();
+
+ void setLocation(SourceLocation loc) { CurLoc = loc; };
+
+ /// EmitStopPoint - Emit a call to llvm.dbg.stoppoint to indicate a change of
+ /// source line.
+ void EmitStopPoint(llvm::Function *Fn, llvm::IRBuilder &Builder);
+
+ /// EmitRegionStart - Emit a call to llvm.dbg.region.start to indicate start
+ /// of a new block.
+ void EmitRegionStart(llvm::Function *Fn, llvm::IRBuilder &Builder);
+
+ /// EmitRegionEnd - 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);
+};
+} // namespace CodeGen
+} // namespace clang
+
+#endif
//
//===----------------------------------------------------------------------===//
+#include "CGDebugInfo.h"
+#include "CodeGenModule.h"
#include "CodeGenFunction.h"
#include "clang/AST/AST.h"
#include "clang/Basic/TargetInfo.h"
void CodeGenFunction::EmitStmt(const Stmt *S) {
assert(S && "Null statement?");
+ // Generate stoppoints if we are emitting debug info.
+ // Beginning of a Compound Statement (e.g. an opening '{') does not produce
+ // executable code. So do not generate a stoppoint for that.
+ CGDebugInfo *DI = CGM.getDebugInfo();
+ if (DI && S->getStmtClass() != Stmt::CompoundStmtClass) {
+ if (S->getLocStart().isValid()) {
+ DI->setLocation(S->getLocStart());
+ }
+
+ DI->EmitStopPoint(CurFn, Builder);
+ }
+
switch (S->getStmtClass()) {
default:
// Must be an expression in a stmt context. Emit the value (to get
// 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);
//
//===----------------------------------------------------------------------===//
+#include "CGDebugInfo.h"
#include "CodeGenModule.h"
#include "CodeGenFunction.h"
#include "clang/AST/ASTContext.h"
CodeGenModule::CodeGenModule(ASTContext &C, const LangOptions &LO,
llvm::Module &M, const llvm::TargetData &TD,
- Diagnostic &diags)
+ Diagnostic &diags, bool GenerateDebugInfo)
: Context(C), Features(LO), TheModule(M), TheTargetData(TD), Diags(diags),
Types(C, M, TD), MemCpyFn(0), MemSetFn(0), CFConstantStringClassRef(0) {
//TODO: Make this selectable at runtime
Runtime = CreateObjCRuntime(M,
getTypes().ConvertType(getContext().IntTy),
getTypes().ConvertType(getContext().LongTy));
+
+ // If debug info generation is enabled, create the CGDebugInfo object.
+ if (GenerateDebugInfo)
+ DebugInfo = new CGDebugInfo(this);
+ else
+ DebugInfo = NULL;
}
CodeGenModule::~CodeGenModule() {
EmitGlobalCtors();
EmitAnnotations();
delete Runtime;
-
+ delete DebugInfo;
// Run the verifier to check that the generated code is consistent.
assert(!verifyModule(TheModule));
}
namespace CodeGen {
class CodeGenFunction;
-
+ class CGDebugInfo;
+
/// CodeGenModule - This class organizes the cross-module state that is used
/// while generating LLVM code.
class CodeGenModule {
Diagnostic &Diags;
CodeGenTypes Types;
CGObjCRuntime *Runtime;
+ CGDebugInfo *DebugInfo;
llvm::Function *MemCpyFn;
llvm::Function *MemSetFn;
std::vector<llvm::Function *> BuiltinFunctions;
public:
CodeGenModule(ASTContext &C, const LangOptions &Features, llvm::Module &M,
- const llvm::TargetData &TD, Diagnostic &Diags);
+ const llvm::TargetData &TD, Diagnostic &Diags,
+ bool GenerateDebugInfo);
~CodeGenModule();
CGObjCRuntime *getObjCRuntime() { return Runtime; }
+ CGDebugInfo *getDebugInfo() { return DebugInfo; }
ASTContext &getContext() const { return Context; }
const LangOptions &getLangOptions() const { return Features; }
llvm::Module &getModule() const { return TheModule; }
const llvm::TargetData *TD;
ASTContext *Ctx;
const LangOptions &Features;
+ bool GenerateDebugInfo;
protected:
llvm::Module *&M;
CodeGen::CodeGenModule *Builder;
public:
CodeGenerator(Diagnostic &diags, const LangOptions &LO,
- llvm::Module *&DestModule)
- : Diags(diags), Features(LO), M(DestModule) {}
+ llvm::Module *&DestModule, bool DebugInfoFlag)
+ : Diags(diags), Features(LO), GenerateDebugInfo(DebugInfoFlag),
+ M(DestModule) {}
~CodeGenerator() {
delete Builder;
M->setTargetTriple(Ctx->Target.getTargetTriple());
M->setDataLayout(Ctx->Target.getTargetDescription());
TD = new llvm::TargetData(Ctx->Target.getTargetDescription());
- Builder = new CodeGen::CodeGenModule(Context, Features, *M, *TD, Diags);
+ Builder = new CodeGen::CodeGenModule(Context, Features, *M, *TD, Diags,
+ GenerateDebugInfo);
}
virtual void HandleTopLevelDecl(Decl *D) {
ASTConsumer *clang::CreateLLVMCodeGen(Diagnostic &Diags,
const LangOptions &Features,
- llvm::Module *&DestModule) {
- return new CodeGenerator(Diags, Features, DestModule);
+ llvm::Module *&DestModule,
+ bool GenerateDebugInfo) {
+ return new CodeGenerator(Diags, Features, DestModule, GenerateDebugInfo);
}