1 #ifndef SMART_TYPE_H
2 #define SMART_TYPE_H
3 
4 #include <pass.h>
5 #include <magic/support/Backports.h>
6 #include <magic/support/EDIType.h>
7 #include <magic/support/TypeUtil.h>
8 #include <magic/support/BitFieldAggregation.h>
9 
10 using namespace llvm;
11 
12 namespace llvm {
13 
14 #define SmartTypeLog(M) DEBUG(dbgs() << "SmartType: " << M << "\n")
15 #define SmartTypeErr(M) errs() << "SmartType: " << M << "\n"
16 
17 #if HAVE_EXCEPTIONS
18 #define THROW(E) throw E
19 #define TRY(B) try{ B }
20 #define CATCH(E, B) catch(E){ B }
21 #else
22 #define THROW(E) assert(0 && "throw: Exceptions disabled")
23 #define TRY(B) assert(0 && "try: Exceptions disabled");
24 #define CATCH(E, B) assert(0 && "catch: Exceptions disabled");
25 #endif
26 
27 #define SmartType_assert(X) do {              \
28         if(!(X)) {                        \
29             if(useExceptions) {           \
30                 THROW(std::exception());  \
31             }                             \
32             errs() << "Assertion failed, dumping object...\n"; \
33             errs() << "Name is: " << this->aEDIType.getName() << "\n"; \
34             errs() << *this; \
35         }                                 \
36         assert(X);                        \
37     } while(0)
38 
39 class SmartType {
40   public:
41       SmartType(const SmartType& et);
42       SmartType(TYPECONST Type *type, const DIType *aDIType, bool useExceptions=false, bool forceRawTypeRepresentation=false);
43       SmartType(TYPECONST Type *type, const EDIType *aEDIType, bool useExceptions=false, bool forceRawTypeRepresentation=false);
44       ~SmartType();
45 
46       SmartType& operator=(const SmartType& et);
47       void cloneFrom(const SmartType& et);
48 
49       const std::string getDescription() const;
50       const SmartType* getContainedType(unsigned i) const;
51       unsigned getNumContainedTypes() const;
52       const DIDerivedType& getMember(unsigned i) const;
53       unsigned getUnionMemberIdx() const;
54       const SmartType* getTopStructType(unsigned index) const;
55 
56       TYPECONST Type *getType() const;
57       const EDIType *getEDIType() const;
58       bool isTypeConsistent() const;
59       bool hasInnerPointers() const;
60       bool isVoidTy() const;
61       bool isPrimitiveTy() const;
62       bool isAggregateType() const;
63       bool isFunctionTy() const;
64       bool isStructTy() const;
65       bool isArrayTy() const;
66       bool isPointerTy() const;
67       bool isOpaqueTy() const;
68       bool isPaddedTy() const;
69       unsigned getNumElements() const;
70       bool isUseExceptions() const;
71 
72       void verify() const;
73       bool verifyTy() const;
74       void print(raw_ostream &OS) const;
75       bool equals(const SmartType* other, bool isDebug=false) const;
76       bool hasRawTypeRepresentation() const;
77 
78       static const SmartType* getSmartTypeFromGV(Module &M, GlobalVariable *GV, DIGlobalVariable *DIG = NULL);
79       static const SmartType* getSmartTypeFromLV(Module &M, AllocaInst *AI, DIVariable *DIV = NULL);
80       static const SmartType* getSmartTypeFromFunction(Module &M, Function *F, DISubprogram *DIS = NULL);
81       static const SmartType* getStructSmartTypeByName(Module &M, GlobalVariable* GV, std::string &name, bool isUnion=false);
82       static std::vector<const SmartType*>* getTopStructSmartTypes(Module &M, GlobalVariable* GV);
83       static bool isTypeConsistent(TYPECONST Type *type, const EDIType *aEDIType, bool useBfas=true, int *weakConsistencyLevel=NULL);
84 
85   private:
86       TYPECONST Type *type;
87       EDIType aEDIType;
88       bool hasExplicitContainedEDITypes;
89       bool isInconsistent;
90       std::vector<EDIType*> explicitContainedEDITypes;
91       std::vector<BitFieldAggregation> bfas;
92       bool useExceptions;
93       bool rawTypeRepresentation;
94       unsigned unionMemberIdx;
95       static std::vector<TYPECONST Type*> equalsNestedTypes;
96       static bool forceRawUnions;
97       static bool forceRawBitfields;
98 
99       void init(TYPECONST Type *type, const EDIType *aEDIType, bool useExceptions, bool forceRawTypeRepresentation);
100       void normalize();
101       void flattenFunctionTy();
102       int flattenFunctionArgs(TYPECONST Type *type, const EDIType *aEDIType, unsigned nextContainedType);
103       bool isTy(bool isTyType, bool isTyEDIType, const char* source) const;
104 
105       static unsigned getBFAFreeIdx(unsigned i, const std::vector<BitFieldAggregation> &inputBfas);
106       static bool isRawTypeConsistent(TYPECONST Type *type, const EDIType *aEDIType);
107       static bool isTypeConsistent2(TYPECONST Type *type, const EDIType *aEDIType);
108       static bool isTypeConsistent2(std::vector<TYPECONST Type*> &nestedTypes, std::vector<const EDIType*> &nestedEDITypes, const SmartType *aSmartType);
109 };
110 
111 inline raw_ostream &operator<<(raw_ostream &OS, const SmartType &aSmartType) {
112     aSmartType.print(OS);
113     return OS;
114 }
115 
116 inline TYPECONST Type *SmartType::getType() const {
117     return type;
118 }
119 
120 inline const EDIType *SmartType::getEDIType() const {
121     return &aEDIType;
122 }
123 
124 inline bool SmartType::isTypeConsistent() const {
125     if(isInconsistent) {
126         return false;
127     }
128     if(isFunctionTy() || hasRawTypeRepresentation()) {
129         return true;
130     }
131     return isTypeConsistent(type, &aEDIType);
132 }
133 
134 inline bool SmartType::hasInnerPointers() const {
135     return aEDIType.hasInnerPointers();
136 }
137 
138 inline bool SmartType::isVoidTy() const {
139     return isTy(type->isVoidTy(), aEDIType.isVoidTy(), "isVoidTy");
140 }
141 
142 inline bool SmartType::isPrimitiveTy() const {
143     if(aEDIType.isComplexFloatingPointTy()) {
144         assert(type->isStructTy());
145         return true;
146     }
147     return isTy(type->isPrimitiveType(), aEDIType.isPrimitiveType(), "isPrimitiveTy");
148 }
149 
150 inline bool SmartType::isAggregateType() const {
151     return isTy(type->isAggregateType(), aEDIType.isAggregateType(), "isAggregateType");
152 }
153 
154 inline bool SmartType::isFunctionTy() const {
155     if(isOpaqueTy()) {
156         return false;
157     }
158     return isTy(type->isFunctionTy(), aEDIType.isFunctionTy(), "isFunctionTy");
159 }
160 
161 inline bool SmartType::isStructTy() const {
162     if(aEDIType.isComplexFloatingPointTy()) {
163         assert(type->isStructTy());
164         return false;
165     }
166     if(aEDIType.isArrayTy() && TypeUtil::isArrayAsStructTy(type)) {
167         return false;
168     }
169     if(isOpaqueTy()) {
170         return false;
171     }
172     return isTy(type->isStructTy(), aEDIType.isUnionOrStructTy(), "isStructTy");
173 }
174 
175 inline bool SmartType::isArrayTy() const {
176     if(aEDIType.isArrayTy() && TypeUtil::isArrayAsStructTy(type)) {
177         return true;
178     }
179     if (hasRawTypeRepresentation()) { // only possible for structs and bitfields
180         return false;
181     }
182     return isTy(type->isArrayTy(), aEDIType.isArrayTy(), "isArrayTy");
183 }
184 
185 inline bool SmartType::isPointerTy() const {
186     return isTy(type->isPointerTy(), aEDIType.isPointerTy(), "isPointerTy");
187 }
188 
189 inline bool SmartType::isOpaqueTy() const {
190     return TypeUtil::isOpaqueTy(type) || aEDIType.isOpaqueTy();
191 }
192 
193 inline bool SmartType::isPaddedTy() const {
194     if(!isAggregateType() || hasRawTypeRepresentation()) {
195         return false;
196     }
197     return TypeUtil::isPaddedType(type);
198 }
199 
200 inline unsigned SmartType::getNumElements() const {
201     if(!isArrayTy()) {
202         return 0;
203     }
204     unsigned EDINumElements = aEDIType.getNumElements();
205     unsigned numElements;
206     if(type->isArrayTy()) {
207         numElements = ((ArrayType*)type)->getNumElements();
208     }
209     else {
210         assert(type->isStructTy());
211         numElements = type->getNumContainedTypes();
212     }
213     if(numElements == 0) {
214         assert(EDINumElements <= 1 || EDINumElements==UINT_MAX);
215         return 0;
216     }
217     assert(numElements == EDINumElements);
218     return numElements;
219 }
220 
221 inline bool SmartType::isUseExceptions() const {
222     return useExceptions;
223 }
224 
225 inline bool SmartType::verifyTy() const {
226     if(isVoidTy()) return true;
227     if(isPrimitiveTy()) return true;
228     if(isAggregateType()) return true;
229     if(isFunctionTy()) return true;
230     if(isStructTy()) return true;
231     if(isArrayTy()) return true;
232     if(isPointerTy()) return true;
233     if(isOpaqueTy()) return true;
234 
235     return false;
236 }
237 
238 inline bool SmartType::hasRawTypeRepresentation() const {
239     return rawTypeRepresentation;
240 }
241 
242 }
243 
244 #endif
245