diff --git a/.gitignore b/.gitignore index 4583ab1fb895357de1462bbd5a36ddc035661c25..17f1e53ff5b411bb847594df8b69aeb82948058d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ test262/data/ test262/eshost/ test262/harness/ -out/ \ No newline at end of file +test262/__pycache__/ +out/ diff --git a/BUILD.gn b/BUILD.gn index bbe7d8a4534cc0ece4d6b4e00e9623ff48635c49..b92dc779c873c0313eb7df11b47e4625c2a46e34 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -12,7 +12,6 @@ # limitations under the License. import("//arkcompiler/runtime_core/ark_config.gni") -import("//build/ohos.gni") group("ets_frontend_build") { deps = [ diff --git a/es2panda/BUILD.gn b/es2panda/BUILD.gn index 075eedd3e83fda04fc59ca1a6d4c77b847704ba1..86804569e550da0371d2d514c78e79b4723cde97 100644 --- a/es2panda/BUILD.gn +++ b/es2panda/BUILD.gn @@ -13,7 +13,6 @@ import("//arkcompiler/ets_frontend/ets_frontend_config.gni") import("//arkcompiler/runtime_core/ark_config.gni") -import("//build/ohos.gni") es2panda_src = [ "es2panda.cpp", @@ -154,6 +153,7 @@ es2panda_src = [ "ir/ts/tsModuleBlock.cpp", "ir/ts/tsModuleDeclaration.cpp", "ir/ts/tsNamedTupleMember.cpp", + "ir/ts/tsNamespaceExportDeclaration.cpp", "ir/ts/tsNeverKeyword.cpp", "ir/ts/tsNonNullExpression.cpp", "ir/ts/tsNullKeyword.cpp", @@ -394,7 +394,7 @@ ohos_static_library("es2panda_lib") { "$ark_root/libpandabase:libarkbase_frontend_static", "$ark_root/libpandafile:libarkfile_frontend_static", "$ark_root/libziparchive:libarkziparchive_frontend_static", - "//third_party/icu/icu4c:static_icuuc", + "$ark_third_party_root/icu/icu4c:static_icuuc", ] if (enable_bytecode_optimizer) { @@ -515,15 +515,28 @@ if (is_mac) { } } -ohos_copy("build_es2abc_for_hap") { - deps = [ ":es2panda(${host_toolchain})" ] - es2abc_root_out_dir = - get_label_info(":es2panda_build($host_toolchain)", "root_out_dir") - es2abc_target_out_dir = - get_label_info(":es2panda_build($host_toolchain)", "target_out_dir") - - sources = [ "${es2abc_root_out_dir}/arkcompiler/ets_frontend/es2abc" ] - outputs = [ "${es2abc_target_out_dir}/build/bin/es2abc" ] +if (is_linux) { + ohos_copy("build_es2abc_for_hap") { + deps = [ ":es2panda(${host_toolchain})" ] + es2abc_root_out_dir = + get_label_info(":es2panda_build($host_toolchain)", "root_out_dir") + es2abc_target_out_dir = + get_label_info(":es2panda_build($host_toolchain)", "target_out_dir") + + sources = [ "${es2abc_root_out_dir}/arkcompiler/ets_frontend/es2abc" ] + outputs = [ "${es2abc_target_out_dir}/build/bin/es2abc" ] + } +} else if (is_mac) { + ohos_copy("build_es2abc_for_hap") { + deps = [ ":es2panda(${host_toolchain})" ] + es2abc_root_out_dir = + get_label_info(":es2panda_build($host_toolchain)", "root_out_dir") + es2abc_target_out_dir = + get_label_info(":es2panda_build($host_toolchain)", "target_out_dir") + + sources = [ "${es2abc_root_out_dir}/arkcompiler/ets_frontend/es2abc" ] + outputs = [ "${es2abc_target_out_dir}/build-mac/bin/es2abc" ] + } } group("es2panda_build") { diff --git a/es2panda/aot/main.cpp b/es2panda/aot/main.cpp index 6b0f618d48360e24550ba4bfe0b5790057e17d44..3b936d39182e819f2c13d8819e79432662309b57 100644 --- a/es2panda/aot/main.cpp +++ b/es2panda/aot/main.cpp @@ -80,37 +80,61 @@ static void DumpPandaFileSizeStatistic(std::map &stat) std::cout << "total: " << totalSize << std::endl; } -static bool GenerateProgram(std::vector &progs, - std::unique_ptr &options) +static bool GenerateMultiProgram(const std::unordered_map &programs, + const std::unique_ptr &options) +{ + if (options->CompilerOptions().mergeAbc) { + std::vector progs; + for (auto &prog: programs) { + progs.push_back(prog.first); + } + + auto output = programs.begin()->second; + if (!panda::pandasm::AsmEmitter::EmitPrograms(output, progs, true)) { + std::cerr << "Failed to emit merged program, error: " << + panda::pandasm::AsmEmitter::GetLastError() << std::endl; + return false; + } + } else { + for (auto &prog: programs) { + if (!panda::pandasm::AsmEmitter::Emit(prog.second, *(prog.first), nullptr, nullptr, true)) { + std::cout << "Failed to emit single program, error: " << + panda::pandasm::AsmEmitter::GetLastError() << std::endl; + return false; + } + } + } + return true; +} + +static bool GenerateProgram(const std::unordered_map &programs, + const std::unique_ptr &options) { int optLevel = options->OptLevel(); bool dumpSize = options->SizeStat(); - const std::string output = options->CompilerOutput(); const es2panda::CompilerOptions compilerOptions = options->CompilerOptions(); if (compilerOptions.dumpAsm || compilerOptions.dumpLiteralBuffer) { - for (auto *prog : progs) { + for (auto &prog : programs) { if (compilerOptions.dumpAsm) { - es2panda::Compiler::DumpAsm(prog); + es2panda::Compiler::DumpAsm(prog.first); } if (compilerOptions.dumpLiteralBuffer) { - panda::es2panda::util::Dumper::DumpLiterals(prog->literalarray_table); + panda::es2panda::util::Dumper::DumpLiterals(prog.first->literalarray_table); } } } - if (progs.size() > 1) { - if (!panda::pandasm::AsmEmitter::EmitPrograms(output, progs, true)) { - std::cerr << "Failed to emit merged program " << std::endl; - return false; - } + if (programs.size() > 1) { + return GenerateMultiProgram(programs, options); } else { - auto *prog = progs[0]; + auto *prog = programs.begin()->first; std::map stat; std::map *statp = optLevel != 0 ? &stat : nullptr; panda::pandasm::AsmEmitter::PandaFileToPandaAsmMaps maps {}; panda::pandasm::AsmEmitter::PandaFileToPandaAsmMaps *mapsp = optLevel != 0 ? &maps : nullptr; + auto output = programs.begin()->second; if (output.empty()) { GenerateBase64Output(prog, mapsp); return true; @@ -133,6 +157,30 @@ static bool GenerateProgram(std::vector &progs, return true; } +static bool GenerateAbcFiles(const std::map &programsInfo, + const std::unique_ptr &options, size_t expectedProgsCount) +{ + std::unordered_map programs; + for (auto &info : programsInfo) { + auto outputFileName = options->OutputFiles().empty() ? options->CompilerOutput() : + options->OutputFiles().at(info.first); + programs.insert({info.second->program, outputFileName}); + } + + if (programs.size() != expectedProgsCount) { + std::cerr << "the size of programs is expected to be " << expectedProgsCount + << ", but is " << programs.size() << std::endl; + return false; + } + + if (!GenerateProgram(programs, options)) { + std::cerr << "GenerateProgram Failed!" << std::endl; + return false; + } + + return true; +} + int Run(int argc, const char **argv) { auto options = std::make_unique(); @@ -175,19 +223,7 @@ int Run(int argc, const char **argv) options->CacheFile()); } - std::vector programs; - programs.reserve(programsInfo.size()); - for (auto &it : programsInfo) { - programs.emplace_back(it.second->program); - } - if (programs.size() != expectedProgsCount) { - std::cerr << "the size of programs is expected to be " << expectedProgsCount - << ", but is " << programs.size() << std::endl; - return 1; - } - - if (!GenerateProgram(programs, options)) { - std::cerr << "GenerateProgram Failed!" << std::endl; + if (!GenerateAbcFiles(programsInfo, options, expectedProgsCount)) { return 1; } diff --git a/es2panda/aot/options.cpp b/es2panda/aot/options.cpp index d581dab53ac1c70e9f9c62cd76feee4c2ce02550..6b591b2694baa992f8637dd8d890e6de1a201c07 100644 --- a/es2panda/aot/options.cpp +++ b/es2panda/aot/options.cpp @@ -66,17 +66,19 @@ bool Options::CollectInputFilesFromFileList(const std::string &input) return false; } - constexpr size_t ITEM_COUNT = 4; + constexpr size_t ITEM_COUNT_MERGE = 4; // item list: [filePath; recordName; moduleKind; sourceFile] + constexpr size_t ITEM_COUNT_NOT_MERGE = 5; // item list: [filePath; recordName; moduleKind; sourceFile; outputfile] while (std::getline(ifs, line)) { const std::string seperator = ";"; std::vector itemList = GetStringItems(line, seperator); - if (itemList.size() != ITEM_COUNT) { + if ((compilerOptions_.mergeAbc && itemList.size() != ITEM_COUNT_MERGE) || + (!compilerOptions_.mergeAbc && itemList.size() != ITEM_COUNT_NOT_MERGE)) { std::cerr << "Failed to parse input file" << std::endl; return false; } - // itemList: [filePath, recordName, moduleKind, sourceFile] + std::string fileName = itemList[0]; - std::string recordName = itemList[1]; + std::string recordName = compilerOptions_.mergeAbc ? itemList[1] : ""; parser::ScriptKind scriptKind; if (itemList[2] == "script") { scriptKind = parser::ScriptKind::SCRIPT; @@ -89,6 +91,9 @@ bool Options::CollectInputFilesFromFileList(const std::string &input) es2panda::SourceFile src(fileName, recordName, scriptKind); src.sourcefile = itemList[3]; sourceFiles_.push_back(src); + if (!compilerOptions_.mergeAbc) { + outputFiles_.insert({fileName, itemList[4]}); + } } return true; } @@ -149,7 +154,8 @@ bool Options::Parse(int argc, const char **argv) panda::PandArg base64Output("base64Output", false, "output panda file content as base64 to std out"); panda::PandArg sourceFile("source-file", "", "specify the file path info recorded in generated abc"); - panda::PandArg outputProto("outputProto", "", "compiler proto serialize binary output (.proto)"); + panda::PandArg outputProto("outputProto", "", + "specify the output name for serializd protobuf file (.protoBin)"); panda::PandArg opCacheFile("cache-file", "", "cache file for incremental compile"); panda::PandArg opNpmModuleEntryList("npm-module-entry-list", "", "entry list file for module compile"); panda::PandArg opMergeAbc("merge-abc", false, "Compile as merge abc"); @@ -306,6 +312,7 @@ bool Options::Parse(int argc, const char **argv) recordName_ = compilerOutput_.empty() ? "Base64Output" : RemoveExtension(util::Helpers::BaseName(compilerOutput_)); } + compilerOptions_.mergeAbc = opMergeAbc.GetValue(); } if (!inputIsEmpty) { diff --git a/es2panda/aot/options.h b/es2panda/aot/options.h index 0bd501f57cda9ffd70e19e34add86b974a26f87f..f2bae2a776c546fc16832cb5f24b8d4f501bb46a 100644 --- a/es2panda/aot/options.h +++ b/es2panda/aot/options.h @@ -132,6 +132,11 @@ public: return npmModuleEntryList_; } + const std::unordered_map &OutputFiles() const + { + return outputFiles_; + } + bool CollectInputFilesFromFileList(const std::string &input); bool CollectInputFilesFromFileDirectory(const std::string &input, const std::string &extension); @@ -154,6 +159,7 @@ private: std::string cacheFile_; std::string npmModuleEntryList_; std::vector sourceFiles_; + std::unordered_map outputFiles_; }; } // namespace panda::es2panda::aot diff --git a/es2panda/binder/binder.cpp b/es2panda/binder/binder.cpp index 47b85b99676b3303e32added1978fff7bf90f1c3..0d2fd97b87f69bb69448c3bfcb0de0f38c478e55 100644 --- a/es2panda/binder/binder.cpp +++ b/es2panda/binder/binder.cpp @@ -15,7 +15,6 @@ #include "binder.h" -#include #include #include #include @@ -44,11 +43,13 @@ #include #include #include +#include #include #include #include #include #include +#include namespace panda::es2panda::binder { void Binder::InitTopScope() @@ -120,17 +121,32 @@ void Binder::IdentifierAnalysis(ResolveBindingFlags flags) void Binder::ValidateExportDecl(const ir::ExportNamedDeclaration *exportDecl) { - if (exportDecl->Source() != nullptr || exportDecl->Decl() != nullptr) { + if (exportDecl->Source() != nullptr || exportDecl->Decl() != nullptr || exportDecl->IsType()) { return; } ASSERT(topScope_->IsModuleScope()); for (auto *it : exportDecl->Specifiers()) { auto localName = it->AsExportSpecifier()->Local()->Name(); - if (topScope_->FindLocal(localName) == nullptr) { + if (scope_->IsTSModuleScope()) { + if (scope_->FindLocal(localName, ResolveBindingOptions::ALL) == nullptr && + !scope_->InLocalTSBindings(localName) && + !scope_->AsTSModuleScope()->InExportBindings(localName)) { + ThrowUndeclaredExport(it->AsExportSpecifier()->Local()->Start(), localName); + } + continue; + } + ASSERT(topScope_ == scope_); + if (scope_->FindLocal(localName) == nullptr) { + // The declaration of ts cannot correspond to the variables of ts before transform, + // After the transform, they are all js variables. So it can return directly here. + if (scope_->InLocalTSBindings(localName) || + scope_->FindLocal(localName, ResolveBindingOptions::INTERFACES)) { + continue; + } ThrowUndeclaredExport(it->AsExportSpecifier()->Local()->Start(), localName); } - topScope_->AsModuleScope()->ConvertLocalVariableToModuleVariable(Allocator(), localName); + scope_->AsModuleScope()->ConvertLocalVariableToModuleVariable(Allocator(), localName); } } @@ -247,7 +263,7 @@ void Binder::BuildScriptFunction(Scope *outerScope, const ir::ScriptFunction *sc outerVarScope->AddFlag(VariableScopeFlags::INNER_ARROW); } - ASSERT(scope_->IsFunctionScope() || scope_->IsTSModuleScope()); + ASSERT(scope_->IsFunctionScope() || scope_->IsTSModuleScope() || scope_->IsTSEnumScope()); BuildFunction(scope_->AsFunctionVariableScope(), util::Helpers::FunctionName(scriptFunc), scriptFunc); } @@ -589,6 +605,11 @@ void Binder::ResolveReference(const ir::AstNode *parent, ir::AstNode *childNode) ResolveReferences(childNode); break; } + case ir::AstNodeType::TS_ENUM_DECLARATION: { + auto scopeCtx = LexicalScope::Enter(this, childNode->AsTSEnumDeclaration()->Scope()); + ResolveReferences(childNode); + break; + } default: { ResolveReferences(childNode); break; @@ -609,6 +630,7 @@ void Binder::AddMandatoryParam(const std::string_view &name) auto &funcParams = scope_->AsFunctionVariableScope()->ParamScope()->Params(); funcParams.insert(funcParams.begin(), param); + scope_->AsFunctionVariableScope()->ParamScope()->Bindings().insert({decl->Name(), param}); scope_->AsFunctionVariableScope()->Bindings().insert({decl->Name(), param}); } @@ -664,17 +686,24 @@ void Binder::AddMandatoryParams() } } -void Binder::AddDeclarationName(const util::StringView &name) +void Binder::AddDeclarationName(const util::StringView &name, DeclType type) { if (extension_ != ScriptExtension::TS) { return; } variableNames_.insert(name); + + if (type == DeclType::ENUM) { + return; + } auto *scope = GetScope(); while (scope != nullptr) { if (scope->IsTSModuleScope()) { scope->AsTSModuleScope()->AddDeclarationName(name); } + if (scope->IsTSEnumScope()) { + scope->AsTSEnumScope()->AddDeclarationName(name); + } scope = scope->Parent(); } } diff --git a/es2panda/binder/binder.h b/es2panda/binder/binder.h index 414ff63344732770753dc12bfde8f73a8fe5a1a3..a45d8a198daec5f148103262440a115c961e2e6e 100644 --- a/es2panda/binder/binder.h +++ b/es2panda/binder/binder.h @@ -123,14 +123,14 @@ public: return anonymousFunctionNames_; } - void AddDeclarationName(const util::StringView &name); + void AddDeclarationName(const util::StringView &name, DeclType type = DeclType::NONE); bool HasVariableName(const util::StringView &name) const; static constexpr std::string_view FUNCTION_ARGUMENTS = "arguments"; - static constexpr std::string_view MANDATORY_PARAM_FUNC = "=f"; - static constexpr std::string_view MANDATORY_PARAM_NEW_TARGET = "=nt"; - static constexpr std::string_view MANDATORY_PARAM_THIS = "=t"; + static constexpr std::string_view MANDATORY_PARAM_FUNC = "4funcObj"; + static constexpr std::string_view MANDATORY_PARAM_NEW_TARGET = "4newTarget"; + static constexpr std::string_view MANDATORY_PARAM_THIS = "this"; static constexpr std::string_view CJS_MANDATORY_PARAM_EXPORTS = "exports"; static constexpr std::string_view CJS_MANDATORY_PARAM_REQUIRE = "require"; @@ -142,9 +142,9 @@ public: static constexpr uint32_t MANDATORY_PARAMS_NUMBER = 3; static constexpr uint32_t CJS_MANDATORY_PARAMS_NUMBER = 8; - static constexpr std::string_view LEXICAL_MANDATORY_PARAM_FUNC = "!f"; - static constexpr std::string_view LEXICAL_MANDATORY_PARAM_NEW_TARGET = "!nt"; - static constexpr std::string_view LEXICAL_MANDATORY_PARAM_THIS = "!t"; + static constexpr std::string_view LEXICAL_MANDATORY_PARAM_FUNC = "0funcObj"; + static constexpr std::string_view LEXICAL_MANDATORY_PARAM_NEW_TARGET = "0newTarget"; + static constexpr std::string_view LEXICAL_MANDATORY_PARAM_THIS = "0this"; static constexpr std::string_view MAIN_FUNC_NAME = "func_main_0"; static constexpr std::string_view ANONYMOUS_FUNC_NAME = ""; @@ -272,7 +272,7 @@ T *Binder::AddDecl(const lexer::SourcePosition &pos, Args &&... args) T *decl = Allocator()->New(std::forward(args)...); if (scope_->AddDecl(Allocator(), decl, program_->Extension())) { - AddDeclarationName(decl->Name()); + AddDeclarationName(decl->Name(), decl->Type()); return decl; } @@ -286,7 +286,7 @@ T *Binder::AddDecl(const lexer::SourcePosition &pos, DeclarationFlags flag, Args decl->AddFlag(flag); if (scope_->AddDecl(Allocator(), decl, program_->Extension())) { - AddDeclarationName(decl->Name()); + AddDeclarationName(decl->Name(), decl->Type()); return decl; } diff --git a/es2panda/binder/declaration.h b/es2panda/binder/declaration.h index c835e99e5ed2f3b1c06c231de62bb1c27a7c0a01..8e20c759a21d3c648ac8f312ffc22e4e2a7a281b 100644 --- a/es2panda/binder/declaration.h +++ b/es2panda/binder/declaration.h @@ -25,6 +25,7 @@ class AstNode; class ScriptFunction; class TSInterfaceDeclaration; class TSModuleDeclaration; +class TSEnumDeclaration; class ImportDeclaration; } // namespace panda::es2panda::ir @@ -32,6 +33,7 @@ namespace panda::es2panda::binder { class Scope; class LocalScope; +class TSEnumScope; #define DECLARE_CLASSES(decl_kind, className) class className; DECLARATION_KINDS(DECLARE_CLASSES) @@ -133,32 +135,46 @@ private: ArenaVector declarations_; }; -class EnumLiteralDecl : public Decl { +class EnumLiteralDecl : public MultiDecl { public: - explicit EnumLiteralDecl(util::StringView name, bool isConst) : Decl(name), isConst_(isConst) {} - + explicit EnumLiteralDecl(ArenaAllocator *allocator, util::StringView name, + bool isExport, bool isDeclare, bool isConst) : MultiDecl(allocator, name), + isExport_(isExport), isDeclare_(isDeclare), isConst_(isConst) {} + DeclType Type() const override { return DeclType::ENUM_LITERAL; } + bool IsExport() const + { + return isExport_; + } + + bool IsDeclare() const + { + return isDeclare_; + } + bool IsConst() const { return isConst_; } - void BindScope(LocalScope *scope) + void BindScope(TSEnumScope *scope) { scope_ = scope; } - LocalScope *Scope() + TSEnumScope *Scope() { return scope_; } private: - LocalScope *scope_ {}; + TSEnumScope *scope_ {nullptr}; + bool isExport_ {}; + bool isDeclare_ {}; bool isConst_ {}; }; diff --git a/es2panda/binder/scope.cpp b/es2panda/binder/scope.cpp index 696521f1887da45376ff38bcfe1baf3a1ac91e21..63e1295967f3da73a975ff76f34261c37b79141f 100644 --- a/es2panda/binder/scope.cpp +++ b/es2panda/binder/scope.cpp @@ -196,13 +196,9 @@ bool Scope::AddLocal(ArenaAllocator *allocator, Variable *currentVariable, Decl return true; } - case DeclType::ENUM: { - bindings_.insert({newDecl->Name(), allocator->New(newDecl, false)}); - return true; - } case DeclType::ENUM_LITERAL: { - bindings_.insert({newDecl->Name(), allocator->New(newDecl, VariableFlags::ENUM_LITERAL)}); - return true; + return tsBindings_.AddTSVariable( + newDecl->Name(), allocator->New(newDecl, VariableFlags::ENUM_LITERAL)); } case DeclType::INTERFACE: { bindings_.insert({newDecl->Name(), allocator->New(newDecl, VariableFlags::INTERFACE)}); @@ -298,12 +294,8 @@ bool FunctionScope::AddBinding(ArenaAllocator *allocator, Variable *currentVaria case DeclType::FUNC: { return AddFunction(allocator, currentVariable, newDecl, extension); } - case DeclType::ENUM: { - bindings_.insert({newDecl->Name(), allocator->New(newDecl, false)}); - return true; - } case DeclType::ENUM_LITERAL: { - return AddTSBinding(allocator, currentVariable, newDecl, VariableFlags::ENUM_LITERAL); + return AddTSBinding(allocator, newDecl, VariableFlags::ENUM_LITERAL); } case DeclType::NAMESPACE: { return AddTSBinding(allocator, newDecl, VariableFlags::NAMESPACE); @@ -320,6 +312,13 @@ bool FunctionScope::AddBinding(ArenaAllocator *allocator, Variable *currentVaria } } +bool TSEnumScope::AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, + [[maybe_unused]] ScriptExtension extension) +{ + ASSERT(newDecl->Type() == DeclType::ENUM); + return enumMemberBindings_->insert({newDecl->Name(), allocator->New(newDecl, false)}).second; +} + bool GlobalScope::AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, [[maybe_unused]] ScriptExtension extension) { @@ -330,12 +329,8 @@ bool GlobalScope::AddBinding(ArenaAllocator *allocator, Variable *currentVariabl case DeclType::FUNC: { return AddFunction(allocator, currentVariable, newDecl, extension); } - case DeclType::ENUM: { - bindings_.insert({newDecl->Name(), allocator->New(newDecl, false)}); - return true; - } case DeclType::ENUM_LITERAL: { - return AddTSBinding(allocator, currentVariable, newDecl, VariableFlags::ENUM_LITERAL); + return AddTSBinding(allocator, newDecl, VariableFlags::ENUM_LITERAL); } case DeclType::NAMESPACE: { return AddTSBinding(allocator, newDecl, VariableFlags::NAMESPACE); @@ -401,12 +396,8 @@ bool ModuleScope::AddBinding(ArenaAllocator *allocator, Variable *currentVariabl AddFunction(allocator, currentVariable, newDecl, extension) : AddFunction(allocator, currentVariable, newDecl, extension); } - case DeclType::ENUM: { - bindings_.insert({newDecl->Name(), allocator->New(newDecl, false)}); - return true; - } case DeclType::ENUM_LITERAL: { - return AddTSBinding(allocator, currentVariable, newDecl, VariableFlags::ENUM_LITERAL); + return AddTSBinding(allocator, newDecl, VariableFlags::ENUM_LITERAL); } case DeclType::NAMESPACE: { return AddTSBinding(allocator, newDecl, VariableFlags::NAMESPACE); diff --git a/es2panda/binder/scope.h b/es2panda/binder/scope.h index 70be5ce9a70b62060ee50a843eb4bf1fcdc7fb26..29c03a3297ca0c4a9603c581b36bd91ddb7eab68 100644 --- a/es2panda/binder/scope.h +++ b/es2panda/binder/scope.h @@ -258,7 +258,12 @@ public: return node_; } - void BindNode(const ir::AstNode *node) + ir::AstNode *Node() + { + return node_; + } + + void BindNode(ir::AstNode *node) { node_ = node; } @@ -358,7 +363,7 @@ protected: ArenaVector decls_; VariableMap bindings_; TSBindings tsBindings_; - const ir::AstNode *node_ {}; + ir::AstNode *node_ {}; const compiler::IRNode *startIns_ {}; const compiler::IRNode *endIns_ {}; }; @@ -801,6 +806,48 @@ private: ArenaSet variableNames_; }; +class TSEnumScope : public FunctionScope { +public: + explicit TSEnumScope(ArenaAllocator *allocator, Scope *parent, VariableMap *enumMemberBindings) : FunctionScope( + allocator, nullptr), enumMemberBindings_(enumMemberBindings), variableNames_(allocator->Adapter()) + { + paramScope_ = allocator->New(allocator, parent); + paramScope_->BindFunctionScope(this); + SetParent(paramScope_); + } + + ScopeType Type() const override + { + return ScopeType::TSENUM; + } + + Variable *FindEnumMemberVariable(const util::StringView &name) const + { + auto res = enumMemberBindings_->find(name); + if (res == enumMemberBindings_->end()) { + return nullptr; + } + return res->second; + } + + void AddDeclarationName(const util::StringView &name) + { + variableNames_.insert(name); + } + + bool HasDeclarationName(const util::StringView &name) const + { + return variableNames_.find(name) != variableNames_.end(); + } + + bool AddBinding(ArenaAllocator *allocator, Variable *currentVariable, Decl *newDecl, + [[maybe_unused]] ScriptExtension extension) override; + +private: + VariableMap *enumMemberBindings_; + ArenaSet variableNames_; +}; + inline VariableFlags VariableScope::DeclFlagToVariableFlag(DeclarationFlags declFlag) { VariableFlags varFlag = VariableFlags::NONE; @@ -889,7 +936,7 @@ bool VariableScope::AddTSBinding(ArenaAllocator *allocator, Decl *newDecl, Varia newDecl->Name(), allocator->New(newDecl, flags)); } case VariableFlags::ENUM_LITERAL: { - return tsBindings_.AddTSVariable( + return tsBindings_.AddTSVariable( newDecl->Name(), allocator->New(newDecl, flags)); } case VariableFlags::INTERFACE: { diff --git a/es2panda/binder/variable.cpp b/es2panda/binder/variable.cpp index 7c82dd583c4efc94180795cbbd19b096c74ffadc..0539c9ccc5c0648abfe147207c4e3d992eb9887d 100644 --- a/es2panda/binder/variable.cpp +++ b/es2panda/binder/variable.cpp @@ -70,6 +70,7 @@ void ModuleVariable::SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] void EnumVariable::SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper) {} void NamespaceVariable::SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper) {} void ImportEqualsVariable::SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper) {} +void EnumLiteralVariable::SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper) {} void EnumVariable::ResetDecl(Decl *decl) { diff --git a/es2panda/binder/variable.h b/es2panda/binder/variable.h index d9408beec3ad53a41f22fd6856222dd07ded7b6b..ad258986818255d123bfe333f7926d7eac30d76e 100644 --- a/es2panda/binder/variable.h +++ b/es2panda/binder/variable.h @@ -35,6 +35,9 @@ class Decl; class Scope; class VariableScope; class ExportBindings; +class Variable; + +using VariableMap = ArenaUnorderedMap; #define DECLARE_CLASSES(type, className) class className; VARIABLE_TYPES(DECLARE_CLASSES) @@ -46,7 +49,7 @@ public: NO_COPY_SEMANTIC(Variable); NO_MOVE_SEMANTIC(Variable); - VariableType virtual Type() const = 0; + virtual VariableType Type() const = 0; #define DECLARE_CHECKS_CASTS(variableType, className) \ bool Is##className() const \ @@ -232,6 +235,26 @@ public: backReference_ = true; } + bool IsVisited() const + { + return isVisited_; + } + + void SetVisited() + { + isVisited_ = true; + } + + bool StringInit() const + { + return isStringInit_; + } + + void SetStringInit() + { + isStringInit_ = true; + } + void ResetDecl(Decl *decl); void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper = nullptr) override; @@ -239,6 +262,8 @@ public: private: EnumMemberResult value_ {false}; bool backReference_ {}; + bool isVisited_ {false}; + bool isStringInit_ {false}; }; class NamespaceVariable : public Variable { @@ -266,6 +291,40 @@ private: ExportBindings *exportBindings_ {nullptr}; }; +class EnumLiteralVariable : public Variable { +public: + explicit EnumLiteralVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {} + + VariableType Type() const override + { + return VariableType::ENUMLITERAL; + } + + void SetLexical([[maybe_unused]] Scope *scope, [[maybe_unused]] util::Hotfix *hotfixHelper = nullptr) override; + + VariableMap *GetEnumMembers() const + { + return enumMemberBindings_; + } + + Variable *FindEnumMemberVariable(const util::StringView &name) const + { + auto res = enumMemberBindings_->find(name); + if (res == enumMemberBindings_->end()) { + return nullptr; + } + return res->second; + } + + void SetEnumMembers(VariableMap *enumMemberBindings) + { + enumMemberBindings_ = enumMemberBindings; + } + +private: + VariableMap *enumMemberBindings_ {nullptr}; +}; + class ImportEqualsVariable : public Variable { public: explicit ImportEqualsVariable(Decl *decl, VariableFlags flags) : Variable(decl, flags) {} diff --git a/es2panda/binder/variableFlags.h b/es2panda/binder/variableFlags.h index cc60c28879ea140d791b815322c5a639aff68f81..4d0d465663813d4c884ef21b2ad4306b3efbe188 100644 --- a/es2panda/binder/variableFlags.h +++ b/es2panda/binder/variableFlags.h @@ -58,7 +58,8 @@ enum class DeclType { _(FUNCTION, FunctionScope) \ _(GLOBAL, GlobalScope) \ _(MODULE, ModuleScope) \ - _(TSMODULE, TSModuleScope) + _(TSMODULE, TSModuleScope) \ + _(TSENUM, TSEnumScope) enum class ScopeType { @@ -89,7 +90,8 @@ DEFINE_BITOPS(ResolveBindingFlags) _(MODULE, ModuleVariable) \ _(ENUM, EnumVariable) \ _(NAMESPACE, NamespaceVariable) \ - _(IMPORT_EQUALS, ImportEqualsVariable) + _(IMPORT_EQUALS, ImportEqualsVariable) \ + _(ENUMLITERAL, EnumLiteralVariable) enum class VariableType { #define GEN_VARIABLE_TYPES(type, class_name) type, @@ -167,7 +169,7 @@ DEFINE_BITOPS(DeclarationFlags) enum class TSBindingType : size_t { NAMESPACE = 0, - ENUM, + ENUMLITERAL, INTERFACE, IMPORT_EQUALS, COUNT, diff --git a/es2panda/compiler/base/hoisting.cpp b/es2panda/compiler/base/hoisting.cpp index 2bf9a660b684094da30d87d2c2c73c0e2adaa92f..741c6f08fd776013aef9d7f53c504ccf2a52d347 100644 --- a/es2panda/compiler/base/hoisting.cpp +++ b/es2panda/compiler/base/hoisting.cpp @@ -70,7 +70,7 @@ static void HoistFunction(PandaGen *pg, binder::Variable *var, const binder::Fun } ASSERT(scope->IsFunctionScope() || scope->IsCatchScope() || scope->IsLocalScope() || - scope->IsModuleScope() || scope->IsTSModuleScope()); + scope->IsModuleScope() || scope->IsTSModuleScope() || scope->IsTSEnumScope()); binder::ScopeFindResult result(decl->Name(), scope, 0, var); pg->DefineFunction(decl->Node(), scriptFunction, internalName); diff --git a/es2panda/compiler/core/function.cpp b/es2panda/compiler/core/function.cpp index b9a4bce84f25fb5ddf8ee00fc4d97bebd9ee837a..fe4e8b0f89b99f8d45832033c65f29af1f355137 100644 --- a/es2panda/compiler/core/function.cpp +++ b/es2panda/compiler/core/function.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include namespace panda::es2panda::compiler { @@ -58,7 +59,11 @@ static void CompileFunctionParameterDeclaration(PandaGen *pg, const ir::ScriptFu uint32_t index = 0; - for (const auto *param : func->Params()) { + for (const auto *it : func->Params()) { + auto *param = it; + if (param->IsTSParameterProperty()) { + param = param->AsTSParameterProperty()->Parameter(); + } LReference ref = LReference::CreateLRef(pg, param, true); [[maybe_unused]] binder::Variable *paramVar = ref.Variable(); @@ -124,6 +129,9 @@ static void CompileInstanceFields(PandaGen *pg, const ir::ScriptFunction *decl) for (auto const &stmt : statements) { if (stmt->IsClassProperty()) { const auto *prop = stmt->AsClassProperty(); + if (prop->IsStatic()) { + continue; + } if (!prop->Value()) { pg->LoadConst(stmt, Constant::JS_UNDEFINED); } else { @@ -156,7 +164,9 @@ static void CompileFunction(PandaGen *pg) pg->StoreAccToLexEnv(pg->RootNode(), funcParamScope->Find(funcParamScope->NameVar()->Name()), true); } + pg->SetSourceLocationFlag(lexer::SourceLocationFlag::INVALID_SOURCE_LOCATION); pg->FunctionEnter(); + pg->SetSourceLocationFlag(lexer::SourceLocationFlag::VALID_SOURCE_LOCATION); CompileFunctionParameterDeclaration(pg, decl); const ir::AstNode *body = decl->Body(); @@ -185,7 +195,7 @@ static void CompileFunctionOrProgram(PandaGen *pg) } else { pg->FunctionInit(nullptr); - if (topScope->IsFunctionScope() || topScope->IsTSModuleScope()) { + if (topScope->IsFunctionScope() || topScope->IsTSModuleScope() || topScope->IsTSEnumScope()) { CompileFunction(pg); } else { ASSERT(topScope->IsGlobalScope() || topScope->IsModuleScope()); @@ -197,6 +207,7 @@ static void CompileFunctionOrProgram(PandaGen *pg) void Function::Compile(PandaGen *pg) { CompileFunctionOrProgram(pg); + pg->AdjustSpillInsns(); pg->SetFunctionKind(); pg->SetSourceLocationFlag(lexer::SourceLocationFlag::INVALID_SOURCE_LOCATION); pg->CopyFunctionArguments(pg->RootNode()); diff --git a/es2panda/compiler/core/pandagen.cpp b/es2panda/compiler/core/pandagen.cpp index 88a863f84f23b3fbf09436c1d599fd4fea1d0c86..a7c61bf5f4494790c6178411b33788f1e2a0cdaf 100644 --- a/es2panda/compiler/core/pandagen.cpp +++ b/es2panda/compiler/core/pandagen.cpp @@ -91,7 +91,7 @@ void PandaGen::SetFunctionKind() Label *PandaGen::AllocLabel() { std::string id = std::string {Label::PREFIX} + std::to_string(labelId_++); - return sa_.AllocLabel(std::move(id)); + return ra_.AllocLabel(std::move(id)); } bool PandaGen::IsDebug() const @@ -210,6 +210,8 @@ void PandaGen::InitializeLexEnv(const ir::AstNode *node) void PandaGen::CopyFunctionArguments(const ir::AstNode *node) { FrontAllocator fa(this); + auto spillRegsCount = ra_.GetSpillRegsCount(); + totalRegs_ += spillRegsCount; VReg targetReg = totalRegs_; for (const auto *param : topScope_->ParamScope()->Params()) { @@ -221,11 +223,11 @@ void PandaGen::CopyFunctionArguments(const ir::AstNode *node) auto typeIndex = context_->TypeRecorder()->GetVariableTypeIndex(param); if (typeIndex != extractor::TypeRecorder::PRIMITIVETYPE_ANY) { // Simply encode type index for params - MoveVregWithType(node, -(typeIndex + 1), param->Vreg(), targetReg++); + MoveVregWithType(node, -(typeIndex + 1), param->Vreg() + spillRegsCount, targetReg++); continue; } } - MoveVreg(node, param->Vreg(), targetReg++); + MoveVreg(node, param->Vreg() + spillRegsCount, targetReg++); } } @@ -462,9 +464,9 @@ void PandaGen::TryLoadGlobalByName(const ir::AstNode *node, const util::StringVi } else { int64_t typeIndex = extractor::TypeExtractor::GetBuiltinTypeIndex(name); if (context_->IsTypeExtractorEnabled() && typeIndex != extractor::TypeRecorder::PRIMITIVETYPE_ANY) { - sa_.EmitWithType(node, typeIndex, 0, name); + ra_.EmitWithType(node, typeIndex, 0, name); } else { - sa_.Emit(node, 0, name); + ra_.Emit(node, 0, name); } } strings_.insert(name); @@ -493,7 +495,7 @@ void PandaGen::TryStoreGlobalByName(const ir::AstNode *node, const util::StringV if (isDebuggerEvaluateExpressionMode()) { StoreObjByNameViaDebugger(node, name); } else { - sa_.Emit(node, 0, name); + ra_.Emit(node, 0, name); } strings_.insert(name); } @@ -501,7 +503,7 @@ void PandaGen::TryStoreGlobalByName(const ir::AstNode *node, const util::StringV void PandaGen::LoadObjByName(const ir::AstNode *node, VReg obj, const util::StringView &prop) { LoadAccumulator(node, obj); // object is load to acc - sa_.Emit(node, 0, prop); + ra_.Emit(node, 0, prop); strings_.insert(prop); } @@ -515,11 +517,11 @@ void PandaGen::LoadObjByIndex(const ir::AstNode *node, VReg obj, int64_t index) { LoadAccumulator(node, obj); // object is load to acc if (index <= util::Helpers::MAX_INT16) { - sa_.Emit(node, 0, index); + ra_.Emit(node, 0, index); return; } - sa_.Emit(node, index); + ra_.Emit(node, index); } void PandaGen::LoadObjByValue(const ir::AstNode *node, VReg obj) @@ -586,13 +588,13 @@ void PandaGen::LoadAccumulator(const ir::AstNode *node, VReg reg) void PandaGen::LoadGlobalVar(const ir::AstNode *node, const util::StringView &name) { - sa_.Emit(node, 0, name); + ra_.Emit(node, 0, name); strings_.insert(name); } void PandaGen::StoreGlobalVar(const ir::AstNode *node, const util::StringView &name) { - sa_.Emit(node, 0, name); + ra_.Emit(node, 0, name); strings_.insert(name); } @@ -608,28 +610,28 @@ void PandaGen::StoreAccToLexEnv(const ir::AstNode *node, const binder::ScopeFind void PandaGen::LoadAccumulatorString(const ir::AstNode *node, const util::StringView &str) { - sa_.Emit(node, str); + ra_.Emit(node, str); strings_.insert(str); } void PandaGen::LoadAccumulatorFloat(const ir::AstNode *node, double num) { - sa_.Emit(node, num); + ra_.Emit(node, num); } void PandaGen::LoadAccumulatorInt(const ir::AstNode *node, int32_t num) { - sa_.Emit(node, num); + ra_.Emit(node, num); } void PandaGen::LoadAccumulatorInt(const ir::AstNode *node, size_t num) { - sa_.Emit(node, static_cast(num)); + ra_.Emit(node, static_cast(num)); } void PandaGen::LoadAccumulatorBigInt(const ir::AstNode *node, const util::StringView &num) { - sa_.Emit(node, num); + ra_.Emit(node, num); strings_.insert(num); } @@ -643,39 +645,39 @@ void PandaGen::LoadConst(const ir::AstNode *node, Constant id) { switch (id) { case Constant::JS_HOLE: { - sa_.Emit(node); + ra_.Emit(node); break; } case Constant::JS_NAN: { - sa_.Emit(node); + ra_.Emit(node); break; } case Constant::JS_INFINITY: { - sa_.Emit(node); + ra_.Emit(node); break; } case Constant::JS_GLOBAL: { - sa_.Emit(node); + ra_.Emit(node); break; } case Constant::JS_UNDEFINED: { - sa_.Emit(node); + ra_.Emit(node); break; } case Constant::JS_SYMBOL: { - sa_.Emit(node); + ra_.Emit(node); break; } case Constant::JS_NULL: { - sa_.Emit(node); + ra_.Emit(node); break; } case Constant::JS_TRUE: { - sa_.Emit(node); + ra_.Emit(node); break; } case Constant::JS_FALSE: { - sa_.Emit(node); + ra_.Emit(node); break; } default: { @@ -696,12 +698,12 @@ void PandaGen::MoveVregWithType(const ir::AstNode *node, int64_t typeIndex, VReg void PandaGen::SetLabel([[maybe_unused]] const ir::AstNode *node, Label *label) { - sa_.AddLabel(label); + ra_.AddLabel(label); } void PandaGen::Branch(const ir::AstNode *node, Label *label) { - sa_.Emit(node, label); + ra_.Emit(node, label); } bool PandaGen::CheckControlFlowChange() const @@ -831,12 +833,12 @@ void PandaGen::Unary(const ir::AstNode *node, lexer::TokenType op, VReg operand) } case lexer::TokenType::PUNCTUATOR_MINUS: { LoadAccumulator(node, operand); - sa_.Emit(node, 0); + ra_.Emit(node, 0); break; } case lexer::TokenType::PUNCTUATOR_TILDE: { LoadAccumulator(node, operand); - sa_.Emit(node, 0); + ra_.Emit(node, 0); break; } case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK: { @@ -845,12 +847,12 @@ void PandaGen::Unary(const ir::AstNode *node, lexer::TokenType op, VReg operand) } case lexer::TokenType::PUNCTUATOR_PLUS_PLUS: { LoadAccumulator(node, operand); - sa_.Emit(node, 0); + ra_.Emit(node, 0); break; } case lexer::TokenType::PUNCTUATOR_MINUS_MINUS: { LoadAccumulator(node, operand); - sa_.Emit(node, 0); + ra_.Emit(node, 0); break; } case lexer::TokenType::KEYW_VOID: @@ -1020,7 +1022,7 @@ void PandaGen::GreaterEqual(const ir::AstNode *node, VReg lhs) void PandaGen::IsTrue(const ir::AstNode *node) { - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::BranchIfUndefined(const ir::AstNode *node, Label *target) @@ -1030,7 +1032,7 @@ void PandaGen::BranchIfUndefined(const ir::AstNode *node, Label *target) StoreAccumulator(node, tmp); LoadConst(node, Constant::JS_UNDEFINED); Equal(node, tmp); - sa_.Emit(node, target); + ra_.Emit(node, target); } void PandaGen::BranchIfNotUndefined(const ir::AstNode *node, Label *target) @@ -1040,7 +1042,7 @@ void PandaGen::BranchIfNotUndefined(const ir::AstNode *node, Label *target) StoreAccumulator(node, tmp); LoadConst(node, Constant::JS_UNDEFINED); Equal(node, tmp); - sa_.Emit(node, target); + ra_.Emit(node, target); } void PandaGen::BranchIfStrictNotUndefined(const ir::AstNode *node, class Label *target) @@ -1050,13 +1052,13 @@ void PandaGen::BranchIfStrictNotUndefined(const ir::AstNode *node, class Label * StoreAccumulator(node, tmp); LoadConst(node, Constant::JS_UNDEFINED); StrictEqual(node, tmp); - sa_.Emit(node, target); + ra_.Emit(node, target); } void PandaGen::BranchIfTrue(const ir::AstNode *node, Label *target) { IsTrue(node); - sa_.Emit(node, target); + ra_.Emit(node, target); } void PandaGen::BranchIfNotTrue(const ir::AstNode *node, Label *target) @@ -1067,13 +1069,23 @@ void PandaGen::BranchIfNotTrue(const ir::AstNode *node, Label *target) void PandaGen::BranchIfFalse(const ir::AstNode *node, Label *target) { - sa_.Emit(node); - sa_.Emit(node, target); + ra_.Emit(node); + ra_.Emit(node, target); +} + +void PandaGen::BranchIfStrictNull(const ir::AstNode *node, class Label *target) +{ + RegScope rs(this); + VReg tmp = AllocReg(); + StoreAccumulator(node, tmp); + LoadConst(node, Constant::JS_NULL); + ra_.Emit(node, 0, tmp); + ra_.Emit(node, target); } void PandaGen::EmitThrow(const ir::AstNode *node) { - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::EmitRethrow(const ir::AstNode *node) @@ -1090,7 +1102,7 @@ void PandaGen::EmitRethrow(const ir::AstNode *node) LoadAccumulator(node, exception); NotEqual(node, hole); - sa_.Emit(node, skipThrow); + ra_.Emit(node, skipThrow); SetLabel(node, doThrow); LoadAccumulator(node, exception); @@ -1101,12 +1113,12 @@ void PandaGen::EmitRethrow(const ir::AstNode *node) void PandaGen::EmitReturn(const ir::AstNode *node) { - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::EmitReturnUndefined(const ir::AstNode *node) { - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::ImplicitReturn(const ir::AstNode *node) @@ -1180,11 +1192,11 @@ void PandaGen::CallThis(const ir::AstNode *node, VReg startReg, size_t argCount) default: { int64_t actualArgs = argCount - 1; if (actualArgs <= util::Helpers::MAX_INT8) { - rra_.Emit(node, thisReg, argCount + 1, 0, actualArgs, thisReg); + ra_.EmitRange(node, argCount, 0, actualArgs, thisReg); break; } - rra_.Emit(node, thisReg, argCount + 1, actualArgs, thisReg); + ra_.EmitRange(node, argCount, actualArgs, thisReg); break; } } @@ -1195,7 +1207,7 @@ void PandaGen::Call(const ir::AstNode *node, VReg startReg, size_t argCount) LoadAccumulator(node, startReg); // callee is load to acc switch (argCount) { case 0: { // 0 args - sa_.Emit(node, 0); + ra_.Emit(node, 0); break; } case 1: { // 1 arg @@ -1219,11 +1231,11 @@ void PandaGen::Call(const ir::AstNode *node, VReg startReg, size_t argCount) default: { VReg arg0 = startReg + 1; if (argCount <= util::Helpers::MAX_INT8) { - rra_.Emit(node, arg0, argCount, 0, argCount, arg0); + ra_.EmitRange(node, argCount, 0, argCount, arg0); break; } - rra_.Emit(node, arg0, argCount, argCount, arg0); + ra_.EmitRange(node, argCount, argCount, arg0); break; } } @@ -1234,20 +1246,20 @@ void PandaGen::SuperCall(const ir::AstNode *node, VReg startReg, size_t argCount if (RootNode()->AsScriptFunction()->IsArrow()) { GetFunctionObject(node); // load funcobj to acc for super call in arrow function if (argCount <= util::Helpers::MAX_INT8) { - rra_.Emit(node, startReg, argCount, 0, static_cast(argCount), startReg); + ra_.EmitRange(node, argCount, 0, static_cast(argCount), startReg); } else { - rra_.Emit(node, startReg, argCount, static_cast(argCount), startReg); + ra_.EmitRange(node, argCount, static_cast(argCount), startReg); } return; } if (argCount <= util::Helpers::MAX_INT8) { // no need to load funcobj to acc for super call in other kinds of functions - rra_.Emit(node, startReg, argCount, 0, static_cast(argCount), startReg); + ra_.EmitRange(node, argCount, 0, static_cast(argCount), startReg); return; } - rra_.Emit(node, startReg, argCount, static_cast(argCount), startReg); + ra_.EmitRange(node, argCount, static_cast(argCount), startReg); } void PandaGen::SuperCallSpread(const ir::AstNode *node, VReg vs) @@ -1258,11 +1270,11 @@ void PandaGen::SuperCallSpread(const ir::AstNode *node, VReg vs) void PandaGen::NewObject(const ir::AstNode *node, VReg startReg, size_t argCount) { if (argCount <= util::Helpers::MAX_INT8) { - rra_.Emit(node, startReg, argCount, 0, static_cast(argCount), startReg); + ra_.EmitRange(node, argCount, 0, static_cast(argCount), startReg); return; } - rra_.Emit(node, startReg, argCount, static_cast(argCount), startReg); + ra_.EmitRange(node, argCount, static_cast(argCount), startReg); } void PandaGen::DefineFunction(const ir::AstNode *node, const ir::ScriptFunction *realNode, const util::StringView &name) @@ -1283,7 +1295,7 @@ void PandaGen::DefineFunction(const ir::AstNode *node, const ir::ScriptFunction void PandaGen::TypeOf(const ir::AstNode *node) { - sa_.Emit(node, 0); + ra_.Emit(node, 0); } void PandaGen::CallSpread(const ir::AstNode *node, VReg func, VReg thisReg, VReg args) @@ -1299,7 +1311,7 @@ void PandaGen::NewObjSpread(const ir::AstNode *node, VReg obj) void PandaGen::GetUnmappedArgs(const ir::AstNode *node) { - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::Negate(const ir::AstNode *node) @@ -1317,13 +1329,13 @@ void PandaGen::Negate(const ir::AstNode *node) void PandaGen::ToNumber(const ir::AstNode *node, VReg arg) { LoadAccumulator(node, arg); - sa_.Emit(node, 0); + ra_.Emit(node, 0); } void PandaGen::ToNumeric(const ir::AstNode *node, VReg arg) { LoadAccumulator(node, arg); - sa_.Emit(node, 0); + ra_.Emit(node, 0); } void PandaGen::CreateGeneratorObj(const ir::AstNode *node, VReg funcObj) @@ -1373,18 +1385,18 @@ void PandaGen::GeneratorComplete(const ir::AstNode *node, VReg genObj) void PandaGen::ResumeGenerator(const ir::AstNode *node, VReg genObj) { LoadAccumulator(node, genObj); - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::GetResumeMode(const ir::AstNode *node, VReg genObj) { LoadAccumulator(node, genObj); - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::AsyncFunctionEnter(const ir::AstNode *node) { - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::AsyncFunctionAwait(const ir::AstNode *node, VReg asyncFuncObj) @@ -1415,17 +1427,17 @@ void PandaGen::AsyncGeneratorReject(const ir::AstNode *node, VReg asyncGenObj) void PandaGen::GetTemplateObject(const ir::AstNode *node, VReg value) { LoadAccumulator(node, value); - sa_.Emit(node, 0); + ra_.Emit(node, 0); } void PandaGen::CopyRestArgs(const ir::AstNode *node, uint32_t index) { - index <= util::Helpers::MAX_INT8 ? sa_.Emit(node, index) : sa_.Emit(node, index); + index <= util::Helpers::MAX_INT8 ? ra_.Emit(node, index) : ra_.Emit(node, index); } void PandaGen::GetPropIterator(const ir::AstNode *node) { - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::GetNextPropName(const ir::AstNode *node, VReg iter) @@ -1435,7 +1447,7 @@ void PandaGen::GetNextPropName(const ir::AstNode *node, VReg iter) void PandaGen::CreateEmptyObject(const ir::AstNode *node) { - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::CreateObjectWithBuffer(const ir::AstNode *node, uint32_t idx) @@ -1443,7 +1455,7 @@ void PandaGen::CreateObjectWithBuffer(const ir::AstNode *node, uint32_t idx) ASSERT(util::Helpers::IsInteger(idx)); std::string idxStr = std::string(context_->Binder()->Program()->RecordName()) + "_" + std::to_string(idx); util::UString litId(idxStr, allocator_); - sa_.Emit(node, 0, litId.View()); + ra_.Emit(node, 0, litId.View()); } void PandaGen::SetObjectWithProto(const ir::AstNode *node, VReg proto, VReg obj) @@ -1466,7 +1478,7 @@ void PandaGen::DefineGetterSetterByValue(const ir::AstNode *node, VReg obj, VReg void PandaGen::CreateEmptyArray(const ir::AstNode *node) { - sa_.Emit(node, 0); + ra_.Emit(node, 0); } void PandaGen::CreateArrayWithBuffer(const ir::AstNode *node, uint32_t idx) @@ -1474,7 +1486,7 @@ void PandaGen::CreateArrayWithBuffer(const ir::AstNode *node, uint32_t idx) ASSERT(util::Helpers::IsInteger(idx)); std::string idxStr = std::string(context_->Binder()->Program()->RecordName()) + "_" + std::to_string(idx); util::UString litId(idxStr, allocator_); - sa_.Emit(node, 0, litId.View()); + ra_.Emit(node, 0, litId.View()); } void PandaGen::CreateArray(const ir::AstNode *node, const ArenaVector &elements, VReg obj) @@ -1585,19 +1597,19 @@ void PandaGen::ThrowIfNotObject(const ir::AstNode *node, VReg obj) void PandaGen::ThrowThrowNotExist(const ir::AstNode *node) { - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::GetIterator(const ir::AstNode *node) { - sa_.Emit(node, 0); + ra_.Emit(node, 0); } void PandaGen::GetAsyncIterator(const ir::AstNode *node) { /* * TODO: async iterator - * sa_.Emit(node); + * ra_.Emit(node); */ } @@ -1612,18 +1624,16 @@ void PandaGen::CreateObjectWithExcludedKeys(const ir::AstNode *node, VReg obj, V size_t argRegCnt = (argCount == 0 ? argCount : argCount - 1); if (argRegCnt <= util::Helpers::MAX_INT8) { - rra_.Emit(node, argStart, argCount, static_cast(argRegCnt), - obj, argStart); + ra_.EmitRange(node, argCount, static_cast(argRegCnt), obj, argStart); return; } - rra_.Emit(node, argStart, argCount, static_cast(argRegCnt), - obj, argStart); + ra_.EmitRange(node, argCount, static_cast(argRegCnt), obj, argStart); } void PandaGen::ThrowObjectNonCoercible(const ir::AstNode *node) { - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::CloseIterator(const ir::AstNode *node, VReg iter) @@ -1643,28 +1653,28 @@ void PandaGen::DefineClassWithBuffer(const ir::AstNode *node, const util::String void PandaGen::LoadLocalModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable) { auto index = variable->Index(); - index <= util::Helpers::MAX_INT8 ? sa_.Emit(node, index) : - sa_.Emit(node, index); + index <= util::Helpers::MAX_INT8 ? ra_.Emit(node, index) : + ra_.Emit(node, index); } void PandaGen::LoadExternalModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable) { auto index = variable->Index(); - index <= util::Helpers::MAX_INT8 ? sa_.Emit(node, index) : - sa_.Emit(node, index); + index <= util::Helpers::MAX_INT8 ? ra_.Emit(node, index) : + ra_.Emit(node, index); } void PandaGen::StoreModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable) { auto index = variable->Index(); - index <= util::Helpers::MAX_INT8 ? sa_.Emit(node, index) : - sa_.Emit(node, index); + index <= util::Helpers::MAX_INT8 ? ra_.Emit(node, index) : + ra_.Emit(node, index); } void PandaGen::GetModuleNamespace(const ir::AstNode *node, uint32_t index) { - index <= util::Helpers::MAX_INT8 ? sa_.Emit(node, index) : - sa_.Emit(node, index); + index <= util::Helpers::MAX_INT8 ? ra_.Emit(node, index) : + ra_.Emit(node, index); } void PandaGen::DynamicImportCall(const ir::AstNode *node) @@ -1681,7 +1691,7 @@ void PandaGen::StSuperByName(const ir::AstNode *node, VReg obj, const util::Stri void PandaGen::LdSuperByName(const ir::AstNode *node, VReg obj, const util::StringView &key) { LoadAccumulator(node, obj); // object is load to acc - sa_.Emit(node, 0, key); + ra_.Emit(node, 0, key); strings_.insert(key); } @@ -1741,27 +1751,27 @@ void PandaGen::LoadSuperProperty(const ir::AstNode *node, VReg obj, const Operan void PandaGen::LoadLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot) { if ((level > util::Helpers::MAX_INT8) || (slot > util::Helpers::MAX_INT8)) { - sa_.Emit(node, level, slot); + ra_.Emit(node, level, slot); return; } - sa_.Emit(node, level, slot); + ra_.Emit(node, level, slot); } void PandaGen::LoadLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot, const util::StringView &name) { if (context_->HotfixHelper() && context_->HotfixHelper()->IsPatchVar(slot)) { uint32_t patchSlot = context_->HotfixHelper()->GetPatchLexicalIdx(std::string(name)); - sa_.Emit(node, patchSlot); + ra_.Emit(node, patchSlot); return; } if ((level > util::Helpers::MAX_INT8) || (slot > util::Helpers::MAX_INT8)) { - sa_.Emit(node, level, slot); + ra_.Emit(node, level, slot); return; } - sa_.Emit(node, level, slot); + ra_.Emit(node, level, slot); } void PandaGen::StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot) @@ -1789,7 +1799,7 @@ void PandaGen::StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t { if (context_->HotfixHelper() && context_->HotfixHelper()->IsPatchVar(slot)) { uint32_t patchSlot = context_->HotfixHelper()->GetPatchLexicalIdx(std::string(name)); - sa_.Emit(node, patchSlot); + ra_.Emit(node, patchSlot); return; } RegScope rs(this); @@ -1800,7 +1810,7 @@ void PandaGen::StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t void PandaGen::ThrowIfSuperNotCorrectCall(const ir::AstNode *node, int64_t num) { - sa_.Emit(node, num); + ra_.Emit(node, num); } void PandaGen::ThrowUndefinedIfHole(const ir::AstNode *node, const util::StringView &name) @@ -1828,14 +1838,14 @@ void PandaGen::ThrowConstAssignment(const ir::AstNode *node, const util::StringV void PandaGen::PopLexEnv(const ir::AstNode *node) { - sa_.Emit(node); + ra_.Emit(node); } void PandaGen::CopyLexEnv(const ir::AstNode *node) { /* * TODO: add copy lexenv to optimize the loop env creation - * sa_.Emit(node); + * ra_.Emit(node); */ } @@ -1852,15 +1862,15 @@ void PandaGen::NewLexicalEnv(const ir::AstNode *node, uint32_t num, binder::Vari void PandaGen::NewLexEnv(const ir::AstNode *node, uint32_t num) { - num <= util::Helpers::MAX_INT8 ? sa_.Emit(node, num) : sa_.Emit(node, num); + num <= util::Helpers::MAX_INT8 ? ra_.Emit(node, num) : ra_.Emit(node, num); } void PandaGen::NewLexEnvWithScopeInfo(const ir::AstNode *node, uint32_t num, int32_t scopeInfoIdx) { std::string idxStr = std::string(context_->Binder()->Program()->RecordName()) + "_" + std::to_string(scopeInfoIdx); util::UString litId(idxStr, allocator_); - num <= util::Helpers::MAX_INT8 ? sa_.Emit(node, num, litId.View()) : - sa_.Emit(node, num, litId.View()); + num <= util::Helpers::MAX_INT8 ? ra_.Emit(node, num, litId.View()) : + ra_.Emit(node, num, litId.View()); } uint32_t PandaGen::TryDepth() const @@ -1980,13 +1990,13 @@ VReg PandaGen::LoadPropertyKey(const ir::Expression *prop, bool isComputed) void PandaGen::StLetOrClassToGlobalRecord(const ir::AstNode *node, const util::StringView &name) { - sa_.Emit(node, 0, name); + ra_.Emit(node, 0, name); strings_.insert(name); } void PandaGen::StConstToGlobalRecord(const ir::AstNode *node, const util::StringView &name) { - sa_.Emit(node, 0, name); + ra_.Emit(node, 0, name); strings_.insert(name); } diff --git a/es2panda/compiler/core/pandagen.h b/es2panda/compiler/core/pandagen.h index cdc5a69bc9ed5f42fb9da97f9fd51da737b5fb8d..7bdf525e81f91f95410e22d5caaf34508748498a 100644 --- a/es2panda/compiler/core/pandagen.h +++ b/es2panda/compiler/core/pandagen.h @@ -89,9 +89,7 @@ public: catchList_(allocator_->Adapter()), strings_(allocator_->Adapter()), buffStorage_(allocator_->Adapter()), - sa_(this), - ra_(this), - rra_(this) + ra_(this) { } ~PandaGen() = default; @@ -143,6 +141,11 @@ public: return insns_; } + void SetInsns(ArenaList &newInsns) + { + insns_.assign(newInsns.begin(), newInsns.end()); + } + ArenaMap &TypedInsns() { return typedInsns_; @@ -155,6 +158,9 @@ public: VReg AllocReg() { + if (usedRegs_ > UINT16_MAX) { + throw Error(ErrorType::GENERIC, "Can't alloc new reg because all regs ran out"); + } return usedRegs_++; } @@ -205,9 +211,12 @@ public: void SetSourceLocationFlag(lexer::SourceLocationFlag flag) { - sa_.SetSourceLocationFlag(flag); ra_.SetSourceLocationFlag(flag); - rra_.SetSourceLocationFlag(flag); + } + + void AdjustSpillInsns() + { + ra_.AdjustInsRegWhenHasSpill(); } panda::panda_file::FunctionKind GetFunctionKind() const @@ -313,6 +322,7 @@ public: void BranchIfNotTrue(const ir::AstNode *node, class Label *target); void BranchIfFalse(const ir::AstNode *node, class Label *target); void BranchIfNotFalse(const ir::AstNode *node, class Label *target); + void BranchIfStrictNull(const ir::AstNode *node, class Label *target); void EmitThrow(const ir::AstNode *node); void EmitRethrow(const ir::AstNode *node); @@ -479,9 +489,7 @@ private: DynamicContext *dynamicContext_ {}; OptionalChain *optionalChain_ {}; InlineCache ic_; - SimpleAllocator sa_; RegAllocator ra_; - RangeRegAllocator rra_; IcSizeType currentSlot_ {0}; uint32_t usedRegs_ {0}; diff --git a/es2panda/compiler/core/regAllocator.cpp b/es2panda/compiler/core/regAllocator.cpp index 7e9ce2ca7268ae0afc3ad16cda4b9b2ad95d2ad8..7c41a1bd4d9f6b82b890cae7a80a2ad427f395f4 100644 --- a/es2panda/compiler/core/regAllocator.cpp +++ b/es2panda/compiler/core/regAllocator.cpp @@ -21,161 +21,191 @@ namespace panda::es2panda::compiler { -// AllocatorBase +// FrontAllocator -void AllocatorBase::PushBack(IRNode *ins) +FrontAllocator::FrontAllocator(PandaGen *pg) + : pg_(pg), insn_(std::move(pg_->Insns()), pg_->Allocator()->Adapter()) { - pg_->Insns().push_back(ins); } -ArenaAllocator *AllocatorBase::Allocator() const +FrontAllocator::~FrontAllocator() { - return pg_->Allocator(); + pg_->Insns().splice(pg_->Insns().end(), std::move(insn_)); } -void AllocatorBase::UpdateIcSlot(IRNode *node) +// RegAllocator + +void RegAllocator::PushBack(IRNode *ins) { - auto inc = node->SetIcSlot(pg_->GetCurrentSlot()); - pg_->IncreaseCurrentSlot(inc); + pg_->Insns().push_back(ins); } -void SimpleAllocator::Run(IRNode *ins, int64_t typeIndex) +ArenaAllocator *RegAllocator::Allocator() const { - PushBack(ins); - pg_->TypedInsns()[ins] = typeIndex; + return pg_->Allocator(); } -// FrontAllocator - -FrontAllocator::FrontAllocator(PandaGen *pg) - : AllocatorBase(pg), insn_(std::move(pg_->Insns()), pg_->Allocator()->Adapter()) +uint16_t RegAllocator::GetSpillRegsCount() const { + return spillRegs_; } -FrontAllocator::~FrontAllocator() +void RegAllocator::UpdateIcSlot(IRNode *node) { - pg_->Insns().splice(pg_->Insns().end(), std::move(insn_)); + auto inc = node->SetIcSlot(pg_->GetCurrentSlot()); + pg_->IncreaseCurrentSlot(inc); } -// SimpleAllocator -Label *SimpleAllocator::AllocLabel(std::string &&id) +Label *RegAllocator::AllocLabel(std::string &&id) { const auto *lastInsNode = pg_->Insns().empty() ? FIRST_NODE_OF_FUNCTION : pg_->Insns().back()->Node(); return Alloc