13e457fe3SDavid van Moolenbroek #ifndef SMART_TYPE_H
23e457fe3SDavid van Moolenbroek #define SMART_TYPE_H
33e457fe3SDavid van Moolenbroek 
43e457fe3SDavid van Moolenbroek #include <pass.h>
53e457fe3SDavid van Moolenbroek #include <magic/support/EDIType.h>
63e457fe3SDavid van Moolenbroek #include <magic/support/TypeUtil.h>
73e457fe3SDavid van Moolenbroek #include <magic/support/BitFieldAggregation.h>
83e457fe3SDavid van Moolenbroek 
93e457fe3SDavid van Moolenbroek using namespace llvm;
103e457fe3SDavid van Moolenbroek 
113e457fe3SDavid van Moolenbroek namespace llvm {
123e457fe3SDavid van Moolenbroek 
133e457fe3SDavid van Moolenbroek #define SmartTypeLog(M) DEBUG(dbgs() << "SmartType: " << M << "\n")
143e457fe3SDavid van Moolenbroek #define SmartTypeErr(M) errs() << "SmartType: " << M << "\n"
153e457fe3SDavid van Moolenbroek 
163e457fe3SDavid van Moolenbroek #if HAVE_EXCEPTIONS
173e457fe3SDavid van Moolenbroek #define THROW(E) throw E
183e457fe3SDavid van Moolenbroek #define TRY(B) try{ B }
193e457fe3SDavid van Moolenbroek #define CATCH(E, B) catch(E){ B }
203e457fe3SDavid van Moolenbroek #else
213e457fe3SDavid van Moolenbroek #define THROW(E) assert(0 && "throw: Exceptions disabled")
223e457fe3SDavid van Moolenbroek #define TRY(B) assert(0 && "try: Exceptions disabled");
233e457fe3SDavid van Moolenbroek #define CATCH(E, B) assert(0 && "catch: Exceptions disabled");
243e457fe3SDavid van Moolenbroek #endif
253e457fe3SDavid van Moolenbroek 
263e457fe3SDavid van Moolenbroek #define SmartType_assert(X) do {              \
273e457fe3SDavid van Moolenbroek         if(!(X)) {                        \
283e457fe3SDavid van Moolenbroek             if(useExceptions) {           \
293e457fe3SDavid van Moolenbroek                 THROW(std::exception());  \
303e457fe3SDavid van Moolenbroek             }                             \
313e457fe3SDavid van Moolenbroek             errs() << "Assertion failed, dumping object...\n"; \
323e457fe3SDavid van Moolenbroek             errs() << "Name is: " << this->aEDIType.getName() << "\n"; \
333e457fe3SDavid van Moolenbroek             errs() << *this; \
343e457fe3SDavid van Moolenbroek         }                                 \
353e457fe3SDavid van Moolenbroek         assert(X);                        \
363e457fe3SDavid van Moolenbroek     } while(0)
373e457fe3SDavid van Moolenbroek 
383e457fe3SDavid van Moolenbroek class SmartType {
393e457fe3SDavid van Moolenbroek   public:
403e457fe3SDavid van Moolenbroek       SmartType(const SmartType& et);
413e457fe3SDavid van Moolenbroek       SmartType(TYPECONST Type *type, const DIType *aDIType, bool useExceptions=false, bool forceRawTypeRepresentation=false);
423e457fe3SDavid van Moolenbroek       SmartType(TYPECONST Type *type, const EDIType *aEDIType, bool useExceptions=false, bool forceRawTypeRepresentation=false);
433e457fe3SDavid van Moolenbroek       ~SmartType();
443e457fe3SDavid van Moolenbroek 
453e457fe3SDavid van Moolenbroek       SmartType& operator=(const SmartType& et);
463e457fe3SDavid van Moolenbroek       void cloneFrom(const SmartType& et);
473e457fe3SDavid van Moolenbroek 
483e457fe3SDavid van Moolenbroek       const std::string getDescription() const;
493e457fe3SDavid van Moolenbroek       const SmartType* getContainedType(unsigned i) const;
503e457fe3SDavid van Moolenbroek       unsigned getNumContainedTypes() const;
513e457fe3SDavid van Moolenbroek       const DIDerivedType& getMember(unsigned i) const;
523e457fe3SDavid van Moolenbroek       unsigned getUnionMemberIdx() const;
533e457fe3SDavid van Moolenbroek       const SmartType* getTopStructType(unsigned index) const;
543e457fe3SDavid van Moolenbroek 
553e457fe3SDavid van Moolenbroek       TYPECONST Type *getType() const;
563e457fe3SDavid van Moolenbroek       const EDIType *getEDIType() const;
573e457fe3SDavid van Moolenbroek       bool isTypeConsistent() const;
583e457fe3SDavid van Moolenbroek       bool hasInnerPointers() const;
593e457fe3SDavid van Moolenbroek       bool isVoidTy() const;
603e457fe3SDavid van Moolenbroek       bool isPrimitiveTy() const;
613e457fe3SDavid van Moolenbroek       bool isAggregateType() const;
623e457fe3SDavid van Moolenbroek       bool isFunctionTy() const;
633e457fe3SDavid van Moolenbroek       bool isStructTy() const;
643e457fe3SDavid van Moolenbroek       bool isArrayTy() const;
653e457fe3SDavid van Moolenbroek       bool isPointerTy() const;
663e457fe3SDavid van Moolenbroek       bool isOpaqueTy() const;
673e457fe3SDavid van Moolenbroek       bool isPaddedTy() const;
683e457fe3SDavid van Moolenbroek       unsigned getNumElements() const;
693e457fe3SDavid van Moolenbroek       bool isUseExceptions() const;
703e457fe3SDavid van Moolenbroek 
713e457fe3SDavid van Moolenbroek       void verify() const;
723e457fe3SDavid van Moolenbroek       bool verifyTy() const;
733e457fe3SDavid van Moolenbroek       void print(raw_ostream &OS) const;
743e457fe3SDavid van Moolenbroek       bool equals(const SmartType* other, bool isDebug=false) const;
753e457fe3SDavid van Moolenbroek       bool hasRawTypeRepresentation() const;
763e457fe3SDavid van Moolenbroek 
773e457fe3SDavid van Moolenbroek       static const SmartType* getSmartTypeFromGV(Module &M, GlobalVariable *GV, DIGlobalVariable *DIG = NULL);
783e457fe3SDavid van Moolenbroek       static const SmartType* getSmartTypeFromLV(Module &M, AllocaInst *AI, DIVariable *DIV = NULL);
793e457fe3SDavid van Moolenbroek       static const SmartType* getSmartTypeFromFunction(Module &M, Function *F, DISubprogram *DIS = NULL);
803e457fe3SDavid van Moolenbroek       static const SmartType* getStructSmartTypeByName(Module &M, GlobalVariable* GV, std::string &name, bool isUnion=false);
813e457fe3SDavid van Moolenbroek       static std::vector<const SmartType*>* getTopStructSmartTypes(Module &M, GlobalVariable* GV);
823e457fe3SDavid van Moolenbroek       static bool isTypeConsistent(TYPECONST Type *type, const EDIType *aEDIType, bool useBfas=true, int *weakConsistencyLevel=NULL);
833e457fe3SDavid van Moolenbroek 
843e457fe3SDavid van Moolenbroek   private:
853e457fe3SDavid van Moolenbroek       TYPECONST Type *type;
863e457fe3SDavid van Moolenbroek       EDIType aEDIType;
873e457fe3SDavid van Moolenbroek       bool hasExplicitContainedEDITypes;
883e457fe3SDavid van Moolenbroek       bool isInconsistent;
893e457fe3SDavid van Moolenbroek       std::vector<EDIType*> explicitContainedEDITypes;
903e457fe3SDavid van Moolenbroek       std::vector<BitFieldAggregation> bfas;
913e457fe3SDavid van Moolenbroek       bool useExceptions;
923e457fe3SDavid van Moolenbroek       bool rawTypeRepresentation;
933e457fe3SDavid van Moolenbroek       unsigned unionMemberIdx;
943e457fe3SDavid van Moolenbroek       static std::vector<TYPECONST Type*> equalsNestedTypes;
953e457fe3SDavid van Moolenbroek       static bool forceRawUnions;
963e457fe3SDavid van Moolenbroek       static bool forceRawBitfields;
973e457fe3SDavid van Moolenbroek 
983e457fe3SDavid van Moolenbroek       void init(TYPECONST Type *type, const EDIType *aEDIType, bool useExceptions, bool forceRawTypeRepresentation);
993e457fe3SDavid van Moolenbroek       void normalize();
1003e457fe3SDavid van Moolenbroek       void flattenFunctionTy();
1013e457fe3SDavid van Moolenbroek       int flattenFunctionArgs(TYPECONST Type *type, const EDIType *aEDIType, unsigned nextContainedType);
1023e457fe3SDavid van Moolenbroek       bool isTy(bool isTyType, bool isTyEDIType, const char* source) const;
1033e457fe3SDavid van Moolenbroek 
1043e457fe3SDavid van Moolenbroek       static unsigned getBFAFreeIdx(unsigned i, const std::vector<BitFieldAggregation> &inputBfas);
1053e457fe3SDavid van Moolenbroek       static bool isRawTypeConsistent(TYPECONST Type *type, const EDIType *aEDIType);
1063e457fe3SDavid van Moolenbroek       static bool isTypeConsistent2(TYPECONST Type *type, const EDIType *aEDIType);
1073e457fe3SDavid van Moolenbroek       static bool isTypeConsistent2(std::vector<TYPECONST Type*> &nestedTypes, std::vector<const EDIType*> &nestedEDITypes, const SmartType *aSmartType);
1083e457fe3SDavid van Moolenbroek };
1093e457fe3SDavid van Moolenbroek 
1103e457fe3SDavid van Moolenbroek inline raw_ostream &operator<<(raw_ostream &OS, const SmartType &aSmartType) {
1113e457fe3SDavid van Moolenbroek     aSmartType.print(OS);
1123e457fe3SDavid van Moolenbroek     return OS;
1133e457fe3SDavid van Moolenbroek }
1143e457fe3SDavid van Moolenbroek 
getType()1153e457fe3SDavid van Moolenbroek inline TYPECONST Type *SmartType::getType() const {
1163e457fe3SDavid van Moolenbroek     return type;
1173e457fe3SDavid van Moolenbroek }
1183e457fe3SDavid van Moolenbroek 
getEDIType()1193e457fe3SDavid van Moolenbroek inline const EDIType *SmartType::getEDIType() const {
1203e457fe3SDavid van Moolenbroek     return &aEDIType;
1213e457fe3SDavid van Moolenbroek }
1223e457fe3SDavid van Moolenbroek 
isTypeConsistent()1233e457fe3SDavid van Moolenbroek inline bool SmartType::isTypeConsistent() const {
1243e457fe3SDavid van Moolenbroek     if(isInconsistent) {
1253e457fe3SDavid van Moolenbroek         return false;
1263e457fe3SDavid van Moolenbroek     }
1273e457fe3SDavid van Moolenbroek     if(isFunctionTy() || hasRawTypeRepresentation()) {
1283e457fe3SDavid van Moolenbroek         return true;
1293e457fe3SDavid van Moolenbroek     }
1303e457fe3SDavid van Moolenbroek     return isTypeConsistent(type, &aEDIType);
1313e457fe3SDavid van Moolenbroek }
1323e457fe3SDavid van Moolenbroek 
hasInnerPointers()1333e457fe3SDavid van Moolenbroek inline bool SmartType::hasInnerPointers() const {
1343e457fe3SDavid van Moolenbroek     return aEDIType.hasInnerPointers();
1353e457fe3SDavid van Moolenbroek }
1363e457fe3SDavid van Moolenbroek 
isVoidTy()1373e457fe3SDavid van Moolenbroek inline bool SmartType::isVoidTy() const {
1383e457fe3SDavid van Moolenbroek     return isTy(type->isVoidTy(), aEDIType.isVoidTy(), "isVoidTy");
1393e457fe3SDavid van Moolenbroek }
1403e457fe3SDavid van Moolenbroek 
isPrimitiveTy()1413e457fe3SDavid van Moolenbroek inline bool SmartType::isPrimitiveTy() const {
1423e457fe3SDavid van Moolenbroek     if(aEDIType.isComplexFloatingPointTy()) {
1433e457fe3SDavid van Moolenbroek         assert(type->isStructTy());
1443e457fe3SDavid van Moolenbroek         return true;
1453e457fe3SDavid van Moolenbroek     }
146*bdb56518SDavid van Moolenbroek     return isTy(PassUtil::isPrimitiveTy(type), aEDIType.isPrimitiveType(), "isPrimitiveTy");
1473e457fe3SDavid van Moolenbroek }
1483e457fe3SDavid van Moolenbroek 
isAggregateType()1493e457fe3SDavid van Moolenbroek inline bool SmartType::isAggregateType() const {
1503e457fe3SDavid van Moolenbroek     return isTy(type->isAggregateType(), aEDIType.isAggregateType(), "isAggregateType");
1513e457fe3SDavid van Moolenbroek }
1523e457fe3SDavid van Moolenbroek 
isFunctionTy()1533e457fe3SDavid van Moolenbroek inline bool SmartType::isFunctionTy() const {
1543e457fe3SDavid van Moolenbroek     if(isOpaqueTy()) {
1553e457fe3SDavid van Moolenbroek         return false;
1563e457fe3SDavid van Moolenbroek     }
1573e457fe3SDavid van Moolenbroek     return isTy(type->isFunctionTy(), aEDIType.isFunctionTy(), "isFunctionTy");
1583e457fe3SDavid van Moolenbroek }
1593e457fe3SDavid van Moolenbroek 
isStructTy()1603e457fe3SDavid van Moolenbroek inline bool SmartType::isStructTy() const {
1613e457fe3SDavid van Moolenbroek     if(aEDIType.isComplexFloatingPointTy()) {
1623e457fe3SDavid van Moolenbroek         assert(type->isStructTy());
1633e457fe3SDavid van Moolenbroek         return false;
1643e457fe3SDavid van Moolenbroek     }
1653e457fe3SDavid van Moolenbroek     if(aEDIType.isArrayTy() && TypeUtil::isArrayAsStructTy(type)) {
1663e457fe3SDavid van Moolenbroek         return false;
1673e457fe3SDavid van Moolenbroek     }
1683e457fe3SDavid van Moolenbroek     if(isOpaqueTy()) {
1693e457fe3SDavid van Moolenbroek         return false;
1703e457fe3SDavid van Moolenbroek     }
1713e457fe3SDavid van Moolenbroek     return isTy(type->isStructTy(), aEDIType.isUnionOrStructTy(), "isStructTy");
1723e457fe3SDavid van Moolenbroek }
1733e457fe3SDavid van Moolenbroek 
isArrayTy()1743e457fe3SDavid van Moolenbroek inline bool SmartType::isArrayTy() const {
1753e457fe3SDavid van Moolenbroek     if(aEDIType.isArrayTy() && TypeUtil::isArrayAsStructTy(type)) {
1763e457fe3SDavid van Moolenbroek         return true;
1773e457fe3SDavid van Moolenbroek     }
1783e457fe3SDavid van Moolenbroek     if (hasRawTypeRepresentation()) { // only possible for structs and bitfields
1793e457fe3SDavid van Moolenbroek         return false;
1803e457fe3SDavid van Moolenbroek     }
1813e457fe3SDavid van Moolenbroek     return isTy(type->isArrayTy(), aEDIType.isArrayTy(), "isArrayTy");
1823e457fe3SDavid van Moolenbroek }
1833e457fe3SDavid van Moolenbroek 
isPointerTy()1843e457fe3SDavid van Moolenbroek inline bool SmartType::isPointerTy() const {
1853e457fe3SDavid van Moolenbroek     return isTy(type->isPointerTy(), aEDIType.isPointerTy(), "isPointerTy");
1863e457fe3SDavid van Moolenbroek }
1873e457fe3SDavid van Moolenbroek 
isOpaqueTy()1883e457fe3SDavid van Moolenbroek inline bool SmartType::isOpaqueTy() const {
1893e457fe3SDavid van Moolenbroek     return TypeUtil::isOpaqueTy(type) || aEDIType.isOpaqueTy();
1903e457fe3SDavid van Moolenbroek }
1913e457fe3SDavid van Moolenbroek 
isPaddedTy()1923e457fe3SDavid van Moolenbroek inline bool SmartType::isPaddedTy() const {
1933e457fe3SDavid van Moolenbroek     if(!isAggregateType() || hasRawTypeRepresentation()) {
1943e457fe3SDavid van Moolenbroek         return false;
1953e457fe3SDavid van Moolenbroek     }
1963e457fe3SDavid van Moolenbroek     return TypeUtil::isPaddedType(type);
1973e457fe3SDavid van Moolenbroek }
1983e457fe3SDavid van Moolenbroek 
getNumElements()1993e457fe3SDavid van Moolenbroek inline unsigned SmartType::getNumElements() const {
2003e457fe3SDavid van Moolenbroek     if(!isArrayTy()) {
2013e457fe3SDavid van Moolenbroek         return 0;
2023e457fe3SDavid van Moolenbroek     }
2033e457fe3SDavid van Moolenbroek     unsigned EDINumElements = aEDIType.getNumElements();
2043e457fe3SDavid van Moolenbroek     unsigned numElements;
2053e457fe3SDavid van Moolenbroek     if(type->isArrayTy()) {
2063e457fe3SDavid van Moolenbroek         numElements = ((ArrayType*)type)->getNumElements();
2073e457fe3SDavid van Moolenbroek     }
2083e457fe3SDavid van Moolenbroek     else {
2093e457fe3SDavid van Moolenbroek         assert(type->isStructTy());
2103e457fe3SDavid van Moolenbroek         numElements = type->getNumContainedTypes();
2113e457fe3SDavid van Moolenbroek     }
2123e457fe3SDavid van Moolenbroek     if(numElements == 0) {
2133e457fe3SDavid van Moolenbroek         assert(EDINumElements <= 1 || EDINumElements==UINT_MAX);
2143e457fe3SDavid van Moolenbroek         return 0;
2153e457fe3SDavid van Moolenbroek     }
2163e457fe3SDavid van Moolenbroek     assert(numElements == EDINumElements);
2173e457fe3SDavid van Moolenbroek     return numElements;
2183e457fe3SDavid van Moolenbroek }
2193e457fe3SDavid van Moolenbroek 
isUseExceptions()2203e457fe3SDavid van Moolenbroek inline bool SmartType::isUseExceptions() const {
2213e457fe3SDavid van Moolenbroek     return useExceptions;
2223e457fe3SDavid van Moolenbroek }
2233e457fe3SDavid van Moolenbroek 
verifyTy()2243e457fe3SDavid van Moolenbroek inline bool SmartType::verifyTy() const {
2253e457fe3SDavid van Moolenbroek     if(isVoidTy()) return true;
2263e457fe3SDavid van Moolenbroek     if(isPrimitiveTy()) return true;
2273e457fe3SDavid van Moolenbroek     if(isAggregateType()) return true;
2283e457fe3SDavid van Moolenbroek     if(isFunctionTy()) return true;
2293e457fe3SDavid van Moolenbroek     if(isStructTy()) return true;
2303e457fe3SDavid van Moolenbroek     if(isArrayTy()) return true;
2313e457fe3SDavid van Moolenbroek     if(isPointerTy()) return true;
2323e457fe3SDavid van Moolenbroek     if(isOpaqueTy()) return true;
2333e457fe3SDavid van Moolenbroek 
2343e457fe3SDavid van Moolenbroek     return false;
2353e457fe3SDavid van Moolenbroek }
2363e457fe3SDavid van Moolenbroek 
hasRawTypeRepresentation()2373e457fe3SDavid van Moolenbroek inline bool SmartType::hasRawTypeRepresentation() const {
2383e457fe3SDavid van Moolenbroek     return rawTypeRepresentation;
2393e457fe3SDavid van Moolenbroek }
2403e457fe3SDavid van Moolenbroek 
2413e457fe3SDavid van Moolenbroek }
2423e457fe3SDavid van Moolenbroek 
2433e457fe3SDavid van Moolenbroek #endif
244