Index: llvm/trunk/lib/CodeGen/SafeStack.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SafeStack.cpp +++ llvm/trunk/lib/CodeGen/SafeStack.cpp @@ -24,6 +24,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/BranchProbabilityInfo.h" +#include "llvm/Analysis/InlineCost.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" @@ -61,6 +62,7 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" +#include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Transforms/Utils/Local.h" #include #include @@ -88,6 +90,13 @@ } // namespace llvm +/// Use __safestack_pointer_address even if the platform has a faster way of +/// access safe stack pointer. +static cl::opt + SafeStackUsePointerAddress("safestack-use-pointer-address", + cl::init(false), cl::Hidden); + + namespace { /// Rewrite an SCEV expression for a memory access address to an expression that @@ -191,6 +200,9 @@ bool IsAccessSafe(Value *Addr, uint64_t Size, const Value *AllocaPtr, uint64_t AllocaSize); + bool ShouldInlinePointerAddress(CallSite &CS); + void TryInlinePointerAddress(); + public: SafeStack(Function &F, const TargetLoweringBase &TL, const DataLayout &DL, ScalarEvolution &SE) @@ -695,6 +707,35 @@ } } +bool SafeStack::ShouldInlinePointerAddress(CallSite &CS) { + Function *Callee = CS.getCalledFunction(); + if (CS.hasFnAttr(Attribute::AlwaysInline) && isInlineViable(*Callee)) + return true; + if (Callee->isInterposable() || Callee->hasFnAttribute(Attribute::NoInline) || + CS.isNoInline()) + return false; + return true; +} + +void SafeStack::TryInlinePointerAddress() { + if (!isa(UnsafeStackPtr)) + return; + + if(F.hasFnAttribute(Attribute::OptimizeNone)) + return; + + CallSite CS(UnsafeStackPtr); + Function *Callee = CS.getCalledFunction(); + if (!Callee || Callee->isDeclaration()) + return; + + if (!ShouldInlinePointerAddress(CS)) + return; + + InlineFunctionInfo IFI; + InlineFunction(CS, IFI); +} + bool SafeStack::run() { assert(F.hasFnAttribute(Attribute::SafeStack) && "Can't run SafeStack on a function without the attribute"); @@ -731,7 +772,13 @@ ++NumUnsafeStackRestorePointsFunctions; IRBuilder<> IRB(&F.front(), F.begin()->getFirstInsertionPt()); - UnsafeStackPtr = TL.getSafeStackPointerLocation(IRB); + if (SafeStackUsePointerAddress) { + Value *Fn = F.getParent()->getOrInsertFunction( + "__safestack_pointer_address", StackPtrTy->getPointerTo(0)); + UnsafeStackPtr = IRB.CreateCall(Fn); + } else { + UnsafeStackPtr = TL.getSafeStackPointerLocation(IRB); + } // Load the current stack pointer (we'll also use it as a base pointer). // FIXME: use a dedicated register for it ? @@ -779,6 +826,8 @@ IRB.CreateStore(BasePointer, UnsafeStackPtr); } + TryInlinePointerAddress(); + DEBUG(dbgs() << "[SafeStack] safestack applied\n"); return true; } Index: llvm/trunk/test/CodeGen/X86/safestack.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/safestack.ll +++ llvm/trunk/test/CodeGen/X86/safestack.ll @@ -4,6 +4,8 @@ ; RUN: llc -mtriple=x86_64-linux-android < %s -o - | FileCheck --check-prefix=ANDROID-X64 %s ; RUN: llc -mtriple=x86_64-fuchsia < %s -o - | FileCheck --check-prefix=FUCHSIA-X64 %s +; RUN: llc -mtriple=i386-linux -safestack-use-pointer-address < %s -o - | FileCheck --check-prefix=LINUX-I386-PA %s + define void @_Z1fv() safestack { entry: %x = alloca i32, align 4 @@ -35,3 +37,9 @@ ; FUCHSIA-X64: movq %fs:24, %[[A:.*]] ; FUCHSIA-X64: leaq -16(%[[A]]), %[[B:.*]] ; FUCHSIA-X64: movq %[[B]], %fs:24 + +; LINUX-I386-PA: calll __safestack_pointer_address +; LINUX-I386-PA: movl %eax, %[[A:.*]] +; LINUX-I386-PA: movl (%[[A]]), %[[B:.*]] +; LINUX-I386-PA: leal -16(%[[B]]), %[[C:.*]] +; LINUX-I386-PA: movl %[[C]], (%[[A]]) Index: llvm/trunk/test/CodeGen/X86/safestack_inline.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/safestack_inline.ll +++ llvm/trunk/test/CodeGen/X86/safestack_inline.ll @@ -0,0 +1,30 @@ +; RUN: sed -e "s/ATTR//" %s | llc -mtriple=x86_64-linux -safestack-use-pointer-address | FileCheck --check-prefix=INLINE %s +; RUN: sed -e "s/ATTR/noinline/" %s | llc -mtriple=x86_64-linux -safestack-use-pointer-address | FileCheck --check-prefix=CALL %s + +@p = external thread_local global i8*, align 8 + +define nonnull i8** @__safestack_pointer_address() local_unnamed_addr ATTR { +entry: + ret i8** @p +} + +define void @_Z1fv() safestack { +entry: + %x = alloca i32, align 4 + %0 = bitcast i32* %x to i8* + call void @_Z7CapturePi(i32* nonnull %x) + ret void +} + +declare void @_Z7CapturePi(i32*) + +; INLINE: movq p@GOTTPOFF(%rip), %[[A:.*]] +; INLINE: movq %fs:(%[[A]]), %[[B:.*]] +; INLINE: leaq -16(%[[B]]), %[[C:.*]] +; INLINE: movq %[[C]], %fs:(%[[A]]) + +; CALL: callq __safestack_pointer_address +; CALL: movq %rax, %[[A:.*]] +; CALL: movq (%[[A]]), %[[B:.*]] +; CALL: leaq -16(%[[B]]), %[[C:.*]] +; CALL: movq %[[C]], (%[[A]])