1 //===- ConstantHandling.cpp - Implement ConstantHandling.h ----------------===//
3 // This file implements the various intrinsic operations, on constant values.
5 //===----------------------------------------------------------------------===//
7 #include "llvm/Transforms/Scalar/ConstantHandling.h"
9 AnnotationID ConstRules::AID(AnnotationManager::getID("opt::ConstRules",
12 //===----------------------------------------------------------------------===//
13 // TemplateRules Class
14 //===----------------------------------------------------------------------===//
16 // TemplateRules - Implement a subclass of ConstRules that provides all
17 // operations as noops. All other rules classes inherit from this class so
18 // that if functionality is needed in the future, it can simply be added here
19 // and to ConstRules without changing anything else...
21 // This class also provides subclasses with typesafe implementations of methods
22 // so that don't have to do type casting.
24 template<class ArgType, class SubClassName>
25 class TemplateRules : public ConstRules {
27 //===--------------------------------------------------------------------===//
28 // Redirecting functions that cast to the appropriate types
29 //===--------------------------------------------------------------------===//
31 virtual Constant *op_not(const Constant *V) const {
32 return SubClassName::Not((const ArgType *)V);
36 virtual Constant *add(const Constant *V1,
37 const Constant *V2) const {
38 return SubClassName::Add((const ArgType *)V1, (const ArgType *)V2);
41 virtual Constant *sub(const Constant *V1,
42 const Constant *V2) const {
43 return SubClassName::Sub((const ArgType *)V1, (const ArgType *)V2);
46 virtual Constant *mul(const Constant *V1,
47 const Constant *V2) const {
48 return SubClassName::Mul((const ArgType *)V1, (const ArgType *)V2);
51 virtual ConstantBool *lessthan(const Constant *V1,
52 const Constant *V2) const {
53 return SubClassName::LessThan((const ArgType *)V1, (const ArgType *)V2);
56 // Casting operators. ick
57 virtual ConstantBool *castToBool(const Constant *V) const {
58 return SubClassName::CastToBool((const ArgType*)V);
60 virtual ConstantSInt *castToSByte(const Constant *V) const {
61 return SubClassName::CastToSByte((const ArgType*)V);
63 virtual ConstantUInt *castToUByte(const Constant *V) const {
64 return SubClassName::CastToUByte((const ArgType*)V);
66 virtual ConstantSInt *castToShort(const Constant *V) const {
67 return SubClassName::CastToShort((const ArgType*)V);
69 virtual ConstantUInt *castToUShort(const Constant *V) const {
70 return SubClassName::CastToUShort((const ArgType*)V);
72 virtual ConstantSInt *castToInt(const Constant *V) const {
73 return SubClassName::CastToInt((const ArgType*)V);
75 virtual ConstantUInt *castToUInt(const Constant *V) const {
76 return SubClassName::CastToUInt((const ArgType*)V);
78 virtual ConstantSInt *castToLong(const Constant *V) const {
79 return SubClassName::CastToLong((const ArgType*)V);
81 virtual ConstantUInt *castToULong(const Constant *V) const {
82 return SubClassName::CastToULong((const ArgType*)V);
84 virtual ConstantFP *castToFloat(const Constant *V) const {
85 return SubClassName::CastToFloat((const ArgType*)V);
87 virtual ConstantFP *castToDouble(const Constant *V) const {
88 return SubClassName::CastToDouble((const ArgType*)V);
90 virtual ConstantPointer *castToPointer(const Constant *V,
91 const PointerType *Ty) const {
92 return SubClassName::CastToPointer((const ArgType*)V, Ty);
95 //===--------------------------------------------------------------------===//
96 // Default "noop" implementations
97 //===--------------------------------------------------------------------===//
99 inline static Constant *Not(const ArgType *V) { return 0; }
101 inline static Constant *Add(const ArgType *V1, const ArgType *V2) {
104 inline static Constant *Sub(const ArgType *V1, const ArgType *V2) {
107 inline static Constant *Mul(const ArgType *V1, const ArgType *V2) {
110 inline static ConstantBool *LessThan(const ArgType *V1, const ArgType *V2) {
114 // Casting operators. ick
115 inline static ConstantBool *CastToBool (const Constant *V) { return 0; }
116 inline static ConstantSInt *CastToSByte (const Constant *V) { return 0; }
117 inline static ConstantUInt *CastToUByte (const Constant *V) { return 0; }
118 inline static ConstantSInt *CastToShort (const Constant *V) { return 0; }
119 inline static ConstantUInt *CastToUShort(const Constant *V) { return 0; }
120 inline static ConstantSInt *CastToInt (const Constant *V) { return 0; }
121 inline static ConstantUInt *CastToUInt (const Constant *V) { return 0; }
122 inline static ConstantSInt *CastToLong (const Constant *V) { return 0; }
123 inline static ConstantUInt *CastToULong (const Constant *V) { return 0; }
124 inline static ConstantFP *CastToFloat (const Constant *V) { return 0; }
125 inline static ConstantFP *CastToDouble(const Constant *V) { return 0; }
126 inline static ConstantPointer *CastToPointer(const Constant *,
127 const PointerType *) {return 0;}
132 //===----------------------------------------------------------------------===//
134 //===----------------------------------------------------------------------===//
136 // EmptyRules provides a concrete base class of ConstRules that does nothing
138 struct EmptyRules : public TemplateRules<Constant, EmptyRules> {
143 //===----------------------------------------------------------------------===//
145 //===----------------------------------------------------------------------===//
147 // BoolRules provides a concrete base class of ConstRules for the 'bool' type.
149 struct BoolRules : public TemplateRules<ConstantBool, BoolRules> {
151 inline static Constant *Not(const ConstantBool *V) {
152 return ConstantBool::get(!V->getValue());
155 inline static Constant *Or(const ConstantBool *V1,
156 const ConstantBool *V2) {
157 return ConstantBool::get(V1->getValue() | V2->getValue());
160 inline static Constant *And(const ConstantBool *V1,
161 const ConstantBool *V2) {
162 return ConstantBool::get(V1->getValue() & V2->getValue());
167 //===----------------------------------------------------------------------===//
168 // PointerRules Class
169 //===----------------------------------------------------------------------===//
171 // PointerRules provides a concrete base class of ConstRules for pointer types
173 struct PointerRules : public TemplateRules<ConstantPointer, PointerRules> {
174 inline static ConstantBool *CastToBool (const Constant *V) {
175 if (V->isNullValue()) return ConstantBool::False;
176 return 0; // Can't const prop other types of pointers
178 inline static ConstantSInt *CastToSByte (const Constant *V) {
179 if (V->isNullValue()) return ConstantSInt::get(Type::SByteTy, 0);
180 return 0; // Can't const prop other types of pointers
182 inline static ConstantUInt *CastToUByte (const Constant *V) {
183 if (V->isNullValue()) return ConstantUInt::get(Type::UByteTy, 0);
184 return 0; // Can't const prop other types of pointers
186 inline static ConstantSInt *CastToShort (const Constant *V) {
187 if (V->isNullValue()) return ConstantSInt::get(Type::ShortTy, 0);
188 return 0; // Can't const prop other types of pointers
190 inline static ConstantUInt *CastToUShort(const Constant *V) {
191 if (V->isNullValue()) return ConstantUInt::get(Type::UShortTy, 0);
192 return 0; // Can't const prop other types of pointers
194 inline static ConstantSInt *CastToInt (const Constant *V) {
195 if (V->isNullValue()) return ConstantSInt::get(Type::IntTy, 0);
196 return 0; // Can't const prop other types of pointers
198 inline static ConstantUInt *CastToUInt (const Constant *V) {
199 if (V->isNullValue()) return ConstantUInt::get(Type::UIntTy, 0);
200 return 0; // Can't const prop other types of pointers
202 inline static ConstantSInt *CastToLong (const Constant *V) {
203 if (V->isNullValue()) return ConstantSInt::get(Type::LongTy, 0);
204 return 0; // Can't const prop other types of pointers
206 inline static ConstantUInt *CastToULong (const Constant *V) {
207 if (V->isNullValue()) return ConstantUInt::get(Type::ULongTy, 0);
208 return 0; // Can't const prop other types of pointers
210 inline static ConstantFP *CastToFloat (const Constant *V) {
211 if (V->isNullValue()) return ConstantFP::get(Type::FloatTy, 0);
212 return 0; // Can't const prop other types of pointers
214 inline static ConstantFP *CastToDouble(const Constant *V) {
215 if (V->isNullValue()) return ConstantFP::get(Type::DoubleTy, 0);
216 return 0; // Can't const prop other types of pointers
219 inline static ConstantPointer *CastToPointer(const ConstantPointer *V,
220 const PointerType *PTy) {
221 if (V->isNullValue())
222 return ConstantPointerNull::get(PTy);
223 return 0; // Can't const prop other types of pointers
228 //===----------------------------------------------------------------------===//
230 //===----------------------------------------------------------------------===//
232 // DirectRules provides a concrete base classes of ConstRules for a variety of
233 // different types. This allows the C++ compiler to automatically generate our
234 // constant handling operations in a typesafe and accurate manner.
236 template<class ConstantClass, class BuiltinType, Type **Ty>
238 : public TemplateRules<ConstantClass,
239 DirectRules<ConstantClass, BuiltinType, Ty> > {
241 inline static Constant *Not(const ConstantClass *V) {
242 return ConstantClass::get(*Ty, !(BuiltinType)V->getValue());;
245 inline static Constant *Add(const ConstantClass *V1,
246 const ConstantClass *V2) {
247 BuiltinType Result = (BuiltinType)V1->getValue() +
248 (BuiltinType)V2->getValue();
249 return ConstantClass::get(*Ty, Result);
252 inline static Constant *Sub(const ConstantClass *V1,
253 const ConstantClass *V2) {
254 BuiltinType Result = (BuiltinType)V1->getValue() -
255 (BuiltinType)V2->getValue();
256 return ConstantClass::get(*Ty, Result);
259 inline static Constant *Mul(const ConstantClass *V1,
260 const ConstantClass *V2) {
261 BuiltinType Result = (BuiltinType)V1->getValue() *
262 (BuiltinType)V2->getValue();
263 return ConstantClass::get(*Ty, Result);
266 inline static ConstantBool *LessThan(const ConstantClass *V1,
267 const ConstantClass *V2) {
268 bool Result = (BuiltinType)V1->getValue() < (BuiltinType)V2->getValue();
269 return ConstantBool::get(Result);
272 inline static ConstantPointer *CastToPointer(const ConstantClass *V,
273 const PointerType *PTy) {
274 if (V->isNullValue()) // Is it a FP or Integral null value?
275 return ConstantPointerNull::get(PTy);
276 return 0; // Can't const prop other types of pointers
279 // Casting operators. ick
280 #define DEF_CAST(TYPE, CLASS, CTYPE) \
281 inline static CLASS *CastTo##TYPE (const ConstantClass *V) { \
282 return CLASS::get(Type::TYPE##Ty, (CTYPE)(BuiltinType)V->getValue()); \
285 DEF_CAST(Bool , ConstantBool, bool)
286 DEF_CAST(SByte , ConstantSInt, signed char)
287 DEF_CAST(UByte , ConstantUInt, unsigned char)
288 DEF_CAST(Short , ConstantSInt, signed short)
289 DEF_CAST(UShort, ConstantUInt, unsigned short)
290 DEF_CAST(Int , ConstantSInt, signed int)
291 DEF_CAST(UInt , ConstantUInt, unsigned int)
292 DEF_CAST(Long , ConstantSInt, int64_t)
293 DEF_CAST(ULong , ConstantUInt, uint64_t)
294 DEF_CAST(Float , ConstantFP , float)
295 DEF_CAST(Double, ConstantFP , double)
299 //===----------------------------------------------------------------------===//
300 // DirectRules Subclasses
301 //===----------------------------------------------------------------------===//
303 // Given the DirectRules class we can now implement lots of types with little
304 // code. Thank goodness C++ compilers are great at stomping out layers of
305 // templates... can you imagine having to do this all by hand? (/me is lazy :)
308 // ConstRules::find - Return the constant rules that take care of the specified
311 Annotation *ConstRules::find(AnnotationID AID, const Annotable *TyA, void *) {
312 assert(AID == ConstRules::AID && "Bad annotation for factory!");
313 const Type *Ty = cast<Type>((const Value*)TyA);
315 switch (Ty->getPrimitiveID()) {
316 case Type::BoolTyID: return new BoolRules();
317 case Type::PointerTyID: return new PointerRules();
318 case Type::SByteTyID:
319 return new DirectRules<ConstantSInt, signed char , &Type::SByteTy>();
320 case Type::UByteTyID:
321 return new DirectRules<ConstantUInt, unsigned char , &Type::UByteTy>();
322 case Type::ShortTyID:
323 return new DirectRules<ConstantSInt, signed short, &Type::ShortTy>();
324 case Type::UShortTyID:
325 return new DirectRules<ConstantUInt, unsigned short, &Type::UShortTy>();
327 return new DirectRules<ConstantSInt, signed int , &Type::IntTy>();
329 return new DirectRules<ConstantUInt, unsigned int , &Type::UIntTy>();
331 return new DirectRules<ConstantSInt, int64_t , &Type::LongTy>();
332 case Type::ULongTyID:
333 return new DirectRules<ConstantUInt, uint64_t , &Type::ULongTy>();
334 case Type::FloatTyID:
335 return new DirectRules<ConstantFP , float , &Type::FloatTy>();
336 case Type::DoubleTyID:
337 return new DirectRules<ConstantFP , double , &Type::DoubleTy>();
339 return new EmptyRules();