1 //===- StackSafetyAnalysis.cpp - Stack memory safety analysis -------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 //===----------------------------------------------------------------------===// 10 11 #include "llvm/Analysis/StackSafetyAnalysis.h" 12 #include "llvm/ADT/APInt.h" 13 #include "llvm/Analysis/ScalarEvolutionExpressions.h" 14 #include "llvm/IR/ConstantRange.h" 15 #include "llvm/IR/DerivedTypes.h" 16 #include "llvm/IR/GlobalValue.h" 17 #include "llvm/IR/InstIterator.h" 18 #include "llvm/IR/Instructions.h" 19 #include "llvm/IR/IntrinsicInst.h" 20 #include "llvm/InitializePasses.h" 21 #include "llvm/Support/Casting.h" 22 #include "llvm/Support/CommandLine.h" 23 #include "llvm/Support/raw_ostream.h" 24 #include <algorithm> 25 #include <memory> 26 27 using namespace llvm; 28 29 #define DEBUG_TYPE "stack-safety" 30 31 static cl::opt<int> StackSafetyMaxIterations("stack-safety-max-iterations", 32 cl::init(20), cl::Hidden); 33 34 namespace { 35 36 using GVToSSI = StackSafetyGlobalInfo::GVToSSI; 37 38 /// Rewrite an SCEV expression for a memory access address to an expression that 39 /// represents offset from the given alloca. 40 class AllocaOffsetRewriter : public SCEVRewriteVisitor<AllocaOffsetRewriter> { 41 const Value *AllocaPtr; 42 43 public: 44 AllocaOffsetRewriter(ScalarEvolution &SE, const Value *AllocaPtr) 45 : SCEVRewriteVisitor(SE), AllocaPtr(AllocaPtr) {} 46 47 const SCEV *visitUnknown(const SCEVUnknown *Expr) { 48 // FIXME: look through one or several levels of definitions? 49 // This can be inttoptr(AllocaPtr) and SCEV would not unwrap 50 // it for us. 51 if (Expr->getValue() == AllocaPtr) 52 return SE.getZero(Expr->getType()); 53 return Expr; 54 } 55 }; 56 57 /// Describes use of address in as a function call argument. 58 struct PassAsArgInfo { 59 /// Function being called. 60 const GlobalValue *Callee = nullptr; 61 /// Index of argument which pass address. 62 size_t ParamNo = 0; 63 // Offset range of address from base address (alloca or calling function 64 // argument). 65 // Range should never set to empty-set, that is an invalid access range 66 // that can cause empty-set to be propagated with ConstantRange::add 67 ConstantRange Offset; 68 PassAsArgInfo(const GlobalValue *Callee, size_t ParamNo, ConstantRange Offset) 69 : Callee(Callee), ParamNo(ParamNo), Offset(Offset) {} 70 71 StringRef getName() const { return Callee->getName(); } 72 }; 73 74 raw_ostream &operator<<(raw_ostream &OS, const PassAsArgInfo &P) { 75 return OS << "@" << P.getName() << "(arg" << P.ParamNo << ", " << P.Offset 76 << ")"; 77 } 78 79 /// Describe uses of address (alloca or parameter) inside of the function. 80 struct UseInfo { 81 // Access range if the address (alloca or parameters). 82 // It is allowed to be empty-set when there are no known accesses. 83 ConstantRange Range; 84 85 // List of calls which pass address as an argument. 86 SmallVector<PassAsArgInfo, 4> Calls; 87 88 explicit UseInfo(unsigned PointerSize) : Range{PointerSize, false} {} 89 90 void updateRange(const ConstantRange &R) { 91 assert(!R.isUpperSignWrapped()); 92 Range = Range.unionWith(R); 93 assert(!Range.isUpperSignWrapped()); 94 } 95 }; 96 97 raw_ostream &operator<<(raw_ostream &OS, const UseInfo &U) { 98 OS << U.Range; 99 for (auto &Call : U.Calls) 100 OS << ", " << Call; 101 return OS; 102 } 103 104 // Check if we should bailout for such ranges. 105 bool isUnsafe(const ConstantRange &R) { 106 return R.isEmptySet() || R.isFullSet() || R.isUpperSignWrapped(); 107 } 108 109 /// Calculate the allocation size of a given alloca. Returns empty range 110 // in case of confution. 111 ConstantRange getStaticAllocaSizeRange(const AllocaInst &AI) { 112 const DataLayout &DL = AI.getModule()->getDataLayout(); 113 TypeSize TS = DL.getTypeAllocSize(AI.getAllocatedType()); 114 unsigned PointerSize = DL.getMaxPointerSizeInBits(); 115 // Fallback to empty range for alloca size. 116 ConstantRange R = ConstantRange::getEmpty(PointerSize); 117 if (TS.isScalable()) 118 return R; 119 APInt APSize(PointerSize, TS.getFixedSize(), true); 120 if (APSize.isNonPositive()) 121 return R; 122 if (AI.isArrayAllocation()) { 123 auto C = dyn_cast<ConstantInt>(AI.getArraySize()); 124 if (!C) 125 return R; 126 bool Overflow = false; 127 APInt Mul = C->getValue(); 128 if (Mul.isNonPositive()) 129 return R; 130 Mul = Mul.sextOrTrunc(PointerSize); 131 APSize = APSize.smul_ov(Mul, Overflow); 132 if (Overflow) 133 return R; 134 } 135 R = ConstantRange(APInt::getNullValue(PointerSize), APSize); 136 assert(!isUnsafe(R)); 137 return R; 138 } 139 140 /// Describes uses of allocas and parameters inside of a single function. 141 struct FunctionInfo { 142 SmallVector<UseInfo, 4> Allocas; 143 SmallVector<UseInfo, 4> Params; 144 const GlobalValue *GV = nullptr; 145 // TODO: describe return value as depending on one or more of its arguments. 146 147 // StackSafetyDataFlowAnalysis counter stored here for faster access. 148 int UpdateCount = 0; 149 150 FunctionInfo() = default; 151 FunctionInfo(const Function *F) : GV(F){}; 152 explicit FunctionInfo(const GlobalAlias *A); 153 154 bool IsDSOLocal() const { return GV->isDSOLocal(); }; 155 156 bool IsInterposable() const { return GV->isInterposable(); }; 157 158 StringRef getName() const { return GV->getName(); } 159 160 void print(raw_ostream &O, StringRef Name, const Function *F) const { 161 // TODO: Consider different printout format after 162 // StackSafetyDataFlowAnalysis. Calls and parameters are irrelevant then. 163 O << " @" << Name << (IsDSOLocal() ? "" : " dso_preemptable") 164 << (IsInterposable() ? " interposable" : "") << "\n"; 165 166 O << " args uses:\n"; 167 size_t Pos = 0; 168 for (auto &P : Params) { 169 StringRef Name = "<N/A>"; 170 if (F) 171 Name = F->getArg(Pos)->getName(); 172 O << " " << Name << "[]: " << P << "\n"; 173 ++Pos; 174 } 175 176 O << " allocas uses:\n"; 177 if (F) { 178 size_t Pos = 0; 179 for (auto &I : instructions(F)) { 180 if (auto AI = dyn_cast<AllocaInst>(&I)) { 181 auto &AS = Allocas[Pos]; 182 O << " " << AI->getName() << "[" 183 << getStaticAllocaSizeRange(*AI).getUpper() << "]: " << AS << "\n"; 184 ++Pos; 185 } 186 } 187 } else { 188 assert(Allocas.empty()); 189 } 190 } 191 }; 192 193 FunctionInfo::FunctionInfo(const GlobalAlias *A) : GV(A) { 194 unsigned PointerSize = A->getParent()->getDataLayout().getPointerSizeInBits(); 195 const GlobalObject *Aliasee = A->getBaseObject(); 196 const FunctionType *Type = cast<FunctionType>(Aliasee->getValueType()); 197 // 'Forward' all parameters to this alias to the aliasee 198 for (unsigned ArgNo = 0; ArgNo < Type->getNumParams(); ArgNo++) { 199 Params.emplace_back(PointerSize); 200 UseInfo &US = Params.back(); 201 US.Calls.emplace_back(Aliasee, ArgNo, ConstantRange(APInt(PointerSize, 0))); 202 } 203 } 204 205 } // namespace 206 207 struct StackSafetyInfo::InfoTy { 208 FunctionInfo Info; 209 }; 210 211 StackSafetyInfo makeSSI(FunctionInfo Info) { 212 return StackSafetyInfo(StackSafetyInfo::InfoTy{std::move(Info)}); 213 } 214 215 namespace { 216 217 class StackSafetyLocalAnalysis { 218 Function &F; 219 const DataLayout &DL; 220 ScalarEvolution &SE; 221 unsigned PointerSize = 0; 222 223 const ConstantRange UnknownRange; 224 225 ConstantRange offsetFrom(Value *Addr, Value *Base); 226 ConstantRange getAccessRange(Value *Addr, Value *Base, 227 ConstantRange SizeRange); 228 ConstantRange getAccessRange(Value *Addr, Value *Base, TypeSize Size); 229 ConstantRange getMemIntrinsicAccessRange(const MemIntrinsic *MI, const Use &U, 230 Value *Base); 231 232 bool analyzeAllUses(Value *Ptr, UseInfo &AS); 233 234 public: 235 StackSafetyLocalAnalysis(Function &F, ScalarEvolution &SE) 236 : F(F), DL(F.getParent()->getDataLayout()), SE(SE), 237 PointerSize(DL.getPointerSizeInBits()), 238 UnknownRange(PointerSize, true) {} 239 240 // Run the transformation on the associated function. 241 FunctionInfo run(); 242 }; 243 244 ConstantRange StackSafetyLocalAnalysis::offsetFrom(Value *Addr, Value *Base) { 245 if (!SE.isSCEVable(Addr->getType())) 246 return UnknownRange; 247 248 AllocaOffsetRewriter Rewriter(SE, Base); 249 const SCEV *Expr = Rewriter.visit(SE.getSCEV(Addr)); 250 ConstantRange Offset = SE.getSignedRange(Expr); 251 if (isUnsafe(Offset)) 252 return UnknownRange; 253 return Offset.sextOrTrunc(PointerSize); 254 } 255 256 ConstantRange 257 StackSafetyLocalAnalysis::getAccessRange(Value *Addr, Value *Base, 258 ConstantRange SizeRange) { 259 // Zero-size loads and stores do not access memory. 260 if (SizeRange.isEmptySet()) 261 return ConstantRange::getEmpty(PointerSize); 262 assert(!isUnsafe(SizeRange)); 263 264 ConstantRange Offsets = offsetFrom(Addr, Base); 265 if (isUnsafe(Offsets)) 266 return UnknownRange; 267 268 if (Offsets.signedAddMayOverflow(SizeRange) != 269 ConstantRange::OverflowResult::NeverOverflows) 270 return UnknownRange; 271 Offsets = Offsets.add(SizeRange); 272 if (isUnsafe(Offsets)) 273 return UnknownRange; 274 return Offsets; 275 } 276 277 ConstantRange StackSafetyLocalAnalysis::getAccessRange(Value *Addr, Value *Base, 278 TypeSize Size) { 279 if (Size.isScalable()) 280 return UnknownRange; 281 APInt APSize(PointerSize, Size.getFixedSize(), true); 282 if (APSize.isNegative()) 283 return UnknownRange; 284 return getAccessRange( 285 Addr, Base, ConstantRange(APInt::getNullValue(PointerSize), APSize)); 286 } 287 288 ConstantRange StackSafetyLocalAnalysis::getMemIntrinsicAccessRange( 289 const MemIntrinsic *MI, const Use &U, Value *Base) { 290 if (auto MTI = dyn_cast<MemTransferInst>(MI)) { 291 if (MTI->getRawSource() != U && MTI->getRawDest() != U) 292 return ConstantRange::getEmpty(PointerSize); 293 } else { 294 if (MI->getRawDest() != U) 295 return ConstantRange::getEmpty(PointerSize); 296 } 297 298 auto *CalculationTy = IntegerType::getIntNTy(SE.getContext(), PointerSize); 299 if (!SE.isSCEVable(MI->getLength()->getType())) 300 return UnknownRange; 301 302 const SCEV *Expr = 303 SE.getTruncateOrZeroExtend(SE.getSCEV(MI->getLength()), CalculationTy); 304 ConstantRange Sizes = SE.getSignedRange(Expr); 305 if (Sizes.getUpper().isNegative() || isUnsafe(Sizes)) 306 return UnknownRange; 307 Sizes = Sizes.sextOrTrunc(PointerSize); 308 ConstantRange SizeRange(APInt::getNullValue(PointerSize), 309 Sizes.getUpper() - 1); 310 return getAccessRange(U, Base, SizeRange); 311 } 312 313 /// The function analyzes all local uses of Ptr (alloca or argument) and 314 /// calculates local access range and all function calls where it was used. 315 bool StackSafetyLocalAnalysis::analyzeAllUses(Value *Ptr, UseInfo &US) { 316 SmallPtrSet<const Value *, 16> Visited; 317 SmallVector<const Value *, 8> WorkList; 318 WorkList.push_back(Ptr); 319 320 // A DFS search through all uses of the alloca in bitcasts/PHI/GEPs/etc. 321 while (!WorkList.empty()) { 322 const Value *V = WorkList.pop_back_val(); 323 for (const Use &UI : V->uses()) { 324 auto I = cast<const Instruction>(UI.getUser()); 325 assert(V == UI.get()); 326 327 switch (I->getOpcode()) { 328 case Instruction::Load: { 329 US.updateRange( 330 getAccessRange(UI, Ptr, DL.getTypeStoreSize(I->getType()))); 331 break; 332 } 333 334 case Instruction::VAArg: 335 // "va-arg" from a pointer is safe. 336 break; 337 case Instruction::Store: { 338 if (V == I->getOperand(0)) { 339 // Stored the pointer - conservatively assume it may be unsafe. 340 US.updateRange(UnknownRange); 341 return false; 342 } 343 US.updateRange(getAccessRange( 344 UI, Ptr, DL.getTypeStoreSize(I->getOperand(0)->getType()))); 345 break; 346 } 347 348 case Instruction::Ret: 349 // Information leak. 350 // FIXME: Process parameters correctly. This is a leak only if we return 351 // alloca. 352 US.updateRange(UnknownRange); 353 return false; 354 355 case Instruction::Call: 356 case Instruction::Invoke: { 357 const auto &CB = cast<CallBase>(*I); 358 359 if (I->isLifetimeStartOrEnd()) 360 break; 361 362 if (const MemIntrinsic *MI = dyn_cast<MemIntrinsic>(I)) { 363 US.updateRange(getMemIntrinsicAccessRange(MI, UI, Ptr)); 364 break; 365 } 366 367 // FIXME: consult devirt? 368 // Do not follow aliases, otherwise we could inadvertently follow 369 // dso_preemptable aliases or aliases with interposable linkage. 370 const GlobalValue *Callee = 371 dyn_cast<GlobalValue>(CB.getCalledOperand()->stripPointerCasts()); 372 if (!Callee) { 373 US.updateRange(UnknownRange); 374 return false; 375 } 376 377 assert(isa<Function>(Callee) || isa<GlobalAlias>(Callee)); 378 379 auto B = CB.arg_begin(), E = CB.arg_end(); 380 int Found = 0; 381 for (auto A = B; A != E; ++A) { 382 if (A->get() == V) { 383 ++Found; 384 ConstantRange Offset = offsetFrom(UI, Ptr); 385 US.Calls.emplace_back(Callee, A - B, Offset); 386 } 387 } 388 if (!Found) { 389 US.updateRange(UnknownRange); 390 return false; 391 } 392 393 break; 394 } 395 396 default: 397 if (Visited.insert(I).second) 398 WorkList.push_back(cast<const Instruction>(I)); 399 } 400 } 401 } 402 403 return true; 404 } 405 406 FunctionInfo StackSafetyLocalAnalysis::run() { 407 FunctionInfo Info(&F); 408 assert(!F.isDeclaration() && 409 "Can't run StackSafety on a function declaration"); 410 411 LLVM_DEBUG(dbgs() << "[StackSafety] " << F.getName() << "\n"); 412 413 for (auto &I : instructions(F)) { 414 if (auto AI = dyn_cast<AllocaInst>(&I)) { 415 Info.Allocas.emplace_back(PointerSize); 416 UseInfo &AS = Info.Allocas.back(); 417 analyzeAllUses(AI, AS); 418 } 419 } 420 421 for (Argument &A : make_range(F.arg_begin(), F.arg_end())) { 422 Info.Params.emplace_back(PointerSize); 423 UseInfo &PS = Info.Params.back(); 424 analyzeAllUses(&A, PS); 425 } 426 427 LLVM_DEBUG(Info.print(dbgs(), F.getName(), &F)); 428 LLVM_DEBUG(dbgs() << "[StackSafety] done\n"); 429 return Info; 430 } 431 432 class StackSafetyDataFlowAnalysis { 433 using FunctionMap = std::map<const GlobalValue *, FunctionInfo>; 434 435 FunctionMap Functions; 436 // Callee-to-Caller multimap. 437 DenseMap<const GlobalValue *, SmallVector<const GlobalValue *, 4>> Callers; 438 SetVector<const GlobalValue *> WorkList; 439 440 unsigned PointerSize = 0; 441 const ConstantRange UnknownRange; 442 443 ConstantRange getArgumentAccessRange(const GlobalValue *Callee, 444 unsigned ParamNo) const; 445 bool updateOneUse(UseInfo &US, bool UpdateToFullSet); 446 void updateOneNode(const GlobalValue *Callee, FunctionInfo &FS); 447 void updateOneNode(const GlobalValue *Callee) { 448 updateOneNode(Callee, Functions.find(Callee)->second); 449 } 450 void updateAllNodes() { 451 for (auto &F : Functions) 452 updateOneNode(F.first, F.second); 453 } 454 void runDataFlow(); 455 #ifndef NDEBUG 456 void verifyFixedPoint(); 457 #endif 458 459 public: 460 StackSafetyDataFlowAnalysis( 461 Module &M, std::function<const FunctionInfo &(Function &)> FI); 462 GVToSSI run(); 463 }; 464 465 StackSafetyDataFlowAnalysis::StackSafetyDataFlowAnalysis( 466 Module &M, std::function<const FunctionInfo &(Function &)> FI) 467 : PointerSize(M.getDataLayout().getPointerSizeInBits()), 468 UnknownRange(PointerSize, true) { 469 // Without ThinLTO, run the local analysis for every function in the TU and 470 // then run the DFA. 471 for (auto &F : M.functions()) 472 if (!F.isDeclaration()) 473 Functions.emplace(&F, FI(F)); 474 for (auto &A : M.aliases()) 475 if (isa<Function>(A.getBaseObject())) 476 Functions.emplace(&A, FunctionInfo(&A)); 477 } 478 479 ConstantRange 480 StackSafetyDataFlowAnalysis::getArgumentAccessRange(const GlobalValue *Callee, 481 unsigned ParamNo) const { 482 auto IT = Functions.find(Callee); 483 // Unknown callee (outside of LTO domain or an indirect call). 484 if (IT == Functions.end()) 485 return UnknownRange; 486 const FunctionInfo &FS = IT->second; 487 // The definition of this symbol may not be the definition in this linkage 488 // unit. 489 if (!FS.IsDSOLocal() || FS.IsInterposable()) 490 return UnknownRange; 491 if (ParamNo >= FS.Params.size()) // possibly vararg 492 return UnknownRange; 493 return FS.Params[ParamNo].Range; 494 } 495 496 bool StackSafetyDataFlowAnalysis::updateOneUse(UseInfo &US, 497 bool UpdateToFullSet) { 498 bool Changed = false; 499 for (auto &CS : US.Calls) { 500 assert(!CS.Offset.isEmptySet() && 501 "Param range can't be empty-set, invalid offset range"); 502 503 ConstantRange CalleeRange = getArgumentAccessRange(CS.Callee, CS.ParamNo); 504 CalleeRange = CalleeRange.add(CS.Offset); 505 if (!US.Range.contains(CalleeRange)) { 506 Changed = true; 507 if (UpdateToFullSet) 508 US.Range = UnknownRange; 509 else 510 US.Range = US.Range.unionWith(CalleeRange); 511 } 512 } 513 return Changed; 514 } 515 516 void StackSafetyDataFlowAnalysis::updateOneNode(const GlobalValue *Callee, 517 FunctionInfo &FS) { 518 bool UpdateToFullSet = FS.UpdateCount > StackSafetyMaxIterations; 519 bool Changed = false; 520 for (auto &AS : FS.Allocas) 521 Changed |= updateOneUse(AS, UpdateToFullSet); 522 for (auto &PS : FS.Params) 523 Changed |= updateOneUse(PS, UpdateToFullSet); 524 525 if (Changed) { 526 LLVM_DEBUG(dbgs() << "=== update [" << FS.UpdateCount 527 << (UpdateToFullSet ? ", full-set" : "") << "] " << &FS 528 << "\n"); 529 // Callers of this function may need updating. 530 for (auto &CallerID : Callers[Callee]) 531 WorkList.insert(CallerID); 532 533 ++FS.UpdateCount; 534 } 535 } 536 537 void StackSafetyDataFlowAnalysis::runDataFlow() { 538 Callers.clear(); 539 WorkList.clear(); 540 541 SmallVector<const GlobalValue *, 16> Callees; 542 for (auto &F : Functions) { 543 Callees.clear(); 544 FunctionInfo &FS = F.second; 545 for (auto &AS : FS.Allocas) 546 for (auto &CS : AS.Calls) 547 Callees.push_back(CS.Callee); 548 for (auto &PS : FS.Params) 549 for (auto &CS : PS.Calls) 550 Callees.push_back(CS.Callee); 551 552 llvm::sort(Callees); 553 Callees.erase(std::unique(Callees.begin(), Callees.end()), Callees.end()); 554 555 for (auto &Callee : Callees) 556 Callers[Callee].push_back(F.first); 557 } 558 559 updateAllNodes(); 560 561 while (!WorkList.empty()) { 562 const GlobalValue *Callee = WorkList.back(); 563 WorkList.pop_back(); 564 updateOneNode(Callee); 565 } 566 } 567 568 #ifndef NDEBUG 569 void StackSafetyDataFlowAnalysis::verifyFixedPoint() { 570 WorkList.clear(); 571 updateAllNodes(); 572 assert(WorkList.empty()); 573 } 574 #endif 575 576 GVToSSI StackSafetyDataFlowAnalysis::run() { 577 runDataFlow(); 578 LLVM_DEBUG(verifyFixedPoint()); 579 580 GVToSSI SSI; 581 for (auto &F : Functions) 582 SSI.emplace(F.first, makeSSI(F.second)); 583 return SSI; 584 } 585 586 bool setStackSafetyMetadata(Module &M, const GVToSSI &SSGI) { 587 bool Changed = false; 588 for (auto &F : M.functions()) { 589 if (F.isDeclaration() || F.hasOptNone()) 590 continue; 591 auto Iter = SSGI.find(&F); 592 if (Iter == SSGI.end()) 593 continue; 594 const FunctionInfo &Summary = Iter->second.getInfo().Info; 595 size_t Pos = 0; 596 for (auto &I : instructions(F)) { 597 if (auto AI = dyn_cast<AllocaInst>(&I)) { 598 auto &AS = Summary.Allocas[Pos]; 599 if (getStaticAllocaSizeRange(*AI).contains(AS.Range)) { 600 AI->setMetadata(M.getMDKindID("stack-safe"), 601 MDNode::get(M.getContext(), None)); 602 Changed = true; 603 } 604 ++Pos; 605 } 606 } 607 } 608 return Changed; 609 } 610 611 } // end anonymous namespace 612 613 StackSafetyInfo::StackSafetyInfo(StackSafetyInfo &&) = default; 614 StackSafetyInfo &StackSafetyInfo::operator=(StackSafetyInfo &&) = default; 615 616 StackSafetyInfo::StackSafetyInfo(InfoTy Info) 617 : Info(new InfoTy(std::move(Info))) {} 618 619 StackSafetyInfo::~StackSafetyInfo() = default; 620 621 void StackSafetyInfo::print(raw_ostream &O, const GlobalValue &F) const { 622 Info->Info.print(O, F.getName(), dyn_cast<Function>(&F)); 623 } 624 625 bool StackSafetyGlobalInfo::setMetadata(Module &M) const { 626 return setStackSafetyMetadata(M, SSGI); 627 } 628 629 void StackSafetyGlobalInfo::print(raw_ostream &O) const { 630 if (SSGI.empty()) 631 return; 632 const Module &M = *SSGI.begin()->first->getParent(); 633 for (auto &F : M.functions()) { 634 if (!F.isDeclaration()) { 635 SSGI.find(&F)->second.print(O, F); 636 O << "\n"; 637 } 638 } 639 for (auto &A : M.aliases()) { 640 SSGI.find(&A)->second.print(O, A); 641 O << "\n"; 642 } 643 } 644 645 LLVM_DUMP_METHOD void StackSafetyGlobalInfo::dump() const { print(dbgs()); } 646 647 AnalysisKey StackSafetyAnalysis::Key; 648 649 StackSafetyInfo StackSafetyAnalysis::run(Function &F, 650 FunctionAnalysisManager &AM) { 651 StackSafetyLocalAnalysis SSLA(F, AM.getResult<ScalarEvolutionAnalysis>(F)); 652 return makeSSI(SSLA.run()); 653 } 654 655 PreservedAnalyses StackSafetyPrinterPass::run(Function &F, 656 FunctionAnalysisManager &AM) { 657 OS << "'Stack Safety Local Analysis' for function '" << F.getName() << "'\n"; 658 AM.getResult<StackSafetyAnalysis>(F).print(OS, F); 659 return PreservedAnalyses::all(); 660 } 661 662 char StackSafetyInfoWrapperPass::ID = 0; 663 664 StackSafetyInfoWrapperPass::StackSafetyInfoWrapperPass() : FunctionPass(ID) { 665 initializeStackSafetyInfoWrapperPassPass(*PassRegistry::getPassRegistry()); 666 } 667 668 void StackSafetyInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { 669 AU.addRequired<ScalarEvolutionWrapperPass>(); 670 AU.setPreservesAll(); 671 } 672 673 void StackSafetyInfoWrapperPass::print(raw_ostream &O, const Module *M) const { 674 SSI->print(O, *F); 675 } 676 677 bool StackSafetyInfoWrapperPass::runOnFunction(Function &F) { 678 StackSafetyLocalAnalysis SSLA( 679 F, getAnalysis<ScalarEvolutionWrapperPass>().getSE()); 680 SSI = makeSSI(SSLA.run()); 681 this->F = &F; 682 return false; 683 } 684 685 AnalysisKey StackSafetyGlobalAnalysis::Key; 686 687 StackSafetyGlobalInfo 688 StackSafetyGlobalAnalysis::run(Module &M, ModuleAnalysisManager &AM) { 689 FunctionAnalysisManager &FAM = 690 AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); 691 692 StackSafetyDataFlowAnalysis SSDFA( 693 M, [&FAM](Function &F) -> const FunctionInfo & { 694 return FAM.getResult<StackSafetyAnalysis>(F).getInfo().Info; 695 }); 696 return SSDFA.run(); 697 } 698 699 PreservedAnalyses StackSafetyGlobalPrinterPass::run(Module &M, 700 ModuleAnalysisManager &AM) { 701 OS << "'Stack Safety Analysis' for module '" << M.getName() << "'\n"; 702 AM.getResult<StackSafetyGlobalAnalysis>(M).print(OS); 703 return PreservedAnalyses::all(); 704 } 705 706 PreservedAnalyses 707 StackSafetyGlobalAnnotatorPass::run(Module &M, ModuleAnalysisManager &AM) { 708 auto &SSGI = AM.getResult<StackSafetyGlobalAnalysis>(M); 709 SSGI.setMetadata(M); 710 return PreservedAnalyses::all(); 711 } 712 713 char StackSafetyGlobalInfoWrapperPass::ID = 0; 714 715 StackSafetyGlobalInfoWrapperPass::StackSafetyGlobalInfoWrapperPass( 716 bool SetMetadata) 717 : ModulePass(ID), SetMetadata(SetMetadata) { 718 initializeStackSafetyGlobalInfoWrapperPassPass( 719 *PassRegistry::getPassRegistry()); 720 } 721 722 void StackSafetyGlobalInfoWrapperPass::print(raw_ostream &O, 723 const Module *M) const { 724 SSGI.print(O); 725 } 726 727 void StackSafetyGlobalInfoWrapperPass::getAnalysisUsage( 728 AnalysisUsage &AU) const { 729 AU.addRequired<StackSafetyInfoWrapperPass>(); 730 } 731 732 bool StackSafetyGlobalInfoWrapperPass::runOnModule(Module &M) { 733 StackSafetyDataFlowAnalysis SSDFA( 734 M, [this](Function &F) -> const FunctionInfo & { 735 return getAnalysis<StackSafetyInfoWrapperPass>(F) 736 .getResult() 737 .getInfo() 738 .Info; 739 }); 740 SSGI = SSDFA.run(); 741 return SetMetadata ? SSGI.setMetadata(M) : false; 742 } 743 744 ModulePass *llvm::createStackSafetyGlobalInfoWrapperPass(bool SetMetadata) { 745 return new StackSafetyGlobalInfoWrapperPass(SetMetadata); 746 } 747 748 static const char LocalPassArg[] = "stack-safety-local"; 749 static const char LocalPassName[] = "Stack Safety Local Analysis"; 750 INITIALIZE_PASS_BEGIN(StackSafetyInfoWrapperPass, LocalPassArg, LocalPassName, 751 false, true) 752 INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass) 753 INITIALIZE_PASS_END(StackSafetyInfoWrapperPass, LocalPassArg, LocalPassName, 754 false, true) 755 756 static const char GlobalPassName[] = "Stack Safety Analysis"; 757 INITIALIZE_PASS_BEGIN(StackSafetyGlobalInfoWrapperPass, DEBUG_TYPE, 758 GlobalPassName, false, false) 759 INITIALIZE_PASS_DEPENDENCY(StackSafetyInfoWrapperPass) 760 INITIALIZE_PASS_END(StackSafetyGlobalInfoWrapperPass, DEBUG_TYPE, 761 GlobalPassName, false, false) 762