[llvm] r216423 - Declare that musttail calls in variadic functions forward the ellipsis

Reid Kleckner reid at kleckner.net
Mon Aug 25 17:33:29 PDT 2014


Author: rnk
Date: Mon Aug 25 19:33:28 2014
New Revision: 216423

URL: http://llvm.org/viewvc/llvm-project?rev=216423&view=rev
Log:
Declare that musttail calls in variadic functions forward the ellipsis

Summary:
There is no functionality change here except in the way we assemble and
dump musttail calls in variadic functions. There's really no need to
separate out the bits for musttail and "is forwarding varargs" on call
instructions. A musttail call by definition has to forward the ellipsis
or it would fail verification.

Reviewers: chandlerc, nlewycky

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D4892

Added:
    llvm/trunk/test/Assembler/musttail-invalid-1.ll
    llvm/trunk/test/Assembler/musttail-invalid-2.ll
    llvm/trunk/test/Assembler/musttail.ll
    llvm/trunk/test/Transforms/Inline/inline-musttail-varargs.ll
Modified:
    llvm/trunk/docs/LangRef.rst
    llvm/trunk/lib/AsmParser/LLParser.cpp
    llvm/trunk/lib/AsmParser/LLParser.h
    llvm/trunk/lib/IR/AsmWriter.cpp

Modified: llvm/trunk/docs/LangRef.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=216423&r1=216422&r2=216423&view=diff
==============================================================================
--- llvm/trunk/docs/LangRef.rst (original)
+++ llvm/trunk/docs/LangRef.rst Mon Aug 25 19:33:28 2014
@@ -6591,6 +6591,9 @@ This instruction requires several argume
    - The calling conventions of the caller and callee must match.
    - All ABI-impacting function attributes, such as sret, byval, inreg,
      returned, and inalloca, must match.
+   - The callee must be varargs iff the caller is varargs. Bitcasting a
+     non-varargs function to the appropriate varargs type is legal so
+     long as the non-varargs prefixes obey the other rules.
 
    Tail call optimization for calls marked ``tail`` is guaranteed to occur if
    the following conditions are met:

Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=216423&r1=216422&r2=216423&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
+++ llvm/trunk/lib/AsmParser/LLParser.cpp Mon Aug 25 19:33:28 2014
@@ -1819,7 +1819,8 @@ bool LLParser::ParseType(Type *&Result,
 ///  Arg
 ///    ::= Type OptionalAttributes Value OptionalAttributes
 bool LLParser::ParseParameterList(SmallVectorImpl<ParamInfo> &ArgList,
-                                  PerFunctionState &PFS) {
+                                  PerFunctionState &PFS, bool IsMustTailCall,
+                                  bool InVarArgsFunc) {
   if (ParseToken(lltok::lparen, "expected '(' in call"))
     return true;
 
@@ -1830,6 +1831,17 @@ bool LLParser::ParseParameterList(SmallV
         ParseToken(lltok::comma, "expected ',' in argument list"))
       return true;
 
+    // Parse an ellipsis if this is a musttail call in a variadic function.
+    if (Lex.getKind() == lltok::dotdotdot) {
+      const char *Msg = "unexpected ellipsis in argument list for ";
+      if (!IsMustTailCall)
+        return TokError(Twine(Msg) + "non-musttail call");
+      if (!InVarArgsFunc)
+        return TokError(Twine(Msg) + "musttail call in non-varargs function");
+      Lex.Lex();  // Lex the '...', it is purely for readability.
+      return ParseToken(lltok::rparen, "expected ')' at end of argument list");
+    }
+
     // Parse the argument.
     LocTy ArgLoc;
     Type *ArgTy = nullptr;
@@ -1846,6 +1858,10 @@ bool LLParser::ParseParameterList(SmallV
                                                              ArgAttrs)));
   }
 
+  if (IsMustTailCall && InVarArgsFunc)
+    return TokError("expected '...' at end of argument list for musttail call "
+                    "in varargs function");
+
   Lex.Lex();  // Lex the ')'.
   return false;
 }
@@ -4214,7 +4230,8 @@ bool LLParser::ParseCall(Instruction *&I
       ParseOptionalReturnAttrs(RetAttrs) ||
       ParseType(RetType, RetTypeLoc, true /*void allowed*/) ||
       ParseValID(CalleeID) ||
-      ParseParameterList(ArgList, PFS) ||
+      ParseParameterList(ArgList, PFS, TCK == CallInst::TCK_MustTail,
+                         PFS.getFunction().isVarArg()) ||
       ParseFnAttributeValuePairs(FnAttrs, FwdRefAttrGrps, false,
                                  BuiltinLoc))
     return true;

Modified: llvm/trunk/lib/AsmParser/LLParser.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.h?rev=216423&r1=216422&r2=216423&view=diff
==============================================================================
--- llvm/trunk/lib/AsmParser/LLParser.h (original)
+++ llvm/trunk/lib/AsmParser/LLParser.h Mon Aug 25 19:33:28 2014
@@ -372,7 +372,9 @@ namespace llvm {
         : Loc(loc), V(v), Attrs(attrs) {}
     };
     bool ParseParameterList(SmallVectorImpl<ParamInfo> &ArgList,
-                            PerFunctionState &PFS);
+                            PerFunctionState &PFS,
+                            bool IsMustTailCall = false,
+                            bool InVarArgsFunc = false);
 
     // Constant Parsing.
     bool ParseValID(ValID &ID, PerFunctionState *PFS = nullptr);

