return false;
}
+/// Search for the first call to the llvm.stackprotector intrinsic and return it
+/// if present.
+static const CallInst *findStackProtectorIntrinsic(Function &F) {
+ for (const BasicBlock &BB : F)
+ for (const Instruction &I : BB)
+ if (const CallInst *CI = dyn_cast<CallInst>(&I))
+ if (CI->getCalledFunction() ==
+ Intrinsic::getDeclaration(F.getParent(), Intrinsic::stackprotector))
+ return CI;
+ return nullptr;
+}
+
/// Check whether or not this function needs a stack protector based
/// upon the stack protector level.
///
bool StackProtector::RequiresStackProtector() {
bool Strong = false;
bool NeedsProtector = false;
- for (const BasicBlock &BB : *F)
- for (const Instruction &I : BB)
- if (const CallInst *CI = dyn_cast<CallInst>(&I))
- if (CI->getCalledFunction() ==
- Intrinsic::getDeclaration(F->getParent(),
- Intrinsic::stackprotector))
- HasPrologue = true;
+ HasPrologue = findStackProtectorIntrinsic(*F);
if (F->hasFnAttribute(Attribute::SafeStack))
return false;
// protection in SDAG.
bool SupportsSelectionDAGSP =
TLI->useStackGuardXorFP() ||
- (EnableSelectionDAGSP && !TM->Options.EnableFastISel);
+ (EnableSelectionDAGSP && !TM->Options.EnableFastISel &&
+ !TM->Options.EnableGlobalISel);
AllocaInst *AI = nullptr; // Place on stack that stores the stack guard.
for (Function::iterator I = F->begin(), E = F->end(); I != E;) {
if (SupportsSelectionDAGSP)
break;
+ // Find the stack guard slot if the prologue was not created by this pass
+ // itself via a previous call to CreatePrologue().
+ if (!AI) {
+ const CallInst *SPCall = findStackProtectorIntrinsic(*F);
+ assert(SPCall && "Call to llvm.stackprotector is missing");
+ AI = cast<AllocaInst>(SPCall->getArgOperand(1));
+ }
+
// Set HasIRCheck to true, so that SelectionDAG will not generate its own
// version. SelectionDAG called 'shouldEmitSDCheck' to check whether
// instrumentation has already been generated.
--- /dev/null
+; RUN: llc -O0 -stop-before=irtranslator -global-isel %s -o - | FileCheck %s
+; RUN: llc -O0 -stop-after=irtranslator -verify-machineinstrs -global-isel %s -o - | FileCheck --check-prefixes CHECK,CHECK-MIR %s
+
+; Check that when using GlobalISel, the StackProtector pass currently inserts
+; both prologue and epilogue instrumentation because GlobalISel does not have
+; the same epilogue insertion/optimization as SelectionDAG.
+
+target triple = "armv8-arm-none-eabi"
+
+define void @foo() ssp {
+; CHECK-LABEL: entry:
+; CHECK-NEXT: %StackGuardSlot = alloca i8*
+; CHECK-NEXT: %0 = call i8* @llvm.stackguard()
+; CHECK-NEXT: call void @llvm.stackprotector(i8* %0, i8** %StackGuardSlot)
+; CHECK-NEXT: %buf = alloca [8 x i8], align 1
+; CHECK-NEXT: %1 = call i8* @llvm.stackguard()
+; CHECK-NEXT: %2 = load volatile i8*, i8** %StackGuardSlot
+; CHECK-NEXT: %3 = icmp eq i8* %1, %2
+; CHECK-NEXT: br i1 %3, label %SP_return, label %CallStackCheckFailBlk, !prof !0
+;
+; CHECK: SP_return:
+; CHECK-NEXT: ret void
+;
+; CHECK: CallStackCheckFailBlk:
+; CHECK-NEXT: call void @__stack_chk_fail()
+; CHECK-NEXT: unreachable
+
+; CHECK-MIR: bb.1.entry:
+; CHECK-MIR: %0:_(p0) = G_FRAME_INDEX %stack.0.StackGuardSlot
+; CHECK-MIR-NEXT: %1:gpr(p0) = LOAD_STACK_GUARD :: (dereferenceable invariant load 4 from @__stack_chk_guard)
+; CHECK-MIR-NEXT: %2:gpr(p0) = LOAD_STACK_GUARD :: (dereferenceable invariant load 4 from @__stack_chk_guard)
+; CHECK-MIR-NEXT: G_STORE %2(p0), %0(p0) :: (volatile store 4 into %stack.0.StackGuardSlot, align 8)
+; CHECK-MIR-NEXT: %3:_(p0) = G_FRAME_INDEX %stack.1.buf
+; CHECK-MIR-NEXT: %4:gpr(p0) = LOAD_STACK_GUARD :: (dereferenceable invariant load 4 from @__stack_chk_guard)
+; CHECK-MIR-NEXT: %5:_(p0) = G_LOAD %0(p0) :: (volatile load 4 from %ir.StackGuardSlot)
+; CHECK-MIR-NEXT: %6:_(s1) = G_ICMP intpred(eq), %4(p0), %5
+; CHECK-MIR-NEXT: G_BRCOND %6(s1), %bb.2
+; CHECK-MIR-NEXT: G_BR %bb.3
+;
+; CHECK-MIR: bb.2.SP_return:
+; CHECK-MIR-NEXT: BX_RET 14, $noreg
+;
+; CHECK-MIR: bb.3.CallStackCheckFailBlk:
+; CHECK-MIR-NEXT: ADJCALLSTACKDOWN 0, 0, 14, $noreg, implicit-def $sp, implicit $sp
+; CHECK-MIR-NEXT: BL @__stack_chk_fail, csr_aapcs, implicit-def $lr, implicit $sp
+; CHECK-MIR-NEXT: ADJCALLSTACKUP 0, 0, 14, $noreg, implicit-def $sp, implicit $sp
+entry:
+ %buf = alloca [8 x i8], align 1
+ ret void
+}