//===--- 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? }