minix/minix/llvm/passes/magic/support/SmartType.cpp
David van Moolenbroek 3e457fe321 Import magic pass from llvm-apps
Change-Id: I19535b913b50f2ff24aeb80ddefc92e305c31fe8
2015-09-17 13:57:53 +00:00

781 lines
28 KiB
C++

#include <magic/support/SmartType.h>
#include <limits.h>
using namespace llvm;
namespace llvm {
#define DEBUG_EQUALS 0
#define DEBUG_BFAS 0
#define DEBUG_UNIONS 0
int debugEquals = 0;
//===----------------------------------------------------------------------===//
// Constructors, destructor, and operators
//===----------------------------------------------------------------------===//
SmartType::SmartType(const SmartType& et) {
cloneFrom(et);
}
SmartType::SmartType(TYPECONST Type *type, const DIType *aDIType, bool useExceptions, bool forceRawTypeRepresentation) {
EDIType tmp(*aDIType);
init(type, &tmp, useExceptions, forceRawTypeRepresentation);
normalize();
}
SmartType::SmartType(TYPECONST Type *type, const EDIType *aEDIType, bool useExceptions, bool forceRawTypeRepresentation) {
init(type, aEDIType, useExceptions, forceRawTypeRepresentation);
normalize();
}
SmartType::~SmartType() {
if(hasExplicitContainedEDITypes) {
for(unsigned i=0;i<explicitContainedEDITypes.size();i++) {
const EDIType* aEDIType = explicitContainedEDITypes[i];
delete aEDIType;
}
}
}
SmartType& SmartType::operator=(const SmartType& et) {
if (this != &et) {
cloneFrom(et);
}
return *this;
}
void SmartType::cloneFrom(const SmartType& et) {
init(et.type, &et.aEDIType, et.useExceptions, false);
if(et.hasExplicitContainedEDITypes) {
hasExplicitContainedEDITypes = true;
for(unsigned i=0;i<et.explicitContainedEDITypes.size();i++) {
const EDIType* aEDIType = et.explicitContainedEDITypes[i];
explicitContainedEDITypes.push_back(new EDIType(*aEDIType));
}
}
isInconsistent = et.isInconsistent;
rawTypeRepresentation = et.rawTypeRepresentation;
bfas = et.bfas;
}
//===----------------------------------------------------------------------===//
// Getters
//===----------------------------------------------------------------------===//
const std::string SmartType::getDescription() const {
return TypeUtil::getDescription(type, &aEDIType);
}
const SmartType* SmartType::getContainedType(unsigned i) const {
assert(!rawTypeRepresentation);
bool hasBitFields = false;
TYPECONST Type *subType = type->getContainedType(i);
const SmartType* retSmartType = NULL;
if(hasExplicitContainedEDITypes) {
const EDIType subEDIType(*(explicitContainedEDITypes[i]));
retSmartType = new SmartType(subType, &subEDIType, useExceptions);
}
else {
if(aEDIType.isUnionTy()) {
assert(i == 0);
i = unionMemberIdx;
}
else if(bfas.size() > 0) {
i = getBFAFreeIdx(i, bfas);
hasBitFields = true;
}
const EDIType subEDIType(aEDIType.getContainedType(i));
retSmartType = new SmartType(subType, &subEDIType, useExceptions, hasBitFields && subEDIType.isIntegerTy() && subType->isArrayTy());
}
return retSmartType;
}
unsigned SmartType::getNumContainedTypes() const {
if(rawTypeRepresentation || aEDIType.isComplexFloatingPointTy() || isOpaqueTy()) {
return 0;
}
unsigned numContainedTypes = type->getNumContainedTypes();
unsigned numContainedEDITypes;
if(hasExplicitContainedEDITypes) {
numContainedEDITypes = explicitContainedEDITypes.size();
}
else {
if(aEDIType.isUnionTy()) {
numContainedEDITypes = 1;
}
else {
numContainedEDITypes = aEDIType.getNumContainedTypes();
if(bfas.size() > 0) {
for(unsigned i=0;i<bfas.size();i++) {
numContainedEDITypes -= (bfas[i].getSize() - 1);
}
}
}
}
if(numContainedTypes == numContainedEDITypes+1 && isPaddedTy()) {
numContainedTypes--;
}
if(numContainedTypes != numContainedEDITypes) {
if(isArrayTy() && TypeUtil::isArrayAsStructTy(type)) {
numContainedTypes = 1;
}
}
SmartType_assert(numContainedTypes == numContainedEDITypes);
return numContainedTypes;
}
const DIDerivedType& SmartType::getMember(unsigned i) const {
assert(!rawTypeRepresentation);
if(bfas.size() > 0) {
i = getBFAFreeIdx(i, bfas);
}
return aEDIType.getMember(i);
}
unsigned SmartType::getUnionMemberIdx() const {
assert(!rawTypeRepresentation);
SmartType_assert(isTy(type->isStructTy(), aEDIType.isUnionTy(), "getUnionMemberIdx"));
SmartType_assert(getNumContainedTypes() == 1);
TYPECONST Type* uMemberType = type->getContainedType(0);
unsigned numSubEDITypes = aEDIType.getNumContainedTypes();
std::vector<unsigned> indexes;
int maxWeakConsistencyLevel = -1;
unsigned maxWeakConsistencyIndex = -1;
int maxWeakConsistencyLevelEntries;
unsigned index;
for(unsigned i=0;i<numSubEDITypes;i++) {
int weakConsistencyLevel;
EDIType subEDIType = aEDIType.getContainedType(i);
if(isTypeConsistent(uMemberType, &subEDIType, true, &weakConsistencyLevel)) {
indexes.push_back(i);
if(weakConsistencyLevel > maxWeakConsistencyLevel) {
maxWeakConsistencyLevel = weakConsistencyLevel;
maxWeakConsistencyIndex = i;
maxWeakConsistencyLevelEntries = 1;
}
else if(weakConsistencyLevel == maxWeakConsistencyLevel) {
maxWeakConsistencyLevelEntries++;
}
}
}
if(indexes.size() == 0) {
//try to match names if we failed before
std::string name = EDIType::lookupUnionMemberName(type);
if(name.compare("")) {
for(unsigned i=0;i<numSubEDITypes;i++) {
EDIType subEDIType = aEDIType.getContainedType(i);
if(!subEDIType.getName().compare(name)) {
indexes.push_back(i);
maxWeakConsistencyIndex = i;
}
}
}
}
if(indexes.size() == 0) {
//No valid union member found
#if DEBUG_UNIONS
SmartTypeErr("getUnionMemberIdx: resorting to a raw type. No valid union member found for: " << getDescription());
#endif
return UINT_MAX;
}
index = maxWeakConsistencyIndex;
if(indexes.size() > 1) {
SmartTypeLog("getUnionMemberIdx: warning: multiple valid union members found, automatically selecting the first most-consistent member:");
SmartTypeLog(" - target member type is: " << TypeUtil::getDescription(uMemberType));
SmartTypeLog(" - selected index is: " << index);
for(unsigned i=0;i<indexes.size();i++) {
EDIType subEDIType = aEDIType.getContainedType(indexes[i]);
SmartTypeLog(" - " << indexes[i] << ". " << TypeUtil::getDescription(&subEDIType));
}
}
return index;
}
const SmartType* SmartType::getTopStructType(unsigned index) const {
TYPECONST Type *topType = TypeUtil::lookupTopStructType(type, index);
const EDIType *topEDIType = aEDIType.getTopStructType(index);
assert((topType && topEDIType) || (!topType && !topEDIType));
if(topType) {
const SmartType* retSmartType = new SmartType(topType, topEDIType);
return retSmartType;
}
return NULL;
}
//===----------------------------------------------------------------------===//
// Other public methods
//===----------------------------------------------------------------------===//
void SmartType::verify() const {
SmartType_assert(isTypeConsistent());
}
void SmartType::print(raw_ostream &OS) const {
OS << getDescription();
}
bool SmartType::equals(const SmartType* other, bool isDebug) const {
static std::set<std::pair<MDNode*, MDNode*> > compatibleMDNodes;
static std::set<std::pair<MDNode*, MDNode*> >::iterator compatibleMDNodesIt;
#if DEBUG_EQUALS
if(debugEquals) SmartTypeErr("COMPARING :" << getDescription() << " VS " << other->getDescription());
#endif
if(type != other->getType()) {
#if DEBUG_EQUALS
if(debugEquals) SmartTypeErr("----> false1");
#endif
return false;
}
if(isOpaqueTy() || other->isOpaqueTy()) {
return isOpaqueTy() && other->isOpaqueTy();
}
if(aEDIType.getTag() != other->getEDIType()->getTag()) {
#if DEBUG_EQUALS
if(debugEquals) SmartTypeErr("----> false1b");
#endif
return false;
}
if(isFunctionTy() && (!isTypeConsistent() || !other->isTypeConsistent())) {
//we just compare the types for inconsistent functions types
return true;
}
if(hasRawTypeRepresentation() || other->hasRawTypeRepresentation()) {
return !aEDIType.getNamesString().compare(other->getEDIType()->getNamesString());
}
unsigned numContainedTypes = getNumContainedTypes();
unsigned otherNumContainedTypes = other->getNumContainedTypes();
if(numContainedTypes != otherNumContainedTypes) {
#if DEBUG_EQUALS
if(debugEquals) SmartTypeErr("----> false2");
#endif
return false;
}
unsigned numElements = aEDIType.getNumElements();
unsigned otherNumElements = other->getEDIType()->getNumElements();
if(numElements != otherNumElements) {
#if DEBUG_EQUALS
if(debugEquals) SmartTypeErr("----> false2b");
#endif
return false;
}
std::string name = aEDIType.getName();
std::string otherName = other->getEDIType()->getName();
if(name.compare(otherName)) {
#if DEBUG_EQUALS
if(debugEquals) SmartTypeErr("----> false3: " << name << " vs " << otherName);
#endif
return false;
}
if(aEDIType.getNames().size() > 1 || other->getEDIType()->getNames().size() > 1) {
std::string namesString = aEDIType.getNamesString();
std::string otherNamesString = other->getEDIType()->getNamesString();
if(namesString.compare(otherNamesString)) {
#if DEBUG_EQUALS
if(debugEquals) SmartTypeErr("----> false4: " << namesString << " vs " << otherNamesString);
#endif
return false;
}
}
if(numContainedTypes == 0) {
#if DEBUG_EQUALS
if(debugEquals) SmartTypeErr("----> true4");
#endif
return true;
}
MDNode *node = *(aEDIType.getDIType());
MDNode *otherNode = *(other->getEDIType()->getDIType());
if(node == otherNode) {
return true;
}
for(unsigned i=0;i<SmartType::equalsNestedTypes.size();i++) {
if(type == SmartType::equalsNestedTypes[i]) {
#if DEBUG_EQUALS
if(debugEquals) SmartTypeErr("----> true5");
#endif
return true;
}
}
//before digging the type tree, see if we have these 2 metadata nodes in cache
//this gives us an impressive speedup
MDNode *minNode = node < otherNode ? node : otherNode;
MDNode *maxNode = node < otherNode ? otherNode : node;
compatibleMDNodesIt = compatibleMDNodes.find(std::pair<MDNode*, MDNode*>(minNode, maxNode));
if(compatibleMDNodesIt != compatibleMDNodes.end()) {
return true;
}
SmartType::equalsNestedTypes.push_back(type);
const SmartType* containedType = NULL;
const SmartType* otherContainedType = NULL;
bool sameContainedTypes = true;
for(unsigned i=0;i<numContainedTypes;i++) {
containedType = getContainedType(i);
otherContainedType = other->getContainedType(i);
sameContainedTypes = containedType->equals(otherContainedType);
delete containedType;
delete otherContainedType;
if(!sameContainedTypes) {
break;
}
}
SmartType::equalsNestedTypes.pop_back();
if(!sameContainedTypes) {
#if DEBUG_EQUALS
if(debugEquals) SmartTypeErr("----> false6");
#endif
return false;
}
#if DEBUG_EQUALS
if(debugEquals) SmartTypeErr("----> true7");
#endif
compatibleMDNodes.insert(std::pair<MDNode*, MDNode*>(minNode, maxNode));
return true;
}
//===----------------------------------------------------------------------===//
// Public static methods
//===----------------------------------------------------------------------===//
const SmartType* SmartType::getSmartTypeFromGV(Module &M, GlobalVariable *GV, DIGlobalVariable *DIG) {
//ignore anonymous strings
if(GV->getName().startswith(".str")) {
return NULL;
}
Value *DIGV = Backports::findDbgGlobalDeclare(GV);
if (!DIGV) {
return NULL;
}
DIGlobalVariable Var(cast<MDNode>(DIGV));
DIType aDIType = Var.getType();
const SmartType* retSmartType = new SmartType(GV->getType()->getElementType(), &aDIType);
if(DIG) {
*DIG = Var;
}
return retSmartType;
}
const SmartType* SmartType::getSmartTypeFromLV(Module &M, AllocaInst *AI, DIVariable *DIV) {
const DbgDeclareInst *DDI = Backports::FindAllocaDbgDeclare(AI);
if (!DDI) {
return NULL;
}
if(DDI == (const DbgDeclareInst *) -1) {
return (const SmartType*)-1;
}
DIVariable Var(cast<MDNode>(DDI->getVariable()));
DIType aDIType = Var.getType();
if(DIV) {
*DIV = Var;
}
const SmartType* aSmartType = new SmartType(AI->getAllocatedType(), &aDIType);
return aSmartType;
}
const SmartType* SmartType::getSmartTypeFromFunction(Module &M, Function *F, DISubprogram *DIS) {
Value *DIF = Backports::findDbgSubprogramDeclare(F);
if (!DIF) {
return NULL;
}
DISubprogram Sub(cast<MDNode>(DIF));
DIType aDIType = Sub.getType();
const SmartType* retSmartType = new SmartType(F->getType()->getElementType(), &aDIType);
if(DIS) {
*DIS = Sub;
}
return retSmartType;
}
const SmartType* SmartType::getStructSmartTypeByName(Module &M, GlobalVariable* GV, std::string &name, bool isUnion) {
std::string structName((isUnion ? "union." : "struct.") + name);
TYPECONST Type *targetType = M.getTypeByName(structName);
const EDIType *targetEDIType = EDIType::getStructEDITypeByName(name);
const SmartType *retSmartType = NULL;
if(targetType && targetEDIType) {
retSmartType = new SmartType(targetType, targetEDIType);
}
return retSmartType;
}
std::vector<const SmartType*>* SmartType::getTopStructSmartTypes(Module &M, GlobalVariable* GV) {
std::vector<std::string> names;
std::vector<unsigned> flags;
TypeUtil::parseTopStructTypes(M, GV->getType()->getElementType(), &names, &flags);
std::vector<const SmartType*> *vector = new std::vector<const SmartType*>;
for(unsigned i=0;i<names.size();i++) {
std::string entryName = names[i];
unsigned entryFlags = flags[i];
const SmartType *aSmartType = NULL;
if(!(entryFlags & TypeUtil::TYPE_ANONYMOUS) && !(entryFlags & TypeUtil::TYPE_UNNAMED)) {
aSmartType = getStructSmartTypeByName(M, GV, entryName, (entryFlags & TypeUtil::TYPE_UNION));
}
if(aSmartType == NULL) {
//this method can fail due to name clashing but is the only one possible for anonymous or unnamed struct types
const SmartType *GVSmartType = getSmartTypeFromGV(M, GV);
assert(GVSmartType && "Unable to find a match for anonymous or unnamed struct type");
aSmartType = GVSmartType->getTopStructType(i);
delete GVSmartType;
assert(aSmartType != NULL);
}
vector->push_back(aSmartType);
}
return vector;
}
//===----------------------------------------------------------------------===//
// Private methods
//===----------------------------------------------------------------------===//
void SmartType::init(TYPECONST Type *type, const EDIType *aEDIType, bool useExceptions, bool forceRawTypeRepresentation) {
this->type = type;
this->aEDIType = *aEDIType;
this->useExceptions = useExceptions;
hasExplicitContainedEDITypes = false;
isInconsistent = false;
rawTypeRepresentation = false;
unionMemberIdx = 0;
if(aEDIType->isUnionTy()) {
if(forceRawUnions) {
rawTypeRepresentation = true;
}
else {
unionMemberIdx = getUnionMemberIdx();
if(unionMemberIdx == UINT_MAX) {
rawTypeRepresentation = true;
unionMemberIdx = 0;
}
}
}
else if(forceRawTypeRepresentation || (forceRawBitfields && BitFieldAggregation::hasBitFields(type, &(this->aEDIType)))) {
rawTypeRepresentation = true;
}
}
void SmartType::normalize() {
if(isFunctionTy() && !hasExplicitContainedEDITypes) {
flattenFunctionTy();
hasExplicitContainedEDITypes = true;
}
if(!hasExplicitContainedEDITypes && !rawTypeRepresentation) {
if(!BitFieldAggregation::getBitFieldAggregations(type, &aEDIType, bfas, true)) {
//failed to determine bfas
#if DEBUG_BFAS
SmartTypeErr("normalize: resorting to a raw type. Cannot determine bfas for: " << getDescription());
#endif
rawTypeRepresentation = true;
}
}
}
void SmartType::flattenFunctionTy() {
SmartType_assert(isFunctionTy() && !hasExplicitContainedEDITypes);
SmartType_assert(explicitContainedEDITypes.size() == 0);
#if MAGIC_FLATTEN_FUNCTION_ARGS
int ret = flattenFunctionArgs(type, &aEDIType, 0);
if(ret < 0 || explicitContainedEDITypes.size() != type->getNumContainedTypes()) {
SmartTypeLog("Warning: function flattening produced an inconsistent type!");
isInconsistent = true;
}
#else
isInconsistent = true;
#endif
}
int SmartType::flattenFunctionArgs(TYPECONST Type *type, const EDIType *aEDIType, unsigned nextContainedType) {
unsigned containedTypes = type->getNumContainedTypes();
unsigned containedEDITypes = aEDIType->isUnionTy() ? 1 : aEDIType->getNumContainedTypes();
unsigned containedEDIOptions = aEDIType->isUnionTy() ? aEDIType->getNumContainedTypes() : 1;
int ret;
unsigned nextContainedEDIType = 0;
while(nextContainedEDIType < containedEDITypes) {
SmartType_assert(nextContainedType < containedTypes);
TYPECONST Type *containedType = type->getContainedType(nextContainedType);
unsigned currExplicitEDITypes = explicitContainedEDITypes.size();
unsigned i;
for(i=nextContainedEDIType;i<nextContainedEDIType+containedEDIOptions;i++) {
const EDIType containedEDIType = aEDIType->getContainedType(i);
if(isTypeConsistent(containedType, &containedEDIType)) {
explicitContainedEDITypes.push_back(new EDIType(containedEDIType));
break;
}
if(!containedEDIType.isAggregateType()) {
continue;
}
ret = flattenFunctionArgs(type, &containedEDIType, nextContainedType);
if(ret == 0) {
break;
}
}
if(i >= nextContainedEDIType+containedEDIOptions) {
while(explicitContainedEDITypes.size() > currExplicitEDITypes) {
EDIType* aEDIType = explicitContainedEDITypes[explicitContainedEDITypes.size()-1];
explicitContainedEDITypes.pop_back();
delete aEDIType;
}
return -1;
}
nextContainedType += (explicitContainedEDITypes.size() - currExplicitEDITypes);
nextContainedEDIType++;
}
return 0;
}
bool SmartType::isTy(bool isTyType, bool isTyEDIType, const char* source) const {
bool check = (isTyType && isTyEDIType) || (!isTyType && !isTyEDIType);
if(!check) {
SmartTypeErr(source << " failed");
}
SmartType_assert(check);
return isTyType;
}
//===----------------------------------------------------------------------===//
// Private static methods
//===----------------------------------------------------------------------===//
unsigned SmartType::getBFAFreeIdx(unsigned i, const std::vector<BitFieldAggregation> &inputBfas) {
for(unsigned j=0;j<inputBfas.size();j++) {
if(i<inputBfas[j].getEDITypeIndex()) {
break;
}
else if(i>inputBfas[j].getEDITypeIndex()) {
i += (inputBfas[j].getSize() - 1);
}
else {
i = inputBfas[j].getRepresentativeEDITypeIndex();
break;
}
}
return i;
}
bool SmartType::isRawTypeConsistent(TYPECONST Type *type, const EDIType *aEDIType) {
if(aEDIType->isVoidTy()) {
return type->isVoidTy() || (type->isIntegerTy() && ((IntegerType*)type)->getBitWidth() == 8);
}
if(type->isFloatingPointTy()) {
return aEDIType->isFloatingPointTy();
}
if(type->isIntegerTy()) {
if(aEDIType->isCharTy() || aEDIType->isBoolTy()) {
return (((IntegerType*)type)->getBitWidth() <= 8);
}
return aEDIType->isIntegerTy() || aEDIType->isEnumTy();
}
if(type->isFunctionTy()) {
return aEDIType->isFunctionTy();
}
if(TypeUtil::isOpaqueTy(type)) {
return (aEDIType->isOpaqueTy());
}
return false;
}
bool SmartType::isTypeConsistent2(std::vector<TYPECONST Type*> &nestedTypes, std::vector<const EDIType*> &nestedEDITypes, const SmartType *aSmartType) {
assert(aSmartType->isUseExceptions());
TYPECONST Type *type = aSmartType->getType();
const EDIType *aEDIType = aSmartType->getEDIType();
if(aEDIType->isPointerTy() || aEDIType->isUnionOrStructTy()) {
for(unsigned j=0;j<nestedTypes.size();j++) {
if(nestedTypes[j] == type && nestedEDITypes[j]->equals(aEDIType)) {
return true;
}
}
}
unsigned nTypes = type->getNumContainedTypes();
unsigned nEDITypes = aEDIType->getNumContainedTypes();
if(nTypes == 0 || nEDITypes == 0) {
if(nTypes != 0 || nEDITypes != 0) {
return false;
}
return isRawTypeConsistent(type, aEDIType);
}
if(!aSmartType->verifyTy()) {
return false;
}
unsigned numContainedTypes = aSmartType->getNumContainedTypes();
nestedTypes.push_back(type);
nestedEDITypes.push_back(aEDIType);
for(unsigned i=0;i<numContainedTypes;i++) {
const SmartType *containedSmartType = aSmartType->getContainedType(i);
assert(containedSmartType->isUseExceptions());
SmartType clonedSmartType(*containedSmartType);
assert(clonedSmartType.isUseExceptions());
delete containedSmartType;
if(!isTypeConsistent2(nestedTypes, nestedEDITypes, &clonedSmartType)) {
return false;
}
}
nestedTypes.pop_back();
nestedEDITypes.pop_back();
return true;
}
bool SmartType::isTypeConsistent2(TYPECONST Type *type, const EDIType *aEDIType) {
/* Exception-handling based isTypeConsistent(). Broken with -fno-exceptions. */
static std::vector<TYPECONST Type*> nestedTypes;
static std::vector<const EDIType*> nestedEDITypes;
static unsigned level = 0;
if(level == 0) {
nestedTypes.clear();
nestedEDITypes.clear();
}
bool checkTypeConsistent = false;
bool useExceptions = true;
level++;
assert(useExceptions);
TRY(
const SmartType aSmartType(type, aEDIType, useExceptions);
checkTypeConsistent = isTypeConsistent2(nestedTypes, nestedEDITypes, &aSmartType);
)
CATCH(std::exception& e,
checkTypeConsistent = false;
)
level--;
return checkTypeConsistent;
}
bool SmartType::isTypeConsistent(TYPECONST Type *type, const EDIType *aEDIType, bool useBfas, int *weakConsistencyLevel) {
static std::vector<TYPECONST Type*> nestedTypes;
static std::vector<const EDIType*> nestedEDITypes;
static unsigned level = 0;
if(level == 0) {
if(weakConsistencyLevel) {
*weakConsistencyLevel = INT_MAX;
}
}
if(aEDIType->isPointerTy() || aEDIType->isUnionOrStructTy()) {
for(unsigned j=0;j<nestedTypes.size();j++) {
if(nestedTypes[j] == type && nestedEDITypes[j]->equals(aEDIType)) {
return true;
}
}
}
unsigned nTypes = type->getNumContainedTypes();
unsigned nEDITypes = aEDIType->getNumContainedTypes();
if(nTypes == 0 || nEDITypes == 0) {
if(nTypes != 0 || nEDITypes != 0) {
return false;
}
return isRawTypeConsistent(type, aEDIType);
}
if(aEDIType->isOpaqueTy()) {
return (TypeUtil::isOpaqueTy(type));
}
bool isArrayOrVectorTy = aEDIType->isArrayTy() || aEDIType->isVectorTy();
unsigned nEDINumElements = aEDIType->getNumElements();
if(aEDIType->isDerivedType() || isArrayOrVectorTy) {
TYPECONST Type *nextType = type;
if(aEDIType->isPointerTy()) {
if(!type->isPointerTy()) {
return false;
}
nextType = type->getContainedType(0);
}
else if(aEDIType->isArrayTy()) {
if(!type->isArrayTy() || ((ArrayType*)type)->getNumElements() != nEDINumElements) {
return false;
}
nextType = type->getContainedType(0);
}
else if(aEDIType->isVectorTy()) {
if(!type->isVectorTy() || ((VectorType*)type)->getNumElements() != nEDINumElements) {
return false;
}
nextType = type->getContainedType(0);
}
const EDIType aEDISubType(aEDIType->getContainedType(0));
nestedEDITypes.push_back(aEDIType);
nestedTypes.push_back(type);
level++;
bool ret = isTypeConsistent(nextType, &aEDISubType, useBfas, weakConsistencyLevel);
level--;
nestedTypes.pop_back();
nestedEDITypes.pop_back();
return ret;
}
else if(aEDIType->isCompositeType()) {
if(!aEDIType->isUnionOrStructTy() && !aEDIType->isVectorTy() && !aEDIType->isFunctionTy()) {
return false;
}
if(aEDIType->isUnionOrStructTy() && !type->isStructTy()) {
return false;
}
if(aEDIType->isVectorTy() && !type->isVectorTy()) {
return false;
}
if(aEDIType->isFunctionTy() && !type->isFunctionTy()) {
return false;
}
if(aEDIType->isUnionTy() || aEDIType->isFunctionTy()) {
if(weakConsistencyLevel) {
*weakConsistencyLevel = level;
}
return true; //xxx we should be less conservative here
}
unsigned numContainedEDITypes = aEDIType->getNumContainedTypes();
std::vector<BitFieldAggregation> myBfas;
if(numContainedEDITypes != type->getNumContainedTypes()) {
if(!useBfas) {
return false;
}
if(!BitFieldAggregation::getBitFieldAggregations(type, aEDIType, myBfas, true)) {
return false;
}
for(unsigned i=0;i<myBfas.size();i++) {
numContainedEDITypes -= (myBfas[i].getSize() - 1);
}
if(numContainedEDITypes != type->getNumContainedTypes()) {
return false;
}
nestedEDITypes.push_back(aEDIType);
nestedTypes.push_back(type);
level++;
for(unsigned i=0;i<numContainedEDITypes;i++) {
const EDIType aEDISubType(aEDIType->getContainedType(getBFAFreeIdx(i, myBfas)));
if(!isTypeConsistent(type->getContainedType(i), &aEDISubType, useBfas, weakConsistencyLevel)) {
level--;
nestedTypes.pop_back();
nestedEDITypes.pop_back();
return false;
}
}
level--;
nestedTypes.pop_back();
nestedEDITypes.pop_back();
return true;
}
nestedEDITypes.push_back(aEDIType);
nestedTypes.push_back(type);
level++;
for(unsigned i=0;i<numContainedEDITypes;i++) {
const EDIType aEDISubType(aEDIType->getContainedType(i));
if(!isTypeConsistent(type->getContainedType(i), &aEDISubType, useBfas, weakConsistencyLevel)) {
level--;
nestedTypes.pop_back();
nestedEDITypes.pop_back();
return false;
}
}
level--;
nestedTypes.pop_back();
nestedEDITypes.pop_back();
return true;
}
return false;
}
std::vector<TYPECONST Type*> SmartType::equalsNestedTypes;
}