[llvm] r216779 - Verifier: Don't reject varargs callee cleanup functions
Reid Kleckner
reid at kleckner.net
Fri Aug 29 14:25:28 PDT 2014
Author: rnk
Date: Fri Aug 29 16:25:28 2014
New Revision: 216779
URL: http://llvm.org/viewvc/llvm-project?rev=216779&view=rev
Log:
Verifier: Don't reject varargs callee cleanup functions
We've rejected these kinds of functions since r28405 in 2006 because
it's impossible to lower the return of a callee cleanup varargs
function. However there are lots of legal ways to leave such a function
without returning, such as aborting. Today we can leave a function with
a musttail call to another function with the correct prototype, and
everything works out.
I'm removing the verifier check declaring that a normal return from such
a function is UB.
Reviewed By: nlewycky
Differential Revision: http://reviews.llvm.org/D5059
Added:
llvm/trunk/test/CodeGen/X86/vararg-callee-cleanup.ll
Modified:
llvm/trunk/lib/IR/Verifier.cpp
llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
llvm/trunk/test/Verifier/musttail-valid.ll
Modified: llvm/trunk/lib/IR/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=216779&r1=216778&r2=216779&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Verifier.cpp (original)
+++ llvm/trunk/lib/IR/Verifier.cpp Fri Aug 29 16:25:28 2014
@@ -1055,20 +1055,19 @@ void Verifier::visitFunction(const Funct
"Attribute 'builtin' can only be applied to a callsite.", &F);
// Check that this function meets the restrictions on this calling convention.
+ // Sometimes varargs is used for perfectly forwarding thunks, so some of these
+ // restrictions can be lifted.
switch (F.getCallingConv()) {
default:
- break;
case CallingConv::C:
break;
case CallingConv::Fast:
case CallingConv::Cold:
- case CallingConv::X86_FastCall:
- case CallingConv::X86_ThisCall:
case CallingConv::Intel_OCL_BI:
case CallingConv::PTX_Kernel:
case CallingConv::PTX_Device:
- Assert1(!F.isVarArg(),
- "Varargs functions must have C calling conventions!", &F);
+ Assert1(!F.isVarArg(), "Calling convention does not support varargs or "
+ "perfect forwarding!", &F);
break;
}
Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=216779&r1=216778&r2=216779&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Fri Aug 29 16:25:28 2014
@@ -3605,23 +3605,18 @@ bool X86::isOffsetSuitableForCodeModel(i
/// own arguments. Callee pop is necessary to support tail calls.
bool X86::isCalleePop(CallingConv::ID CallingConv,
bool is64Bit, bool IsVarArg, bool TailCallOpt) {
- if (IsVarArg)
- return false;
-
switch (CallingConv) {
default:
return false;
case CallingConv::X86_StdCall:
- return !is64Bit;
case CallingConv::X86_FastCall:
- return !is64Bit;
case CallingConv::X86_ThisCall:
return !is64Bit;
case CallingConv::Fast:
- return TailCallOpt;
case CallingConv::GHC:
- return TailCallOpt;
case CallingConv::HiPE:
+ if (IsVarArg)
+ return false;
return TailCallOpt;
}
}
Added: llvm/trunk/test/CodeGen/X86/vararg-callee-cleanup.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/vararg-callee-cleanup.ll?rev=216779&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/vararg-callee-cleanup.ll (added)
+++ llvm/trunk/test/CodeGen/X86/vararg-callee-cleanup.ll Fri Aug 29 16:25:28 2014
@@ -0,0 +1,54 @@
+; RUN: llc -mtriple=i686-pc-windows < %s | FileCheck %s
+
+target datalayout = "e-m:w-p:32:32-i64:64-f80:32-n8:16:32-S32"
+
+declare x86_thiscallcc void @thiscall_thunk(i8* %this, ...)
+define i32 @call_varargs_thiscall_thunk(i8* %a, i32 %b, i32 %c, i32 %d) {
+ call x86_thiscallcc void (i8*, ...)* @thiscall_thunk(i8* %a, i32 1, i32 2)
+ call x86_thiscallcc void (i8*, ...)* @thiscall_thunk(i8* %a, i32 1, i32 2)
+ %t1 = add i32 %b, %c
+ %r = add i32 %t1, %d
+ ret i32 %r
+}
+
+; CHECK: _call_varargs_thiscall_thunk:
+; CHECK: calll _thiscall_thunk
+; CHECK-NEXT: subl $8, %esp
+
+; We don't mangle the argument size into variadic callee cleanup functions.
+
+declare x86_stdcallcc void @stdcall_thunk(i8* %this, ...)
+define i32 @call_varargs_stdcall_thunk(i8* %a, i32 %b, i32 %c, i32 %d) {
+ call x86_stdcallcc void (i8*, ...)* @stdcall_thunk(i8* %a, i32 1, i32 2)
+ call x86_stdcallcc void (i8*, ...)* @stdcall_thunk(i8* %a, i32 1, i32 2)
+ %t1 = add i32 %b, %c
+ %r = add i32 %t1, %d
+ ret i32 %r
+}
+
+; CHECK: _call_varargs_stdcall_thunk:
+; CHECK: calll _stdcall_thunk{{$}}
+; CHECK-NEXT: subl $12, %esp
+
+declare x86_fastcallcc void @fastcall_thunk(i8* %this, ...)
+define i32 @call_varargs_fastcall_thunk(i8* %a, i32 %b, i32 %c, i32 %d) {
+ call x86_fastcallcc void (i8*, ...)* @fastcall_thunk(i8* inreg %a, i32 inreg 1, i32 2)
+ call x86_fastcallcc void (i8*, ...)* @fastcall_thunk(i8* inreg %a, i32 inreg 1, i32 2)
+ %t1 = add i32 %b, %c
+ %r = add i32 %t1, %d
+ ret i32 %r
+}
+
+; CHECK: _call_varargs_fastcall_thunk:
+; CHECK: calll @fastcall_thunk{{$}}
+; CHECK-NEXT: subl $4, %esp
+
+; If you actually return from such a thunk, it will only pop the non-variadic
+; portion of the arguments, which is different from what the callee passes.
+
+define x86_stdcallcc void @varargs_stdcall_return(i32, i32, ...) {
+ ret void
+}
+
+; CHECK: _varargs_stdcall_return:
+; CHECK: retl $8
Modified: llvm/trunk/test/Verifier/musttail-valid.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/musttail-valid.ll?rev=216779&r1=216778&r2=216779&view=diff
==============================================================================
--- llvm/trunk/test/Verifier/musttail-valid.ll (original)
+++ llvm/trunk/test/Verifier/musttail-valid.ll Fri Aug 29 16:25:28 2014
@@ -14,3 +14,26 @@ define i32* @similar_ret_ptrty() {
%w = bitcast i8* %v to i32*
ret i32* %w
}
+
+declare x86_thiscallcc void @varargs_thiscall(i8*, ...)
+define x86_thiscallcc void @varargs_thiscall_thunk(i8* %this, ...) {
+ musttail call x86_thiscallcc void (i8*, ...)* @varargs_thiscall(i8* %this, ...)
+ ret void
+}
+
+declare x86_fastcallcc void @varargs_fastcall(i8*, ...)
+define x86_fastcallcc void @varargs_fastcall_thunk(i8* %this, ...) {
+ musttail call x86_fastcallcc void (i8*, ...)* @varargs_fastcall(i8* %this, ...)
+ ret void
+}
+
+define x86_thiscallcc void @varargs_thiscall_unreachable(i8* %this, ...) {
+ unreachable
+}
+
+define x86_thiscallcc void @varargs_thiscall_ret_unreachable(i8* %this, ...) {
+ musttail call x86_thiscallcc void (i8*, ...)* @varargs_thiscall(i8* %this, ...)
+ ret void
+bb1:
+ ret void
+}
More information about the llvm-commits
mailing list