diff --git a/src/bin/jbc2mpl b/src/bin/jbc2mpl index 32e63dcaad1927944d1a817bc66e15e76eadc632..fe1e8f579795e378e235cad2475a617bf21f5c17 100755 Binary files a/src/bin/jbc2mpl and b/src/bin/jbc2mpl differ diff --git a/src/bin/maple b/src/bin/maple index dd405083d60af04723ca9e58b7873704ec1c1f72..b08c429a502f99b8e1427f6d8f9864265cf1932b 100755 Binary files a/src/bin/maple and b/src/bin/maple differ diff --git a/src/deplibs/libmplphase.a b/src/deplibs/libmplphase.a index dbe5c974020e89e8671a46d3e2335b17d4ee7c02..7e369f90ca02ff4c0535fa08c1f4736ce8a149b1 100644 Binary files a/src/deplibs/libmplphase.a and b/src/deplibs/libmplphase.a differ diff --git a/src/maple_ipa/include/module_phases.def b/src/maple_ipa/include/module_phases.def index 2e78edcf3a05a274cea190ac5e1c197d18219432..ddecb1390f61501fb551a9b9b42a563afcad1af1 100644 --- a/src/maple_ipa/include/module_phases.def +++ b/src/maple_ipa/include/module_phases.def @@ -20,6 +20,7 @@ MODAPHASE(MoPhase_CALLGRAPH_ANALYSIS, DoCallGraph) MODTPHASE(MoPhase_GENNATIVESTUBFUNC, DoGenerateNativeStubFunc) MODAPHASE(MoPhase_VTABLEANALYSIS, DoVtableAnalysis) MODAPHASE(MoPhase_REFLECTIONANALYSIS, DoReflectionAnalysis) +MODAPHASE(MoPhase_ANNOTATIONANALYSIS, DoAnnotationAnalysis) MODTPHASE(MoPhase_VTABLEIMPL, DoVtableImpl) MODTPHASE(MoPhase_JAVAINTRNLOWERING, DoJavaIntrnLowering) MODTPHASE(MoPhase_JAVAEHLOWER, JavaEHLowererPhase) diff --git a/src/maple_ipa/include/retype.h b/src/maple_ipa/include/retype.h index 456524adcfdc781cc77678c255bf0638f74e6919..670a5ab713a934673a98f263a45cf6fd630cd34a 100644 --- a/src/maple_ipa/include/retype.h +++ b/src/maple_ipa/include/retype.h @@ -25,13 +25,15 @@ class Retype { virtual ~Retype() {} - void ReplaceRetypeExpr(const BaseNode &opnd) const; - void RetypeStmt(MIRFunction &func) const; - void DoRetype() const; + void ReplaceRetypeExpr(const BaseNode &opnd); + void RetypeStmt(MIRFunction &func); + void DoRetype(); private: MIRModule *mirModule; MapleAllocator allocator; + std::map reg2varGenericInfo; + void TransmitGenericInfo(MIRFunction &func, StmtNode &stmt); }; } // namespace maple #endif // MAPLE_IPA_INCLUDE_RETYPE_H diff --git a/src/maple_ipa/src/module_phase_manager.cpp b/src/maple_ipa/src/module_phase_manager.cpp index d7b96915bfd753087b7989d214f14df74c0c0721..3df676ec5d6f705424ca3dec9a965b6f9acd77eb 100644 --- a/src/maple_ipa/src/module_phase_manager.cpp +++ b/src/maple_ipa/src/module_phase_manager.cpp @@ -24,6 +24,7 @@ #include "native_stub_func.h" #include "vtable_analysis.h" #include "reflection_analysis.h" +#include "annotation_analysis.h" #include "vtable_impl.h" #include "java_intrn_lowering.h" #include "java_eh_lower.h" diff --git a/src/maple_ipa/src/retype.cpp b/src/maple_ipa/src/retype.cpp index b89437398aa2c7c6e00df7bad5ef0418f435825c..99ec7d9bb8e5bd93d5ca8a01b44930cadb1594ec 100644 --- a/src/maple_ipa/src/retype.cpp +++ b/src/maple_ipa/src/retype.cpp @@ -17,7 +17,8 @@ #include namespace maple { -void Retype::ReplaceRetypeExpr(const BaseNode &expr) const { +class AnnotationType; +void Retype::ReplaceRetypeExpr(const BaseNode &expr) { if (expr.NumOpnds() == 0) { return; } @@ -31,7 +32,35 @@ void Retype::ReplaceRetypeExpr(const BaseNode &expr) const { } } -void Retype::RetypeStmt(MIRFunction &func) const { +void Retype::TransmitGenericInfo(MIRFunction &func, StmtNode &stmt) { + if (stmt.GetOpCode() != OP_dassign) { + return; + } + DassignNode &dassignNode = static_cast(stmt); + BaseNode *rhs = static_cast(stmt).GetRHS(); + if (!rhs->IsLeaf()) { + return; + } + GStrIdx lhsNameStrIdx = func.GetLocalOrGlobalSymbol(dassignNode.GetStIdx())->GetNameStrIdx(); + GStrIdx rhsNameStrIdx = func.GetLocalOrGlobalSymbol(static_cast(rhs)->GetStIdx())->GetNameStrIdx(); + const MapleMap &map = func.GetAliasVarMap(); + if (reg2varGenericInfo.find(lhsNameStrIdx) == reg2varGenericInfo.end() || + reg2varGenericInfo[lhsNameStrIdx].sigStrIdx == 0) { + return; + } + if (reg2varGenericInfo.find(rhsNameStrIdx) != reg2varGenericInfo.end() && + reg2varGenericInfo[rhsNameStrIdx].sigStrIdx != 0) { + return; + } + MIRAliasVars aliasVar = reg2varGenericInfo[lhsNameStrIdx]; + aliasVar.memPoolStrIdx = rhsNameStrIdx; + if (map.find(rhsNameStrIdx) != map.end() && map.at(rhsNameStrIdx).memPoolStrIdx != rhsNameStrIdx) { + CHECK_FATAL(false, "must be"); + } + func.SetAliasVarMap(rhsNameStrIdx, aliasVar); +} + +void Retype::RetypeStmt(MIRFunction &func) { if (func.IsEmpty()) { return; } @@ -43,6 +72,7 @@ void Retype::RetypeStmt(MIRFunction &func) const { BaseNode *opnd = stmt.Opnd(i); if (opnd->GetOpCode() == OP_retype) { stmt.SetOpnd(opnd->Opnd(0), i); + TransmitGenericInfo(func, stmt); continue; } else { ReplaceRetypeExpr(*opnd); @@ -51,12 +81,18 @@ void Retype::RetypeStmt(MIRFunction &func) const { } } -void Retype::DoRetype() const { +void Retype::DoRetype() { for (MIRFunction *func : mirModule->GetFunctionList()) { if (func->IsEmpty()) { continue; } + for (auto pair : func->GetAliasVarMap()) { + GStrIdx varNameStrIdx = pair.first; + GStrIdx regNameStrIdx = pair.second.memPoolStrIdx; + reg2varGenericInfo[regNameStrIdx] = pair.second; + } RetypeStmt(*func); + reg2varGenericInfo.clear(); } } } // namespace maple diff --git a/src/maple_ir/include/metadata_layout.h b/src/maple_ir/include/metadata_layout.h index 7c750babfafc66f7a6618f056d9df17400945409..65427de33613aa1571dba8e85aa1fa0e8e2a3dc1 100644 --- a/src/maple_ir/include/metadata_layout.h +++ b/src/maple_ir/include/metadata_layout.h @@ -214,7 +214,7 @@ struct MByteRef32 { }; // MethodMeta defined in methodmeta.h -// FieldMeta defined in FieldMeta.h +// FieldMeta defined in fieldmeta.h // MethodDesc contains MethodMetadata and stack map struct MethodDesc { // relative offset for method metadata relative to current PC. diff --git a/src/maple_ir/include/mir_function.h b/src/maple_ir/include/mir_function.h index b3be8edded0493811d54d46130707e825507f4ed..1b337b492284f81e40550a93231d95559f69c6fb 100644 --- a/src/maple_ir/include/mir_function.h +++ b/src/maple_ir/include/mir_function.h @@ -786,6 +786,41 @@ class MIRFunction { return codeMemPoolAllocator; } + void AddFuncGenericDeclare(GenericDeclare *g) { + genericDeclare.push_back(g); + } + + void AddFuncGenericArg(AnnotationType *a) { + genericArg.push_back(a); + } + + void AddFuncGenericRet(AnnotationType *r) { + genericRet = r; + } + + void AddFuncLocalGenericVar(GStrIdx str, AnnotationType *at) { + genericLocalVar[str] = at; + } + + MapleVector &GetFuncGenericDeclare() { + return genericDeclare; + } + + MapleVector &GetFuncGenericArg() { + return genericArg; + } + + AnnotationType *GetFuncGenericRet() { + return genericRet; + } + + AnnotationType *GetFuncLocalGenericVar(GStrIdx str) { + if (genericLocalVar.find(str) == genericLocalVar.end()) { + return nullptr; + } + return genericLocalVar[str]; + } + void AddProfileDesc(uint64 hash, uint32 start, uint32 end) { profileDesc = module->GetMemPool()->New(hash, start, end); @@ -814,6 +849,11 @@ class MIRFunction { MapleVector argumentsTyIdx{module->GetMPAllocator().Adapter()}; // arguments types of this function MapleVector argumentsAttrs{module->GetMPAllocator().Adapter()}; + MapleVector genericDeclare{module->GetMPAllocator().Adapter()}; + MapleVector genericArg{module->GetMPAllocator().Adapter()}; + MapleMap genericLocalVar{module->GetMPAllocator().Adapter()}; + AnnotationType *genericRet = nullptr; + MIRSymbolTable *symTab = nullptr; MIRTypeNameTable *typeNameTab = nullptr; MIRLabelTable *labelTab = nullptr; diff --git a/src/maple_ir/include/mir_module.h b/src/maple_ir/include/mir_module.h index 06db828bbb7155986ac7ccb4380b99d265851745..2098bcf1cd1cf6adc3e3ddaf91ed4bc1655c1e9a 100644 --- a/src/maple_ir/include/mir_module.h +++ b/src/maple_ir/include/mir_module.h @@ -137,6 +137,12 @@ class MIRModule { const MapleAllocator &GetMPAllocator() const { return memPoolAllocator; } + + void ChangePragmaMemPool(MemPool *newPragma) { + pragmaMemPool = newPragma; + pragmaMemPoolAllocator.SetMemPool(newPragma); + } + MapleAllocator &GetMPAllocator() { return memPoolAllocator; } diff --git a/src/maple_ir/include/mir_type.h b/src/maple_ir/include/mir_type.h index 2870fb36a925e0ed68c94491faf0fe6940a46110..feb7bcb4e278b02ebfa10f4af04e56103d9050d3 100644 --- a/src/maple_ir/include/mir_type.h +++ b/src/maple_ir/include/mir_type.h @@ -694,7 +694,9 @@ using MethodPair = std::pair; using MethodVector = std::vector; using MethodPtrVector = std::vector; using MIREncodedArray = std::vector; - +class GenericDeclare; +class AnnotationType; +class GenericType; // used by kTypeStruct, kTypeStructIncomplete, kTypeUnion class MIRStructType : public MIRType { public: @@ -974,6 +976,36 @@ class MIRStructType : public MIRType { CHECK_FATAL(false, "can not use GetPragmaVec"); } + std::vector& GetGenericDeclare() { + return genericDeclare; + } + + void AddClassGenericDeclare(GenericDeclare *gd) { + genericDeclare.push_back(gd); + } + + void AddFieldGenericDeclare(GStrIdx g, AnnotationType *a) { + if (fieldGenericDeclare.find(g) != fieldGenericDeclare.end()) { + CHECK_FATAL(fieldGenericDeclare[g] == a, "MUST BE"); + } + fieldGenericDeclare[g] = a; + } + + AnnotationType *GetFieldGenericDeclare(GStrIdx g) { + if (fieldGenericDeclare.find(g) == fieldGenericDeclare.end()) { + return nullptr; + } + return fieldGenericDeclare[g]; + } + + void AddInheritaceGeneric(GenericType *a) { + inheritanceGeneric.push_back(a); + } + + std::vector &GetInheritanceGeneric() { + return inheritanceGeneric; + } + virtual const MIREncodedArray &GetStaticValue() const { CHECK_FATAL(false, "can not use GetStaticValue"); } @@ -1013,6 +1045,9 @@ class MIRStructType : public MIRType { mutable bool hasVolatileField = false; // for caching computed value mutable bool hasVolatileFieldSet = false; // if true, just read hasVolatileField; // otherwise compute to initialize hasVolatileField + std::vector genericDeclare; + std::map fieldGenericDeclare; + std::vector inheritanceGeneric; private: FieldPair TraverseToField(FieldID fieldID) const ; FieldPair TraverseToField(GStrIdx fieldStrIdx) const ; diff --git a/src/maple_ir/src/parser.cpp b/src/maple_ir/src/parser.cpp index 0333f127eba4e9765eadb837db56e556b73b3a43..d0fa6ae8760c3bb7c92b6fe8232dfdbdadcb35ae 100644 --- a/src/maple_ir/src/parser.cpp +++ b/src/maple_ir/src/parser.cpp @@ -2203,7 +2203,7 @@ bool MIRParser::ParseAlias(StmtNodePtr&) { } GStrIdx signStrIdx(0); if (lexer.GetTokenKind() == TK_string) { - // ignore the signature string + signStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(lexer.GetName()); lexer.NextToken(); } MIRAliasVars aliasVar; diff --git a/src/mpl2mpl/BUILD.gn b/src/mpl2mpl/BUILD.gn index 90bdf75c994eb11fa215a836645aab30009587c9..1d050a34f1590bfd8b442e863c12efbf11ab611a 100644 --- a/src/mpl2mpl/BUILD.gn +++ b/src/mpl2mpl/BUILD.gn @@ -38,6 +38,7 @@ src_libmpl2mpl = [ "src/constantfold.cpp", "src/analyzector.cpp", "src/coderelayout.cpp", + "src/annotation_analysis.cpp", ] configs = [ "${MAPLEALL_ROOT}:mapleallcompilecfg" ] diff --git a/src/mpl2mpl/include/annotation_analysis.h b/src/mpl2mpl/include/annotation_analysis.h new file mode 100644 index 0000000000000000000000000000000000000000..101916fb0235f22451d8292e418fc5e4478b8fa5 --- /dev/null +++ b/src/mpl2mpl/include/annotation_analysis.h @@ -0,0 +1,297 @@ +/* + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * + * http://license.coscl.org.cn/MulanPSL + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v1 for more details. + */ +#ifndef MPL2MPL_INCLUDE_ANNOTATION_ANALYSIS_H +#define MPL2MPL_INCLUDE_ANNOTATION_ANALYSIS_H +#include "class_hierarchy.h" +#include "namemangler.h" + +namespace maple { +enum ATokenKind { + kEnd, + kChar, + kTemplateStart, + kTemplateEnd, + kAClassName, + kPrimeTypeName, + kTemplateName, + kExtend, + kSuper, + kArgumentStart, + kArgumentEnd, + kMatch, + kArray, + kString, + kSubClass, + kSemiComma +}; + +enum AKind { + kGenericType, + kGenericDeclare, + kGenericMatch, + kPrimeType, + kExtendType +}; + +enum EInfo { + kHierarchyExtend, + kHierarchyHSuper, + kArrayType +}; + +class AnnotationType { + public: + static int atime; + AnnotationType(AKind ak, GStrIdx strIdx) : id(atime++), kind(ak), typeName(strIdx) {} + ~AnnotationType() = default; + virtual const std::string GetName() const { + return GlobalTables::GetStrTable().GetStringFromStrIdx(typeName); + } + + GStrIdx GetGStrIdx() { + return typeName; + } + + AKind GetKind() const { + return kind; + } + + int GetId() { + return id; + } + + virtual void Dump(); + virtual void ReWriteType(std::string &) { + CHECK_FATAL(false, "impossible"); + } + + protected: + int id; + AKind kind; + GStrIdx typeName; +}; + +class GenericDeclare; +class GenericType : public AnnotationType { + public: + GenericType(GStrIdx strIdx, MIRType *ms, MapleAllocator &alloc) + :AnnotationType(kGenericType, strIdx), + mirStructType(ms), + GenericArg(alloc.Adapter()), + ArgOrder(alloc.Adapter()) {} + ~GenericType() = default; + void AddGenericPair(GenericDeclare *k, AnnotationType *v) { + GenericArg[k] = v; + ArgOrder.push_back(v); + } + + MIRStructType *GetMIRStructType() { + if (mirStructType->IsInstanceOfMIRStructType()) { + return static_cast(mirStructType); + } + CHECK_FATAL(false, "must be"); + return nullptr; + } + + MIRType *GetMIRType() { + return mirStructType; + } + + virtual const std::string GetName() const override { + return mirStructType->GetMplTypeName(); + } + + MapleMap &GetGenericMap() { + return GenericArg; + } + + MapleVector &GetGenericArg() { + return ArgOrder; + } + + virtual void Dump() override; + virtual void ReWriteType(std::string &subClass) override; + private: + MIRType *mirStructType; + MapleMap GenericArg; + MapleVector ArgOrder; +}; + +class GenericDeclare : public AnnotationType { + public: + explicit GenericDeclare(GStrIdx strIdx) + :AnnotationType(kGenericDeclare, strIdx), + defaultType(nullptr) {} + ~GenericDeclare() = default; + AnnotationType *GetDefaultType() { + return defaultType; + } + + void SetDefaultType(AnnotationType *gt) { + defaultType = gt; + } + + std::string GetBelongToName() { + if (defKind == defByStruct) { + return belongsTo.structType->GetName(); + } else { + return belongsTo.func->GetName(); + } + } + + virtual void Dump() override; + + void SetBelongToStruct(MIRStructType *s) { + defKind = defByStruct; + belongsTo.structType = s; + } + + void SetBelongToFunc(MIRFunction *f) { + defKind = defByFunc; + belongsTo.func = f; + } + + private: + AnnotationType *defaultType; + union DefPoint { + MIRStructType *structType; + MIRFunction *func; + }; + DefPoint belongsTo; + enum DefKind { + defByNone, + defByStruct, + defByFunc + }; + DefKind defKind; +}; + +class ExtendGeneric: public AnnotationType { + public: + ExtendGeneric(AnnotationType *c, EInfo h) : AnnotationType(kExtendType, GStrIdx(0)), contains(c), eInfo(h) { + CHECK_FATAL(c->GetKind() != kGenericMatch, "must be"); + } + + virtual void Dump() override { + std::cout << (eInfo == kHierarchyExtend ? '+' : (eInfo == kArrayType ? '[' : '-')); + if (contains->GetKind() == kGenericDeclare) { + std::cout << "T" << contains->GetName() << ";"; + } else { + contains->Dump(); + } + } + + EInfo GetExtendInfo() { + return eInfo; + } + + AnnotationType *GetContainsGeneric() { + return contains; + } + private: + AnnotationType *contains; + EInfo eInfo; +}; + +class AnnotationParser { + public: + explicit AnnotationParser(std::string &s) : signature(s), curIndex(0) {} + ~AnnotationParser() = default; + ATokenKind GetNextToken(char *endC = nullptr); + GenericDeclare *GetOrCreateDeclare(GStrIdx gStrIdx, MemPool &mp, bool check = false, MIRStructType *sType = nullptr); + AnnotationType *GetOrCreateArrayType(AnnotationType *containsType, MemPool &pragmaMemPool); + void BackOne() { + --curIndex; + } + + std::string GetCurIndexStr() { + return signature.substr(0, curIndex < signature.size() ? curIndex : signature.size()); + } + + void InitClassGenericDeclare(MemPool &pragmaMemPool, MIRStructType &mirStruct); + void InitFuncGenericDeclare(MemPool &pragmaMemPool, MIRFunction &mirFunc); + std::string GetNextClassName(bool forSubClass = false); + std::string GetCurStrToken() { + return curStrToken; + } + + void ReplaceSignature(std::string &s) { + signature = s; + curIndex = 0; + } + + private: + std::string &signature; + int curIndex; + std::map created; + std::map createdArrayType; + std::string curStrToken; +}; + +class AnnotationAnalysis : AnalysisResult { + public: + static char annoDeclare; + static char annoSemiColon; + AnnotationAnalysis(MIRModule *mod, MemPool *tmpMp, MemPool *pragmaMp, KlassHierarchy *kh) + : AnalysisResult(tmpMp), + mirModule(mod), + tmpAllocator(tmpMp), + pragmaMemPool(pragmaMp), + pragmaAllocator(pragmaMp), + klassH(kh) { + genericMatch = pragmaMp->New(kGenericMatch, GStrIdx(0)); + GStrIdx strIdx = GlobalTables::GetStrTable().GetStrIdxFromName("Ljava_2Flang_2FObject_3B"); + MIRType &classType = GetTypeFromTyIdx(GlobalTables::GetTypeNameTable().GetTyIdxFromGStrIdx(strIdx)); + dummyObj = pragmaMp->New(strIdx, &static_cast(classType), pragmaAllocator); + }; + ~AnnotationAnalysis() = default; + void Run(); + private: + void AnalysisAnnotation(); + void AnnotationCleanUp(); + void AnalysisAnnotationForClass(MIRPragma &classPragma); + void AnalysisAnnotationForVar(MIRPragma &varPragma, MIRStructType &structType); + void AnalysisAnnotationForFunc(MIRPragma &funcPragma, MIRStructType &structType); + AnnotationType *ReadInGenericType(AnnotationParser &aParser, MIRStructType *sType); + GenericDeclare *ReadInGenericDeclare(AnnotationParser &aParser, MIRStructType *mirStructType = nullptr); + std::string ReadInAllSubString(MIRPragma &classPragma); + void AAForClassInfo(MIRStructType &structType); + void AAForFuncVarInfo(MIRStructType &structType); + void AnalysisAnnotationForFuncLocalVar(MIRFunction &func, AnnotationParser &aParser, MIRStructType &structType); + void ByPassFollowingInfo(AnnotationParser &aParser, MIRStructType *sType); + MIRModule *mirModule; + MapleAllocator tmpAllocator; + MemPool *pragmaMemPool; + MapleAllocator pragmaAllocator; + KlassHierarchy *klassH; + std::set analysised; + std::set analysisedFunc; + AnnotationType *genericMatch; + GenericType *dummyObj; +}; + +class DoAnnotationAnalysis : public ModulePhase { + public: + explicit DoAnnotationAnalysis(ModulePhaseID id) : ModulePhase(id) {} + + ~DoAnnotationAnalysis() = default; + + AnalysisResult *Run(MIRModule *module, ModuleResultMgr *moduleResultMgr) override; + std::string PhaseName() const override { + return "annotationanalysis"; + } +}; +} +#endif diff --git a/src/mpl2mpl/include/gen_check_cast.h b/src/mpl2mpl/include/gen_check_cast.h index f5962cd845a8ee312c42a8d18dc2e6bac0693618..fca8bd193d23160ca324bf425278173a91f1adc8 100644 --- a/src/mpl2mpl/include/gen_check_cast.h +++ b/src/mpl2mpl/include/gen_check_cast.h @@ -58,6 +58,8 @@ class DoCheckCastGeneration : public ModulePhase { AnalysisResult *Run(MIRModule *mod, ModuleResultMgr *mrm) override { OPT_TEMPLATE(CheckCastGenerator); + memPoolCtrler.DeleteMemPool(mod->GetPragmaMemPool()); + mod->ChangePragmaMemPool(nullptr); return nullptr; } }; diff --git a/src/mpl2mpl/src/annotation_analysis.cpp b/src/mpl2mpl/src/annotation_analysis.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6c73b3fc1a3736bc9926fb69f4720c47166dcb74 --- /dev/null +++ b/src/mpl2mpl/src/annotation_analysis.cpp @@ -0,0 +1,572 @@ +/* + * Copyright (c) [2019-2020] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under the Mulan PSL v1. + * You can use this software according to the terms and conditions of the Mulan PSL v1. + * You may obtain a copy of Mulan PSL v1 at: + * + * http://license.coscl.org.cn/MulanPSL + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v1 for more details. + */ +#include "annotation_analysis.h" + +namespace maple { +char AnnotationAnalysis::annoDeclare = ':'; +char AnnotationAnalysis::annoSemiColon = ';'; +int AnnotationType::atime = 0; +MIRStructType *GetClassTypeFromName(std::string &className) { + GStrIdx strIdx = GlobalTables::GetStrTable().GetStrIdxFromName(className); + if (strIdx == 0) { + strIdx = GlobalTables::GetStrTable().GetStrIdxFromName("Ljava_2Flang_2FObject_3B"); + } + TyIdx classTyIdx = GlobalTables::GetTypeNameTable().GetTyIdxFromGStrIdx(strIdx); + MIRType &classType = GetTypeFromTyIdx(classTyIdx); + return &static_cast(classType); +} + +void GenericDeclare::Dump() { + std::cout << GetName() << ":"; + if (defaultType->GetKind() == kGenericDeclare) { + std::cout << "T" << defaultType->GetName() << ";"; + } else if (defaultType->GetKind() == kGenericType) { + defaultType->Dump(); + } else { + CHECK_FATAL(false, "must be"); + } +} + +void GenericType::Dump() { + std::string s = namemangler::DecodeName(GetName()); + s.pop_back(); + std::cout << s; + if (GenericArg.size()) { + std::cout << "<"; + for (AnnotationType *real : ArgOrder) { + if (real->GetKind() == kGenericType) { + real->Dump(); + } else if (real->GetKind() == kGenericDeclare) { + std::cout << "T" << real->GetName() << ";"; + } else { + real->Dump(); + } + } + std::cout << ">"; + } + std::cout << ";"; +} + +void AnnotationType::Dump() { + if (kind == kGenericMatch) { + std::cout << "*"; + } else { + std::cout << GetName(); + } +} + +void GenericType::ReWriteType(std::string &subClass) { + std::string className = mirStructType->GetName(); + int ClassMethodSplitterStrSize = strlen(namemangler::kClassMethodSplitterStr); + className.replace(className.size() - ClassMethodSplitterStrSize, ClassMethodSplitterStrSize, subClass); + mirStructType = GetClassTypeFromName(className); + typeName = GlobalTables::GetStrTable().GetStrIdxFromName(className); + GenericArg.clear(); + ArgOrder.clear(); +} + +GenericDeclare *AnnotationParser::GetOrCreateDeclare(GStrIdx gStrIdx, MemPool &mp, bool check, MIRStructType *sType) { + if (created.find(gStrIdx) != created.end()) { + return created[gStrIdx]; + } + if (check) { + if (sType != nullptr) { + for (GenericDeclare *gd : sType->GetGenericDeclare()) { + if (gd->GetGStrIdx() == gStrIdx) { + return gd; + } + } + } + return nullptr; + } + GenericDeclare *gd = mp.New(gStrIdx); + created[gStrIdx] = gd; + return gd; +} + +ATokenKind AnnotationParser::GetNextToken(char *endC) { + if (curIndex == signature.size()) { + ++curIndex; + return kEnd; + } + CHECK_FATAL(curIndex < signature.size(), "must be"); + if (endC == nullptr) { + switch (signature[curIndex++]) { + case '<': + return kTemplateStart; + case '>': + return kTemplateEnd; + case '(': + return kArgumentStart; + case ')': + return kArgumentEnd; + case '+': + return kExtend; + case '-': + return kSuper; + case '*': + return kMatch; + case '[': + return kArray; + case 'L': + return kAClassName; + case 'T': + return kTemplateName; + case 'I': + case 'Z': + case 'D': + case 'F': + case 'V': + case 'S': + case 'C': + case 'B': + case 'J': + curStrToken = signature[curIndex - 1]; + return kPrimeTypeName; + case '.': + return kSubClass; + case ';': + return kSemiComma; + default: + curStrToken = signature[curIndex - 1]; + return kChar; + } + } + size_t endPos = signature.find_first_of(endC, curIndex); + CHECK_FATAL(endPos != std::string::npos, "must be"); + curStrToken = signature.substr(curIndex, endPos - curIndex); + curIndex = endPos + 1; + if (*endC == ':' && signature[endPos + 1] == ':') { + ++curIndex; + } + return kString; +} + +// read until ; or <, whatever end of classname is ; +std::string AnnotationParser::GetNextClassName(bool forSubClass) { + size_t pos1 = signature.find_first_of(';', curIndex); + size_t pos2 = signature.find_first_of('<', curIndex); + CHECK_FATAL(pos1 != pos2, "must be"); + size_t pos = pos1 < pos2 ? pos1 : pos2; + curStrToken = signature.substr(curIndex - 1, pos - curIndex + 1); + curStrToken += ";"; + curIndex = pos; + if (forSubClass) { + for (int i = 0; i < curStrToken.size(); ++i) { + if (curStrToken[i] == '.') { + curStrToken[i] = '$'; + } + } + } + std::string className = namemangler::EncodeName(curStrToken); + return className; +} + +void AnnotationParser::InitFuncGenericDeclare(MemPool &pragmaMemPool, MIRFunction &mirFunc) { + size_t declarePos = signature.find_first_of(':', curIndex); + size_t prev = 1; + size_t next = 0; + while (declarePos != std::string::npos) { + std::string declareName = signature.substr(prev, declarePos - prev); + if (declareName != "") { + GStrIdx gStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(declareName); + GenericDeclare *tmp = GetOrCreateDeclare(gStrIdx, pragmaMemPool); + tmp->SetBelongToFunc(&mirFunc); + mirFunc.AddFuncGenericDeclare(tmp); + } + if (signature[declarePos + 1] == ':') { + ++declarePos; + } + next = declarePos + 1; + declarePos = signature.find_first_of(':', next); + prev = signature.find_last_of (';', declarePos) + 1; + } +} + +void AnnotationParser::InitClassGenericDeclare(MemPool &pragmaMemPool, MIRStructType &mirStruct) { + size_t declarePos = signature.find_first_of(':', curIndex); + size_t prev = 1; + size_t next = 0; + while (declarePos != std::string::npos) { + std::string declareName = signature.substr(prev, declarePos - prev); + if (declareName != "") { + GStrIdx gStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(declareName); + GenericDeclare *tmp = GetOrCreateDeclare(gStrIdx, pragmaMemPool); + tmp->SetBelongToStruct(&mirStruct); + mirStruct.AddClassGenericDeclare(tmp); + } + if (signature[declarePos + 1] == ':') { + ++declarePos; + } + next = declarePos + 1; + declarePos = signature.find_first_of(':', next); + prev = signature.find_last_of (';', declarePos) + 1; + } +} + +void AnnotationAnalysis::AnnotationCleanUp() { + const MapleVector &klasses = klassH->GetTopoSortedKlasses(); + for (Klass *klass : klasses) { + MIRStructType *mirStruct = klass->GetMIRStructType(); + mirStruct->GetPragmaVec().clear(); + mirStruct->GetPragmaVec().shrink_to_fit(); + } + memPoolCtrler.DeleteMemPool(mirModule->GetPragmaMemPool()); +} + +void AnnotationAnalysis::ByPassFollowingInfo(AnnotationParser &aParser, MIRStructType *sType) { + ATokenKind t = aParser.GetNextToken(); + if (t == kTemplateStart) { + t = aParser.GetNextToken(); + while (t != kTemplateEnd) { + aParser.BackOne(); + ReadInGenericType(aParser, sType); + t = aParser.GetNextToken(); + } + CHECK_FATAL(t == kTemplateEnd, "must be"); + t = aParser.GetNextToken(); + } + while (t == kSubClass) { + std::string subClassName = aParser.GetNextClassName(true); + t = aParser.GetNextToken(); + if (t == kTemplateStart) { + t = aParser.GetNextToken(); + while (t != kTemplateEnd) { + aParser.BackOne(); + ReadInGenericType(aParser, sType); + t = aParser.GetNextToken(); + } + CHECK_FATAL(t == kTemplateEnd, "must be"); + t = aParser.GetNextToken(); + } + } + CHECK_FATAL(t == kSemiComma, "must be"); +} + +AnnotationType *AnnotationParser::GetOrCreateArrayType(AnnotationType *containsType, MemPool &pragmaMemPool) { + if (createdArrayType.find(containsType) != createdArrayType.end()) { + return createdArrayType[containsType]; + } + ExtendGeneric *retType = pragmaMemPool.New(containsType, kArrayType); + createdArrayType[containsType] = retType; + return retType; +} + +AnnotationType *AnnotationAnalysis::ReadInGenericType(AnnotationParser &aParser, MIRStructType *sType) { + ATokenKind tk = aParser.GetNextToken(); + AnnotationType *retType = nullptr; + switch (tk) { + case kAClassName: { + std::string className = aParser.GetNextClassName(); + GStrIdx gStrIdx = GlobalTables::GetStrTable().GetStrIdxFromName(className); + MIRStructType *mirStruct = GetClassTypeFromName(className); + if (mirStruct == nullptr) { + ByPassFollowingInfo(aParser, sType); + retType = dummyObj; + break; + } + std::vector& gdVector = mirStruct->GetGenericDeclare(); + GenericType *gt = pragmaMemPool->New(gStrIdx, mirStruct, pragmaAllocator); + ATokenKind t = aParser.GetNextToken(); + if (t == kTemplateStart) { + AAForClassInfo(*mirStruct); + for (int i = 0; i < gdVector.size(); ++i) { + AnnotationType *tmp = ReadInGenericType(aParser, sType); + gt->AddGenericPair(gdVector[i], tmp); + } + t = aParser.GetNextToken(); + while (t != kTemplateEnd) { + aParser.BackOne(); + ReadInGenericType(aParser, sType); + t = aParser.GetNextToken(); + } + CHECK_FATAL(t == kTemplateEnd, "must be"); + t = aParser.GetNextToken(); + } + while (t == kSubClass) { + std::string subClassName = aParser.GetNextClassName(true); + gt->ReWriteType(subClassName); + t = aParser.GetNextToken(); + if (t == kTemplateStart) { + AAForClassInfo(*gt->GetMIRStructType()); + std::vector& gdTmpVector = gt->GetMIRStructType()->GetGenericDeclare(); + for (int i = 0; i < gdTmpVector.size(); ++i) { + AnnotationType *tmp = ReadInGenericType(aParser, sType); + gt->AddGenericPair(gdTmpVector[i], tmp); + } + t = aParser.GetNextToken(); + while (t != kTemplateEnd) { + aParser.BackOne(); + ReadInGenericType(aParser, sType); + t = aParser.GetNextToken(); + } + CHECK_FATAL(t == kTemplateEnd, "must be"); + t = aParser.GetNextToken(); + } + } + CHECK_FATAL(t == kSemiComma, "must be"); + retType = gt; + break; + } + case kTemplateName: { + aParser.GetNextToken(&annoSemiColon); + GStrIdx s = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(aParser.GetCurStrToken()); + retType = aParser.GetOrCreateDeclare(s, *pragmaMemPool, true, sType); + if (retType == nullptr) { + retType = dummyObj; + } + break; + } + case kExtend: + retType = ReadInGenericType(aParser, sType); + retType = pragmaMemPool->New(retType, kHierarchyExtend); + break; + case kSuper: + retType = ReadInGenericType(aParser, sType); + retType = pragmaMemPool->New(retType, kHierarchyHSuper); + break; + case kArray: + retType = ReadInGenericType(aParser, sType); + retType = aParser.GetOrCreateArrayType(retType, *pragmaMemPool); + break; + case kMatch: + return genericMatch; + case kPrimeTypeName: { + GStrIdx primeStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(aParser.GetCurStrToken()); + retType = pragmaMemPool->New(kPrimeType, primeStrIdx); + break; + } + default: + CHECK_FATAL(false, "must be"); + } + return retType; +} + +GenericDeclare *AnnotationAnalysis::ReadInGenericDeclare(AnnotationParser &aParser, MIRStructType *mirStructType) { + aParser.GetNextToken(&annoDeclare); + GenericDeclare *gDeclare = nullptr; + if (aParser.GetCurStrToken() != "") { + GStrIdx gStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(aParser.GetCurStrToken()); + gDeclare = aParser.GetOrCreateDeclare(gStrIdx, *pragmaMemPool, true, mirStructType); + CHECK_FATAL(gDeclare->GetDefaultType() == nullptr, "must be"); + } + AnnotationType *at = ReadInGenericType(aParser, mirStructType); + if (gDeclare != nullptr) { + gDeclare->SetDefaultType(at); + } + return gDeclare; +} + +std::string AnnotationAnalysis::ReadInAllSubString(MIRPragma &classPragma) { + GStrIdx gStrIdx; + std::string signature; + CHECK_FATAL(classPragma.GetElementVector().size() == 1, "must be"); + for (MIRPragmaElement *pragmaElement : classPragma.GetElementVector()) { + CHECK_FATAL(pragmaElement->GetType() == kValueArray, "must be"); + for (MIRPragmaElement *subPragmaEle : pragmaElement->GetSubElemVec()) { + CHECK_FATAL(subPragmaEle->GetType() == kValueString, "must be"); + gStrIdx.reset(subPragmaEle->GetU64Val()); + const std::string &str = GlobalTables::GetStrTable().GetStringFromStrIdx(gStrIdx); + signature += str; + } + } + return signature; +} + +void FunctionGenericDump(MIRFunction &func) { + if (func.GetFuncGenericDeclare().size()) { + std::cout << '<'; + for (GenericDeclare *gd : func.GetFuncGenericDeclare()) { + gd->Dump(); + } + std::cout << '>'; + } + std::cout << '('; + for (AnnotationType *at : func.GetFuncGenericArg()) { + if (at->GetKind() == kGenericDeclare) { + std::cout << "T" << at->GetName() << ";"; + } else { + at->Dump(); + } + } + std::cout << ')'; + AnnotationType *ret = func.GetFuncGenericRet(); + if (ret->GetKind() == kGenericDeclare) { + std::cout << "T" << ret->GetName() << ";"; + } else { + ret->Dump(); + } + std::cout << std::endl; +} + +void AnnotationAnalysis::AnalysisAnnotationForFuncLocalVar(MIRFunction &func, AnnotationParser &aParser, + MIRStructType &structType) { + for (auto pair : func.GetAliasVarMap()) { + MIRAliasVars aliasVar = pair.second; + if (aliasVar.sigStrIdx) { + std::string newSig = GlobalTables::GetStrTable().GetStringFromStrIdx(aliasVar.sigStrIdx); + aParser.ReplaceSignature(newSig); + AnnotationType *var = ReadInGenericType(aParser, &structType); + func.AddFuncLocalGenericVar(aliasVar.memPoolStrIdx, var); + } + } +} + +void AnnotationAnalysis::AnalysisAnnotationForFunc(MIRPragma &funcPragma, MIRStructType &structType) { + MIRSymbol *funcSymbol = GlobalTables::GetGsymTable().GetSymbolFromStrIdx(funcPragma.GetStrIdx()); + MIRFunction *func = funcSymbol->GetFunction(); + analysisedFunc.insert(func); + CHECK_FATAL(func->GetFuncGenericDeclare().size() == 0, "must be"); + CHECK_FATAL(func->GetFuncGenericArg().size() == 0, "must be"); + std::string signature = ReadInAllSubString(funcPragma); + AnnotationParser aParser(signature); + ATokenKind tk = aParser.GetNextToken(); + if (tk == kTemplateStart) { + aParser.InitFuncGenericDeclare(*pragmaMemPool, *func); + while (aParser.GetNextToken() != kTemplateEnd) { + aParser.BackOne(); + ReadInGenericDeclare(aParser, &structType); + } + tk = aParser.GetNextToken(); + } + CHECK_FATAL(tk == kArgumentStart, "must be"); + tk = aParser.GetNextToken(); + while (tk != kArgumentEnd) { + aParser.BackOne(); + AnnotationType *arg = ReadInGenericType(aParser, &structType); + func->AddFuncGenericArg(arg); + tk = aParser.GetNextToken(); + } + AnnotationType *ret = ReadInGenericType(aParser, &structType); + func->AddFuncGenericRet(ret); + AnalysisAnnotationForFuncLocalVar(*func, aParser, structType); +} + +void AnnotationAnalysis::AnalysisAnnotationForVar(MIRPragma &varPragma, MIRStructType &structType) { + std::string signature = ReadInAllSubString(varPragma); + AnnotationParser aParser(signature); + ATokenKind tk = aParser.GetNextToken(); + CHECK_FATAL(tk == kAClassName || tk == kTemplateName || tk == kArray, "must be"); + aParser.BackOne(); + AnnotationType *at = ReadInGenericType(aParser, &structType); + structType.AddFieldGenericDeclare(varPragma.GetStrIdx(), at); +} + +void AnnotationAnalysis::AnalysisAnnotationForClass(MIRPragma &classPragma) { + TyIdx classTyIdx = GlobalTables::GetTypeNameTable().GetTyIdxFromGStrIdx(classPragma.GetStrIdx()); + MIRType &classType = GetTypeFromTyIdx(classTyIdx); + CHECK_FATAL(classType.GetKind() == kTypeClass || classType.GetKind() == kTypeInterface, "must be"); + std::string signature = ReadInAllSubString(classPragma); + AnnotationParser aParser(signature); + ATokenKind tk = aParser.GetNextToken(); + if (tk != kTemplateStart) { + return; + } + aParser.InitClassGenericDeclare(*pragmaMemPool, static_cast(classType)); + while (aParser.GetNextToken() != kTemplateEnd) { + aParser.BackOne(); + ReadInGenericDeclare(aParser); + } + while (aParser.GetNextToken() != kEnd) { + aParser.BackOne(); + AnnotationType *at = ReadInGenericType(aParser, nullptr); + CHECK_FATAL(at->GetKind() == kGenericType, "must be"); + if (static_cast(at)->GetMIRStructType() != &classType) { + static_cast(classType).AddInheritaceGeneric(static_cast(at)); + } + } + return; +} + +void AnnotationAnalysis::AAForClassInfo(MIRStructType &structType) { + if (analysised.find(&structType) != analysised.end() || structType.IsIncomplete()) { + return; + } + analysised.insert(&structType); + std::vector &pragmaVec = structType.GetPragmaVec(); + for (MIRPragma *pragma : pragmaVec) { + MIRType *pragmaType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(pragma->GetTyIdx()); + if (pragmaType->GetName() != "Lark_2Fannotation_2FSignature_3B") { + continue; + } + if (pragma->GetKind() != kPragmaClass) { + continue; + } + AnalysisAnnotationForClass(*pragma); + } +} + +void AnnotationAnalysis::AAForFuncVarInfo(MIRStructType &structType) { + std::vector &pragmaVec = structType.GetPragmaVec(); + for (MIRPragma *pragma : pragmaVec) { + MIRType *pragmaType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(pragma->GetTyIdx()); + if (pragmaType->GetName() != "Lark_2Fannotation_2FSignature_3B") { + continue; + } + if (pragma->GetKind() == kPragmaVar) { + AnalysisAnnotationForVar(*pragma, structType); + } else if (pragma->GetKind() == kPragmaFunc) { + AnalysisAnnotationForFunc(*pragma, structType); + } + } +} + +void AnnotationAnalysis::AnalysisAnnotation() { + const MapleVector &klasses = klassH->GetTopoSortedKlasses(); + for (Klass *klass : klasses) { + if (klass->IsInterfaceIncomplete() || klass->IsClassIncomplete()) { + continue; + } + MIRStructType *structType = klass->GetMIRStructType(); + AAForClassInfo(*structType); + } + for (Klass *klass : klasses) { + if (klass->IsInterfaceIncomplete() || klass->IsClassIncomplete()) { + continue; + } + MIRStructType *structType = klass->GetMIRStructType(); + AAForFuncVarInfo(*structType); + } + for (MIRFunction *func : mirModule->GetFunctionList()) { + if (func->IsEmpty() || analysisedFunc.find(func) != analysisedFunc.end()) { + continue; + } + MIRType *classType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(func->GetClassTyIdx()); + if (classType == nullptr) { + continue; + } + std::string tmp; + AnnotationParser aParser(tmp); + AnalysisAnnotationForFuncLocalVar(*func, aParser, static_cast(*classType)); + } +} + +void AnnotationAnalysis::Run() { + AnalysisAnnotation(); + AnnotationCleanUp(); +} + +AnalysisResult *DoAnnotationAnalysis::Run(MIRModule *module, ModuleResultMgr *moduleResultMgr) { + MemPool *memPool = memPoolCtrler.NewMemPool("AnnotationAnalysis mempool"); + MemPool *pragmaMemPool = memPoolCtrler.NewMemPool("New Pragma mempool"); + auto *kh = static_cast(moduleResultMgr->GetAnalysisResult(MoPhase_CHA, module)); + ASSERT_NOT_NULL(kh); + AnnotationAnalysis AA(module, memPool, pragmaMemPool, kh); + AA.Run(); + memPoolCtrler.DeleteMemPool(memPool); + module->ChangePragmaMemPool(pragmaMemPool); + return nullptr; +} +} diff --git a/src/mpl2mpl/src/reflection_analysis.cpp b/src/mpl2mpl/src/reflection_analysis.cpp index cdf090aeb134044e269edf1669d454bbb6387b01..cf50eb7bb730bd2aeddcd28b9489eb1407c6d187 100755 --- a/src/mpl2mpl/src/reflection_analysis.cpp +++ b/src/mpl2mpl/src/reflection_analysis.cpp @@ -1889,12 +1889,6 @@ void ReflectionAnalysis::Run() { reflectionMuidStr.clear(); reflectionMuidStr.shrink_to_fit(); GenClassHashMetaData(); - for (Klass *klass : klasses) { - MIRStructType *mirStruct = klass->GetMIRStructType(); - mirStruct->GetPragmaVec().clear(); - mirStruct->GetPragmaVec().shrink_to_fit(); - } - memPoolCtrler.DeleteMemPool(mirModule->GetPragmaMemPool()); } AnalysisResult *DoReflectionAnalysis::Run(MIRModule *module, ModuleResultMgr *moduleResultMgr) {