diff options
-rw-r--r-- | include/llvm/Instructions.h | 6 | ||||
-rw-r--r-- | lib/AsmParser/llvmAsmParser.y | 24 | ||||
-rw-r--r-- | lib/VMCore/AsmWriter.cpp | 8 | ||||
-rw-r--r-- | lib/VMCore/Instruction.cpp | 2 | ||||
-rw-r--r-- | lib/VMCore/Instructions.cpp | 1 |
5 files changed, 34 insertions, 7 deletions
diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h index 06d0490..a27ce2b 100644 --- a/include/llvm/Instructions.h +++ b/include/llvm/Instructions.h @@ -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. diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y index c6251cc..b6a6e96 100644 --- a/lib/AsmParser/llvmAsmParser.y +++ b/lib/AsmParser/llvmAsmParser.y @@ -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; diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index 18d045f..6db1a9a 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -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(); diff --git a/lib/VMCore/Instruction.cpp b/lib/VMCore/Instruction.cpp index 2a48128..e1dead9 100644 --- a/lib/VMCore/Instruction.cpp +++ b/lib/VMCore/Instruction.cpp @@ -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; } diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index 5c88c54..d5adaa7 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -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) |