From: Devang Patel Date: Sat, 23 Feb 2008 00:35:18 +0000 (+0000) Subject: To support multiple return values, now ret instruction supports multiple operands... X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=57ef4f46c182cdbe014d469892090ff50c739cf9;p=oota-llvm.git 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 --- diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h index 8321d6ff556..8d912f23702 100644 --- a/include/llvm/Instructions.h +++ b/include/llvm/Instructions.h @@ -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 &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 &retVals); + ReturnInst(std::vector &retVals, Instruction *InsertBefore); + ReturnInst(std::vector &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; } diff --git a/include/llvm/User.h b/include/llvm/User.h index 6592df9f728..0f1dcfe7a09 100644 --- a/include/llvm/User.h +++ b/include/llvm/User.h @@ -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. diff --git a/lib/AsmParser/llvmAsmParser.y b/lib/AsmParser/llvmAsmParser.y index 9f2e5acf935..b36e85c4a6c 100644 --- a/lib/AsmParser/llvmAsmParser.y +++ b/lib/AsmParser/llvmAsmParser.y @@ -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 Elements; - std::vector Vals; - for (std::vector::iterator I = $2->begin(), - E = $2->end(); I != E; ++I) { - Value *V = *I; - Constant *C = cast(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 { diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index 5194af3723d..8a7eec9b048 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -1304,23 +1304,8 @@ void AssemblyWriter::printInstruction(const Instruction &I) { Out << " }"; writeOperand(I.getOperand(0), false); Out << ", " << cast(I).getIndex(); - } else if (isa(I)) { - if (!Operand) - Out << " void"; - else { - if (I.getOperand(0)->getType()->isFirstClassType()) - writeOperand(I.getOperand(0), true); - else { - Constant *ROp = cast(I.getOperand(0)); - const StructType *STy = cast(ROp->getType()); - unsigned NumElems = STy->getNumElements(); - for (unsigned i = 0; i < NumElems; ++i) { - if (i) - Out << ","; - writeOperand(ROp->getOperand(i), true); - } - } - } + } else if (isa(I) && !Operand) { + Out << " void"; } else if (const CallInst *CI = dyn_cast(&I)) { // Print the calling convention being used. switch (CI->getCallingConv()) { diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index 457987a176a..d1df30b1033 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -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 &retVals, Instruction *InsertBefore) + : TerminatorInst(Type::VoidTy, Instruction::Ret, OperandList, retVals.size(), InsertBefore) { + init(retVals); +} +ReturnInst::ReturnInst(std::vector &retVals, BasicBlock *InsertAtEnd) + : TerminatorInst(Type::VoidTy, Instruction::Ret, OperandList, retVals.size(), InsertAtEnd) { + init(retVals); +} +ReturnInst::ReturnInst(std::vector &retVals) + : TerminatorInst(Type::VoidTy, Instruction::Ret, OperandList, retVals.size()) { + init(retVals); +} void ReturnInst::init(Value *retVal) { if (retVal && retVal->getType() != Type::VoidTy) { assert(!isa(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 &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(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. diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index 427b95b36da..1a7100e5a4a 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -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(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...