forked from OSchip/llvm-project
Add a 'tail' marker for call instructions, patch contributed by
Alexander Friedman. llvm-svn: 21722
This commit is contained in:
parent
e23c139836
commit
0603845a49
|
@ -467,7 +467,8 @@ public:
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
/// CallInst - This class represents a function call, abstracting a target
|
/// 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 {
|
class CallInst : public Instruction {
|
||||||
CallInst(const CallInst &CI);
|
CallInst(const CallInst &CI);
|
||||||
|
@ -501,6 +502,9 @@ public:
|
||||||
virtual CallInst *clone() const;
|
virtual CallInst *clone() const;
|
||||||
bool mayWriteToMemory() const { return true; }
|
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
|
/// getCalledFunction - Return the function being called by this instruction
|
||||||
/// if it is a direct call. If it is a call through a function pointer,
|
/// if it is a direct call. If it is a call through a function pointer,
|
||||||
/// return null.
|
/// return null.
|
||||||
|
|
|
@ -803,6 +803,7 @@ Module *llvm::RunVMAsmParser(const std::string &Filename, FILE *F) {
|
||||||
%type <JumpTable> JumpTable
|
%type <JumpTable> JumpTable
|
||||||
%type <BoolVal> GlobalType // GLOBAL or CONSTANT?
|
%type <BoolVal> GlobalType // GLOBAL or CONSTANT?
|
||||||
%type <BoolVal> OptVolatile // 'volatile' or not
|
%type <BoolVal> OptVolatile // 'volatile' or not
|
||||||
|
%type <BoolVal> OptTailCall // TAIL CALL or plain CALL.
|
||||||
%type <Linkage> OptLinkage
|
%type <Linkage> OptLinkage
|
||||||
%type <Endianness> BigOrLittle
|
%type <Endianness> BigOrLittle
|
||||||
|
|
||||||
|
@ -837,7 +838,7 @@ Module *llvm::RunVMAsmParser(const std::string &Filename, FILE *F) {
|
||||||
%token DECLARE GLOBAL CONSTANT VOLATILE
|
%token DECLARE GLOBAL CONSTANT VOLATILE
|
||||||
%token TO DOTDOTDOT NULL_TOK UNDEF CONST INTERNAL LINKONCE WEAK APPENDING
|
%token TO DOTDOTDOT NULL_TOK UNDEF CONST INTERNAL LINKONCE WEAK APPENDING
|
||||||
%token OPAQUE NOT EXTERNAL TARGET TRIPLE ENDIAN POINTERSIZE LITTLE BIG
|
%token OPAQUE NOT EXTERNAL TARGET TRIPLE ENDIAN POINTERSIZE LITTLE BIG
|
||||||
%token DEPLIBS
|
%token DEPLIBS CALL TAIL
|
||||||
|
|
||||||
// Basic Block Terminating Operators
|
// Basic Block Terminating Operators
|
||||||
%token <TermOpVal> RET BR SWITCH INVOKE UNWIND UNREACHABLE
|
%token <TermOpVal> RET BR SWITCH INVOKE UNWIND UNREACHABLE
|
||||||
|
@ -852,7 +853,8 @@ Module *llvm::RunVMAsmParser(const std::string &Filename, FILE *F) {
|
||||||
|
|
||||||
// Other Operators
|
// Other Operators
|
||||||
%type <OtherOpVal> ShiftOps
|
%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
|
%start Module
|
||||||
%%
|
%%
|
||||||
|
@ -883,6 +885,9 @@ SetCondOps : SETLE | SETGE | SETLT | SETGT | SETEQ | SETNE;
|
||||||
|
|
||||||
ShiftOps : SHL | SHR;
|
ShiftOps : SHL | SHR;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// These are some types that allow classification if we only want a particular
|
// These are some types that allow classification if we only want a particular
|
||||||
// thing... for example, only a signed, unsigned, or integral type.
|
// thing... for example, only a signed, unsigned, or integral type.
|
||||||
SIntType : LONG | INT | SHORT | SBYTE;
|
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 - Just like ValueRefList, except that it may also be empty!
|
||||||
ValueRefListE : ValueRefList | /*empty*/ { $$ = 0; };
|
ValueRefListE : ValueRefList | /*empty*/ { $$ = 0; };
|
||||||
|
|
||||||
|
OptTailCall : TAIL CALL {
|
||||||
|
$$ = true;
|
||||||
|
}
|
||||||
|
| CALL {
|
||||||
|
$$ = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
|
InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
|
||||||
if (!(*$2)->isInteger() && !(*$2)->isFloatingPoint() &&
|
if (!(*$2)->isInteger() && !(*$2)->isFloatingPoint() &&
|
||||||
!isa<PackedType>((*$2).get()))
|
!isa<PackedType>((*$2).get()))
|
||||||
|
@ -1944,8 +1958,8 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
|
||||||
$2->pop_front();
|
$2->pop_front();
|
||||||
}
|
}
|
||||||
delete $2; // Free the list...
|
delete $2; // Free the list...
|
||||||
}
|
}
|
||||||
| CALL TypesV ValueRef '(' ValueRefListE ')' {
|
| OptTailCall TypesV ValueRef '(' ValueRefListE ')' {
|
||||||
const PointerType *PFTy;
|
const PointerType *PFTy;
|
||||||
const FunctionType *Ty;
|
const FunctionType *Ty;
|
||||||
|
|
||||||
|
@ -1997,6 +2011,7 @@ InstVal : ArithmeticOps Types ValueRef ',' ValueRef {
|
||||||
|
|
||||||
$$ = new CallInst(V, *$5);
|
$$ = new CallInst(V, *$5);
|
||||||
}
|
}
|
||||||
|
cast<CallInst>($$)->setTailCall($1);
|
||||||
delete $2;
|
delete $2;
|
||||||
delete $5;
|
delete $5;
|
||||||
}
|
}
|
||||||
|
@ -2020,6 +2035,7 @@ OptVolatile : VOLATILE {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MemoryInst : MALLOC Types {
|
MemoryInst : MALLOC Types {
|
||||||
$$ = new MallocInst(*$2);
|
$$ = new MallocInst(*$2);
|
||||||
delete $2;
|
delete $2;
|
||||||
|
|
|
@ -1043,10 +1043,14 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
|
||||||
if (I.hasName())
|
if (I.hasName())
|
||||||
Out << getLLVMName(I.getName()) << " = ";
|
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()) ||
|
if ((isa<LoadInst>(I) && cast<LoadInst>(I).isVolatile()) ||
|
||||||
(isa<StoreInst>(I) && cast<StoreInst>(I).isVolatile()))
|
(isa<StoreInst>(I) && cast<StoreInst>(I).isVolatile())) {
|
||||||
Out << "volatile ";
|
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...
|
// Print out the opcode...
|
||||||
Out << I.getOpcodeName();
|
Out << I.getOpcodeName();
|
||||||
|
|
|
@ -141,6 +141,8 @@ bool Instruction::isIdenticalTo(Instruction *I) const {
|
||||||
return SI->isVolatile() == cast<StoreInst>(I)->isVolatile();
|
return SI->isVolatile() == cast<StoreInst>(I)->isVolatile();
|
||||||
if (const VANextInst *VAN = dyn_cast<VANextInst>(this))
|
if (const VANextInst *VAN = dyn_cast<VANextInst>(this))
|
||||||
return VAN->getArgType() == cast<VANextInst>(I)->getArgType();
|
return VAN->getArgType() == cast<VANextInst>(I)->getArgType();
|
||||||
|
if (const CallInst *CI = dyn_cast<CallInst>(this))
|
||||||
|
return CI->isTailCall() == cast<CallInst>(I)->isTailCall();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -249,6 +249,7 @@ CallInst::CallInst(Value *Func, const std::string &Name,
|
||||||
CallInst::CallInst(const CallInst &CI)
|
CallInst::CallInst(const CallInst &CI)
|
||||||
: Instruction(CI.getType(), Instruction::Call, new Use[CI.getNumOperands()],
|
: Instruction(CI.getType(), Instruction::Call, new Use[CI.getNumOperands()],
|
||||||
CI.getNumOperands()) {
|
CI.getNumOperands()) {
|
||||||
|
setTailCall(CI.isTailCall());
|
||||||
Use *OL = OperandList;
|
Use *OL = OperandList;
|
||||||
Use *InOL = CI.OperandList;
|
Use *InOL = CI.OperandList;
|
||||||
for (unsigned i = 0, e = CI.getNumOperands(); i != e; ++i)
|
for (unsigned i = 0, e = CI.getNumOperands(); i != e; ++i)
|
||||||
|
|
Loading…
Reference in New Issue