1 //===- ConstantHandling.cpp - Implement ConstantHandling.h ----------------===//
3 // This file implements the various intrinsic operations, on constant values.
5 //===----------------------------------------------------------------------===//
7 #include "llvm/ConstantHandling.h"
10 AnnotationID ConstRules::AID(AnnotationManager::getID("opt::ConstRules",
13 //===----------------------------------------------------------------------===//
14 // TemplateRules Class
15 //===----------------------------------------------------------------------===//
17 // TemplateRules - Implement a subclass of ConstRules that provides all
18 // operations as noops. All other rules classes inherit from this class so
19 // that if functionality is needed in the future, it can simply be added here
20 // and to ConstRules without changing anything else...
22 // This class also provides subclasses with typesafe implementations of methods
23 // so that don't have to do type casting.
25 template<class ArgType, class SubClassName>
26 class TemplateRules : public ConstRules {
28 //===--------------------------------------------------------------------===//
29 // Redirecting functions that cast to the appropriate types
30 //===--------------------------------------------------------------------===//
32 virtual Constant *op_not(const Constant *V) const {
33 return SubClassName::Not((const ArgType *)V);
37 virtual Constant *add(const Constant *V1,
38 const Constant *V2) const {
39 return SubClassName::Add((const ArgType *)V1, (const ArgType *)V2);
42 virtual Constant *sub(const Constant *V1,
43 const Constant *V2) const {
44 return SubClassName::Sub((const ArgType *)V1, (const ArgType *)V2);
47 virtual Constant *mul(const Constant *V1,
48 const Constant *V2) const {
49 return SubClassName::Mul((const ArgType *)V1, (const ArgType *)V2);
51 virtual Constant *div(const Constant *V1,
52 const Constant *V2) const {
53 return SubClassName::Div((const ArgType *)V1, (const ArgType *)V2);
55 virtual Constant *rem(const Constant *V1,
56 const Constant *V2) const {
57 return SubClassName::Rem((const ArgType *)V1, (const ArgType *)V2);
60 virtual ConstantBool *lessthan(const Constant *V1,
61 const Constant *V2) const {
62 return SubClassName::LessThan((const ArgType *)V1, (const ArgType *)V2);
65 // Casting operators. ick
66 virtual ConstantBool *castToBool(const Constant *V) const {
67 return SubClassName::CastToBool((const ArgType*)V);
69 virtual ConstantSInt *castToSByte(const Constant *V) const {
70 return SubClassName::CastToSByte((const ArgType*)V);
72 virtual ConstantUInt *castToUByte(const Constant *V) const {
73 return SubClassName::CastToUByte((const ArgType*)V);
75 virtual ConstantSInt *castToShort(const Constant *V) const {
76 return SubClassName::CastToShort((const ArgType*)V);
78 virtual ConstantUInt *castToUShort(const Constant *V) const {
79 return SubClassName::CastToUShort((const ArgType*)V);
81 virtual ConstantSInt *castToInt(const Constant *V) const {
82 return SubClassName::CastToInt((const ArgType*)V);
84 virtual ConstantUInt *castToUInt(const Constant *V) const {
85 return SubClassName::CastToUInt((const ArgType*)V);
87 virtual ConstantSInt *castToLong(const Constant *V) const {
88 return SubClassName::CastToLong((const ArgType*)V);
90 virtual ConstantUInt *castToULong(const Constant *V) const {
91 return SubClassName::CastToULong((const ArgType*)V);
93 virtual ConstantFP *castToFloat(const Constant *V) const {
94 return SubClassName::CastToFloat((const ArgType*)V);
96 virtual ConstantFP *castToDouble(const Constant *V) const {
97 return SubClassName::CastToDouble((const ArgType*)V);
99 virtual ConstantPointer *castToPointer(const Constant *V,
100 const PointerType *Ty) const {
101 return SubClassName::CastToPointer((const ArgType*)V, Ty);
104 //===--------------------------------------------------------------------===//
105 // Default "noop" implementations
106 //===--------------------------------------------------------------------===//
108 inline static Constant *Not(const ArgType *V) { return 0; }
110 inline static Constant *Add(const ArgType *V1, const ArgType *V2) {
113 inline static Constant *Sub(const ArgType *V1, const ArgType *V2) {
116 inline static Constant *Mul(const ArgType *V1, const ArgType *V2) {
119 inline static Constant *Div(const ArgType *V1, const ArgType *V2) {
122 inline static Constant *Rem(const ArgType *V1, const ArgType *V2) {
125 inline static ConstantBool *LessThan(const ArgType *V1, const ArgType *V2) {
129 // Casting operators. ick
130 inline static ConstantBool *CastToBool (const Constant *V) { return 0; }
131 inline static ConstantSInt *CastToSByte (const Constant *V) { return 0; }
132 inline static ConstantUInt *CastToUByte (const Constant *V) { return 0; }
133 inline static ConstantSInt *CastToShort (const Constant *V) { return 0; }
134 inline static ConstantUInt *CastToUShort(const Constant *V) { return 0; }
135 inline static ConstantSInt *CastToInt (const Constant *V) { return 0; }
136 inline static ConstantUInt *CastToUInt (const Constant *V) { return 0; }
137 inline static ConstantSInt *CastToLong (const Constant *V) { return 0; }
138 inline static ConstantUInt *CastToULong (const Constant *V) { return 0; }
139 inline static ConstantFP *CastToFloat (const Constant *V) { return 0; }
140 inline static ConstantFP *CastToDouble(const Constant *V) { return 0; }
141 inline static ConstantPointer *CastToPointer(const Constant *,
142 const PointerType *) {return 0;}
147 //===----------------------------------------------------------------------===//
149 //===----------------------------------------------------------------------===//
151 // EmptyRules provides a concrete base class of ConstRules that does nothing
153 struct EmptyRules : public TemplateRules<Constant, EmptyRules> {
158 //===----------------------------------------------------------------------===//
160 //===----------------------------------------------------------------------===//
162 // BoolRules provides a concrete base class of ConstRules for the 'bool' type.
164 struct BoolRules : public TemplateRules<ConstantBool, BoolRules> {
166 inline static Constant *Not(const ConstantBool *V) {
167 return ConstantBool::get(!V->getValue());
170 inline static Constant *Or(const ConstantBool *V1,
171 const ConstantBool *V2) {
172 return ConstantBool::get(V1->getValue() | V2->getValue());
175 inline static Constant *And(const ConstantBool *V1,
176 const ConstantBool *V2) {
177 return ConstantBool::get(V1->getValue() & V2->getValue());
182 //===----------------------------------------------------------------------===//
183 // PointerRules Class
184 //===----------------------------------------------------------------------===//
186 // PointerRules provides a concrete base class of ConstRules for pointer types
188 struct PointerRules : public TemplateRules<ConstantPointer, PointerRules> {
189 inline static ConstantBool *CastToBool (const Constant *V) {
190 if (V->isNullValue()) return ConstantBool::False;
191 return 0; // Can't const prop other types of pointers
193 inline static ConstantSInt *CastToSByte (const Constant *V) {
194 if (V->isNullValue()) return ConstantSInt::get(Type::SByteTy, 0);
195 return 0; // Can't const prop other types of pointers
197 inline static ConstantUInt *CastToUByte (const Constant *V) {
198 if (V->isNullValue()) return ConstantUInt::get(Type::UByteTy, 0);
199 return 0; // Can't const prop other types of pointers
201 inline static ConstantSInt *CastToShort (const Constant *V) {
202 if (V->isNullValue()) return ConstantSInt::get(Type::ShortTy, 0);
203 return 0; // Can't const prop other types of pointers
205 inline static ConstantUInt *CastToUShort(const Constant *V) {
206 if (V->isNullValue()) return ConstantUInt::get(Type::UShortTy, 0);
207 return 0; // Can't const prop other types of pointers
209 inline static ConstantSInt *CastToInt (const Constant *V) {
210 if (V->isNullValue()) return ConstantSInt::get(Type::IntTy, 0);
211 return 0; // Can't const prop other types of pointers
213 inline static ConstantUInt *CastToUInt (const Constant *V) {
214 if (V->isNullValue()) return ConstantUInt::get(Type::UIntTy, 0);
215 return 0; // Can't const prop other types of pointers
217 inline static ConstantSInt *CastToLong (const Constant *V) {
218 if (V->isNullValue()) return ConstantSInt::get(Type::LongTy, 0);
219 return 0; // Can't const prop other types of pointers
221 inline static ConstantUInt *CastToULong (const Constant *V) {
222 if (V->isNullValue()) return ConstantUInt::get(Type::ULongTy, 0);
223 return 0; // Can't const prop other types of pointers
225 inline static ConstantFP *CastToFloat (const Constant *V) {
226 if (V->isNullValue()) return ConstantFP::get(Type::FloatTy, 0);
227 return 0; // Can't const prop other types of pointers
229 inline static ConstantFP *CastToDouble(const Constant *V) {
230 if (V->isNullValue()) return ConstantFP::get(Type::DoubleTy, 0);
231 return 0; // Can't const prop other types of pointers
234 inline static ConstantPointer *CastToPointer(const ConstantPointer *V,
235 const PointerType *PTy) {
236 if (V->getType() == PTy)
237 return const_cast<ConstantPointer*>(V); // Allow cast %PTy %ptr to %PTy
238 if (V->isNullValue())
239 return ConstantPointerNull::get(PTy);
240 return 0; // Can't const prop other types of pointers
245 //===----------------------------------------------------------------------===//
247 //===----------------------------------------------------------------------===//
249 // DirectRules provides a concrete base classes of ConstRules for a variety of
250 // different types. This allows the C++ compiler to automatically generate our
251 // constant handling operations in a typesafe and accurate manner.
253 template<class ConstantClass, class BuiltinType, Type **Ty, class SuperClass>
254 struct DirectRules : public TemplateRules<ConstantClass, SuperClass> {
255 inline static Constant *Add(const ConstantClass *V1,
256 const ConstantClass *V2) {
257 BuiltinType Result = (BuiltinType)V1->getValue() +
258 (BuiltinType)V2->getValue();
259 return ConstantClass::get(*Ty, Result);
262 inline static Constant *Sub(const ConstantClass *V1,
263 const ConstantClass *V2) {
264 BuiltinType Result = (BuiltinType)V1->getValue() -
265 (BuiltinType)V2->getValue();
266 return ConstantClass::get(*Ty, Result);
269 inline static Constant *Mul(const ConstantClass *V1,
270 const ConstantClass *V2) {
271 BuiltinType Result = (BuiltinType)V1->getValue() *
272 (BuiltinType)V2->getValue();
273 return ConstantClass::get(*Ty, Result);
276 inline static Constant *Div(const ConstantClass *V1,
277 const ConstantClass *V2) {
278 if (V2->isNullValue()) return 0;
279 BuiltinType Result = (BuiltinType)V1->getValue() /
280 (BuiltinType)V2->getValue();
281 return ConstantClass::get(*Ty, Result);
284 inline static ConstantBool *LessThan(const ConstantClass *V1,
285 const ConstantClass *V2) {
286 bool Result = (BuiltinType)V1->getValue() < (BuiltinType)V2->getValue();
287 return ConstantBool::get(Result);
290 inline static ConstantPointer *CastToPointer(const ConstantClass *V,
291 const PointerType *PTy) {
292 if (V->isNullValue()) // Is it a FP or Integral null value?
293 return ConstantPointerNull::get(PTy);
294 return 0; // Can't const prop other types of pointers
297 // Casting operators. ick
298 #define DEF_CAST(TYPE, CLASS, CTYPE) \
299 inline static CLASS *CastTo##TYPE (const ConstantClass *V) { \
300 return CLASS::get(Type::TYPE##Ty, (CTYPE)(BuiltinType)V->getValue()); \
303 DEF_CAST(Bool , ConstantBool, bool)
304 DEF_CAST(SByte , ConstantSInt, signed char)
305 DEF_CAST(UByte , ConstantUInt, unsigned char)
306 DEF_CAST(Short , ConstantSInt, signed short)
307 DEF_CAST(UShort, ConstantUInt, unsigned short)
308 DEF_CAST(Int , ConstantSInt, signed int)
309 DEF_CAST(UInt , ConstantUInt, unsigned int)
310 DEF_CAST(Long , ConstantSInt, int64_t)
311 DEF_CAST(ULong , ConstantUInt, uint64_t)
312 DEF_CAST(Float , ConstantFP , float)
313 DEF_CAST(Double, ConstantFP , double)
318 //===----------------------------------------------------------------------===//
319 // DirectIntRules Class
320 //===----------------------------------------------------------------------===//
322 // DirectIntRules provides implementations of functions that are valid on
323 // integer types, but not all types in general.
325 template <class ConstantClass, class BuiltinType, Type **Ty>
326 struct DirectIntRules
327 : public DirectRules<ConstantClass, BuiltinType, Ty,
328 DirectIntRules<ConstantClass, BuiltinType, Ty> > {
329 inline static Constant *Not(const ConstantClass *V) {
330 return ConstantClass::get(*Ty, ~(BuiltinType)V->getValue());;
333 inline static Constant *Rem(const ConstantClass *V1,
334 const ConstantClass *V2) {
335 if (V2->isNullValue()) return 0;
336 BuiltinType Result = (BuiltinType)V1->getValue() %
337 (BuiltinType)V2->getValue();
338 return ConstantClass::get(*Ty, Result);
343 //===----------------------------------------------------------------------===//
344 // DirectFPRules Class
345 //===----------------------------------------------------------------------===//
347 // DirectFPRules provides implementations of functions that are valid on
348 // floating point types, but not all types in general.
350 template <class ConstantClass, class BuiltinType, Type **Ty>
352 : public DirectRules<ConstantClass, BuiltinType, Ty,
353 DirectFPRules<ConstantClass, BuiltinType, Ty> > {
354 inline static Constant *Rem(const ConstantClass *V1,
355 const ConstantClass *V2) {
356 if (V2->isNullValue()) return 0;
357 BuiltinType Result = std::fmod((BuiltinType)V1->getValue(),
358 (BuiltinType)V2->getValue());
359 return ConstantClass::get(*Ty, Result);
364 //===----------------------------------------------------------------------===//
365 // DirectRules Subclasses
366 //===----------------------------------------------------------------------===//
368 // Given the DirectRules class we can now implement lots of types with little
369 // code. Thank goodness C++ compilers are great at stomping out layers of
370 // templates... can you imagine having to do this all by hand? (/me is lazy :)
373 // ConstRules::find - Return the constant rules that take care of the specified
376 Annotation *ConstRules::find(AnnotationID AID, const Annotable *TyA, void *) {
377 assert(AID == ConstRules::AID && "Bad annotation for factory!");
378 const Type *Ty = cast<Type>((const Value*)TyA);
380 switch (Ty->getPrimitiveID()) {
381 case Type::BoolTyID: return new BoolRules();
382 case Type::PointerTyID: return new PointerRules();
383 case Type::SByteTyID:
384 return new DirectIntRules<ConstantSInt, signed char , &Type::SByteTy>();
385 case Type::UByteTyID:
386 return new DirectIntRules<ConstantUInt, unsigned char , &Type::UByteTy>();
387 case Type::ShortTyID:
388 return new DirectIntRules<ConstantSInt, signed short, &Type::ShortTy>();
389 case Type::UShortTyID:
390 return new DirectIntRules<ConstantUInt, unsigned short, &Type::UShortTy>();
392 return new DirectIntRules<ConstantSInt, signed int , &Type::IntTy>();
394 return new DirectIntRules<ConstantUInt, unsigned int , &Type::UIntTy>();
396 return new DirectIntRules<ConstantSInt, int64_t , &Type::LongTy>();
397 case Type::ULongTyID:
398 return new DirectIntRules<ConstantUInt, uint64_t , &Type::ULongTy>();
399 case Type::FloatTyID:
400 return new DirectFPRules<ConstantFP , float , &Type::FloatTy>();
401 case Type::DoubleTyID:
402 return new DirectFPRules<ConstantFP , double , &Type::DoubleTy>();
404 return new EmptyRules();