[llvm] 2e37557 - StackProtector: ensure stack checks are inserted before the tail call

Liqiang Tao via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 16 07:25:32 PDT 2022


Author: Liqiang Tao
Date: 2022-09-16T22:24:46+08:00
New Revision: 2e37557fdeed381e8e790e20702ededb13c9cef3

URL: https://github.com/llvm/llvm-project/commit/2e37557fdeed381e8e790e20702ededb13c9cef3
DIFF: https://github.com/llvm/llvm-project/commit/2e37557fdeed381e8e790e20702ededb13c9cef3.diff

LOG: StackProtector: ensure stack checks are inserted before the tail call

The IR stack protector pass should insert stack checks before the tail
calls not only the musttail calls. So that the attributes `ssqreq` and
`tail call`, which are emited by llvm-opt, could be both enabled by
llvm-llc.

Reviewed By: compnerd

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

Added: 
    llvm/test/CodeGen/X86/stack-protector-musttail.ll

Modified: 
    llvm/lib/CodeGen/StackProtector.cpp
    llvm/test/CodeGen/AArch64/stack-protector-musttail.ll
    llvm/test/CodeGen/ARM/Windows/stack-protector-musttail.ll
    llvm/test/CodeGen/X86/tailcc-ssp.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/StackProtector.cpp b/llvm/lib/CodeGen/StackProtector.cpp
index 510a8e3e4ba2..ff828f560f11 100644
--- a/llvm/lib/CodeGen/StackProtector.cpp
+++ b/llvm/lib/CodeGen/StackProtector.cpp
@@ -471,18 +471,18 @@ bool StackProtector::InsertStackProtectors() {
     // instrumentation has already been generated.
     HasIRCheck = true;
 
-    // If we're instrumenting a block with a musttail call, the check has to be
+    // If we're instrumenting a block with a tail call, the check has to be
     // inserted before the call rather than between it and the return. The
-    // verifier guarantees that a musttail call is either directly before the
+    // verifier guarantees that a tail call is either directly before the
     // return or with a single correct bitcast of the return value in between so
     // we don't need to worry about many situations here.
     Instruction *CheckLoc = RI;
     Instruction *Prev = RI->getPrevNonDebugInstruction();
-    if (Prev && isa<CallInst>(Prev) && cast<CallInst>(Prev)->isMustTailCall())
+    if (Prev && isa<CallInst>(Prev) && cast<CallInst>(Prev)->isTailCall())
       CheckLoc = Prev;
     else if (Prev) {
       Prev = Prev->getPrevNonDebugInstruction();
-      if (Prev && isa<CallInst>(Prev) && cast<CallInst>(Prev)->isMustTailCall())
+      if (Prev && isa<CallInst>(Prev) && cast<CallInst>(Prev)->isTailCall())
         CheckLoc = Prev;
     }
 

diff  --git a/llvm/test/CodeGen/AArch64/stack-protector-musttail.ll b/llvm/test/CodeGen/AArch64/stack-protector-musttail.ll
index 8a2e095e6a64..72fa9fe24680 100644
--- a/llvm/test/CodeGen/AArch64/stack-protector-musttail.ll
+++ b/llvm/test/CodeGen/AArch64/stack-protector-musttail.ll
@@ -64,3 +64,42 @@ define i8* @caller2() ssp {
   %res = bitcast i64* %tmp to i8*
   ret i8* %res
 }
+
+define void @caller3() ssp {
+; CHECK-LABEL: define void @caller3()
+; Prologue:
+; CHECK: @llvm.stackguard
+
+; CHECK: [[GUARD:%.*]] = call i8* @llvm.stackguard()
+; CHECK: [[TOKEN:%.*]] = load volatile i8*, i8** {{%.*}}
+; CHECK: [[TST:%.*]] = icmp eq i8* [[GUARD]], [[TOKEN]]
+; CHECK: br i1 [[TST]]
+
+; CHECK: tail call void @callee()
+; CHECK-NEXT: ret void
+  %var = alloca [2 x i64]
+  store [2 x i64]* %var, [2 x i64]** @var
+  tail call void @callee()
+  ret void
+}
+
+define i8* @caller4() ssp {
+; CHECK-LABEL: define i8* @caller4()
+; Prologue:
+; CHECK: @llvm.stackguard
+
+; CHECK: [[GUARD:%.*]] = call i8* @llvm.stackguard()
+; CHECK: [[TOKEN:%.*]] = load volatile i8*, i8** {{%.*}}
+; CHECK: [[TST:%.*]] = icmp eq i8* [[GUARD]], [[TOKEN]]
+; CHECK: br i1 [[TST]]
+
+; CHECK: [[TMP:%.*]] = tail call i64* @callee2()
+; CHECK-NEXT: [[RES:%.*]] = bitcast i64* [[TMP]] to i8*
+; CHECK-NEXT: ret i8* [[RES]]
+
+  %var = alloca [2 x i64]
+  store [2 x i64]* %var, [2 x i64]** @var
+  %tmp = tail call i64* @callee2()
+  %res = bitcast i64* %tmp to i8*
+  ret i8* %res
+}

diff  --git a/llvm/test/CodeGen/ARM/Windows/stack-protector-musttail.ll b/llvm/test/CodeGen/ARM/Windows/stack-protector-musttail.ll
index 93b601c9369f..74829f9d7804 100644
--- a/llvm/test/CodeGen/ARM/Windows/stack-protector-musttail.ll
+++ b/llvm/test/CodeGen/ARM/Windows/stack-protector-musttail.ll
@@ -34,7 +34,6 @@ retblock:
   ret void
 }
 
