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()); }
/// 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)); }
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++; }
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 << " ]"; } } }
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>"; } }
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 << " ]"; }
void DSMonitor::watch(DSNodeHandle N, std::vector<Value*> VS, std::string M) { if (N.isNull() || N.getNode()->isCollapsedNode()) { unwatch(); return; } this->N = N; this->VS = VS; this->message = M; DSGraph *G = N.getNode()->getParentGraph(); caption = getCaption(N.getNode(), G); if (!VS.empty()) { Instruction *I = getInstruction(VS[0]); if (I && I->getMetadata("dbg")) { const DebugLoc DL = I->getDebugLoc(); auto *scope = cast<DIScope>(DL.getScope()); location = scope->getFilename().str() + ":" + std::to_string(DL.getLine()) + ":" + std::to_string(DL.getCol()); } } }
void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const { if (const MachineSDNode *MN = dyn_cast<MachineSDNode>(this)) { if (!MN->memoperands_empty()) { OS << "<"; OS << "Mem:"; for (MachineSDNode::mmo_iterator i = MN->memoperands_begin(), e = MN->memoperands_end(); i != e; ++i) { OS << **i; if (llvm::next(i) != e) OS << " "; } OS << ">"; } } else if (const ShuffleVectorSDNode *SVN = dyn_cast<ShuffleVectorSDNode>(this)) { OS << "<"; for (unsigned i = 0, e = ValueList[0].getVectorNumElements(); i != e; ++i) { int Idx = SVN->getMaskElt(i); if (i) OS << ","; if (Idx < 0) OS << "u"; else OS << Idx; } OS << ">"; } else if (const ConstantSDNode *CSDN = dyn_cast<ConstantSDNode>(this)) { OS << '<' << CSDN->getAPIntValue() << '>'; } else if (const ConstantFPSDNode *CSDN = dyn_cast<ConstantFPSDNode>(this)) { if (&CSDN->getValueAPF().getSemantics()==&APFloat::IEEEsingle) OS << '<' << CSDN->getValueAPF().convertToFloat() << '>'; else if (&CSDN->getValueAPF().getSemantics()==&APFloat::IEEEdouble) OS << '<' << CSDN->getValueAPF().convertToDouble() << '>'; else { OS << "<APFloat("; CSDN->getValueAPF().bitcastToAPInt().dump(); OS << ")>"; } } else if (const GlobalAddressSDNode *GADN = dyn_cast<GlobalAddressSDNode>(this)) { int64_t offset = GADN->getOffset(); OS << '<'; WriteAsOperand(OS, GADN->getGlobal()); OS << '>'; if (offset > 0) OS << " + " << offset; else OS << " " << offset; if (unsigned int TF = GADN->getTargetFlags()) OS << " [TF=" << TF << ']'; } else if (const FrameIndexSDNode *FIDN = dyn_cast<FrameIndexSDNode>(this)) { OS << "<" << FIDN->getIndex() << ">"; } else if (const JumpTableSDNode *JTDN = dyn_cast<JumpTableSDNode>(this)) { OS << "<" << JTDN->getIndex() << ">"; if (unsigned int TF = JTDN->getTargetFlags()) OS << " [TF=" << TF << ']'; } else if (const ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(this)){ int offset = CP->getOffset(); if (CP->isMachineConstantPoolEntry()) OS << "<" << *CP->getMachineCPVal() << ">"; else OS << "<" << *CP->getConstVal() << ">"; if (offset > 0) OS << " + " << offset; else OS << " " << offset; if (unsigned int TF = CP->getTargetFlags()) OS << " [TF=" << TF << ']'; } else if (const TargetIndexSDNode *TI = dyn_cast<TargetIndexSDNode>(this)) { OS << "<" << TI->getIndex() << '+' << TI->getOffset() << ">"; if (unsigned TF = TI->getTargetFlags()) OS << " [TF=" << TF << ']'; } else if (const BasicBlockSDNode *BBDN = dyn_cast<BasicBlockSDNode>(this)) { OS << "<"; const Value *LBB = (const Value*)BBDN->getBasicBlock()->getBasicBlock(); if (LBB) OS << LBB->getName() << " "; OS << (const void*)BBDN->getBasicBlock() << ">"; } else if (const RegisterSDNode *R = dyn_cast<RegisterSDNode>(this)) { OS << ' ' << PrintReg(R->getReg(), G ? G->getTarget().getRegisterInfo() :0); } else if (const ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(this)) { OS << "'" << ES->getSymbol() << "'"; if (unsigned int TF = ES->getTargetFlags()) OS << " [TF=" << TF << ']'; } else if (const SrcValueSDNode *M = dyn_cast<SrcValueSDNode>(this)) { if (M->getValue()) OS << "<" << M->getValue() << ">"; else OS << "<null>"; } else if (const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(this)) { if (MD->getMD()) OS << "<" << MD->getMD() << ">"; else OS << "<null>"; } else if (const VTSDNode *N = dyn_cast<VTSDNode>(this)) { OS << ":" << N->getVT().getEVTString(); } else if (const LoadSDNode *LD = dyn_cast<LoadSDNode>(this)) { OS << "<" << *LD->getMemOperand(); bool doExt = true; switch (LD->getExtensionType()) { default: doExt = false; break; case ISD::EXTLOAD: OS << ", anyext"; break; case ISD::SEXTLOAD: OS << ", sext"; break; case ISD::ZEXTLOAD: OS << ", zext"; break; } if (doExt) OS << " from " << LD->getMemoryVT().getEVTString(); const char *AM = getIndexedModeName(LD->getAddressingMode()); if (*AM) OS << ", " << AM; OS << ">"; } else if (const StoreSDNode *ST = dyn_cast<StoreSDNode>(this)) { OS << "<" << *ST->getMemOperand(); if (ST->isTruncatingStore()) OS << ", trunc to " << ST->getMemoryVT().getEVTString(); const char *AM = getIndexedModeName(ST->getAddressingMode()); if (*AM) OS << ", " << AM; OS << ">"; } else if (const MemSDNode* M = dyn_cast<MemSDNode>(this)) { OS << "<" << *M->getMemOperand() << ">"; } else if (const BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(this)) { OS << "<"; WriteAsOperand(OS, BA->getBlockAddress()->getFunction(), false); OS << ", "; WriteAsOperand(OS, BA->getBlockAddress()->getBasicBlock(), false); OS << ">"; if (unsigned int TF = BA->getTargetFlags()) OS << " [TF=" << TF << ']'; } if (G) if (unsigned Order = G->GetOrdering(this)) OS << " [ORD=" << Order << ']'; if (getNodeId() != -1) OS << " [ID=" << getNodeId() << ']'; DebugLoc dl = getDebugLoc(); if (G && !dl.isUnknown()) { DIScope Scope(dl.getScope(G->getMachineFunction().getFunction()->getContext())); OS << " dbg:"; // Omit the directory, since it's usually long and uninteresting. if (Scope.Verify()) OS << Scope.getFilename(); else OS << "<unknown>"; OS << ':' << dl.getLine(); if (dl.getCol() != 0) OS << ':' << dl.getCol(); } }
bool SancusModuleCreator::handleFunction(Function& f) { if (f.isIntrinsic() || f.isDeclaration()) return false; bool modified = false; // HACK: clang fails to add the needed attributes to main(), add them here if (f.getName() == "main") { f.setSection(".init9"); f.setAlignment(2); modified = true; } SancusModuleInfo info = getSancusModuleInfo(&f); if (info.isInSm) { f.setSection(info.getTextSection()); modified = true; } if (info.isEntry) entries.push_back(&f); std::map<Instruction*, Instruction*> verifications; std::map<Instruction*, Instruction*> replacements; for (inst_iterator it = inst_begin(f), end = inst_end(f); it != end; ++it) { Instruction* inst = &*it; CallSite cs(inst); if (!cs) continue; Function* callee = getCalledFunction(cs); if (callee == nullptr) { if (CallInst* ci = cast<CallInst>(&*it)) { if (ci->isInlineAsm()) continue; } DebugLoc loc = inst->getDebugLoc(); std::string locStr; if (!loc.isUnknown()) { Twine t(" (" + Twine(loc.getLine()) + ":" + Twine(loc.getCol()) + ")"); locStr = t.str(); } // FIXME this warning is too strict since it also fires on "normal" // function pointers. we should try to warn only when a function // pointer is used inside an SM or is created from an SM function. errs() << "WARNING: In function " << f.getName() << locStr << ": Function pointers not supported yet\n"; continue; } else if (callee->isIntrinsic()) continue; else if (callee->getName() == "sancus_call") { replacements[cs.getInstruction()] = handleSancusCall(cs).getInstruction(); continue; } if (Instruction* v = getVerification(info, getSancusModuleInfo(callee), *f.getParent())) { verifications[inst] = v; } Function* stub = getStub(f, *callee); cs.setCalledFunction(stub); if (stub != callee) modified = true; } for (auto pair : verifications) pair.second->insertBefore(pair.first); for (auto pair : replacements) { auto oldInst = pair.first; auto newInst = pair.second; newInst->insertBefore(oldInst); oldInst->replaceAllUsesWith(newInst); oldInst->eraseFromParent(); } return modified; }