diff options
Diffstat (limited to 'llvm/lib/CodeGen/SafeStack.cpp')
-rw-r--r-- | llvm/lib/CodeGen/SafeStack.cpp | 39 |
1 files changed, 31 insertions, 8 deletions
diff --git a/llvm/lib/CodeGen/SafeStack.cpp b/llvm/lib/CodeGen/SafeStack.cpp index 28f5ed861ab..457acb1503c 100644 --- a/llvm/lib/CodeGen/SafeStack.cpp +++ b/llvm/lib/CodeGen/SafeStack.cpp @@ -606,16 +606,39 @@ Value *SafeStack::moveStaticAllocasToUnsafeStack( StaticOffset += Size; StaticOffset = alignTo(StaticOffset, Align); - Value *Off = IRB.CreateGEP(BasePointer, // BasePointer is i8* - ConstantInt::get(Int32Ty, -StaticOffset)); - Value *NewAI = IRB.CreateBitCast(Off, AI->getType(), AI->getName()); - if (AI->hasName() && isa<Instruction>(NewAI)) - cast<Instruction>(NewAI)->takeName(AI); - - // Replace alloc with the new location. replaceDbgDeclareForAlloca(AI, BasePointer, DIB, /*Deref=*/true, -StaticOffset); replaceDbgValueForAlloca(AI, BasePointer, DIB, -StaticOffset); - AI->replaceAllUsesWith(NewAI); + + // Replace uses of the alloca with the new location. + // Insert address calculation close to each use to work around PR27844. + std::string Name = std::string(AI->getName()) + ".unsafe"; + while (!AI->use_empty()) { + Use &U = *AI->use_begin(); + Instruction *User = cast<Instruction>(U.getUser()); + + Instruction *InsertBefore; + if (auto *PHI = dyn_cast<PHINode>(User)) + InsertBefore = PHI->getIncomingBlock(U)->getTerminator(); + else + InsertBefore = User; + + IRBuilder<> IRBUser(InsertBefore); + Value *Off = IRBUser.CreateGEP(BasePointer, // BasePointer is i8* + ConstantInt::get(Int32Ty, -StaticOffset)); + Value *Replacement = IRBUser.CreateBitCast(Off, AI->getType(), Name); + + if (auto *PHI = dyn_cast<PHINode>(User)) { + // PHI nodes may have multiple incoming edges from the same BB (why??), + // all must be updated at once with the same incoming value. + auto *BB = PHI->getIncomingBlock(U); + for (unsigned I = 0; I < PHI->getNumIncomingValues(); ++I) + if (PHI->getIncomingBlock(I) == BB) + PHI->setIncomingValue(I, Replacement); + } else { + U.set(Replacement); + } + } + AI->eraseFromParent(); } |