bool isExternallyInitialized = false);
~GlobalVariable() override {
- NumOperands = 1; // FIXME: needed by operator delete
+ // FIXME: needed by operator delete
+ setGlobalVariableNumOperands(1);
}
/// Provide fast operand accessors
assert(BB && "PHI node got a null basic block!");
assert(getType() == V->getType() &&
"All operands to PHI node must be the same type as the PHI node!");
- if (NumOperands == ReservedSpace)
+ if (getNumOperands() == ReservedSpace)
growOperands(); // Get more space!
// Initialize some new operands.
- ++NumOperands;
- setIncomingValue(NumOperands - 1, V);
- setIncomingBlock(NumOperands - 1, BB);
+ setNumHungOffUseOperands(getNumOperands() + 1);
+ setIncomingValue(getNumOperands() - 1, V);
+ setIncomingBlock(getNumOperands() - 1, BB);
}
/// removeIncomingValue - Remove an incoming value. This is useful if a
User(Type *ty, unsigned vty, Use *OpList, unsigned NumOps)
: Value(ty, vty) {
setOperandList(OpList);
- NumOperands = NumOps;
+ assert(NumOps < (1u << NumUserOperandsBits) && "Too many operands");
+ NumUserOperands = NumOps;
}
/// \brief Allocate the array of Uses, followed by a pointer
public:
~User() override {
// drop the hung off uses.
- Use::zap(getOperandList(), getOperandList() + NumOperands, HasHungOffUses);
+ Use::zap(getOperandList(), getOperandList() + NumUserOperands,
+ HasHungOffUses);
if (HasHungOffUses) {
setOperandList(nullptr);
// Reset NumOperands so User::operator delete() does the right thing.
- NumOperands = 0;
+ NumUserOperands = 0;
}
}
/// \brief Free memory allocated for User and Use objects.
return LegacyOperandList;
}
Value *getOperand(unsigned i) const {
- assert(i < NumOperands && "getOperand() out of range!");
+ assert(i < NumUserOperands && "getOperand() out of range!");
return getOperandList()[i];
}
void setOperand(unsigned i, Value *Val) {
- assert(i < NumOperands && "setOperand() out of range!");
+ assert(i < NumUserOperands && "setOperand() out of range!");
assert((!isa<Constant>((const Value*)this) ||
isa<GlobalValue>((const Value*)this)) &&
"Cannot mutate a constant with setOperand!");
getOperandList()[i] = Val;
}
const Use &getOperandUse(unsigned i) const {
- assert(i < NumOperands && "getOperandUse() out of range!");
+ assert(i < NumUserOperands && "getOperandUse() out of range!");
return getOperandList()[i];
}
Use &getOperandUse(unsigned i) {
- assert(i < NumOperands && "getOperandUse() out of range!");
+ assert(i < NumUserOperands && "getOperandUse() out of range!");
return getOperandList()[i];
}
- unsigned getNumOperands() const { return NumOperands; }
+ unsigned getNumOperands() const { return NumUserOperands; }
+
+ /// Set the number of operands on a GlobalVariable.
+ ///
+ /// GlobalVariable always allocates space for a single operands, but
+ /// doesn't always use it.
+ ///
+ /// FIXME: As that the number of operands is used to find the start of
+ /// the allocated memory in operator delete, we need to always think we have
+ /// 1 operand before delete.
+ void setGlobalVariableNumOperands(unsigned NumOps) {
+ assert(NumOps <= 1 && "GlobalVariable can only have 0 or 1 operands");
+ NumUserOperands = NumOps;
+ }
+
+ /// \brief Subclasses with hung off uses need to manage the operand count
+ /// themselves. In these instances, the operand count isn't used to find the
+ /// OperandList, so there's no issue in having the operand count change.
+ void setNumHungOffUseOperands(unsigned NumOps) {
+ assert(HasHungOffUses && "Must have hung off uses to use this method");
+ assert(NumOps < (1u << NumUserOperandsBits) && "Too many operands");
+ NumUserOperands = NumOps;
+ }
// ---------------------------------------------------------------------------
// Operand Iterator interface...
inline op_iterator op_begin() { return getOperandList(); }
inline const_op_iterator op_begin() const { return getOperandList(); }
inline op_iterator op_end() {
- return getOperandList() + NumOperands;
+ return getOperandList() + NumUserOperands;
}
inline const_op_iterator op_end() const {
- return getOperandList() + NumOperands;
+ return getOperandList() + NumUserOperands;
}
inline op_range operands() {
return op_range(op_begin(), op_end());
/// This is stored here to save space in User on 64-bit hosts. Since most
/// instances of Value have operands, 32-bit hosts aren't significantly
/// affected.
- unsigned NumOperands : 29;
+ ///
+ /// Note, this should *NOT* be used directly by any class other than User.
+ /// User uses this value to find the Use list.
+ static const unsigned NumUserOperandsBits = 29;
+ unsigned NumUserOperands : 29;
bool IsUsedByMD : 1;
bool HasName : 1;
void GlobalVariable::setInitializer(Constant *InitVal) {
if (!InitVal) {
if (hasInitializer()) {
+ // Note, the num operands is used to compute the offset of the operand, so
+ // the order here matters. Clearing the operand then clearing the num
+ // operands ensures we have the correct offset to the operand.
Op<0>().set(nullptr);
- NumOperands = 0;
+ setGlobalVariableNumOperands(0);
}
} else {
assert(InitVal->getType() == getType()->getElementType() &&
"Initializer type must match GlobalVariable type");
+ // Note, the num operands is used to compute the offset of the operand, so
+ // the order here matters. We need to set num operands to 1 first so that
+ // we get the correct offset to the first operand when we set it.
if (!hasInitializer())
- NumOperands = 1;
+ setGlobalVariableNumOperands(1);
Op<0>().set(InitVal);
}
}
// Nuke the last value.
Op<-1>().set(nullptr);
- --NumOperands;
+ setNumHungOffUseOperands(getNumOperands() - 1);
// If the PHI node is dead, because it has zero entries, nuke it now.
if (getNumOperands() == 0 && DeletePHIIfEmpty) {
void LandingPadInst::init(Value *PersFn, unsigned NumReservedValues,
const Twine &NameStr) {
ReservedSpace = NumReservedValues;
- NumOperands = 1;
+ setNumHungOffUseOperands(1);
allocHungoffUses(ReservedSpace);
Op<0>() = PersFn;
setName(NameStr);
unsigned OpNo = getNumOperands();
growOperands(1);
assert(OpNo < ReservedSpace && "Growing didn't work!");
- ++NumOperands;
+ setNumHungOffUseOperands(getNumOperands() + 1);
getOperandList()[OpNo] = Val;
}
void CallInst::init(FunctionType *FTy, Value *Func, ArrayRef<Value *> Args,
const Twine &NameStr) {
this->FTy = FTy;
- assert(NumOperands == Args.size() + 1 && "NumOperands not set up?");
+ assert(getNumOperands() == Args.size() + 1 && "NumOperands not set up?");
Op<-1>() = Func;
#ifndef NDEBUG
void CallInst::init(Value *Func, const Twine &NameStr) {
FTy =
cast<FunctionType>(cast<PointerType>(Func->getType())->getElementType());
- assert(NumOperands == 1 && "NumOperands not set up?");
+ assert(getNumOperands() == 1 && "NumOperands not set up?");
Op<-1>() = Func;
assert(FTy->getNumParams() == 0 && "Calling a function with bad signature");
const Twine &NameStr) {
this->FTy = FTy;
- assert(NumOperands == 3 + Args.size() && "NumOperands not set up?");
+ assert(getNumOperands() == 3 + Args.size() && "NumOperands not set up?");
Op<-3>() = Fn;
Op<-2>() = IfNormal;
Op<-1>() = IfException;
void GetElementPtrInst::init(Value *Ptr, ArrayRef<Value *> IdxList,
const Twine &Name) {
- assert(NumOperands == 1 + IdxList.size() && "NumOperands not initialized?");
+ assert(getNumOperands() == 1 + IdxList.size() &&
+ "NumOperands not initialized?");
Op<0>() = Ptr;
std::copy(IdxList.begin(), IdxList.end(), op_begin() + 1);
setName(Name);
void InsertValueInst::init(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs,
const Twine &Name) {
- assert(NumOperands == 2 && "NumOperands not initialized?");
+ assert(getNumOperands() == 2 && "NumOperands not initialized?");
// There's no fundamental reason why we require at least one index
// (other than weirdness with &*IdxBegin being invalid; see
//===----------------------------------------------------------------------===//
void ExtractValueInst::init(ArrayRef<unsigned> Idxs, const Twine &Name) {
- assert(NumOperands == 1 && "NumOperands not initialized?");
+ assert(getNumOperands() == 1 && "NumOperands not initialized?");
// There's no fundamental reason why we require at least one index.
// But there's no present need to support it.
void SwitchInst::init(Value *Value, BasicBlock *Default, unsigned NumReserved) {
assert(Value && Default && NumReserved);
ReservedSpace = NumReserved;
- NumOperands = 2;
+ setNumHungOffUseOperands(2);
allocHungoffUses(ReservedSpace);
Op<0>() = Value;
SwitchInst::SwitchInst(const SwitchInst &SI)
: TerminatorInst(SI.getType(), Instruction::Switch, nullptr, 0) {
init(SI.getCondition(), SI.getDefaultDest(), SI.getNumOperands());
- NumOperands = SI.getNumOperands();
+ setNumHungOffUseOperands(SI.getNumOperands());
Use *OL = getOperandList();
const Use *InOL = SI.getOperandList();
for (unsigned i = 2, E = SI.getNumOperands(); i != E; i += 2) {
/// addCase - Add an entry to the switch instruction...
///
void SwitchInst::addCase(ConstantInt *OnVal, BasicBlock *Dest) {
- unsigned NewCaseIdx = getNumCases();
- unsigned OpNo = NumOperands;
+ unsigned NewCaseIdx = getNumCases();
+ unsigned OpNo = getNumOperands();
if (OpNo+2 > ReservedSpace)
growOperands(); // Get more space!
// Initialize some new operands.
assert(OpNo+1 < ReservedSpace && "Growing didn't work!");
- NumOperands = OpNo+2;
+ setNumHungOffUseOperands(OpNo+2);
CaseIt Case(this, NewCaseIdx);
Case.setValue(OnVal);
Case.setSuccessor(Dest);
// Nuke the last value.
OL[NumOps-2].set(nullptr);
OL[NumOps-2+1].set(nullptr);
- NumOperands = NumOps-2;
+ setNumHungOffUseOperands(NumOps-2);
}
/// growOperands - grow operands - This grows the operand list in response
assert(Address && Address->getType()->isPointerTy() &&
"Address of indirectbr must be a pointer");
ReservedSpace = 1+NumDests;
- NumOperands = 1;
+ setNumHungOffUseOperands(1);
allocHungoffUses(ReservedSpace);
Op<0>() = Address;
/// addDestination - Add a destination.
///
void IndirectBrInst::addDestination(BasicBlock *DestBB) {
- unsigned OpNo = NumOperands;
+ unsigned OpNo = getNumOperands();
if (OpNo+1 > ReservedSpace)
growOperands(); // Get more space!
// Initialize some new operands.
assert(OpNo < ReservedSpace && "Growing didn't work!");
- NumOperands = OpNo+1;
+ setNumHungOffUseOperands(OpNo+1);
getOperandList()[OpNo] = DestBB;
}
// Nuke the last value.
OL[NumOps-1].set(nullptr);
- NumOperands = NumOps-1;
+ setNumHungOffUseOperands(NumOps-1);
}
BasicBlock *IndirectBrInst::getSuccessorV(unsigned idx) const {
//===----------------------------------------------------------------------===//
void *User::operator new(size_t s, unsigned Us) {
+ assert(Us < (1u << NumUserOperandsBits) && "Too many operands");
void *Storage = ::operator new(s + sizeof(Use) * Us);
Use *Start = static_cast<Use*>(Storage);
Use *End = Start + Us;
User *Obj = reinterpret_cast<User*>(End);
Obj->setOperandList(Start);
Obj->HasHungOffUses = false;
- Obj->NumOperands = Us;
+ Obj->NumUserOperands = Us;
Use::initTags(Start, End);
return Obj;
}
void User::operator delete(void *Usr) {
User *Start = static_cast<User*>(Usr);
- Use *Storage = static_cast<Use*>(Usr) - Start->NumOperands;
+ Use *Storage = static_cast<Use*>(Usr) - Start->NumUserOperands;
// If there were hung-off uses, they will have been freed already and
// NumOperands reset to 0, so here we just free the User itself.
::operator delete(Storage);
//===----------------------------------------------------------------------===//
// Value Class
//===----------------------------------------------------------------------===//
+const unsigned Value::NumUserOperandsBits;
static inline Type *checkType(Type *Ty) {
assert(Ty && "Value defined with a null type: Error!");
Value::Value(Type *ty, unsigned scid)
: VTy(checkType(ty)), UseList(nullptr), SubclassID(scid),
HasValueHandle(0), SubclassOptionalData(0), SubclassData(0),
- NumOperands(0), IsUsedByMD(false), HasName(false) {
+ NumUserOperands(0), IsUsedByMD(false), HasName(false) {
// FIXME: Why isn't this in the subclass gunk??
// Note, we cannot call isa<CallInst> before the CallInst has been
// constructed.