3e457fe321
Change-Id: I19535b913b50f2ff24aeb80ddefc92e305c31fe8
245 lines
7.9 KiB
C++
245 lines
7.9 KiB
C++
#ifndef SMART_TYPE_H
|
|
#define SMART_TYPE_H
|
|
|
|
#include <pass.h>
|
|
#include <magic/support/Backports.h>
|
|
#include <magic/support/EDIType.h>
|
|
#include <magic/support/TypeUtil.h>
|
|
#include <magic/support/BitFieldAggregation.h>
|
|
|
|
using namespace llvm;
|
|
|
|
namespace llvm {
|
|
|
|
#define SmartTypeLog(M) DEBUG(dbgs() << "SmartType: " << M << "\n")
|
|
#define SmartTypeErr(M) errs() << "SmartType: " << M << "\n"
|
|
|
|
#if HAVE_EXCEPTIONS
|
|
#define THROW(E) throw E
|
|
#define TRY(B) try{ B }
|
|
#define CATCH(E, B) catch(E){ B }
|
|
#else
|
|
#define THROW(E) assert(0 && "throw: Exceptions disabled")
|
|
#define TRY(B) assert(0 && "try: Exceptions disabled");
|
|
#define CATCH(E, B) assert(0 && "catch: Exceptions disabled");
|
|
#endif
|
|
|
|
#define SmartType_assert(X) do { \
|
|
if(!(X)) { \
|
|
if(useExceptions) { \
|
|
THROW(std::exception()); \
|
|
} \
|
|
errs() << "Assertion failed, dumping object...\n"; \
|
|
errs() << "Name is: " << this->aEDIType.getName() << "\n"; \
|
|
errs() << *this; \
|
|
} \
|
|
assert(X); \
|
|
} while(0)
|
|
|
|
class SmartType {
|
|
public:
|
|
SmartType(const SmartType& et);
|
|
SmartType(TYPECONST Type *type, const DIType *aDIType, bool useExceptions=false, bool forceRawTypeRepresentation=false);
|
|
SmartType(TYPECONST Type *type, const EDIType *aEDIType, bool useExceptions=false, bool forceRawTypeRepresentation=false);
|
|
~SmartType();
|
|
|
|
SmartType& operator=(const SmartType& et);
|
|
void cloneFrom(const SmartType& et);
|
|
|
|
const std::string getDescription() const;
|
|
const SmartType* getContainedType(unsigned i) const;
|
|
unsigned getNumContainedTypes() const;
|
|
const DIDerivedType& getMember(unsigned i) const;
|
|
unsigned getUnionMemberIdx() const;
|
|
const SmartType* getTopStructType(unsigned index) const;
|
|
|
|
TYPECONST Type *getType() const;
|
|
const EDIType *getEDIType() const;
|
|
bool isTypeConsistent() const;
|
|
bool hasInnerPointers() const;
|
|
bool isVoidTy() const;
|
|
bool isPrimitiveTy() const;
|
|
bool isAggregateType() const;
|
|
bool isFunctionTy() const;
|
|
bool isStructTy() const;
|
|
bool isArrayTy() const;
|
|
bool isPointerTy() const;
|
|
bool isOpaqueTy() const;
|
|
bool isPaddedTy() const;
|
|
unsigned getNumElements() const;
|
|
bool isUseExceptions() const;
|
|
|
|
void verify() const;
|
|
bool verifyTy() const;
|
|
void print(raw_ostream &OS) const;
|
|
bool equals(const SmartType* other, bool isDebug=false) const;
|
|
bool hasRawTypeRepresentation() const;
|
|
|
|
static const SmartType* getSmartTypeFromGV(Module &M, GlobalVariable *GV, DIGlobalVariable *DIG = NULL);
|
|
static const SmartType* getSmartTypeFromLV(Module &M, AllocaInst *AI, DIVariable *DIV = NULL);
|
|
static const SmartType* getSmartTypeFromFunction(Module &M, Function *F, DISubprogram *DIS = NULL);
|
|
static const SmartType* getStructSmartTypeByName(Module &M, GlobalVariable* GV, std::string &name, bool isUnion=false);
|
|
static std::vector<const SmartType*>* getTopStructSmartTypes(Module &M, GlobalVariable* GV);
|
|
static bool isTypeConsistent(TYPECONST Type *type, const EDIType *aEDIType, bool useBfas=true, int *weakConsistencyLevel=NULL);
|
|
|
|
private:
|
|
TYPECONST Type *type;
|
|
EDIType aEDIType;
|
|
bool hasExplicitContainedEDITypes;
|
|
bool isInconsistent;
|
|
std::vector<EDIType*> explicitContainedEDITypes;
|
|
std::vector<BitFieldAggregation> bfas;
|
|
bool useExceptions;
|
|
bool rawTypeRepresentation;
|
|
unsigned unionMemberIdx;
|
|
static std::vector<TYPECONST Type*> equalsNestedTypes;
|
|
static bool forceRawUnions;
|
|
static bool forceRawBitfields;
|
|
|
|
void init(TYPECONST Type *type, const EDIType *aEDIType, bool useExceptions, bool forceRawTypeRepresentation);
|
|
void normalize();
|
|
void flattenFunctionTy();
|
|
int flattenFunctionArgs(TYPECONST Type *type, const EDIType *aEDIType, unsigned nextContainedType);
|
|
bool isTy(bool isTyType, bool isTyEDIType, const char* source) const;
|
|
|
|
static unsigned getBFAFreeIdx(unsigned i, const std::vector<BitFieldAggregation> &inputBfas);
|
|
static bool isRawTypeConsistent(TYPECONST Type *type, const EDIType *aEDIType);
|
|
static bool isTypeConsistent2(TYPECONST Type *type, const EDIType *aEDIType);
|
|
static bool isTypeConsistent2(std::vector<TYPECONST Type*> &nestedTypes, std::vector<const EDIType*> &nestedEDITypes, const SmartType *aSmartType);
|
|
};
|
|
|
|
inline raw_ostream &operator<<(raw_ostream &OS, const SmartType &aSmartType) {
|
|
aSmartType.print(OS);
|
|
return OS;
|
|
}
|
|
|
|
inline TYPECONST Type *SmartType::getType() const {
|
|
return type;
|
|
}
|
|
|
|
inline const EDIType *SmartType::getEDIType() const {
|
|
return &aEDIType;
|
|
}
|
|
|
|
inline bool SmartType::isTypeConsistent() const {
|
|
if(isInconsistent) {
|
|
return false;
|
|
}
|
|
if(isFunctionTy() || hasRawTypeRepresentation()) {
|
|
return true;
|
|
}
|
|
return isTypeConsistent(type, &aEDIType);
|
|
}
|
|
|
|
inline bool SmartType::hasInnerPointers() const {
|
|
return aEDIType.hasInnerPointers();
|
|
}
|
|
|
|
inline bool SmartType::isVoidTy() const {
|
|
return isTy(type->isVoidTy(), aEDIType.isVoidTy(), "isVoidTy");
|
|
}
|
|
|
|
inline bool SmartType::isPrimitiveTy() const {
|
|
if(aEDIType.isComplexFloatingPointTy()) {
|
|
assert(type->isStructTy());
|
|
return true;
|
|
}
|
|
return isTy(type->isPrimitiveType(), aEDIType.isPrimitiveType(), "isPrimitiveTy");
|
|
}
|
|
|
|
inline bool SmartType::isAggregateType() const {
|
|
return isTy(type->isAggregateType(), aEDIType.isAggregateType(), "isAggregateType");
|
|
}
|
|
|
|
inline bool SmartType::isFunctionTy() const {
|
|
if(isOpaqueTy()) {
|
|
return false;
|
|
}
|
|
return isTy(type->isFunctionTy(), aEDIType.isFunctionTy(), "isFunctionTy");
|
|
}
|
|
|
|
inline bool SmartType::isStructTy() const {
|
|
if(aEDIType.isComplexFloatingPointTy()) {
|
|
assert(type->isStructTy());
|
|
return false;
|
|
}
|
|
if(aEDIType.isArrayTy() && TypeUtil::isArrayAsStructTy(type)) {
|
|
return false;
|
|
}
|
|
if(isOpaqueTy()) {
|
|
return false;
|
|
}
|
|
return isTy(type->isStructTy(), aEDIType.isUnionOrStructTy(), "isStructTy");
|
|
}
|
|
|
|
inline bool SmartType::isArrayTy() const {
|
|
if(aEDIType.isArrayTy() && TypeUtil::isArrayAsStructTy(type)) {
|
|
return true;
|
|
}
|
|
if (hasRawTypeRepresentation()) { // only possible for structs and bitfields
|
|
return false;
|
|
}
|
|
return isTy(type->isArrayTy(), aEDIType.isArrayTy(), "isArrayTy");
|
|
}
|
|
|
|
inline bool SmartType::isPointerTy() const {
|
|
return isTy(type->isPointerTy(), aEDIType.isPointerTy(), "isPointerTy");
|
|
}
|
|
|
|
inline bool SmartType::isOpaqueTy() const {
|
|
return TypeUtil::isOpaqueTy(type) || aEDIType.isOpaqueTy();
|
|
}
|
|
|
|
inline bool SmartType::isPaddedTy() const {
|
|
if(!isAggregateType() || hasRawTypeRepresentation()) {
|
|
return false;
|
|
}
|
|
return TypeUtil::isPaddedType(type);
|
|
}
|
|
|
|
inline unsigned SmartType::getNumElements() const {
|
|
if(!isArrayTy()) {
|
|
return 0;
|
|
}
|
|
unsigned EDINumElements = aEDIType.getNumElements();
|
|
unsigned numElements;
|
|
if(type->isArrayTy()) {
|
|
numElements = ((ArrayType*)type)->getNumElements();
|
|
}
|
|
else {
|
|
assert(type->isStructTy());
|
|
numElements = type->getNumContainedTypes();
|
|
}
|
|
if(numElements == 0) {
|
|
assert(EDINumElements <= 1 || EDINumElements==UINT_MAX);
|
|
return 0;
|
|
}
|
|
assert(numElements == EDINumElements);
|
|
return numElements;
|
|
}
|
|
|
|
inline bool SmartType::isUseExceptions() const {
|
|
return useExceptions;
|
|
}
|
|
|
|
inline bool SmartType::verifyTy() const {
|
|
if(isVoidTy()) return true;
|
|
if(isPrimitiveTy()) return true;
|
|
if(isAggregateType()) return true;
|
|
if(isFunctionTy()) return true;
|
|
if(isStructTy()) return true;
|
|
if(isArrayTy()) return true;
|
|
if(isPointerTy()) return true;
|
|
if(isOpaqueTy()) return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
inline bool SmartType::hasRawTypeRepresentation() const {
|
|
return rawTypeRepresentation;
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|