diff options
-rw-r--r-- | include/llvm/Instructions.h | 536 |
1 files changed, 304 insertions, 232 deletions
diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h index 58cc1ee4f1..9d0e02faf9 100644 --- a/include/llvm/Instructions.h +++ b/include/llvm/Instructions.h @@ -31,9 +31,8 @@ class PointerType; /// AllocationInst - This class is the common base class of MallocInst and /// AllocaInst. /// -class AllocationInst : public Instruction { +class AllocationInst : public UnaryInstruction { protected: - void init(const Type *Ty, Value *ArraySize, unsigned iTy); AllocationInst(const Type *Ty, Value *ArraySize, unsigned iTy, const std::string &Name = "", Instruction *InsertBefore = 0); AllocationInst(const Type *Ty, Value *ArraySize, unsigned iTy, @@ -49,8 +48,8 @@ public: /// getArraySize - Get the number of element allocated, for a simple /// allocation of a single element, this will return a constant 1 value. /// - inline const Value *getArraySize() const { return Operands[0]; } - inline Value *getArraySize() { return Operands[0]; } + inline const Value *getArraySize() const { return getOperand(0); } + inline Value *getArraySize() { return getOperand(0); } /// getType - Overload to return most specific pointer type /// @@ -143,9 +142,8 @@ public: /// FreeInst - an instruction to deallocate memory /// -class FreeInst : public Instruction { - void init(Value *Ptr); - +class FreeInst : public UnaryInstruction { + void AssertOK(); public: explicit FreeInst(Value *Ptr, Instruction *InsertBefore = 0); FreeInst(Value *Ptr, BasicBlock *InsertAfter); @@ -171,13 +169,17 @@ public: /// LoadInst - an instruction for reading from memory /// -class LoadInst : public Instruction { - LoadInst(const LoadInst &LI) : Instruction(LI.getType(), Load) { - Volatile = LI.isVolatile(); - init(LI.Operands[0]); - } +class LoadInst : public UnaryInstruction { bool Volatile; // True if this is a volatile load - void init(Value *Ptr); + + LoadInst(const LoadInst &LI) + : UnaryInstruction(LI.getType(), Load, LI.getOperand(0)), + Volatile(LI.isVolatile()) { +#ifndef NDEBUG + AssertOK(); +#endif + } + void AssertOK(); public: LoadInst(Value *Ptr, const std::string &Name, Instruction *InsertBefore); LoadInst(Value *Ptr, const std::string &Name, BasicBlock *InsertAtEnd); @@ -221,12 +223,17 @@ public: /// StoreInst - an instruction for storing to memory /// class StoreInst : public Instruction { - StoreInst(const StoreInst &SI) : Instruction(SI.getType(), Store) { - Volatile = SI.isVolatile(); - init(SI.Operands[0], SI.Operands[1]); - } + Use Ops[2]; bool Volatile; // True if this is a volatile store - void init(Value *Val, Value *Ptr); + StoreInst(const StoreInst &SI) : Instruction(SI.getType(), Store, Ops, 2), + Volatile(SI.isVolatile()) { + Ops[0].init(SI.Ops[0], this); + Ops[1].init(SI.Ops[1], this); +#ifndef NDEBUG + AssertOK(); +#endif + } + void AssertOK(); public: StoreInst(Value *Val, Value *Ptr, Instruction *InsertBefore); StoreInst(Value *Val, Value *Ptr, BasicBlock *InsertAtEnd); @@ -244,6 +251,18 @@ public: /// void setVolatile(bool V) { Volatile = V; } + /// Transparently provide more efficient getOperand methods. + Value *getOperand(unsigned i) const { + assert(i < 2 && "getOperand() out of range!"); + return Ops[i]; + } + void setOperand(unsigned i, Value *Val) { + assert(i < 2 && "setOperand() out of range!"); + Ops[i] = Val; + } + unsigned getNumOperands() const { return 2; } + + virtual StoreInst *clone() const; virtual bool mayWriteToMemory() const { return true; } @@ -271,12 +290,13 @@ public: /// access elements of arrays and structs /// class GetElementPtrInst : public Instruction { - GetElementPtrInst(const GetElementPtrInst &EPI) - : Instruction((static_cast<const Instruction*>(&EPI)->getType()), - GetElementPtr) { - Operands.reserve(EPI.Operands.size()); - for (unsigned i = 0, E = (unsigned)EPI.Operands.size(); i != E; ++i) - Operands.push_back(Use(EPI.Operands[i], this)); + GetElementPtrInst(const GetElementPtrInst &GEPI) + : Instruction(reinterpret_cast<const Type*>(GEPI.getType()), GetElementPtr, + 0, GEPI.getNumOperands()) { + Use *OL = OperandList = new Use[NumOperands]; + Use *GEPIOL = GEPI.OperandList; + for (unsigned i = 0, E = NumOperands; i != E; ++i) + OL[i].init(GEPIOL[i], this); } void init(Value *Ptr, const std::vector<Value*> &Idx); void init(Value *Ptr, Value *Idx0, Value *Idx1); @@ -296,6 +316,7 @@ public: const std::string &Name = "", Instruction *InsertBefore =0); GetElementPtrInst(Value *Ptr, Value *Idx0, Value *Idx1, const std::string &Name, BasicBlock *InsertAtEnd); + ~GetElementPtrInst(); virtual GetElementPtrInst *clone() const; @@ -408,25 +429,18 @@ public: /// CastInst - This class represents a cast from Operand[0] to the type of /// the instruction (i->getType()). /// -class CastInst : public Instruction { - CastInst(const CastInst &CI) : Instruction(CI.getType(), Cast) { - Operands.reserve(1); - Operands.push_back(Use(CI.Operands[0], this)); - } - void init(Value *S) { - Operands.reserve(1); - Operands.push_back(Use(S, this)); +class CastInst : public UnaryInstruction { + CastInst(const CastInst &CI) + : UnaryInstruction(CI.getType(), Cast, CI.getOperand(0)) { } public: CastInst(Value *S, const Type *Ty, const std::string &Name = "", Instruction *InsertBefore = 0) - : Instruction(Ty, Cast, Name, InsertBefore) { - init(S); + : UnaryInstruction(Ty, Cast, S, Name, InsertBefore) { } CastInst(Value *S, const Type *Ty, const std::string &Name, BasicBlock *InsertAtEnd) - : Instruction(Ty, Cast, Name, InsertAtEnd) { - init(S); + : UnaryInstruction(Ty, Cast, S, Name, InsertAtEnd) { } virtual CastInst *clone() const; @@ -476,6 +490,7 @@ public: Instruction *InsertBefore = 0); explicit CallInst(Value *F, const std::string &Name, BasicBlock *InsertAtEnd); + ~CallInst(); virtual CallInst *clone() const; bool mayWriteToMemory() const { return true; } @@ -484,12 +499,12 @@ public: /// if it is a direct call. If it is a call through a function pointer, /// return null. Function *getCalledFunction() const { - return dyn_cast<Function>(Operands[0]); + return (Function*)dyn_cast<Function>(getOperand(0)); } // getCalledValue - Get a pointer to a method that is invoked by this inst. - inline const Value *getCalledValue() const { return Operands[0]; } - inline Value *getCalledValue() { return Operands[0]; } + inline const Value *getCalledValue() const { return getOperand(0); } + inline Value *getCalledValue() { return getOperand(0); } // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const CallInst *) { return true; } @@ -509,27 +524,27 @@ public: /// ShiftInst - This class represents left and right shift instructions. /// class ShiftInst : public Instruction { - ShiftInst(const ShiftInst &SI) : Instruction(SI.getType(), SI.getOpcode()) { - Operands.reserve(2); - Operands.push_back(Use(SI.Operands[0], this)); - Operands.push_back(Use(SI.Operands[1], this)); + Use Ops[2]; + ShiftInst(const ShiftInst &SI) + : Instruction(SI.getType(), SI.getOpcode(), Ops, 2) { + Ops[0].init(SI.Ops[0], this); + Ops[1].init(SI.Ops[1], this); } void init(OtherOps Opcode, Value *S, Value *SA) { assert((Opcode == Shl || Opcode == Shr) && "ShiftInst Opcode invalid!"); - Operands.reserve(2); - Operands.push_back(Use(S, this)); - Operands.push_back(Use(SA, this)); + Ops[0].init(S, this); + Ops[1].init(SA, this); } public: ShiftInst(OtherOps Opcode, Value *S, Value *SA, const std::string &Name = "", Instruction *InsertBefore = 0) - : Instruction(S->getType(), Opcode, Name, InsertBefore) { + : Instruction(S->getType(), Opcode, Ops, 2, Name, InsertBefore) { init(Opcode, S, SA); } ShiftInst(OtherOps Opcode, Value *S, Value *SA, const std::string &Name, BasicBlock *InsertAtEnd) - : Instruction(S->getType(), Opcode, Name, InsertAtEnd) { + : Instruction(S->getType(), Opcode, Ops, 2, Name, InsertAtEnd) { init(Opcode, S, SA); } @@ -537,6 +552,17 @@ public: return static_cast<OtherOps>(Instruction::getOpcode()); } + /// Transparently provide more efficient getOperand methods. + Value *getOperand(unsigned i) const { + assert(i < 2 && "getOperand() out of range!"); + return Ops[i]; + } + void setOperand(unsigned i, Value *Val) { + assert(i < 2 && "setOperand() out of range!"); + Ops[i] = Val; + } + unsigned getNumOperands() const { return 2; } + virtual ShiftInst *clone() const; // Methods for support type inquiry through isa, cast, and dyn_cast: @@ -557,34 +583,46 @@ public: /// SelectInst - This class represents the LLVM 'select' instruction. /// class SelectInst : public Instruction { - SelectInst(const SelectInst &SI) : Instruction(SI.getType(), SI.getOpcode()) { - Operands.reserve(3); - Operands.push_back(Use(SI.Operands[0], this)); - Operands.push_back(Use(SI.Operands[1], this)); - Operands.push_back(Use(SI.Operands[2], this)); - } + Use Ops[3]; + void init(Value *C, Value *S1, Value *S2) { - Operands.reserve(3); - Operands.push_back(Use(C, this)); - Operands.push_back(Use(S1, this)); - Operands.push_back(Use(S2, this)); + Ops[0].init(C, this); + Ops[1].init(S1, this); + Ops[2].init(S2, this); } + SelectInst(const SelectInst &SI) + : Instruction(SI.getType(), SI.getOpcode(), Ops, 3) { + init(SI.Ops[0], SI.Ops[1], SI.Ops[2]); + } public: SelectInst(Value *C, Value *S1, Value *S2, const std::string &Name = "", Instruction *InsertBefore = 0) - : Instruction(S1->getType(), Instruction::Select, Name, InsertBefore) { + : Instruction(S1->getType(), Instruction::Select, Ops, 3, + Name, InsertBefore) { init(C, S1, S2); } SelectInst(Value *C, Value *S1, Value *S2, const std::string &Name, BasicBlock *InsertAtEnd) - : Instruction(S1->getType(), Instruction::Select, Name, InsertAtEnd) { + : Instruction(S1->getType(), Instruction::Select, Ops, 3, + Name, InsertAtEnd) { init(C, S1, S2); } - Value *getCondition() const { return Operands[0]; } - Value *getTrueValue() const { return Operands[1]; } - Value *getFalseValue() const { return Operands[2]; } + Value *getCondition() const { return Ops[0]; } + Value *getTrueValue() const { return Ops[1]; } + Value *getFalseValue() const { return Ops[2]; } + + /// Transparently provide more efficient getOperand methods. + Value *getOperand(unsigned i) const { + assert(i < 3 && "getOperand() out of range!"); + return Ops[i]; + } + void setOperand(unsigned i, Value *Val) { + assert(i < 3 && "setOperand() out of range!"); + Ops[i] = Val; + } + unsigned getNumOperands() const { return 3; } OtherOps getOpcode() const { return static_cast<OtherOps>(Instruction::getOpcode()); @@ -611,27 +649,23 @@ public: /// advances a vararg list passed an argument of the specified type, returning /// the resultant list. /// -class VANextInst : public Instruction { +class VANextInst : public UnaryInstruction { PATypeHolder ArgTy; - void init(Value *List) { - Operands.reserve(1); - Operands.push_back(Use(List, this)); - } VANextInst(const VANextInst &VAN) - : Instruction(VAN.getType(), VANext), ArgTy(VAN.getArgType()) { - init(VAN.Operands[0]); + : UnaryInstruction(VAN.getType(), VANext, VAN.getOperand(0)), + ArgTy(VAN.getArgType()) { } public: VANextInst(Value *List, const Type *Ty, const std::string &Name = "", Instruction *InsertBefore = 0) - : Instruction(List->getType(), VANext, Name, InsertBefore), ArgTy(Ty) { - init(List); + : UnaryInstruction(List->getType(), VANext, List, Name, InsertBefore), + ArgTy(Ty) { } VANextInst(Value *List, const Type *Ty, const std::string &Name, BasicBlock *InsertAtEnd) - : Instruction(List->getType(), VANext, Name, InsertAtEnd), ArgTy(Ty) { - init(List); + : UnaryInstruction(List->getType(), VANext, List, Name, InsertAtEnd), + ArgTy(Ty) { } const Type *getArgType() const { return ArgTy; } @@ -656,25 +690,17 @@ public: /// VAArgInst - This class represents the va_arg llvm instruction, which returns /// an argument of the specified type given a va_list. /// -class VAArgInst : public Instruction { - void init(Value* List) { - Operands.reserve(1); - Operands.push_back(Use(List, this)); - } +class VAArgInst : public UnaryInstruction { VAArgInst(const VAArgInst &VAA) - : Instruction(VAA.getType(), VAArg) { - init(VAA.Operands[0]); - } + : UnaryInstruction(VAA.getType(), VAArg, VAA.getOperand(0)) {} public: VAArgInst(Value *List, const Type *Ty, const std::string &Name = "", Instruction *InsertBefore = 0) - : Instruction(Ty, VAArg, Name, InsertBefore) { - init(List); + : UnaryInstruction(Ty, VAArg, List, Name, InsertBefore) { } VAArgInst(Value *List, const Type *Ty, const std::string &Name, BasicBlock *InsertAtEnd) - : Instruction(Ty, VAArg, Name, InsertAtEnd) { - init(List); + : UnaryInstruction(Ty, VAArg, List, Name, InsertAtEnd) { } virtual VAArgInst *clone() const; @@ -698,46 +724,59 @@ public: // scientist's overactive imagination. // class PHINode : public Instruction { + /// ReservedSpace - The number of operands actually allocated. NumOperands is + /// the number actually in use. + unsigned ReservedSpace; PHINode(const PHINode &PN); public: PHINode(const Type *Ty, const std::string &Name = "", Instruction *InsertBefore = 0) - : Instruction(Ty, Instruction::PHI, Name, InsertBefore) { + : Instruction(Ty, Instruction::PHI, 0, 0, Name, InsertBefore), + ReservedSpace(0) { } PHINode(const Type *Ty, const std::string &Name, BasicBlock *InsertAtEnd) - : Instruction(Ty, Instruction::PHI, Name, InsertAtEnd) { + : Instruction(Ty, Instruction::PHI, 0, 0, Name, InsertAtEnd), + ReservedSpace(0) { + } + + ~PHINode(); + + /// reserveOperandSpace - This method can be used to avoid repeated + /// reallocation of PHI operand lists by reserving space for the correct + /// number of operands before adding them. Unlike normal vector reserves, + /// this method can also be used to trim the operand space. + void reserveOperandSpace(unsigned NumValues) { + resizeOperands(NumValues*2); } virtual PHINode *clone() const; /// getNumIncomingValues - Return the number of incoming edges /// - unsigned getNumIncomingValues() const { return (unsigned)Operands.size()/2; } + unsigned getNumIncomingValues() const { return getNumOperands()/2; } /// getIncomingValue - Return incoming value #x /// Value *getIncomingValue(unsigned i) const { - assert(i*2 < Operands.size() && "Invalid value number!"); - return Operands[i*2]; + assert(i*2 < getNumOperands() && "Invalid value number!"); + return getOperand(i*2); } void setIncomingValue(unsigned i, Value *V) { - assert(i*2 < Operands.size() && "Invalid value number!"); - Operands[i*2] = V; + assert(i*2 < getNumOperands() && "Invalid value number!"); + setOperand(i*2, V); } - inline unsigned getOperandNumForIncomingValue(unsigned i) { + unsigned getOperandNumForIncomingValue(unsigned i) { return i*2; } /// getIncomingBlock - Return incoming basic block #x /// BasicBlock *getIncomingBlock(unsigned i) const { - assert(i*2+1 < Operands.size() && "Invalid value number!"); - return reinterpret_cast<BasicBlock*>(Operands[i*2+1].get()); + return reinterpret_cast<BasicBlock*>(getOperand(i*2+1)); } void setIncomingBlock(unsigned i, BasicBlock *BB) { - assert(i*2+1 < Operands.size() && "Invalid value number!"); - Operands[i*2+1] = reinterpret_cast<Value*>(BB); + setOperand(i*2+1, reinterpret_cast<Value*>(BB)); } unsigned getOperandNumForIncomingBlock(unsigned i) { return i*2+1; @@ -748,8 +787,13 @@ public: void addIncoming(Value *V, BasicBlock *BB) { assert(getType() == V->getType() && "All operands to PHI node must be the same type as the PHI node!"); - Operands.push_back(Use(V, this)); - Operands.push_back(Use(reinterpret_cast<Value*>(BB), this)); + unsigned OpNo = NumOperands; + if (OpNo+2 > ReservedSpace) + resizeOperands(0); // Get more space! + // Initialize some new operands. + NumOperands = OpNo+2; + OperandList[OpNo].init(V, this); + OperandList[OpNo+1].init(reinterpret_cast<Value*>(BB), this); } /// removeIncomingValue - Remove an incoming value. This is useful if a @@ -772,8 +816,9 @@ public: /// block in the value list for this PHI. Returns -1 if no instance. /// int getBasicBlockIndex(const BasicBlock *BB) const { - for (unsigned i = 0; i < Operands.size()/2; ++i) - if (getIncomingBlock(i) == BB) return i; + Use *OL = OperandList; + for (unsigned i = 0, e = getNumOperands(); i != e; i += 2) + if (OL[i+1] == reinterpret_cast<const Value*>(BB)) return i/2; return -1; } @@ -789,6 +834,8 @@ public: static inline bool classof(const Value *V) { return isa<Instruction>(V) && classof(cast<Instruction>(V)); } + private: + void resizeOperands(unsigned NumOperands); }; //===----------------------------------------------------------------------===// @@ -800,12 +847,11 @@ public: /// does not continue in this function any longer. /// class ReturnInst : public TerminatorInst { - ReturnInst(const ReturnInst &RI) : TerminatorInst(Instruction::Ret) { - if (RI.Operands.size()) { - assert(RI.Operands.size() == 1 && "Return insn can only have 1 operand!"); - Operands.reserve(1); - Operands.push_back(Use(RI.Operands[0], this)); - } + Use RetVal; // Possibly null retval. + ReturnInst(const ReturnInst &RI) : TerminatorInst(Instruction::Ret, &RetVal, + RI.getNumOperands()) { + if (RI.getNumOperands()) + RetVal.init(RI.RetVal, this); } void init(Value *RetVal); @@ -822,34 +868,33 @@ public: // // NOTE: If the Value* passed is of type void then the constructor behaves as // if it was passed NULL. - ReturnInst(Value *RetVal = 0, Instruction *InsertBefore = 0) - : TerminatorInst(Instruction::Ret, InsertBefore) { - init(RetVal); + ReturnInst(Value *retVal = 0, Instruction *InsertBefore = 0) + : TerminatorInst(Instruction::Ret, &RetVal, 0, InsertBefore) { + init(retVal); } - ReturnInst(Value *RetVal, BasicBlock *InsertAtEnd) - : TerminatorInst(Instruction::Ret, InsertAtEnd) { - init(RetVal); + ReturnInst(Value *retVal, BasicBlock *InsertAtEnd) + : TerminatorInst(Instruction::Ret, &RetVal, 0, InsertAtEnd) { + init(retVal); } ReturnInst(BasicBlock *InsertAtEnd) - : TerminatorInst(Instruction::Ret, InsertAtEnd) { + : TerminatorInst(Instruction::Ret, &RetVal, 0, InsertAtEnd) { } virtual ReturnInst *clone() const; - inline const Value *getReturnValue() const { - return Operands.size() ? Operands[0].get() : 0; + // Transparently provide more efficient getOperand methods. + Value *getOperand(unsigned i) const { + assert(i < getNumOperands() && "getOperand() out of range!"); + return RetVal; } - inline Value *getReturnValue() { - return Operands.size() ? Operands[0].get() : 0; + void setOperand(unsigned i, Value *Val) { + assert(i < getNumOperands() && "setOperand() out of range!"); + RetVal = Val; } - virtual const BasicBlock *getSuccessor(unsigned idx) const { - assert(0 && "ReturnInst has no successors!"); - abort(); - return 0; - } - virtual void setSuccessor(unsigned idx, BasicBlock *NewSucc); - virtual unsigned getNumSuccessors() const { return 0; } + Value *getReturnValue() const { return RetVal; } + + unsigned getNumSuccessors() const { return 0; } // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const ReturnInst *) { return true; } @@ -859,6 +904,10 @@ public: static inline bool classof(const Value *V) { return isa<Instruction>(V) && classof(cast<Instruction>(V)); } + private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); }; //===----------------------------------------------------------------------===// @@ -869,9 +918,12 @@ public: /// BranchInst - Conditional or Unconditional Branch instruction. /// class BranchInst : public TerminatorInst { + /// Ops list - Branches are strange. The operands are ordered: + /// TrueDest, FalseDest, Cond. This makes some accessors faster because + /// they don't have to check for cond/uncond branchness. + Use Ops[3]; BranchInst(const BranchInst &BI); - void init(BasicBlock *IfTrue); - void init(BasicBlock *True, BasicBlock *False, Value *Cond); + void AssertOK(); public: // BranchInst constructors (where {B, T, F} are blocks, and C is a condition): // BranchInst(BB *B) - 'br B' @@ -881,34 +933,57 @@ public: // BranchInst(BB* B, BB *I) - 'br B' insert at end // BranchInst(BB* T, BB *F, Value *C, BB *I) - 'br C, T, F', insert at end BranchInst(BasicBlock *IfTrue, Instruction *InsertBefore = 0) - : TerminatorInst(Instruction::Br, InsertBefore) { - init(IfTrue); + : TerminatorInst(Instruction::Br, Ops, 1, InsertBefore) { + assert(IfTrue != 0 && "Branch destination may not be null!"); + Ops[0].init(reinterpret_cast<Value*>(IfTrue), this); } BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, Instruction *InsertBefore = 0) - : TerminatorInst(Instruction::Br, InsertBefore) { - init(IfTrue, IfFalse, Cond); + : TerminatorInst(Instruction::Br, Ops, 3, InsertBefore) { + Ops[0].init(reinterpret_cast<Value*>(IfTrue), this); + Ops[1].init(reinterpret_cast<Value*>(IfFalse), this); + Ops[2].init(Cond, this); +#ifndef NDEBUG + AssertOK(); +#endif } BranchInst(BasicBlock *IfTrue, BasicBlock *InsertAtEnd) - : TerminatorInst(Instruction::Br, InsertAtEnd) { - init(IfTrue); + : TerminatorInst(Instruction::Br, Ops, 1, InsertAtEnd) { + assert(IfTrue != 0 && "Branch destination may not be null!"); + Ops[0].init(reinterpret_cast<Value*>(IfTrue), this); } BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, BasicBlock *InsertAtEnd) - : TerminatorInst(Instruction::Br, InsertAtEnd) { - init(IfTrue, IfFalse, Cond); + : TerminatorInst(Instruction::Br, Ops, 3, InsertAtEnd) { + Ops[0].init(reinterpret_cast<Value*>(IfTrue), this); + Ops[1].init(reinterpret_cast<Value*>(IfFalse), this); + Ops[2].init(Cond, this); +#ifndef NDEBUG + AssertOK(); +#endif + } + + + /// Transparently provide more efficient getOperand methods. + Value *getOperand(unsigned i) const { + assert(i < getNumOperands() && "getOperand() out of range!"); + return Ops[i]; + } + void setOperand(unsigned i, Value *Val) { + assert(i < getNumOperands() && "setOperand() out of range!"); + Ops[i] = Val; } virtual BranchInst *clone() const; - inline bool isUnconditional() const { return Operands.size() == 1; } - inline bool isConditional() const { return Operands.size() == 3; } + inline bool isUnconditional() const { return getNumOperands() == 1; } + inline bool isConditional() const { return getNumOperands() == 3; } inline Value *getCondition() const { assert(isConditional() && "Cannot get condition of an uncond branch!"); - return Operands[2].get(); + return getOperand(2); } void setCondition(Value *V) { @@ -918,29 +993,29 @@ public: // setUnconditionalDest - Change the current branch to an unconditional branch // targeting the specified block. - // + // FIXME: Eliminate this ugly method. void setUnconditionalDest(BasicBlock *Dest) { - if (isConditional()) Operands.erase(Operands.begin()+1, Operands.end()); - Operands[0] = reinterpret_cast<Value*>(Dest); + if (isConditional()) { // Convert this to an uncond branch. + NumOperands = 1; + Ops[1].set(0); + Ops[2].set(0); + } + setOperand(0, reinterpret_cast<Value*>(Dest)); } - virtual const BasicBlock *getSuccessor(unsigned i) const { + unsigned getNumSuccessors() const { return 1+isConditional(); } + + BasicBlock *getSuccessor(unsigned i) const { assert(i < getNumSuccessors() && "Successor # out of range for Branch!"); - return (i == 0) ? cast<BasicBlock>(Operands[0].get()) : - cast<BasicBlock>(Operands[1].get()); - } - inline BasicBlock *getSuccessor(unsigned idx) { - const BranchInst *BI = this; - return const_cast<BasicBlock*>(BI->getSuccessor(idx)); + return (i == 0) ? cast<BasicBlock>(getOperand(0)) : + cast<BasicBlock>(getOperand(1)); } - virtual void setSuccessor(unsigned idx, BasicBlock *NewSucc) { + void setSuccessor(unsigned idx, BasicBlock *NewSucc) { assert(idx < getNumSuccessors() && "Successor # out of range for Branch!"); - Operands[idx] = reinterpret_cast<Value*>(NewSucc); + setOperand(idx, reinterpret_cast<Value*>(NewSucc)); } - virtual unsigned getNumSuccessors() const { return 1+isConditional(); } - // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const BranchInst *) { return true; } static inline bool classof(const Instruction *I) { @@ -949,6 +1024,10 @@ public: static inline bool classof(const Value *V) { return isa<Instruction>(V) && classof(cast<Instruction>(V)); } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); }; //===----------------------------------------------------------------------===// @@ -959,42 +1038,49 @@ public: /// SwitchInst - Multiway switch /// class SwitchInst : public TerminatorInst { + unsigned ReservedSpace; // Operand[0] = Value to switch on // Operand[1] = Default basic block destination // Operand[2n ] = Value to match // Operand[2n+1] = BasicBlock to go to on match SwitchInst(const SwitchInst &RI); - void init(Value *Value, BasicBlock *Default); - + void init(Value *Value, BasicBlock *Default, unsigned NumCases); + void resizeOperands(unsigned No); public: - SwitchInst(Value *Value, BasicBlock *Default, Instruction *InsertBefore = 0) - : TerminatorInst(Instruction::Switch, InsertBefore) { - init(Value, Default); + /// SwitchInst ctor - Create a new switch instruction, specifying a value to + /// switch on and a default destination. The number of additional cases can + /// be specified here to make memory allocation more efficient. This + /// constructor can also autoinsert before another instruction. + SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases, + Instruction *InsertBefore = 0) + : TerminatorInst(Instruction::Switch, 0, 0, InsertBefore) { + init(Value, Default, NumCases); } - SwitchInst(Value *Value, BasicBlock *Default, BasicBlock *InsertAtEnd) - : TerminatorInst(Instruction::Switch, InsertAtEnd) { - init(Value, Default); + + /// SwitchInst ctor - Create a new switch instruction, specifying a value to + /// switch on and a default destination. The number of additional cases can + /// be specified here to make memory allocation more efficient. This + /// constructor also autoinserts at the end of the specified BasicBlock. + SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases, + BasicBlock *InsertAtEnd) + : TerminatorInst(Instruction::Switch, 0, 0, InsertAtEnd) { + init(Value, Default, NumCases); } + ~SwitchInst(); - virtual SwitchInst *clone() const; // Accessor Methods for Switch stmt - // - inline const Value *getCondition() const { return Operands[0]; } - inline Value *getCondition() { return Operands[0]; } - void setCondition(Value *V) { Operands[0] = V; } + inline Value *getCondition() const { return getOperand(0); } + void setCondition(Value *V) { setOperand(0, V); } - inline const BasicBlock *getDefaultDest() const { - return cast<BasicBlock>(Operands[1].get()); - } - inline BasicBlock *getDefaultDest() { - return cast<BasicBlock>(Operands[1].get()); + inline BasicBlock *getDefaultDest() const { + return cast<BasicBlock>(getOperand(1)); } /// getNumCases - return the number of 'cases' in this switch instruction. /// Note that case #0 is always the default case. unsigned getNumCases() const { - return (unsigned)Operands.size()/2; + return getNumOperands()/2; } /// getCaseValue - Return the specified case value. Note that case #0, the @@ -1031,31 +1117,24 @@ public: /// void removeCase(unsigned idx); - virtual const BasicBlock *getSuccessor(unsigned idx) const { - assert(idx < getNumSuccessors() &&"Successor idx out of range for switch!"); - return cast<BasicBlock>(Operands[idx*2+1].get()); - } - inline BasicBlock *getSuccessor(unsigned idx) { + virtual SwitchInst *clone() const; + + unsigned getNumSuccessors() const { return getNumOperands()/2; } + BasicBlock *getSuccessor(unsigned idx) const { assert(idx < getNumSuccessors() &&"Successor idx out of range for switch!"); - return cast<BasicBlock>(Operands[idx*2+1].get()); + return cast<BasicBlock>(getOperand(idx*2+1)); } - - virtual void setSuccessor(unsigned idx, BasicBlock *NewSucc) { + void setSuccessor(unsigned idx, BasicBlock *NewSucc) { assert(idx < getNumSuccessors() && "Successor # out of range for switch!"); - Operands[idx*2+1] = reinterpret_cast<Value*>(NewSucc); + setOperand(idx*2+1, reinterpret_cast<Value*>(NewSucc)); } // getSuccessorValue - Return the value associated with the specified // successor. - inline const Constant *getSuccessorValue(unsigned idx) const { + inline Constant *getSuccessorValue(unsigned idx) const { assert(idx < getNumSuccessors() && "Successor # out of range!"); - return cast<Constant>(Operands[idx*2].get()); + return cast<Constant>(getOperand(idx*2)); } - inline Constant *getSuccessorValue(unsigned idx) { - assert(idx < getNumSuccessors() && "Successor # out of range!"); - return cast<Constant>(Operands[idx*2].get()); - } - virtual unsigned getNumSuccessors() const { return (unsigned)Operands.size()/2; } // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const SwitchInst *) { return true; } @@ -1065,6 +1144,10 @@ public: static inline bool classof(const Value *V) { return isa<Instruction>(V) && classof(cast<Instruction>(V)); } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); }; //===----------------------------------------------------------------------===// @@ -1085,6 +1168,7 @@ public: InvokeInst(Value *Fn, BasicBlock *IfNormal, BasicBlock *IfException, const std::vector<Value*> &Params, const std::string &Name, BasicBlock *InsertAtEnd); + ~InvokeInst(); virtual InvokeInst *clone() const; @@ -1094,50 +1178,38 @@ public: /// indirect function invocation. /// Function *getCalledFunction() const { - return dyn_cast<Function>(Operands[0]); + return dyn_cast<Function>(getOperand(0)); } // getCalledValue - Get a pointer to a function that is invoked by this inst. - inline const Value *getCalledValue() const { return Operands[0]; } - inline Value *getCalledValue() { return Operands[0]; } + inline Value *getCalledValue() const { return getOperand(0); } // get*Dest - Return the destination basic blocks... - inline const BasicBlock *getNormalDest() const { - return cast<BasicBlock>(Operands[1].get()); - } - inline BasicBlock *getNormalDest() { - return cast<BasicBlock>(Operands[1].get()); - } - inline const BasicBlock *getUnwindDest() const { - return cast<BasicBlock>(Operands[2].get()); + BasicBlock *getNormalDest() const { + return cast<BasicBlock>(getOperand(1)); } - inline BasicBlock *getUnwindDest() { - return cast<BasicBlock>(Operands[2].get()); + BasicBlock *getUnwindDest() const { + return cast<BasicBlock>(getOperand(2)); } - - inline void setNormalDest(BasicBlock *B){ - Operands[1] = reinterpret_cast<Value*>(B); + void setNormalDest(BasicBlock *B) { + setOperand(1, reinterpret_cast<Value*>(B)); } - inline void setUnwindDest(BasicBlock *B){ - Operands[2] = reinterpret_cast<Value*>(B); + void setUnwindDest(BasicBlock *B) { + setOperand(2, reinterpret_cast<Value*>(B)); } - virtual const BasicBlock *getSuccessor(unsigned i) const { - assert(i < 2 && "Successor # out of range for invoke!"); - return i == 0 ? getNormalDest() : getUnwindDest(); - } - inline BasicBlock *getSuccessor(unsigned i) { + inline BasicBlock *getSuccessor(unsigned i) const { assert(i < 2 && "Successor # out of range for invoke!"); return i == 0 ? getNormalDest() : getUnwindDest(); } - virtual void setSuccessor(unsigned idx, BasicBlock *NewSucc) { + void setSuccessor(unsigned idx, BasicBlock *NewSucc) { assert(idx < 2 && "Successor # out of range for invoke!"); - Operands[idx+1] = reinterpret_cast<Value*>(NewSucc); + setOperand(idx+1, reinterpret_cast<Value*>(NewSucc)); } - virtual unsigned getNumSuccessors() const { return 2; } + unsigned getNumSuccessors() const { return 2; } // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const InvokeInst *) { return true; } @@ -1147,6 +1219,10 @@ public: static inline bool classof(const Value *V) { return isa<Instruction>(V) && classof(cast<Instruction>(V)); } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); }; @@ -1161,21 +1237,15 @@ public: class UnwindInst : public TerminatorInst { public: UnwindInst(Instruction *InsertBefore = 0) - : TerminatorInst(Instruction::Unwind, InsertBefore) { + : TerminatorInst(Instruction::Unwind, 0, 0, InsertBefore) { } UnwindInst(BasicBlock *InsertAtEnd) - : TerminatorInst(Instruction::Unwind, InsertAtEnd) { + : TerminatorInst(Instruction::Unwind, 0, 0, InsertAtEnd) { } virtual UnwindInst *clone() const; - virtual const BasicBlock *getSuccessor(unsigned idx) const { - assert(0 && "UnwindInst has no successors!"); - abort(); - return 0; - } - virtual void setSuccessor(unsigned idx, BasicBlock *NewSucc); - virtual unsigned getNumSuccessors() const { return 0; } + unsigned getNumSuccessors() const { return 0; } // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const UnwindInst *) { return true; } @@ -1185,6 +1255,10 @@ public: static inline bool classof(const Value *V) { return isa<Instruction>(V) && classof(cast<Instruction>(V)); } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); }; //===----------------------------------------------------------------------===// @@ -1199,21 +1273,15 @@ public: class UnreachableInst : public TerminatorInst { public: UnreachableInst(Instruction *InsertBefore = 0) - : TerminatorInst(Instruction::Unreachable, InsertBefore) { + : TerminatorInst(Instruction::Unreachable, 0, 0, InsertBefore) { } UnreachableInst(BasicBlock *InsertAtEnd) - : TerminatorInst(Instruction::Unreachable, InsertAtEnd) { + : TerminatorInst(Instruction::Unreachable, 0, 0, InsertAtEnd) { } virtual UnreachableInst *clone() const; - virtual const BasicBlock *getSuccessor(unsigned idx) const { - assert(0 && "UnreachableInst has no successors!"); - abort(); - return 0; - } - virtual void setSuccessor(unsigned idx, BasicBlock *NewSucc); - virtual unsigned getNumSuccessors() const { return 0; } + unsigned getNumSuccessors() const { return 0; } // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const UnreachableInst *) { return true; } @@ -1223,6 +1291,10 @@ public: static inline bool classof(const Value *V) { return isa<Instruction>(V) |