X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FInstructions.cpp;h=800eb9cd1d866850315993ded9d946c57f5c26b6;hb=b83eb6447ba155342598f0fabe1f08f5baa9164a;hp=205f32b4605a128aaed06a062a50e216f2b739ff;hpb=8fabb621b15a5338304bc87b056d1e2048087c3e;p=oota-llvm.git diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index 205f32b4605..800eb9cd1d8 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -1,13 +1,14 @@ //===-- Instructions.cpp - Implement the LLVM instructions ----------------===// -// +// // The LLVM Compiler Infrastructure // // This file was developed by the LLVM research group and is distributed under // the University of Illinois Open Source License. See LICENSE.TXT for details. -// +// //===----------------------------------------------------------------------===// // -// This file implements the LLVM instructions... +// This file implements all of the non-inline methods for the LLVM instruction +// classes. // //===----------------------------------------------------------------------===// @@ -19,78 +20,263 @@ #include "llvm/Support/CallSite.h" using namespace llvm; +unsigned CallSite::getCallingConv() const { + if (CallInst *CI = dyn_cast(I)) + return CI->getCallingConv(); + else + return cast(I)->getCallingConv(); +} +void CallSite::setCallingConv(unsigned CC) { + if (CallInst *CI = dyn_cast(I)) + CI->setCallingConv(CC); + else + cast(I)->setCallingConv(CC); +} + + + + +//===----------------------------------------------------------------------===// +// TerminatorInst Class +//===----------------------------------------------------------------------===// + +TerminatorInst::TerminatorInst(Instruction::TermOps iType, + Use *Ops, unsigned NumOps, Instruction *IB) + : Instruction(Type::VoidTy, iType, Ops, NumOps, "", IB) { +} + +TerminatorInst::TerminatorInst(Instruction::TermOps iType, + Use *Ops, unsigned NumOps, BasicBlock *IAE) + : Instruction(Type::VoidTy, iType, Ops, NumOps, "", IAE) { +} + +// Out of line virtual method, so the vtable, etc has a home. +TerminatorInst::~TerminatorInst() { +} + +// Out of line virtual method, so the vtable, etc has a home. +UnaryInstruction::~UnaryInstruction() { +} + + +//===----------------------------------------------------------------------===// +// PHINode Class +//===----------------------------------------------------------------------===// + +PHINode::PHINode(const PHINode &PN) + : Instruction(PN.getType(), Instruction::PHI, + new Use[PN.getNumOperands()], PN.getNumOperands()), + ReservedSpace(PN.getNumOperands()) { + Use *OL = OperandList; + for (unsigned i = 0, e = PN.getNumOperands(); i != e; i+=2) { + OL[i].init(PN.getOperand(i), this); + OL[i+1].init(PN.getOperand(i+1), this); + } +} + +PHINode::~PHINode() { + delete [] OperandList; +} + +// removeIncomingValue - Remove an incoming value. This is useful if a +// predecessor basic block is deleted. +Value *PHINode::removeIncomingValue(unsigned Idx, bool DeletePHIIfEmpty) { + unsigned NumOps = getNumOperands(); + Use *OL = OperandList; + assert(Idx*2 < NumOps && "BB not in PHI node!"); + Value *Removed = OL[Idx*2]; + + // Move everything after this operand down. + // + // FIXME: we could just swap with the end of the list, then erase. However, + // client might not expect this to happen. The code as it is thrashes the + // use/def lists, which is kinda lame. + for (unsigned i = (Idx+1)*2; i != NumOps; i += 2) { + OL[i-2] = OL[i]; + OL[i-2+1] = OL[i+1]; + } + + // Nuke the last value. + OL[NumOps-2].set(0); + OL[NumOps-2+1].set(0); + NumOperands = NumOps-2; + + // If the PHI node is dead, because it has zero entries, nuke it now. + if (NumOps == 2 && DeletePHIIfEmpty) { + // If anyone is using this PHI, make them use a dummy value instead... + replaceAllUsesWith(UndefValue::get(getType())); + eraseFromParent(); + } + return Removed; +} + +/// resizeOperands - resize operands - This adjusts the length of the operands +/// list according to the following behavior: +/// 1. If NumOps == 0, grow the operand list in response to a push_back style +/// of operation. This grows the number of ops by 1.5 times. +/// 2. If NumOps > NumOperands, reserve space for NumOps operands. +/// 3. If NumOps == NumOperands, trim the reserved space. +/// +void PHINode::resizeOperands(unsigned NumOps) { + if (NumOps == 0) { + NumOps = (getNumOperands())*3/2; + if (NumOps < 4) NumOps = 4; // 4 op PHI nodes are VERY common. + } else if (NumOps*2 > NumOperands) { + // No resize needed. + if (ReservedSpace >= NumOps) return; + } else if (NumOps == NumOperands) { + if (ReservedSpace == NumOps) return; + } else { + return; + } + + ReservedSpace = NumOps; + Use *NewOps = new Use[NumOps]; + Use *OldOps = OperandList; + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + NewOps[i].init(OldOps[i], this); + OldOps[i].set(0); + } + delete [] OldOps; + OperandList = NewOps; +} + +/// hasConstantValue - If the specified PHI node always merges together the same +/// value, return the value, otherwise return null. +/// +Value *PHINode::hasConstantValue(bool AllowNonDominatingInstruction) const { + // If the PHI node only has one incoming value, eliminate the PHI node... + if (getNumIncomingValues() == 1) + if (getIncomingValue(0) != this) // not X = phi X + return getIncomingValue(0); + else + return UndefValue::get(getType()); // Self cycle is dead. + + // Otherwise if all of the incoming values are the same for the PHI, replace + // the PHI node with the incoming value. + // + Value *InVal = 0; + bool HasUndefInput = false; + for (unsigned i = 0, e = getNumIncomingValues(); i != e; ++i) + if (isa(getIncomingValue(i))) + HasUndefInput = true; + else if (getIncomingValue(i) != this) // Not the PHI node itself... + if (InVal && getIncomingValue(i) != InVal) + return 0; // Not the same, bail out. + else + InVal = getIncomingValue(i); + + // The only case that could cause InVal to be null is if we have a PHI node + // that only has entries for itself. In this case, there is no entry into the + // loop, so kill the PHI. + // + if (InVal == 0) InVal = UndefValue::get(getType()); + + // If we have a PHI node like phi(X, undef, X), where X is defined by some + // instruction, we cannot always return X as the result of the PHI node. Only + // do this if X is not an instruction (thus it must dominate the PHI block), + // or if the client is prepared to deal with this possibility. + if (HasUndefInput && !AllowNonDominatingInstruction) + if (Instruction *IV = dyn_cast(InVal)) + // If it's in the entry block, it dominates everything. + if (IV->getParent() != &IV->getParent()->getParent()->front() || + isa(IV)) + return 0; // Cannot guarantee that InVal dominates this PHINode. + + // All of the incoming values are the same, return the value now. + return InVal; +} + + //===----------------------------------------------------------------------===// // CallInst Implementation //===----------------------------------------------------------------------===// -void CallInst::init(Value *Func, const std::vector &Params) -{ - Operands.reserve(1+Params.size()); - Operands.push_back(Use(Func, this)); +CallInst::~CallInst() { + delete [] OperandList; +} - const FunctionType *FTy = +void CallInst::init(Value *Func, const std::vector &Params) { + NumOperands = Params.size()+1; + Use *OL = OperandList = new Use[Params.size()+1]; + OL[0].init(Func, this); + + const FunctionType *FTy = cast(cast(Func->getType())->getElementType()); - assert((Params.size() == FTy->getNumParams() || + assert((Params.size() == FTy->getNumParams() || (FTy->isVarArg() && Params.size() > FTy->getNumParams())) && - "Calling a function with bad signature"); - for (unsigned i = 0; i != Params.size(); i++) - Operands.push_back(Use(Params[i], this)); + "Calling a function with bad signature!"); + for (unsigned i = 0, e = Params.size(); i != e; ++i) { + assert((i >= FTy->getNumParams() || + FTy->getParamType(i) == Params[i]->getType()) && + "Calling a function with a bad signature!"); + OL[i+1].init(Params[i], this); + } } -void CallInst::init(Value *Func, Value *Actual1, Value *Actual2) -{ - Operands.reserve(3); - Operands.push_back(Use(Func, this)); - - const FunctionType *MTy = +void CallInst::init(Value *Func, Value *Actual1, Value *Actual2) { + NumOperands = 3; + Use *OL = OperandList = new Use[3]; + OL[0].init(Func, this); + OL[1].init(Actual1, this); + OL[2].init(Actual2, this); + + const FunctionType *FTy = cast(cast(Func->getType())->getElementType()); - assert((MTy->getNumParams() == 2 || - (MTy->isVarArg() && MTy->getNumParams() == 0)) && + assert((FTy->getNumParams() == 2 || + (FTy->isVarArg() && FTy->getNumParams() < 2)) && "Calling a function with bad signature"); - Operands.push_back(Use(Actual1, this)); - Operands.push_back(Use(Actual2, this)); + assert((0 >= FTy->getNumParams() || + FTy->getParamType(0) == Actual1->getType()) && + "Calling a function with a bad signature!"); + assert((1 >= FTy->getNumParams() || + FTy->getParamType(1) == Actual2->getType()) && + "Calling a function with a bad signature!"); } -void CallInst::init(Value *Func, Value *Actual) -{ - Operands.reserve(2); - Operands.push_back(Use(Func, this)); - - const FunctionType *MTy = +void CallInst::init(Value *Func, Value *Actual) { + NumOperands = 2; + Use *OL = OperandList = new Use[2]; + OL[0].init(Func, this); + OL[1].init(Actual, this); + + const FunctionType *FTy = cast(cast(Func->getType())->getElementType()); - assert((MTy->getNumParams() == 1 || - (MTy->isVarArg() && MTy->getNumParams() == 0)) && + assert((FTy->getNumParams() == 1 || + (FTy->isVarArg() && FTy->getNumParams() == 0)) && "Calling a function with bad signature"); - Operands.push_back(Use(Actual, this)); + assert((0 == FTy->getNumParams() || + FTy->getParamType(0) == Actual->getType()) && + "Calling a function with a bad signature!"); } -void CallInst::init(Value *Func) -{ - Operands.reserve(1); - Operands.push_back(Use(Func, this)); - - const FunctionType *MTy = +void CallInst::init(Value *Func) { + NumOperands = 1; + Use *OL = OperandList = new Use[1]; + OL[0].init(Func, this); + + const FunctionType *MTy = cast(cast(Func->getType())->getElementType()); assert(MTy->getNumParams() == 0 && "Calling a function with bad signature"); } -CallInst::CallInst(Value *Func, const std::vector &Params, - const std::string &Name, Instruction *InsertBefore) +CallInst::CallInst(Value *Func, const std::vector &Params, + const std::string &Name, Instruction *InsertBefore) : Instruction(cast(cast(Func->getType()) ->getElementType())->getReturnType(), - Instruction::Call, Name, InsertBefore) { + Instruction::Call, 0, 0, Name, InsertBefore) { init(Func, Params); } -CallInst::CallInst(Value *Func, const std::vector &Params, - const std::string &Name, BasicBlock *InsertAtEnd) +CallInst::CallInst(Value *Func, const std::vector &Params, + const std::string &Name, BasicBlock *InsertAtEnd) : Instruction(cast(cast(Func->getType()) ->getElementType())->getReturnType(), - Instruction::Call, Name, InsertAtEnd) { + Instruction::Call, 0, 0, Name, InsertAtEnd) { init(Func, Params); } @@ -98,7 +284,7 @@ CallInst::CallInst(Value *Func, Value *Actual1, Value *Actual2, const std::string &Name, Instruction *InsertBefore) : Instruction(cast(cast(Func->getType()) ->getElementType())->getReturnType(), - Instruction::Call, Name, InsertBefore) { + Instruction::Call, 0, 0, Name, InsertBefore) { init(Func, Actual1, Actual2); } @@ -106,7 +292,7 @@ CallInst::CallInst(Value *Func, Value *Actual1, Value *Actual2, const std::string &Name, BasicBlock *InsertAtEnd) : Instruction(cast(cast(Func->getType()) ->getElementType())->getReturnType(), - Instruction::Call, Name, InsertAtEnd) { + Instruction::Call, 0, 0, Name, InsertAtEnd) { init(Func, Actual1, Actual2); } @@ -114,7 +300,7 @@ CallInst::CallInst(Value *Func, Value* Actual, const std::string &Name, Instruction *InsertBefore) : Instruction(cast(cast(Func->getType()) ->getElementType())->getReturnType(), - Instruction::Call, Name, InsertBefore) { + Instruction::Call, 0, 0, Name, InsertBefore) { init(Func, Actual); } @@ -122,7 +308,7 @@ CallInst::CallInst(Value *Func, Value* Actual, const std::string &Name, BasicBlock *InsertAtEnd) : Instruction(cast(cast(Func->getType()) ->getElementType())->getReturnType(), - Instruction::Call, Name, InsertAtEnd) { + Instruction::Call, 0, 0, Name, InsertAtEnd) { init(Func, Actual); } @@ -130,7 +316,7 @@ CallInst::CallInst(Value *Func, const std::string &Name, Instruction *InsertBefore) : Instruction(cast(cast(Func->getType()) ->getElementType())->getReturnType(), - Instruction::Call, Name, InsertBefore) { + Instruction::Call, 0, 0, Name, InsertBefore) { init(Func); } @@ -138,26 +324,18 @@ CallInst::CallInst(Value *Func, const std::string &Name, BasicBlock *InsertAtEnd) : Instruction(cast(cast(Func->getType()) ->getElementType())->getReturnType(), - Instruction::Call, Name, InsertAtEnd) { + Instruction::Call, 0, 0, Name, InsertAtEnd) { init(Func); } -CallInst::CallInst(const CallInst &CI) - : Instruction(CI.getType(), Instruction::Call) { - Operands.reserve(CI.Operands.size()); - for (unsigned i = 0; i < CI.Operands.size(); ++i) - Operands.push_back(Use(CI.Operands[i], this)); -} - -const Function *CallInst::getCalledFunction() const { - if (const Function *F = dyn_cast(Operands[0])) - return F; - return 0; -} -Function *CallInst::getCalledFunction() { - if (Function *F = dyn_cast(Operands[0])) - return F; - return 0; +CallInst::CallInst(const CallInst &CI) + : Instruction(CI.getType(), Instruction::Call, new Use[CI.getNumOperands()], + CI.getNumOperands()) { + SubclassData = CI.SubclassData; + Use *OL = OperandList; + Use *InOL = CI.OperandList; + for (unsigned i = 0, e = CI.getNumOperands(); i != e; ++i) + OL[i].init(InOL[i], this); } @@ -165,22 +343,31 @@ Function *CallInst::getCalledFunction() { // InvokeInst Implementation //===----------------------------------------------------------------------===// +InvokeInst::~InvokeInst() { + delete [] OperandList; +} + void InvokeInst::init(Value *Fn, BasicBlock *IfNormal, BasicBlock *IfException, - const std::vector &Params) -{ - Operands.reserve(3+Params.size()); - Operands.push_back(Use(Fn, this)); - Operands.push_back(Use((Value*)IfNormal, this)); - Operands.push_back(Use((Value*)IfException, this)); - const FunctionType *MTy = + const std::vector &Params) { + NumOperands = 3+Params.size(); + Use *OL = OperandList = new Use[3+Params.size()]; + OL[0].init(Fn, this); + OL[1].init(IfNormal, this); + OL[2].init(IfException, this); + const FunctionType *FTy = cast(cast(Fn->getType())->getElementType()); - - assert((Params.size() == MTy->getNumParams()) || - (MTy->isVarArg() && Params.size() > MTy->getNumParams()) && + + assert((Params.size() == FTy->getNumParams()) || + (FTy->isVarArg() && Params.size() > FTy->getNumParams()) && "Calling a function with bad signature"); - - for (unsigned i = 0; i < Params.size(); i++) - Operands.push_back(Use(Params[i], this)); + + for (unsigned i = 0, e = Params.size(); i != e; i++) { + assert((i >= FTy->getNumParams() || + FTy->getParamType(i) == Params[i]->getType()) && + "Invoking a function with a bad signature!"); + + OL[i+3].init(Params[i], this); + } } InvokeInst::InvokeInst(Value *Fn, BasicBlock *IfNormal, @@ -189,7 +376,7 @@ InvokeInst::InvokeInst(Value *Fn, BasicBlock *IfNormal, const std::string &Name, Instruction *InsertBefore) : TerminatorInst(cast(cast(Fn->getType()) ->getElementType())->getReturnType(), - Instruction::Invoke, Name, InsertBefore) { + Instruction::Invoke, 0, 0, Name, InsertBefore) { init(Fn, IfNormal, IfException, Params); } @@ -199,120 +386,169 @@ InvokeInst::InvokeInst(Value *Fn, BasicBlock *IfNormal, const std::string &Name, BasicBlock *InsertAtEnd) : TerminatorInst(cast(cast(Fn->getType()) ->getElementType())->getReturnType(), - Instruction::Invoke, Name, InsertAtEnd) { + Instruction::Invoke, 0, 0, Name, InsertAtEnd) { init(Fn, IfNormal, IfException, Params); } -InvokeInst::InvokeInst(const InvokeInst &CI) - : TerminatorInst(CI.getType(), Instruction::Invoke) { - Operands.reserve(CI.Operands.size()); - for (unsigned i = 0; i < CI.Operands.size(); ++i) - Operands.push_back(Use(CI.Operands[i], this)); +InvokeInst::InvokeInst(const InvokeInst &II) + : TerminatorInst(II.getType(), Instruction::Invoke, + new Use[II.getNumOperands()], II.getNumOperands()) { + SubclassData = II.SubclassData; + Use *OL = OperandList, *InOL = II.OperandList; + for (unsigned i = 0, e = II.getNumOperands(); i != e; ++i) + OL[i].init(InOL[i], this); } -const Function *InvokeInst::getCalledFunction() const { - if (const Function *F = dyn_cast(Operands[0])) - return F; - return 0; +BasicBlock *InvokeInst::getSuccessorV(unsigned idx) const { + return getSuccessor(idx); } -Function *InvokeInst::getCalledFunction() { - if (Function *F = dyn_cast(Operands[0])) - return F; - return 0; +unsigned InvokeInst::getNumSuccessorsV() const { + return getNumSuccessors(); } - -// FIXME: Is this supposed to be here? -Function *CallSite::getCalledFunction() const { - Value *Callee = getCalledValue(); - if (Function *F = dyn_cast(Callee)) - return F; - return 0; +void InvokeInst::setSuccessorV(unsigned idx, BasicBlock *B) { + return setSuccessor(idx, B); } + //===----------------------------------------------------------------------===// // ReturnInst Implementation //===----------------------------------------------------------------------===// +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); + } +} + +unsigned ReturnInst::getNumSuccessorsV() const { + return getNumSuccessors(); +} + // Out-of-line ReturnInst method, put here so the C++ compiler can choose to // emit the vtable for the class in this translation unit. -void ReturnInst::setSuccessor(unsigned idx, BasicBlock *NewSucc) { +void ReturnInst::setSuccessorV(unsigned idx, BasicBlock *NewSucc) { + assert(0 && "ReturnInst has no successors!"); +} + +BasicBlock *ReturnInst::getSuccessorV(unsigned idx) const { assert(0 && "ReturnInst has no successors!"); + abort(); + return 0; } + //===----------------------------------------------------------------------===// // UnwindInst Implementation //===----------------------------------------------------------------------===// -// Likewise for UnwindInst -void UnwindInst::setSuccessor(unsigned idx, BasicBlock *NewSucc) { +unsigned UnwindInst::getNumSuccessorsV() const { + return getNumSuccessors(); +} + +void UnwindInst::setSuccessorV(unsigned idx, BasicBlock *NewSucc) { assert(0 && "UnwindInst has no successors!"); } +BasicBlock *UnwindInst::getSuccessorV(unsigned idx) const { + assert(0 && "UnwindInst has no successors!"); + abort(); + return 0; +} + +//===----------------------------------------------------------------------===// +// UnreachableInst Implementation +//===----------------------------------------------------------------------===// + +unsigned UnreachableInst::getNumSuccessorsV() const { + return getNumSuccessors(); +} + +void UnreachableInst::setSuccessorV(unsigned idx, BasicBlock *NewSucc) { + assert(0 && "UnwindInst has no successors!"); +} + +BasicBlock *UnreachableInst::getSuccessorV(unsigned idx) const { + assert(0 && "UnwindInst has no successors!"); + abort(); + return 0; +} + //===----------------------------------------------------------------------===// // BranchInst Implementation //===----------------------------------------------------------------------===// -void BranchInst::init(BasicBlock *IfTrue) -{ - assert(IfTrue != 0 && "Branch destination may not be null!"); - Operands.reserve(1); - Operands.push_back(Use(IfTrue, this)); +void BranchInst::AssertOK() { + if (isConditional()) + assert(getCondition()->getType() == Type::BoolTy && + "May only branch on boolean predicates!"); } -void BranchInst::init(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond) -{ - assert(IfTrue && IfFalse && Cond && - "Branch destinations and condition may not be null!"); - assert(Cond && Cond->getType() == Type::BoolTy && - "May only branch on boolean predicates!"); - Operands.reserve(3); - Operands.push_back(Use(IfTrue, this)); - Operands.push_back(Use(IfFalse, this)); - Operands.push_back(Use(Cond, this)); -} - -BranchInst::BranchInst(const BranchInst &BI) : TerminatorInst(Instruction::Br) { - Operands.reserve(BI.Operands.size()); - Operands.push_back(Use(BI.Operands[0], this)); - if (BI.Operands.size() != 1) { - assert(BI.Operands.size() == 3 && "BR can have 1 or 3 operands!"); - Operands.push_back(Use(BI.Operands[1], this)); - Operands.push_back(Use(BI.Operands[2], this)); +BranchInst::BranchInst(const BranchInst &BI) : + TerminatorInst(Instruction::Br, Ops, BI.getNumOperands()) { + OperandList[0].init(BI.getOperand(0), this); + if (BI.getNumOperands() != 1) { + assert(BI.getNumOperands() == 3 && "BR can have 1 or 3 operands!"); + OperandList[1].init(BI.getOperand(1), this); + OperandList[2].init(BI.getOperand(2), this); } } +BasicBlock *BranchInst::getSuccessorV(unsigned idx) const { + return getSuccessor(idx); +} +unsigned BranchInst::getNumSuccessorsV() const { + return getNumSuccessors(); +} +void BranchInst::setSuccessorV(unsigned idx, BasicBlock *B) { + setSuccessor(idx, B); +} + + //===----------------------------------------------------------------------===// // AllocationInst Implementation //===----------------------------------------------------------------------===// -void AllocationInst::init(const Type *Ty, Value *ArraySize, unsigned iTy) { - assert(Ty != Type::VoidTy && "Cannot allocate void elements!"); - // ArraySize defaults to 1. - if (!ArraySize) ArraySize = ConstantUInt::get(Type::UIntTy, 1); - - Operands.reserve(1); - assert(ArraySize->getType() == Type::UIntTy && - "Malloc/Allocation array size != UIntTy!"); - - Operands.push_back(Use(ArraySize, this)); +static Value *getAISize(Value *Amt) { + if (!Amt) + Amt = ConstantInt::get(Type::UIntTy, 1); + else { + assert(!isa(Amt) && + "Passed basic block into allocation size parameter! Ue other ctor"); + assert(Amt->getType() == Type::UIntTy && + "Malloc/Allocation array size != UIntTy!"); + } + return Amt; } -AllocationInst::AllocationInst(const Type *Ty, Value *ArraySize, unsigned iTy, - const std::string &Name, +AllocationInst::AllocationInst(const Type *Ty, Value *ArraySize, unsigned iTy, + unsigned Align, const std::string &Name, Instruction *InsertBefore) - : Instruction(PointerType::get(Ty), iTy, Name, InsertBefore) { - init(Ty, ArraySize, iTy); + : UnaryInstruction(PointerType::get(Ty), iTy, getAISize(ArraySize), + Name, InsertBefore), Alignment(Align) { + assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!"); + assert(Ty != Type::VoidTy && "Cannot allocate void!"); } -AllocationInst::AllocationInst(const Type *Ty, Value *ArraySize, unsigned iTy, - const std::string &Name, +AllocationInst::AllocationInst(const Type *Ty, Value *ArraySize, unsigned iTy, + unsigned Align, const std::string &Name, BasicBlock *InsertAtEnd) - : Instruction(PointerType::get(Ty), iTy, Name, InsertAtEnd) { - init(Ty, ArraySize, iTy); + : UnaryInstruction(PointerType::get(Ty), iTy, getAISize(ArraySize), + Name, InsertAtEnd), Alignment(Align) { + assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!"); + assert(Ty != Type::VoidTy && "Cannot allocate void!"); +} + +// Out of line virtual method, so the vtable, etc has a home. +AllocationInst::~AllocationInst() { } bool AllocationInst::isArrayAllocation() const { - return getOperand(0) != ConstantUInt::get(Type::UIntTy, 1); + if (ConstantInt *CUI = dyn_cast(getOperand(0))) + return CUI->getZExtValue() != 1; + return true; } const Type *AllocationInst::getAllocatedType() const { @@ -321,33 +557,31 @@ const Type *AllocationInst::getAllocatedType() const { AllocaInst::AllocaInst(const AllocaInst &AI) : AllocationInst(AI.getType()->getElementType(), (Value*)AI.getOperand(0), - Instruction::Alloca) { + Instruction::Alloca, AI.getAlignment()) { } MallocInst::MallocInst(const MallocInst &MI) : AllocationInst(MI.getType()->getElementType(), (Value*)MI.getOperand(0), - Instruction::Malloc) { + Instruction::Malloc, MI.getAlignment()) { } //===----------------------------------------------------------------------===// // FreeInst Implementation //===----------------------------------------------------------------------===// -void FreeInst::init(Value *Ptr) -{ - assert(Ptr && isa(Ptr->getType()) && "Can't free nonpointer!"); - Operands.reserve(1); - Operands.push_back(Use(Ptr, this)); +void FreeInst::AssertOK() { + assert(isa(getOperand(0)->getType()) && + "Can not free something of nonpointer type!"); } FreeInst::FreeInst(Value *Ptr, Instruction *InsertBefore) - : Instruction(Type::VoidTy, Free, "", InsertBefore) { - init(Ptr); + : UnaryInstruction(Type::VoidTy, Free, Ptr, "", InsertBefore) { + AssertOK(); } FreeInst::FreeInst(Value *Ptr, BasicBlock *InsertAtEnd) - : Instruction(Type::VoidTy, Free, "", InsertAtEnd) { - init(Ptr); + : UnaryInstruction(Type::VoidTy, Free, Ptr, "", InsertAtEnd) { + AssertOK(); } @@ -355,37 +589,39 @@ FreeInst::FreeInst(Value *Ptr, BasicBlock *InsertAtEnd) // LoadInst Implementation //===----------------------------------------------------------------------===// -void LoadInst::init(Value *Ptr) { - assert(Ptr && isa(Ptr->getType()) && +void LoadInst::AssertOK() { + assert(isa(getOperand(0)->getType()) && "Ptr must have pointer type."); - Operands.reserve(1); - Operands.push_back(Use(Ptr, this)); } LoadInst::LoadInst(Value *Ptr, const std::string &Name, Instruction *InsertBef) - : Instruction(cast(Ptr->getType())->getElementType(), - Load, Name, InsertBef), Volatile(false) { - init(Ptr); + : UnaryInstruction(cast(Ptr->getType())->getElementType(), + Load, Ptr, Name, InsertBef) { + setVolatile(false); + AssertOK(); } LoadInst::LoadInst(Value *Ptr, const std::string &Name, BasicBlock *InsertAE) - : Instruction(cast(Ptr->getType())->getElementType(), - Load, Name, InsertAE), Volatile(false) { - init(Ptr); + : UnaryInstruction(cast(Ptr->getType())->getElementType(), + Load, Ptr, Name, InsertAE) { + setVolatile(false); + AssertOK(); } LoadInst::LoadInst(Value *Ptr, const std::string &Name, bool isVolatile, Instruction *InsertBef) - : Instruction(cast(Ptr->getType())->getElementType(), - Load, Name, InsertBef), Volatile(isVolatile) { - init(Ptr); + : UnaryInstruction(cast(Ptr->getType())->getElementType(), + Load, Ptr, Name, InsertBef) { + setVolatile(isVolatile); + AssertOK(); } LoadInst::LoadInst(Value *Ptr, const std::string &Name, bool isVolatile, BasicBlock *InsertAE) - : Instruction(cast(Ptr->getType())->getElementType(), - Load, Name, InsertAE), Volatile(isVolatile) { - init(Ptr); + : UnaryInstruction(cast(Ptr->getType())->getElementType(), + Load, Ptr, Name, InsertAE) { + setVolatile(isVolatile); + AssertOK(); } @@ -393,36 +629,47 @@ LoadInst::LoadInst(Value *Ptr, const std::string &Name, bool isVolatile, // StoreInst Implementation //===----------------------------------------------------------------------===// -StoreInst::StoreInst(Value *Val, Value *Ptr, Instruction *InsertBefore) - : Instruction(Type::VoidTy, Store, "", InsertBefore), Volatile(false) { - init(Val, Ptr); +void StoreInst::AssertOK() { + assert(isa(getOperand(1)->getType()) && + "Ptr must have pointer type!"); + assert(getOperand(0)->getType() == + cast(getOperand(1)->getType())->getElementType() + && "Ptr must be a pointer to Val type!"); } -StoreInst::StoreInst(Value *Val, Value *Ptr, BasicBlock *InsertAtEnd) - : Instruction(Type::VoidTy, Store, "", InsertAtEnd), Volatile(false) { - init(Val, Ptr); -} -StoreInst::StoreInst(Value *Val, Value *Ptr, bool isVolatile, - Instruction *InsertBefore) - : Instruction(Type::VoidTy, Store, "", InsertBefore), Volatile(isVolatile) { - init(Val, Ptr); +StoreInst::StoreInst(Value *val, Value *addr, Instruction *InsertBefore) + : Instruction(Type::VoidTy, Store, Ops, 2, "", InsertBefore) { + Ops[0].init(val, this); + Ops[1].init(addr, this); + setVolatile(false); + AssertOK(); } -StoreInst::StoreInst(Value *Val, Value *Ptr, bool isVolatile, - BasicBlock *InsertAtEnd) - : Instruction(Type::VoidTy, Store, "", InsertAtEnd), Volatile(isVolatile) { - init(Val, Ptr); +StoreInst::StoreInst(Value *val, Value *addr, BasicBlock *InsertAtEnd) + : Instruction(Type::VoidTy, Store, Ops, 2, "", InsertAtEnd) { + Ops[0].init(val, this); + Ops[1].init(addr, this); + setVolatile(false); + AssertOK(); } -void StoreInst::init(Value *Val, Value *Ptr) { - assert(isa(Ptr->getType()) && "Ptr must have pointer type!"); - assert(Val->getType() == cast(Ptr->getType())->getElementType() - && "Ptr must be a pointer to Val type!"); +StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile, + Instruction *InsertBefore) + : Instruction(Type::VoidTy, Store, Ops, 2, "", InsertBefore) { + Ops[0].init(val, this); + Ops[1].init(addr, this); + setVolatile(isVolatile); + AssertOK(); +} - Operands.reserve(2); - Operands.push_back(Use(Val, this)); - Operands.push_back(Use(Ptr, this)); +StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile, + BasicBlock *InsertAtEnd) + : Instruction(Type::VoidTy, Store, Ops, 2, "", InsertAtEnd) { + Ops[0].init(val, this); + Ops[1].init(addr, this); + setVolatile(isVolatile); + AssertOK(); } //===----------------------------------------------------------------------===// @@ -433,39 +680,61 @@ void StoreInst::init(Value *Val, Value *Ptr) { // message on bad indexes for a gep instruction. // static inline const Type *checkType(const Type *Ty) { - assert(Ty && "Invalid indices for type!"); + assert(Ty && "Invalid GetElementPtrInst indices for type!"); return Ty; } -void GetElementPtrInst::init(Value *Ptr, const std::vector &Idx) -{ - Operands.reserve(1+Idx.size()); - Operands.push_back(Use(Ptr, this)); +void GetElementPtrInst::init(Value *Ptr, const std::vector &Idx) { + NumOperands = 1+Idx.size(); + Use *OL = OperandList = new Use[NumOperands]; + OL[0].init(Ptr, this); - for (unsigned i = 0, E = Idx.size(); i != E; ++i) - Operands.push_back(Use(Idx[i], this)); + for (unsigned i = 0, e = Idx.size(); i != e; ++i) + OL[i+1].init(Idx[i], this); } void GetElementPtrInst::init(Value *Ptr, Value *Idx0, Value *Idx1) { - Operands.reserve(3); - Operands.push_back(Use(Ptr, this)); - Operands.push_back(Use(Idx0, this)); - Operands.push_back(Use(Idx1, this)); + NumOperands = 3; + Use *OL = OperandList = new Use[3]; + OL[0].init(Ptr, this); + OL[1].init(Idx0, this); + OL[2].init(Idx1, this); +} + +void GetElementPtrInst::init(Value *Ptr, Value *Idx) { + NumOperands = 2; + Use *OL = OperandList = new Use[2]; + OL[0].init(Ptr, this); + OL[1].init(Idx, this); } GetElementPtrInst::GetElementPtrInst(Value *Ptr, const std::vector &Idx, - const std::string &Name, Instruction *InBe) + const std::string &Name, Instruction *InBe) : Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(), Idx, true))), - GetElementPtr, Name, InBe) { + GetElementPtr, 0, 0, Name, InBe) { init(Ptr, Idx); } GetElementPtrInst::GetElementPtrInst(Value *Ptr, const std::vector &Idx, - const std::string &Name, BasicBlock *IAE) + const std::string &Name, BasicBlock *IAE) : Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(), Idx, true))), - GetElementPtr, Name, IAE) { + GetElementPtr, 0, 0, Name, IAE) { + init(Ptr, Idx); +} + +GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx, + const std::string &Name, Instruction *InBe) + : Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(),Idx))), + GetElementPtr, 0, 0, Name, InBe) { + init(Ptr, Idx); +} + +GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx, + const std::string &Name, BasicBlock *IAE) + : Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(),Idx))), + GetElementPtr, 0, 0, Name, IAE) { init(Ptr, Idx); } @@ -473,25 +742,29 @@ GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx0, Value *Idx1, const std::string &Name, Instruction *InBe) : Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(), Idx0, Idx1, true))), - GetElementPtr, Name, InBe) { + GetElementPtr, 0, 0, Name, InBe) { init(Ptr, Idx0, Idx1); } GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx0, Value *Idx1, - const std::string &Name, BasicBlock *IAE) + const std::string &Name, BasicBlock *IAE) : Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(), Idx0, Idx1, true))), - GetElementPtr, Name, IAE) { + GetElementPtr, 0, 0, Name, IAE) { init(Ptr, Idx0, Idx1); } +GetElementPtrInst::~GetElementPtrInst() { + delete[] OperandList; +} + // getIndexedType - Returns the type of the element that would be loaded with // a load instruction with the specified parameters. // -// A null type is returned if the indices are invalid for the specified +// A null type is returned if the indices are invalid for the specified // pointer type. // -const Type* GetElementPtrInst::getIndexedType(const Type *Ptr, +const Type* GetElementPtrInst::getIndexedType(const Type *Ptr, const std::vector &Idx, bool AllowCompositeLeaf) { if (!isa(Ptr)) return 0; // Type isn't a pointer type! @@ -503,7 +776,7 @@ const Type* GetElementPtrInst::getIndexedType(const Type *Ptr, return cast(Ptr)->getElementType(); else return 0; - + unsigned CurIdx = 0; while (const CompositeType *CT = dyn_cast(Ptr)) { if (Idx.size() == CurIdx) { @@ -528,7 +801,7 @@ const Type* GetElementPtrInst::getIndexedType(const Type *Ptr, return CurIdx == Idx.size() ? Ptr : 0; } -const Type* GetElementPtrInst::getIndexedType(const Type *Ptr, +const Type* GetElementPtrInst::getIndexedType(const Type *Ptr, Value *Idx0, Value *Idx1, bool AllowCompositeLeaf) { const PointerType *PTy = dyn_cast(Ptr); @@ -546,33 +819,225 @@ const Type* GetElementPtrInst::getIndexedType(const Type *Ptr, return 0; } +const Type* GetElementPtrInst::getIndexedType(const Type *Ptr, Value *Idx) { + const PointerType *PTy = dyn_cast(Ptr); + if (!PTy) return 0; // Type isn't a pointer type! + + // Check the pointer index. + if (!PTy->indexValid(Idx)) return 0; + + return PTy->getElementType(); +} + +//===----------------------------------------------------------------------===// +// ExtractElementInst Implementation +//===----------------------------------------------------------------------===// + +ExtractElementInst::ExtractElementInst(Value *Val, Value *Index, + const std::string &Name, + Instruction *InsertBef) + : Instruction(cast(Val->getType())->getElementType(), + ExtractElement, Ops, 2, Name, InsertBef) { + assert(isValidOperands(Val, Index) && + "Invalid extractelement instruction operands!"); + Ops[0].init(Val, this); + Ops[1].init(Index, this); +} + +ExtractElementInst::ExtractElementInst(Value *Val, unsigned IndexV, + const std::string &Name, + Instruction *InsertBef) + : Instruction(cast(Val->getType())->getElementType(), + ExtractElement, Ops, 2, Name, InsertBef) { + Constant *Index = ConstantInt::get(Type::UIntTy, IndexV); + assert(isValidOperands(Val, Index) && + "Invalid extractelement instruction operands!"); + Ops[0].init(Val, this); + Ops[1].init(Index, this); +} + + +ExtractElementInst::ExtractElementInst(Value *Val, Value *Index, + const std::string &Name, + BasicBlock *InsertAE) + : Instruction(cast(Val->getType())->getElementType(), + ExtractElement, Ops, 2, Name, InsertAE) { + assert(isValidOperands(Val, Index) && + "Invalid extractelement instruction operands!"); + + Ops[0].init(Val, this); + Ops[1].init(Index, this); +} + +ExtractElementInst::ExtractElementInst(Value *Val, unsigned IndexV, + const std::string &Name, + BasicBlock *InsertAE) + : Instruction(cast(Val->getType())->getElementType(), + ExtractElement, Ops, 2, Name, InsertAE) { + Constant *Index = ConstantInt::get(Type::UIntTy, IndexV); + assert(isValidOperands(Val, Index) && + "Invalid extractelement instruction operands!"); + + Ops[0].init(Val, this); + Ops[1].init(Index, this); +} + + +bool ExtractElementInst::isValidOperands(const Value *Val, const Value *Index) { + if (!isa(Val->getType()) || Index->getType() != Type::UIntTy) + return false; + return true; +} + + +//===----------------------------------------------------------------------===// +// InsertElementInst Implementation +//===----------------------------------------------------------------------===// + +InsertElementInst::InsertElementInst(const InsertElementInst &IE) + : Instruction(IE.getType(), InsertElement, Ops, 3) { + Ops[0].init(IE.Ops[0], this); + Ops[1].init(IE.Ops[1], this); + Ops[2].init(IE.Ops[2], this); +} +InsertElementInst::InsertElementInst(Value *Vec, Value *Elt, Value *Index, + const std::string &Name, + Instruction *InsertBef) + : Instruction(Vec->getType(), InsertElement, Ops, 3, Name, InsertBef) { + assert(isValidOperands(Vec, Elt, Index) && + "Invalid insertelement instruction operands!"); + Ops[0].init(Vec, this); + Ops[1].init(Elt, this); + Ops[2].init(Index, this); +} + +InsertElementInst::InsertElementInst(Value *Vec, Value *Elt, unsigned IndexV, + const std::string &Name, + Instruction *InsertBef) + : Instruction(Vec->getType(), InsertElement, Ops, 3, Name, InsertBef) { + Constant *Index = ConstantInt::get(Type::UIntTy, IndexV); + assert(isValidOperands(Vec, Elt, Index) && + "Invalid insertelement instruction operands!"); + Ops[0].init(Vec, this); + Ops[1].init(Elt, this); + Ops[2].init(Index, this); +} + + +InsertElementInst::InsertElementInst(Value *Vec, Value *Elt, Value *Index, + const std::string &Name, + BasicBlock *InsertAE) + : Instruction(Vec->getType(), InsertElement, Ops, 3, Name, InsertAE) { + assert(isValidOperands(Vec, Elt, Index) && + "Invalid insertelement instruction operands!"); + + Ops[0].init(Vec, this); + Ops[1].init(Elt, this); + Ops[2].init(Index, this); +} + +InsertElementInst::InsertElementInst(Value *Vec, Value *Elt, unsigned IndexV, + const std::string &Name, + BasicBlock *InsertAE) +: Instruction(Vec->getType(), InsertElement, Ops, 3, Name, InsertAE) { + Constant *Index = ConstantInt::get(Type::UIntTy, IndexV); + assert(isValidOperands(Vec, Elt, Index) && + "Invalid insertelement instruction operands!"); + + Ops[0].init(Vec, this); + Ops[1].init(Elt, this); + Ops[2].init(Index, this); +} + +bool InsertElementInst::isValidOperands(const Value *Vec, const Value *Elt, + const Value *Index) { + if (!isa(Vec->getType())) + return false; // First operand of insertelement must be packed type. + + if (Elt->getType() != cast(Vec->getType())->getElementType()) + return false;// Second operand of insertelement must be packed element type. + + if (Index->getType() != Type::UIntTy) + return false; // Third operand of insertelement must be uint. + return true; +} + + +//===----------------------------------------------------------------------===// +// ShuffleVectorInst Implementation +//===----------------------------------------------------------------------===// + +ShuffleVectorInst::ShuffleVectorInst(const ShuffleVectorInst &SV) + : Instruction(SV.getType(), ShuffleVector, Ops, 3) { + Ops[0].init(SV.Ops[0], this); + Ops[1].init(SV.Ops[1], this); + Ops[2].init(SV.Ops[2], this); +} + +ShuffleVectorInst::ShuffleVectorInst(Value *V1, Value *V2, Value *Mask, + const std::string &Name, + Instruction *InsertBefore) + : Instruction(V1->getType(), ShuffleVector, Ops, 3, Name, InsertBefore) { + assert(isValidOperands(V1, V2, Mask) && + "Invalid shuffle vector instruction operands!"); + Ops[0].init(V1, this); + Ops[1].init(V2, this); + Ops[2].init(Mask, this); +} + +ShuffleVectorInst::ShuffleVectorInst(Value *V1, Value *V2, Value *Mask, + const std::string &Name, + BasicBlock *InsertAtEnd) + : Instruction(V1->getType(), ShuffleVector, Ops, 3, Name, InsertAtEnd) { + assert(isValidOperands(V1, V2, Mask) && + "Invalid shuffle vector instruction operands!"); + + Ops[0].init(V1, this); + Ops[1].init(V2, this); + Ops[2].init(Mask, this); +} + +bool ShuffleVectorInst::isValidOperands(const Value *V1, const Value *V2, + const Value *Mask) { + if (!isa(V1->getType())) return false; + if (V1->getType() != V2->getType()) return false; + if (!isa(Mask->getType()) || + cast(Mask->getType())->getElementType() != Type::UIntTy || + cast(Mask->getType())->getNumElements() != + cast(V1->getType())->getNumElements()) + return false; + return true; +} + + //===----------------------------------------------------------------------===// // BinaryOperator Class //===----------------------------------------------------------------------===// -void BinaryOperator::init(BinaryOps iType, Value *S1, Value *S2) +void BinaryOperator::init(BinaryOps iType) { - Operands.reserve(2); - Operands.push_back(Use(S1, this)); - Operands.push_back(Use(S2, this)); - assert(S1 && S2 && S1->getType() == S2->getType()); - + Value *LHS = getOperand(0), *RHS = getOperand(1); + assert(LHS->getType() == RHS->getType() && + "Binary operator operand types must match!"); #ifndef NDEBUG switch (iType) { case Add: case Sub: case Mul: case Div: case Rem: - assert(getType() == S1->getType() && + assert(getType() == LHS->getType() && "Arithmetic operation should return same type as operands!"); - assert((getType()->isInteger() || getType()->isFloatingPoint()) && - "Tried to create an arithmetic operation on a non-arithmetic type!"); + assert((getType()->isInteger() || getType()->isFloatingPoint() || + isa(getType())) && + "Tried to create an arithmetic operation on a non-arithmetic type!"); break; case And: case Or: case Xor: - assert(getType() == S1->getType() && + assert(getType() == LHS->getType() && "Logical operation should return same type as operands!"); - assert(getType()->isIntegral() && - "Tried to create an logical operation on a non-integral type!"); + assert((getType()->isIntegral() || + (isa(getType()) && + cast(getType())->getElementType()->isIntegral())) && + "Tried to create a logical operation on a non-integral type!"); break; case SetLT: case SetGT: case SetLE: case SetGE: case SetEQ: case SetNE: @@ -584,7 +1049,7 @@ void BinaryOperator::init(BinaryOps iType, Value *S1, Value *S2) } BinaryOperator *BinaryOperator::create(BinaryOps Op, Value *S1, Value *S2, - const std::string &Name, + const std::string &Name, Instruction *InsertBefore) { assert(S1->getType() == S2->getType() && "Cannot create binary operator with two operands of differing type!"); @@ -600,7 +1065,7 @@ BinaryOperator *BinaryOperator::create(BinaryOps Op, Value *S1, Value *S2, } BinaryOperator *BinaryOperator::create(BinaryOps Op, Value *S1, Value *S2, - const std::string &Name, + const std::string &Name, BasicBlock *InsertAtEnd) { BinaryOperator *Res = create(Op, S1, S2, Name); InsertAtEnd->getInstList().push_back(Res); @@ -633,15 +1098,31 @@ BinaryOperator *BinaryOperator::createNeg(Value *Op, const std::string &Name, BinaryOperator *BinaryOperator::createNot(Value *Op, const std::string &Name, Instruction *InsertBefore) { - return new BinaryOperator(Instruction::Xor, Op, - ConstantIntegral::getAllOnesValue(Op->getType()), + Constant *C; + if (const PackedType *PTy = dyn_cast(Op->getType())) { + C = ConstantIntegral::getAllOnesValue(PTy->getElementType()); + C = ConstantPacked::get(std::vector(PTy->getNumElements(), C)); + } else { + C = ConstantIntegral::getAllOnesValue(Op->getType()); + } + + return new BinaryOperator(Instruction::Xor, Op, C, Op->getType(), Name, InsertBefore); } BinaryOperator *BinaryOperator::createNot(Value *Op, const std::string &Name, BasicBlock *InsertAtEnd) { - return new BinaryOperator(Instruction::Xor, Op, - ConstantIntegral::getAllOnesValue(Op->getType()), + Constant *AllOnes; + if (const PackedType *PTy = dyn_cast(Op->getType())) { + // Create a vector of all ones values. + Constant *Elt = ConstantIntegral::getAllOnesValue(PTy->getElementType()); + AllOnes = + ConstantPacked::get(std::vector(PTy->getNumElements(), Elt)); + } else { + AllOnes = ConstantIntegral::getAllOnesValue(Op->getType()); + } + + return new BinaryOperator(Instruction::Xor, Op, AllOnes, Op->getType(), Name, InsertAtEnd); } @@ -669,27 +1150,28 @@ bool BinaryOperator::isNot(const Value *V) { return false; } -Value *BinaryOperator::getNegArgument(BinaryOperator *Bop) { - assert(isNeg(Bop) && "getNegArgument from non-'neg' instruction!"); - return Bop->getOperand(1); +Value *BinaryOperator::getNegArgument(Value *BinOp) { + assert(isNeg(BinOp) && "getNegArgument from non-'neg' instruction!"); + return cast(BinOp)->getOperand(1); } -const Value *BinaryOperator::getNegArgument(const BinaryOperator *Bop) { - return getNegArgument((BinaryOperator*)Bop); +const Value *BinaryOperator::getNegArgument(const Value *BinOp) { + return getNegArgument(const_cast(BinOp)); } -Value *BinaryOperator::getNotArgument(BinaryOperator *Bop) { - assert(isNot(Bop) && "getNotArgument on non-'not' instruction!"); - Value *Op0 = Bop->getOperand(0); - Value *Op1 = Bop->getOperand(1); +Value *BinaryOperator::getNotArgument(Value *BinOp) { + assert(isNot(BinOp) && "getNotArgument on non-'not' instruction!"); + BinaryOperator *BO = cast(BinOp); + Value *Op0 = BO->getOperand(0); + Value *Op1 = BO->getOperand(1); if (isConstantAllOnes(Op0)) return Op1; assert(isConstantAllOnes(Op1)); return Op0; } -const Value *BinaryOperator::getNotArgument(const BinaryOperator *Bop) { - return getNotArgument((BinaryOperator*)Bop); +const Value *BinaryOperator::getNotArgument(const Value *BinOp) { + return getNotArgument(const_cast(BinOp)); } @@ -707,16 +1189,43 @@ bool BinaryOperator::swapOperands() { else return true; // Can't commute operands - std::swap(Operands[0], Operands[1]); + std::swap(Ops[0], Ops[1]); return false; } +//===----------------------------------------------------------------------===// +// ShiftInst Class +//===----------------------------------------------------------------------===// + +/// isLogicalShift - Return true if this is a logical shift left or a logical +/// shift right. +bool ShiftInst::isLogicalShift() const { + return getOpcode() == Instruction::Shl || getType()->isUnsigned(); +} + +//===----------------------------------------------------------------------===// +// CastInst Class +//===----------------------------------------------------------------------===// + +/// isTruncIntCast - Return true if this is a truncating integer cast +/// instruction, e.g. a cast from long to uint. +bool CastInst::isTruncIntCast() const { + // The dest type has to be integral, the input has to be integer. + if (!getType()->isIntegral() || !getOperand(0)->getType()->isInteger()) + return false; + + // Has to be large to smaller. + return getOperand(0)->getType()->getPrimitiveSizeInBits() > + getType()->getPrimitiveSizeInBits(); +} + + //===----------------------------------------------------------------------===// // SetCondInst Class //===----------------------------------------------------------------------===// -SetCondInst::SetCondInst(BinaryOps Opcode, Value *S1, Value *S2, +SetCondInst::SetCondInst(BinaryOps Opcode, Value *S1, Value *S2, const std::string &Name, Instruction *InsertBefore) : BinaryOperator(Opcode, S1, S2, Type::BoolTy, Name, InsertBefore) { @@ -724,7 +1233,7 @@ SetCondInst::SetCondInst(BinaryOps Opcode, Value *S1, Value *S2, assert(getInverseCondition(Opcode)); } -SetCondInst::SetCondInst(BinaryOps Opcode, Value *S1, Value *S2, +SetCondInst::SetCondInst(BinaryOps Opcode, Value *S1, Value *S2, const std::string &Name, BasicBlock *InsertAtEnd) : BinaryOperator(Opcode, S1, S2, Type::BoolTy, Name, InsertAtEnd) { @@ -767,28 +1276,42 @@ Instruction::BinaryOps SetCondInst::getSwappedCondition(BinaryOps Opcode) { // SwitchInst Implementation //===----------------------------------------------------------------------===// -void SwitchInst::init(Value *Value, BasicBlock *Default) -{ +void SwitchInst::init(Value *Value, BasicBlock *Default, unsigned NumCases) { assert(Value && Default); - Operands.push_back(Use(Value, this)); - Operands.push_back(Use(Default, this)); -} + ReservedSpace = 2+NumCases*2; + NumOperands = 2; + OperandList = new Use[ReservedSpace]; -SwitchInst::SwitchInst(const SwitchInst &SI) - : TerminatorInst(Instruction::Switch) { - Operands.reserve(SI.Operands.size()); + OperandList[0].init(Value, this); + OperandList[1].init(Default, this); +} - for (unsigned i = 0, E = SI.Operands.size(); i != E; i+=2) { - Operands.push_back(Use(SI.Operands[i], this)); - Operands.push_back(Use(SI.Operands[i+1], this)); +SwitchInst::SwitchInst(const SwitchInst &SI) + : TerminatorInst(Instruction::Switch, new Use[SI.getNumOperands()], + SI.getNumOperands()) { + Use *OL = OperandList, *InOL = SI.OperandList; + for (unsigned i = 0, E = SI.getNumOperands(); i != E; i+=2) { + OL[i].init(InOL[i], this); + OL[i+1].init(InOL[i+1], this); } } +SwitchInst::~SwitchInst() { + delete [] OperandList; +} + + /// addCase - Add an entry to the switch instruction... /// -void SwitchInst::addCase(Constant *OnVal, BasicBlock *Dest) { - Operands.push_back(Use((Value*)OnVal, this)); - Operands.push_back(Use((Value*)Dest, this)); +void SwitchInst::addCase(ConstantInt *OnVal, BasicBlock *Dest) { + unsigned OpNo = NumOperands; + if (OpNo+2 > ReservedSpace) + resizeOperands(0); // Get more space! + // Initialize some new operands. + assert(OpNo+1 < ReservedSpace && "Growing didn't work!"); + NumOperands = OpNo+2; + OperandList[OpNo].init(OnVal, this); + OperandList[OpNo+1].init(Dest, this); } /// removeCase - This method removes the specified successor from the switch @@ -797,6 +1320,103 @@ void SwitchInst::addCase(Constant *OnVal, BasicBlock *Dest) { /// void SwitchInst::removeCase(unsigned idx) { assert(idx != 0 && "Cannot remove the default case!"); - assert(idx*2 < Operands.size() && "Successor index out of range!!!"); - Operands.erase(Operands.begin()+idx*2, Operands.begin()+(idx+1)*2); + assert(idx*2 < getNumOperands() && "Successor index out of range!!!"); + + unsigned NumOps = getNumOperands(); + Use *OL = OperandList; + + // Move everything after this operand down. + // + // FIXME: we could just swap with the end of the list, then erase. However, + // client might not expect this to happen. The code as it is thrashes the + // use/def lists, which is kinda lame. + for (unsigned i = (idx+1)*2; i != NumOps; i += 2) { + OL[i-2] = OL[i]; + OL[i-2+1] = OL[i+1]; + } + + // Nuke the last value. + OL[NumOps-2].set(0); + OL[NumOps-2+1].set(0); + NumOperands = NumOps-2; +} + +/// resizeOperands - resize operands - This adjusts the length of the operands +/// list according to the following behavior: +/// 1. If NumOps == 0, grow the operand list in response to a push_back style +/// of operation. This grows the number of ops by 1.5 times. +/// 2. If NumOps > NumOperands, reserve space for NumOps operands. +/// 3. If NumOps == NumOperands, trim the reserved space. +/// +void SwitchInst::resizeOperands(unsigned NumOps) { + if (NumOps == 0) { + NumOps = getNumOperands()/2*6; + } else if (NumOps*2 > NumOperands) { + // No resize needed. + if (ReservedSpace >= NumOps) return; + } else if (NumOps == NumOperands) { + if (ReservedSpace == NumOps) return; + } else { + return; + } + + ReservedSpace = NumOps; + Use *NewOps = new Use[NumOps]; + Use *OldOps = OperandList; + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + NewOps[i].init(OldOps[i], this); + OldOps[i].set(0); + } + delete [] OldOps; + OperandList = NewOps; +} + + +BasicBlock *SwitchInst::getSuccessorV(unsigned idx) const { + return getSuccessor(idx); +} +unsigned SwitchInst::getNumSuccessorsV() const { + return getNumSuccessors(); +} +void SwitchInst::setSuccessorV(unsigned idx, BasicBlock *B) { + setSuccessor(idx, B); +} + + +// Define these methods here so vtables don't get emitted into every translation +// unit that uses these classes. + +GetElementPtrInst *GetElementPtrInst::clone() const { + return new GetElementPtrInst(*this); +} + +BinaryOperator *BinaryOperator::clone() const { + return create(getOpcode(), Ops[0], Ops[1]); +} + +MallocInst *MallocInst::clone() const { return new MallocInst(*this); } +AllocaInst *AllocaInst::clone() const { return new AllocaInst(*this); } +FreeInst *FreeInst::clone() const { return new FreeInst(getOperand(0)); } +LoadInst *LoadInst::clone() const { return new LoadInst(*this); } +StoreInst *StoreInst::clone() const { return new StoreInst(*this); } +CastInst *CastInst::clone() const { return new CastInst(*this); } +CallInst *CallInst::clone() const { return new CallInst(*this); } +ShiftInst *ShiftInst::clone() const { return new ShiftInst(*this); } +SelectInst *SelectInst::clone() const { return new SelectInst(*this); } +VAArgInst *VAArgInst::clone() const { return new VAArgInst(*this); } +ExtractElementInst *ExtractElementInst::clone() const { + return new ExtractElementInst(*this); +} +InsertElementInst *InsertElementInst::clone() const { + return new InsertElementInst(*this); +} +ShuffleVectorInst *ShuffleVectorInst::clone() const { + return new ShuffleVectorInst(*this); } +PHINode *PHINode::clone() const { return new PHINode(*this); } +ReturnInst *ReturnInst::clone() const { return new ReturnInst(*this); } +BranchInst *BranchInst::clone() const { return new BranchInst(*this); } +SwitchInst *SwitchInst::clone() const { return new SwitchInst(*this); } +InvokeInst *InvokeInst::clone() const { return new InvokeInst(*this); } +UnwindInst *UnwindInst::clone() const { return new UnwindInst(); } +UnreachableInst *UnreachableInst::clone() const { return new UnreachableInst();}