1 #ifndef EDITYPE_H
2 #define EDITYPE_H
3 
4 #include <pass.h>
5 
6 using namespace llvm;
7 
8 namespace llvm {
9 
10 #define EDITypeLog(M) DEBUG(dbgs() << "EDIType: " << M << "\n")
11 #define EDITypeErr(M) errs() << "EDIType: " << M << "\n"
12 
13 #define EDIType_assert(X) do {            \
14         if(!(X)) {                        \
15             errs() << "Assertion failed, dumping object...\n"; \
16             errs() << *this;              \
17         }                                 \
18         assert(X);                        \
19     } while(0)
20 
21 class EDIType {
22   public:
23       EDIType(const MDNode *N, bool norm=true, bool checkOpaqueTypes=true);
24       EDIType(bool norm=false, bool checkOpaqueTypes=false);
25       EDIType(const DIType aDIType, bool norm=true, bool checkOpaqueTypes=true);
26 
27       bool operator == (const EDIType& aEDIType) const;
28 
29       static const bool NORMALIZE = true;
30       static const bool DO_NOT_NORMALIZE = false;
31       static const bool CHECK_OPAQUE_TYPES = true;
32       static const bool DO_NOT_CHECK_OPAQUE_TYPES = false;
33 
34       const std::string getDescription(int skipUnions=0, int skipStructs=0, int allowMultiNames=0) const;
35       const EDIType& getContainedType(unsigned i, bool norm=true) const;
36       unsigned getNumContainedTypes() const;
37       const DIDerivedType& getMember(unsigned i) const;
38       bool isUnionOrStructTy(bool isStruct=true, bool isUnion=true) const;
39       bool hasInnerPointers() const;
40       DIArray getTypeArray() const;
41       const EDIType* getTopStructType(unsigned index) const;
42 
43       unsigned getNumElements() const;
44       unsigned getNumDimensions() const;
45       void setCurrentDimension(unsigned dimension);
46       unsigned getCurrentDimension() const;
47       const DIType *getDIType() const;
48       StringRef getName() const;
49       std::vector<StringRef> getNames() const;
50       StringRef getNamesString() const;
51       std::vector<unsigned> getEnumValues() const;
52       unsigned getTag()const;
53       EDIType getTypeDerivedFrom() const;
54       bool isType() const;
55       bool isBasicType() const;
56       bool isDerivedType() const;
57       bool isCompositeType() const;
58       bool isPrimitiveType() const;
59       bool isAggregateType() const;
60       bool isVoidTy() const;
61       bool isComplexFloatingPointTy() const;
62       bool isFloatingPointTy() const;
63       bool isCharTy() const;
64       bool isIntTy() const;
65       bool isBoolTy() const;
66       bool isIntegerTy() const;
67       bool isFunctionTy() const;
68       bool isArrayTy() const;
69       bool isEnumTy() const;
70       bool isVectorTy() const;
71       bool isUnionTy() const;
72       bool isStructTy() const;
73       bool isPointerTy() const;
74       bool isOpaqueTy() const;
75 
76       void print(raw_ostream &OS) const;
77       void printDescription(raw_ostream &OS, int skipUnions=0, int skipStructs=0, int allowMultiNames=0) const;
78       bool equals(const EDIType *other) const;
79 
80       static std::string lookupTypedefName(std::string &name);
81       static std::string lookupUnionMemberName(TYPECONST Type* type);
82       static const EDIType* getStructEDITypeByName(std::string &name);
83       static void setModule(Module *M);
84       static void writeTypeSymbolic(raw_string_ostream &OS, TYPECONST Type *type, const Module *M);
85 
86   private:
87       DIType aDIType;
88       unsigned currentDimension;
89       bool checkOpaqueTypes;
90       StringRef myName;
91       std::vector<StringRef> myNames;
92       static StringRef voidName;
93       static Module *module;
94       static DebugInfoFinder DIFinder;
95 
96       void init(bool norm, bool checkOpaqueTypes);
97       void normalize();
98       void normalizeTypedef();
99 };
100 
101 inline raw_ostream &operator<<(raw_ostream &OS, const EDIType &aEDIType) {
102     aEDIType.print(OS);
103     return OS;
104 }
105 
106 inline unsigned EDIType::getNumElements() const {
107     if(!isArrayTy() && !isVectorTy()) {
108         return 1;
109     }
110     const DIArray aDIArray = getTypeArray();
111     const DIDescriptor aDIDescriptor = aDIArray.getElement(currentDimension);
112     assert(aDIDescriptor.getTag() == dwarf::DW_TAG_subrange_type);
113 
114     return PassUtil::getDbgSubrangeNumElements((DISubrange)aDIDescriptor);
115 }
116 
117 inline unsigned EDIType::getNumDimensions() const {
118     return isArrayTy() || isVectorTy() ? getTypeArray().getNumElements() : 1;
119 }
120 
121 inline void EDIType::setCurrentDimension(unsigned dimension) {
122     assert(dimension < getNumDimensions());
123     this->currentDimension = dimension;
124 }
125 
126 inline unsigned EDIType::getCurrentDimension() const {
127     return currentDimension;
128 }
129 
130 inline const DIType *EDIType::getDIType() const {
131     return &aDIType;
132 }
133 
134 inline StringRef EDIType::getName() const {
135     return myName;
136 }
137 
138 inline std::vector<StringRef> EDIType::getNames() const {
139     return myNames;
140 }
141 
142 inline StringRef EDIType::getNamesString() const {
143     std::string string;
144     raw_string_ostream ostream(string);
145     for(unsigned i=0;i<myNames.size();i++) {
146         if(i>0) ostream << "|";
147         ostream << myNames[i];
148     }
149     ostream.flush();
150     return string;
151 }
152 
153 inline std::vector<unsigned> EDIType::getEnumValues() const {
154     assert(isEnumTy());
155     std::vector<unsigned> enumValues;
156     DIArray aDIArray = getTypeArray();
157     unsigned numValues = aDIArray.getNumElements();
158     for(unsigned i=0;i<numValues;i++) {
159         DIDescriptor aDIDescriptor = aDIArray.getElement(i);
160         assert(aDIDescriptor.getTag() == dwarf::DW_TAG_enumerator);
161         const unsigned value = (unsigned) ((DIEnumerator)aDIDescriptor).getEnumValue();
162         enumValues.push_back(value);
163     }
164     return enumValues;
165 }
166 
167 inline unsigned EDIType::getTag()const {
168     return aDIType.getTag();
169 }
170 
171 inline EDIType EDIType::getTypeDerivedFrom() const {
172     EDIType_assert(isDerivedType() || isCompositeType());
173     EDIType subType(PassUtil::getDITypeDerivedFrom((const DIDerivedType)aDIType));
174     return subType;
175 }
176 
177 inline bool EDIType::isType() const {
178     return aDIType.isType() || isVoidTy();
179 }
180 
181 inline bool EDIType::isBasicType() const {
182     return aDIType.isBasicType();
183 }
184 
185 inline bool EDIType::isDerivedType() const {
186     return aDIType.isDerivedType() && !aDIType.isCompositeType();
187 }
188 
189 inline bool EDIType::isCompositeType() const {
190     return aDIType.isCompositeType();
191 }
192 
193 inline bool EDIType::isPrimitiveType() const {
194     return (isVoidTy() || isFloatingPointTy());
195 }
196 
197 inline bool EDIType::isAggregateType() const {
198     return isUnionOrStructTy() || isArrayTy() || isVectorTy();
199 }
200 
201 inline bool EDIType::isVoidTy() const {
202     return !aDIType.isValid(); //xxx we should keep track of this to spot all the i8* = void*
203 }
204 
205 inline bool EDIType::isComplexFloatingPointTy() const {
206     if(!isBasicType()) return false;
207     return (((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_complex_float);
208 }
209 
210 inline bool EDIType::isFloatingPointTy() const {
211     if(!isBasicType()) return false;
212     return EDIType::isComplexFloatingPointTy() || (((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_float);
213 }
214 
215 inline bool EDIType::isCharTy() const {
216     if(!isBasicType()) return false;
217     return (((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_signed_char ||
218         ((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_unsigned_char);
219 }
220 
221 inline bool EDIType::isIntTy() const {
222     if(!isBasicType()) return false;
223     return (((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_signed ||
224         ((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_unsigned);
225 }
226 
227 inline bool EDIType::isBoolTy() const {
228     if(!isBasicType()) return false;
229     return (((DIBasicType)aDIType).getEncoding() == dwarf::DW_ATE_boolean);
230 }
231 
232 inline bool EDIType::isIntegerTy() const {
233     return (isCharTy() || isIntTy() || isBoolTy());
234 }
235 
236 inline bool EDIType::isFunctionTy() const {
237     return (getTag() == dwarf::DW_TAG_subroutine_type && !isOpaqueTy());
238 }
239 
240 inline bool EDIType::isArrayTy() const {
241     return (getTag() == dwarf::DW_TAG_array_type && !isOpaqueTy());
242 }
243 
244 inline bool EDIType::isEnumTy() const {
245     return (getTag() == dwarf::DW_TAG_enumeration_type && !isOpaqueTy());
246 }
247 
248 inline bool EDIType::isVectorTy() const {
249     return (PassUtil::isDbgVectorTy(aDIType) && !isOpaqueTy());
250 }
251 
252 inline bool EDIType::isUnionTy() const {
253     return isUnionOrStructTy(false, true);
254 }
255 
256 inline bool EDIType::isStructTy() const {
257     return isUnionOrStructTy(true, false);
258 }
259 
260 inline bool EDIType::isPointerTy() const {
261     return (getTag() == dwarf::DW_TAG_pointer_type);
262 }
263 
264 inline bool EDIType::isOpaqueTy() const {
265     return (isCompositeType() && getTypeArray().getNumElements() == 0);
266 }
267 
268 inline void EDIType::writeTypeSymbolic(raw_string_ostream &OS, TYPECONST Type *type, const Module *M) {
269     return PassUtil::writeTypeSymbolic(OS, type, M);
270 }
271 
272 }
273 
274 #endif
275