To support multiple return values, now ret instruction supports multiple operands instead of one aggregate operand.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47508 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Devang Patel 2008-02-23 00:35:18 +00:00
parent 313d4b8093
commit 57ef4f46c1
6 changed files with 77 additions and 65 deletions

View File

@ -1379,9 +1379,9 @@ public:
/// does not continue in this function any longer.
///
class ReturnInst : public TerminatorInst {
Use RetVal; // Return Value: null if 'void'.
ReturnInst(const ReturnInst &RI);
void init(Value *RetVal);
void init(std::vector<Value *> &RetVals);
public:
// ReturnInst constructors:
@ -1397,21 +1397,15 @@ public:
// if it was passed NULL.
explicit ReturnInst(Value *retVal = 0, Instruction *InsertBefore = 0);
ReturnInst(Value *retVal, BasicBlock *InsertAtEnd);
ReturnInst(std::vector<Value *> &retVals);
ReturnInst(std::vector<Value *> &retVals, Instruction *InsertBefore);
ReturnInst(std::vector<Value *> &retVals, BasicBlock *InsertAtEnd);
explicit ReturnInst(BasicBlock *InsertAtEnd);
virtual ~ReturnInst();
virtual ReturnInst *clone() const;
// Transparently provide more efficient getOperand methods.
Value *getOperand(unsigned i) const {
assert(i < getNumOperands() && "getOperand() out of range!");
return RetVal;
}
void setOperand(unsigned i, Value *Val) {
assert(i < getNumOperands() && "setOperand() out of range!");
RetVal = Val;
}
Value *getReturnValue() const { return RetVal; }
Value *getReturnValue(unsigned n = 0) const;
unsigned getNumSuccessors() const { return 0; }

View File

@ -29,8 +29,9 @@ protected:
/// OperandList - This is a pointer to the array of Users for this operand.
/// For nodes of fixed arity (e.g. a binary operator) this array will live
/// embedded into the derived class. For nodes of variable arity
/// (e.g. ConstantArrays, CallInst, PHINodes, etc), this memory will be
/// dynamically allocated and should be destroyed by the classes virtual dtor.
/// (e.g. ConstantArrays, CallInst, PHINodes, ReturnInst etc), this memory
/// will be dynamically allocated and should be destroyed by the classes
/// virtual dtor.
Use *OperandList;
/// NumOperands - The number of values used by this User.

View File

@ -2531,7 +2531,7 @@ ReturnedVal : ResolvedVal {
$$->push_back($1);
CHECK_FOR_ERROR
}
| ReturnedVal ',' ConstVal {
| ReturnedVal ',' ResolvedVal {
($$=$1)->push_back($3);
CHECK_FOR_ERROR
};
@ -2580,28 +2580,7 @@ InstructionList : InstructionList Inst {
BBTerminatorInst :
RET ReturnedVal { // Return with a result...
if($2->size() == 1)
$$ = new ReturnInst($2->back());
else {
std::vector<const Type*> Elements;
std::vector<Constant*> Vals;
for (std::vector<Value *>::iterator I = $2->begin(),
E = $2->end(); I != E; ++I) {
Value *V = *I;
Constant *C = cast<Constant>(V);
Elements.push_back(V->getType());
Vals.push_back(C);
}
const StructType *STy = StructType::get(Elements);
PATypeHolder *PTy =
new PATypeHolder(HandleUpRefs(StructType::get(Elements)));
Constant *CS = ConstantStruct::get(STy, Vals); // *$2);
$$ = new ReturnInst(CS);
delete PTy;
}
$$ = new ReturnInst(*$2);
delete $2;
CHECK_FOR_ERROR
}
@ -3174,6 +3153,7 @@ MemoryInst : MALLOC Types OptCAlign {
if (!GetResultInst::isValidOperands(TmpVal, $5))
GEN_ERROR("Invalid getresult operands");
$$ = new GetResultInst(TmpVal, $5);
delete $2;
CHECK_FOR_ERROR
}
| GETELEMENTPTR Types ValueRef IndexList {

View File

@ -1304,23 +1304,8 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
Out << " }";
writeOperand(I.getOperand(0), false);
Out << ", " << cast<GetResultInst>(I).getIndex();
} else if (isa<ReturnInst>(I)) {
if (!Operand)
Out << " void";
else {
if (I.getOperand(0)->getType()->isFirstClassType())
writeOperand(I.getOperand(0), true);
else {
Constant *ROp = cast<Constant>(I.getOperand(0));
const StructType *STy = cast<StructType>(ROp->getType());
unsigned NumElems = STy->getNumElements();
for (unsigned i = 0; i < NumElems; ++i) {
if (i)
Out << ",";
writeOperand(ROp->getOperand(i), true);
}
}
}
} else if (isa<ReturnInst>(I) && !Operand) {
Out << " void";
} else if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
// Print the calling convention being used.
switch (CI->getCallingConv()) {

View File

@ -573,34 +573,75 @@ bool InvokeInst::isStructReturn() const {
ReturnInst::ReturnInst(const ReturnInst &RI)
: TerminatorInst(Type::VoidTy, Instruction::Ret,
&RetVal, RI.getNumOperands()) {
if (RI.getNumOperands())
RetVal.init(RI.RetVal, this);
OperandList, RI.getNumOperands()) {
unsigned N = RI.getNumOperands();
Use *OL = OperandList = new Use[N];
for (unsigned i = 0; i < N; ++i)
OL[i].init(RI.getOperand(i), this);
}
ReturnInst::ReturnInst(Value *retVal, Instruction *InsertBefore)
: TerminatorInst(Type::VoidTy, Instruction::Ret, &RetVal, 0, InsertBefore) {
: TerminatorInst(Type::VoidTy, Instruction::Ret, OperandList, 0, InsertBefore) {
init(retVal);
}
ReturnInst::ReturnInst(Value *retVal, BasicBlock *InsertAtEnd)
: TerminatorInst(Type::VoidTy, Instruction::Ret, &RetVal, 0, InsertAtEnd) {
: TerminatorInst(Type::VoidTy, Instruction::Ret, OperandList, 0, InsertAtEnd) {
init(retVal);
}
ReturnInst::ReturnInst(BasicBlock *InsertAtEnd)
: TerminatorInst(Type::VoidTy, Instruction::Ret, &RetVal, 0, InsertAtEnd) {
: TerminatorInst(Type::VoidTy, Instruction::Ret, OperandList, 0, InsertAtEnd) {
}
ReturnInst::ReturnInst(std::vector<Value *> &retVals, Instruction *InsertBefore)
: TerminatorInst(Type::VoidTy, Instruction::Ret, OperandList, retVals.size(), InsertBefore) {
init(retVals);
}
ReturnInst::ReturnInst(std::vector<Value *> &retVals, BasicBlock *InsertAtEnd)
: TerminatorInst(Type::VoidTy, Instruction::Ret, OperandList, retVals.size(), InsertAtEnd) {
init(retVals);
}
ReturnInst::ReturnInst(std::vector<Value *> &retVals)
: TerminatorInst(Type::VoidTy, Instruction::Ret, OperandList, retVals.size()) {
init(retVals);
}
void ReturnInst::init(Value *retVal) {
if (retVal && retVal->getType() != Type::VoidTy) {
assert(!isa<BasicBlock>(retVal) &&
"Cannot return basic block. Probably using the incorrect ctor");
NumOperands = 1;
RetVal.init(retVal, this);
Use *OL = OperandList = new Use[1];
OL[0].init(retVal, this);
}
}
void ReturnInst::init(std::vector<Value *> &retVals) {
if (retVals.empty())
return;
NumOperands = retVals.size();
if (NumOperands == 1) {
Value *V = retVals[0];
if (V->getType() == Type::VoidTy)
return;
}
Use *OL = OperandList = new Use[NumOperands];
for (unsigned i = 0; i < NumOperands; ++i) {
Value *V = retVals[i];
assert(!isa<BasicBlock>(V) &&
"Cannot return basic block. Probably using the incorrect ctor");
OL[i].init(V, this);
}
}
Value *ReturnInst::getReturnValue(unsigned n) const {
if (NumOperands)
return OperandList[n];
else
return 0;
}
unsigned ReturnInst::getNumSuccessorsV() const {
return getNumSuccessors();
}
@ -617,6 +658,10 @@ BasicBlock *ReturnInst::getSuccessorV(unsigned idx) const {
return 0;
}
ReturnInst::~ReturnInst() {
if (NumOperands)
delete [] OperandList;
}
//===----------------------------------------------------------------------===//
// UnwindInst Implementation
@ -2759,7 +2804,6 @@ bool GetResultInst::isValidOperands(const Value *Aggregate, unsigned Index) {
return false;
}
// Define these methods here so vtables don't get emitted into every translation
// unit that uses these classes.

View File

@ -576,14 +576,22 @@ void Verifier::visitTerminatorInst(TerminatorInst &I) {
void Verifier::visitReturnInst(ReturnInst &RI) {
Function *F = RI.getParent()->getParent();
if (RI.getNumOperands() == 0)
unsigned N = RI.getNumOperands();
if (N == 0)
Assert2(F->getReturnType() == Type::VoidTy,
"Found return instr that returns void in Function of non-void "
"return type!", &RI, F->getReturnType());
else
else if (N == 1)
Assert2(F->getReturnType() == RI.getOperand(0)->getType(),
"Function return type does not match operand "
"type of return inst!", &RI, F->getReturnType());
else {
const StructType *STy = cast<StructType>(F->getReturnType());
for (unsigned i = 0; i < N; i++)
Assert2(STy->getElementType(i) == RI.getOperand(i)->getType(),
"Function return type does not match operand "
"type of return inst!", &RI, F->getReturnType());
}
// Check to make sure that the return value has necessary properties for
// terminators...