Modified: llvm/trunk/lib/IR/AsmWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/AsmWriter.cpp?rev=216423&r1=216422&r2=216423&view=diff
==============================================================================
--- llvm/trunk/lib/IR/AsmWriter.cpp (original)
+++ llvm/trunk/lib/IR/AsmWriter.cpp Mon Aug 25 19:33:28 2014
@@ -2174,6 +2174,14 @@ void AssemblyWriter::printInstruction(co
         Out << ", ";
       writeParamOperand(CI->getArgOperand(op), PAL, op + 1);
     }
+
+    // Emit an ellipsis if this is a musttail call in a vararg function.  This
+    // is only to aid readability, musttail calls forward varargs by default.
+    if (CI->isMustTailCall() && CI->getParent() &&
+        CI->getParent()->getParent() &&
+        CI->getParent()->getParent()->isVarArg())
+      Out << ", ...";
+
     Out << ')';
     if (PAL.hasAttributes(AttributeSet::FunctionIndex))
       Out << " #" << Machine.getAttributeGroupSlot(PAL.getFnAttributes());

Added: llvm/trunk/test/Assembler/musttail-invalid-1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/musttail-invalid-1.ll?rev=216423&view=auto
==============================================================================
--- llvm/trunk/test/Assembler/musttail-invalid-1.ll (added)
+++ llvm/trunk/test/Assembler/musttail-invalid-1.ll Mon Aug 25 19:33:28 2014
@@ -0,0 +1,14 @@
+; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
+
+; Check the error message on using ", ..." when we can't actually forward
+; varargs.
+
+%struct.A = type { i32 }
+
+declare i8* @f(i8*, ...)
+
+define i8* @f_thunk(i8* %this) {
+  %rv = musttail call i8* (i8*, ...)* @f(i8* %this, ...)
+; CHECK: error: unexpected ellipsis in argument list for musttail call in non-varargs function
+  ret i8* %rv
+}

Added: llvm/trunk/test/Assembler/musttail-invalid-2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/musttail-invalid-2.ll?rev=216423&view=auto
==============================================================================
--- llvm/trunk/test/Assembler/musttail-invalid-2.ll (added)
+++ llvm/trunk/test/Assembler/musttail-invalid-2.ll Mon Aug 25 19:33:28 2014
@@ -0,0 +1,13 @@
+; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
+
+; Check the error message on skipping ", ..." at the end of a musttail call argument list.
+
+%struct.A = type { i32 }
+
+declare i8* @f(i8*, ...)
+
+define i8* @f_thunk(i8* %this, ...) {
+  %rv = musttail call i8* (i8*, ...)* @f(i8* %this)
+; CHECK: error: expected '...' at end of argument list for musttail call in varargs function
+  ret i8* %rv
+}

Added: llvm/trunk/test/Assembler/musttail.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/musttail.ll?rev=216423&view=auto
==============================================================================
--- llvm/trunk/test/Assembler/musttail.ll (added)
+++ llvm/trunk/test/Assembler/musttail.ll Mon Aug 25 19:33:28 2014
@@ -0,0 +1,14 @@
+; RUN: llvm-as < %s | llvm-dis | FileCheck %s
+
+; Check that the ellipsis round trips.
+
+%struct.A = type { i32 }
+
+declare i8* @f(i8*, ...)
+
+define i8* @f_thunk(i8* %this, ...) {
+  %rv = musttail call i8* (i8*, ...)* @f(i8* %this, ...)
+  ret i8* %rv
+}
+; CHECK-LABEL: define i8* @f_thunk(i8* %this, ...)
+; CHECK: %rv = musttail call i8* (i8*, ...)* @f(i8* %this, ...)

Added: llvm/trunk/test/Transforms/Inline/inline-musttail-varargs.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/inline-musttail-varargs.ll?rev=216423&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/Inline/inline-musttail-varargs.ll (added)
+++ llvm/trunk/test/Transforms/Inline/inline-musttail-varargs.ll Mon Aug 25 19:33:28 2014
@@ -0,0 +1,22 @@
+; RUN: opt < %s -inline -instcombine -S | FileCheck %s
+
+; We can't inline this thunk yet, but one day we will be able to.  And when we
+; do, this test case will be ready.
+
+declare void @ext_method(i8*, i32)
+
+define linkonce_odr void @thunk(i8* %this, ...) {
+  %this_adj = getelementptr i8* %this, i32 4
+  musttail call void (i8*, ...)* bitcast (void (i8*, i32)* @ext_method to void (i8*, ...)*)(i8* %this_adj, ...)
+  ret void
+}
+
+define void @thunk_caller(i8* %p) {
+  call void (i8*, ...)* @thunk(i8* %p, i32 42)
+  ret void
+}
+; CHECK-LABEL: define void @thunk_caller(i8* %p)
+; CHECK: call void (i8*, ...)* @thunk(i8* %p, i32 42)
+
+; FIXME: Inline the thunk. This should be significantly easier than inlining
+; general varargs functions.





More information about the llvm-commits mailing list