From fc74abfba5128544a750fce22fdf13eb0403e3ce Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 23 Jul 2008 00:34:11 +0000 Subject: Enable first-class aggregates support. Remove the GetResultInst instruction. It is still accepted in LLVM assembly and bitcode, where it is now auto-upgraded to ExtractValueInst. Also, remove support for return instructions with multiple values. These are auto-upgraded to use InsertValueInst instructions. The IRBuilder still accepts multiple-value returns, and auto-upgrades them to InsertValueInst instructions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@53941 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/VMCore/AsmWriter.cpp | 3 -- lib/VMCore/AutoUpgrade.cpp | 28 ------------ lib/VMCore/Instruction.cpp | 1 - lib/VMCore/Instructions.cpp | 103 +++++--------------------------------------- lib/VMCore/Verifier.cpp | 41 ++++++++---------- 5 files changed, 27 insertions(+), 149 deletions(-) (limited to 'lib/VMCore') diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index 9e010051a5..98c6fefad7 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -1299,9 +1299,6 @@ void AssemblyWriter::printInstruction(const Instruction &I) { writeOperand(I.getOperand(op ), false); Out << ','; writeOperand(I.getOperand(op+1), false); Out << " ]"; } - } else if (const GetResultInst *GRI = dyn_cast(&I)) { - writeOperand(I.getOperand(0), true); - Out << ", " << GRI->getIndex(); } else if (const ExtractValueInst *EVI = dyn_cast(&I)) { writeOperand(I.getOperand(0), true); for (const unsigned *i = EVI->idx_begin(), *e = EVI->idx_end(); i != e; ++i) diff --git a/lib/VMCore/AutoUpgrade.cpp b/lib/VMCore/AutoUpgrade.cpp index fd7d6dcd4c..a48fbd2c90 100644 --- a/lib/VMCore/AutoUpgrade.cpp +++ b/lib/VMCore/AutoUpgrade.cpp @@ -414,31 +414,3 @@ void llvm::UpgradeCallsToIntrinsic(Function* F) { } } } - -/// This is an auto-upgrade hook for mutiple-value return statements. -/// This function auto-upgrades all such return statements in the given -/// function to use aggregate return values built with insertvalue -/// instructions. -void llvm::UpgradeMultipleReturnValues(Function *CurrentFunction) { - const Type *ReturnType = CurrentFunction->getReturnType(); - for (Function::iterator I = CurrentFunction->begin(), - E = CurrentFunction->end(); I != E; ++I) { - BasicBlock *BB = I; - if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { - unsigned NumVals = RI->getNumOperands(); - if (NumVals > 1 || - (isa(ReturnType) && - (NumVals == 0 || RI->getOperand(0)->getType() != ReturnType))) { - std::vector Types(NumVals); - for (unsigned i = 0; i != NumVals; ++i) - Types[i] = RI->getOperand(i)->getType(); - const Type *ReturnType = StructType::get(Types); - Value *RV = UndefValue::get(ReturnType); - for (unsigned i = 0; i != NumVals; ++i) - RV = InsertValueInst::Create(RV, RI->getOperand(i), i, "mrv", RI); - ReturnInst::Create(RV, RI); - RI->eraseFromParent(); - } - } - } -} diff --git a/lib/VMCore/Instruction.cpp b/lib/VMCore/Instruction.cpp index e8738d2ba7..97334b3e24 100644 --- a/lib/VMCore/Instruction.cpp +++ b/lib/VMCore/Instruction.cpp @@ -146,7 +146,6 @@ const char *Instruction::getOpcodeName(unsigned OpCode) { case ExtractElement: return "extractelement"; case InsertElement: return "insertelement"; case ShuffleVector: return "shufflevector"; - case GetResult: return "getresult"; case ExtractValue: return "extractvalue"; case InsertValue: return "insertvalue"; diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index 36c3de72ce..3906c521c2 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -500,75 +500,30 @@ void InvokeInst::removeParamAttr(unsigned i, ParameterAttributes attr) { ReturnInst::ReturnInst(const ReturnInst &RI) : TerminatorInst(Type::VoidTy, Instruction::Ret, - OperandTraits::op_end(this) - - RI.getNumOperands(), + OperandTraits::op_end(this) - + RI.getNumOperands(), RI.getNumOperands()) { - unsigned N = RI.getNumOperands(); - if (N == 1) + if (RI.getNumOperands()) Op<0>() = RI.Op<0>(); - else if (N) { - Use *OL = OperandList; - for (unsigned i = 0; i < N; ++i) - OL[i] = RI.getOperand(i); - } } ReturnInst::ReturnInst(Value *retVal, Instruction *InsertBefore) : TerminatorInst(Type::VoidTy, Instruction::Ret, - OperandTraits::op_end(this) - (retVal != 0), - retVal != 0, InsertBefore) { + OperandTraits::op_end(this) - !!retVal, !!retVal, + InsertBefore) { if (retVal) - init(&retVal, 1); + Op<0>() = retVal; } ReturnInst::ReturnInst(Value *retVal, BasicBlock *InsertAtEnd) : TerminatorInst(Type::VoidTy, Instruction::Ret, - OperandTraits::op_end(this) - (retVal != 0), - retVal != 0, InsertAtEnd) { + OperandTraits::op_end(this) - !!retVal, !!retVal, + InsertAtEnd) { if (retVal) - init(&retVal, 1); + Op<0>() = retVal; } ReturnInst::ReturnInst(BasicBlock *InsertAtEnd) : TerminatorInst(Type::VoidTy, Instruction::Ret, - OperandTraits::op_end(this), - 0, InsertAtEnd) { -} - -ReturnInst::ReturnInst(Value * const* retVals, unsigned N, - Instruction *InsertBefore) - : TerminatorInst(Type::VoidTy, Instruction::Ret, - OperandTraits::op_end(this) - N, - N, InsertBefore) { - if (N != 0) - init(retVals, N); -} -ReturnInst::ReturnInst(Value * const* retVals, unsigned N, - BasicBlock *InsertAtEnd) - : TerminatorInst(Type::VoidTy, Instruction::Ret, - OperandTraits::op_end(this) - N, - N, InsertAtEnd) { - if (N != 0) - init(retVals, N); -} - -void ReturnInst::init(Value * const* retVals, unsigned N) { - assert (N > 0 && "Invalid operands numbers in ReturnInst init"); - - NumOperands = N; - if (NumOperands == 1) { - Value *V = *retVals; - if (V->getType() == Type::VoidTy) - return; - Op<0>() = V; - return; - } - - Use *OL = OperandList; - for (unsigned i = 0; i < NumOperands; ++i) { - Value *V = *retVals++; - assert(!isa(V) && - "Cannot return basic block. Probably using the incorrect ctor"); - OL[i] = V; - } + OperandTraits::op_end(this), 0, InsertAtEnd) { } unsigned ReturnInst::getNumSuccessorsV() const { @@ -2855,43 +2810,6 @@ void SwitchInst::setSuccessorV(unsigned idx, BasicBlock *B) { setSuccessor(idx, B); } -//===----------------------------------------------------------------------===// -// GetResultInst Implementation -//===----------------------------------------------------------------------===// - -GetResultInst::GetResultInst(Value *Aggregate, unsigned Index, - const std::string &Name, - Instruction *InsertBef) - : UnaryInstruction(cast(Aggregate->getType()) - ->getElementType(Index), - GetResult, Aggregate, InsertBef), - Idx(Index) { - assert(isValidOperands(Aggregate, Index) - && "Invalid GetResultInst operands!"); - setName(Name); -} - -bool GetResultInst::isValidOperands(const Value *Aggregate, unsigned Index) { - if (!Aggregate) - return false; - - if (const StructType *STy = dyn_cast(Aggregate->getType())) { - unsigned NumElements = STy->getNumElements(); - if (Index >= NumElements || NumElements == 0) - return false; - - // getresult aggregate value's element types are restricted to - // avoid nested aggregates. - for (unsigned i = 0; i < NumElements; ++i) - if (!STy->getElementType(i)->isFirstClassType()) - return false; - - // Otherwise, Aggregate is valid. - return true; - } - return false; -} - // Define these methods here so vtables don't get emitted into every translation // unit that uses these classes. @@ -2972,4 +2890,3 @@ InvokeInst *InvokeInst::clone() const { } UnwindInst *UnwindInst::clone() const { return new UnwindInst(); } UnreachableInst *UnreachableInst::clone() const { return new UnreachableInst();} -GetResultInst *GetResultInst::clone() const { return new GetResultInst(*this); } diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index 79c24f334c..0aef414a68 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -259,7 +259,8 @@ namespace { void visitUserOp2(Instruction &I) { visitUserOp1(I); } void visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI); void visitAllocationInst(AllocationInst &AI); - void visitGetResultInst(GetResultInst &GRI); + void visitExtractValueInst(ExtractValueInst &EVI); + void visitInsertValueInst(InsertValueInst &IVI); void VerifyCallSite(CallSite CS); void VerifyIntrinsicPrototype(Intrinsic::ID ID, Function *F, @@ -1090,18 +1091,23 @@ void Verifier::visitAllocationInst(AllocationInst &AI) { visitInstruction(AI); } -void Verifier::visitGetResultInst(GetResultInst &GRI) { - Assert1(GetResultInst::isValidOperands(GRI.getAggregateValue(), - GRI.getIndex()), - "Invalid GetResultInst operands!", &GRI); - Assert1(isa(GRI.getAggregateValue()) || - isa(GRI.getAggregateValue()) || - isa(GRI.getAggregateValue()), - "GetResultInst operand must be a call/invoke/undef!", &GRI); +void Verifier::visitExtractValueInst(ExtractValueInst &EVI) { + Assert1(ExtractValueInst::getIndexedType(EVI.getAggregateOperand()->getType(), + EVI.idx_begin(), EVI.idx_end()) == + EVI.getType(), + "Invalid ExtractValueInst operands!", &EVI); - visitInstruction(GRI); + visitInstruction(EVI); } +void Verifier::visitInsertValueInst(InsertValueInst &IVI) { + Assert1(ExtractValueInst::getIndexedType(IVI.getAggregateOperand()->getType(), + IVI.idx_begin(), IVI.idx_end()) == + IVI.getOperand(1)->getType(), + "Invalid InsertValueInst operands!", &IVI); + + visitInstruction(IVI); +} /// verifyInstruction - Verify that an instruction is well formed. /// @@ -1151,20 +1157,7 @@ void Verifier::visitInstruction(Instruction &I) { // Check to make sure that only first-class-values are operands to // instructions. if (!I.getOperand(i)->getType()->isFirstClassType()) { - if (isa(I) || isa(I)) - Assert1(isa(I.getOperand(i)->getType()), - "Invalid ReturnInst operands!", &I); - else if (isa(I) || isa(I)) { - if (const PointerType *PT = dyn_cast - (I.getOperand(i)->getType())) { - const Type *ETy = PT->getElementType(); - Assert1(isa(ETy), "Invalid CallInst operands!", &I); - } - else - Assert1(0, "Invalid CallInst operands!", &I); - } - else - Assert1(0, "Instruction operands must be first-class values!", &I); + Assert1(0, "Instruction operands must be first-class values!", &I); } if (Function *F = dyn_cast(I.getOperand(i))) { -- cgit v1.2.3