void DataChecks::CreateCrossCheck(IRBuilder<> &Builder, Value *V) { IntegerType *PtrIntTy = Builder.getIntPtrTy(*DL); // Cast the value to IntPtrType auto *VTy = V->getType(); if (VTy->isPointerTy()) V = Builder.CreatePtrToInt(V, PtrIntTy); else V = Builder.CreateZExtOrTrunc(V, PtrIntTy); // Call the check function. // TODO: Optimize by inlining the call? if (XCheckLog) { DebugLoc Loc = Builder.GetInsertPoint()->getDebugLoc(); Value *caller = Builder.CreateGlobalStringPtr(Builder.GetInsertBlock()->getParent()->getName()); Value *line, *col, *file; if (Loc) { line = Builder.getInt32(Loc.getLine()); col = Builder.getInt32(Loc.getCol()); file = Builder.CreateGlobalStringPtr(Loc->getFilename()); } else { line = Builder.getInt32(-1); col = Builder.getInt32(-1); file = Builder.CreateGlobalStringPtr("unknown"); } Builder.CreateCall(CheckFnTy, CheckFn, { caller, file, line, col, V }); } else { Builder.CreateCall(CheckFnTy, CheckFn, {V}); } NumCrossChecks++; }
DiagnosticLocation::DiagnosticLocation(const DebugLoc &DL) { if (!DL) return; Filename = DL->getFilename(); Line = DL->getLine(); Column = DL->getColumn(); }
/// \brief Get the weight for an instruction. /// /// The "weight" of an instruction \p Inst is the number of samples /// collected on that instruction at runtime. To retrieve it, we /// need to compute the line number of \p Inst relative to the start of its /// function. We use HeaderLineno to compute the offset. We then /// look up the samples collected for \p Inst using BodySamples. /// /// \param Inst Instruction to query. /// /// \returns the weight of \p Inst. ErrorOr<uint64_t> SampleProfileLoader::getInstWeight(const Instruction &Inst) const { DebugLoc DLoc = Inst.getDebugLoc(); if (!DLoc) return std::error_code(); const FunctionSamples *FS = findFunctionSamples(Inst); if (!FS) return std::error_code(); const DILocation *DIL = DLoc; unsigned Lineno = DLoc.getLine(); unsigned HeaderLineno = DIL->getScope()->getSubprogram()->getLine(); uint32_t LineOffset = getOffset(Lineno, HeaderLineno); uint32_t Discriminator = DIL->getDiscriminator(); ErrorOr<uint64_t> R = FS->findSamplesAt(LineOffset, Discriminator); if (R) { bool FirstMark = CoverageTracker.markSamplesUsed(FS, LineOffset, Discriminator); if (FirstMark) { const Function *F = Inst.getParent()->getParent(); LLVMContext &Ctx = F->getContext(); emitOptimizationRemark(Ctx, DEBUG_TYPE, *F, DLoc, Twine("Applied ") + Twine(*R) + " samples from profile"); } DEBUG(dbgs() << " " << Lineno << "." << DIL->getDiscriminator() << ":" << Inst << " (line offset: " << Lineno - HeaderLineno << "." << DIL->getDiscriminator() << " - weight: " << R.get() << ")\n"); } return R; }
void WinCodeViewLineTables::beginInstruction(const MachineInstr *MI) { // Ignore DBG_VALUE locations and function prologue. if (!Asm || MI->isDebugValue() || MI->getFlag(MachineInstr::FrameSetup)) return; DebugLoc DL = MI->getDebugLoc(); if (DL == PrevInstLoc || DL.isUnknown()) return; maybeRecordLocation(DL, Asm->MF); }
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, DebugLoc Loc) : Key(Key), Loc(Loc) { if (Loc) { Val = (Loc->getFilename() + ":" + Twine(Loc.getLine()) + ":" + Twine(Loc.getCol())).str(); } else { Val = "<UNKNOWN LOCATION>"; } }
/// extractLexicalScopes - Extract instruction ranges for each lexical scopes /// for the given machine function. void LexicalScopes:: extractLexicalScopes(SmallVectorImpl<InsnRange> &MIRanges, DenseMap<const MachineInstr *, LexicalScope *> &MI2ScopeMap) { // Scan each instruction and create scopes. First build working set of scopes. for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); I != E; ++I) { const MachineInstr *RangeBeginMI = NULL; const MachineInstr *PrevMI = NULL; DebugLoc PrevDL; for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); II != IE; ++II) { const MachineInstr *MInsn = II; // Check if instruction has valid location information. const DebugLoc MIDL = MInsn->getDebugLoc(); if (MIDL.isUnknown()) { PrevMI = MInsn; continue; } // If scope has not changed then skip this instruction. if (MIDL == PrevDL) { PrevMI = MInsn; continue; } // Ignore DBG_VALUE. It does not contribute to any instruction in output. if (MInsn->isDebugValue()) continue; if (RangeBeginMI) { // If we have already seen a beginning of an instruction range and // current instruction scope does not match scope of first instruction // in this range then create a new instruction range. InsnRange R(RangeBeginMI, PrevMI); MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL); MIRanges.push_back(R); } // This is a beginning of a new instruction range. RangeBeginMI = MInsn; // Reset previous markers. PrevMI = MInsn; PrevDL = MIDL; } // Create last instruction range. if (RangeBeginMI && PrevMI && !PrevDL.isUnknown()) { InsnRange R(RangeBeginMI, PrevMI); MIRanges.push_back(R); MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL); } } }
//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); }
unsigned ScopeInfoFinder::getInstLine(const Instruction *I) { DebugLoc Loc = I->getDebugLoc(); if (Loc.isUnknown()) { if (DEBUG_MATCHER) { errs() << "Unknown LOC" << "\n"; } return 0; } return Loc.getLine(); }
unsigned ScopeInfoFinder::getLastLine(Function *F) { if (F == NULL || F->begin() == F->end()) //empty block return 0; const BasicBlock & BB = F->back(); const Instruction & I = BB.back(); DebugLoc Loc = I.getDebugLoc(); if (Loc.isUnknown()) return 0; return Loc.getLine(); }
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)); }
// 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; }
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; }
void DIVariable::printExtendedName(raw_ostream &OS) const { const LLVMContext &Ctx = DbgNode->getContext(); StringRef Res = getName(); if (!Res.empty()) OS << Res << "," << getLineNumber(); if (MDNode *InlinedAt = getInlinedAt()) { DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(InlinedAt); if (!InlinedAtDL.isUnknown()) { OS << " @["; printDebugLoc(InlinedAtDL, OS, Ctx); OS << "]"; } } }
void DebugLoc::dump(const LLVMContext &Ctx) const { #ifndef NDEBUG if (!isUnknown()) { dbgs() << getLine(); if (getCol() != 0) dbgs() << ',' << getCol(); DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(getInlinedAt(Ctx)); if (!InlinedAtDL.isUnknown()) { dbgs() << " @ "; InlinedAtDL.dump(Ctx); } else dbgs() << "\n"; } #endif }
/// \brief Get the weight for an instruction. /// /// The "weight" of an instruction \p Inst is the number of samples /// collected on that instruction at runtime. To retrieve it, we /// need to compute the line number of \p Inst relative to the start of its /// function. We use HeaderLineno to compute the offset. We then /// look up the samples collected for \p Inst using BodySamples. /// /// \param Inst Instruction to query. /// /// \returns The profiled weight of I. unsigned SampleProfileLoader::getInstWeight(Instruction &Inst) { DebugLoc DLoc = Inst.getDebugLoc(); unsigned Lineno = DLoc.getLine(); if (Lineno < HeaderLineno) return 0; DILocation DIL(DLoc.getAsMDNode(*Ctx)); int LOffset = Lineno - HeaderLineno; unsigned Discriminator = DIL.getDiscriminator(); unsigned Weight = Samples->samplesAt(LOffset, Discriminator); DEBUG(dbgs() << " " << Lineno << "." << Discriminator << ":" << Inst << " (line offset: " << LOffset << "." << Discriminator << " - weight: " << Weight << ")\n"); return Weight; }
void JITEmitter::processDebugLoc(DebugLoc DL, bool BeforePrintingInsn) { if (DL.isUnknown()) return; if (!BeforePrintingInsn) return; const LLVMContext &Context = EmissionDetails.MF->getFunction()->getContext(); if (DL.getScope(Context) != 0 && PrevDL != DL) { JITEvent_EmittedFunctionDetails::LineStart NextLine; NextLine.Address = getCurrentPCValue(); NextLine.Loc = DL; EmissionDetails.LineStarts.push_back(NextLine); } PrevDL = DL; }
DISubprogram llvm::getDISubprogram(const Function *F) { // We look for the first instr that has a debug annotation leading back to F. for (auto &BB : *F) { auto Inst = std::find_if(BB.begin(), BB.end(), [](const Instruction &Inst) { return !Inst.getDebugLoc().isUnknown(); }); if (Inst == BB.end()) continue; DebugLoc DLoc = Inst->getDebugLoc(); const MDNode *Scope = DLoc.getScopeNode(); DISubprogram Subprogram = getDISubprogram(Scope); return Subprogram.describes(F) ? Subprogram : DISubprogram(); } return DISubprogram(); }
/// 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))); }
void Matcher::processInst(Function *F) { for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; FI++) { /** Get each instruction's scope information **/ for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; BI++) { DebugLoc Loc = BI->getDebugLoc(); if (Loc.isUnknown()) continue; LLVMContext & Ctx = BI->getContext(); DIDescriptor Scope(Loc.getScope(Ctx)); if (Scope.isLexicalBlock()) { DILexicalBlock DILB(Scope); errs() << "Block :" << DILB.getLineNumber() << ", " << DILB.getColumnNumber() << "\n"; } } } }
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 << " ]"; }
void WinCodeViewLineTables::beginFunction(const MachineFunction *MF) { assert(!CurFn && "Can't process two functions at once!"); if (!Asm || !Asm->MMI->hasDebugInfo()) return; const Function *GV = MF->getFunction(); assert(FnDebugInfo.count(GV) == false); VisitedFunctions.push_back(GV); CurFn = &FnDebugInfo[GV]; // Find the end of the function prolog. // FIXME: is there a simpler a way to do this? Can we just search // for the first instruction of the function, not the last of the prolog? DebugLoc PrologEndLoc; bool EmptyPrologue = true; for (const auto &MBB : *MF) { if (!PrologEndLoc.isUnknown()) break; for (const auto &MI : MBB) { if (MI.isDebugValue()) continue; // First known non-DBG_VALUE and non-frame setup location marks // the beginning of the function body. // FIXME: do we need the first subcondition? if (!MI.getFlag(MachineInstr::FrameSetup) && (!MI.getDebugLoc().isUnknown())) { PrologEndLoc = MI.getDebugLoc(); break; } EmptyPrologue = false; } } // Record beginning of function if we have a non-empty prologue. if (!PrologEndLoc.isUnknown() && !EmptyPrologue) { DebugLoc FnStartDL = PrologEndLoc.getFnDebugLoc(MF->getFunction()->getContext()); maybeRecordLocation(FnStartDL, MF); } }
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 << " ]"; }
void DebugLoc::print(const LLVMContext &Ctx, raw_ostream &OS) const { if (!isUnknown()) { // Print source line info. DIScope Scope(getScope(Ctx)); assert((!Scope || Scope.isScope()) && "Scope of a DebugLoc should be null or a DIScope."); if (Scope) OS << Scope.getFilename(); else OS << "<unknown>"; OS << ':' << getLine(); if (getCol() != 0) OS << ':' << getCol(); DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(getInlinedAt(Ctx)); if (!InlinedAtDL.isUnknown()) { OS << " @[ "; InlinedAtDL.print(Ctx, OS); OS << " ]"; } } }
/// dominates - Return true if DebugLoc's lexical scope dominates at least one /// machine instruction's lexical scope in a given machine basic block. bool LexicalScopes::dominates(DebugLoc DL, MachineBasicBlock *MBB) { LexicalScope *Scope = getOrCreateLexicalScope(DL); if (!Scope) return false; // Current function scope covers all basic blocks in the function. if (Scope == CurrentFnLexicalScope && MBB->getParent() == MF) return true; bool Result = false; for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E; ++I) { DebugLoc IDL = I->getDebugLoc(); if (IDL.isUnknown()) continue; if (LexicalScope *IScope = getOrCreateLexicalScope(IDL)) if (Scope->dominates(IScope)) return true; } return Result; }
void WinCodeViewLineTables::maybeRecordLocation(DebugLoc DL, const MachineFunction *MF) { const MDNode *Scope = DL.getScope(); if (!Scope) return; StringRef Filename = getFullFilepath(Scope); // Skip this instruction if it has the same file:line as the previous one. assert(CurFn); if (!CurFn->Instrs.empty()) { const InstrInfoTy &LastInstr = InstrInfo[CurFn->Instrs.back()]; if (LastInstr.Filename == Filename && LastInstr.LineNumber == DL.getLine()) return; } FileNameRegistry.add(Filename); MCSymbol *MCL = Asm->MMI->getContext().CreateTempSymbol(); Asm->OutStreamer.EmitLabel(MCL); CurFn->Instrs.push_back(MCL); InstrInfo[MCL] = InstrInfoTy(Filename, DL.getLine()); }
/// fixupLineNumbers - Update inlined instructions' line numbers to /// to encode location where these instructions are inlined. static void fixupLineNumbers(Function *Fn, Function::iterator FI, Instruction *TheCall) { DebugLoc TheCallDL = TheCall->getDebugLoc(); if (TheCallDL.isUnknown()) return; for (; FI != Fn->end(); ++FI) { for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) { DebugLoc DL = BI->getDebugLoc(); if (!DL.isUnknown()) { BI->setDebugLoc(updateInlinedAtInfo(DL, TheCallDL, BI->getContext())); if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(BI)) { LLVMContext &Ctx = BI->getContext(); MDNode *InlinedAt = BI->getDebugLoc().getInlinedAt(Ctx); DVI->setOperand(2, createInlinedVariable(DVI->getVariable(), InlinedAt, Ctx)); } } } } }
void getDebugLocation(const Region *R, unsigned &LineBegin, unsigned &LineEnd, std::string &FileName) { LineBegin = -1; LineEnd = 0; for (const BasicBlock *BB : R->blocks()) for (const Instruction &Inst : *BB) { DebugLoc DL = Inst.getDebugLoc(); if (!DL) continue; auto *Scope = cast<DIScope>(DL.getScope()); if (FileName.empty()) FileName = Scope->getFilename(); unsigned NewLine = DL.getLine(); LineBegin = std::min(LineBegin, NewLine); LineEnd = std::max(LineEnd, NewLine); } }
void CodeViewDebug::beginFunction(const MachineFunction *MF) { assert(!CurFn && "Can't process two functions at once!"); if (!Asm || !MMI->hasDebugInfo()) return; DebugHandlerBase::beginFunction(MF); const Function *GV = MF->getFunction(); assert(FnDebugInfo.count(GV) == false); CurFn = &FnDebugInfo[GV]; CurFn->FuncId = NextFuncId++; CurFn->Begin = Asm->getFunctionBegin(); // Find the end of the function prolog. First known non-DBG_VALUE and // non-frame setup location marks the beginning of the function body. // FIXME: is there a simpler a way to do this? Can we just search // for the first instruction of the function, not the last of the prolog? DebugLoc PrologEndLoc; bool EmptyPrologue = true; for (const auto &MBB : *MF) { for (const auto &MI : MBB) { if (!MI.isDebugValue() && !MI.getFlag(MachineInstr::FrameSetup) && MI.getDebugLoc()) { PrologEndLoc = MI.getDebugLoc(); break; } else if (!MI.isDebugValue()) { EmptyPrologue = false; } } } // Record beginning of function if we have a non-empty prologue. if (PrologEndLoc && !EmptyPrologue) { DebugLoc FnStartDL = PrologEndLoc.getFnDebugLoc(); maybeRecordLocation(FnStartDL, MF); } }