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