[llvm] r347862 - [GlobalISel] Fix insertion of stack-protector epilogue

Petr Pavlu via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 29 05:22:53 PST 2018


Author: petr.pavlu
Date: Thu Nov 29 05:22:53 2018
New Revision: 347862

URL: http://llvm.org/viewvc/llvm-project?rev=347862&view=rev
Log:
[GlobalISel] Fix insertion of stack-protector epilogue

* Tell the StackProtector pass to generate the epilogue instrumentation
  when GlobalISel is enabled because GISel currently does not implement
  the same deferred epilogue insertion as SelectionDAG.
* Update StackProtector::InsertStackProtectors() to find a stack guard
  slot by searching for the llvm.stackprotector intrinsic when the
  prologue was not created by StackProtector itself but the pass still
  needs to generate the epilogue instrumentation. This fixes a problem
  when the pass would abort because the stack guard AllocInst pointer
  was null when generating the epilogue -- test
  CodeGen/AArch64/GlobalISel/arm64-irtranslator-stackprotect.ll.

Differential Revision: https://reviews.llvm.org/D54518

Added:
    llvm/trunk/test/CodeGen/AArch64/GlobalISel/irtranslator-stackprotect-check.ll
Modified:
    llvm/trunk/lib/CodeGen/StackProtector.cpp

Modified: llvm/trunk/lib/CodeGen/StackProtector.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/StackProtector.cpp?rev=347862&r1=347861&r2=347862&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/StackProtector.cpp (original)
+++ llvm/trunk/lib/CodeGen/StackProtector.cpp Thu Nov 29 05:22:53 2018
@@ -199,6 +199,18 @@ bool StackProtector::HasAddressTaken(con
   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.
 ///
@@ -215,13 +227,7 @@ bool StackProtector::HasAddressTaken(con
 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;
@@ -379,7 +385,8 @@ bool StackProtector::InsertStackProtecto
   // 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;) {
@@ -399,6 +406,14 @@ bool StackProtector::InsertStackProtecto
     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.

Added: llvm/trunk/test/CodeGen/AArch64/GlobalISel/irtranslator-stackprotect-check.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/GlobalISel/irtranslator-stackprotect-check.ll?rev=347862&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/GlobalISel/irtranslator-stackprotect-check.ll (added)
+++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/irtranslator-stackprotect-check.ll Thu Nov 29 05:22:53 2018
@@ -0,0 +1,50 @@
+; 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
+}




More information about the llvm-commits mailing list