diff --git a/src/mapleall/maple_ir/include/mir_type.h b/src/mapleall/maple_ir/include/mir_type.h index 8c9cf8d79f8e782db59d30aa749577cd6ae4d37a..73e3031bb36ec25d575a200016a198a29d54e42f 100755 --- a/src/mapleall/maple_ir/include/mir_type.h +++ b/src/mapleall/maple_ir/include/mir_type.h @@ -396,6 +396,9 @@ class GenericAttrs { #if MIR_FEATURE_FULL constexpr size_t kShiftNumOfTypeKind = 8; constexpr size_t kShiftNumOfNameStrIdx = 6; + +class MIRStructType; + class MIRType { public: MIRType(MIRTypeKind kind, PrimType pType) : typeKind(kind), primType(pType) {} @@ -458,6 +461,10 @@ class MIRType { return GetPrimTypeSize(primType); } + virtual uint32 GetAlign() const { + return GetPrimTypeSize(primType); + } + virtual bool HasVolatileField() const { return false; } @@ -515,6 +522,9 @@ class MIRType { constexpr uint8 idxShift = 2; return ((static_cast(primType) << idxShift) + (typeKind << kShiftNumOfTypeKind)) % kTypeHashLength; } + virtual bool HasFields() const { return false; } + virtual size_t NumberOfFieldIDs() { return 0; } // total number of field IDs the type is consisted of, excluding its own field ID + virtual MIRStructType *EmbeddedStructType() { return nullptr; } // return any struct type directly embedded in this type protected: MIRTypeKind typeKind; @@ -640,18 +650,8 @@ class MIRArrayType : public MIRType { void Dump(int indent, bool dontUseName) const override; - size_t GetSize() const override { - size_t elemSize = GetElemType()->GetSize(); - if (elemSize == 0) { - return 0; - } - size_t numElems = sizeArray[0]; - for (size_t i = 1; i < dim; ++i) { - CHECK_FATAL(i < kMaxArrayDim, "array index out of range"); - numElems *= sizeArray[i]; - } - return elemSize * numElems; - } + size_t GetSize() const override; + uint32 GetAlign() const override; size_t GetHashIndex() const override { constexpr uint8 idxShift = 2; @@ -667,6 +667,9 @@ class MIRArrayType : public MIRType { std::string GetMplTypeName() const override; std::string GetCompactMplTypeName() const override; + bool HasFields() const override; + size_t NumberOfFieldIDs() override; + MIRStructType *EmbeddedStructType() override; private: TyIdx eTyIdx{ 0 }; uint16 dim = 0; @@ -713,6 +716,10 @@ class MIRFarrayType : public MIRType { std::string GetMplTypeName() const override; std::string GetCompactMplTypeName() const override; + bool HasFields() const override; + size_t NumberOfFieldIDs() override; + MIRStructType *EmbeddedStructType() override; + private: TyIdx elemTyIdx; }; @@ -969,6 +976,7 @@ class MIRStructType : public MIRType { bool IsLocal() const; size_t GetSize() const override; + uint32 GetAlign() const override; size_t GetHashIndex() const override { return ((static_cast(nameStrIdx) << kShiftNumOfNameStrIdx) + (typeKind << kShiftNumOfTypeKind)) % @@ -1062,6 +1070,10 @@ class MIRStructType : public MIRType { CHECK_FATAL(false, "can not use PushbackIsString"); } + bool HasFields() const override { return true; } + size_t NumberOfFieldIDs() override; + MIRStructType *EmbeddedStructType() override { return this; } + virtual FieldPair TraverseToFieldRef(FieldID &fieldID) const; std::string GetMplTypeName() const override; std::string GetCompactMplTypeName() const override; @@ -1279,6 +1291,8 @@ class MIRClassType : public MIRStructType { kTypeHashLength; } + size_t NumberOfFieldIDs() override; + private: TyIdx parentTyIdx{ 0 }; std::vector interfacesImplemented{}; // for the list of interfaces the class implements @@ -1393,6 +1407,10 @@ class MIRInterfaceType : public MIRStructType { kTypeHashLength; } + bool HasFields() const override { return false; } + size_t NumberOfFieldIDs() override { return 0; } + MIRStructType *EmbeddedStructType() override { return nullptr; } + private: std::vector parentsTyIdx{}; // multiple inheritence std::vector info{}; diff --git a/src/mapleall/maple_ir/src/mir_type.cpp b/src/mapleall/maple_ir/src/mir_type.cpp index 5058d1c5875e6539b895006c6e16fb0a0267a16e..260f6bb7d60a3a7784024040da2e13de797b40fc 100755 --- a/src/mapleall/maple_ir/src/mir_type.cpp +++ b/src/mapleall/maple_ir/src/mir_type.cpp @@ -133,6 +133,10 @@ bool IsNoCvtNeeded(PrimType toType, PrimType fromType) { case PTY_i8: case PTY_i16: return fromType == PTY_i32; + case PTY_u64: + return fromType == PTY_ptr; + case PTY_ptr: + return fromType == PTY_u64; default: return false; } @@ -490,6 +494,45 @@ void MIRFuncType::Dump(int indent, bool dontUseName) const { LogInfo::MapleLogger() << ">"; } +static constexpr uint64 RoundUpConst(uint64 offset, uint8 align) { + return (-align) & (offset + align - 1); +} + +static inline uint64 RoundUp(uint64 offset, uint8 align) { + if (align == 0) { + return offset; + } + return RoundUpConst(offset, align); +} + +static constexpr uint64 RoundDownConst(uint64 offset, uint8 align) { + return (-align) & offset; +} + +static inline uint64 RoundDown(uint64 offset, uint8 align) { + if (align == 0) { + return offset; + } + return RoundDownConst(offset, align); +} + +size_t MIRArrayType::GetSize() const { + size_t elemsize = GetElemType()->GetSize(); + if (elemsize == 0) { + return 0; + } + elemsize = RoundUp(elemsize, typeAttrs.GetAlign()); + size_t numelems = sizeArray[0]; + for (int i = 1; i < dim; i++) { + numelems *= sizeArray[i]; + } + return elemsize * numelems; +} + +uint32 MIRArrayType::GetAlign() const { + return std::max(GetElemType()->GetAlign(), typeAttrs.GetAlign()); +} + void MIRArrayType::Dump(int indent, bool dontUseName) const { if (!dontUseName && CheckAndDumpTypeName(nameStrIdx, nameIsLocal)) { return; @@ -919,27 +962,78 @@ static void DumpInterfaces(std::vector interfaces, int indent) { size_t MIRStructType::GetSize() const { if (typeKind == kTypeUnion) { - size_t maxSize = GetElemType(0)->GetSize(); - for (size_t i = 1; i < fields.size(); ++i) { - size_t size = GetElemType(i)->GetSize(); - if (size == 0) { - return 0; - } + if (fields.size() == 0) { + return isCPlusPlus ? 1 : 0; + } + size_t maxSize = 0; + for (size_t i = 0; i < fields.size(); ++i) { + TyIdxFieldAttrPair tfap = GetFieldTyIdxAttrPair(i); + MIRType *fieldType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tfap.first); + size_t size = RoundUp(fieldType->GetSize(), tfap.second.GetAlign()); if (maxSize < size) { maxSize = size; } } return maxSize; } - size_t size = 0; + // since there may be bitfields, perform a layout process for the fields + size_t byteOfst = 0; + size_t bitOfst = 0; for (size_t i = 0; i < fields.size(); ++i) { - size_t fieldSize = GetElemType(i)->GetSize(); - if (fieldSize == 0) { - return 0; + TyIdxFieldAttrPair tfap = GetFieldTyIdxAttrPair(i); + MIRType *fieldType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tfap.first); + if (fieldType->GetKind() != kTypeBitField) { + if (byteOfst * 8 < bitOfst) { + byteOfst = (bitOfst >> 3) + 1; + } + byteOfst = RoundUp(byteOfst, std::max(fieldType->GetAlign(), tfap.second.GetAlign())); + byteOfst += fieldType->GetSize(); + bitOfst = byteOfst * 8; + } else { + MIRBitFieldType *bitfType = static_cast(fieldType); + if (bitfType->GetFieldSize() == 0) { // special case, for aligning purpose + bitOfst = RoundUp(bitOfst, GetPrimTypeBitSize(bitfType->GetPrimType())); + byteOfst = bitOfst >> 3; + } else { + if (RoundDown(bitOfst + bitfType->GetFieldSize() - 1, GetPrimTypeBitSize(bitfType->GetPrimType())) != + RoundDown(bitOfst, GetPrimTypeBitSize(bitfType->GetPrimType()))) { + bitOfst = RoundUp(bitOfst, GetPrimTypeBitSize(bitfType->GetPrimType())); + byteOfst = bitOfst >> 3; + } + bitOfst += bitfType->GetFieldSize(); + byteOfst = bitOfst >> 3; + } } - size += fieldSize; } - return size; + if (byteOfst * 8 < bitOfst) { + byteOfst = (bitOfst >> 3) + 1; + } + byteOfst = RoundUp(byteOfst, GetAlign()); + if (byteOfst == 0 && isCPlusPlus) { + return 1; // empty struct in C++ has size 1 + } + return byteOfst; +} + +uint32 MIRStructType::GetAlign() const { + if (fields.size() == 0) { + return 0; + } + uint8 maxAlign = 1; + for (size_t i = 0; i < fields.size(); ++i) { + TyIdxFieldAttrPair tfap = GetFieldTyIdxAttrPair(i); + MIRType *fieldType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tfap.first); + uint32 algn = fieldType->GetAlign(); + if (fieldType->GetKind() == kTypeBitField) { + algn = GetPrimTypeSize(fieldType->GetPrimType()); + } else { + algn = std::max(algn, tfap.second.GetAlign()); + } + if (maxAlign < algn) { + maxAlign = algn; + } + } + return maxAlign; } void MIRStructType::DumpFieldsAndMethods(int indent, bool hasMethod) const { @@ -1152,6 +1246,21 @@ std::string MIRArrayType::GetMplTypeName() const { return ss.str(); } +bool MIRArrayType::HasFields() const { + MIRType *elemType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(eTyIdx); + return elemType->HasFields(); +} + +size_t MIRArrayType::NumberOfFieldIDs() { + MIRType *elemType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(eTyIdx); + return elemType->NumberOfFieldIDs(); +} + +MIRStructType *MIRArrayType::EmbeddedStructType() { + MIRType *elemType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(eTyIdx); + return elemType->EmbeddedStructType(); +} + MIRType *MIRFarrayType::GetElemType() const { return GlobalTables::GetTypeTable().GetTypeFromTyIdx(elemTyIdx); } @@ -1173,6 +1282,21 @@ std::string MIRFarrayType::GetMplTypeName() const { return ss.str(); } +bool MIRFarrayType::HasFields() const { + MIRType *elemType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(elemTyIdx); + return elemType->HasFields(); +} + +size_t MIRFarrayType::NumberOfFieldIDs() { + MIRType *elemType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(elemTyIdx); + return elemType->NumberOfFieldIDs(); +} + +MIRStructType *MIRFarrayType::EmbeddedStructType() { + MIRType *elemType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(elemTyIdx); + return elemType->EmbeddedStructType(); +} + bool MIRFuncType::EqualTo(const MIRType &type) const { if (type.GetKind() != typeKind) { return false; @@ -1191,7 +1315,24 @@ bool MIRBitFieldType::EqualTo(const MIRType &type) const { } bool MIRStructType::EqualTo(const MIRType &type) const { - return (typeKind == type.GetKind() && nameStrIdx == type.GetNameStrIdx()); + if (type.GetKind() != typeKind) { + return false; + } + const MIRStructType *p = dynamic_cast(&type); + CHECK_FATAL(p != nullptr, "p is null in MIRStructType::EqualTo"); + if (fields != p->fields) { + return false; + } + if (staticFields != p->staticFields) { + return false; + } + if (parentFields != p->parentFields) { + return false; + } + if (methods != p->methods) { + return false; + } + return true; } std::string MIRStructType::GetCompactMplTypeName() const { @@ -1203,6 +1344,9 @@ MIRType *MIRStructType::GetElemType(uint32 n) const { } MIRType *MIRStructType::GetFieldType(FieldID fieldID) { + if (fieldID == 0) { + return this; + } const FieldPair &fieldPair = TraverseToField(fieldID); return GlobalTables::GetTypeTable().GetTypeFromTyIdx(fieldPair.second.first); } @@ -1220,11 +1364,52 @@ std::string MIRStructType::GetMplTypeName() const { } bool MIRClassType::EqualTo(const MIRType &type) const { - return (typeKind == type.GetKind() && nameStrIdx == type.GetNameStrIdx()); + if (type.GetKind() != typeKind) { + return false; + } + bool structeq = MIRStructType::EqualTo(type); + if (!structeq) { + return false; + } + + const MIRClassType &classty = static_cast(type); + // classes have parent except empty/thirdparty classes + if (parentTyIdx != classty.parentTyIdx) { + return false; + } + + if (interfacesImplemented != classty.interfacesImplemented) { + return false; + } + if (info != classty.info) { + return false; + } + if (infoIsString != classty.infoIsString) { + return false; + } + return true; } bool MIRInterfaceType::EqualTo(const MIRType &type) const { - return (typeKind == type.GetKind() && nameStrIdx == type.GetNameStrIdx()); + if (type.GetKind() != typeKind) { + return false; + } + bool structeq = MIRStructType::EqualTo(type); + if (!structeq) { + return false; + } + + const MIRInterfaceType &interfacety = static_cast(type); + if (parentsTyIdx != interfacety.parentsTyIdx) { + return false; + } + if (info != interfacety.info) { + return false; + } + if (infoIsString != interfacety.infoIsString) { + return false; + } + return true; } bool MIRTypeByName::EqualTo(const MIRType &type) const { @@ -1397,6 +1582,15 @@ bool MIRInterfaceType::HasTypeParam() const { return false; } +size_t MIRClassType::NumberOfFieldIDs() { + size_t parentFieldIDs = 0; + if (parentTyIdx != TyIdx(0)) { + MIRType *parentty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(parentTyIdx); + parentFieldIDs = parentty->NumberOfFieldIDs(); + } + return parentFieldIDs + MIRStructType::NumberOfFieldIDs(); +} + FieldPair MIRClassType::TraverseToFieldRef(FieldID &fieldID) const { if (parentTyIdx != 0u) { auto *parentClassType = @@ -1456,6 +1650,16 @@ std::string MIRPtrType::GetCompactMplTypeName() const { return pointedType->GetCompactMplTypeName(); } +size_t MIRStructType::NumberOfFieldIDs() { + size_t count = 0; + for (FieldPair curpair : fields) { + count++; + MIRType *curfieldtype = GlobalTables::GetTypeTable().GetTypeFromTyIdx(curpair.second.first); + count += curfieldtype->NumberOfFieldIDs(); + } + return count; +} + TypeAttrs FieldAttrs::ConvertToTypeAttrs() { TypeAttrs attr; constexpr uint32 maxAttrNum = 64;