mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-29 22:50:47 +00:00
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:
parent
313d4b8093
commit
57ef4f46c1
@ -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; }
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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()) {
|
||||
|
@ -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.
|
||||
|
||||
|
@ -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...
|
||||
|
Loading…
Reference in New Issue
Block a user