//
// 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 is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//
-#include "llvm/BasicBlock.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
-#include "llvm/ParameterAttributes.h"
#include "llvm/Support/CallSite.h"
#include "llvm/Support/ConstantRange.h"
#include "llvm/Support/MathExtras.h"
using namespace llvm;
+//===----------------------------------------------------------------------===//
+// CallSite Class
+//===----------------------------------------------------------------------===//
+
+CallSite::CallSite(Instruction *C) {
+ assert((isa<CallInst>(C) || isa<InvokeInst>(C)) && "Not a call!");
+ I = C;
+}
unsigned CallSite::getCallingConv() const {
if (CallInst *CI = dyn_cast<CallInst>(I))
return CI->getCallingConv();
else
cast<InvokeInst>(I)->setCallingConv(CC);
}
-const ParamAttrsList* CallSite::getParamAttrs() const {
+const AttrListPtr &CallSite::getAttributes() const {
if (CallInst *CI = dyn_cast<CallInst>(I))
- return CI->getParamAttrs();
+ return CI->getAttributes();
else
- return cast<InvokeInst>(I)->getParamAttrs();
+ return cast<InvokeInst>(I)->getAttributes();
}
-void CallSite::setParamAttrs(const ParamAttrsList *PAL) {
+void CallSite::setAttributes(const AttrListPtr &PAL) {
if (CallInst *CI = dyn_cast<CallInst>(I))
- CI->setParamAttrs(PAL);
+ CI->setAttributes(PAL);
else
- cast<InvokeInst>(I)->setParamAttrs(PAL);
+ cast<InvokeInst>(I)->setAttributes(PAL);
}
-bool CallSite::paramHasAttr(uint16_t i, ParameterAttributes attr) const {
+bool CallSite::paramHasAttr(uint16_t i, Attributes attr) const {
if (CallInst *CI = dyn_cast<CallInst>(I))
return CI->paramHasAttr(i, attr);
else
return cast<InvokeInst>(I)->paramHasAttr(i, attr);
}
+uint16_t CallSite::getParamAlignment(uint16_t i) const {
+ if (CallInst *CI = dyn_cast<CallInst>(I))
+ return CI->getParamAlignment(i);
+ else
+ return cast<InvokeInst>(I)->getParamAlignment(i);
+}
+
bool CallSite::doesNotAccessMemory() const {
if (CallInst *CI = dyn_cast<CallInst>(I))
return CI->doesNotAccessMemory();
else
return cast<InvokeInst>(I)->doesNotAccessMemory();
}
+void CallSite::setDoesNotAccessMemory(bool doesNotAccessMemory) {
+ if (CallInst *CI = dyn_cast<CallInst>(I))
+ CI->setDoesNotAccessMemory(doesNotAccessMemory);
+ else
+ cast<InvokeInst>(I)->setDoesNotAccessMemory(doesNotAccessMemory);
+}
bool CallSite::onlyReadsMemory() const {
if (CallInst *CI = dyn_cast<CallInst>(I))
return CI->onlyReadsMemory();
else
return cast<InvokeInst>(I)->onlyReadsMemory();
}
+void CallSite::setOnlyReadsMemory(bool onlyReadsMemory) {
+ if (CallInst *CI = dyn_cast<CallInst>(I))
+ CI->setOnlyReadsMemory(onlyReadsMemory);
+ else
+ cast<InvokeInst>(I)->setOnlyReadsMemory(onlyReadsMemory);
+}
+bool CallSite::doesNotReturn() const {
+ if (CallInst *CI = dyn_cast<CallInst>(I))
+ return CI->doesNotReturn();
+ else
+ return cast<InvokeInst>(I)->doesNotReturn();
+}
+void CallSite::setDoesNotReturn(bool doesNotReturn) {
+ if (CallInst *CI = dyn_cast<CallInst>(I))
+ CI->setDoesNotReturn(doesNotReturn);
+ else
+ cast<InvokeInst>(I)->setDoesNotReturn(doesNotReturn);
+}
bool CallSite::doesNotThrow() const {
if (CallInst *CI = dyn_cast<CallInst>(I))
return CI->doesNotThrow();
cast<InvokeInst>(I)->setDoesNotThrow(doesNotThrow);
}
+bool CallSite::hasArgument(const Value *Arg) const {
+ for (arg_iterator AI = this->arg_begin(), E = this->arg_end(); AI != E; ++AI)
+ if (AI->get() == Arg)
+ return true;
+ return false;
+}
+
//===----------------------------------------------------------------------===//
// TerminatorInst Class
//===----------------------------------------------------------------------===//
TerminatorInst::~TerminatorInst() {
}
+//===----------------------------------------------------------------------===//
+// UnaryInstruction Class
+//===----------------------------------------------------------------------===//
+
// 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()),
+ allocHungoffUses(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);
+ OL[i] = PN.getOperand(i);
+ OL[i+1] = PN.getOperand(i+1);
}
}
PHINode::~PHINode() {
- delete [] OperandList;
+ if (OperandList)
+ dropHungoffUses(OperandList);
}
// removeIncomingValue - Remove an incoming value. This is useful if a
/// 3. If NumOps == NumOperands, trim the reserved space.
///
void PHINode::resizeOperands(unsigned NumOps) {
+ unsigned e = getNumOperands();
if (NumOps == 0) {
- NumOps = (getNumOperands())*3/2;
+ NumOps = e*3/2;
if (NumOps < 4) NumOps = 4; // 4 op PHI nodes are VERY common.
} else if (NumOps*2 > NumOperands) {
// No resize needed.
}
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;
+ Use *NewOps = allocHungoffUses(NumOps);
+ std::copy(OldOps, OldOps + e, NewOps);
OperandList = NewOps;
+ if (OldOps) Use::zap(OldOps, OldOps + e, true);
}
/// hasConstantValue - If the specified PHI node always merges together the same
///
Value *PHINode::hasConstantValue(bool AllowNonDominatingInstruction) const {
// If the PHI node only has one incoming value, eliminate the PHI node...
- if (getNumIncomingValues() == 1)
+ 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<UndefValue>(getIncomingValue(i)))
+ if (isa<UndefValue>(getIncomingValue(i))) {
HasUndefInput = true;
- else if (getIncomingValue(i) != this) // Not the PHI node itself...
+ } 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
//===----------------------------------------------------------------------===//
CallInst::~CallInst() {
- delete [] OperandList;
- if (ParamAttrs)
- ParamAttrs->dropRef();
}
void CallInst::init(Value *Func, Value* const *Params, unsigned NumParams) {
- ParamAttrs = 0;
- NumOperands = NumParams+1;
- Use *OL = OperandList = new Use[NumParams+1];
- OL[0].init(Func, this);
+ assert(NumOperands == NumParams+1 && "NumOperands not set up?");
+ Use *OL = OperandList;
+ OL[0] = Func;
const FunctionType *FTy =
cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
assert((i >= FTy->getNumParams() ||
FTy->getParamType(i) == Params[i]->getType()) &&
"Calling a function with a bad signature!");
- OL[i+1].init(Params[i], this);
+ OL[i+1] = Params[i];
}
}
void CallInst::init(Value *Func, Value *Actual1, Value *Actual2) {
- ParamAttrs = 0;
- NumOperands = 3;
- Use *OL = OperandList = new Use[3];
- OL[0].init(Func, this);
- OL[1].init(Actual1, this);
- OL[2].init(Actual2, this);
+ assert(NumOperands == 3 && "NumOperands not set up?");
+ Use *OL = OperandList;
+ OL[0] = Func;
+ OL[1] = Actual1;
+ OL[2] = Actual2;
const FunctionType *FTy =
cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
}
void CallInst::init(Value *Func, Value *Actual) {
- ParamAttrs = 0;
- NumOperands = 2;
- Use *OL = OperandList = new Use[2];
- OL[0].init(Func, this);
- OL[1].init(Actual, this);
+ assert(NumOperands == 2 && "NumOperands not set up?");
+ Use *OL = OperandList;
+ OL[0] = Func;
+ OL[1] = Actual;
const FunctionType *FTy =
cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
}
void CallInst::init(Value *Func) {
- ParamAttrs = 0;
- NumOperands = 1;
- Use *OL = OperandList = new Use[1];
- OL[0].init(Func, this);
+ assert(NumOperands == 1 && "NumOperands not set up?");
+ Use *OL = OperandList;
+ OL[0] = Func;
const FunctionType *FTy =
cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
assert(FTy->getNumParams() == 0 && "Calling a function with bad signature");
}
-#if 0
-// Leave for llvm-gcc
-CallInst::CallInst(Value *Func, Value* const *Args, unsigned NumArgs,
- const std::string &Name, BasicBlock *InsertAtEnd)
- : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
- ->getElementType())->getReturnType(),
- Instruction::Call, 0, 0, InsertAtEnd) {
- init(Func, Args, NumArgs);
- setName(Name);
-}
-CallInst::CallInst(Value *Func, Value* const *Args, unsigned NumArgs,
- const std::string &Name, Instruction *InsertBefore)
- : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
- ->getElementType())->getReturnType(),
- Instruction::Call, 0, 0, InsertBefore) {
- init(Func, Args, NumArgs);
- setName(Name);
-}
-
-CallInst::CallInst(Value *Func, Value *Actual1, Value *Actual2,
- const std::string &Name, Instruction *InsertBefore)
- : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
- ->getElementType())->getReturnType(),
- Instruction::Call, 0, 0, InsertBefore) {
- init(Func, Actual1, Actual2);
- setName(Name);
-}
-
-CallInst::CallInst(Value *Func, Value *Actual1, Value *Actual2,
- const std::string &Name, BasicBlock *InsertAtEnd)
- : Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
- ->getElementType())->getReturnType(),
- Instruction::Call, 0, 0, InsertAtEnd) {
- init(Func, Actual1, Actual2);
- setName(Name);
-}
-#endif
CallInst::CallInst(Value *Func, Value* Actual, const std::string &Name,
Instruction *InsertBefore)
: Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
->getElementType())->getReturnType(),
- Instruction::Call, 0, 0, InsertBefore) {
+ Instruction::Call,
+ OperandTraits<CallInst>::op_end(this) - 2,
+ 2, InsertBefore) {
init(Func, Actual);
setName(Name);
}
BasicBlock *InsertAtEnd)
: Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
->getElementType())->getReturnType(),
- Instruction::Call, 0, 0, InsertAtEnd) {
+ Instruction::Call,
+ OperandTraits<CallInst>::op_end(this) - 2,
+ 2, InsertAtEnd) {
init(Func, Actual);
setName(Name);
}
Instruction *InsertBefore)
: Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
->getElementType())->getReturnType(),
- Instruction::Call, 0, 0, InsertBefore) {
+ Instruction::Call,
+ OperandTraits<CallInst>::op_end(this) - 1,
+ 1, InsertBefore) {
init(Func);
setName(Name);
}
BasicBlock *InsertAtEnd)
: Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
->getElementType())->getReturnType(),
- Instruction::Call, 0, 0, InsertAtEnd) {
+ Instruction::Call,
+ OperandTraits<CallInst>::op_end(this) - 1,
+ 1, InsertAtEnd) {
init(Func);
setName(Name);
}
CallInst::CallInst(const CallInst &CI)
- : Instruction(CI.getType(), Instruction::Call, new Use[CI.getNumOperands()],
- CI.getNumOperands()),
- ParamAttrs(0) {
- setParamAttrs(CI.getParamAttrs());
+ : Instruction(CI.getType(), Instruction::Call,
+ OperandTraits<CallInst>::op_end(this) - CI.getNumOperands(),
+ CI.getNumOperands()) {
+ setAttributes(CI.getAttributes());
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);
+ OL[i] = InOL[i];
}
-void CallInst::setParamAttrs(const ParamAttrsList *newAttrs) {
- if (ParamAttrs == newAttrs)
- return;
-
- if (ParamAttrs)
- ParamAttrs->dropRef();
-
- if (newAttrs)
- newAttrs->addRef();
+void CallInst::addAttribute(unsigned i, Attributes attr) {
+ AttrListPtr PAL = getAttributes();
+ PAL = PAL.addAttr(i, attr);
+ setAttributes(PAL);
+}
- ParamAttrs = newAttrs;
+void CallInst::removeAttribute(unsigned i, Attributes attr) {
+ AttrListPtr PAL = getAttributes();
+ PAL = PAL.removeAttr(i, attr);
+ setAttributes(PAL);
}
-bool CallInst::paramHasAttr(uint16_t i, ParameterAttributes attr) const {
- if (ParamAttrs && ParamAttrs->paramHasAttr(i, attr))
+bool CallInst::paramHasAttr(unsigned i, Attributes attr) const {
+ if (AttributeList.paramHasAttr(i, attr))
return true;
if (const Function *F = getCalledFunction())
return F->paramHasAttr(i, attr);
return false;
}
-void CallInst::setDoesNotThrow(bool doesNotThrow) {
- const ParamAttrsList *PAL = getParamAttrs();
- if (doesNotThrow)
- PAL = ParamAttrsList::includeAttrs(PAL, 0, ParamAttr::NoUnwind);
- else
- PAL = ParamAttrsList::excludeAttrs(PAL, 0, ParamAttr::NoUnwind);
- setParamAttrs(PAL);
-}
-
//===----------------------------------------------------------------------===//
// InvokeInst Implementation
//===----------------------------------------------------------------------===//
-InvokeInst::~InvokeInst() {
- delete [] OperandList;
- if (ParamAttrs)
- ParamAttrs->dropRef();
-}
-
void InvokeInst::init(Value *Fn, BasicBlock *IfNormal, BasicBlock *IfException,
Value* const *Args, unsigned NumArgs) {
- ParamAttrs = 0;
- NumOperands = 3+NumArgs;
- Use *OL = OperandList = new Use[3+NumArgs];
- OL[0].init(Fn, this);
- OL[1].init(IfNormal, this);
- OL[2].init(IfException, this);
+ assert(NumOperands == 3+NumArgs && "NumOperands not set up?");
+ Use *OL = OperandList;
+ OL[0] = Fn;
+ OL[1] = IfNormal;
+ OL[2] = IfException;
const FunctionType *FTy =
cast<FunctionType>(cast<PointerType>(Fn->getType())->getElementType());
FTy = FTy; // silence warning.
- assert((NumArgs == FTy->getNumParams()) ||
- (FTy->isVarArg() && NumArgs > FTy->getNumParams()) &&
+ assert(((NumArgs == FTy->getNumParams()) ||
+ (FTy->isVarArg() && NumArgs > FTy->getNumParams())) &&
"Calling a function with bad signature");
for (unsigned i = 0, e = NumArgs; i != e; i++) {
FTy->getParamType(i) == Args[i]->getType()) &&
"Invoking a function with a bad signature!");
- OL[i+3].init(Args[i], this);
+ OL[i+3] = Args[i];
}
}
InvokeInst::InvokeInst(const InvokeInst &II)
: TerminatorInst(II.getType(), Instruction::Invoke,
- new Use[II.getNumOperands()], II.getNumOperands()),
- ParamAttrs(0) {
- setParamAttrs(II.getParamAttrs());
+ OperandTraits<InvokeInst>::op_end(this)
+ - II.getNumOperands(),
+ II.getNumOperands()) {
+ setAttributes(II.getAttributes());
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);
+ OL[i] = InOL[i];
}
BasicBlock *InvokeInst::getSuccessorV(unsigned idx) const {
return setSuccessor(idx, B);
}
-void InvokeInst::setParamAttrs(const ParamAttrsList *newAttrs) {
- if (ParamAttrs == newAttrs)
- return;
-
- if (ParamAttrs)
- ParamAttrs->dropRef();
-
- if (newAttrs)
- newAttrs->addRef();
-
- ParamAttrs = newAttrs;
-}
-
-bool InvokeInst::paramHasAttr(uint16_t i, ParameterAttributes attr) const {
- if (ParamAttrs && ParamAttrs->paramHasAttr(i, attr))
+bool InvokeInst::paramHasAttr(unsigned i, Attributes attr) const {
+ if (AttributeList.paramHasAttr(i, attr))
return true;
if (const Function *F = getCalledFunction())
return F->paramHasAttr(i, attr);
return false;
}
-void InvokeInst::setDoesNotThrow(bool doesNotThrow) {
- const ParamAttrsList *PAL = getParamAttrs();
- if (doesNotThrow)
- PAL = ParamAttrsList::includeAttrs(PAL, 0, ParamAttr::NoUnwind);
- else
- PAL = ParamAttrsList::excludeAttrs(PAL, 0, ParamAttr::NoUnwind);
- setParamAttrs(PAL);
+void InvokeInst::addAttribute(unsigned i, Attributes attr) {
+ AttrListPtr PAL = getAttributes();
+ PAL = PAL.addAttr(i, attr);
+ setAttributes(PAL);
+}
+
+void InvokeInst::removeAttribute(unsigned i, Attributes attr) {
+ AttrListPtr PAL = getAttributes();
+ PAL = PAL.removeAttr(i, attr);
+ setAttributes(PAL);
}
ReturnInst::ReturnInst(const ReturnInst &RI)
: TerminatorInst(Type::VoidTy, Instruction::Ret,
- &RetVal, RI.getNumOperands()) {
+ OperandTraits<ReturnInst>::op_end(this) -
+ RI.getNumOperands(),
+ RI.getNumOperands()) {
if (RI.getNumOperands())
- RetVal.init(RI.RetVal, this);
+ Op<0>() = RI.Op<0>();
}
ReturnInst::ReturnInst(Value *retVal, Instruction *InsertBefore)
- : TerminatorInst(Type::VoidTy, Instruction::Ret, &RetVal, 0, InsertBefore) {
- init(retVal);
+ : TerminatorInst(Type::VoidTy, Instruction::Ret,
+ OperandTraits<ReturnInst>::op_end(this) - !!retVal, !!retVal,
+ InsertBefore) {
+ if (retVal)
+ Op<0>() = retVal;
}
ReturnInst::ReturnInst(Value *retVal, BasicBlock *InsertAtEnd)
- : TerminatorInst(Type::VoidTy, Instruction::Ret, &RetVal, 0, InsertAtEnd) {
- init(retVal);
+ : TerminatorInst(Type::VoidTy, Instruction::Ret,
+ OperandTraits<ReturnInst>::op_end(this) - !!retVal, !!retVal,
+ InsertAtEnd) {
+ if (retVal)
+ Op<0>() = retVal;
}
ReturnInst::ReturnInst(BasicBlock *InsertAtEnd)
- : TerminatorInst(Type::VoidTy, Instruction::Ret, &RetVal, 0, InsertAtEnd) {
-}
-
-
-
-void ReturnInst::init(Value *retVal) {
- if (retVal && retVal->getType() != Type::VoidTy) {
- assert(!isa<BasicBlock>(retVal) &&
- "Cannot return basic block. Probably using the incorrect ctor");
- NumOperands = 1;
- RetVal.init(retVal, this);
- }
+ : TerminatorInst(Type::VoidTy, Instruction::Ret,
+ OperandTraits<ReturnInst>::op_end(this), 0, InsertAtEnd) {
}
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.
+/// 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::setSuccessorV(unsigned idx, BasicBlock *NewSucc) {
assert(0 && "ReturnInst has no successors!");
}
return 0;
}
+ReturnInst::~ReturnInst() {
+}
//===----------------------------------------------------------------------===//
// UnwindInst Implementation
}
BranchInst::BranchInst(BasicBlock *IfTrue, Instruction *InsertBefore)
- : TerminatorInst(Type::VoidTy, Instruction::Br, Ops, 1, InsertBefore) {
+ : TerminatorInst(Type::VoidTy, Instruction::Br,
+ OperandTraits<BranchInst>::op_end(this) - 1,
+ 1, InsertBefore) {
assert(IfTrue != 0 && "Branch destination may not be null!");
- Ops[0].init(reinterpret_cast<Value*>(IfTrue), this);
+ Op<0>() = IfTrue;
}
BranchInst::BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond,
Instruction *InsertBefore)
-: TerminatorInst(Type::VoidTy, 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);
+ : TerminatorInst(Type::VoidTy, Instruction::Br,
+ OperandTraits<BranchInst>::op_end(this) - 3,
+ 3, InsertBefore) {
+ Op<0>() = IfTrue;
+ Op<1>() = IfFalse;
+ Op<2>() = Cond;
#ifndef NDEBUG
AssertOK();
#endif
}
BranchInst::BranchInst(BasicBlock *IfTrue, BasicBlock *InsertAtEnd)
- : TerminatorInst(Type::VoidTy, Instruction::Br, Ops, 1, InsertAtEnd) {
+ : TerminatorInst(Type::VoidTy, Instruction::Br,
+ OperandTraits<BranchInst>::op_end(this) - 1,
+ 1, InsertAtEnd) {
assert(IfTrue != 0 && "Branch destination may not be null!");
- Ops[0].init(reinterpret_cast<Value*>(IfTrue), this);
+ Op<0>() = IfTrue;
}
BranchInst::BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond,
BasicBlock *InsertAtEnd)
- : TerminatorInst(Type::VoidTy, 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);
+ : TerminatorInst(Type::VoidTy, Instruction::Br,
+ OperandTraits<BranchInst>::op_end(this) - 3,
+ 3, InsertAtEnd) {
+ Op<0>() = IfTrue;
+ Op<1>() = IfFalse;
+ Op<2>() = Cond;
#ifndef NDEBUG
AssertOK();
#endif
BranchInst::BranchInst(const BranchInst &BI) :
- TerminatorInst(Type::VoidTy, Instruction::Br, Ops, BI.getNumOperands()) {
- OperandList[0].init(BI.getOperand(0), this);
+ TerminatorInst(Type::VoidTy, Instruction::Br,
+ OperandTraits<BranchInst>::op_end(this) - BI.getNumOperands(),
+ BI.getNumOperands()) {
+ OperandList[0] = BI.getOperand(0);
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);
+ OperandList[1] = BI.getOperand(1);
+ OperandList[2] = BI.getOperand(2);
}
}
unsigned Align, const std::string &Name,
Instruction *InsertBefore)
: UnaryInstruction(PointerType::getUnqual(Ty), iTy, getAISize(ArraySize),
- InsertBefore), Alignment(Align) {
- assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!");
+ InsertBefore) {
+ setAlignment(Align);
assert(Ty != Type::VoidTy && "Cannot allocate void!");
setName(Name);
}
unsigned Align, const std::string &Name,
BasicBlock *InsertAtEnd)
: UnaryInstruction(PointerType::getUnqual(Ty), iTy, getAISize(ArraySize),
- InsertAtEnd), Alignment(Align) {
- assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!");
+ InsertAtEnd) {
+ setAlignment(Align);
assert(Ty != Type::VoidTy && "Cannot allocate void!");
setName(Name);
}
AllocationInst::~AllocationInst() {
}
+void AllocationInst::setAlignment(unsigned Align) {
+ assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!");
+ SubclassData = Log2_32(Align) + 1;
+ assert(getAlignment() == Align && "Alignment representation error!");
+}
+
bool AllocationInst::isArrayAllocation() const {
if (ConstantInt *CI = dyn_cast<ConstantInt>(getOperand(0)))
return CI->getZExtValue() != 1;
//===----------------------------------------------------------------------===//
void StoreInst::AssertOK() {
+ assert(getOperand(0) && getOperand(1) && "Both operands must be non-null!");
assert(isa<PointerType>(getOperand(1)->getType()) &&
"Ptr must have pointer type!");
assert(getOperand(0)->getType() ==
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);
+ : Instruction(Type::VoidTy, Store,
+ OperandTraits<StoreInst>::op_begin(this),
+ OperandTraits<StoreInst>::operands(this),
+ InsertBefore) {
+ Op<0>() = val;
+ Op<1>() = addr;
setVolatile(false);
setAlignment(0);
AssertOK();
}
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);
+ : Instruction(Type::VoidTy, Store,
+ OperandTraits<StoreInst>::op_begin(this),
+ OperandTraits<StoreInst>::operands(this),
+ InsertAtEnd) {
+ Op<0>() = val;
+ Op<1>() = addr;
setVolatile(false);
setAlignment(0);
AssertOK();
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);
+ : Instruction(Type::VoidTy, Store,
+ OperandTraits<StoreInst>::op_begin(this),
+ OperandTraits<StoreInst>::operands(this),
+ InsertBefore) {
+ Op<0>() = val;
+ Op<1>() = addr;
setVolatile(isVolatile);
setAlignment(0);
AssertOK();
StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
unsigned Align, Instruction *InsertBefore)
- : Instruction(Type::VoidTy, Store, Ops, 2, InsertBefore) {
- Ops[0].init(val, this);
- Ops[1].init(addr, this);
+ : Instruction(Type::VoidTy, Store,
+ OperandTraits<StoreInst>::op_begin(this),
+ OperandTraits<StoreInst>::operands(this),
+ InsertBefore) {
+ Op<0>() = val;
+ Op<1>() = addr;
setVolatile(isVolatile);
setAlignment(Align);
AssertOK();
StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
unsigned Align, BasicBlock *InsertAtEnd)
- : Instruction(Type::VoidTy, Store, Ops, 2, InsertAtEnd) {
- Ops[0].init(val, this);
- Ops[1].init(addr, this);
+ : Instruction(Type::VoidTy, Store,
+ OperandTraits<StoreInst>::op_begin(this),
+ OperandTraits<StoreInst>::operands(this),
+ InsertAtEnd) {
+ Op<0>() = val;
+ Op<1>() = addr;
setVolatile(isVolatile);
setAlignment(Align);
AssertOK();
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);
+ : Instruction(Type::VoidTy, Store,
+ OperandTraits<StoreInst>::op_begin(this),
+ OperandTraits<StoreInst>::operands(this),
+ InsertAtEnd) {
+ Op<0>() = val;
+ Op<1>() = addr;
setVolatile(isVolatile);
setAlignment(0);
AssertOK();
return cast<PointerType>(Val->getType())->getAddressSpace();
}
-void GetElementPtrInst::init(Value *Ptr, Value* const *Idx, unsigned NumIdx) {
- NumOperands = 1+NumIdx;
- Use *OL = OperandList = new Use[NumOperands];
- OL[0].init(Ptr, this);
+void GetElementPtrInst::init(Value *Ptr, Value* const *Idx, unsigned NumIdx,
+ const std::string &Name) {
+ assert(NumOperands == 1+NumIdx && "NumOperands not initialized?");
+ Use *OL = OperandList;
+ OL[0] = Ptr;
for (unsigned i = 0; i != NumIdx; ++i)
- OL[i+1].init(Idx[i], this);
+ OL[i+1] = Idx[i];
+
+ setName(Name);
}
-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);
+void GetElementPtrInst::init(Value *Ptr, Value *Idx, const std::string &Name) {
+ assert(NumOperands == 2 && "NumOperands not initialized?");
+ Use *OL = OperandList;
+ OL[0] = Ptr;
+ OL[1] = Idx;
+
+ setName(Name);
+}
+
+GetElementPtrInst::GetElementPtrInst(const GetElementPtrInst &GEPI)
+ : Instruction(GEPI.getType(), GetElementPtr,
+ OperandTraits<GetElementPtrInst>::op_end(this)
+ - GEPI.getNumOperands(),
+ GEPI.getNumOperands()) {
+ Use *OL = OperandList;
+ Use *GEPIOL = GEPI.OperandList;
+ for (unsigned i = 0, E = NumOperands; i != E; ++i)
+ OL[i] = GEPIOL[i];
}
GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx,
const std::string &Name, Instruction *InBe)
: Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(),Idx)),
retrieveAddrSpace(Ptr)),
- GetElementPtr, 0, 0, InBe) {
- init(Ptr, Idx);
- setName(Name);
+ GetElementPtr,
+ OperandTraits<GetElementPtrInst>::op_end(this) - 2,
+ 2, InBe) {
+ init(Ptr, Idx, Name);
}
GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx,
const std::string &Name, BasicBlock *IAE)
: Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(),Idx)),
retrieveAddrSpace(Ptr)),
- GetElementPtr, 0, 0, IAE) {
- init(Ptr, Idx);
- setName(Name);
-}
-
-GetElementPtrInst::~GetElementPtrInst() {
- delete[] OperandList;
+ GetElementPtr,
+ OperandTraits<GetElementPtrInst>::op_end(this) - 2,
+ 2, IAE) {
+ init(Ptr, Idx, Name);
}
// getIndexedType - Returns the type of the element that would be loaded with
// a load instruction with the specified parameters.
//
+// The Idxs pointer should point to a continuous piece of memory containing the
+// indices, either as Value* or uint64_t.
+//
// A null type is returned if the indices are invalid for the specified
// pointer type.
//
-const Type* GetElementPtrInst::getIndexedType(const Type *Ptr,
- Value* const *Idxs,
- unsigned NumIdx,
- bool AllowCompositeLeaf) {
- if (!isa<PointerType>(Ptr)) return 0; // Type isn't a pointer type!
+template <typename IndexTy>
+static const Type* getIndexedTypeInternal(const Type *Ptr,
+ IndexTy const *Idxs,
+ unsigned NumIdx) {
+ const PointerType *PTy = dyn_cast<PointerType>(Ptr);
+ if (!PTy) return 0; // Type isn't a pointer type!
+ const Type *Agg = PTy->getElementType();
// Handle the special case of the empty set index set...
if (NumIdx == 0)
- if (AllowCompositeLeaf ||
- cast<PointerType>(Ptr)->getElementType()->isFirstClassType())
- return cast<PointerType>(Ptr)->getElementType();
- else
- return 0;
+ return Agg;
- unsigned CurIdx = 0;
- while (const CompositeType *CT = dyn_cast<CompositeType>(Ptr)) {
- if (NumIdx == CurIdx) {
- if (AllowCompositeLeaf || CT->isFirstClassType()) return Ptr;
- return 0; // Can't load a whole structure or array!?!?
- }
-
- Value *Index = Idxs[CurIdx++];
- if (isa<PointerType>(CT) && CurIdx != 1)
- return 0; // Can only index into pointer types at the first index!
+ unsigned CurIdx = 1;
+ for (; CurIdx != NumIdx; ++CurIdx) {
+ const CompositeType *CT = dyn_cast<CompositeType>(Agg);
+ if (!CT || isa<PointerType>(CT)) return 0;
+ IndexTy Index = Idxs[CurIdx];
if (!CT->indexValid(Index)) return 0;
- Ptr = CT->getTypeAtIndex(Index);
+ Agg = CT->getTypeAtIndex(Index);
// If the new type forwards to another type, then it is in the middle
// of being refined to another type (and hence, may have dropped all
// references to what it was using before). So, use the new forwarded
// type.
- if (const Type * Ty = Ptr->getForwardedType()) {
- Ptr = Ty;
- }
+ if (const Type *Ty = Agg->getForwardedType())
+ Agg = Ty;
}
- return CurIdx == NumIdx ? Ptr : 0;
+ return CurIdx == NumIdx ? Agg : 0;
+}
+
+const Type* GetElementPtrInst::getIndexedType(const Type *Ptr,
+ Value* const *Idxs,
+ unsigned NumIdx) {
+ return getIndexedTypeInternal(Ptr, Idxs, NumIdx);
+}
+
+const Type* GetElementPtrInst::getIndexedType(const Type *Ptr,
+ uint64_t const *Idxs,
+ unsigned NumIdx) {
+ return getIndexedTypeInternal(Ptr, Idxs, NumIdx);
}
const Type* GetElementPtrInst::getIndexedType(const Type *Ptr, Value *Idx) {
const std::string &Name,
Instruction *InsertBef)
: Instruction(cast<VectorType>(Val->getType())->getElementType(),
- ExtractElement, Ops, 2, InsertBef) {
+ ExtractElement,
+ OperandTraits<ExtractElementInst>::op_begin(this),
+ 2, InsertBef) {
assert(isValidOperands(Val, Index) &&
"Invalid extractelement instruction operands!");
- Ops[0].init(Val, this);
- Ops[1].init(Index, this);
+ Op<0>() = Val;
+ Op<1>() = Index;
setName(Name);
}
const std::string &Name,
Instruction *InsertBef)
: Instruction(cast<VectorType>(Val->getType())->getElementType(),
- ExtractElement, Ops, 2, InsertBef) {
+ ExtractElement,
+ OperandTraits<ExtractElementInst>::op_begin(this),
+ 2, InsertBef) {
Constant *Index = ConstantInt::get(Type::Int32Ty, IndexV);
assert(isValidOperands(Val, Index) &&
"Invalid extractelement instruction operands!");
- Ops[0].init(Val, this);
- Ops[1].init(Index, this);
+ Op<0>() = Val;
+ Op<1>() = Index;
setName(Name);
}
const std::string &Name,
BasicBlock *InsertAE)
: Instruction(cast<VectorType>(Val->getType())->getElementType(),
- ExtractElement, Ops, 2, InsertAE) {
+ ExtractElement,
+ OperandTraits<ExtractElementInst>::op_begin(this),
+ 2, InsertAE) {
assert(isValidOperands(Val, Index) &&
"Invalid extractelement instruction operands!");
- Ops[0].init(Val, this);
- Ops[1].init(Index, this);
+ Op<0>() = Val;
+ Op<1>() = Index;
setName(Name);
}
const std::string &Name,
BasicBlock *InsertAE)
: Instruction(cast<VectorType>(Val->getType())->getElementType(),
- ExtractElement, Ops, 2, InsertAE) {
+ ExtractElement,
+ OperandTraits<ExtractElementInst>::op_begin(this),
+ 2, InsertAE) {
Constant *Index = ConstantInt::get(Type::Int32Ty, IndexV);
assert(isValidOperands(Val, Index) &&
"Invalid extractelement instruction operands!");
- Ops[0].init(Val, this);
- Ops[1].init(Index, this);
+ Op<0>() = Val;
+ Op<1>() = Index;
setName(Name);
}
//===----------------------------------------------------------------------===//
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);
+ : Instruction(IE.getType(), InsertElement,
+ OperandTraits<InsertElementInst>::op_begin(this), 3) {
+ Op<0>() = IE.Op<0>();
+ Op<1>() = IE.Op<1>();
+ Op<2>() = IE.Op<2>();
}
InsertElementInst::InsertElementInst(Value *Vec, Value *Elt, Value *Index,
const std::string &Name,
Instruction *InsertBef)
- : Instruction(Vec->getType(), InsertElement, Ops, 3, InsertBef) {
+ : Instruction(Vec->getType(), InsertElement,
+ OperandTraits<InsertElementInst>::op_begin(this),
+ 3, 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);
+ Op<0>() = Vec;
+ Op<1>() = Elt;
+ Op<2>() = Index;
setName(Name);
}
InsertElementInst::InsertElementInst(Value *Vec, Value *Elt, unsigned IndexV,
const std::string &Name,
Instruction *InsertBef)
- : Instruction(Vec->getType(), InsertElement, Ops, 3, InsertBef) {
+ : Instruction(Vec->getType(), InsertElement,
+ OperandTraits<InsertElementInst>::op_begin(this),
+ 3, InsertBef) {
Constant *Index = ConstantInt::get(Type::Int32Ty, 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);
+ Op<0>() = Vec;
+ Op<1>() = Elt;
+ Op<2>() = Index;
setName(Name);
}
InsertElementInst::InsertElementInst(Value *Vec, Value *Elt, Value *Index,
const std::string &Name,
BasicBlock *InsertAE)
- : Instruction(Vec->getType(), InsertElement, Ops, 3, InsertAE) {
+ : Instruction(Vec->getType(), InsertElement,
+ OperandTraits<InsertElementInst>::op_begin(this),
+ 3, 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);
+ Op<0>() = Vec;
+ Op<1>() = Elt;
+ Op<2>() = Index;
setName(Name);
}
InsertElementInst::InsertElementInst(Value *Vec, Value *Elt, unsigned IndexV,
const std::string &Name,
BasicBlock *InsertAE)
-: Instruction(Vec->getType(), InsertElement, Ops, 3, InsertAE) {
+: Instruction(Vec->getType(), InsertElement,
+ OperandTraits<InsertElementInst>::op_begin(this),
+ 3, InsertAE) {
Constant *Index = ConstantInt::get(Type::Int32Ty, 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);
+ Op<0>() = Vec;
+ Op<1>() = Elt;
+ Op<2>() = Index;
setName(Name);
}
//===----------------------------------------------------------------------===//
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);
+ : Instruction(SV.getType(), ShuffleVector,
+ OperandTraits<ShuffleVectorInst>::op_begin(this),
+ OperandTraits<ShuffleVectorInst>::operands(this)) {
+ Op<0>() = SV.Op<0>();
+ Op<1>() = SV.Op<1>();
+ Op<2>() = SV.Op<2>();
}
ShuffleVectorInst::ShuffleVectorInst(Value *V1, Value *V2, Value *Mask,
const std::string &Name,
Instruction *InsertBefore)
- : Instruction(V1->getType(), ShuffleVector, Ops, 3, InsertBefore) {
+ : Instruction(V1->getType(), ShuffleVector,
+ OperandTraits<ShuffleVectorInst>::op_begin(this),
+ OperandTraits<ShuffleVectorInst>::operands(this),
+ 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);
+ Op<0>() = V1;
+ Op<1>() = V2;
+ Op<2>() = Mask;
setName(Name);
}
ShuffleVectorInst::ShuffleVectorInst(Value *V1, Value *V2, Value *Mask,
const std::string &Name,
BasicBlock *InsertAtEnd)
- : Instruction(V1->getType(), ShuffleVector, Ops, 3, InsertAtEnd) {
+ : Instruction(V1->getType(), ShuffleVector,
+ OperandTraits<ShuffleVectorInst>::op_begin(this),
+ OperandTraits<ShuffleVectorInst>::operands(this),
+ 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);
+ Op<0>() = V1;
+ Op<1>() = V2;
+ Op<2>() = Mask;
setName(Name);
}
bool ShuffleVectorInst::isValidOperands(const Value *V1, const Value *V2,
const Value *Mask) {
- if (!isa<VectorType>(V1->getType())) return false;
- if (V1->getType() != V2->getType()) return false;
- if (!isa<VectorType>(Mask->getType()) ||
- cast<VectorType>(Mask->getType())->getElementType() != Type::Int32Ty ||
- cast<VectorType>(Mask->getType())->getNumElements() !=
- cast<VectorType>(V1->getType())->getNumElements())
+ if (!isa<VectorType>(V1->getType()) ||
+ V1->getType() != V2->getType())
+ return false;
+
+ const VectorType *MaskTy = dyn_cast<VectorType>(Mask->getType());
+ if (!isa<Constant>(Mask) || MaskTy == 0 ||
+ MaskTy->getElementType() != Type::Int32Ty ||
+ MaskTy->getNumElements() !=
+ cast<VectorType>(V1->getType())->getNumElements())
return false;
return true;
}
+/// getMaskValue - Return the index from the shuffle mask for the specified
+/// output result. This is either -1 if the element is undef or a number less
+/// than 2*numelements.
+int ShuffleVectorInst::getMaskValue(unsigned i) const {
+ const Constant *Mask = cast<Constant>(getOperand(2));
+ if (isa<UndefValue>(Mask)) return -1;
+ if (isa<ConstantAggregateZero>(Mask)) return 0;
+ const ConstantVector *MaskCV = cast<ConstantVector>(Mask);
+ assert(i < MaskCV->getNumOperands() && "Index out of range");
+
+ if (isa<UndefValue>(MaskCV->getOperand(i)))
+ return -1;
+ return cast<ConstantInt>(MaskCV->getOperand(i))->getZExtValue();
+}
+
+//===----------------------------------------------------------------------===//
+// InsertValueInst Class
+//===----------------------------------------------------------------------===//
+
+void InsertValueInst::init(Value *Agg, Value *Val, const unsigned *Idx,
+ unsigned NumIdx, const std::string &Name) {
+ assert(NumOperands == 2 && "NumOperands not initialized?");
+ Op<0>() = Agg;
+ Op<1>() = Val;
+
+ Indices.insert(Indices.end(), Idx, Idx + NumIdx);
+ setName(Name);
+}
+
+void InsertValueInst::init(Value *Agg, Value *Val, unsigned Idx,
+ const std::string &Name) {
+ assert(NumOperands == 2 && "NumOperands not initialized?");
+ Op<0>() = Agg;
+ Op<1>() = Val;
+
+ Indices.push_back(Idx);
+ setName(Name);
+}
+
+InsertValueInst::InsertValueInst(const InsertValueInst &IVI)
+ : Instruction(IVI.getType(), InsertValue,
+ OperandTraits<InsertValueInst>::op_begin(this), 2),
+ Indices(IVI.Indices) {
+ Op<0>() = IVI.getOperand(0);
+ Op<1>() = IVI.getOperand(1);
+}
+
+InsertValueInst::InsertValueInst(Value *Agg,
+ Value *Val,
+ unsigned Idx,
+ const std::string &Name,
+ Instruction *InsertBefore)
+ : Instruction(Agg->getType(), InsertValue,
+ OperandTraits<InsertValueInst>::op_begin(this),
+ 2, InsertBefore) {
+ init(Agg, Val, Idx, Name);
+}
+
+InsertValueInst::InsertValueInst(Value *Agg,
+ Value *Val,
+ unsigned Idx,
+ const std::string &Name,
+ BasicBlock *InsertAtEnd)
+ : Instruction(Agg->getType(), InsertValue,
+ OperandTraits<InsertValueInst>::op_begin(this),
+ 2, InsertAtEnd) {
+ init(Agg, Val, Idx, Name);
+}
+
+//===----------------------------------------------------------------------===//
+// ExtractValueInst Class
+//===----------------------------------------------------------------------===//
+
+void ExtractValueInst::init(const unsigned *Idx, unsigned NumIdx,
+ const std::string &Name) {
+ assert(NumOperands == 1 && "NumOperands not initialized?");
+
+ Indices.insert(Indices.end(), Idx, Idx + NumIdx);
+ setName(Name);
+}
+
+void ExtractValueInst::init(unsigned Idx, const std::string &Name) {
+ assert(NumOperands == 1 && "NumOperands not initialized?");
+
+ Indices.push_back(Idx);
+ setName(Name);
+}
+
+ExtractValueInst::ExtractValueInst(const ExtractValueInst &EVI)
+ : UnaryInstruction(EVI.getType(), ExtractValue, EVI.getOperand(0)),
+ Indices(EVI.Indices) {
+}
+
+// getIndexedType - Returns the type of the element that would be extracted
+// with an extractvalue instruction with the specified parameters.
+//
+// A null type is returned if the indices are invalid for the specified
+// pointer type.
+//
+const Type* ExtractValueInst::getIndexedType(const Type *Agg,
+ const unsigned *Idxs,
+ unsigned NumIdx) {
+ unsigned CurIdx = 0;
+ for (; CurIdx != NumIdx; ++CurIdx) {
+ const CompositeType *CT = dyn_cast<CompositeType>(Agg);
+ if (!CT || isa<PointerType>(CT) || isa<VectorType>(CT)) return 0;
+ unsigned Index = Idxs[CurIdx];
+ if (!CT->indexValid(Index)) return 0;
+ Agg = CT->getTypeAtIndex(Index);
+
+ // If the new type forwards to another type, then it is in the middle
+ // of being refined to another type (and hence, may have dropped all
+ // references to what it was using before). So, use the new forwarded
+ // type.
+ if (const Type *Ty = Agg->getForwardedType())
+ Agg = Ty;
+ }
+ return CurIdx == NumIdx ? Agg : 0;
+}
+
+const Type* ExtractValueInst::getIndexedType(const Type *Agg,
+ unsigned Idx) {
+ return getIndexedType(Agg, &Idx, 1);
+}
//===----------------------------------------------------------------------===//
// BinaryOperator Class
BinaryOperator::BinaryOperator(BinaryOps iType, Value *S1, Value *S2,
const Type *Ty, const std::string &Name,
Instruction *InsertBefore)
- : Instruction(Ty, iType, Ops, 2, InsertBefore) {
- Ops[0].init(S1, this);
- Ops[1].init(S2, this);
+ : Instruction(Ty, iType,
+ OperandTraits<BinaryOperator>::op_begin(this),
+ OperandTraits<BinaryOperator>::operands(this),
+ InsertBefore) {
+ Op<0>() = S1;
+ Op<1>() = S2;
init(iType);
setName(Name);
}
BinaryOperator::BinaryOperator(BinaryOps iType, Value *S1, Value *S2,
const Type *Ty, const std::string &Name,
BasicBlock *InsertAtEnd)
- : Instruction(Ty, iType, Ops, 2, InsertAtEnd) {
- Ops[0].init(S1, this);
- Ops[1].init(S2, this);
+ : Instruction(Ty, iType,
+ OperandTraits<BinaryOperator>::op_begin(this),
+ OperandTraits<BinaryOperator>::operands(this),
+ InsertAtEnd) {
+ Op<0>() = S1;
+ Op<1>() = S2;
init(iType);
setName(Name);
}
case AShr:
assert(getType() == LHS->getType() &&
"Shift operation should return same type as operands!");
- assert(getType()->isInteger() &&
- "Shift operation requires integer operands");
+ assert((getType()->isInteger() ||
+ (isa<VectorType>(getType()) &&
+ cast<VectorType>(getType())->getElementType()->isInteger())) &&
+ "Tried to create a shift operation on a non-integral type!");
break;
case And: case Or:
case Xor:
#endif
}
-BinaryOperator *BinaryOperator::create(BinaryOps Op, Value *S1, Value *S2,
+BinaryOperator *BinaryOperator::Create(BinaryOps Op, Value *S1, Value *S2,
const std::string &Name,
Instruction *InsertBefore) {
assert(S1->getType() == S2->getType() &&
return new BinaryOperator(Op, S1, S2, S1->getType(), Name, InsertBefore);
}
-BinaryOperator *BinaryOperator::create(BinaryOps Op, Value *S1, Value *S2,
+BinaryOperator *BinaryOperator::Create(BinaryOps Op, Value *S1, Value *S2,
const std::string &Name,
BasicBlock *InsertAtEnd) {
- BinaryOperator *Res = create(Op, S1, S2, Name);
+ BinaryOperator *Res = Create(Op, S1, S2, Name);
InsertAtEnd->getInstList().push_back(Res);
return Res;
}
-BinaryOperator *BinaryOperator::createNeg(Value *Op, const std::string &Name,
+BinaryOperator *BinaryOperator::CreateNeg(Value *Op, const std::string &Name,
Instruction *InsertBefore) {
Value *zero = ConstantExpr::getZeroValueForNegationExpr(Op->getType());
return new BinaryOperator(Instruction::Sub,
Op->getType(), Name, InsertBefore);
}
-BinaryOperator *BinaryOperator::createNeg(Value *Op, const std::string &Name,
+BinaryOperator *BinaryOperator::CreateNeg(Value *Op, const std::string &Name,
BasicBlock *InsertAtEnd) {
Value *zero = ConstantExpr::getZeroValueForNegationExpr(Op->getType());
return new BinaryOperator(Instruction::Sub,
Op->getType(), Name, InsertAtEnd);
}
-BinaryOperator *BinaryOperator::createNot(Value *Op, const std::string &Name,
+BinaryOperator *BinaryOperator::CreateNot(Value *Op, const std::string &Name,
Instruction *InsertBefore) {
Constant *C;
if (const VectorType *PTy = dyn_cast<VectorType>(Op->getType())) {
Op->getType(), Name, InsertBefore);
}
-BinaryOperator *BinaryOperator::createNot(Value *Op, const std::string &Name,
+BinaryOperator *BinaryOperator::CreateNot(Value *Op, const std::string &Name,
BasicBlock *InsertAtEnd) {
Constant *AllOnes;
if (const VectorType *PTy = dyn_cast<VectorType>(Op->getType())) {
bool BinaryOperator::swapOperands() {
if (!isCommutative())
return true; // Can't commute operands
- std::swap(Ops[0], Ops[1]);
+ Op<0>().swap(Op<1>());
return false;
}
/// changed in order to effect the cast. Essentially, it identifies cases where
/// no code gen is necessary for the cast, hence the name no-op cast. For
/// example, the following are all no-op casts:
-/// # bitcast uint %X, int
-/// # bitcast uint* %x, sbyte*
-/// # bitcast vector< 2 x int > %x, vector< 4 x short>
-/// # ptrtoint uint* %x, uint ; on 32-bit plaforms only
+/// # bitcast i32* %x to i8*
+/// # bitcast <2 x i32> %x to <4 x i16>
+/// # ptrtoint i32* %x to i32 ; on 32-bit plaforms only
/// @brief Determine if a cast is a no-op.
bool CastInst::isNoopCast(const Type *IntPtrTy) const {
switch (getOpcode()) {
return 0;
}
-CastInst *CastInst::create(Instruction::CastOps op, Value *S, const Type *Ty,
+CastInst *CastInst::Create(Instruction::CastOps op, Value *S, const Type *Ty,
const std::string &Name, Instruction *InsertBefore) {
// Construct and return the appropriate CastInst subclass
switch (op) {
return 0;
}
-CastInst *CastInst::create(Instruction::CastOps op, Value *S, const Type *Ty,
+CastInst *CastInst::Create(Instruction::CastOps op, Value *S, const Type *Ty,
const std::string &Name, BasicBlock *InsertAtEnd) {
// Construct and return the appropriate CastInst subclass
switch (op) {
return 0;
}
-CastInst *CastInst::createZExtOrBitCast(Value *S, const Type *Ty,
+CastInst *CastInst::CreateZExtOrBitCast(Value *S, const Type *Ty,
const std::string &Name,
Instruction *InsertBefore) {
if (S->getType()->getPrimitiveSizeInBits() == Ty->getPrimitiveSizeInBits())
- return create(Instruction::BitCast, S, Ty, Name, InsertBefore);
- return create(Instruction::ZExt, S, Ty, Name, InsertBefore);
+ return Create(Instruction::BitCast, S, Ty, Name, InsertBefore);
+ return Create(Instruction::ZExt, S, Ty, Name, InsertBefore);
}
-CastInst *CastInst::createZExtOrBitCast(Value *S, const Type *Ty,
+CastInst *CastInst::CreateZExtOrBitCast(Value *S, const Type *Ty,
const std::string &Name,
BasicBlock *InsertAtEnd) {
if (S->getType()->getPrimitiveSizeInBits() == Ty->getPrimitiveSizeInBits())
- return create(Instruction::BitCast, S, Ty, Name, InsertAtEnd);
- return create(Instruction::ZExt, S, Ty, Name, InsertAtEnd);
+ return Create(Instruction::BitCast, S, Ty, Name, InsertAtEnd);
+ return Create(Instruction::ZExt, S, Ty, Name, InsertAtEnd);
}
-CastInst *CastInst::createSExtOrBitCast(Value *S, const Type *Ty,
+CastInst *CastInst::CreateSExtOrBitCast(Value *S, const Type *Ty,
const std::string &Name,
Instruction *InsertBefore) {
if (S->getType()->getPrimitiveSizeInBits() == Ty->getPrimitiveSizeInBits())
- return create(Instruction::BitCast, S, Ty, Name, InsertBefore);
- return create(Instruction::SExt, S, Ty, Name, InsertBefore);
+ return Create(Instruction::BitCast, S, Ty, Name, InsertBefore);
+ return Create(Instruction::SExt, S, Ty, Name, InsertBefore);
}
-CastInst *CastInst::createSExtOrBitCast(Value *S, const Type *Ty,
+CastInst *CastInst::CreateSExtOrBitCast(Value *S, const Type *Ty,
const std::string &Name,
BasicBlock *InsertAtEnd) {
if (S->getType()->getPrimitiveSizeInBits() == Ty->getPrimitiveSizeInBits())
- return create(Instruction::BitCast, S, Ty, Name, InsertAtEnd);
- return create(Instruction::SExt, S, Ty, Name, InsertAtEnd);
+ return Create(Instruction::BitCast, S, Ty, Name, InsertAtEnd);
+ return Create(Instruction::SExt, S, Ty, Name, InsertAtEnd);
}
-CastInst *CastInst::createTruncOrBitCast(Value *S, const Type *Ty,
+CastInst *CastInst::CreateTruncOrBitCast(Value *S, const Type *Ty,
const std::string &Name,
Instruction *InsertBefore) {
if (S->getType()->getPrimitiveSizeInBits() == Ty->getPrimitiveSizeInBits())
- return create(Instruction::BitCast, S, Ty, Name, InsertBefore);
- return create(Instruction::Trunc, S, Ty, Name, InsertBefore);
+ return Create(Instruction::BitCast, S, Ty, Name, InsertBefore);
+ return Create(Instruction::Trunc, S, Ty, Name, InsertBefore);
}
-CastInst *CastInst::createTruncOrBitCast(Value *S, const Type *Ty,
+CastInst *CastInst::CreateTruncOrBitCast(Value *S, const Type *Ty,
const std::string &Name,
BasicBlock *InsertAtEnd) {
if (S->getType()->getPrimitiveSizeInBits() == Ty->getPrimitiveSizeInBits())
- return create(Instruction::BitCast, S, Ty, Name, InsertAtEnd);
- return create(Instruction::Trunc, S, Ty, Name, InsertAtEnd);
+ return Create(Instruction::BitCast, S, Ty, Name, InsertAtEnd);
+ return Create(Instruction::Trunc, S, Ty, Name, InsertAtEnd);
}
-CastInst *CastInst::createPointerCast(Value *S, const Type *Ty,
+CastInst *CastInst::CreatePointerCast(Value *S, const Type *Ty,
const std::string &Name,
BasicBlock *InsertAtEnd) {
assert(isa<PointerType>(S->getType()) && "Invalid cast");
"Invalid cast");
if (Ty->isInteger())
- return create(Instruction::PtrToInt, S, Ty, Name, InsertAtEnd);
- return create(Instruction::BitCast, S, Ty, Name, InsertAtEnd);
+ return Create(Instruction::PtrToInt, S, Ty, Name, InsertAtEnd);
+ return Create(Instruction::BitCast, S, Ty, Name, InsertAtEnd);
}
/// @brief Create a BitCast or a PtrToInt cast instruction
-CastInst *CastInst::createPointerCast(Value *S, const Type *Ty,
+CastInst *CastInst::CreatePointerCast(Value *S, const Type *Ty,
const std::string &Name,
Instruction *InsertBefore) {
assert(isa<PointerType>(S->getType()) && "Invalid cast");
"Invalid cast");
if (Ty->isInteger())
- return create(Instruction::PtrToInt, S, Ty, Name, InsertBefore);
- return create(Instruction::BitCast, S, Ty, Name, InsertBefore);
+ return Create(Instruction::PtrToInt, S, Ty, Name, InsertBefore);
+ return Create(Instruction::BitCast, S, Ty, Name, InsertBefore);
}
-CastInst *CastInst::createIntegerCast(Value *C, const Type *Ty,
+CastInst *CastInst::CreateIntegerCast(Value *C, const Type *Ty,
bool isSigned, const std::string &Name,
Instruction *InsertBefore) {
assert(C->getType()->isInteger() && Ty->isInteger() && "Invalid cast");
(SrcBits == DstBits ? Instruction::BitCast :
(SrcBits > DstBits ? Instruction::Trunc :
(isSigned ? Instruction::SExt : Instruction::ZExt)));
- return create(opcode, C, Ty, Name, InsertBefore);
+ return Create(opcode, C, Ty, Name, InsertBefore);
}
-CastInst *CastInst::createIntegerCast(Value *C, const Type *Ty,
+CastInst *CastInst::CreateIntegerCast(Value *C, const Type *Ty,
bool isSigned, const std::string &Name,
BasicBlock *InsertAtEnd) {
assert(C->getType()->isInteger() && Ty->isInteger() && "Invalid cast");
(SrcBits == DstBits ? Instruction::BitCast :
(SrcBits > DstBits ? Instruction::Trunc :
(isSigned ? Instruction::SExt : Instruction::ZExt)));
- return create(opcode, C, Ty, Name, InsertAtEnd);
+ return Create(opcode, C, Ty, Name, InsertAtEnd);
}
-CastInst *CastInst::createFPCast(Value *C, const Type *Ty,
+CastInst *CastInst::CreateFPCast(Value *C, const Type *Ty,
const std::string &Name,
Instruction *InsertBefore) {
assert(C->getType()->isFloatingPoint() && Ty->isFloatingPoint() &&
Instruction::CastOps opcode =
(SrcBits == DstBits ? Instruction::BitCast :
(SrcBits > DstBits ? Instruction::FPTrunc : Instruction::FPExt));
- return create(opcode, C, Ty, Name, InsertBefore);
+ return Create(opcode, C, Ty, Name, InsertBefore);
}
-CastInst *CastInst::createFPCast(Value *C, const Type *Ty,
+CastInst *CastInst::CreateFPCast(Value *C, const Type *Ty,
const std::string &Name,
BasicBlock *InsertAtEnd) {
assert(C->getType()->isFloatingPoint() && Ty->isFloatingPoint() &&
Instruction::CastOps opcode =
(SrcBits == DstBits ? Instruction::BitCast :
(SrcBits > DstBits ? Instruction::FPTrunc : Instruction::FPExt));
- return create(opcode, C, Ty, Name, InsertAtEnd);
+ return Create(opcode, C, Ty, Name, InsertAtEnd);
+}
+
+// Check whether it is valid to call getCastOpcode for these types.
+// This routine must be kept in sync with getCastOpcode.
+bool CastInst::isCastable(const Type *SrcTy, const Type *DestTy) {
+ if (!SrcTy->isFirstClassType() || !DestTy->isFirstClassType())
+ return false;
+
+ if (SrcTy == DestTy)
+ return true;
+
+ // Get the bit sizes, we'll need these
+ unsigned SrcBits = SrcTy->getPrimitiveSizeInBits(); // 0 for ptr/vector
+ unsigned DestBits = DestTy->getPrimitiveSizeInBits(); // 0 for ptr/vector
+
+ // Run through the possibilities ...
+ if (DestTy->isInteger()) { // Casting to integral
+ if (SrcTy->isInteger()) { // Casting from integral
+ return true;
+ } else if (SrcTy->isFloatingPoint()) { // Casting from floating pt
+ return true;
+ } else if (const VectorType *PTy = dyn_cast<VectorType>(SrcTy)) {
+ // Casting from vector
+ return DestBits == PTy->getBitWidth();
+ } else { // Casting from something else
+ return isa<PointerType>(SrcTy);
+ }
+ } else if (DestTy->isFloatingPoint()) { // Casting to floating pt
+ if (SrcTy->isInteger()) { // Casting from integral
+ return true;
+ } else if (SrcTy->isFloatingPoint()) { // Casting from floating pt
+ return true;
+ } else if (const VectorType *PTy = dyn_cast<VectorType>(SrcTy)) {
+ // Casting from vector
+ return DestBits == PTy->getBitWidth();
+ } else { // Casting from something else
+ return false;
+ }
+ } else if (const VectorType *DestPTy = dyn_cast<VectorType>(DestTy)) {
+ // Casting to vector
+ if (const VectorType *SrcPTy = dyn_cast<VectorType>(SrcTy)) {
+ // Casting from vector
+ return DestPTy->getBitWidth() == SrcPTy->getBitWidth();
+ } else { // Casting from something else
+ return DestPTy->getBitWidth() == SrcBits;
+ }
+ } else if (isa<PointerType>(DestTy)) { // Casting to pointer
+ if (isa<PointerType>(SrcTy)) { // Casting from pointer
+ return true;
+ } else if (SrcTy->isInteger()) { // Casting from integral
+ return true;
+ } else { // Casting from something else
+ return false;
+ }
+ } else { // Casting to something else
+ return false;
+ }
}
// Provide a way to get a "cast" where the cast opcode is inferred from the
// castIsValid( getCastOpcode(Val, Ty), Val, Ty)
// should not assert in castIsValid. In other words, this produces a "correct"
// casting opcode for the arguments passed to it.
+// This routine must be kept in sync with isCastable.
Instruction::CastOps
CastInst::getCastOpcode(
const Value *Src, bool SrcIsSigned, const Type *DestTy, bool DestIsSigned) {
unsigned SrcBits = SrcTy->getPrimitiveSizeInBits(); // 0 for ptr/vector
unsigned DestBits = DestTy->getPrimitiveSizeInBits(); // 0 for ptr/vector
+ assert(SrcTy->isFirstClassType() && DestTy->isFirstClassType() &&
+ "Only first class types are castable!");
+
// Run through the possibilities ...
if (DestTy->isInteger()) { // Casting to integral
if (SrcTy->isInteger()) { // Casting from integral
switch (op) {
default: return false; // This is an input error
case Instruction::Trunc:
- return SrcTy->isInteger() && DstTy->isInteger()&& SrcBitSize > DstBitSize;
+ return SrcTy->isIntOrIntVector() &&
+ DstTy->isIntOrIntVector()&& SrcBitSize > DstBitSize;
case Instruction::ZExt:
- return SrcTy->isInteger() && DstTy->isInteger()&& SrcBitSize < DstBitSize;
+ return SrcTy->isIntOrIntVector() &&
+ DstTy->isIntOrIntVector()&& SrcBitSize < DstBitSize;
case Instruction::SExt:
- return SrcTy->isInteger() && DstTy->isInteger()&& SrcBitSize < DstBitSize;
+ return SrcTy->isIntOrIntVector() &&
+ DstTy->isIntOrIntVector()&& SrcBitSize < DstBitSize;
case Instruction::FPTrunc:
- return SrcTy->isFloatingPoint() && DstTy->isFloatingPoint() &&
- SrcBitSize > DstBitSize;
+ return SrcTy->isFPOrFPVector() &&
+ DstTy->isFPOrFPVector() &&
+ SrcBitSize > DstBitSize;
case Instruction::FPExt:
- return SrcTy->isFloatingPoint() && DstTy->isFloatingPoint() &&
- SrcBitSize < DstBitSize;
+ return SrcTy->isFPOrFPVector() &&
+ DstTy->isFPOrFPVector() &&
+ SrcBitSize < DstBitSize;
case Instruction::UIToFP:
case Instruction::SIToFP:
if (const VectorType *SVTy = dyn_cast<VectorType>(SrcTy)) {
if (const VectorType *DVTy = dyn_cast<VectorType>(DstTy)) {
- return SVTy->getElementType()->isInteger() &&
- DVTy->getElementType()->isFloatingPoint() &&
+ return SVTy->getElementType()->isIntOrIntVector() &&
+ DVTy->getElementType()->isFPOrFPVector() &&
SVTy->getNumElements() == DVTy->getNumElements();
}
}
- return SrcTy->isInteger() && DstTy->isFloatingPoint();
+ return SrcTy->isIntOrIntVector() && DstTy->isFPOrFPVector();
case Instruction::FPToUI:
case Instruction::FPToSI:
if (const VectorType *SVTy = dyn_cast<VectorType>(SrcTy)) {
if (const VectorType *DVTy = dyn_cast<VectorType>(DstTy)) {
- return SVTy->getElementType()->isFloatingPoint() &&
- DVTy->getElementType()->isInteger() &&
+ return SVTy->getElementType()->isFPOrFPVector() &&
+ DVTy->getElementType()->isIntOrIntVector() &&
SVTy->getNumElements() == DVTy->getNumElements();
}
}
- return SrcTy->isFloatingPoint() && DstTy->isInteger();
+ return SrcTy->isFPOrFPVector() && DstTy->isIntOrIntVector();
case Instruction::PtrToInt:
return isa<PointerType>(SrcTy) && DstTy->isInteger();
case Instruction::IntToPtr:
if (isa<PointerType>(SrcTy) != isa<PointerType>(DstTy))
return false;
- // Now we know we're not dealing with a pointer/non-poiner mismatch. In all
+ // Now we know we're not dealing with a pointer/non-pointer mismatch. In all
// these cases, the cast is okay if the source and destination bit widths
// are identical.
return SrcBitSize == DstBitSize;
// CmpInst Classes
//===----------------------------------------------------------------------===//
-CmpInst::CmpInst(OtherOps op, unsigned short predicate, Value *LHS, Value *RHS,
- const std::string &Name, Instruction *InsertBefore)
- : Instruction(Type::Int1Ty, op, Ops, 2, InsertBefore) {
- Ops[0].init(LHS, this);
- Ops[1].init(RHS, this);
+CmpInst::CmpInst(const Type *ty, OtherOps op, unsigned short predicate,
+ Value *LHS, Value *RHS, const std::string &Name,
+ Instruction *InsertBefore)
+ : Instruction(ty, op,
+ OperandTraits<CmpInst>::op_begin(this),
+ OperandTraits<CmpInst>::operands(this),
+ InsertBefore) {
+ Op<0>() = LHS;
+ Op<1>() = RHS;
SubclassData = predicate;
setName(Name);
- if (op == Instruction::ICmp) {
- assert(predicate >= ICmpInst::FIRST_ICMP_PREDICATE &&
- predicate <= ICmpInst::LAST_ICMP_PREDICATE &&
- "Invalid ICmp predicate value");
- const Type* Op0Ty = getOperand(0)->getType();
- const Type* Op1Ty = getOperand(1)->getType();
- assert(Op0Ty == Op1Ty &&
- "Both operands to ICmp instruction are not of the same type!");
- // Check that the operands are the right type
- assert((Op0Ty->isInteger() || isa<PointerType>(Op0Ty)) &&
- "Invalid operand types for ICmp instruction");
- return;
- }
- assert(op == Instruction::FCmp && "Invalid CmpInst opcode");
- assert(predicate <= FCmpInst::LAST_FCMP_PREDICATE &&
- "Invalid FCmp predicate value");
- const Type* Op0Ty = getOperand(0)->getType();
- const Type* Op1Ty = getOperand(1)->getType();
- assert(Op0Ty == Op1Ty &&
- "Both operands to FCmp instruction are not of the same type!");
- // Check that the operands are the right type
- assert(Op0Ty->isFloatingPoint() &&
- "Invalid operand types for FCmp instruction");
}
-
-CmpInst::CmpInst(OtherOps op, unsigned short predicate, Value *LHS, Value *RHS,
- const std::string &Name, BasicBlock *InsertAtEnd)
- : Instruction(Type::Int1Ty, op, Ops, 2, InsertAtEnd) {
- Ops[0].init(LHS, this);
- Ops[1].init(RHS, this);
+
+CmpInst::CmpInst(const Type *ty, OtherOps op, unsigned short predicate,
+ Value *LHS, Value *RHS, const std::string &Name,
+ BasicBlock *InsertAtEnd)
+ : Instruction(ty, op,
+ OperandTraits<CmpInst>::op_begin(this),
+ OperandTraits<CmpInst>::operands(this),
+ InsertAtEnd) {
+ Op<0>() = LHS;
+ Op<1>() = RHS;
SubclassData = predicate;
setName(Name);
- if (op == Instruction::ICmp) {
- assert(predicate >= ICmpInst::FIRST_ICMP_PREDICATE &&
- predicate <= ICmpInst::LAST_ICMP_PREDICATE &&
- "Invalid ICmp predicate value");
-
- const Type* Op0Ty = getOperand(0)->getType();
- const Type* Op1Ty = getOperand(1)->getType();
- assert(Op0Ty == Op1Ty &&
- "Both operands to ICmp instruction are not of the same type!");
- // Check that the operands are the right type
- assert(Op0Ty->isInteger() || isa<PointerType>(Op0Ty) &&
- "Invalid operand types for ICmp instruction");
- return;
- }
- assert(op == Instruction::FCmp && "Invalid CmpInst opcode");
- assert(predicate <= FCmpInst::LAST_FCMP_PREDICATE &&
- "Invalid FCmp predicate value");
- const Type* Op0Ty = getOperand(0)->getType();
- const Type* Op1Ty = getOperand(1)->getType();
- assert(Op0Ty == Op1Ty &&
- "Both operands to FCmp instruction are not of the same type!");
- // Check that the operands are the right type
- assert(Op0Ty->isFloatingPoint() &&
- "Invalid operand types for FCmp instruction");
}
CmpInst *
-CmpInst::create(OtherOps Op, unsigned short predicate, Value *S1, Value *S2,
+CmpInst::Create(OtherOps Op, unsigned short predicate, Value *S1, Value *S2,
const std::string &Name, Instruction *InsertBefore) {
if (Op == Instruction::ICmp) {
- return new ICmpInst(ICmpInst::Predicate(predicate), S1, S2, Name,
+ return new ICmpInst(CmpInst::Predicate(predicate), S1, S2, Name,
InsertBefore);
}
- return new FCmpInst(FCmpInst::Predicate(predicate), S1, S2, Name,
- InsertBefore);
+ if (Op == Instruction::FCmp) {
+ return new FCmpInst(CmpInst::Predicate(predicate), S1, S2, Name,
+ InsertBefore);
+ }
+ if (Op == Instruction::VICmp) {
+ return new VICmpInst(CmpInst::Predicate(predicate), S1, S2, Name,
+ InsertBefore);
+ }
+ return new VFCmpInst(CmpInst::Predicate(predicate), S1, S2, Name,
+ InsertBefore);
}
CmpInst *
-CmpInst::create(OtherOps Op, unsigned short predicate, Value *S1, Value *S2,
+CmpInst::Create(OtherOps Op, unsigned short predicate, Value *S1, Value *S2,
const std::string &Name, BasicBlock *InsertAtEnd) {
if (Op == Instruction::ICmp) {
- return new ICmpInst(ICmpInst::Predicate(predicate), S1, S2, Name,
+ return new ICmpInst(CmpInst::Predicate(predicate), S1, S2, Name,
InsertAtEnd);
}
- return new FCmpInst(FCmpInst::Predicate(predicate), S1, S2, Name,
- InsertAtEnd);
+ if (Op == Instruction::FCmp) {
+ return new FCmpInst(CmpInst::Predicate(predicate), S1, S2, Name,
+ InsertAtEnd);
+ }
+ if (Op == Instruction::VICmp) {
+ return new VICmpInst(CmpInst::Predicate(predicate), S1, S2, Name,
+ InsertAtEnd);
+ }
+ return new VFCmpInst(CmpInst::Predicate(predicate), S1, S2, Name,
+ InsertAtEnd);
}
void CmpInst::swapOperands() {
}
-ICmpInst::Predicate ICmpInst::getInversePredicate(Predicate pred) {
+CmpInst::Predicate CmpInst::getInversePredicate(Predicate pred) {
switch (pred) {
- default:
- assert(!"Unknown icmp predicate!");
+ default: assert(!"Unknown cmp predicate!");
case ICMP_EQ: return ICMP_NE;
case ICMP_NE: return ICMP_EQ;
case ICMP_UGT: return ICMP_ULE;
case ICMP_SLT: return ICMP_SGE;
case ICMP_SGE: return ICMP_SLT;
case ICMP_SLE: return ICMP_SGT;
- }
-}
-ICmpInst::Predicate ICmpInst::getSwappedPredicate(Predicate pred) {
- switch (pred) {
- default: assert(! "Unknown icmp predicate!");
- case ICMP_EQ: case ICMP_NE:
- return pred;
- case ICMP_SGT: return ICMP_SLT;
- case ICMP_SLT: return ICMP_SGT;
- case ICMP_SGE: return ICMP_SLE;
- case ICMP_SLE: return ICMP_SGE;
- case ICMP_UGT: return ICMP_ULT;
- case ICMP_ULT: return ICMP_UGT;
- case ICMP_UGE: return ICMP_ULE;
- case ICMP_ULE: return ICMP_UGE;
+ case FCMP_OEQ: return FCMP_UNE;
+ case FCMP_ONE: return FCMP_UEQ;
+ case FCMP_OGT: return FCMP_ULE;
+ case FCMP_OLT: return FCMP_UGE;
+ case FCMP_OGE: return FCMP_ULT;
+ case FCMP_OLE: return FCMP_UGT;
+ case FCMP_UEQ: return FCMP_ONE;
+ case FCMP_UNE: return FCMP_OEQ;
+ case FCMP_UGT: return FCMP_OLE;
+ case FCMP_ULT: return FCMP_OGE;
+ case FCMP_UGE: return FCMP_OLT;
+ case FCMP_ULE: return FCMP_OGT;
+ case FCMP_ORD: return FCMP_UNO;
+ case FCMP_UNO: return FCMP_ORD;
+ case FCMP_TRUE: return FCMP_FALSE;
+ case FCMP_FALSE: return FCMP_TRUE;
}
}
}
}
+ICmpInst::Predicate ICmpInst::getUnsignedPredicate(Predicate pred) {
+ switch (pred) {
+ default: assert(! "Unknown icmp predicate!");
+ case ICMP_EQ: case ICMP_NE:
+ case ICMP_UGT: case ICMP_ULT: case ICMP_UGE: case ICMP_ULE:
+ return pred;
+ case ICMP_SGT: return ICMP_UGT;
+ case ICMP_SLT: return ICMP_ULT;
+ case ICMP_SGE: return ICMP_UGE;
+ case ICMP_SLE: return ICMP_ULE;
+ }
+}
+
bool ICmpInst::isSignedPredicate(Predicate pred) {
switch (pred) {
default: assert(! "Unknown icmp predicate!");
return ConstantRange(Lower, Upper);
}
-FCmpInst::Predicate FCmpInst::getInversePredicate(Predicate pred) {
- switch (pred) {
- default:
- assert(!"Unknown icmp predicate!");
- case FCMP_OEQ: return FCMP_UNE;
- case FCMP_ONE: return FCMP_UEQ;
- case FCMP_OGT: return FCMP_ULE;
- case FCMP_OLT: return FCMP_UGE;
- case FCMP_OGE: return FCMP_ULT;
- case FCMP_OLE: return FCMP_UGT;
- case FCMP_UEQ: return FCMP_ONE;
- case FCMP_UNE: return FCMP_OEQ;
- case FCMP_UGT: return FCMP_OLE;
- case FCMP_ULT: return FCMP_OGE;
- case FCMP_UGE: return FCMP_OLT;
- case FCMP_ULE: return FCMP_OGT;
- case FCMP_ORD: return FCMP_UNO;
- case FCMP_UNO: return FCMP_ORD;
- case FCMP_TRUE: return FCMP_FALSE;
- case FCMP_FALSE: return FCMP_TRUE;
- }
-}
-
-FCmpInst::Predicate FCmpInst::getSwappedPredicate(Predicate pred) {
+CmpInst::Predicate CmpInst::getSwappedPredicate(Predicate pred) {
switch (pred) {
- default: assert(!"Unknown fcmp predicate!");
+ default: assert(!"Unknown cmp predicate!");
+ case ICMP_EQ: case ICMP_NE:
+ return pred;
+ case ICMP_SGT: return ICMP_SLT;
+ case ICMP_SLT: return ICMP_SGT;
+ case ICMP_SGE: return ICMP_SLE;
+ case ICMP_SLE: return ICMP_SGE;
+ case ICMP_UGT: return ICMP_ULT;
+ case ICMP_ULT: return ICMP_UGT;
+ case ICMP_UGE: return ICMP_ULE;
+ case ICMP_ULE: return ICMP_UGE;
+
case FCMP_FALSE: case FCMP_TRUE:
case FCMP_OEQ: case FCMP_ONE:
case FCMP_UEQ: case FCMP_UNE:
assert(Value && Default);
ReservedSpace = 2+NumCases*2;
NumOperands = 2;
- OperandList = new Use[ReservedSpace];
+ OperandList = allocHungoffUses(ReservedSpace);
- OperandList[0].init(Value, this);
- OperandList[1].init(Default, this);
+ OperandList[0] = Value;
+ OperandList[1] = Default;
}
/// SwitchInst ctor - Create a new switch instruction, specifying a value to
SwitchInst::SwitchInst(const SwitchInst &SI)
: TerminatorInst(Type::VoidTy, Instruction::Switch,
- new Use[SI.getNumOperands()], SI.getNumOperands()) {
+ allocHungoffUses(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);
+ OL[i] = InOL[i];
+ OL[i+1] = InOL[i+1];
}
}
SwitchInst::~SwitchInst() {
- delete [] OperandList;
+ dropHungoffUses(OperandList);
}
// 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);
+ OperandList[OpNo] = OnVal;
+ OperandList[OpNo+1] = Dest;
}
/// removeCase - This method removes the specified successor from the switch
/// 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.
+/// of operation. This grows the number of ops by 3 times.
/// 2. If NumOps > NumOperands, reserve space for NumOps operands.
/// 3. If NumOps == NumOperands, trim the reserved space.
///
void SwitchInst::resizeOperands(unsigned NumOps) {
+ unsigned e = getNumOperands();
if (NumOps == 0) {
- NumOps = getNumOperands()/2*6;
+ NumOps = e*3;
} else if (NumOps*2 > NumOperands) {
// No resize needed.
if (ReservedSpace >= NumOps) return;
}
ReservedSpace = NumOps;
- Use *NewOps = new Use[NumOps];
+ Use *NewOps = allocHungoffUses(NumOps);
Use *OldOps = OperandList;
- for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
- NewOps[i].init(OldOps[i], this);
- OldOps[i].set(0);
+ for (unsigned i = 0; i != e; ++i) {
+ NewOps[i] = OldOps[i];
}
- delete [] OldOps;
OperandList = NewOps;
+ if (OldOps) Use::zap(OldOps, OldOps + e, true);
}
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);
+ return new(getNumOperands()) GetElementPtrInst(*this);
}
BinaryOperator *BinaryOperator::clone() const {
- return create(getOpcode(), Ops[0], Ops[1]);
+ return Create(getOpcode(), Op<0>(), Op<1>());
}
FCmpInst* FCmpInst::clone() const {
- return new FCmpInst(getPredicate(), Ops[0], Ops[1]);
+ return new FCmpInst(getPredicate(), Op<0>(), Op<1>());
}
ICmpInst* ICmpInst::clone() const {
- return new ICmpInst(getPredicate(), Ops[0], Ops[1]);
+ return new ICmpInst(getPredicate(), Op<0>(), Op<1>());
+}
+
+VFCmpInst* VFCmpInst::clone() const {
+ return new VFCmpInst(getPredicate(), Op<0>(), Op<1>());
+}
+VICmpInst* VICmpInst::clone() const {
+ return new VICmpInst(getPredicate(), Op<0>(), Op<1>());
}
+ExtractValueInst *ExtractValueInst::clone() const {
+ return new ExtractValueInst(*this);
+}
+InsertValueInst *InsertValueInst::clone() const {
+ return new InsertValueInst(*this);
+}
+
+
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)); }
CastInst *PtrToIntInst::clone() const { return new PtrToIntInst(*this); }
CastInst *IntToPtrInst::clone() const { return new IntToPtrInst(*this); }
CastInst *BitCastInst::clone() const { return new BitCastInst(*this); }
-CallInst *CallInst::clone() const { return new CallInst(*this); }
-SelectInst *SelectInst::clone() const { return new SelectInst(*this); }
+CallInst *CallInst::clone() const {
+ return new(getNumOperands()) CallInst(*this);
+}
+SelectInst *SelectInst::clone() const {
+ return new(getNumOperands()) 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);
+ return InsertElementInst::Create(*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); }
+ReturnInst *ReturnInst::clone() const {
+ return new(getNumOperands()) ReturnInst(*this);
+}
+BranchInst *BranchInst::clone() const {
+ return new(getNumOperands()) BranchInst(*this);
+}
SwitchInst *SwitchInst::clone() const { return new SwitchInst(*this); }
-InvokeInst *InvokeInst::clone() const { return new InvokeInst(*this); }
+InvokeInst *InvokeInst::clone() const {
+ return new(getNumOperands()) InvokeInst(*this);
+}
UnwindInst *UnwindInst::clone() const { return new UnwindInst(); }
UnreachableInst *UnreachableInst::clone() const { return new UnreachableInst();}