Add a 'tail' marker for call instructions, patch contributed by
authorChris Lattner <sabre@nondot.org>
Fri, 6 May 2005 05:51:46 +0000 (05:51 +0000)
committerChris Lattner <sabre@nondot.org>
Fri, 6 May 2005 05:51:46 +0000 (05:51 +0000)
Alexander Friedman.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@21722 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Instructions.h
lib/AsmParser/llvmAsmParser.y
lib/VMCore/AsmWriter.cpp
lib/VMCore/Instruction.cpp
lib/VMCore/Instructions.cpp

index 06d0490725b858f7fd83e1b6b0748b4a34504828..a27ce2bc04363ee76ba0f78e4d1bf48f916a63fd 100644 (file)
@@ -467,7 +467,8 @@ public:
 //===----------------------------------------------------------------------===//
 
 /// CallInst - This class represents a function call, abstracting a target
-/// machine's calling convention.
+/// machine's calling convention.  This class uses the SubClassData field to
+/// indicate whether or not this is a tail call.
 ///
 class CallInst : public Instruction {
   CallInst(const CallInst &CI);
@@ -501,6 +502,9 @@ public:
   virtual CallInst *clone() const;
   bool mayWriteToMemory() const { return true; }
 
+  bool isTailCall() const           { return SubclassData; }
+  void setTailCall(bool isTailCall) { SubclassData = isTailCall; }
+
   /// getCalledFunction - Return the function being called by this instruction
   /// if it is a direct call.  If it is a call through a function pointer,
   /// return null.
index c6251cc983fd85b011911c04b12ddfa90524df71..b6a6e96fceb7d6a062246520c7040c8c36e03632 100644 (file)
@@ -803,6 +803,7 @@ Module *llvm::RunVMAsmParser(const std::string &Filename, FILE *F) {
 %type <JumpTable>     JumpTable
 %type <BoolVal>       GlobalType                  // GLOBAL or CONSTANT?
 %type <BoolVal>       OptVolatile                 // 'volatile' or not
+%type <BoolVal>       OptTailCall                 // TAIL CALL or plain CALL.
 %type <Linkage>       OptLinkage
 %type <Endianness>    BigOrLittle
 
@@ -837,7 +838,7 @@ Module *llvm::RunVMAsmParser(const std::string &Filename, FILE *F) {
 %token DECLARE GLOBAL CONSTANT VOLATILE
 %token TO DOTDOTDOT NULL_TOK UNDEF CONST INTERNAL LINKONCE WEAK  APPENDING
 %token OPAQUE NOT EXTERNAL TARGET TRIPLE ENDIAN POINTERSIZE LITTLE BIG
-%token DEPLIBS 
+%token DEPLIBS CALL TAIL
 
 // Basic Block Terminating Operators 
 %token <TermOpVal> RET BR SWITCH INVOKE UNWIND UNREACHABLE
@@ -852,7 +853,8 @@ Module *llvm::RunVMAsmParser(const std::string &Filename, FILE *F) {
 
 // Other Operators
 %type  <OtherOpVal> ShiftOps
-%token <OtherOpVal> PHI_TOK CALL CAST SELECT SHL SHR VAARG VANEXT
+%token <OtherOpVal> PHI_TOK CAST SELECT SHL SHR VAARG VANEXT
+
 
 %start Module
 %%
@@ -883,6 +885,9 @@ SetCondOps   : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE;
 
 ShiftOps  : SHL | SHR;
 
+
+
+
 // These are some types that allow classification if we only want a particular 
 // thing... for example, only a signed, unsigned, or integral type.
 SIntType :  LONG |  INT |  SHORT | SBYTE;
@@ -1858,6 +1863,15 @@ ValueRefList : ResolvedVal {    // Used for call statements, and memory insts...
 // ValueRefListE - Just like ValueRefList, except that it may also be empty!
 ValueRefListE : ValueRefList | /*empty*/ { $$ = 0; };
 
+OptTailCall : TAIL CALL {
+    $$ = true;
+  }
+  | CALL {
+    $$ = false;
+  };
+
+
+
 InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
     if (!(*$2)->isInteger() && !(*$2)->isFloatingPoint() && 
         !isa<PackedType>((*$2).get()))
@@ -1944,8 +1958,8 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
       $2->pop_front();
     }
     delete $2;  // Free the list...
-  } 
-  | CALL TypesV ValueRef '(' ValueRefListE ')' {
+  }
+  | OptTailCall TypesV ValueRef '(' ValueRefListE ')'  {
     const PointerType *PFTy;
     const FunctionType *Ty;
 
@@ -1997,6 +2011,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
 
       $$ = new CallInst(V, *$5);
     }
+    cast<CallInst>($$)->setTailCall($1);
     delete $2;
     delete $5;
   }
@@ -2020,6 +2035,7 @@ OptVolatile : VOLATILE {
   };
 
 
+
 MemoryInst : MALLOC Types {
     $$ = new MallocInst(*$2);
     delete $2;
index 18d045f48873c6b615cf19f8d5fab9db39842433..6db1a9a26c1947ead79a87f1cd6b80f8e1c9ef8b 100644 (file)
@@ -1043,10 +1043,14 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
   if (I.hasName())
     Out << getLLVMName(I.getName()) << " = ";
 
-  // If this is a volatile load or store, print out the volatile marker
+  // If this is a volatile load or store, print out the volatile marker.
   if ((isa<LoadInst>(I)  && cast<LoadInst>(I).isVolatile()) ||
-      (isa<StoreInst>(I) && cast<StoreInst>(I).isVolatile()))
+      (isa<StoreInst>(I) && cast<StoreInst>(I).isVolatile())) {
       Out << "volatile ";
+  } else if (isa<CallInst>(I) && cast<CallInst>(I).isTailCall()) {
+    // If this is a call, check if it's a tail call.
+    Out << "tail ";
+  }
 
   // Print out the opcode...
   Out << I.getOpcodeName();
index 2a4812831a169e4dacdc3ba5dc4057f046446e2f..e1dead99f23fc7260f91608057688b2867601096 100644 (file)
@@ -141,6 +141,8 @@ bool Instruction::isIdenticalTo(Instruction *I) const {
     return SI->isVolatile() == cast<StoreInst>(I)->isVolatile();
   if (const VANextInst *VAN = dyn_cast<VANextInst>(this))
     return VAN->getArgType() == cast<VANextInst>(I)->getArgType();
+  if (const CallInst *CI = dyn_cast<CallInst>(this))
+    return CI->isTailCall() == cast<CallInst>(I)->isTailCall();
   return true;
 }
 
index 5c88c5428ddb15169e95491df7a43af3f0bca735..d5adaa79d952f1ffc1a76fb57be409272127c37c 100644 (file)
@@ -249,6 +249,7 @@ CallInst::CallInst(Value *Func, const std::string &Name,
 CallInst::CallInst(const CallInst &CI)
   : Instruction(CI.getType(), Instruction::Call, new Use[CI.getNumOperands()],
                 CI.getNumOperands()) {
+  setTailCall(CI.isTailCall());
   Use *OL = OperandList;
   Use *InOL = CI.OperandList;
   for (unsigned i = 0, e = CI.getNumOperands(); i != e; ++i)