aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/SafeStack.cpp
diff options
context:
space:
mode:
authorEvgeniy Stepanov <eugeni.stepanov@gmail.com>2016-06-29 20:37:43 +0000
committerEvgeniy Stepanov <eugeni.stepanov@gmail.com>2016-06-29 20:37:43 +0000
commita5da256f9225b8a1fc4010a3c8101d91fba264bd (patch)
tree543dc475c2b597ef86defcf3ebdadc87db93e872 /llvm/lib/CodeGen/SafeStack.cpp
parentb9e053cfd716434b5b3df2024709a498a381f816 (diff)
downloadllvm-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.cpp88
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;