Add support for casting operators
[oota-llvm.git] / lib / VMCore / ConstantFold.cpp
1 //===- ConstantHandling.cpp - Implement ConstantHandling.h ----------------===//
2 //
3 // This file implements the various intrinsic operations, on constant values.
4 //
5 //===----------------------------------------------------------------------===//
6
7 #include "llvm/Optimizations/ConstantHandling.h"
8
9 namespace opt {
10
11 //===----------------------------------------------------------------------===//
12 //                             TemplateRules Class
13 //===----------------------------------------------------------------------===//
14 //
15 // TemplateRules - Implement a subclass of ConstRules that provides all 
16 // operations as noops.  All other rules classes inherit from this class so 
17 // that if functionality is needed in the future, it can simply be added here 
18 // and to ConstRules without changing anything else...
19 // 
20 // This class also provides subclasses with typesafe implementations of methods
21 // so that don't have to do type casting.
22 //
23 template<class ArgType, class SubClassName>
24 class TemplateRules : public ConstRules {
25
26   //===--------------------------------------------------------------------===//
27   // Redirecting functions that cast to the appropriate types
28   //===--------------------------------------------------------------------===//
29
30   virtual ConstPoolVal *not(const ConstPoolVal *V) const {
31     return SubClassName::Not((const ArgType *)V);
32   }
33
34   
35   virtual ConstPoolVal *add(const ConstPoolVal *V1, 
36                             const ConstPoolVal *V2) const { 
37     return SubClassName::Add((const ArgType *)V1, (const ArgType *)V2);  
38   }
39
40   virtual ConstPoolVal *sub(const ConstPoolVal *V1, 
41                             const ConstPoolVal *V2) const { 
42     return SubClassName::Sub((const ArgType *)V1, (const ArgType *)V2);  
43   }
44
45   virtual ConstPoolVal *mul(const ConstPoolVal *V1, 
46                             const ConstPoolVal *V2) const { 
47     return SubClassName::Mul((const ArgType *)V1, (const ArgType *)V2);  
48   }
49
50   virtual ConstPoolBool *lessthan(const ConstPoolVal *V1, 
51                                   const ConstPoolVal *V2) const { 
52     return SubClassName::LessThan((const ArgType *)V1, (const ArgType *)V2);
53   }
54
55   //===--------------------------------------------------------------------===//
56   // Default "noop" implementations
57   //===--------------------------------------------------------------------===//
58
59   inline static ConstPoolVal *Not(const ArgType *V) { return 0; }
60
61   inline static ConstPoolVal *Add(const ArgType *V1, const ArgType *V2) {
62     return 0;
63   }
64   inline static ConstPoolVal *Sub(const ArgType *V1, const ArgType *V2) {
65     return 0;
66   }
67   inline static ConstPoolVal *Mul(const ArgType *V1, const ArgType *V2) {
68     return 0;
69   }
70   inline static ConstPoolBool *LessThan(const ArgType *V1, const ArgType *V2) {
71     return 0;
72   }
73 };
74
75
76
77 //===----------------------------------------------------------------------===//
78 //                             EmptyRules Class
79 //===----------------------------------------------------------------------===//
80 //
81 // EmptyRules provides a concrete base class of ConstRules that does nothing
82 //
83 static    // EmptyInst is static
84 struct EmptyRules : public TemplateRules<ConstPoolVal, EmptyRules> {
85 } EmptyInst;
86
87
88
89 //===----------------------------------------------------------------------===//
90 //                              BoolRules Class
91 //===----------------------------------------------------------------------===//
92 //
93 // BoolRules provides a concrete base class of ConstRules for the 'bool' type.
94 //
95 static   // BoolTyInst is static...
96 struct BoolRules : public TemplateRules<ConstPoolBool, BoolRules> {
97
98   inline static ConstPoolVal *Not(const ConstPoolBool *V) { 
99     return new ConstPoolBool(!V->getValue());
100   }
101
102   inline static ConstPoolVal *Or(const ConstPoolBool *V1, 
103                                  const ConstPoolBool *V2) {
104     bool Result = V1->getValue() | V2->getValue();
105     return new ConstPoolBool(Result);
106   }
107
108   inline static ConstPoolVal *And(const ConstPoolBool *V1, 
109                                   const ConstPoolBool *V2) {
110     bool Result = V1->getValue() & V2->getValue();
111     return new ConstPoolBool(Result);
112   }
113 } BoolTyInst;
114
115
116 //===----------------------------------------------------------------------===//
117 //                             DirectRules Class
118 //===----------------------------------------------------------------------===//
119 //
120 // DirectRules provides a concrete base classes of ConstRules for a variety of
121 // different types.  This allows the C++ compiler to automatically generate our
122 // constant handling operations in a typesafe and accurate manner.
123 //
124 template<class ConstPoolClass, class BuiltinType, const Type **Ty>
125 struct DirectRules 
126   : public TemplateRules<ConstPoolClass, 
127                          DirectRules<ConstPoolClass, BuiltinType, Ty> > {
128
129   inline static ConstPoolVal *Not(const ConstPoolClass *V) { 
130     return new ConstPoolClass(*Ty, !(BuiltinType)V->getValue());;
131   }
132
133   inline static ConstPoolVal *Add(const ConstPoolClass *V1, 
134                                   const ConstPoolClass *V2) {
135     BuiltinType Result = (BuiltinType)V1->getValue() + 
136                          (BuiltinType)V2->getValue();
137     return new ConstPoolClass(*Ty, Result);
138   }
139
140   inline static ConstPoolVal *Sub(const ConstPoolClass *V1, 
141                                   const ConstPoolClass *V2) {
142     BuiltinType Result = (BuiltinType)V1->getValue() -
143                          (BuiltinType)V2->getValue();
144     return new ConstPoolClass(*Ty, Result);
145   }
146
147   inline static ConstPoolVal *Mul(const ConstPoolClass *V1, 
148                                    const ConstPoolClass *V2) {
149     BuiltinType Result = (BuiltinType)V1->getValue() *
150                          (BuiltinType)V2->getValue();
151     return new ConstPoolClass(*Ty, Result);
152   }
153
154   inline static ConstPoolBool *LessThan(const ConstPoolClass *V1, 
155                                         const ConstPoolClass *V2) {
156     bool Result = (BuiltinType)V1->getValue() < (BuiltinType)V2->getValue();
157     return new ConstPoolBool(Result);
158   } 
159 };
160
161 //===----------------------------------------------------------------------===//
162 //                            DirectRules Subclasses
163 //===----------------------------------------------------------------------===//
164 //
165 // Given the DirectRules class we can now implement lots of types with little
166 // code.  Thank goodness C++ compilers are great at stomping out layers of 
167 // templates... can you imagine having to do this all by hand? (/me is lazy :)
168 //
169 static DirectRules<ConstPoolSInt,   signed char , &Type::SByteTy>  SByteTyInst;
170 static DirectRules<ConstPoolUInt, unsigned char , &Type::UByteTy>  UByteTyInst;
171 static DirectRules<ConstPoolSInt,   signed short, &Type::ShortTy>  ShortTyInst;
172 static DirectRules<ConstPoolUInt, unsigned short, &Type::UShortTy> UShortTyInst;
173 static DirectRules<ConstPoolSInt,   signed int  , &Type::IntTy>    IntTyInst;
174 static DirectRules<ConstPoolUInt, unsigned int  , &Type::UIntTy>   UIntTyInst;
175 static DirectRules<ConstPoolSInt,  int64_t      , &Type::LongTy>   LongTyInst;
176 static DirectRules<ConstPoolUInt, uint64_t      , &Type::ULongTy>  ULongTyInst;
177 static DirectRules<ConstPoolFP  , float         , &Type::FloatTy>  FloatTyInst;
178 static DirectRules<ConstPoolFP  , double        , &Type::DoubleTy> DoubleTyInst;
179
180
181 // ConstRules::find - Return the constant rules that take care of the specified
182 // type.  Note that this is cached in the Type value itself, so switch statement
183 // is only hit at most once per type.
184 //
185 const ConstRules *ConstRules::find(const Type *Ty) {
186   const ConstRules *Result;
187   switch (Ty->getPrimitiveID()) {
188   case Type::BoolTyID:   Result = &BoolTyInst;   break;
189   case Type::SByteTyID:  Result = &SByteTyInst;  break;
190   case Type::UByteTyID:  Result = &UByteTyInst;  break;
191   case Type::ShortTyID:  Result = &ShortTyInst;  break;
192   case Type::UShortTyID: Result = &UShortTyInst; break;
193   case Type::IntTyID:    Result = &IntTyInst;    break;
194   case Type::UIntTyID:   Result = &UIntTyInst;   break;
195   case Type::LongTyID:   Result = &LongTyInst;   break;
196   case Type::ULongTyID:  Result = &ULongTyInst;  break;
197   case Type::FloatTyID:  Result = &FloatTyInst;  break;
198   case Type::DoubleTyID: Result = &DoubleTyInst; break;
199   default:               Result = &EmptyInst;    break;
200   }
201
202   Ty->setConstRules(Result);   // Cache the value for future short circuiting!
203   return Result;
204 }
205
206
207 } // End namespace opt