// Constant Class
//===----------------------------------------------------------------------===//
-// Specialize setName to take care of symbol table majik
-void Constant::setName(const std::string &Name, SymbolTable *ST) {
- assert(ST && "Type::setName - Must provide symbol table argument!");
-
- if (Name.size()) ST->insert(Name, this);
-}
-
void Constant::destroyConstantImpl() {
// When a Constant is destroyed, there may be lingering
// references to the constant by other constants in the constant pool. These
// Normal Constructors
ConstantIntegral::ConstantIntegral(const Type *Ty, uint64_t V)
- : Constant(Ty) {
+ : Constant(Ty, SimpleConstantVal, 0, 0) {
Val.Unsigned = V;
}
ConstantSInt::ConstantSInt(const Type *Ty, int64_t V) : ConstantInt(Ty, V) {
assert(Ty->isInteger() && Ty->isSigned() &&
- "Illegal type for unsigned integer constant!");
+ "Illegal type for signed integer constant!");
assert(isValueValidForType(Ty, V) && "Value too large for type!");
}
assert(isValueValidForType(Ty, V) && "Value too large for type!");
}
-ConstantFP::ConstantFP(const Type *Ty, double V) : Constant(Ty) {
+ConstantFP::ConstantFP(const Type *Ty, double V)
+ : Constant(Ty, SimpleConstantVal, 0, 0) {
assert(isValueValidForType(Ty, V) && "Value too large for type!");
Val = V;
}
ConstantArray::ConstantArray(const ArrayType *T,
- const std::vector<Constant*> &V) : Constant(T) {
- Operands.reserve(V.size());
+ const std::vector<Constant*> &V)
+ : Constant(T, SimpleConstantVal, new Use[V.size()], V.size()) {
+ assert(V.size() == T->getNumElements() &&
+ "Invalid initializer vector for constant array");
+ Use *OL = OperandList;
for (unsigned i = 0, e = V.size(); i != e; ++i) {
- assert(V[i]->getType() == T->getElementType() ||
- (T->isAbstract() &&
- V[i]->getType()->getTypeID() == T->getElementType()->getTypeID()));
- Operands.push_back(Use(V[i], this));
+ assert((V[i]->getType() == T->getElementType() ||
+ (T->isAbstract() &&
+ V[i]->getType()->getTypeID()==T->getElementType()->getTypeID())) &&
+ "Initializer for array element doesn't match array element type!");
+ OL[i].init(V[i], this);
}
}
+ConstantArray::~ConstantArray() {
+ delete [] OperandList;
+}
+
ConstantStruct::ConstantStruct(const StructType *T,
- const std::vector<Constant*> &V) : Constant(T) {
+ const std::vector<Constant*> &V)
+ : Constant(T, SimpleConstantVal, new Use[V.size()], V.size()) {
assert(V.size() == T->getNumElements() &&
"Invalid initializer vector for constant structure");
- Operands.reserve(V.size());
+ Use *OL = OperandList;
for (unsigned i = 0, e = V.size(); i != e; ++i) {
assert((V[i]->getType() == T->getElementType(i) ||
((T->getElementType(i)->isAbstract() ||
V[i]->getType()->isAbstract()) &&
- T->getElementType(i)->getTypeID() == V[i]->getType()->getTypeID())) &&
+ T->getElementType(i)->getTypeID()==V[i]->getType()->getTypeID()))&&
"Initializer for struct element doesn't match struct element type!");
- Operands.push_back(Use(V[i], this));
+ OL[i].init(V[i], this);
}
}
+ConstantStruct::~ConstantStruct() {
+ delete [] OperandList;
+}
+
+
ConstantPacked::ConstantPacked(const PackedType *T,
- const std::vector<Constant*> &V) : Constant(T) {
- Operands.reserve(V.size());
+ const std::vector<Constant*> &V)
+ : Constant(T, SimpleConstantVal, new Use[V.size()], V.size()) {
+ Use *OL = OperandList;
for (unsigned i = 0, e = V.size(); i != e; ++i) {
- assert(V[i]->getType() == T->getElementType() ||
- (T->isAbstract() &&
- V[i]->getType()->getTypeID() == T->getElementType()->getTypeID()));
- Operands.push_back(Use(V[i], this));
+ assert((V[i]->getType() == T->getElementType() ||
+ (T->isAbstract() &&
+ V[i]->getType()->getTypeID()==T->getElementType()->getTypeID())) &&
+ "Initializer for packed element doesn't match packed element type!");
+ OL[i].init(V[i], this);
}
}
-ConstantExpr::ConstantExpr(unsigned Opcode, Constant *C, const Type *Ty)
- : Constant(Ty, ConstantExprVal), iType(Opcode) {
- Operands.reserve(1);
- Operands.push_back(Use(C, this));
-}
-
-// Select instruction creation ctor
-ConstantExpr::ConstantExpr(Constant *C, Constant *V1, Constant *V2)
- : Constant(V1->getType(), ConstantExprVal), iType(Instruction::Select) {
- Operands.reserve(3);
- Operands.push_back(Use(C, this));
- Operands.push_back(Use(V1, this));
- Operands.push_back(Use(V2, this));
+ConstantPacked::~ConstantPacked() {
+ delete [] OperandList;
}
+/// UnaryConstantExpr - This class is private to Constants.cpp, and is used
+/// behind the scenes to implement unary constant exprs.
+class UnaryConstantExpr : public ConstantExpr {
+ Use Op;
+public:
+ UnaryConstantExpr(unsigned Opcode, Constant *C, const Type *Ty)
+ : ConstantExpr(Ty, Opcode, &Op, 1), Op(C, this) {}
+};
static bool isSetCC(unsigned Opcode) {
return Opcode == Instruction::SetEQ || Opcode == Instruction::SetNE ||
Opcode == Instruction::SetLE || Opcode == Instruction::SetGE;
}
-ConstantExpr::ConstantExpr(unsigned Opcode, Constant *C1, Constant *C2)
- : Constant(isSetCC(Opcode) ? Type::BoolTy : C1->getType(), ConstantExprVal),
- iType(Opcode) {
- Operands.reserve(2);
- Operands.push_back(Use(C1, this));
- Operands.push_back(Use(C2, this));
-}
+/// BinaryConstantExpr - This class is private to Constants.cpp, and is used
+/// behind the scenes to implement binary constant exprs.
+class BinaryConstantExpr : public ConstantExpr {
+ Use Ops[2];
+public:
+ BinaryConstantExpr(unsigned Opcode, Constant *C1, Constant *C2)
+ : ConstantExpr(isSetCC(Opcode) ? Type::BoolTy : C1->getType(),
+ Opcode, Ops, 2) {
+ Ops[0].init(C1, this);
+ Ops[1].init(C2, this);
+ }
+};
-ConstantExpr::ConstantExpr(Constant *C, const std::vector<Constant*> &IdxList,
- const Type *DestTy)
- : Constant(DestTy, ConstantExprVal), iType(Instruction::GetElementPtr) {
- Operands.reserve(1+IdxList.size());
- Operands.push_back(Use(C, this));
- for (unsigned i = 0, E = IdxList.size(); i != E; ++i)
- Operands.push_back(Use(IdxList[i], this));
-}
+/// SelectConstantExpr - This class is private to Constants.cpp, and is used
+/// behind the scenes to implement select constant exprs.
+class SelectConstantExpr : public ConstantExpr {
+ Use Ops[3];
+public:
+ SelectConstantExpr(Constant *C1, Constant *C2, Constant *C3)
+ : ConstantExpr(C2->getType(), Instruction::Select, Ops, 3) {
+ Ops[0].init(C1, this);
+ Ops[1].init(C2, this);
+ Ops[2].init(C3, this);
+ }
+};
+
+/// GetElementPtrConstantExpr - This class is private to Constants.cpp, and is
+/// used behind the scenes to implement getelementpr constant exprs.
+struct GetElementPtrConstantExpr : public ConstantExpr {
+ GetElementPtrConstantExpr(Constant *C, const std::vector<Constant*> &IdxList,
+ const Type *DestTy)
+ : ConstantExpr(DestTy, Instruction::GetElementPtr,
+ new Use[IdxList.size()+1], IdxList.size()+1) {
+ OperandList[0].init(C, this);
+ for (unsigned i = 0, E = IdxList.size(); i != E; ++i)
+ OperandList[i+1].init(IdxList[i], this);
+ }
+ ~GetElementPtrConstantExpr() {
+ delete [] OperandList;
+ }
+};
/// ConstantExpr::get* - Return some common constants without having to
/// specify the full Instruction::OPCODE identifier.
typedef std::map<const TypeClass*, MapIterator> AbstractTypeMapTy;
AbstractTypeMapTy AbstractTypeMap;
+
+ friend void Constant::clearAllValueMaps();
+ private:
+ void clear(std::vector<Constant *> &Constants) {
+ for(MapIterator I = Map.begin(); I != Map.end(); ++I)
+ Constants.push_back(I->second);
+ Map.clear();
+ AbstractTypeMap.clear();
+ }
+
public:
// getOrCreate - Return the specified constant from the map, creating it if
// necessary.
}
+//---- UndefValue::get() implementation...
+//
+
+namespace llvm {
+ // UndefValue does not take extra "value" argument...
+ template<class ValType>
+ struct ConstantCreator<UndefValue, Type, ValType> {
+ static UndefValue *create(const Type *Ty, const ValType &V) {
+ return new UndefValue(Ty);
+ }
+ };
+
+ template<>
+ struct ConvertConstantType<UndefValue, Type> {
+ static void convert(UndefValue *OldC, const Type *NewTy) {
+ // Make everyone now use a constant of the new type.
+ Constant *New = UndefValue::get(NewTy);
+ assert(New != OldC && "Didn't replace constant??");
+ OldC->uncheckedReplaceAllUsesWith(New);
+ OldC->destroyConstant(); // This constant is now dead, destroy it.
+ }
+ };
+}
+
+static ValueMap<char, Type, UndefValue> UndefValueConstants;
+
+static char getValType(UndefValue *) {
+ return 0;
+}
+
+
+UndefValue *UndefValue::get(const Type *Ty) {
+ return UndefValueConstants.getOrCreate(Ty, 0);
+}
+
+// destroyConstant - Remove the constant from the constant table.
+//
+void UndefValue::destroyConstant() {
+ UndefValueConstants.remove(this);
+ destroyConstantImpl();
+}
+
+
+
+
//---- ConstantExpr::get() implementations...
//
typedef std::pair<unsigned, std::vector<Constant*> > ExprMapKeyType;
struct ConstantCreator<ConstantExpr, Type, ExprMapKeyType> {
static ConstantExpr *create(const Type *Ty, const ExprMapKeyType &V) {
if (V.first == Instruction::Cast)
- return new ConstantExpr(Instruction::Cast, V.second[0], Ty);
+ return new UnaryConstantExpr(Instruction::Cast, V.second[0], Ty);
if ((V.first >= Instruction::BinaryOpsBegin &&
V.first < Instruction::BinaryOpsEnd) ||
V.first == Instruction::Shl || V.first == Instruction::Shr)
- return new ConstantExpr(V.first, V.second[0], V.second[1]);
+ return new BinaryConstantExpr(V.first, V.second[0], V.second[1]);
if (V.first == Instruction::Select)
- return new ConstantExpr(V.second[0], V.second[1], V.second[2]);
+ return new SelectConstantExpr(V.second[0], V.second[1], V.second[2]);
assert(V.first == Instruction::GetElementPtr && "Invalid ConstantExpr!");
std::vector<Constant*> IdxList(V.second.begin()+1, V.second.end());
- return new ConstantExpr(V.second[0], IdxList, Ty);
+ return new GetElementPtrConstantExpr(V.second[0], IdxList, Ty);
}
};
break;
case Instruction::GetElementPtr:
// Make everyone now use a constant of the new type...
- std::vector<Constant*> C;
- for (unsigned i = 1, e = OldC->getNumOperands(); i != e; ++i)
- C.push_back(cast<Constant>(OldC->getOperand(i)));
- New = ConstantExpr::getGetElementPtrTy(NewTy, OldC->getOperand(0), C);
+ std::vector<Value*> Idx(OldC->op_begin()+1, OldC->op_end());
+ New = ConstantExpr::getGetElementPtrTy(NewTy, OldC->getOperand(0), Idx);
break;
}
}
Constant *ConstantExpr::getSignExtend(Constant *C, const Type *Ty) {
- assert(C->getType()->isInteger() && Ty->isInteger() &&
+ assert(C->getType()->isIntegral() && Ty->isIntegral() &&
C->getType()->getPrimitiveSize() <= Ty->getPrimitiveSize() &&
"This is an illegal sign extension!");
- C = ConstantExpr::getCast(C, C->getType()->getSignedVersion());
- return ConstantExpr::getCast(C, Ty);
+ if (C->getType() != Type::BoolTy) {
+ C = ConstantExpr::getCast(C, C->getType()->getSignedVersion());
+ return ConstantExpr::getCast(C, Ty);
+ } else {
+ if (C == ConstantBool::True)
+ return ConstantIntegral::getAllOnesValue(Ty);
+ else
+ return ConstantIntegral::getNullValue(Ty);
+ }
}
Constant *ConstantExpr::getZeroExtend(Constant *C, const Type *Ty) {
- assert(C->getType()->isInteger() && Ty->isInteger() &&
+ assert(C->getType()->isIntegral() && Ty->isIntegral() &&
C->getType()->getPrimitiveSize() <= Ty->getPrimitiveSize() &&
"This is an illegal zero extension!");
- C = ConstantExpr::getCast(C, C->getType()->getUnsignedVersion());
+ if (C->getType() != Type::BoolTy)
+ C = ConstantExpr::getCast(C, C->getType()->getUnsignedVersion());
return ConstantExpr::getCast(C, Ty);
}
+Constant *ConstantExpr::getSizeOf(const Type *Ty) {
+ // sizeof is implemented as: (ulong) gep (Ty*)null, 1
+ return getCast(
+ getGetElementPtr(getNullValue(PointerType::get(Ty)),
+ std::vector<Constant*>(1, ConstantInt::get(Type::UIntTy, 1))),
+ Type::ULongTy);
+}
+
+Constant *ConstantExpr::getPtrPtrFromArrayPtr(Constant *C) {
+ // pointer from array is implemented as: getelementptr arr ptr, 0, 0
+ static std::vector<Constant*> Indices(2, ConstantUInt::get(Type::UIntTy, 0));
+
+ return ConstantExpr::getGetElementPtr(C, Indices);
+}
+
Constant *ConstantExpr::getTy(const Type *ReqTy, unsigned Opcode,
Constant *C1, Constant *C2) {
if (Opcode == Instruction::Shl || Opcode == Instruction::Shr)
case Instruction::Xor:
assert(C1->getType() == C2->getType() && "Op types should be identical!");
assert(C1->getType()->isIntegral() &&
- "Tried to create an logical operation on a non-integral type!");
+ "Tried to create a logical operation on a non-integral type!");
break;
case Instruction::SetLT: case Instruction::SetGT: case Instruction::SetLE:
case Instruction::SetGE: case Instruction::SetEQ: case Instruction::SetNE:
Constant *ConstantExpr::getGetElementPtrTy(const Type *ReqTy, Constant *C,
- const std::vector<Constant*> &IdxList) {
- assert(GetElementPtrInst::getIndexedType(C->getType(),
- std::vector<Value*>(IdxList.begin(), IdxList.end()), true) &&
+ const std::vector<Value*> &IdxList) {
+ assert(GetElementPtrInst::getIndexedType(C->getType(), IdxList, true) &&
"GEP indices invalid!");
if (Constant *FC = ConstantFoldGetElementPtr(C, IdxList))
assert(isa<PointerType>(C->getType()) &&
"Non-pointer type for constant GetElementPtr expression");
// Look up the constant in the table first to ensure uniqueness
- std::vector<Constant*> argVec(1, C);
- argVec.insert(argVec.end(), IdxList.begin(), IdxList.end());
- const ExprMapKeyType &Key = std::make_pair(Instruction::GetElementPtr,argVec);
+ std::vector<Constant*> ArgVec;
+ ArgVec.reserve(IdxList.size()+1);
+ ArgVec.push_back(C);
+ for (unsigned i = 0, e = IdxList.size(); i != e; ++i)
+ ArgVec.push_back(cast<Constant>(IdxList[i]));
+ const ExprMapKeyType &Key = std::make_pair(Instruction::GetElementPtr,ArgVec);
return ExprConstants.getOrCreate(ReqTy, Key);
}
const Type *Ty = GetElementPtrInst::getIndexedType(C->getType(), VIdxList,
true);
assert(Ty && "GEP indices invalid!");
+ return getGetElementPtrTy(PointerType::get(Ty), C, VIdxList);
+}
+
+Constant *ConstantExpr::getGetElementPtr(Constant *C,
+ const std::vector<Value*> &IdxList) {
+ // Get the result type of the getelementptr!
+ const Type *Ty = GetElementPtrInst::getIndexedType(C->getType(), IdxList,
+ true);
+ assert(Ty && "GEP indices invalid!");
return getGetElementPtrTy(PointerType::get(Ty), C, IdxList);
}
return Instruction::getOpcodeName(getOpcode());
}
+/// clearAllValueMaps - This method frees all internal memory used by the
+/// constant subsystem, which can be used in environments where this memory
+/// is otherwise reported as a leak.
+void Constant::clearAllValueMaps() {
+ std::vector<Constant *> Constants;
+
+ DoubleConstants.clear(Constants);
+ FloatConstants.clear(Constants);
+ SIntConstants.clear(Constants);
+ UIntConstants.clear(Constants);
+ AggZeroConstants.clear(Constants);
+ ArrayConstants.clear(Constants);
+ StructConstants.clear(Constants);
+ PackedConstants.clear(Constants);
+ NullPtrConstants.clear(Constants);
+ UndefValueConstants.clear(Constants);
+ ExprConstants.clear(Constants);
+
+ for (std::vector<Constant *>::iterator I = Constants.begin(),
+ E = Constants.end(); I != E; ++I)
+ (*I)->dropAllReferences();
+ for (std::vector<Constant *>::iterator I = Constants.begin(),
+ E = Constants.end(); I != E; ++I)
+ (*I)->destroyConstantImpl();
+ Constants.clear();
+}