diff options
author | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2016-06-29 20:37:43 +0000 |
---|---|---|
committer | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2016-06-29 20:37:43 +0000 |
commit | a5da256f9225b8a1fc4010a3c8101d91fba264bd (patch) | |
tree | 543dc475c2b597ef86defcf3ebdadc87db93e872 /llvm/lib/CodeGen/SafeStack.cpp | |
parent | b9e053cfd716434b5b3df2024709a498a381f816 (diff) | |
download | llvm-a5da256f9225b8a1fc4010a3c8101d91fba264bd.zip llvm-a5da256f9225b8a1fc4010a3c8101d91fba264bd.tar.gz llvm-a5da256f9225b8a1fc4010a3c8101d91fba264bd.tar.bz2 |
StackColoring for SafeStack.
This is a fix for PR27842.
An IR-level implementation of stack coloring tailored to work with
SafeStack. It is a bit weaker than the MI implementation in that it
does not the "lifetime start at first access" logic. This can be
improved in the future.
This patch also replaces the naive implementation of stack frame
layout with a greedy algorithm that can split existing stack slots
and even fit small objects inside the alignment padding of other
objects.
llvm-svn: 274162
Diffstat (limited to 'llvm/lib/CodeGen/SafeStack.cpp')
-rw-r--r-- | llvm/lib/CodeGen/SafeStack.cpp | 88 |
1 files changed, 50 insertions, 38 deletions
diff --git a/llvm/lib/CodeGen/SafeStack.cpp b/llvm/lib/CodeGen/SafeStack.cpp index b4a2ec4..19cd59b 100644 --- a/llvm/lib/CodeGen/SafeStack.cpp +++ b/llvm/lib/CodeGen/SafeStack.cpp @@ -15,6 +15,8 @@ // //===----------------------------------------------------------------------===// +#include "SafeStackColoring.h" +#include "SafeStackLayout.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/Triple.h" #include "llvm/Analysis/BranchProbabilityInfo.h" @@ -46,6 +48,7 @@ #include "llvm/Transforms/Utils/ModuleUtils.h" using namespace llvm; +using namespace llvm::safestack; #define DEBUG_TYPE "safestack" @@ -516,40 +519,66 @@ Value *SafeStack::moveStaticAllocasToUnsafeStack( DIBuilder DIB(*F.getParent()); - // Compute maximum alignment among static objects on the unsafe stack. - unsigned MaxAlignment = 0; + StackColoring SSC(F, StaticAllocas); + SSC.run(); + SSC.removeAllMarkers(); + + // Unsafe stack always grows down. + StackLayout SSL(StackAlignment); + if (StackGuardSlot) { + Type *Ty = StackGuardSlot->getAllocatedType(); + unsigned Align = + std::max(DL->getPrefTypeAlignment(Ty), StackGuardSlot->getAlignment()); + SSL.addObject(StackGuardSlot, getStaticAllocaAllocationSize(StackGuardSlot), + Align, SSC.getLiveRange(StackGuardSlot)); + } + for (Argument *Arg : ByValArguments) { Type *Ty = Arg->getType()->getPointerElementType(); + uint64_t Size = DL->getTypeStoreSize(Ty); + if (Size == 0) + Size = 1; // Don't create zero-sized stack objects. + + // Ensure the object is properly aligned. unsigned Align = std::max((unsigned)DL->getPrefTypeAlignment(Ty), Arg->getParamAlignment()); - if (Align > MaxAlignment) - MaxAlignment = Align; + SSL.addObject(Arg, Size, Align, SSC.getFullLiveRange()); } + for (AllocaInst *AI : StaticAllocas) { Type *Ty = AI->getAllocatedType(); + uint64_t Size = getStaticAllocaAllocationSize(AI); + if (Size == 0) + Size = 1; // Don't create zero-sized stack objects. + + // Ensure the object is properly aligned. unsigned Align = std::max((unsigned)DL->getPrefTypeAlignment(Ty), AI->getAlignment()); - if (Align > MaxAlignment) - MaxAlignment = Align; + + SSL.addObject(AI, Size, Align, SSC.getLiveRange(AI)); } - if (MaxAlignment > StackAlignment) { + SSL.computeLayout(); + unsigned FrameAlignment = SSL.getFrameAlignment(); + + // FIXME: tell SSL that we start at a less-then-MaxAlignment aligned location + // (AlignmentSkew). + if (FrameAlignment > StackAlignment) { // Re-align the base pointer according to the max requested alignment. - assert(isPowerOf2_32(MaxAlignment)); + assert(isPowerOf2_32(FrameAlignment)); IRB.SetInsertPoint(BasePointer->getNextNode()); BasePointer = cast<Instruction>(IRB.CreateIntToPtr( IRB.CreateAnd(IRB.CreatePtrToInt(BasePointer, IntPtrTy), - ConstantInt::get(IntPtrTy, ~uint64_t(MaxAlignment - 1))), + ConstantInt::get(IntPtrTy, ~uint64_t(FrameAlignment - 1))), StackPtrTy)); } - int64_t StaticOffset = 0; // Current stack top. IRB.SetInsertPoint(BasePointer->getNextNode()); if (StackGuardSlot) { - StaticOffset += getStaticAllocaAllocationSize(StackGuardSlot); + unsigned Offset = SSL.getObjectOffset(StackGuardSlot); Value *Off = IRB.CreateGEP(BasePointer, // BasePointer is i8* - ConstantInt::get(Int32Ty, -StaticOffset)); + ConstantInt::get(Int32Ty, -Offset)); Value *NewAI = IRB.CreateBitCast(Off, StackGuardSlot->getType(), "StackGuardSlot"); @@ -559,29 +588,21 @@ Value *SafeStack::moveStaticAllocasToUnsafeStack( } for (Argument *Arg : ByValArguments) { + unsigned Offset = SSL.getObjectOffset(Arg); Type *Ty = Arg->getType()->getPointerElementType(); uint64_t Size = DL->getTypeStoreSize(Ty); if (Size == 0) Size = 1; // Don't create zero-sized stack objects. - // Ensure the object is properly aligned. - unsigned Align = std::max((unsigned)DL->getPrefTypeAlignment(Ty), - Arg->getParamAlignment()); - - // Add alignment. - // NOTE: we ensure that BasePointer itself is aligned to >= Align. - StaticOffset += Size; - StaticOffset = alignTo(StaticOffset, Align); - Value *Off = IRB.CreateGEP(BasePointer, // BasePointer is i8* - ConstantInt::get(Int32Ty, -StaticOffset)); + ConstantInt::get(Int32Ty, -Offset)); Value *NewArg = IRB.CreateBitCast(Off, Arg->getType(), Arg->getName() + ".unsafe-byval"); // Replace alloc with the new location. replaceDbgDeclare(Arg, BasePointer, BasePointer->getNextNode(), DIB, - /*Deref=*/true, -StaticOffset); + /*Deref=*/true, -Offset); Arg->replaceAllUsesWith(NewArg); IRB.SetInsertPoint(cast<Instruction>(NewArg)->getNextNode()); IRB.CreateMemCpy(Off, Arg, Size, Arg->getParamAlignment()); @@ -590,23 +611,14 @@ Value *SafeStack::moveStaticAllocasToUnsafeStack( // Allocate space for every unsafe static AllocaInst on the unsafe stack. for (AllocaInst *AI : StaticAllocas) { IRB.SetInsertPoint(AI); + unsigned Offset = SSL.getObjectOffset(AI); - Type *Ty = AI->getAllocatedType(); uint64_t Size = getStaticAllocaAllocationSize(AI); if (Size == 0) Size = 1; // Don't create zero-sized stack objects. - // Ensure the object is properly aligned. - unsigned Align = - std::max((unsigned)DL->getPrefTypeAlignment(Ty), AI->getAlignment()); - - // Add alignment. - // NOTE: we ensure that BasePointer itself is aligned to >= Align. - StaticOffset += Size; - StaticOffset = alignTo(StaticOffset, Align); - - replaceDbgDeclareForAlloca(AI, BasePointer, DIB, /*Deref=*/true, -StaticOffset); - replaceDbgValueForAlloca(AI, BasePointer, DIB, -StaticOffset); + replaceDbgDeclareForAlloca(AI, BasePointer, DIB, /*Deref=*/true, -Offset); + replaceDbgValueForAlloca(AI, BasePointer, DIB, -Offset); // Replace uses of the alloca with the new location. // Insert address calculation close to each use to work around PR27844. @@ -623,7 +635,7 @@ Value *SafeStack::moveStaticAllocasToUnsafeStack( IRBuilder<> IRBUser(InsertBefore); Value *Off = IRBUser.CreateGEP(BasePointer, // BasePointer is i8* - ConstantInt::get(Int32Ty, -StaticOffset)); + ConstantInt::get(Int32Ty, -Offset)); Value *Replacement = IRBUser.CreateBitCast(Off, AI->getType(), Name); if (auto *PHI = dyn_cast<PHINode>(User)) { @@ -644,13 +656,13 @@ Value *SafeStack::moveStaticAllocasToUnsafeStack( // Re-align BasePointer so that our callees would see it aligned as // expected. // FIXME: no need to update BasePointer in leaf functions. - StaticOffset = alignTo(StaticOffset, StackAlignment); + unsigned FrameSize = alignTo(SSL.getFrameSize(), StackAlignment); // Update shadow stack pointer in the function epilogue. IRB.SetInsertPoint(BasePointer->getNextNode()); Value *StaticTop = - IRB.CreateGEP(BasePointer, ConstantInt::get(Int32Ty, -StaticOffset), + IRB.CreateGEP(BasePointer, ConstantInt::get(Int32Ty, -FrameSize), "unsafe_stack_static_top"); IRB.CreateStore(StaticTop, UnsafeStackPtr); return StaticTop; |