aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Instructions.h6
-rw-r--r--lib/AsmParser/llvmAsmParser.y24
-rw-r--r--lib/VMCore/AsmWriter.cpp8
-rw-r--r--lib/VMCore/Instruction.cpp2
-rw-r--r--lib/VMCore/Instructions.cpp1
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)