From 0258a10935931fe9a8acf5e476b8a8250270764d Mon Sep 17 00:00:00 2001 From: oh-rgx Date: Wed, 18 Jun 2025 11:40:02 +0800 Subject: [PATCH] opt emit Signed-off-by: oh-rgx --- ets2panda/checker/types/signature.cpp | 5 + ets2panda/checker/types/signature.h | 1 + ets2panda/compiler/core/ETSGen.cpp | 18 +-- ets2panda/compiler/core/ETSemitter.cpp | 150 +++++++++++++++++------ ets2panda/compiler/core/ETSemitter.h | 5 +- ets2panda/compiler/core/JSemitter.h | 3 + ets2panda/compiler/core/compilerImpl.cpp | 1 + ets2panda/compiler/core/emitter.cpp | 13 +- ets2panda/compiler/core/emitter.h | 10 +- ets2panda/compiler/core/regAllocator.cpp | 11 ++ ets2panda/compiler/core/regAllocator.h | 108 ++++++++++++++++ 11 files changed, 273 insertions(+), 52 deletions(-) diff --git a/ets2panda/checker/types/signature.cpp b/ets2panda/checker/types/signature.cpp index 5ced79c411..86fe531867 100644 --- a/ets2panda/checker/types/signature.cpp +++ b/ets2panda/checker/types/signature.cpp @@ -26,6 +26,11 @@ util::StringView Signature::InternalName() const return internalName_.Empty() && func_ != nullptr ? func_->Scope()->InternalName() : internalName_; } +util::StringView Signature::InternalName() +{ + return internalName_.Empty() && func_ != nullptr ? func_->Scope()->InternalName() : internalName_; +} + Signature *Signature::Substitute(TypeRelation *relation, const Substitution *substitution) { if (substitution == nullptr || substitution->empty()) { diff --git a/ets2panda/checker/types/signature.h b/ets2panda/checker/types/signature.h index d94e607e8b..fd7b82d418 100644 --- a/ets2panda/checker/types/signature.h +++ b/ets2panda/checker/types/signature.h @@ -290,6 +290,7 @@ public: void ToAssemblerType(std::stringstream &ss) const; [[nodiscard]] util::StringView InternalName() const; + [[nodiscard]] util::StringView InternalName(); [[nodiscard]] Signature *Copy(ArenaAllocator *allocator, TypeRelation *relation, GlobalTypesHolder *globalTypes); [[nodiscard]] Signature *Substitute(TypeRelation *relation, const Substitution *substitution); diff --git a/ets2panda/compiler/core/ETSGen.cpp b/ets2panda/compiler/core/ETSGen.cpp index 4abf10587d..aa70a37836 100644 --- a/ets2panda/compiler/core/ETSGen.cpp +++ b/ets2panda/compiler/core/ETSGen.cpp @@ -297,6 +297,8 @@ util::StringView ETSGen::FormClassPropReference(const checker::ETSObjectType *cl { std::stringstream ss; ss << classType->AssemblerName().Mutf8() << Signatures::METHOD_SEPARATOR << name; + auto &usedName = Context()->emitter->Program()->usedRecordName; + usedName.try_emplace(classType->AssemblerName().Mutf8()).first->second.insert(name.Mutf8()); return util::StringView(*ProgElement()->Strings().emplace(ss.str()).first); } @@ -447,7 +449,7 @@ void ETSGen::CallRangeFillUndefined(const ir::AstNode *const node, checker::Sign void ETSGen::LoadUndefinedDynamic(const ir::AstNode *node, Language lang) { RegScope rs(this); - Ra().Emit(node, Signatures::Dynamic::GetUndefinedBuiltin(lang), dummyReg_, dummyReg_); + Ra().Emit(node, util::StringView(Signatures::Dynamic::GetUndefinedBuiltin(lang)), dummyReg_, dummyReg_); SetAccumulatorType(Checker()->GlobalBuiltinDynamicType(lang)); } @@ -458,7 +460,7 @@ void ETSGen::LoadThis(const ir::AstNode *node) void ETSGen::CreateBigIntObject(const ir::AstNode *node, VReg arg0, std::string_view signature) { - Ra().Emit(node, signature, arg0, dummyReg_); + Ra().Emit(node, util::StringView(signature), arg0, dummyReg_); } VReg ETSGen::GetThisReg() const @@ -2233,7 +2235,7 @@ void ETSGen::StringBuilderAppend(const ir::AstNode *node, VReg builder) Label *ifUndefined = AllocLabel(); Label *end = AllocLabel(); BranchIfUndefined(node, ifUndefined); - Ra().Emit(node, Signatures::BUILTIN_OBJECT_TO_STRING, dummyReg_, 0); + Ra().Emit(node, util::StringView(Signatures::BUILTIN_OBJECT_TO_STRING), dummyReg_, 0); JumpTo(node, end); SetLabel(node, ifUndefined); @@ -2241,7 +2243,7 @@ void ETSGen::StringBuilderAppend(const ir::AstNode *node, VReg builder) SetLabel(node, end); } else { - Ra().Emit(node, Signatures::BUILTIN_OBJECT_TO_STRING, dummyReg_, 0); + Ra().Emit(node, util::StringView(Signatures::BUILTIN_OBJECT_TO_STRING), dummyReg_, 0); } } @@ -2281,7 +2283,7 @@ void ETSGen::BuildString(const ir::Expression *node) { RegScope rs(this); - Ra().Emit(node, Signatures::BUILTIN_STRING_BUILDER_CTOR, dummyReg_, dummyReg_); + Ra().Emit(node, util::StringView(Signatures::BUILTIN_STRING_BUILDER_CTOR), dummyReg_, dummyReg_); SetAccumulatorType(Checker()->GlobalStringBuilderBuiltinType()); auto builder = AllocReg(); @@ -2319,7 +2321,7 @@ void ETSGen::BuildTemplateString(const ir::TemplateLiteral *node) { RegScope rs(this); - Ra().Emit(node, Signatures::BUILTIN_STRING_BUILDER_CTOR, dummyReg_, dummyReg_); + Ra().Emit(node, util::StringView(Signatures::BUILTIN_STRING_BUILDER_CTOR), dummyReg_, dummyReg_); SetAccumulatorType(Checker()->GlobalStringBuilderBuiltinType()); auto builder = AllocReg(); @@ -2381,7 +2383,7 @@ void ETSGen::LoadResizableArrayElement(const ir::AstNode *node, const VReg arrOb { auto *vRegType = GetVRegType(arrObj); auto *elementType = vRegType->AsETSResizableArrayType()->ElementType(); - Ra().Emit(node, Signatures::BUILTIN_ARRAY_GET_ELEMENT, arrObj, arrIndex); + Ra().Emit(node, util::StringView(Signatures::BUILTIN_ARRAY_GET_ELEMENT), arrObj, arrIndex); SetAccumulatorType(elementType); } @@ -2564,7 +2566,7 @@ void ETSGen::DoubleIsNaN(const ir::AstNode *node) void ETSGen::LoadStringChar(const ir::AstNode *node, const VReg stringObj, const VReg charIndex, bool needBox) { - Ra().Emit(node, Signatures::BUILTIN_STRING_CHAR_AT, stringObj, charIndex); + Ra().Emit(node, util::StringView(Signatures::BUILTIN_STRING_CHAR_AT), stringObj, charIndex); SetAccumulatorType(Checker()->GlobalCharType()); if (needBox) { Ra().Emit(node, Signatures::BUILTIN_CHAR_VALUE_OF, dummyReg_, 0); diff --git a/ets2panda/compiler/core/ETSemitter.cpp b/ets2panda/compiler/core/ETSemitter.cpp index 81ff05cfe2..e5ce4a1bea 100644 --- a/ets2panda/compiler/core/ETSemitter.cpp +++ b/ets2panda/compiler/core/ETSemitter.cpp @@ -112,7 +112,7 @@ static pandasm::Type PandasmTypeWithRank(checker::Type const *type, uint32_t ran return pandasm::Type(ss.str(), rank == 0 ? type->Rank() : rank); } -static pandasm::Function GenScriptFunction(const ir::ScriptFunction *scriptFunc, ETSEmitter *emitter) +static pandasm::Function GenScriptFunction(const ir::ScriptFunction *scriptFunc, ETSEmitter *emitter, bool external) { auto *funcScope = scriptFunc->Scope(); auto *paramScope = funcScope->ParamScope(); @@ -126,13 +126,23 @@ static pandasm::Function GenScriptFunction(const ir::ScriptFunction *scriptFunc, !var->Declaration()->Node()->IsETSParameterExpression()) { continue; } + + std::string typeName = var->TsType()->ToAssemblerTypeWithRank(); + std::string mapName = emitter->Program()->mapTable.find(typeName) != emitter->Program()->mapTable.end() ? + emitter->Program()->mapTable[typeName] : typeName; + emitter->Program()->usedRecordName.try_emplace(mapName); func.params.back().GetOrCreateMetadata().SetAnnotations(emitter->GenCustomAnnotations( - var->Declaration()->Node()->AsETSParameterExpression()->Annotations(), var->Name().Mutf8())); + var->Declaration()->Node()->AsETSParameterExpression()->Annotations(), var->Name().Mutf8(), external)); } if (scriptFunc->IsConstructor() || scriptFunc->IsStaticBlock()) { + emitter->Program()->usedRecordName.try_emplace(std::string(Signatures::PRIMITIVE_VOID)); func.returnType = pandasm::Type(Signatures::PRIMITIVE_VOID, 0); } else { + std::string typeName = scriptFunc->Signature()->ReturnType()->ToAssemblerTypeWithRank(); + std::string mapName = emitter->Program()->mapTable.find(typeName) != emitter->Program()->mapTable.end() ? + emitter->Program()->mapTable[typeName] : typeName; + emitter->Program()->usedRecordName.try_emplace(mapName); func.returnType = PandasmTypeWithRank(scriptFunc->Signature()->ReturnType()); } @@ -146,7 +156,7 @@ static pandasm::Function GenScriptFunction(const ir::ScriptFunction *scriptFunc, } func.metadata->SetAccessFlags(accessFlags); if (!scriptFunc->IsExternal()) { - func.metadata->SetAnnotations(emitter->GenCustomAnnotations(scriptFunc->Annotations(), func.name)); + func.metadata->SetAnnotations(emitter->GenCustomAnnotations(scriptFunc->Annotations(), func.name, external)); } return func; @@ -156,7 +166,7 @@ pandasm::Function *ETSFunctionEmitter::GenFunctionSignature() { auto *scriptFunc = Cg()->RootNode()->AsScriptFunction(); auto *emitter = static_cast(Cg()->Context()->emitter); - auto func = GenScriptFunction(scriptFunc, emitter); + auto func = GenScriptFunction(scriptFunc, emitter, Cg()->RootNode()->AsScriptFunction()->IsExternal()); if (Cg()->RootNode()->AsScriptFunction()->IsExternal()) { func.metadata->SetAttribute(Signatures::EXTERNAL); @@ -263,9 +273,22 @@ static std::vector> StoreExportNodes( return result; } +void ETSEmitter::GenExternalRecords() +{ + const auto *varbinder = static_cast(Context()->parserProgram->VarBinder()); + + for (auto [extProg, recordTable] : varbinder->GetExternalRecordTable()) { + if (recordTable == varbinder->GetRecordTable()) { + continue; + } + GenExternalRecord(recordTable, extProg); + } +} + void ETSEmitter::GenAnnotation() { Program()->lang = EXTENSION; + Program()->AddMappingTable(); const auto *varbinder = static_cast(Context()->parserProgram->VarBinder()); auto *globalRecordTable = varbinder->GetGlobalRecordTable(); @@ -285,7 +308,7 @@ void ETSEmitter::GenAnnotation() for (auto *signature : globalRecordTable->Signatures()) { auto *scriptFunc = signature->Node()->AsScriptFunction(); - auto func = GenScriptFunction(scriptFunc, this); + auto func = GenScriptFunction(scriptFunc, this, scriptFunc->IsDeclare()); if (scriptFunc->IsDeclare()) { func.metadata->SetAttribute(Signatures::EXTERNAL); } @@ -297,13 +320,6 @@ void ETSEmitter::GenAnnotation() Program()->AddToFunctionTable(std::move(func)); } - for (auto [extProg, recordTable] : varbinder->GetExternalRecordTable()) { - if (recordTable == varbinder->GetRecordTable()) { - continue; - } - GenExternalRecord(recordTable, extProg); - } - const auto *checker = static_cast(Context()->GetChecker()); for (auto [arrType, signature] : checker->GlobalArrayTypes()) { @@ -327,33 +343,46 @@ void ETSEmitter::GenExternalRecord(varbinder::RecordTable *recordTable, const pa { bool isGenStdLib = recordTable->Program()->VarBinder()->IsGenStdLib(); const auto *varbinder = static_cast(Context()->parserProgram->VarBinder()); + auto &usedName = Program()->usedRecordName; auto baseName = varbinder->GetRecordTable()->RecordName().Mutf8(); for (auto *annoDecl : recordTable->AnnotationDeclarations()) { - auto newBaseName = GenerateMangledName(baseName, annoDecl->GetBaseName()->Name().Mutf8()); - GenCustomAnnotationRecord(annoDecl, newBaseName, !isGenStdLib); + if (isGenStdLib || usedName.find(annoDecl->InternalName().Mutf8()) != usedName.end()) { + auto newBaseName = GenerateMangledName(baseName, annoDecl->GetBaseName()->Name().Mutf8()); + GenCustomAnnotationRecord(annoDecl, newBaseName, !isGenStdLib); + } } for (auto *classDecl : recordTable->ClassDefinitions()) { - GenClassRecord(classDecl, !isGenStdLib); + if (isGenStdLib || usedName.find(classDecl->InternalName().Mutf8()) != usedName.end()) { + GenClassRecord(classDecl, !isGenStdLib); + } } for (auto *interfaceDecl : recordTable->InterfaceDeclarations()) { - GenInterfaceRecord(interfaceDecl, !isGenStdLib); + if (isGenStdLib || usedName.find(interfaceDecl->InternalName().Mutf8()) != usedName.end()) { + GenInterfaceRecord(interfaceDecl, !isGenStdLib); + } } for (auto const *signature : recordTable->Signatures()) { - auto func = GenScriptFunction(signature->Node()->AsScriptFunction(), this); - - if (!isGenStdLib) { - func.metadata->SetAttribute(Signatures::EXTERNAL); - } + auto sciptfunc = signature->Node()->AsScriptFunction(); + auto ownerName = sciptfunc->Signature()->Owner()->AssemblerName().Mutf8(); + auto funcName = sciptfunc->Scope()->InternalName().Mutf8(); + if (isGenStdLib || (usedName.find(ownerName) != usedName.end() && + usedName[ownerName].find(funcName) != usedName[ownerName].end())) { + auto func = GenScriptFunction(signature->Node()->AsScriptFunction(), this, !isGenStdLib); + + if (!isGenStdLib) { + func.metadata->SetAttribute(Signatures::EXTERNAL); + } - if (func.metadata->IsForeign() && IsFromSelfHeadFile(func.name, Context()->parserProgram, extProg)) { - continue; - } + if (func.metadata->IsForeign() && IsFromSelfHeadFile(func.name, Context()->parserProgram, extProg)) { + continue; + } - if (Program()->functionStaticTable.find(func.name) == Program()->functionStaticTable.cend()) { - Program()->AddToFunctionTable(std::move(func)); + if (Program()->functionStaticTable.find(func.name) == Program()->functionStaticTable.cend()) { + Program()->AddToFunctionTable(std::move(func)); + } } } } @@ -439,7 +468,13 @@ void ETSEmitter::EmitDefaultFieldValue(pandasm::Field &classField, const ir::Exp void ETSEmitter::GenInterfaceMethodDefinition(const ir::MethodDefinition *methodDef, bool external) { auto *scriptFunc = methodDef->Function(); - auto func = GenScriptFunction(scriptFunc, this); + auto &usedName = Program()->usedRecordName; + auto ownerName = scriptFunc->Signature()->Owner()->AssemblerName().Mutf8(); + auto funcName = scriptFunc->Scope()->InternalName().Mutf8(); + if (external && (usedName[ownerName].find(funcName) == usedName[ownerName].end())) { + return; + } + auto func = GenScriptFunction(scriptFunc, this, external); if (external) { func.metadata->SetAttribute(Signatures::EXTERNAL); @@ -458,10 +493,15 @@ void ETSEmitter::GenClassField(const ir::ClassProperty *prop, pandasm::Record &c auto field = pandasm::Field(Program()->lang); field.name = prop->Id()->Name().Mutf8(); field.type = PandasmTypeWithRank(prop->TsType()); + + std::string typeName = prop->TsType()->ToAssemblerTypeWithRank(); + std::string mapName = Program()->mapTable.find(typeName) != Program()->mapTable.end() ? + Program()->mapTable[typeName] : typeName; + Program()->usedRecordName.try_emplace(mapName); field.metadata->SetAccessFlags(TranslateModifierFlags(prop->Modifiers())); if (!external) { - field.metadata->SetAnnotations(GenCustomAnnotations(prop->Annotations(), field.name)); + field.metadata->SetAnnotations(GenCustomAnnotations(prop->Annotations(), field.name, external)); } if (external || prop->IsDeclare()) { @@ -473,7 +513,7 @@ void ETSEmitter::GenClassField(const ir::ClassProperty *prop, pandasm::Record &c classRecord.fieldList.emplace_back(std::move(field)); } -void ETSEmitter::GenClassInheritedFields(const checker::ETSObjectType *baseType, pandasm::Record &classRecord) +void ETSEmitter::GenClassInheritedFields(const checker::ETSObjectType *baseType, pandasm::Record &classRecord, bool external) { std::vector foreignProps = baseType->ForeignProperties(); @@ -482,8 +522,11 @@ void ETSEmitter::GenClassInheritedFields(const checker::ETSObjectType *baseType, if (!declNode->IsClassProperty()) { continue; } - - GenClassField(declNode->AsClassProperty(), classRecord, true); + auto &usedName = Program()->usedRecordName; + auto name = declNode->AsClassProperty()->Id()->Name().Mutf8(); + if (!external || usedName[classRecord.name].find(name) != usedName[classRecord.name].end()) { + GenClassField(declNode->AsClassProperty(), classRecord, true); + } } } @@ -514,15 +557,26 @@ void ETSEmitter::GenInterfaceRecord(const ir::TSInterfaceDeclaration *interfaceD accessFlags |= ACC_STATIC; } - interfaceRecord.metadata->SetAnnotations(GenCustomAnnotations(interfaceDecl->Annotations(), interfaceRecord.name)); + interfaceRecord.metadata->SetAnnotations(GenCustomAnnotations(interfaceDecl->Annotations(), interfaceRecord.name, external)); interfaceRecord.metadata->SetAccessFlags(accessFlags); interfaceRecord.sourceFile = std::string {Context()->parserProgram->VarBinder()->Program()->RelativeFilePath()}; + if (!external) { + if (interfaceDecl->Annotations().empty()) { + Program()->usedRecordName.try_emplace(std::string(Signatures::INTERFACE_OBJ_LITERAL)); + } + Program()->usedRecordName.try_emplace(std::string(Signatures::BUILTIN_OBJECT)); + } interfaceRecord.metadata->SetAttributeValue(Signatures::EXTENDS_ATTRIBUTE, Signatures::BUILTIN_OBJECT); - GenClassInheritedFields(baseType, interfaceRecord); + GenClassInheritedFields(baseType, interfaceRecord, external); for (const auto *prop : interfaceDecl->Body()->Body()) { if (prop->IsClassProperty()) { + auto &usedName = Program()->usedRecordName; + auto propName = prop->AsClassProperty()->Id()->Name().Mutf8(); + if (external && (usedName[interfaceRecord.name].find(propName) == usedName[interfaceRecord.name].end())) { + continue; + } GenClassField(prop->AsClassProperty(), interfaceRecord, external); } else if (prop->IsMethodDefinition()) { GenInterfaceMethodDefinition(prop->AsMethodDefinition(), external); @@ -605,7 +659,7 @@ void ETSEmitter::GenClassRecord(const ir::ClassDefinition *classDef, bool extern classRecord.sourceFile = std::string {Context()->parserProgram->VarBinder()->Program()->RelativeFilePath()}; auto *baseType = classDef->TsType()->AsETSObjectType(); - GenClassInheritedFields(baseType, classRecord); + GenClassInheritedFields(baseType, classRecord, external); for (const auto *prop : classDef->Body()) { if (!prop->IsClassProperty()) { continue; @@ -621,11 +675,17 @@ void ETSEmitter::GenClassRecord(const ir::ClassDefinition *classDef, bool extern } if (baseType->SuperType() != nullptr) { - classRecord.metadata->SetAttributeValue(Signatures::EXTENDS_ATTRIBUTE, - baseType->SuperType()->AssemblerName().Mutf8()); + std::string name = baseType->SuperType()->AssemblerName().Mutf8(); + if (!external) { + Program()->usedRecordName.try_emplace(baseType->SuperType()->AssemblerName().Mutf8()); + } + classRecord.metadata->SetAttributeValue(Signatures::EXTENDS_ATTRIBUTE, name); } else { // NOTE: rtakacs. Replace the whole if block (below) with assert when lambda objects have super class. if (baseType->AssemblerName().Mutf8() != Signatures::BUILTIN_OBJECT) { + if (!external) { + Program()->usedRecordName.try_emplace(std::string(Signatures::BUILTIN_OBJECT)); + } classRecord.metadata->SetAttributeValue(Signatures::EXTENDS_ATTRIBUTE, Signatures::BUILTIN_OBJECT); } } @@ -638,6 +698,9 @@ void ETSEmitter::GenClassRecord(const ir::ClassDefinition *classDef, bool extern continue; } std::string name = declNode->AsTSInterfaceDeclaration()->InternalName().Mutf8(); + if (!external) { + Program()->usedRecordName.try_emplace(name); + } classRecord.metadata->SetAttributeValue(Signatures::IMPLEMENTS_ATTRIBUTE, name); } @@ -806,10 +869,20 @@ void ETSEmitter::CreateLiteralArrayProp(const ir::ClassProperty *prop, std::stri void ETSEmitter::GenCustomAnnotationProp(const ir::ClassProperty *prop, std::string &baseName, pandasm::Record &record, bool external) { + auto &usedName = Program()->usedRecordName; + auto name = prop->Id()->Name().Mutf8(); + if (external && usedName[record.name].find(name) == usedName[record.name].end()) { + return; + } auto field = pandasm::Field(Program()->lang); auto *type = prop->TsType(); field.name = prop->Id()->Name().Mutf8(); field.type = PandasmTypeWithRank(type); + + std::string typeName = prop->TsType()->ToAssemblerTypeWithRank(); + std::string mapName = Program()->mapTable.find(typeName) != Program()->mapTable.end() ? + Program()->mapTable[typeName] : typeName; + usedName.try_emplace(mapName); field.metadata->SetAccessFlags(TranslateModifierFlags(prop->Modifiers())); if (external) { @@ -918,7 +991,7 @@ pandasm::AnnotationData ETSEmitter::GenCustomAnnotation(ir::AnnotationUsage *ann } std::vector ETSEmitter::GenCustomAnnotations( - const ArenaVector &annotationUsages, const std::string &baseName) + const ArenaVector &annotationUsages, const std::string &baseName, bool external) { std::vector annotations; for (auto *anno : annotationUsages) { @@ -927,6 +1000,9 @@ std::vector ETSEmitter::GenCustomAnnotations( auto newBaseName = GenerateMangledName(baseName, anno->GetBaseName()->Name().Mutf8()); annotations.emplace_back(GenCustomAnnotation(anno, newBaseName)); } + if (!external) { + Program()->usedRecordName.try_emplace(annoDecl->InternalName().Mutf8()); + } } return annotations; } diff --git a/ets2panda/compiler/core/ETSemitter.h b/ets2panda/compiler/core/ETSemitter.h index db06f5bd5d..09df3e50fe 100644 --- a/ets2panda/compiler/core/ETSemitter.h +++ b/ets2panda/compiler/core/ETSemitter.h @@ -79,8 +79,9 @@ public: NO_MOVE_SEMANTIC(ETSEmitter); void GenAnnotation() override; + void GenExternalRecords() override; std::vector GenCustomAnnotations( - const ArenaVector &annotationUsages, const std::string &baseName); + const ArenaVector &annotationUsages, const std::string &baseName, bool external); private: using DynamicCallNamesMap = ArenaMap, uint32_t>; @@ -107,7 +108,7 @@ private: void GenClassField(const ir::ClassProperty *prop, pandasm::Record &classRecord, bool external); void GenInterfaceMethodDefinition(const ir::MethodDefinition *methodDef, bool external); - void GenClassInheritedFields(const checker::ETSObjectType *baseType, pandasm::Record &classRecord); + void GenClassInheritedFields(const checker::ETSObjectType *baseType, pandasm::Record &classRecord, bool external); pandasm::AnnotationData GenAnnotationSignature(const ir::ClassDefinition *classDef); pandasm::AnnotationData GenAnnotationModule(const ir::ClassDefinition *classDef); pandasm::AnnotationData GenAnnotationEnclosingClass(std::string_view className); diff --git a/ets2panda/compiler/core/JSemitter.h b/ets2panda/compiler/core/JSemitter.h index 72b8577c06..9bbdd19978 100644 --- a/ets2panda/compiler/core/JSemitter.h +++ b/ets2panda/compiler/core/JSemitter.h @@ -49,6 +49,9 @@ public: NO_MOVE_SEMANTIC(JSEmitter); void GenAnnotation() override; + void GenExternalRecords() override + { + } private: void GenESAnnotationRecord(); diff --git a/ets2panda/compiler/core/compilerImpl.cpp b/ets2panda/compiler/core/compilerImpl.cpp index 86b978ffe4..d2e419a6fd 100644 --- a/ets2panda/compiler/core/compilerImpl.cpp +++ b/ets2panda/compiler/core/compilerImpl.cpp @@ -71,6 +71,7 @@ ark::pandasm::Program *CompilerImpl::Emit(public_lib::Context *context) /* Main thread can also be used instead of idling */ queue_.Consume(); + context->emitter->GenExternalRecords(); auto *emitter = context->emitter; queue_.Wait([emitter](CompileJob *job) { emitter->AddProgramElement(job->GetProgramElement()); }); diff --git a/ets2panda/compiler/core/emitter.cpp b/ets2panda/compiler/core/emitter.cpp index 95b7d45aee..1aa2ae7e7b 100644 --- a/ets2panda/compiler/core/emitter.cpp +++ b/ets2panda/compiler/core/emitter.cpp @@ -129,6 +129,14 @@ static LiteralPair TransformLiteral(const compiler::Literal *literal) void FunctionEmitter::Generate() { + bool isGenStdLib = Cg()->VarBinder()->IsGenStdLib(); + bool isExternal = Cg()->RootNode()->AsScriptFunction()->IsExternal(); + auto &usedName= Cg()->Context()->emitter->Program()->usedRecordName; + auto ownerName = Cg()->RootNode()->AsScriptFunction()->Signature()->Owner()->AssemblerName().Mutf8(); + if (!isGenStdLib && isExternal && usedName.find(ownerName) == usedName.end()) { + return; + } + auto *func = GenFunctionSignature(); GenFunctionInstructions(func); GenVariablesDebugInfo(func); @@ -273,6 +281,7 @@ void FunctionEmitter::GenFunctionCatchTables(pandasm::Function *func) auto &pandaCatchBlock = func->catchBlocks.emplace_back(); pandaCatchBlock.exceptionRecord = catchBlock->Exception(); + Cg()->Context()->emitter->Program()->usedRecordName.try_emplace(pandaCatchBlock.exceptionRecord); pandaCatchBlock.tryBeginLabel = labelSet.TryBegin()->Id(); pandaCatchBlock.tryEndLabel = labelSet.TryEnd()->Id(); pandaCatchBlock.catchBeginLabel = labelSet.CatchBegin()->Id(); @@ -452,7 +461,9 @@ void Emitter::AddProgramElement(ProgramElement *programElement) literalBufferIndex_ = newLiteralBufferIndex; auto *function = programElement->Function(); - prog_->AddToFunctionTable(std::move(*function)); + if (function != nullptr) { + prog_->AddToFunctionTable(std::move(*function)); + } } static std::string CanonicalizeName(std::string name) diff --git a/ets2panda/compiler/core/emitter.h b/ets2panda/compiler/core/emitter.h index 84049be833..9ffc475a18 100644 --- a/ets2panda/compiler/core/emitter.h +++ b/ets2panda/compiler/core/emitter.h @@ -118,15 +118,17 @@ public: } virtual void GenAnnotation() = 0; + virtual void GenExternalRecords() = 0; -protected: - explicit Emitter(const public_lib::Context *context); - - pandasm::Program *Program() const + pandasm::Program *Program() { return prog_; } +protected: + explicit Emitter(const public_lib::Context *context); + + const public_lib::Context *Context() const { return context_; diff --git a/ets2panda/compiler/core/regAllocator.cpp b/ets2panda/compiler/core/regAllocator.cpp index 408daed8c6..f9de1e7551 100644 --- a/ets2panda/compiler/core/regAllocator.cpp +++ b/ets2panda/compiler/core/regAllocator.cpp @@ -17,6 +17,7 @@ #include "compiler/core/codeGen.h" #include "checker/types/type.h" +#include "public/public.h" #include #include @@ -41,6 +42,16 @@ const CodeGen &AllocatorBase::GetCodeGen() const noexcept return *cg_; } +std::unordered_map> &AllocatorBase::GeUsedRecordName() +{ + return cg_->Context()->emitter->Program()->usedRecordName; +} + +std::unordered_map &AllocatorBase::GeMapTable() +{ + return cg_->Context()->emitter->Program()->mapTable; +} + ArenaAllocator &AllocatorBase::Allocator() noexcept { return *cg_->Allocator(); diff --git a/ets2panda/compiler/core/regAllocator.h b/ets2panda/compiler/core/regAllocator.h index 2f48a9a674..53fdc37926 100644 --- a/ets2panda/compiler/core/regAllocator.h +++ b/ets2panda/compiler/core/regAllocator.h @@ -20,6 +20,11 @@ #include "compiler/core/regSpiller.h" #include "util/es2pandaMacros.h" +#include +#include +#include +#include + namespace ark::es2panda::ir { class AstNode; } // namespace ark::es2panda::ir @@ -34,10 +39,47 @@ public: NO_MOVE_SEMANTIC(AllocatorBase); ~AllocatorBase() = default; + void HandleAndRecordName(std::string funcName) + { + auto className = funcName.substr(0, funcName.rfind('.', funcName.find(':'))); + auto &usedName = GeUsedRecordName(); + auto &mapTable = GeMapTable(); + usedName[className].insert(funcName); + + for(size_t start = funcName.find(':') + 1, end; start < funcName.size(); start = end + 1) { + if((end = funcName.find(';', start)) == std::string::npos){ + break; + } + std::string str = funcName.substr(start, end - start); + if (mapTable.find(str) != mapTable.end()) { + usedName.try_emplace(mapTable[str]); + } else { + usedName.try_emplace(str); + } + } + } + + void HandleArrayName(std::string arratName) + { + auto &mapTable = GeMapTable(); + auto &usedName = GeUsedRecordName(); + if (mapTable.find(arratName) != mapTable.end()) { + usedName.try_emplace(mapTable[arratName]); + return; + } + + if (auto pos = arratName.find("["); pos != std::string::npos) { + usedName.try_emplace(arratName.substr(0, pos)); + usedName.try_emplace("escompat.Array"); + } + } + protected: void PushBack(IRNode *ins) const; [[nodiscard]] CodeGen &GetCodeGen() noexcept; [[nodiscard]] const CodeGen &GetCodeGen() const noexcept; + std::unordered_map> &GeUsedRecordName(); + std::unordered_map &GeMapTable(); template [[nodiscard]] T *Alloc(const ir::AstNode *const node, Args &&...args) @@ -71,6 +113,20 @@ public: template void Emit(const ir::AstNode *const node, Args &&...args) { + if constexpr (std::is_same_v) { + auto &&classRef = std::get<0>(std::forward_as_tuple(std::forward(args)...)); + GeUsedRecordName().try_emplace(classRef.Mutf8()); + } else if constexpr (std::is_same_v) { + auto &&target = std::get<0>(std::forward_as_tuple(std::forward(args)...)); + GeUsedRecordName().try_emplace(target.Mutf8()); + } else if constexpr (std::is_same_v) { + auto &&target = std::get<0>(std::forward_as_tuple(std::forward(args)...)); + GeUsedRecordName().try_emplace(target.Mutf8()); + else if constexpr (std::is_same_v) { + auto &&target = std::get<0>(std::forward_as_tuple(std::forward(args)...)); + GeUsedRecordName().try_emplace(target.Mutf8()); + } + Add(node, std::forward(args)...); } }; @@ -104,6 +160,44 @@ public: template ::max(), typename... Args> void Emit(const ir::AstNode *const node, Args &&...args) { + if constexpr (std::is_same_v) { + auto &&name = std::get<0>(std::forward_as_tuple(std::forward(args)...)); + HandleAndRecordName(name.Mutf8()); + } else if constexpr (std::is_same_v) { + auto &&name = std::get<0>(std::forward_as_tuple(std::forward(args)...)); + HandleAndRecordName(name.Mutf8()); + } else if constexpr (std::is_same_v) { + auto &&name = std::get<0>(std::forward_as_tuple(std::forward(args)...)); + HandleAndRecordName(std::string(name)); + } else if constexpr (std::is_same_v) { + auto &&name = std::get<0>(std::forward_as_tuple(std::forward(args)...)); + HandleAndRecordName(name.Mutf8()); + } else if constexpr (std::is_same_v) { + auto &&name = std::get<1>(std::forward_as_tuple(std::forward(args)...)); + HandleArrayName(name.Mutf8()); + } else if constexpr (std::is_same_v) { + auto &&name = std::get<2>(std::forward_as_tuple(std::forward(args)...)); + HandleArrayName(name.Mutf8()); + } else if constexpr (std::is_same_v) { + auto &&name = std::get<0>(std::forward_as_tuple(std::forward(args)...)); + HandleAndRecordName(name.Mutf8()); + } else if constexpr (std::is_same_v) { + auto &&name = std::get<0>(std::forward_as_tuple(std::forward(args)...)); + HandleAndRecordName(name.Mutf8()); + } else if constexpr (std::is_same_v) { + auto &&name = std::get<0>(std::forward_as_tuple(std::forward(args)...)); + HandleAndRecordName(name.Mutf8()); + } else if constexpr (std::is_same_v) { + auto &&name = std::get<0>(std::forward_as_tuple(std::forward(args)...)); + HandleAndRecordName(name.Mutf8()); + } else if constexpr (std::is_same_v) { + auto &&name = std::get<0>(std::forward_as_tuple(std::forward(args)...)); + HandleAndRecordName(name.Mutf8()); + } else if constexpr (std::is_same_v) { + auto &&name = std::get<0>(std::forward_as_tuple(std::forward(args)...)); + HandleAndRecordName(name.Mutf8()); + } + auto *const ins = Alloc(node, std::forward(args)...); Run(ins, VALID_VREGS); } @@ -122,6 +216,20 @@ public: template void Emit(const ir::AstNode *const node, const VReg rangeStart, const std::size_t argCount, Args &&...args) { + if constexpr (std::is_same_v) { + auto &&name = std::get<0>(std::forward_as_tuple(std::forward(args)...)); + HandleAndRecordName(name.Mutf8()); + } else if constexpr (std::is_same_v) { + auto &&name = std::get<0>(std::forward_as_tuple(std::forward(args)...)); + HandleAndRecordName(name.Mutf8()); + } else if constexpr (std::is_same_v) { + auto &&name = std::get<0>(std::forward_as_tuple(std::forward(args)...)); + HandleAndRecordName(name.Mutf8()); + } else if constexpr (std::is_same_v) { + auto &&name = std::get<0>(std::forward_as_tuple(std::forward(args)...)); + HandleAndRecordName(name.Mutf8()); + } + auto *const ins = Alloc(node, std::forward(args)...); Run(ins, rangeStart, argCount); } -- Gitee