/// processLexicalBlock void DebugInfoFinder::processLexicalBlock(DILexicalBlock LB) { DIScope Context = LB.getContext(); if (Context.isLexicalBlock()) return processLexicalBlock(DILexicalBlock(Context)); else return processSubprogram(DISubprogram(Context)); }
void LineNumberAnnotatedWriter::emitInstructionAnnot( const Instruction *I, formatted_raw_ostream &Out) { DILocation *NewInstrLoc = I->getDebugLoc(); if (!NewInstrLoc) { auto Loc = DebugLoc.find(I); if (Loc != DebugLoc.end()) NewInstrLoc = Loc->second; } if (!NewInstrLoc || NewInstrLoc == InstrLoc) return; InstrLoc = NewInstrLoc; std::vector<DILineInfo> DIvec; do { DIvec.emplace_back(); DILineInfo &DI = DIvec.back(); DIScope *scope = NewInstrLoc->getScope(); if (scope) DI.FunctionName = scope->getName(); DI.FileName = NewInstrLoc->getFilename(); DI.Line = NewInstrLoc->getLine(); NewInstrLoc = NewInstrLoc->getInlinedAt(); } while (NewInstrLoc); LinePrinter.emit_lineinfo(Out, DIvec); }
/// EmitDeclare - Constructs the debug code for allocation of a new variable. /// region - "llvm.dbg.declare." void DebugInfo::EmitDeclare(tree decl, unsigned Tag, const char *Name, tree type, Value *AI, LLVMBuilder &Builder) { // Ignore compiler generated temporaries. if (DECL_IGNORED_P(decl)) return; assert(!RegionStack.empty() && "Region stack mismatch, stack empty!"); expanded_location Loc = GetNodeLocation(decl, false); // Construct variable. DIScope VarScope = DIScope(cast<MDNode>(RegionStack.back())); DIType Ty = getOrCreateType(type); if (DECL_ARTIFICIAL (decl)) Ty = DebugFactory.CreateArtificialType(Ty); // If type info is not available then do not emit debug info for this var. if (!Ty.getNode()) return; llvm::DIVariable D = DebugFactory.CreateVariable(Tag, VarScope, Name, getOrCreateFile(Loc.file), Loc.line, Ty, optimize); // Insert an llvm.dbg.declare into the current block. Instruction *Call = DebugFactory.InsertDeclare(AI, D, Builder.GetInsertBlock()); Call->setDebugLoc(DebugLoc::get(Loc.line, 0, VarScope.getNode())); }
// Print source location of function, and display name, // falls back to printing the module's location and the function's LLVM name. static void printLocation(const llvm::Function *F) { unsigned MDDebugKind = F->getParent()->getMDKindID("dbg"); if (MDDebugKind) { // Try to find the function's name and location for (Function::const_iterator I=F->begin(),E=F->end(); I != E; ++I) { if (const TerminatorInst *T = I->getTerminator()) { if (MDNode *N = T->getMetadata(MDDebugKind)) { DILocation Loc(N); DIScope Scope = Loc.getScope(); while (Scope.isLexicalBlock()) { DILexicalBlock LB(Scope.getNode()); Scope = LB.getContext(); } if (Scope.isSubprogram()) { DISubprogram SP(Scope.getNode()); errs() << /*Loc.getDirectory() << "/" << */Loc.getFilename() << ": in function '" << SP.getDisplayName() << "': "; return; } } } } } // Fallback to printing module location and function name printLocation(F->getParent()); errs() << "in function '" << F->getName() << "': "; }
StringRef WinCodeViewLineTables::getFullFilepath(const MDNode *S) { assert(S); assert((isa<MDCompileUnit>(S) || isa<MDFile>(S) || isa<MDSubprogram>(S) || isa<MDLexicalBlockBase>(S)) && "Unexpected scope info"); DIScope Scope = cast<MDScope>(S); StringRef Dir = Scope.getDirectory(), Filename = Scope.getFilename(); char *&Result = DirAndFilenameToFilepathMap[std::make_pair(Dir, Filename)]; if (Result) return Result; // Clang emits directory and relative filename info into the IR, but CodeView // operates on full paths. We could change Clang to emit full paths too, but // that would increase the IR size and probably not needed for other users. // For now, just concatenate and canonicalize the path here. std::string Filepath; if (Filename.find(':') == 1) Filepath = Filename; else Filepath = (Dir + "\\" + Filename).str(); // Canonicalize the path. We have to do it textually because we may no longer // have access the file in the filesystem. // First, replace all slashes with backslashes. std::replace(Filepath.begin(), Filepath.end(), '/', '\\'); // Remove all "\.\" with "\". size_t Cursor = 0; while ((Cursor = Filepath.find("\\.\\", Cursor)) != std::string::npos) Filepath.erase(Cursor, 2); // Replace all "\XXX\..\" with "\". Don't try too hard though as the original // path should be well-formatted, e.g. start with a drive letter, etc. Cursor = 0; while ((Cursor = Filepath.find("\\..\\", Cursor)) != std::string::npos) { // Something's wrong if the path starts with "\..\", abort. if (Cursor == 0) break; size_t PrevSlash = Filepath.rfind('\\', Cursor - 1); if (PrevSlash == std::string::npos) // Something's wrong, abort. break; Filepath.erase(PrevSlash, Cursor + 3 - PrevSlash); // The next ".." might be following the one we've just erased. Cursor = PrevSlash; } // Remove all duplicate backslashes. Cursor = 0; while ((Cursor = Filepath.find("\\\\", Cursor)) != std::string::npos) Filepath.erase(Cursor, 1); Result = strdup(Filepath.c_str()); return StringRef(Result); }
//changed scope was * LLVMValueRef LLVMGetDebugLoc(unsigned Line, unsigned Col, LLVMValueRef Scope) { // MDNode *S = unwrapDI<DIDescriptor>(*Scope); // DebugLoc loc = DebugLoc::get(Line,Col,S); DIScope S = unwrapDI<DIScope>(Scope); DebugLoc loc = DebugLoc::get(Line,Col,S); LLVMContext &ctx = S->getContext(); MDNode *L = loc.getAsMDNode(ctx); return wrap(L); }
/// CreateLocation - Creates a debug info location. DILocation DIFactory::CreateLocation(unsigned LineNo, unsigned ColumnNo, DIScope S, DILocation OrigLoc) { Value *Elts[] = { ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), ConstantInt::get(Type::getInt32Ty(VMContext), ColumnNo), S.getNode(), OrigLoc.getNode(), }; return DILocation(MDNode::get(VMContext, &Elts[0], 4)); }
static void printDebugLoc(DebugLoc DL, raw_ostream &CommentOS, const LLVMContext &Ctx) { if (!DL) return; DIScope Scope = cast<MDScope>(DL.getScope()); // Omit the directory, because it's likely to be long and uninteresting. CommentOS << Scope.getFilename(); CommentOS << ':' << DL.getLine(); if (DL.getCol() != 0) CommentOS << ':' << DL.getCol(); DebugLoc InlinedAtDL = DL.getInlinedAt(); if (!InlinedAtDL) return; CommentOS << " @[ "; printDebugLoc(InlinedAtDL, CommentOS, Ctx); CommentOS << " ]"; }
const DILocation *DILocation::getMergedLocation(const DILocation *LocA, const DILocation *LocB) { if (!LocA || !LocB) return nullptr; if (LocA == LocB) return LocA; SmallPtrSet<DILocation *, 5> InlinedLocationsA; for (DILocation *L = LocA->getInlinedAt(); L; L = L->getInlinedAt()) InlinedLocationsA.insert(L); SmallSet<std::pair<DIScope *, DILocation *>, 5> Locations; DIScope *S = LocA->getScope(); DILocation *L = LocA->getInlinedAt(); while (S) { Locations.insert(std::make_pair(S, L)); S = S->getScope().resolve(); if (!S && L) { S = L->getScope(); L = L->getInlinedAt(); } } const DILocation *Result = LocB; S = LocB->getScope(); L = LocB->getInlinedAt(); while (S) { if (Locations.count(std::make_pair(S, L))) break; S = S->getScope().resolve(); if (!S && L) { S = L->getScope(); L = L->getInlinedAt(); } } // If the two locations are irreconsilable, just pick one. This is misleading, // but on the other hand, it's a "line 0" location. if (!S || !isa<DILocalScope>(S)) S = LocA->getScope(); return DILocation::get(Result->getContext(), 0, 0, S, L); }
bool DebugInfoFinder::addScope(DIScope Scope) { if (!Scope) return false; // FIXME: Ocaml binding generates a scope with no content, we treat it // as null for now. if (Scope->getNumOperands() == 0) return false; if (!NodesSeen.insert(Scope).second) return false; Scopes.push_back(Scope); return true; }
void DebugInfoFinder::processScope(DIScope Scope) { if (Scope.isType()) { DIType Ty(Scope); processType(Ty); return; } if (Scope.isCompileUnit()) { addCompileUnit(DICompileUnit(Scope)); return; } if (Scope.isSubprogram()) { processSubprogram(DISubprogram(Scope)); return; } if (!addScope(Scope)) return; if (Scope.isLexicalBlock()) { DILexicalBlock LB(Scope); processScope(LB.getContext()); } else if (Scope.isLexicalBlockFile()) { DILexicalBlockFile LBF = DILexicalBlockFile(Scope); processScope(LBF.getScope()); } else if (Scope.isNameSpace()) { DINameSpace NS(Scope); processScope(NS.getContext()); } }
void DIEItem::ShowContext(DetailsView* detailsView, DIScope scope) { // TODO: Fill out these cases. if (scope.isCompileUnit()) { DICompileUnit diCompileUnit(scope); detailsView->Add(_("ContextType"), _("DICompileUnit")); detailsView->Add(_("Context"), toWxStr(diCompileUnit.getDirectory()) + _("/") + toWxStr(diCompileUnit.getFilename())); } else if (scope.isFile()) { DIFile diFile(scope); detailsView->Add(_("ContextType"), _("DIFile")); detailsView->Add(_("Context"), toWxStr(diFile.getDirectory()) + _("/") + toWxStr(diFile.getFilename())); } else if (scope.isNameSpace()) { DINameSpace diNameSpace(scope); detailsView->Add(_("ContextType"), _("DINameSpace")); detailsView->Add(_("Context"), diNameSpace.getName()); } else if (scope.isSubprogram()) { DISubprogram diSubprogram(scope); detailsView->Add(_("ContextType"), _("DISubprogram")); detailsView->Add(_("Context"), diSubprogram.getName()); } else if (scope.isLexicalBlock()) { detailsView->Add(_("ContextType"), _("DILexicalBlock")); // TODO: Implement context name. detailsView->Add(_("Context"), _("?{}")); } else if (scope.isType()) { detailsView->Add(_("ContextType"), _("DIType")); detailsView->Add(_("Context"), DITypeToString(DIType(scope))); } else { detailsView->Add(_("Context"), _("??? [Unknown]")); } }
// Print instruction location, falls back to printing function location, // (and LLVM instruction if specified). void printLocation(const llvm::Instruction *I, bool fallback) { const BasicBlock *BB = I->getParent(); bool approx = false; BasicBlock::const_iterator It = I; do { BasicBlock::const_iterator ItB = BB->begin(); while (It != ItB) { if (MDNode *N = It->getMetadata("dbg")) { DILocation Loc(N); errs() << /*Loc.getDirectory() << "/" <<*/ Loc.getFilename() << ":" << Loc.getLineNumber(); if (unsigned Col = Loc.getColumnNumber()) { errs() << ":" << Col; } if (approx) errs() << "(?)"; errs() << ": "; DIScope Scope = Loc.getScope(); while (Scope.isLexicalBlock()) { DILexicalBlock LB(Scope.getNode()); Scope = LB.getContext(); } if (Scope.isSubprogram()) { DISubprogram SP(Scope.getNode()); errs() << "in function '" << SP.getDisplayName() << "': "; } return; } approx = true; --It; } BB = BB->getUniquePredecessor(); if (BB) It = BB->end(); } while (BB); printLocation(I->getParent()->getParent()); if (fallback) errs() << *I << ":\n"; }
const char *LLVMGetDirectory(LLVMValueRef Scope) { DIScope S = unwrapDI<DIScope>(Scope); StringRef str = S.getDirectory(); return str.data(); }
const char *LLVMGetFileName(LLVMValueRef Scope) { DIScope S = unwrapDI<DIScope>(Scope); StringRef str = S.getFilename(); return str.data(); }