-
 declare i64* @callee2()
 
 define i8* @caller2() sspreq {
@@ -54,3 +53,35 @@ define i8* @caller2() sspreq {
   %res = bitcast i64* %tmp to i8*
   ret i8* %res
 }
+
+define void @caller3() sspreq {
+; CHECK-LABEL: define void @caller3()
+; Prologue:
+
+; CHECK: call void @__security_check_cookie
+
+; CHECK: tail call void @callee()
+; CHECK-NEXT: ret void
+  %var = alloca [2 x i64]
+  store [2 x i64]* %var, [2 x i64]** @var
+  tail call void @callee()
+  ret void
+}
+
+define i8* @caller4() sspreq {
+; CHECK-LABEL: define i8* @caller4()
+; Prologue:
+; CHECK: @llvm.stackguard
+
+; CHECK: call void @__security_check_cookie
+
+; CHECK: [[TMP:%.*]] = tail call i64* @callee2()
+; CHECK-NEXT: [[RES:%.*]] = bitcast i64* [[TMP]] to i8*
+; CHECK-NEXT: ret i8* [[RES]]
+
+  %var = alloca [2 x i64]
+  store [2 x i64]* %var, [2 x i64]** @var
+  %tmp = tail call i64* @callee2()
+  %res = bitcast i64* %tmp to i8*
+  ret i8* %res
+}

diff  --git a/llvm/test/CodeGen/X86/stack-protector-musttail.ll b/llvm/test/CodeGen/X86/stack-protector-musttail.ll
new file mode 100644
index 000000000000..aa6945af7c0e
--- /dev/null
+++ b/llvm/test/CodeGen/X86/stack-protector-musttail.ll
@@ -0,0 +1,105 @@
+; RUN: llc -mtriple=x86_64-linux-gnu -fast-isel %s -o - -start-before=stack-protector -stop-after=stack-protector  | FileCheck %s
+
+ at var = global [2 x i64]* null
+
+declare void @callee()
+
+define void @caller1() sspreq {
+; CHECK-LABEL: define void @caller1()
+; Prologue:
+; CHECK: @llvm.stackprotector
+
+; CHECK: [[GUARD:%.*]] = load volatile i8*, i8*
+; CHECK: [[TOKEN:%.*]] = load volatile i8*, i8** {{%.*}}
+; CHECK: [[TST:%.*]] = icmp eq i8* [[GUARD]], [[TOKEN]]
+; CHECK: br i1 [[TST]]
+
+; CHECK: musttail call void @callee()
+; CHECK-NEXT: ret void
+  %var = alloca [2 x i64]
+  store [2 x i64]* %var, [2 x i64]** @var
+  musttail call void @callee()
+  ret void
+}
+
+define void @justret() sspreq {
+; CHECK-LABEL: define void @justret()
+; Prologue:
+; CHECK: @llvm.stackprotector
+
+; CHECK: [[GUARD:%.*]] = load volatile i8*, i8*
+; CHECK: [[TOKEN:%.*]] = load volatile i8*, i8** {{%.*}}
+; CHECK: [[TST:%.*]] = icmp eq i8* [[GUARD]], [[TOKEN]]
+; CHECK: br i1 [[TST]]
+
+; CHECK: ret void
+  %var = alloca [2 x i64]
+  store [2 x i64]* %var, [2 x i64]** @var
+  br label %retblock
+
+retblock:
+  ret void
+}
+
+
+declare i64* @callee2()
+
+define i8* @caller2() sspreq {
+; CHECK-LABEL: define i8* @caller2()
+; Prologue:
+; CHECK: @llvm.stackprotector
+
+; CHECK: [[GUARD:%.*]] = load volatile i8*, i8*
+; CHECK: [[TOKEN:%.*]] = load volatile i8*, i8** {{%.*}}
+; CHECK: [[TST:%.*]] = icmp eq i8* [[GUARD]], [[TOKEN]]
+; CHECK: br i1 [[TST]]
+
+; CHECK: [[TMP:%.*]] = musttail call i64* @callee2()
+; CHECK-NEXT: [[RES:%.*]] = bitcast i64* [[TMP]] to i8*
+; CHECK-NEXT: ret i8* [[RES]]
+
+  %var = alloca [2 x i64]
+  store [2 x i64]* %var, [2 x i64]** @var
+  %tmp = musttail call i64* @callee2()
+  %res = bitcast i64* %tmp to i8*
+  ret i8* %res
+}
+
+define void @caller3() sspreq {
+; CHECK-LABEL: define void @caller3()
+; Prologue:
+; CHECK: @llvm.stackprotector
+
+; CHECK: [[GUARD:%.*]] = load volatile i8*, i8*
+; CHECK: [[TOKEN:%.*]] = load volatile i8*, i8** {{%.*}}
+; CHECK: [[TST:%.*]] = icmp eq i8* [[GUARD]], [[TOKEN]]
+; CHECK: br i1 [[TST]]
+
+; CHECK: tail call void @callee()
+; CHECK-NEXT: ret void
+  %var = alloca [2 x i64]
+  store [2 x i64]* %var, [2 x i64]** @var
+  tail call void @callee()
+  ret void
+}
+
+define i8* @caller4() sspreq {
+; CHECK-LABEL: define i8* @caller4()
+; Prologue:
+; CHECK: @llvm.stackprotector
+
+; CHECK: [[GUARD:%.*]] = load volatile i8*, i8*
+; CHECK: [[TOKEN:%.*]] = load volatile i8*, i8** {{%.*}}
+; CHECK: [[TST:%.*]] = icmp eq i8* [[GUARD]], [[TOKEN]]
+; CHECK: br i1 [[TST]]
+
+; CHECK: [[TMP:%.*]] = tail call i64* @callee2()
+; CHECK-NEXT: [[RES:%.*]] = bitcast i64* [[TMP]] to i8*
+; CHECK-NEXT: ret i8* [[RES]]
+
+  %var = alloca [2 x i64]
+  store [2 x i64]* %var, [2 x i64]** @var
+  %tmp = tail call i64* @callee2()
+  %res = bitcast i64* %tmp to i8*
+  ret i8* %res
+}

diff  --git a/llvm/test/CodeGen/X86/tailcc-ssp.ll b/llvm/test/CodeGen/X86/tailcc-ssp.ll
index 33617b490fa5..bb9b4429c076 100644
--- a/llvm/test/CodeGen/X86/tailcc-ssp.ll
+++ b/llvm/test/CodeGen/X86/tailcc-ssp.ll
@@ -1,12 +1,18 @@
-; RUN: llc -mtriple=x86_64-windows-msvc %s -o - -verify-machineinstrs | FileCheck %s
+; RUN: llc -mtriple=x86_64-windows-msvc %s -o - -verify-machineinstrs | FileCheck %s -check-prefix=WINDOWS
+; RUN: llc -mtriple=x86_64-linux-gnu    %s -o - -verify-machineinstrs | FileCheck %s -check-prefix=LINUX
 
 declare void @h(ptr, i64, ptr)
 
 define tailcc void @tailcall_frame(ptr %0, i64 %1) sspreq {
-; CHECK-LABEL: tailcall_frame:
-; CHECK: callq __security_check_cookie
-; CHECK: xorl %ecx, %ecx
-; CHECK: jmp h
+; WINDOWS-LABEL: tailcall_frame:
+; WINDOWS: callq __security_check_cookie
+; WINDOWS: xorl %ecx, %ecx
+; WINDOWS: jmp h
+
+; LINUX-LABEL: tailcall_frame:
+; LINUX: jne
+; LINUX: jmp h
+; LINUX: callq __stack_chk_fail
 
    tail call tailcc void @h(ptr null, i64 0, ptr null)
    ret void
@@ -14,12 +20,19 @@ define tailcc void @tailcall_frame(ptr %0, i64 %1) sspreq {
 
 declare void @bar()
 define void @tailcall_unrelated_frame() sspreq {
-; CHECK-LABEL: tailcall_unrelated_frame:
-; CHECK: subq [[STACK:\$.*]], %rsp
-; CHECK: callq bar
-; CHECK: callq __security_check_cookie
-; CHECK: addq [[STACK]], %rsp
-; CHECK: jmp bar
+; WINDOWS-LABEL: tailcall_unrelated_frame:
+; WINDOWS: subq [[STACK:\$.*]], %rsp
+; WINDOWS: callq bar
+; WINDOWS: callq __security_check_cookie
+; WINDOWS: addq [[STACK]], %rsp
+; WINDOWS: jmp bar
+
+; LINUX-LABEL: tailcall_unrelated_frame:
+; LINUX: callq bar
+; LINUX: jne
+; LINUX: jmp bar
+; LINUX: callq __stack_chk_fail
+
   call void @bar()
   tail call void @bar()
   ret void


        


More information about the llvm-commits mailing list