//
// 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/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
-#include "llvm/ParameterAttributes.h"
+#include "llvm/ParamAttrsList.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 {
+ if (CallInst *CI = dyn_cast<CallInst>(I))
+ return CI->getParamAttrs();
+ else
+ return cast<InvokeInst>(I)->getParamAttrs();
+}
+void CallSite::setParamAttrs(const ParamAttrsList *PAL) {
+ if (CallInst *CI = dyn_cast<CallInst>(I))
+ CI->setParamAttrs(PAL);
+ else
+ cast<InvokeInst>(I)->setParamAttrs(PAL);
+}
+bool CallSite::paramHasAttr(uint16_t i, ParameterAttributes 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();
+}
+bool CallSite::onlyReadsMemory() const {
+ if (CallInst *CI = dyn_cast<CallInst>(I))
+ return CI->onlyReadsMemory();
+ else
+ return cast<InvokeInst>(I)->onlyReadsMemory();
+}
+bool CallSite::doesNotThrow() const {
+ if (CallInst *CI = dyn_cast<CallInst>(I))
+ return CI->doesNotThrow();
+ else
+ return cast<InvokeInst>(I)->doesNotThrow();
+}
+void CallSite::setDoesNotThrow(bool doesNotThrow) {
+ if (CallInst *CI = dyn_cast<CallInst>(I))
+ CI->setDoesNotThrow(doesNotThrow);
+ else
+ cast<InvokeInst>(I)->setDoesNotThrow(doesNotThrow);
+}
//===----------------------------------------------------------------------===//
// TerminatorInst Class
///
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;
- delete ParamAttrs; // FIXME: ParamAttrsList should be uniqued!
+ if (ParamAttrs)
+ ParamAttrs->dropRef();
}
void CallInst::init(Value *Func, Value* const *Params, unsigned NumParams) {
assert(FTy->getNumParams() == 0 && "Calling a function with bad signature");
}
-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);
-}
-
CallInst::CallInst(Value *Func, Value* Actual, const std::string &Name,
Instruction *InsertBefore)
: Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
init(Func, Actual);
setName(Name);
}
-
CallInst::CallInst(Value *Func, const std::string &Name,
Instruction *InsertBefore)
: Instruction(cast<FunctionType>(cast<PointerType>(Func->getType())
CallInst::CallInst(const CallInst &CI)
: Instruction(CI.getType(), Instruction::Call, new Use[CI.getNumOperands()],
- CI.getNumOperands()) {
- ParamAttrs = 0;
+ CI.getNumOperands()),
+ ParamAttrs(0) {
+ setParamAttrs(CI.getParamAttrs());
SubclassData = CI.SubclassData;
Use *OL = OperandList;
Use *InOL = CI.OperandList;
OL[i].init(InOL[i], this);
}
+void CallInst::setParamAttrs(const ParamAttrsList *newAttrs) {
+ if (ParamAttrs == newAttrs)
+ return;
+
+ if (ParamAttrs)
+ ParamAttrs->dropRef();
+
+ if (newAttrs)
+ newAttrs->addRef();
+
+ ParamAttrs = newAttrs;
+}
+
+bool CallInst::paramHasAttr(uint16_t i, ParameterAttributes attr) const {
+ if (ParamAttrs && ParamAttrs->paramHasAttr(i, attr))
+ return true;
+ if (const Function *F = getCalledFunction())
+ return F->paramHasAttr(i, attr);
+ return false;
+}
+
+uint16_t CallInst::getParamAlignment(uint16_t i) const {
+ if (ParamAttrs && ParamAttrs->getParamAlignment(i))
+ return ParamAttrs->getParamAlignment(i);
+ if (const Function *F = getCalledFunction())
+ return F->getParamAlignment(i);
+ return 0;
+}
+
+/// @brief Determine if the call does not access memory.
+bool CallInst::doesNotAccessMemory() const {
+ return paramHasAttr(0, ParamAttr::ReadNone);
+}
+
+/// @brief Determine if the call does not access or only reads memory.
+bool CallInst::onlyReadsMemory() const {
+ return doesNotAccessMemory() || paramHasAttr(0, ParamAttr::ReadOnly);
+}
+
+/// @brief Determine if the call cannot return.
+bool CallInst::doesNotReturn() const {
+ return paramHasAttr(0, ParamAttr::NoReturn);
+}
+
+/// @brief Determine if the call cannot unwind.
+bool CallInst::doesNotThrow() const {
+ return paramHasAttr(0, ParamAttr::NoUnwind);
+}
+
+/// @brief Determine if the call returns a structure.
+bool CallInst::isStructReturn() const {
+ // Be friendly and also check the callee.
+ return paramHasAttr(1, ParamAttr::StructRet);
+}
+
+/// @brief Determine if any call argument is an aggregate passed by value.
+bool CallInst::hasByValArgument() const {
+ if (ParamAttrs && ParamAttrs->hasAttrSomewhere(ParamAttr::ByVal))
+ return true;
+ // Be consistent with other methods and check the callee too.
+ if (const Function *F = getCalledFunction())
+ if (const ParamAttrsList *PAL = F->getParamAttrs())
+ return PAL->hasAttrSomewhere(ParamAttr::ByVal);
+ 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;
- delete ParamAttrs; // FIXME: ParamAttrsList should be uniqued!
+ if (ParamAttrs)
+ ParamAttrs->dropRef();
}
void InvokeInst::init(Value *Fn, BasicBlock *IfNormal, BasicBlock *IfException,
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++) {
}
}
-InvokeInst::InvokeInst(Value *Fn, BasicBlock *IfNormal,
- BasicBlock *IfException,
- Value* const *Args, unsigned NumArgs,
- const std::string &Name, Instruction *InsertBefore)
- : TerminatorInst(cast<FunctionType>(cast<PointerType>(Fn->getType())
- ->getElementType())->getReturnType(),
- Instruction::Invoke, 0, 0, InsertBefore) {
- init(Fn, IfNormal, IfException, Args, NumArgs);
- setName(Name);
-}
-
-InvokeInst::InvokeInst(Value *Fn, BasicBlock *IfNormal,
- BasicBlock *IfException,
- Value* const *Args, unsigned NumArgs,
- const std::string &Name, BasicBlock *InsertAtEnd)
- : TerminatorInst(cast<FunctionType>(cast<PointerType>(Fn->getType())
- ->getElementType())->getReturnType(),
- Instruction::Invoke, 0, 0, InsertAtEnd) {
- init(Fn, IfNormal, IfException, Args, NumArgs);
- setName(Name);
-}
-
InvokeInst::InvokeInst(const InvokeInst &II)
: TerminatorInst(II.getType(), Instruction::Invoke,
- new Use[II.getNumOperands()], II.getNumOperands()) {
- ParamAttrs = 0;
+ new Use[II.getNumOperands()], II.getNumOperands()),
+ ParamAttrs(0) {
+ setParamAttrs(II.getParamAttrs());
SubclassData = II.SubclassData;
Use *OL = OperandList, *InOL = II.OperandList;
for (unsigned i = 0, e = II.getNumOperands(); i != e; ++i)
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))
+ return true;
+ if (const Function *F = getCalledFunction())
+ return F->paramHasAttr(i, attr);
+ return false;
+}
+
+uint16_t InvokeInst::getParamAlignment(uint16_t i) const {
+ if (ParamAttrs && ParamAttrs->getParamAlignment(i))
+ return ParamAttrs->getParamAlignment(i);
+ if (const Function *F = getCalledFunction())
+ return F->getParamAlignment(i);
+ return 0;
+}
+
+/// @brief Determine if the call does not access memory.
+bool InvokeInst::doesNotAccessMemory() const {
+ return paramHasAttr(0, ParamAttr::ReadNone);
+}
+
+/// @brief Determine if the call does not access or only reads memory.
+bool InvokeInst::onlyReadsMemory() const {
+ return doesNotAccessMemory() || paramHasAttr(0, ParamAttr::ReadOnly);
+}
+
+/// @brief Determine if the call cannot return.
+bool InvokeInst::doesNotReturn() const {
+ return paramHasAttr(0, ParamAttr::NoReturn);
+}
+
+/// @brief Determine if the call cannot unwind.
+bool InvokeInst::doesNotThrow() const {
+ return paramHasAttr(0, ParamAttr::NoUnwind);
+}
+
+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);
+}
+
+/// @brief Determine if the call returns a structure.
+bool InvokeInst::isStructReturn() const {
+ // Be friendly and also check the callee.
+ return paramHasAttr(1, ParamAttr::StructRet);
+}
+
//===----------------------------------------------------------------------===//
// ReturnInst Implementation
ReturnInst::ReturnInst(const ReturnInst &RI)
: TerminatorInst(Type::VoidTy, Instruction::Ret,
- &RetVal, RI.getNumOperands()) {
- if (RI.getNumOperands())
- RetVal.init(RI.RetVal, this);
+ OperandList, RI.getNumOperands()) {
+ unsigned N = RI.getNumOperands();
+ Use *OL = OperandList = new Use[N];
+ for (unsigned i = 0; i < N; ++i)
+ OL[i].init(RI.getOperand(i), this);
}
ReturnInst::ReturnInst(Value *retVal, Instruction *InsertBefore)
- : TerminatorInst(Type::VoidTy, Instruction::Ret, &RetVal, 0, InsertBefore) {
+ : TerminatorInst(Type::VoidTy, Instruction::Ret, OperandList, 0, InsertBefore) {
init(retVal);
}
ReturnInst::ReturnInst(Value *retVal, BasicBlock *InsertAtEnd)
- : TerminatorInst(Type::VoidTy, Instruction::Ret, &RetVal, 0, InsertAtEnd) {
+ : TerminatorInst(Type::VoidTy, Instruction::Ret, OperandList, 0, InsertAtEnd) {
init(retVal);
}
ReturnInst::ReturnInst(BasicBlock *InsertAtEnd)
- : TerminatorInst(Type::VoidTy, Instruction::Ret, &RetVal, 0, InsertAtEnd) {
+ : TerminatorInst(Type::VoidTy, Instruction::Ret, OperandList, 0, InsertAtEnd) {
}
-
+ReturnInst::ReturnInst(std::vector<Value *> &retVals, Instruction *InsertBefore)
+ : TerminatorInst(Type::VoidTy, Instruction::Ret, OperandList, retVals.size(), InsertBefore) {
+ init(retVals);
+}
+ReturnInst::ReturnInst(std::vector<Value *> &retVals, BasicBlock *InsertAtEnd)
+ : TerminatorInst(Type::VoidTy, Instruction::Ret, OperandList, retVals.size(), InsertAtEnd) {
+ init(retVals);
+}
+ReturnInst::ReturnInst(std::vector<Value *> &retVals)
+ : TerminatorInst(Type::VoidTy, Instruction::Ret, OperandList, retVals.size()) {
+ init(retVals);
+}
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);
+ Use *OL = OperandList = new Use[1];
+ OL[0].init(retVal, this);
+ }
+}
+
+void ReturnInst::init(std::vector<Value *> &retVals) {
+ if (retVals.empty())
+ return;
+
+ NumOperands = retVals.size();
+ if (NumOperands == 1) {
+ Value *V = retVals[0];
+ if (V->getType() == Type::VoidTy)
+ return;
+ }
+
+ Use *OL = OperandList = new Use[NumOperands];
+ for (unsigned i = 0; i < NumOperands; ++i) {
+ Value *V = retVals[i];
+ assert(!isa<BasicBlock>(V) &&
+ "Cannot return basic block. Probably using the incorrect ctor");
+ OL[i].init(V, this);
}
}
+Value *ReturnInst::getReturnValue(unsigned n) const {
+ if (NumOperands)
+ return OperandList[n];
+ else
+ return 0;
+}
+
unsigned ReturnInst::getNumSuccessorsV() const {
return getNumSuccessors();
}
return 0;
}
+ReturnInst::~ReturnInst() {
+ if (NumOperands)
+ delete [] OperandList;
+}
//===----------------------------------------------------------------------===//
// UnwindInst Implementation
Amt = ConstantInt::get(Type::Int32Ty, 1);
else {
assert(!isa<BasicBlock>(Amt) &&
- "Passed basic block into allocation size parameter! Ue other ctor");
+ "Passed basic block into allocation size parameter! Use other ctor");
assert(Amt->getType() == Type::Int32Ty &&
"Malloc/Allocation array size is not a 32-bit integer!");
}
AllocationInst::AllocationInst(const Type *Ty, Value *ArraySize, unsigned iTy,
unsigned Align, const std::string &Name,
Instruction *InsertBefore)
- : UnaryInstruction(PointerType::get(Ty), iTy, getAISize(ArraySize),
+ : UnaryInstruction(PointerType::getUnqual(Ty), iTy, getAISize(ArraySize),
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,
unsigned Align, const std::string &Name,
BasicBlock *InsertAtEnd)
- : UnaryInstruction(PointerType::get(Ty), iTy, getAISize(ArraySize),
+ : UnaryInstruction(PointerType::getUnqual(Ty), iTy, getAISize(ArraySize),
InsertAtEnd), Alignment(Align) {
assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!");
assert(Ty != Type::VoidTy && "Cannot allocate void!");
setName(Name);
}
+LoadInst::LoadInst(Value *Ptr, const std::string &Name, bool isVolatile,
+ unsigned Align, BasicBlock *InsertAE)
+ : UnaryInstruction(cast<PointerType>(Ptr->getType())->getElementType(),
+ Load, Ptr, InsertAE) {
+ setVolatile(isVolatile);
+ setAlignment(Align);
+ AssertOK();
+ setName(Name);
+}
+
LoadInst::LoadInst(Value *Ptr, const std::string &Name, bool isVolatile,
BasicBlock *InsertAE)
: UnaryInstruction(cast<PointerType>(Ptr->getType())->getElementType(),
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);
+ setVolatile(isVolatile);
+ setAlignment(Align);
+ AssertOK();
+}
+
StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
BasicBlock *InsertAtEnd)
: Instruction(Type::VoidTy, Store, Ops, 2, InsertAtEnd) {
// GetElementPtrInst Implementation
//===----------------------------------------------------------------------===//
-// checkType - Simple wrapper function to give a better assertion failure
-// message on bad indexes for a gep instruction.
-//
-static inline const Type *checkType(const Type *Ty) {
- assert(Ty && "Invalid GetElementPtrInst indices for type!");
- return Ty;
+static unsigned retrieveAddrSpace(const Value *Val) {
+ return cast<PointerType>(Val->getType())->getAddressSpace();
}
void GetElementPtrInst::init(Value *Ptr, Value* const *Idx, unsigned NumIdx) {
OL[i+1].init(Idx[i], this);
}
-void GetElementPtrInst::init(Value *Ptr, Value *Idx0, Value *Idx1) {
- 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[1].init(Idx, this);
}
-
-GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value* const *Idx,
- unsigned NumIdx,
- const std::string &Name, Instruction *InBe)
-: Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(),
- Idx, NumIdx, true))),
- GetElementPtr, 0, 0, InBe) {
- init(Ptr, Idx, NumIdx);
- setName(Name);
-}
-
-GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value* const *Idx,
- unsigned NumIdx,
- const std::string &Name, BasicBlock *IAE)
-: Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(),
- Idx, NumIdx, true))),
- GetElementPtr, 0, 0, IAE) {
- init(Ptr, Idx, NumIdx);
- setName(Name);
-}
-
GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx,
const std::string &Name, Instruction *InBe)
- : Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(),Idx))),
+ : Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(),Idx)),
+ retrieveAddrSpace(Ptr)),
GetElementPtr, 0, 0, InBe) {
init(Ptr, Idx);
setName(Name);
GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx,
const std::string &Name, BasicBlock *IAE)
- : Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(),Idx))),
+ : Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(),Idx)),
+ retrieveAddrSpace(Ptr)),
GetElementPtr, 0, 0, IAE) {
init(Ptr, Idx);
setName(Name);
}
-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, 0, 0, InBe) {
- init(Ptr, Idx0, Idx1);
- setName(Name);
-}
-
-GetElementPtrInst::GetElementPtrInst(Value *Ptr, Value *Idx0, Value *Idx1,
- const std::string &Name, BasicBlock *IAE)
- : Instruction(PointerType::get(checkType(getIndexedType(Ptr->getType(),
- Idx0, Idx1, true))),
- GetElementPtr, 0, 0, IAE) {
- init(Ptr, Idx0, Idx1);
- setName(Name);
-}
-
GetElementPtrInst::~GetElementPtrInst() {
delete[] OperandList;
}
if (!isa<PointerType>(Ptr)) return 0; // Type isn't a pointer type!
// Handle the special case of the empty set index set...
- if (NumIdx == 0)
+ if (NumIdx == 0) {
if (AllowCompositeLeaf ||
cast<PointerType>(Ptr)->getElementType()->isFirstClassType())
return cast<PointerType>(Ptr)->getElementType();
else
return 0;
+ }
unsigned CurIdx = 0;
while (const CompositeType *CT = dyn_cast<CompositeType>(Ptr)) {
return CurIdx == NumIdx ? Ptr : 0;
}
-const Type* GetElementPtrInst::getIndexedType(const Type *Ptr,
- Value *Idx0, Value *Idx1,
- bool AllowCompositeLeaf) {
- const PointerType *PTy = dyn_cast<PointerType>(Ptr);
- if (!PTy) return 0; // Type isn't a pointer type!
-
- // Check the pointer index.
- if (!PTy->indexValid(Idx0)) return 0;
-
- const CompositeType *CT = dyn_cast<CompositeType>(PTy->getElementType());
- if (!CT || !CT->indexValid(Idx1)) return 0;
-
- const Type *ElTy = CT->getTypeAtIndex(Idx1);
- if (AllowCompositeLeaf || ElTy->isFirstClassType())
- return ElTy;
- return 0;
-}
-
const Type* GetElementPtrInst::getIndexedType(const Type *Ptr, Value *Idx) {
const PointerType *PTy = dyn_cast<PointerType>(Ptr);
if (!PTy) return 0; // Type isn't a pointer type!
return true;
}
+/// hasAllConstantIndices - Return true if all of the indices of this GEP are
+/// constant integers. If so, the result pointer and the first operand have
+/// a constant offset between them.
+bool GetElementPtrInst::hasAllConstantIndices() const {
+ for (unsigned i = 1, e = getNumOperands(); i != e; ++i) {
+ if (!isa<ConstantInt>(getOperand(i)))
+ return false;
+ }
+ return true;
+}
+
//===----------------------------------------------------------------------===//
// ExtractElementInst Implementation
return false; // First operand of insertelement must be vector type.
if (Elt->getType() != cast<VectorType>(Vec->getType())->getElementType())
- return false;// Second operand of insertelement must be packed element type.
+ return false;// Second operand of insertelement must be vector element type.
if (Index->getType() != Type::Int32Ty)
return false; // Third operand of insertelement must be uint.
// isConstantAllOnes - Helper function for several functions below
static inline bool isConstantAllOnes(const Value *V) {
- return isa<ConstantInt>(V) &&cast<ConstantInt>(V)->isAllOnesValue();
+ if (const ConstantInt *CI = dyn_cast<ConstantInt>(V))
+ return CI->isAllOnesValue();
+ if (const ConstantVector *CV = dyn_cast<ConstantVector>(V))
+ return CV->isAllOnesValue();
+ return false;
}
bool BinaryOperator::isNeg(const Value *V) {
/// example, the following are all no-op casts:
/// # bitcast uint %X, int
/// # bitcast uint* %x, sbyte*
-/// # bitcast packed< 2 x int > %x, packed< 4 x short>
+/// # bitcast vector< 2 x int > %x, vector< 4 x short>
/// # ptrtoint uint* %x, uint ; on 32-bit plaforms only
/// @brief Determine if a cast is a no-op.
bool CastInst::isNoopCast(const Type *IntPtrTy) const {
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
// types and size of the operand. This, basically, is a parallel of the
// logic in the castIsValid function below. This axiom should hold:
// 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) {
// Get the bit sizes, we'll need these
const Type *SrcTy = Src->getType();
- unsigned SrcBits = SrcTy->getPrimitiveSizeInBits(); // 0 for ptr/packed
- unsigned DestBits = DestTy->getPrimitiveSizeInBits(); // 0 for ptr/packed
+ 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
return FPToUI; // FP -> uint
} else if (const VectorType *PTy = dyn_cast<VectorType>(SrcTy)) {
assert(DestBits == PTy->getBitWidth() &&
- "Casting packed to integer of different width");
+ "Casting vector to integer of different width");
return BitCast; // Same size, no-op cast
} else {
assert(isa<PointerType>(SrcTy) &&
}
} else if (const VectorType *PTy = dyn_cast<VectorType>(SrcTy)) {
assert(DestBits == PTy->getBitWidth() &&
- "Casting packed to floating point of different width");
+ "Casting vector to floating point of different width");
return BitCast; // same size, no-op cast
} else {
assert(0 && "Casting pointer or non-first class to float");
} else if (const VectorType *DestPTy = dyn_cast<VectorType>(DestTy)) {
if (const VectorType *SrcPTy = dyn_cast<VectorType>(SrcTy)) {
assert(DestPTy->getBitWidth() == SrcPTy->getBitWidth() &&
- "Casting packed to packed of different widths");
- return BitCast; // packed -> packed
+ "Casting vector to vector of different widths");
+ return BitCast; // vector -> vector
} else if (DestPTy->getBitWidth() == SrcBits) {
- return BitCast; // float/int -> packed
+ return BitCast; // float/int -> vector
} else {
- assert(!"Illegal cast to packed (wrong type or size)");
+ assert(!"Illegal cast to vector (wrong type or size)");
}
} else if (isa<PointerType>(DestTy)) {
if (isa<PointerType>(SrcTy)) {
return SrcTy->isFloatingPoint() && DstTy->isFloatingPoint() &&
SrcBitSize < DstBitSize;
case Instruction::UIToFP:
- return SrcTy->isInteger() && DstTy->isFloatingPoint();
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() &&
+ SVTy->getNumElements() == DVTy->getNumElements();
+ }
+ }
return SrcTy->isInteger() && DstTy->isFloatingPoint();
case Instruction::FPToUI:
- return SrcTy->isFloatingPoint() && DstTy->isInteger();
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() &&
+ SVTy->getNumElements() == DVTy->getNumElements();
+ }
+ }
return SrcTy->isFloatingPoint() && DstTy->isInteger();
case Instruction::PtrToInt:
return isa<PointerType>(SrcTy) && DstTy->isInteger();
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;
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) &&
+ assert((Op0Ty->isInteger() || isa<PointerType>(Op0Ty)) &&
"Invalid operand types for ICmp instruction");
return;
}
}
}
+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!");
setSuccessor(idx, B);
}
+//===----------------------------------------------------------------------===//
+// GetResultInst Implementation
+//===----------------------------------------------------------------------===//
+
+GetResultInst::GetResultInst(Value *Aggregate, unsigned Index,
+ const std::string &Name,
+ Instruction *InsertBef)
+ : Instruction(cast<StructType>(Aggregate->getType())->getElementType(Index),
+ GetResult, &Aggr, 1, InsertBef) {
+ assert(isValidOperands(Aggregate, Index) && "Invalid GetResultInst operands!");
+ Aggr.init(Aggregate, this);
+ Idx = Index;
+ setName(Name);
+}
+
+bool GetResultInst::isValidOperands(const Value *Aggregate, unsigned Index) {
+ if (!Aggregate)
+ return false;
+
+ if (const StructType *STy = dyn_cast<StructType>(Aggregate->getType())) {
+ unsigned NumElements = STy->getNumElements();
+ if (Index >= NumElements)
+ return false;
+
+ // getresult aggregate value's element types are restricted to
+ // avoid nested aggregates.
+ for (unsigned i = 0; i < NumElements; ++i)
+ if (!STy->getElementType(i)->isFirstClassType())
+ return false;
+
+ // Otherwise, Aggregate is valid.
+ return true;
+ }
+ return false;
+}
// Define these methods here so vtables don't get emitted into every translation
// unit that uses these classes.
return create(getOpcode(), Ops[0], Ops[1]);
}
-CmpInst* CmpInst::clone() const {
- return create(getOpcode(), getPredicate(), Ops[0], Ops[1]);
+FCmpInst* FCmpInst::clone() const {
+ return new FCmpInst(getPredicate(), Ops[0], Ops[1]);
+}
+ICmpInst* ICmpInst::clone() const {
+ return new ICmpInst(getPredicate(), Ops[0], Ops[1]);
}
MallocInst *MallocInst::clone() const { return new MallocInst(*this); }
InvokeInst *InvokeInst::clone() const { return new InvokeInst(*this); }
UnwindInst *UnwindInst::clone() const { return new UnwindInst(); }
UnreachableInst *UnreachableInst::clone() const { return new UnreachableInst();}
+GetResultInst *GetResultInst::clone() const { return new GetResultInst(*this); }