void CodeViewDebug::maybeRecordLocation(DebugLoc DL, const MachineFunction *MF) { // Skip this instruction if it has the same location as the previous one. if (DL == CurFn->LastLoc) return; const DIScope *Scope = DL.get()->getScope(); if (!Scope) return; // Skip this line if it is longer than the maximum we can record. LineInfo LI(DL.getLine(), DL.getLine(), /*IsStatement=*/true); if (LI.getStartLine() != DL.getLine() || LI.isAlwaysStepInto() || LI.isNeverStepInto()) return; ColumnInfo CI(DL.getCol(), /*EndColumn=*/0); if (CI.getStartColumn() != DL.getCol()) return; if (!CurFn->HaveLineInfo) CurFn->HaveLineInfo = true; unsigned FileId = 0; if (CurFn->LastLoc.get() && CurFn->LastLoc->getFile() == DL->getFile()) FileId = CurFn->LastFileId; else FileId = CurFn->LastFileId = maybeRecordFile(DL->getFile()); CurFn->LastLoc = DL; unsigned FuncId = CurFn->FuncId; if (const DILocation *SiteLoc = DL->getInlinedAt()) { const DILocation *Loc = DL.get(); // If this location was actually inlined from somewhere else, give it the ID // of the inline call site. FuncId = getInlineSite(SiteLoc, Loc->getScope()->getSubprogram()).SiteFuncId; // Ensure we have links in the tree of inline call sites. bool FirstLoc = true; while ((SiteLoc = Loc->getInlinedAt())) { InlineSite &Site = getInlineSite(SiteLoc, Loc->getScope()->getSubprogram()); if (!FirstLoc) addLocIfNotPresent(Site.ChildSites, Loc); FirstLoc = false; Loc = SiteLoc; } addLocIfNotPresent(CurFn->ChildSites, Loc); } OS.EmitCVLocDirective(FuncId, FileId, DL.getLine(), DL.getCol(), /*PrologueEnd=*/false, /*IsStmt=*/false, DL->getFilename()); }
void CodeViewDebug::maybeRecordLocation(DebugLoc DL, const MachineFunction *MF) { // Skip this instruction if it has the same location as the previous one. if (DL == CurFn->LastLoc) return; const DIScope *Scope = DL.get()->getScope(); if (!Scope) return; // Skip this line if it is longer than the maximum we can record. LineInfo LI(DL.getLine(), DL.getLine(), /*IsStatement=*/true); if (LI.getStartLine() != DL.getLine() || LI.isAlwaysStepInto() || LI.isNeverStepInto()) return; ColumnInfo CI(DL.getCol(), /*EndColumn=*/0); if (CI.getStartColumn() != DL.getCol()) return; if (!CurFn->HaveLineInfo) CurFn->HaveLineInfo = true; unsigned FileId = 0; if (CurFn->LastLoc.get() && CurFn->LastLoc->getFile() == DL->getFile()) FileId = CurFn->LastFileId; else FileId = CurFn->LastFileId = maybeRecordFile(DL->getFile()); CurFn->LastLoc = DL; unsigned FuncId = CurFn->FuncId; if (const DILocation *Loc = DL->getInlinedAt()) { // If this location was actually inlined from somewhere else, give it the ID // of the inline call site. FuncId = getInlineSite(DL.get()).SiteFuncId; // Ensure we have links in the tree of inline call sites. const DILocation *ChildLoc = nullptr; while (Loc->getInlinedAt()) { InlineSite &Site = getInlineSite(Loc); if (ChildLoc) { // Record the child inline site if not already present. auto B = Site.ChildSites.begin(), E = Site.ChildSites.end(); if (std::find(B, E, Loc) != E) break; Site.ChildSites.push_back(Loc); } ChildLoc = Loc; } } Asm->OutStreamer->EmitCVLocDirective(FuncId, FileId, DL.getLine(), DL.getCol(), /*PrologueEnd=*/false, /*IsStmt=*/false, DL->getFilename()); }
bool DISubprogram::Verify() const { auto *N = getRaw(); if (!N) return false; if (!isScopeRef(N->getScope())) return false; if (auto *Op = N->getType()) if (!isa<MDNode>(Op)) return false; if (!isTypeRef(getContainingType())) return false; if (isLValueReference() && isRValueReference()) return false; // If a DISubprogram has an llvm::Function*, then scope chains from all // instructions within the function should lead to this DISubprogram. if (auto *F = getFunction()) { for (auto &BB : *F) { for (auto &I : BB) { DebugLoc DL = I.getDebugLoc(); if (DL.isUnknown()) continue; MDNode *Scope = nullptr; MDNode *IA = nullptr; // walk the inlined-at scopes while ((IA = DL.getInlinedAt())) DL = DebugLoc::getFromDILocation(IA); DL.getScopeAndInlinedAt(Scope, IA); if (!Scope) return false; assert(!IA); while (!DIDescriptor(Scope).isSubprogram()) { DILexicalBlockFile D(Scope); Scope = D.isLexicalBlockFile() ? D.getScope() : DebugLoc::getFromDILexicalBlock(Scope).getScope(); if (!Scope) return false; } if (!DISubprogram(Scope).describes(F)) return false; } } } return true; }
/// updateInlinedAtInfo - Helper function used by fixupLineNumbers to /// recursively update InlinedAtEntry of a DebugLoc. static DebugLoc updateInlinedAtInfo(const DebugLoc &DL, const DebugLoc &InlinedAtDL, LLVMContext &Ctx) { if (MDNode *IA = DL.getInlinedAt(Ctx)) { DebugLoc NewInlinedAtDL = updateInlinedAtInfo(DebugLoc::getFromDILocation(IA), InlinedAtDL, Ctx); return DebugLoc::get(DL.getLine(), DL.getCol(), DL.getScope(Ctx), NewInlinedAtDL.getAsMDNode(Ctx)); } return DebugLoc::get(DL.getLine(), DL.getCol(), DL.getScope(Ctx), InlinedAtDL.getAsMDNode(Ctx)); }
static void print_source_line(raw_ostream &stream, DebugLoc Loc) { MDNode *inlinedAt = Loc.getInlinedAt(jl_LLVMContext); if (inlinedAt != NULL) { DebugLoc inlineloc = DebugLoc::getFromDILocation(inlinedAt); stream << "Source line: " << inlineloc.getLine() << "\n"; DILexicalBlockFile innerscope = DILexicalBlockFile(Loc.getScope(jl_LLVMContext)); stream << "Source line: [inline] " << innerscope.getFilename().str().c_str() << ':' << Loc.getLine() << "\n"; } else { stream << "Source line: " << Loc.getLine() << "\n"; } }
bool DISubprogram::Verify() const { if (!isSubprogram()) return false; // Make sure context @ field 2 is a ScopeRef and type @ field 3 is a MDNode. if (!fieldIsScopeRef(DbgNode, 2)) return false; if (!fieldIsMDNode(DbgNode, 3)) return false; // Containing type @ field 4. if (!fieldIsTypeRef(DbgNode, 4)) return false; // A subprogram can't be both & and &&. if (isLValueReference() && isRValueReference()) return false; // If a DISubprogram has an llvm::Function*, then scope chains from all // instructions within the function should lead to this DISubprogram. if (auto *F = getFunction()) { for (auto &BB : *F) { for (auto &I : BB) { DebugLoc DL = I.getDebugLoc(); if (DL.isUnknown()) continue; MDNode *Scope = nullptr; MDNode *IA = nullptr; // walk the inlined-at scopes while ((IA = DL.getInlinedAt())) DL = DebugLoc::getFromDILocation(IA); DL.getScopeAndInlinedAt(Scope, IA); if (!Scope) return false; assert(!IA); while (!DIDescriptor(Scope).isSubprogram()) { DILexicalBlockFile D(Scope); Scope = D.isLexicalBlockFile() ? D.getScope() : DebugLoc::getFromDILexicalBlock(Scope).getScope(); if (!Scope) return false; } if (!DISubprogram(Scope).describes(F)) return false; } } } return DbgNode->getNumOperands() == 9 && getNumHeaderFields() == 12; }
// Tries to remove a sanity check; returns true if it worked. bool AsapPass::optimizeCheckAway(llvm::Instruction *Inst) { BranchInst *BI = cast<BranchInst>(Inst); assert(BI->isConditional() && "Sanity check must be conditional branch."); unsigned int RegularBranch = getRegularBranch(BI, SCI); bool Changed = false; if (RegularBranch == 0) { BI->setCondition(ConstantInt::getTrue(Inst->getContext())); Changed = true; } else if (RegularBranch == 1) { BI->setCondition(ConstantInt::getFalse(Inst->getContext())); Changed = true; } else { // This can happen, e.g., in the following case: // array[-1] = a + b; // is transformed into // if (a + b overflows) // report_overflow() // else // report_index_out_of_bounds(); // In this case, removing the sanity check does not help much, so we // just do nothing. // Thanks to Will Dietz for his explanation at // http://lists.cs.uiuc.edu/pipermail/llvmdev/2014-April/071958.html dbgs() << "Warning: Sanity check with no regular branch found.\n"; dbgs() << "The sanity check has been kept intact.\n"; } if (PrintRemovedChecks && Changed) { DebugLoc DL = getSanityCheckDebugLoc(BI, RegularBranch); printDebugLoc(DL, BI->getContext(), dbgs()); dbgs() << ": SanityCheck with cost "; dbgs() << *BI->getMetadata("cost")->getOperand(0); if (MDNode *IA = DL.getInlinedAt()) { dbgs() << " (inlined at "; printDebugLoc(DebugLoc(IA), BI->getContext(), dbgs()); dbgs() << ")"; } BasicBlock *Succ = BI->getSuccessor(RegularBranch == 0 ? 1 : 0); if (const CallInst *CI = SCI->findSanityCheckCall(Succ)) { dbgs() << " " << CI->getCalledFunction()->getName(); } dbgs() << "\n"; } return Changed; }
/// processModule - Process entire module and collect debug info. void DebugInfoFinder::processModule(Module &M) { if (NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu")) for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) addCompileUnit(DICompileUnit(CU_Nodes->getOperand(i))); for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) for (Function::iterator FI = (*I).begin(), FE = (*I).end(); FI != FE; ++FI) for (BasicBlock::iterator BI = (*FI).begin(), BE = (*FI).end(); BI != BE; ++BI) { if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(BI)) processDeclare(DDI); DebugLoc Loc = BI->getDebugLoc(); if (Loc.isUnknown()) continue; LLVMContext &Ctx = BI->getContext(); DIDescriptor Scope(Loc.getScope(Ctx)); if (Scope.isCompileUnit()) addCompileUnit(DICompileUnit(Scope)); else if (Scope.isSubprogram()) processSubprogram(DISubprogram(Scope)); else if (Scope.isLexicalBlock()) processLexicalBlock(DILexicalBlock(Scope)); if (MDNode *IA = Loc.getInlinedAt(Ctx)) processLocation(DILocation(IA)); } if (NamedMDNode *NMD = M.getNamedMetadata("llvm.dbg.gv")) { for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { DIGlobalVariable DIG(cast<MDNode>(NMD->getOperand(i))); if (addGlobalVariable(DIG)) { if (DIG.getVersion() <= LLVMDebugVersion10) addCompileUnit(DIG.getCompileUnit()); processType(DIG.getType()); } } } if (NamedMDNode *NMD = M.getNamedMetadata("llvm.dbg.sp")) for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) processSubprogram(DISubprogram(NMD->getOperand(i))); }
static void printDebugLoc(DebugLoc DL, raw_ostream &CommentOS, const LLVMContext &Ctx) { if (!DL.isUnknown()) { // Print source line info. DIScope Scope(DL.getScope(Ctx)); assert(Scope.isScope() && "Scope of a DebugLoc should be a DIScope."); // 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 = DebugLoc::getFromDILocation(DL.getInlinedAt(Ctx)); if (!InlinedAtDL.isUnknown()) { CommentOS << " @[ "; printDebugLoc(InlinedAtDL, CommentOS, Ctx); CommentOS << " ]"; } } }
static void printDebugLoc(DebugLoc DL, raw_ostream &CommentOS, const LLVMContext &Ctx) { if (!DL) return; auto *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 << " ]"; }
static void printDebugLoc(DebugLoc DL, raw_ostream &CommentOS, const LLVMContext &Ctx) { if (!DL) return; DIScope Scope(DL.getScope()); assert(Scope.isScope() && "Scope of a DebugLoc should be a DIScope."); // 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 << " ]"; }