diff --git a/llvm/lib/CodeGen/StackProtector.cpp b/llvm/lib/CodeGen/StackProtector.cpp --- a/llvm/lib/CodeGen/StackProtector.cpp +++ b/llvm/lib/CodeGen/StackProtector.cpp @@ -478,11 +478,11 @@ // we don't need to worry about many situations here. Instruction *CheckLoc = RI; Instruction *Prev = RI->getPrevNonDebugInstruction(); - if (Prev && isa(Prev) && cast(Prev)->isMustTailCall()) + if (Prev && isa(Prev) && cast(Prev)->isTailCall()) CheckLoc = Prev; else if (Prev) { Prev = Prev->getPrevNonDebugInstruction(); - if (Prev && isa(Prev) && cast(Prev)->isMustTailCall()) + if (Prev && isa(Prev) && cast(Prev)->isTailCall()) CheckLoc = Prev; } diff --git a/llvm/test/CodeGen/AArch64/stack-protector-musttail.ll b/llvm/test/CodeGen/AArch64/stack-protector-musttail.ll --- a/llvm/test/CodeGen/AArch64/stack-protector-musttail.ll +++ b/llvm/test/CodeGen/AArch64/stack-protector-musttail.ll @@ -64,3 +64,42 @@ %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 +} \ No newline at end of file diff --git a/llvm/test/CodeGen/ARM/Windows/stack-protector-musttail.ll b/llvm/test/CodeGen/ARM/Windows/stack-protector-musttail.ll --- a/llvm/test/CodeGen/ARM/Windows/stack-protector-musttail.ll +++ b/llvm/test/CodeGen/ARM/Windows/stack-protector-musttail.ll @@ -34,7 +34,6 @@ ret void } - declare i64* @callee2() define i8* @caller2() sspreq { @@ -54,3 +53,35 @@ %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 +} \ No newline at end of file diff --git a/llvm/test/CodeGen/X86/stack-protector-musttail.ll b/llvm/test/CodeGen/X86/stack-protector-musttail.ll new file mode 100644 --- /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 + +@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 --- 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 @@ 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