diff --git a/BUILD.gn b/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..f8c78ee6ccb1382b9669f0c6848eacdd06be8808 --- /dev/null +++ b/BUILD.gn @@ -0,0 +1,22 @@ +# Copyright (c) 2021-2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/runtime_core/ark_config.gni") +import("//build/ohos.gni") + +group("ets_frontend_build") { + deps = [ + "./es2panda:es2panda_build", + "./ts2panda:ark_ts2abc_build", + ] +} diff --git a/OAT.xml b/OAT.xml index d70eb7ebe42bb1387ea3c9901d50ab0f80d621ae..4efd6e9cf074a78838fd6ee5b40f42db6156fafe 100644 --- a/OAT.xml +++ b/OAT.xml @@ -53,7 +53,7 @@ Note:If the text contains special characters, please escape them according to th - + diff --git a/README.md b/README.md index 311ebb5c70fd3f98f5068b4d953c0d781143f548..20dd9bce714eeabdadf6a32169f7ad3c0a696765 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# ts2abc +# ets_frontend -- [ts2abc ](#ts2abc-) +- [ets_frontend ](#ets_frontend-) - [Introduction](#introduction) - [Directory Structure](#directory-structure) - [Build](#Build) @@ -9,14 +9,14 @@ ## Introduction -ts2abc is a front-end tool in the ARK Runtime Subsystem. It converts JavaScript(JS) files into ARK bytecode files. +ets_frontend is a front-end tool in the ARK Runtime Subsystem. It converts JavaScript(JS) files into ARK bytecode files. For more information, see: [ARK Runtime Subsystem](https://gitee.com/openharmony/docs/blob/master/en/readme/ARK-Runtime-Subsystem.md). ## Directory Structure ``` -/ark/ts2abc/ +/arkcompiler/ets_frontend/ ├── test262 # scripts for configuration and running Test262 ├── testTs # system test cases ├── ts2panda @@ -31,7 +31,7 @@ For more information, see: [ARK Runtime Subsystem](https://gitee.com/openharmony ## Build -ts2abc uses the command line interaction mode and converts JS code into ARK bytecode files that can be run on an ARK runtime system. ts2abc supports Windows, Linux, and macOS. Front-end tools, converting JS source code into ARK bytecode, can be built by specifying the `--build-target` with `ark_ts2abc` on Linux. +ets_frontend uses the command line interaction mode and converts JS code into ARK bytecode files that can be run on an ARK runtime system. ets_frontend supports Windows, Linux, and macOS. Front-end tools, converting JS source code into ARK bytecode, can be built by specifying the `--build-target` with `ark_ts2abc` on Linux. ``` $ ./build.sh --product-name hispark_taurus_standard --build-target ark_ts2abc_build @@ -270,8 +270,8 @@ For more information, please see: [ARK-Runtime-Usage-Guide](https://gitee.com/op ## Repositories Involved -[ark\_runtime\_core](https://gitee.com/openharmony/ark_runtime_core) +[arkcompiler\_runtime\_core](https://gitee.com/openharmony/arkcompiler_runtime_core) -[ark\_js\_runtime](https://gitee.com/openharmony/ark_js_runtime) +[arkcompiler\_ets\_runtime](https://gitee.com/openharmony/arkcompiler_ets_runtime) -**[ark\_ts2abc](https://gitee.com/openharmony/ark_ts2abc)** +**[arkcompiler\_ets\_frontend](https://gitee.com/openharmony/arkcompiler_ets_frontend)** diff --git a/README_zh.md b/README_zh.md index 3cf2b8b5b11862e47c92366d18d226e3ad15dd21..37d31bd7e52b076f1091298abba571c944638f14 100644 --- a/README_zh.md +++ b/README_zh.md @@ -1,6 +1,6 @@ -# ts2abc组件 +# ets_frontend组件 -- [ts2abc组件](#ts2abc组件) +- [ets_frontend组件](#ets_frontend组件) - [简介](#简介) - [目录](#目录) - [编译构建](#编译构建) @@ -9,14 +9,14 @@ ## 简介 -ts2abc组件是方舟运行时子系统的前端工具,支持将JavaScript文件转换为方舟字节码文件。 +ets_frontend组件是方舟运行时子系统的前端工具,支持将JavaScript文件转换为方舟字节码文件。 更多信息请参考:[方舟运行时子系统](https://gitee.com/openharmony/docs/blob/master/zh-cn/readme/ARK-Runtime-Subsystem-zh.md) ## 目录 ``` -/ark/ts2abc/ +/arkcompiler/ets_frontend/ ├── test262 # test262测试配置和运行脚本 ├── testTs # 系统测试目录 ├── ts2panda @@ -31,7 +31,7 @@ ts2abc组件是方舟运行时子系统的前端工具,支持将JavaScript文 ## 编译构建 -ts2abc组件采用命令行交互方式,支持将JavaScript代码转换为方舟字节码文件,使其能够在方舟运行时上运行。支持Windows/Linux/MacOS平台。方舟前端工具在linux平台上可通过全量编译或指定编译前端工具链获取。 +ets_frontend组件采用命令行交互方式,支持将JavaScript代码转换为方舟字节码文件,使其能够在方舟运行时上运行。支持Windows/Linux/MacOS平台。方舟前端工具在linux平台上可通过全量编译或指定编译前端工具链获取。 ``` $ ./build.sh --product-name hispark_taurus_standard --build-target ark_ts2abc_build @@ -41,7 +41,7 @@ $ ./build.sh --product-name hispark_taurus_standard --build-target ark_ts2abc_bu 安装`node`和`npm` -使用ts2abc组件将JavaScript文件转换为方舟字节码文件 +使用ets_frontend组件将JavaScript文件转换为方舟字节码文件 ``` $ cd out/hispark_taurus/clang_x64/ark/ark/build @@ -271,8 +271,8 @@ $ node --expose-gc src/index.js [options] file.js ## 相关仓 -[ark\_runtime\_core](https://gitee.com/openharmony/ark_runtime_core) +[arkcompiler\_runtime\_core](https://gitee.com/openharmony/arkcompiler_runtime_core) -[ark\_js\_runtime](https://gitee.com/openharmony/ark_js_runtime) +[arkcompiler\_ets\_runtime](https://gitee.com/openharmony/arkcompiler_ets_runtime) -**[ark\_ts2abc](https://gitee.com/openharmony/ark_ts2abc)** +**[arkcompiler\_ets\_frontend](https://gitee.com/openharmony/arkcompiler_ets_frontend)** diff --git a/bundle.json b/bundle.json index 36f2d2379df2eaa05fdfbc398f42b8ca1f3b6699..4ea189cf703d9a76a80d73df06765ca01a4be1a3 100644 --- a/bundle.json +++ b/bundle.json @@ -1,10 +1,10 @@ { - "name": "@ohos/ark_ts2abc", + "name": "@ohos/arkcompiler_ets_frontend", "description": "支持应用TS/JS语言代码的编译,行为符合ArkUI框架需要的Strict模式的ES2015标准", "version": "3.1", "license": "Apache V2", "component": { - "name": "ark_frontend_tool", + "name": "ets_frontend", "subsystem": "ark", "syscap": [], "features": [], @@ -18,9 +18,11 @@ "third_party": [] }, "build": { - "sub_component": [], + "sub_component": [ + "//arkcompiler/ets_frontend:ets_frontend_build" + ], "inner_kits": [], "test": [] } } -} \ No newline at end of file +} diff --git a/es2panda/BUILD.gn b/es2panda/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..31eda11e1fb5cb994b62b1ab1977499d511a2f89 --- /dev/null +++ b/es2panda/BUILD.gn @@ -0,0 +1,484 @@ +# Copyright (c) 2021-2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_frontend/ets_frontend_config.gni") +import("//arkcompiler/runtime_core/ark_config.gni") +import("//build/ohos.gni") + +es2panda_src = [ + "es2panda.cpp", + "binder/binder.cpp", + "binder/declaration.cpp", + "binder/scope.cpp", + "binder/variable.cpp", + "compiler/base/catchTable.cpp", + "compiler/base/condition.cpp", + "compiler/base/destructuring.cpp", + "compiler/base/hoisting.cpp", + "compiler/base/iterators.cpp", + "compiler/base/lexenv.cpp", + "compiler/base/literals.cpp", + "compiler/base/lreference.cpp", + "compiler/core/compileQueue.cpp", + "compiler/core/compilerContext.cpp", + "compiler/core/compilerImpl.cpp", + "compiler/core/dynamicContext.cpp", + "compiler/core/emitter.cpp", + "compiler/core/envScope.cpp", + "compiler/core/function.cpp", + "compiler/core/inlineCache.cpp", + "compiler/core/labelTarget.cpp", + "compiler/core/moduleContext.cpp", + "compiler/core/pandagen.cpp", + "compiler/core/regAllocator.cpp", + "compiler/core/regScope.cpp", + "compiler/core/switchBuilder.cpp", + "compiler/debugger/debuginfoDumper.cpp", + "compiler/function/asyncFunctionBuilder.cpp", + "compiler/function/asyncGeneratorFunctionBuilder.cpp", + "compiler/function/functionBuilder.cpp", + "compiler/function/generatorFunctionBuilder.cpp", + "ir/astDump.cpp", + "ir/base/catchClause.cpp", + "ir/base/classDefinition.cpp", + "ir/base/classProperty.cpp", + "ir/base/decorator.cpp", + "ir/base/metaProperty.cpp", + "ir/base/methodDefinition.cpp", + "ir/base/property.cpp", + "ir/base/scriptFunction.cpp", + "ir/base/spreadElement.cpp", + "ir/base/templateElement.cpp", + "ir/expression.cpp", + "ir/expressions/arrayExpression.cpp", + "ir/expressions/arrowFunctionExpression.cpp", + "ir/expressions/assignmentExpression.cpp", + "ir/expressions/awaitExpression.cpp", + "ir/expressions/binaryExpression.cpp", + "ir/expressions/callExpression.cpp", + "ir/expressions/chainExpression.cpp", + "ir/expressions/classExpression.cpp", + "ir/expressions/conditionalExpression.cpp", + "ir/expressions/functionExpression.cpp", + "ir/expressions/identifier.cpp", + "ir/expressions/importExpression.cpp", + "ir/expressions/literal.cpp", + "ir/expressions/literals/bigIntLiteral.cpp", + "ir/expressions/literals/booleanLiteral.cpp", + "ir/expressions/literals/nullLiteral.cpp", + "ir/expressions/literals/numberLiteral.cpp", + "ir/expressions/literals/regExpLiteral.cpp", + "ir/expressions/literals/stringLiteral.cpp", + "ir/expressions/literals/taggedLiteral.cpp", + "ir/expressions/memberExpression.cpp", + "ir/expressions/newExpression.cpp", + "ir/expressions/objectExpression.cpp", + "ir/expressions/omittedExpression.cpp", + "ir/expressions/sequenceExpression.cpp", + "ir/expressions/superExpression.cpp", + "ir/expressions/taggedTemplateExpression.cpp", + "ir/expressions/templateLiteral.cpp", + "ir/expressions/thisExpression.cpp", + "ir/expressions/unaryExpression.cpp", + "ir/expressions/updateExpression.cpp", + "ir/expressions/yieldExpression.cpp", + "ir/module/exportAllDeclaration.cpp", + "ir/module/exportDefaultDeclaration.cpp", + "ir/module/exportNamedDeclaration.cpp", + "ir/module/exportSpecifier.cpp", + "ir/module/importDeclaration.cpp", + "ir/module/importDefaultSpecifier.cpp", + "ir/module/importNamespaceSpecifier.cpp", + "ir/module/importSpecifier.cpp", + "ir/statement.cpp", + "ir/statements/blockStatement.cpp", + "ir/statements/breakStatement.cpp", + "ir/statements/classDeclaration.cpp", + "ir/statements/continueStatement.cpp", + "ir/statements/debuggerStatement.cpp", + "ir/statements/doWhileStatement.cpp", + "ir/statements/emptyStatement.cpp", + "ir/statements/expressionStatement.cpp", + "ir/statements/forInStatement.cpp", + "ir/statements/forOfStatement.cpp", + "ir/statements/forUpdateStatement.cpp", + "ir/statements/functionDeclaration.cpp", + "ir/statements/ifStatement.cpp", + "ir/statements/labelledStatement.cpp", + "ir/statements/loopStatement.cpp", + "ir/statements/returnStatement.cpp", + "ir/statements/switchCaseStatement.cpp", + "ir/statements/switchStatement.cpp", + "ir/statements/throwStatement.cpp", + "ir/statements/tryStatement.cpp", + "ir/statements/variableDeclaration.cpp", + "ir/statements/variableDeclarator.cpp", + "ir/statements/whileStatement.cpp", + "ir/ts/tsAnyKeyword.cpp", + "ir/ts/tsArrayType.cpp", + "ir/ts/tsAsExpression.cpp", + "ir/ts/tsBigintKeyword.cpp", + "ir/ts/tsBooleanKeyword.cpp", + "ir/ts/tsClassImplements.cpp", + "ir/ts/tsConditionalType.cpp", + "ir/ts/tsConstructorType.cpp", + "ir/ts/tsEnumDeclaration.cpp", + "ir/ts/tsEnumMember.cpp", + "ir/ts/tsExternalModuleReference.cpp", + "ir/ts/tsFunctionType.cpp", + "ir/ts/tsImportEqualsDeclaration.cpp", + "ir/ts/tsImportType.cpp", + "ir/ts/tsIndexSignature.cpp", + "ir/ts/tsIndexedAccessType.cpp", + "ir/ts/tsInferType.cpp", + "ir/ts/tsInterfaceBody.cpp", + "ir/ts/tsInterfaceDeclaration.cpp", + "ir/ts/tsInterfaceHeritage.cpp", + "ir/ts/tsIntersectionType.cpp", + "ir/ts/tsLiteralType.cpp", + "ir/ts/tsMappedType.cpp", + "ir/ts/tsMethodSignature.cpp", + "ir/ts/tsModuleBlock.cpp", + "ir/ts/tsModuleDeclaration.cpp", + "ir/ts/tsNamedTupleMember.cpp", + "ir/ts/tsNeverKeyword.cpp", + "ir/ts/tsNonNullExpression.cpp", + "ir/ts/tsNullKeyword.cpp", + "ir/ts/tsNumberKeyword.cpp", + "ir/ts/tsObjectKeyword.cpp", + "ir/ts/tsParameterProperty.cpp", + "ir/ts/tsParenthesizedType.cpp", + "ir/ts/tsPrivateIdentifier.cpp", + "ir/ts/tsPropertySignature.cpp", + "ir/ts/tsQualifiedName.cpp", + "ir/ts/tsSignatureDeclaration.cpp", + "ir/ts/tsStringKeyword.cpp", + "ir/ts/tsThisType.cpp", + "ir/ts/tsTupleType.cpp", + "ir/ts/tsTypeAliasDeclaration.cpp", + "ir/ts/tsTypeAssertion.cpp", + "ir/ts/tsTypeLiteral.cpp", + "ir/ts/tsTypeOperator.cpp", + "ir/ts/tsTypeParameter.cpp", + "ir/ts/tsTypeParameterDeclaration.cpp", + "ir/ts/tsTypeParameterInstantiation.cpp", + "ir/ts/tsTypePredicate.cpp", + "ir/ts/tsTypeQuery.cpp", + "ir/ts/tsTypeReference.cpp", + "ir/ts/tsUndefinedKeyword.cpp", + "ir/ts/tsUnionType.cpp", + "ir/ts/tsUnknownKeyword.cpp", + "ir/ts/tsVoidKeyword.cpp", + "lexer/keywordsUtil.cpp", + "lexer/lexer.cpp", + "lexer/regexp/regexp.cpp", + "lexer/token/sourceLocation.cpp", + "lexer/token/token.cpp", + "parser/context/parserContext.cpp", + "parser/expressionParser.cpp", + "parser/parserImpl.cpp", + "parser/program/program.cpp", + "parser/statementParser.cpp", + "typescript/checker.cpp", + "typescript/core/binaryLikeExpression.cpp", + "typescript/core/destructuring.cpp", + "typescript/core/function.cpp", + "typescript/core/generics.cpp", + "typescript/core/helpers.cpp", + "typescript/core/object.cpp", + "typescript/core/typeCreation.cpp", + "typescript/core/typeElaboration.cpp", + "typescript/core/typeRelation.cpp", + "typescript/core/util.cpp", + "typescript/types/anyType.cpp", + "typescript/types/arrayType.cpp", + "typescript/types/bigintLiteralType.cpp", + "typescript/types/bigintType.cpp", + "typescript/types/booleanLiteralType.cpp", + "typescript/types/booleanType.cpp", + "typescript/types/constructorType.cpp", + "typescript/types/enumLiteralType.cpp", + "typescript/types/enumType.cpp", + "typescript/types/functionType.cpp", + "typescript/types/globalTypesHolder.cpp", + "typescript/types/indexInfo.cpp", + "typescript/types/interfaceType.cpp", + "typescript/types/neverType.cpp", + "typescript/types/nonPrimitiveType.cpp", + "typescript/types/nullType.cpp", + "typescript/types/numberLiteralType.cpp", + "typescript/types/numberType.cpp", + "typescript/types/objectDescriptor.cpp", + "typescript/types/objectLiteralType.cpp", + "typescript/types/objectType.cpp", + "typescript/types/signature.cpp", + "typescript/types/stringLiteralType.cpp", + "typescript/types/stringType.cpp", + "typescript/types/tupleType.cpp", + "typescript/types/type.cpp", + "typescript/types/typeParameter.cpp", + "typescript/types/typeReference.cpp", + "typescript/types/typeRelation.cpp", + "typescript/types/undefinedType.cpp", + "typescript/types/unionType.cpp", + "typescript/types/unknownType.cpp", + "typescript/types/voidType.cpp", + "util/bitset.cpp", + "util/helpers.cpp", + "util/ustring.cpp", +] + +config("es2abc_config_src") { + include_dirs = [ + "./", + "./binder", + "./util", + "./compiler/base", + "./compiler/core", + "./compiler/debugger", + "./compiler/function", + "./ir", + "./ir/base", + "./ir/expressions", + "./ir/module", + "./ir/statements", + "./ir/ts", + "./parser", + "./parser/context", + "./lexer", + "./lexer/token", + "./lexer/regexp", + "./typescript", + "./typescript/types", + ] + + cflags = [ "-fexceptions" ] +} + +config("es2abc_config_common") { + configs = [ + "$ark_root:ark_config", + "$sdk_libc_secshared_config", + "$ark_root/libpandafile:arkfile_public_config", + "$ark_root/libpandabase:arkbase_public_config", + "$ark_root/runtime:arkruntime_public_config", + "$ark_root/assembler:arkassembler_public_config", + ":es2abc_config_src", + ] + + if (enable_bytecode_optimizer) { + defines = [ "ENABLE_BYTECODE_OPT" ] + configs += [ + "$ark_root/compiler:arkcompiler_public_config", + "$ark_root/bytecode_optimizer:bytecodeopt_public_config", + ] + } +} + +# generate headers for es2panda parser +generated_header_dir = "${target_out_dir}/gen" +action_foreach("gen_keywords_headers") { + template_files = [ + "keywords.h.erb", + "keywordsMap.h.erb", + ] + keywords_templates_dir = "./lexer/templates" + keywords_generator = "./lexer/scripts/keywords.rb" + + sources = [] + foreach(file, template_files) { + sources += [ rebase_path("${keywords_templates_dir}/${file}") ] + } + outputs = [ "${generated_header_dir}/{{source_name_part}}" ] + + script = "scripts/gen_keywords.sh" + inputs = [ "${keywords_generator}" ] + args = [ + "-g", + rebase_path("${keywords_generator}"), + "-t", + "{{source}}", + "-o", + "{{source_name_part}}", + "-d", + rebase_path("${generated_header_dir}"), + ] +} + +# generate headers for es2panda compiler +isa_gen = "${ark_root}/isa/gen.rb" +isa_gen_data = "$root_gen_dir/isa/isa.yaml" +isa_gen_require = "${ark_root}/isa/isapi.rb" +action_foreach("gen_isa_headers") { + deps = [ "//arkcompiler/runtime_core/isa:isa_combine" ] + + template_files = [ + "isa.h.erb", + "formats.h.erb", + ] + keywords_templates_dir = "./compiler/templates" + + sources = [] + foreach(file, template_files) { + sources += [ rebase_path("${keywords_templates_dir}/${file}") ] + } + outputs = [ "${generated_header_dir}/{{source_name_part}}" ] + + script = "scripts/gen_isa.sh" + inputs = [ + "${isa_gen}", + "${isa_gen_data}", + "${isa_gen_require}", + ] + args = [ + "-g", + rebase_path("${isa_gen}"), + "-t", + "{{source}}", + "-a", + rebase_path("${isa_gen_data}"), + "-o", + "{{source_name_part}}", + "-d", + rebase_path("${generated_header_dir}"), + "-r", + rebase_path("${isa_gen_require}"), + ] +} + +ohos_static_library("es2panda_lib") { + sources = es2panda_src + use_exceptions = true + + configs = [ ":es2abc_config_common" ] + + include_dirs = [ + "${target_out_dir}", + "//third_party/icu/icu4c/source/common", + "//third_party/icu/icu4c/source/i18n", + "//third_party/icu/icu4c/source ", + ] + + deps = [ + ":gen_isa_headers", + ":gen_keywords_headers", + "$ark_root/assembler:libarkassembler_frontend_static", + "$ark_root/libpandabase:libarkbase_frontend_static", + "$ark_root/libpandafile:libarkfile_frontend_static", + "$ark_root/libziparchive:libarkziparchive_frontend_static", + "//third_party/icu/icu4c:static_icuuc", + ] + + cflags = [ "-Wno-implicit-fallthrough" ] +} + +ohos_executable("es2panda") { + use_exceptions = true + sources = [ + "aot/main.cpp", + "aot/options.cpp", + ] + + include_dirs = [ "./aot" ] + + configs = [ ":es2abc_config_common" ] + + deps = [ ":es2panda_lib" ] + + if (is_linux) { + if (build_public_version) { + ldflags = [ "-static-libstdc++" ] + } else { + libs = [ libcpp_static_lib ] + } + } + + if (enable_bytecode_optimizer) { + deps += [ + "$ark_root/bytecode_optimizer:libarkbytecodeopt_frontend_static", + "$ark_root/compiler:libarkcompiler_frontend_static", + ] + } + + output_name = "es2abc" + install_enable = true + subsystem_name = "ark" +} + +if (is_linux) { + ohos_copy("es2abc_build") { + deps = [ ":es2panda" ] + sources = [ "${root_out_dir}/ark/ark/es2abc" ] + outputs = [ "${target_out_dir}/es2abc-tmp" ] + module_source_dir = "${root_out_dir}/ark/ark" + module_install_name = "es2abc" + } + + ohos_copy("es2abc_build_ets") { + deps = [ ":es2panda" ] + sources = [ "${root_out_dir}/ark/ark/es2abc" ] + outputs = [ "${root_out_dir}/ark/ark/es2abc-ets" ] + module_source_dir = "${root_out_dir}/ark/ark" + module_install_name = "es2abc" + } +} + +if (is_mingw) { + ohos_copy("es2abc_build_win") { + deps = [ ":es2panda" ] + sources = [ "${root_out_dir}/ark/ark/es2abc.exe" ] + outputs = [ "${target_out_dir}/es2abc-tmp" ] + module_source_dir = "${root_out_dir}/ark/ark" + module_install_name = "es2abc.exe" + } + + ohos_copy("es2abc_build_win_ets") { + deps = [ ":es2panda" ] + sources = [ "${root_out_dir}/ark/ark/es2abc.exe" ] + outputs = [ "${root_out_dir}/ark/ark/es2abc-win-ets" ] + module_source_dir = "${root_out_dir}/ark/ark" + module_install_name = "es2abc.exe" + } +} + +if (is_mac) { + ohos_copy("es2abc_build_mac") { + deps = [ ":es2panda" ] + sources = [ "${root_out_dir}/ark/ark/es2abc" ] + outputs = [ "${target_out_dir}/es2abc-tmp" ] + module_source_dir = "${root_out_dir}/ark/ark" + module_install_name = "es2abc" + } + + ohos_copy("es2abc_build_mac_ets") { + deps = [ ":es2panda" ] + sources = [ "${root_out_dir}/ark/ark/es2abc" ] + outputs = [ "${root_out_dir}/ark/ark/es2abc-mac-ets" ] + module_source_dir = "${root_out_dir}/ark/ark" + module_install_name = "es2abc" + } +} + +group("es2panda_build") { + if (host_os == "linux") { + deps = [ ":es2panda(${toolchain_linux})" ] + } + + if (host_os == "mac") { + deps = [ ":es2panda(${toolchain_mac})" ] + } +} + +group("es2panda_build_win") { + deps = [ ":es2panda(${toolchain_win})" ] +} diff --git a/es2panda/aot/main.cpp b/es2panda/aot/main.cpp index 8dbd680977fa6e901ca1e41d7f6dbc8235458125..79c5131dec17642a0799feb1dc1c771c6999f135 100644 --- a/es2panda/aot/main.cpp +++ b/es2panda/aot/main.cpp @@ -14,12 +14,18 @@ */ #include +#ifdef ENABLE_BYTECODE_OPT #include #include +#else +#include +#include +#include +#endif #include #include #include -#include +#include #include #include @@ -124,8 +130,8 @@ int Run(int argc, const char **argv) return 0; } - std::cout << err.TypeString() << ": " << err.Message(); - std::cout << " [" << options->SourceFile() << ":" << err.Line() << ":" << err.Col() << "]" << std::endl; + std::cerr << err.TypeString() << ": " << err.Message(); + std::cerr << " [" << options->SourceFile() << ":" << err.Line() << ":" << err.Col() << "]" << std::endl; return err.ErrorCode(); } diff --git a/es2panda/aot/options.cpp b/es2panda/aot/options.cpp index 9be3f001c5b1f2f8a6c5e7e5cd796649fe38f70d..9f72eac598d446a9f0b38324db70539060e0ed72 100644 --- a/es2panda/aot/options.cpp +++ b/es2panda/aot/options.cpp @@ -18,6 +18,7 @@ #include #include +#include namespace panda::es2panda::aot { diff --git a/es2panda/aot/options.h b/es2panda/aot/options.h index af8c8e3093a40394bd8679a28407a28d4dd16708..9b681e7f11c393c02d38bcb12ad22715e34947db 100644 --- a/es2panda/aot/options.h +++ b/es2panda/aot/options.h @@ -17,7 +17,7 @@ #define ES2PANDA_AOT_OPTIONS_H #include -#include +#include #include #include diff --git a/es2panda/binder/binder.cpp b/es2panda/binder/binder.cpp index d2a8b2ad397c8be9b3a5a17ca306bd6354d2d199..09b100fa66261288b8e02b52809086eb1be1e780 100644 --- a/es2panda/binder/binder.cpp +++ b/es2panda/binder/binder.cpp @@ -80,7 +80,7 @@ void Binder::IdentifierAnalysis() ASSERT(program_->Ast()); ASSERT(scope_ == topScope_); - BuildFunction(topScope_, "main"); + BuildFunction(topScope_, MAIN_FUNC_NAME); ResolveReferences(program_->Ast()); AddMandatoryParams(); } @@ -151,7 +151,7 @@ void Binder::LookupIdentReference(ir::Identifier *ident) return; } - if (res.variable->Declaration()->IsLetOrConstDecl() && !res.variable->HasFlag(VariableFlags::INITIALIZED)) { + if (res.variable->Declaration()->IsLetOrConstOrClassDecl() && !res.variable->HasFlag(VariableFlags::INITIALIZED)) { ident->SetTdz(); } @@ -160,13 +160,22 @@ void Binder::LookupIdentReference(ir::Identifier *ident) void Binder::BuildFunction(FunctionScope *funcScope, util::StringView name) { - uint32_t idx = functionScopes_.size(); functionScopes_.push_back(funcScope); + bool funcNameWithoutDot = (name.Find(".") == std::string::npos); + bool funcNameWithoutBackslash = (name.Find("\\") == std::string::npos); + if (name != ANONYMOUS_FUNC_NAME && funcNameWithoutDot && funcNameWithoutBackslash && !functionNames_.count(name)) { + functionNames_.insert(name); + funcScope->BindName(name, name); + return; + } std::stringstream ss; - ss << "func_" << name << "_" << std::to_string(idx); + uint32_t idx = functionNameIndex_++; + ss << "#" << std::to_string(idx) << "#"; + if (funcNameWithoutDot && funcNameWithoutBackslash) { + ss << name; + } util::UString internalName(ss.str(), Allocator()); - funcScope->BindName(name, internalName.View()); } @@ -245,7 +254,7 @@ void Binder::BuildClassDefinition(ir::ClassDefinition *classDef) if (classDef->Parent()->IsClassDeclaration()) { ScopeFindResult res = scope_->Find(classDef->Ident()->Name()); - ASSERT(res.variable && res.variable->Declaration()->IsLetDecl()); + ASSERT(res.variable && res.variable->Declaration()->IsClassDecl()); res.variable->AddFlag(VariableFlags::INITIALIZED); } diff --git a/es2panda/binder/binder.h b/es2panda/binder/binder.h index 28f4b038d2ecfe000b020cd6552496d5d681d9d0..90f06aebf7b561d4a2e79950e73bcbfce5f8c20d 100644 --- a/es2panda/binder/binder.h +++ b/es2panda/binder/binder.h @@ -41,7 +41,12 @@ class VariableScope; class Binder { public: - explicit Binder(parser::Program *program) : program_(program), functionScopes_(Allocator()->Adapter()) {} + explicit Binder(parser::Program *program) + : program_(program), + functionScopes_(Allocator()->Adapter()), + functionNames_(Allocator()->Adapter()) + { + } NO_COPY_SEMANTIC(Binder); DEFAULT_MOVE_SEMANTIC(Binder); ~Binder() = default; @@ -104,6 +109,9 @@ public: 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 MAIN_FUNC_NAME = "func_main_0"; + static constexpr std::string_view ANONYMOUS_FUNC_NAME = ""; + private: using MandatoryParams = std::array; @@ -138,6 +146,8 @@ private: GlobalScope *topScope_ {}; Scope *scope_ {}; ArenaVector functionScopes_; + ArenaSet functionNames_; + size_t functionNameIndex_ {1}; }; template diff --git a/es2panda/binder/declaration.h b/es2panda/binder/declaration.h index ab65a7579ac6db9768e837f80d82e57f8cbcdd62..1e83a306e81acefd442f5954be7f244a77dd040d 100644 --- a/es2panda/binder/declaration.h +++ b/es2panda/binder/declaration.h @@ -77,9 +77,9 @@ public: node_ = node; } - bool IsLetOrConstDecl() const + bool IsLetOrConstOrClassDecl() const { - return IsLetDecl() || IsConstDecl(); + return IsLetDecl() || IsConstDecl() || IsClassDecl(); } protected: @@ -234,6 +234,16 @@ public: } }; +class ClassDecl : public Decl { +public: + explicit ClassDecl(util::StringView name) : Decl(name) {} + + DeclType Type() const override + { + return DeclType::CLASS; + } +}; + class ParameterDecl : public Decl { public: explicit ParameterDecl(util::StringView name) : Decl(name) {} diff --git a/es2panda/binder/scope.cpp b/es2panda/binder/scope.cpp index 402bdd7a0c77989d8eb0451300936e38afe78d8d..90a0c64cebba9176b51b860c6c8087244d6c0068 100644 --- a/es2panda/binder/scope.cpp +++ b/es2panda/binder/scope.cpp @@ -49,6 +49,20 @@ VariableScope *Scope::EnclosingVariableScope() return nullptr; } +FunctionScope *Scope::EnclosingFunctionVariableScope() +{ + Scope *iter = this; + while (iter) { + if (iter->IsFunctionVariableScope()) { + return iter->AsFunctionVariableScope(); + } + + iter = iter->Parent(); + } + + return nullptr; +} + Variable *Scope::FindLocal(const util::StringView &name, ResolveBindingOptions options) const { if (options & ResolveBindingOptions::INTERFACES) { @@ -78,6 +92,23 @@ ScopeFindResult Scope::Find(const util::StringView &name, ResolveBindingOptions uint32_t lexLevel = 0; const auto *iter = this; + if (iter->IsFunctionParamScope()) { + Variable *v = iter->FindLocal(name, options); + + if (v != nullptr) { + return {name, const_cast(iter), level, lexLevel, v}; + } + + level++; + auto *funcVariableScope = iter->AsFunctionParamScope()->GetFunctionScope(); + + if (funcVariableScope->NeedLexEnv()) { + lexLevel++; + } + + iter = iter->Parent(); + } + while (iter != nullptr) { Variable *v = iter->FindLocal(name, options); @@ -444,7 +475,7 @@ void LoopDeclarationScope::ConvertToVariableScope(ArenaAllocator *allocator) } for (auto &[name, var] : bindings_) { - if (!var->LexicalBound() || !var->Declaration()->IsLetOrConstDecl()) { + if (!var->LexicalBound() || !var->Declaration()->IsLetOrConstOrClassDecl()) { continue; } diff --git a/es2panda/binder/scope.h b/es2panda/binder/scope.h index 9621858f36bc2b887ed1fcbdbfc61b26cdb6b729..0dfda446f97fd19617d51a7fbdc27babaa2843d1 100644 --- a/es2panda/binder/scope.h +++ b/es2panda/binder/scope.h @@ -121,6 +121,8 @@ public: VariableScope *EnclosingVariableScope(); + FunctionScope *EnclosingFunctionVariableScope(); + const ArenaVector &Decls() const { return decls_; @@ -314,6 +316,17 @@ public: return params_; } + bool HasParam(util::StringView name) const + { + for (auto *param : params_) { + if (param->Name() == name) { + return true; + } + } + + return false; + } + std::tuple AddParamDecl(ArenaAllocator *allocator, const ir::AstNode *param); protected: diff --git a/es2panda/binder/variableFlags.h b/es2panda/binder/variableFlags.h index dee8b1475741544e27355e61683873cafe375fb3..3a7f3a713898e34bc994833a0da56a1e1cd1c2e9 100644 --- a/es2panda/binder/variableFlags.h +++ b/es2panda/binder/variableFlags.h @@ -24,6 +24,7 @@ namespace panda::es2panda::binder { _(VAR, VarDecl) \ _(LET, LetDecl) \ _(CONST, ConstDecl) \ + _(CLASS, ClassDecl) \ _(FUNC, FunctionDecl) \ _(PARAM, ParameterDecl) \ _(IMPORT, ImportDecl) \ diff --git a/es2panda/compiler/base/condition.cpp b/es2panda/compiler/base/condition.cpp index 644e9195fecef0aaa030ac05f26f19ebe9c77636..577d8c63e49a2a67b455939e124e1c9b00346dde 100644 --- a/es2panda/compiler/base/condition.cpp +++ b/es2panda/compiler/base/condition.cpp @@ -51,11 +51,9 @@ void Condition::Compile(PandaGen *pg, const ir::Expression *expr, Label *falseLa } case lexer::TokenType::PUNCTUATOR_LOGICAL_AND: { binExpr->Left()->Compile(pg); - pg->ToBoolean(binExpr); pg->BranchIfFalse(binExpr, falseLabel); binExpr->Right()->Compile(pg); - pg->ToBoolean(binExpr); pg->BranchIfFalse(binExpr, falseLabel); return; } @@ -63,11 +61,9 @@ void Condition::Compile(PandaGen *pg, const ir::Expression *expr, Label *falseLa auto *endLabel = pg->AllocLabel(); binExpr->Left()->Compile(pg); - pg->ToBoolean(binExpr); pg->BranchIfTrue(binExpr, endLabel); binExpr->Right()->Compile(pg); - pg->ToBoolean(binExpr); pg->BranchIfFalse(binExpr, falseLabel); pg->SetLabel(binExpr, endLabel); return; @@ -87,7 +83,6 @@ void Condition::Compile(PandaGen *pg, const ir::Expression *expr, Label *falseLa // General case including some binExpr i.E.(a+b) expr->Compile(pg); - pg->ToBoolean(expr); pg->BranchIfFalse(expr, falseLabel); } diff --git a/es2panda/compiler/base/destructuring.cpp b/es2panda/compiler/base/destructuring.cpp index 7ff756529f3b4f1b528f3245a35b19636af46963..70d9ef0754d749ed9ca0aee4dbe9c1fd9857bf7c 100644 --- a/es2panda/compiler/base/destructuring.cpp +++ b/es2panda/compiler/base/destructuring.cpp @@ -71,7 +71,6 @@ static void GenRestElement(PandaGen *pg, const ir::SpreadElement *restElement, static void GenArray(PandaGen *pg, const ir::ArrayExpression *array) { - // RegScope rs(pg); DestructuringIterator iterator(pg, array); if (array->Elements().empty()) { @@ -223,9 +222,15 @@ static void GenObject(PandaGen *pg, const ir::ObjectExpression *object, VReg rhs if (properties.empty() || properties.back()->IsRestElement()) { auto *notNullish = pg->AllocLabel(); + auto *nullish = pg->AllocLabel(); - pg->LoadAccumulator(object, rhs); - pg->BranchIfCoercible(object, notNullish); + pg->LoadConst(object, Constant::JS_NULL); + pg->Condition(object, lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL, rhs, nullish); + pg->LoadConst(object, Constant::JS_UNDEFINED); + pg->Condition(object, lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL, rhs, nullish); + pg->Branch(object, notNullish); + + pg->SetLabel(object, nullish); pg->ThrowObjectNonCoercible(object); pg->SetLabel(object, notNullish); diff --git a/es2panda/compiler/base/hoisting.cpp b/es2panda/compiler/base/hoisting.cpp index 07621e8d630c5793019c81bf2641fc2da9f5b9e2..815bf147a86f6909f90fd4781086b0773e07651c 100644 --- a/es2panda/compiler/base/hoisting.cpp +++ b/es2panda/compiler/base/hoisting.cpp @@ -31,6 +31,11 @@ static void HoistVar(PandaGen *pg, binder::Variable *var, const binder::VarDecl return; } + auto *funcScope = scope->EnclosingFunctionVariableScope(); + if (funcScope->ParamScope()->HasParam(decl->Name())) { + return; + } + binder::ScopeFindResult result(decl->Name(), scope, 0, var); pg->LoadConst(decl->Node(), Constant::JS_UNDEFINED); diff --git a/es2panda/compiler/base/iterators.cpp b/es2panda/compiler/base/iterators.cpp index 1bf7ad888797b1fb5f2c829aab527b4979a09c8a..47d653b8ee8b1aa983ecb5b73cb67f91726c5ee0 100644 --- a/es2panda/compiler/base/iterators.cpp +++ b/es2panda/compiler/base/iterators.cpp @@ -35,13 +35,11 @@ Iterator::Iterator(PandaGen *pg, const ir::AstNode *node, IteratorType type) pg_->StoreAccumulator(node, iterator_); pg_->LoadObjByName(node_, iterator_, "next"); pg_->StoreAccumulator(node_, method_); - - pg_->ThrowIfNotObject(node_); } void Iterator::GetMethod(util::StringView name) const { - pg_->GetMethod(node_, iterator_, name); + pg_->LoadObjByName(node_, iterator_, name); pg_->StoreAccumulator(node_, method_); } @@ -63,14 +61,13 @@ void Iterator::Next() const pg_->FuncBuilder()->Await(node_); } - pg_->ThrowIfNotObject(node_); pg_->StoreAccumulator(node_, nextResult_); + pg_->ThrowIfNotObject(node_, nextResult_); } void Iterator::Complete() const { pg_->LoadObjByName(node_, nextResult_, "done"); - pg_->ToBoolean(node_); } void Iterator::Value() const @@ -81,10 +78,34 @@ void Iterator::Value() const void Iterator::Close(bool abruptCompletion) const { if (type_ == IteratorType::SYNC) { - if (!abruptCompletion) { - pg_->LoadConst(node_, Constant::JS_HOLE); + RegScope rs(pg_); + VReg exception = pg_->AllocReg(); + VReg doneResult = pg_->AllocReg(); + VReg innerResult = pg_->AllocReg(); + Label *noReturn = pg_->AllocLabel(); + + if (abruptCompletion) { + pg_->StoreAccumulator(node_, exception); + } + + pg_->StoreConst(node_, doneResult, Constant::JS_TRUE); + Complete(); + pg_->Condition(node_, lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL, doneResult, noReturn); + + // close iterator + pg_->LoadObjByName(node_, iterator_, "return"); + pg_->StoreAccumulator(node_, method_); + pg_->LoadConst(node_, Constant::JS_UNDEFINED); + pg_->Condition(node_, lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL, method_, noReturn); + CallMethod(); + pg_->StoreAccumulator(node_, innerResult); + pg_->ThrowIfNotObject(node_, innerResult); + + pg_->SetLabel(node_, noReturn); + if (abruptCompletion) { + pg_->LoadAccumulator(node_, exception); + pg_->EmitThrow(node_); } - pg_->CloseIterator(node_, iterator_); return; } @@ -160,7 +181,7 @@ void Iterator::Close(bool abruptCompletion) const // 8. If Type(innerResult.[[Value]]) is not Object, throw a TypeError exception. pg_->LoadAccumulator(node_, innerResult); - pg_->ThrowIfNotObject(node_); + pg_->ThrowIfNotObject(node_, innerResult); } DestructuringIterator::DestructuringIterator(PandaGen *pg, const ir::AstNode *node) diff --git a/es2panda/compiler/base/lexenv.cpp b/es2panda/compiler/base/lexenv.cpp index f3410f06c2ff81e8e0a5a098f5909111720f2970..0ca34ca25e0c11190c76de901f020355f8c9171b 100644 --- a/es2panda/compiler/base/lexenv.cpp +++ b/es2panda/compiler/base/lexenv.cpp @@ -91,7 +91,7 @@ static void ExpandStoreLexVar(PandaGen *pg, const ir::AstNode *node, const binde const auto *decl = result.variable->Declaration(); - if (decl->IsLetOrConstDecl() && !isDecl) { + if (decl->IsLetOrConstOrClassDecl() && !isDecl) { RegScope rs(pg); VReg valueReg = pg->AllocReg(); diff --git a/es2panda/compiler/core/emitter.cpp b/es2panda/compiler/core/emitter.cpp index 6e617cb41f196d3b1ae3fdc361eed462f28af155..d807dfc245ccf255b4f0f56033d7dcabe7c39912 100644 --- a/es2panda/compiler/core/emitter.cpp +++ b/es2panda/compiler/core/emitter.cpp @@ -75,7 +75,8 @@ void FunctionEmitter::GenBufferLiterals(const LiteralBuffer *buff) { auto &[idx, array] = literalBuffers_.emplace_back(); idx = buff->Index(); - array.reserve(buff->Literals().size() * 2); + constexpr size_t ARRAY_EXPANSION = 2; + array.reserve(buff->Literals().size() * ARRAY_EXPANSION); for (const auto *literal : buff->Literals()) { panda::pandasm::LiteralArray::Literal valueLit; @@ -114,16 +115,17 @@ void FunctionEmitter::GenBufferLiterals(const LiteralBuffer *buff) valueLit.value_ = literal->GetMethod().Mutf8(); break; } - case ir::LiteralTag::GENERATOR_METHOD: { - valueLit.tag_ = panda::panda_file::LiteralTag::GENERATORMETHOD; - valueLit.value_ = literal->GetMethod().Mutf8(); + case ir::LiteralTag::METHODAFFILIATE: { + valueLit.tag_ = panda::panda_file::LiteralTag::METHODAFFILIATE; + valueLit.value_ = literal->GetMethodAffiliate(); break; } - case ir::LiteralTag::ASYNC_GENERATOR_METHOD: { - valueLit.tag_ = panda::panda_file::LiteralTag::ASYNCGENERATORMETHOD; + case ir::LiteralTag::GENERATOR_METHOD: { + valueLit.tag_ = panda::panda_file::LiteralTag::GENERATORMETHOD; valueLit.value_ = literal->GetMethod().Mutf8(); break; } + // TODO: support ir::LiteralTag::ASYNC_GENERATOR_METHOD case ir::LiteralTag::NULL_VALUE: { valueLit.tag_ = panda::panda_file::LiteralTag::NULLVALUE; valueLit.value_ = static_cast(0); @@ -181,16 +183,17 @@ static size_t GetIRNodeWholeLength(const IRNode *node) } size_t len = 1; + constexpr size_t BIT_WIDTH = 8; const auto format = MatchFormat(node, formats); for (auto fi : format.GetFormatItem()) { - len += fi.Bitwidth() / 8; + len += fi.Bitwidth() / BIT_WIDTH; } return len; } -static std::string WholeLine(const util::StringView &source, lexer::SourceRange range) +[[maybe_unused]] static std::string WholeLine(const util::StringView &source, lexer::SourceRange range) { return source.Substr(range.start.index, range.end.index).EscapeSymbol(); } @@ -208,7 +211,7 @@ void FunctionEmitter::GenInstructionDebugInfo(const IRNode *ins, panda::pandasm: } } - pandaIns->ins_debug.line_number = astNode->Range().start.line + 1; + pandaIns->ins_debug.line_number = astNode->Range().start.line; if (pg_->IsDebug()) { size_t insLen = GetIRNodeWholeLength(ins); @@ -218,7 +221,8 @@ void FunctionEmitter::GenInstructionDebugInfo(const IRNode *ins, panda::pandasm: } offset_ += insLen; - pandaIns->ins_debug.whole_line = WholeLine(SourceCode(), astNode->Range()); + + pandaIns->ins_debug.column_number = astNode->Range().start.index; } } diff --git a/es2panda/compiler/core/envScope.cpp b/es2panda/compiler/core/envScope.cpp index 6e2fa13c78c7038bb1a0d4e2a0eb7405af141868..93fa239666a9f0cab650072dbb4b6ac52c1c080e 100644 --- a/es2panda/compiler/core/envScope.cpp +++ b/es2panda/compiler/core/envScope.cpp @@ -77,8 +77,23 @@ void LoopEnvScope::CopyPetIterationCtx() return; } - pg_->CopyLexEnv(scope_->Node()); + auto num = scope_->LexicalSlots(); + RegScope rs(pg_); + std::vector lexicals; + lexicals.reserve(num); + for (uint32_t i = 0; i < num; i++) { + VReg lexical = pg_->AllocReg(); + pg_->LoadLexicalVar(scope_->Node(), 0, i); + pg_->StoreAccumulator(scope_->Node(), lexical); + lexicals.push_back(lexical); + } + pg_->PopLexEnv(scope_->Node()); + pg_->NewLexEnv(scope_->Node(), num); pg_->StoreAccumulator(scope_->Node(), lexEnv_); + + for (uint32_t i = 0; i < num; i++) { + pg_->StoreLexicalVar(scope_->Node(), 0, i, lexicals[i]); + } } } // namespace panda::es2panda::compiler diff --git a/es2panda/compiler/core/pandagen.cpp b/es2panda/compiler/core/pandagen.cpp index 7d58fa71c45b4622695a76884a4c7035854e2eac..82b4eea600673eab4ce0d97325643bdaa76b79db 100644 --- a/es2panda/compiler/core/pandagen.cpp +++ b/es2panda/compiler/core/pandagen.cpp @@ -31,8 +31,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -162,8 +164,7 @@ void PandaGen::CopyFunctionArguments(const ir::AstNode *node) for (const auto *param : topScope_->ParamScope()->Params()) { if (param->LexicalBound()) { - LoadAccumulator(node, targetReg++); - StoreLexicalVar(node, 0, param->LexIdx()); + StoreLexicalVar(node, 0, param->LexIdx(), targetReg++); } else { ra_.Emit(node, param->Vreg(), targetReg++); } @@ -222,6 +223,12 @@ void PandaGen::LoadVar(const ir::Identifier *node, const binder::ScopeFindResult } ASSERT(var->IsLocalVariable()); + + if (var->Declaration()->IsLetOrConstOrClassDecl() && result.scope->IsGlobalScope()) { + TryLoadGlobalByName(node, result.name); + return; + } + LoadAccFromLexEnv(node, result); } @@ -245,6 +252,20 @@ void PandaGen::StoreVar(const ir::AstNode *node, const binder::ScopeFindResult & } ASSERT(var->IsLocalVariable()); + + if (var->Declaration()->IsLetOrConstOrClassDecl() && result.scope->IsGlobalScope()) { + if (!isDeclaration) { + TryStoreGlobalByName(node, var->Name()); + } else if (var->Declaration()->IsLetDecl()) { + StLetToGlobalRecord(node, var->Name()); + } else if (var->Declaration()->IsConstDecl()) { + StConstToGlobalRecord(node, var->Name()); + } else if (var->Declaration()->IsClassDecl()) { + StClassToGlobalRecord(node, var->Name()); + } + return; + } + StoreAccToLexEnv(node, result, isDeclaration); } @@ -300,10 +321,10 @@ void PandaGen::StoreObjProperty(const ir::AstNode *node, VReg obj, const Operand StoreObjByName(node, obj, std::get(prop)); } -void PandaGen::StoreOwnProperty(const ir::AstNode *node, VReg obj, const Operand &prop) +void PandaGen::StoreOwnProperty(const ir::AstNode *node, VReg obj, const Operand &prop, bool nameSetting) { if (std::holds_alternative(prop)) { - StOwnByValue(node, obj, std::get(prop)); + StOwnByValue(node, obj, std::get(prop), nameSetting); return; } @@ -313,7 +334,7 @@ void PandaGen::StoreOwnProperty(const ir::AstNode *node, VReg obj, const Operand } ASSERT(std::holds_alternative(prop)); - StOwnByName(node, obj, std::get(prop)); + StOwnByName(node, obj, std::get(prop), nameSetting); } void PandaGen::TryLoadGlobalByName(const ir::AstNode *node, const util::StringView &name) @@ -360,20 +381,22 @@ void PandaGen::StoreObjByIndex(const ir::AstNode *node, VReg obj, int64_t index) ra_.Emit(node, index, obj); } -void PandaGen::StOwnByName(const ir::AstNode *node, VReg obj, const util::StringView &prop) +void PandaGen::StOwnByName(const ir::AstNode *node, VReg obj, const util::StringView &prop, bool nameSetting) { - ra_.Emit(node, prop, obj); + nameSetting ? ra_.Emit(node, prop, obj) : + ra_.Emit(node, prop, obj); strings_.insert(prop); } -void PandaGen::StOwnByValue(const ir::AstNode *node, VReg obj, VReg prop) +void PandaGen::StOwnByValue(const ir::AstNode *node, VReg obj, VReg prop, bool nameSetting) { - ra_.Emit(node, obj, prop); + nameSetting ? ra_.Emit(node, obj, prop) : + ra_.Emit(node, obj, prop); } void PandaGen::StOwnByIndex(const ir::AstNode *node, VReg obj, int64_t index) { - ra_.Emit(node, index, obj); + ra_.Emit(node, obj, index); } void PandaGen::DeleteObjProperty(const ir::AstNode *node, VReg obj, const Operand &prop) @@ -415,7 +438,7 @@ void PandaGen::StoreGlobalVar(const ir::AstNode *node, const util::StringView &n void PandaGen::StoreGlobalLet(const ir::AstNode *node, const util::StringView &name) { - sa_.Emit(node, name); + sa_.Emit(node, name); strings_.insert(name); } @@ -455,6 +478,12 @@ void PandaGen::LoadAccumulatorInt(const ir::AstNode *node, size_t num) sa_.Emit(node, static_cast(num)); } +void PandaGen::LoadAccumulatorBigInt(const ir::AstNode *node, const util::StringView &num) +{ + sa_.Emit(node, num); + strings_.insert(num); +} + void PandaGen::StoreConst(const ir::AstNode *node, VReg reg, Constant id) { LoadConst(node, id); @@ -646,7 +675,7 @@ void PandaGen::Unary(const ir::AstNode *node, lexer::TokenType op, VReg operand) break; } case lexer::TokenType::PUNCTUATOR_EXCLAMATION_MARK: { - sa_.Emit(node); + Negate(node); break; } case lexer::TokenType::PUNCTUATOR_PLUS_PLUS: { @@ -784,19 +813,38 @@ void PandaGen::Binary(const ir::AstNode *node, lexer::TokenType op, VReg lhs) void PandaGen::BranchIfUndefined(const ir::AstNode *node, Label *target) { - sa_.Emit(node); - BranchIfTrue(node, target); + RegScope rs(this); + VReg tmp = AllocReg(); + StoreAccumulator(node, tmp); + sa_.Emit(node); + ra_.Emit(node, tmp); + sa_.Emit(node, target); } void PandaGen::BranchIfNotUndefined(const ir::AstNode *node, Label *target) { - sa_.Emit(node); - BranchIfFalse(node, target); + RegScope rs(this); + VReg tmp = AllocReg(); + StoreAccumulator(node, tmp); + sa_.Emit(node); + ra_.Emit(node, tmp); + sa_.Emit(node, target); +} + +void PandaGen::BranchIfStrictNotUndefined(const ir::AstNode *node, class Label *target) +{ + RegScope rs(this); + VReg tmp = AllocReg(); + StoreAccumulator(node, tmp); + LoadConst(node, Constant::JS_UNDEFINED); + ra_.Emit(node, tmp); + sa_.Emit(node, target); } void PandaGen::BranchIfTrue(const ir::AstNode *node, Label *target) { - sa_.Emit(node, target); + sa_.Emit(node); + sa_.Emit(node, target); } void PandaGen::BranchIfNotTrue(const ir::AstNode *node, Label *target) @@ -807,13 +855,8 @@ void PandaGen::BranchIfNotTrue(const ir::AstNode *node, Label *target) void PandaGen::BranchIfFalse(const ir::AstNode *node, Label *target) { - sa_.Emit(node, target); -} - -void PandaGen::BranchIfCoercible(const ir::AstNode *node, Label *target) -{ - sa_.Emit(node); - BranchIfTrue(node, target); + sa_.Emit(node); + sa_.Emit(node, target); } void PandaGen::EmitThrow(const ir::AstNode *node) @@ -823,12 +866,12 @@ void PandaGen::EmitThrow(const ir::AstNode *node) void PandaGen::EmitRethrow(const ir::AstNode *node) { - sa_.Emit(node); + // TODO: rethrow in try-catch } void PandaGen::EmitReturn(const ir::AstNode *node) { - sa_.Emit(node); + sa_.Emit(node); } void PandaGen::EmitReturnUndefined(const ir::AstNode *node) @@ -861,7 +904,7 @@ void PandaGen::ValidateClassDirectReturn(const ir::AstNode *node) auto *notUndefined = AllocLabel(); auto *condEnd = AllocLabel(); - BranchIfNotUndefined(node, notUndefined); + BranchIfStrictNotUndefined(node, notUndefined); GetThis(func); ThrowIfSuperNotCorrectCall(func, 0); Branch(node, condEnd); @@ -888,25 +931,25 @@ void PandaGen::Call(const ir::AstNode *node, VReg startReg, size_t argCount) switch (argCount) { case 0: { // 0 args - ra_.Emit(node, callee); + ra_.Emit(node, callee); break; } case 1: { // 1 arg VReg arg0 = callee + 1; - ra_.Emit(node, callee, arg0); + ra_.Emit(node, callee, arg0); break; } case 2: { // 2 args VReg arg0 = callee + 1; VReg arg1 = arg0 + 1; - ra_.Emit(node, callee, arg0, arg1); + ra_.Emit(node, callee, arg0, arg1); break; } case 3: { // 3 args VReg arg0 = callee + 1; VReg arg1 = arg0 + 1; VReg arg2 = arg1 + 1; - ra_.Emit(node, callee, arg0, arg1, arg2); + ra_.Emit(node, callee, arg0, arg1, arg2); break; } default: { @@ -938,21 +981,22 @@ void PandaGen::LoadHomeObject(const ir::AstNode *node) void PandaGen::DefineFunction(const ir::AstNode *node, const ir::ScriptFunction *realNode, const util::StringView &name) { - if (realNode->IsAsync()) { + auto formalParamCnt = realNode->FormalParamsLength(); + if (realNode->IsMethod()) { + ra_.Emit(node, name, static_cast(formalParamCnt), LexEnv()); + } else if (realNode->IsAsync()) { if (realNode->IsGenerator()) { - ra_.Emit(node, name, LexEnv()); + // TODO(): async generator } else { - ra_.Emit(node, name, LexEnv()); + ra_.Emit(node, name, static_cast(formalParamCnt), LexEnv()); } } else if (realNode->IsGenerator()) { - ra_.Emit(node, name, LexEnv()); + ra_.Emit(node, name, static_cast(formalParamCnt), LexEnv()); } else if (realNode->IsArrow()) { LoadHomeObject(node); - ra_.Emit(node, name, LexEnv()); - } else if (realNode->IsMethod()) { - ra_.Emit(node, name, LexEnv()); + ra_.Emit(node, name, static_cast(formalParamCnt), LexEnv()); } else { - ra_.Emit(node, name, LexEnv()); + ra_.Emit(node, name, static_cast(formalParamCnt), LexEnv()); } strings_.insert(name); @@ -980,12 +1024,14 @@ void PandaGen::GetUnmappedArgs(const ir::AstNode *node) void PandaGen::Negate(const ir::AstNode *node) { - sa_.Emit(node); -} - -void PandaGen::ToBoolean(const ir::AstNode *node) -{ - sa_.Emit(node); + auto *falseLabel = AllocLabel(); + auto *endLabel = AllocLabel(); + BranchIfTrue(node, falseLabel); + LoadConst(node, Constant::JS_TRUE); + Branch(node, endLabel); + SetLabel(node, falseLabel); + LoadConst(node, Constant::JS_FALSE); + SetLabel(node, endLabel); } void PandaGen::ToNumber(const ir::AstNode *node, VReg arg) @@ -993,12 +1039,6 @@ void PandaGen::ToNumber(const ir::AstNode *node, VReg arg) ra_.Emit(node, arg); } -void PandaGen::GetMethod(const ir::AstNode *node, VReg obj, const util::StringView &name) -{ - ra_.Emit(node, name, obj); - strings_.insert(name); -} - void PandaGen::CreateGeneratorObj(const ir::AstNode *node, VReg funcObj) { ra_.Emit(node, funcObj); @@ -1006,32 +1046,44 @@ void PandaGen::CreateGeneratorObj(const ir::AstNode *node, VReg funcObj) void PandaGen::CreateAsyncGeneratorObj(const ir::AstNode *node, VReg funcObj) { - ra_.Emit(node, funcObj); + /* + * TODO: async generator + * ra_.Emit(node, funcObj); + */ } -void PandaGen::CreateIterResultObject(const ir::AstNode *node, bool done) +void PandaGen::CreateIterResultObject(const ir::AstNode *node, VReg value, VReg done) { - ra_.Emit(node, static_cast(done)); + ra_.Emit(node, value, done); } -void PandaGen::SuspendGenerator(const ir::AstNode *node, VReg genObj) +void PandaGen::SuspendGenerator(const ir::AstNode *node, VReg genObj, VReg iterResult) { - ra_.Emit(node, genObj); + ra_.Emit(node, genObj, iterResult); } void PandaGen::SuspendAsyncGenerator(const ir::AstNode *node, VReg asyncGenObj) { - ra_.Emit(node, asyncGenObj); + /* + * TODO: suspend async generator + * ra_.Emit(node, asyncGenObj); + */ } void PandaGen::GeneratorYield(const ir::AstNode *node, VReg genObj) { - ra_.Emit(node, genObj, static_cast(GeneratorState::SUSPENDED_YIELD)); + /* + * TODO: set generator yield + * ra_.Emit(node, genObj, static_cast(GeneratorState::SUSPENDED_YIELD)); + */ } void PandaGen::GeneratorComplete(const ir::AstNode *node, VReg genObj) { - ra_.Emit(node, genObj, static_cast(GeneratorState::COMPLETED)); + /* + * TODO: set generator complete + * ra_.Emit(node, genObj, static_cast(GeneratorState::COMPLETED)); + */ } void PandaGen::ResumeGenerator(const ir::AstNode *node, VReg genObj) @@ -1049,29 +1101,35 @@ void PandaGen::AsyncFunctionEnter(const ir::AstNode *node) sa_.Emit(node); } -void PandaGen::AsyncFunctionAwait(const ir::AstNode *node, VReg asyncFuncObj) +void PandaGen::AsyncFunctionAwait(const ir::AstNode *node, VReg asyncFuncObj, VReg retVal) { - ra_.Emit(node, asyncFuncObj); + ra_.Emit(node, asyncFuncObj, retVal); } -void PandaGen::AsyncFunctionResolve(const ir::AstNode *node, VReg asyncFuncObj) +void PandaGen::AsyncFunctionResolve(const ir::AstNode *node, VReg asyncFuncObj, VReg value, VReg canSuspend) { - ra_.Emit(node, asyncFuncObj); + ra_.Emit(node, asyncFuncObj, value, canSuspend); } -void PandaGen::AsyncFunctionReject(const ir::AstNode *node, VReg asyncFuncObj) +void PandaGen::AsyncFunctionReject(const ir::AstNode *node, VReg asyncFuncObj, VReg value, VReg canSuspend) { - ra_.Emit(node, asyncFuncObj); + ra_.Emit(node, asyncFuncObj, value, canSuspend); } void PandaGen::AsyncGeneratorResolve(const ir::AstNode *node, VReg asyncGenObj) { - ra_.Emit(node, asyncGenObj); + /* + * TODO: async generator resolve + * ra_.Emit(node, asyncGenObj); + */ } void PandaGen::AsyncGeneratorReject(const ir::AstNode *node, VReg asyncGenObj) { - ra_.Emit(node, asyncGenObj); + /* + * TODO: async generator reject + * ra_.Emit(node, asyncGenObj); + */ } void PandaGen::GetTemplateObject(const ir::AstNode *node, VReg value) @@ -1241,9 +1299,9 @@ void PandaGen::StoreArraySpread(const ir::AstNode *node, VReg array, VReg index) ra_.Emit(node, array, index); } -void PandaGen::ThrowIfNotObject(const ir::AstNode *node) +void PandaGen::ThrowIfNotObject(const ir::AstNode *node, VReg obj) { - ra_.Emit(node); + ra_.Emit(node, obj); } void PandaGen::ThrowThrowNotExist(const ir::AstNode *node) @@ -1258,17 +1316,22 @@ void PandaGen::GetIterator(const ir::AstNode *node) void PandaGen::GetAsyncIterator(const ir::AstNode *node) { - sa_.Emit(node); + /* + * TODO: async iterator + * sa_.Emit(node); + */ } void PandaGen::CreateObjectWithExcludedKeys(const ir::AstNode *node, VReg obj, VReg argStart, size_t argCount) { ASSERT(argStart == obj + 1); - if (argCount == 0) { // Do not emit undefined register - argStart = obj; + if (argCount == 0) { + LoadConst(node, Constant::JS_UNDEFINED); + StoreAccumulator(node, argStart); } - rra_.Emit(node, argStart, argCount, static_cast(argCount), obj, + size_t argRegCnt = (argCount == 0 ? argCount : argCount - 1); + rra_.Emit(node, argStart, argCount, static_cast(argRegCnt), obj, argStart); } @@ -1284,21 +1347,28 @@ void PandaGen::CloseIterator(const ir::AstNode *node, VReg iter) void PandaGen::ImportModule(const ir::AstNode *node, const util::StringView &name) { - sa_.Emit(node, name); - strings_.insert(name); + /* + * TODO: module + * sa_.Emit(node, name); + * strings_.insert(name); + */ } void PandaGen::DefineClassWithBuffer(const ir::AstNode *node, const util::StringView &ctorId, int32_t litIdx, VReg lexenv, VReg base) { - ra_.Emit(node, ctorId, litIdx, lexenv, base); + auto formalParamCnt = node->AsClassDefinition()->Ctor()->Function()->FormalParamsLength(); + ra_.Emit(node, ctorId, litIdx, static_cast(formalParamCnt), lexenv, base); strings_.insert(ctorId); } void PandaGen::LoadModuleVariable(const ir::AstNode *node, VReg module, const util::StringView &name) { - ra_.Emit(node, name, module); - strings_.insert(name); + /* + * TODO: module + * ra_.Emit(node, name, module); + * strings_.insert(name); + */ } void PandaGen::StoreModuleVar(const ir::AstNode *node, const util::StringView &name) @@ -1386,7 +1456,15 @@ void PandaGen::LoadLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t void PandaGen::StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot) { - ra_.Emit(node, level, slot); + RegScope rs(this); + VReg value = AllocReg(); + StoreAccumulator(node, value); + ra_.Emit(node, level, slot, value); +} + +void PandaGen::StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot, VReg value) +{ + ra_.Emit(node, level, slot, value); } void PandaGen::ThrowIfSuperNotCorrectCall(const ir::AstNode *node, int64_t num) @@ -1396,13 +1474,24 @@ void PandaGen::ThrowIfSuperNotCorrectCall(const ir::AstNode *node, int64_t num) void PandaGen::ThrowUndefinedIfHole(const ir::AstNode *node, const util::StringView &name) { - ra_.Emit(node, name); + RegScope rs(this); + VReg holeReg = AllocReg(); + StoreAccumulator(node, holeReg); + LoadAccumulatorString(node, name); + VReg nameReg = AllocReg(); + StoreAccumulator(node, nameReg); + ra_.Emit(node, holeReg, nameReg); + LoadAccumulator(node, holeReg); strings_.insert(name); } void PandaGen::ThrowConstAssignment(const ir::AstNode *node, const util::StringView &name) { - ra_.Emit(node, name); + RegScope rs(this); + LoadAccumulatorString(node, name); + VReg nameReg = AllocReg(); + StoreAccumulator(node, nameReg); + ra_.Emit(node, nameReg); strings_.insert(name); } @@ -1413,7 +1502,10 @@ void PandaGen::PopLexEnv(const ir::AstNode *node) void PandaGen::CopyLexEnv(const ir::AstNode *node) { - sa_.Emit(node); + /* + * TODO: add copy lexenv to optimize the loop env creation + * sa_.Emit(node); + */ } void PandaGen::NewLexEnv(const ir::AstNode *node, uint32_t num) @@ -1459,11 +1551,15 @@ Operand PandaGen::ToNamedPropertyKey(const ir::Expression *prop, bool isComputed { VReg res {0}; - if (!isComputed) { - if (prop->IsIdentifier()) { - return prop->AsIdentifier()->Name(); - } - } else if (prop->IsStringLiteral()) { + if (isComputed) { + return res; + } + + if (prop->IsIdentifier()) { + return prop->AsIdentifier()->Name(); + } + + if (prop->IsStringLiteral()) { const util::StringView &str = prop->AsStringLiteral()->Str(); /* TODO(dbatyai): remove this when runtime handles __proto__ as property name correctly */ @@ -1477,7 +1573,9 @@ Operand PandaGen::ToNamedPropertyKey(const ir::Expression *prop, bool isComputed } return str; - } else if (prop->IsNumberLiteral()) { + } + + if (prop->IsNumberLiteral()) { auto num = prop->AsNumberLiteral()->Number(); if (util::Helpers::IsIndex(num)) { return static_cast(num); @@ -1523,4 +1621,22 @@ VReg PandaGen::LoadPropertyKey(const ir::Expression *prop, bool isComputed) return propReg; } +void PandaGen::StLetToGlobalRecord(const ir::AstNode *node, const util::StringView &name) +{ + sa_.Emit(node, name); + strings_.insert(name); +} + +void PandaGen::StConstToGlobalRecord(const ir::AstNode *node, const util::StringView &name) +{ + sa_.Emit(node, name); + strings_.insert(name); +} + +void PandaGen::StClassToGlobalRecord(const ir::AstNode *node, const util::StringView &name) +{ + sa_.Emit(node, name); + strings_.insert(name); +} + } // namespace panda::es2panda::compiler diff --git a/es2panda/compiler/core/pandagen.h b/es2panda/compiler/core/pandagen.h index eefd2e4b24180c09cf99b988a6a7f24cd2927186..7e82902931a418aa2eed6a7f9cdc03f18d391c8b 100644 --- a/es2panda/compiler/core/pandagen.h +++ b/es2panda/compiler/core/pandagen.h @@ -208,6 +208,10 @@ public: void LoadVar(const ir::Identifier *node, const binder::ScopeFindResult &result); void StoreVar(const ir::AstNode *node, const binder::ScopeFindResult &result, bool isDeclaration); + void StLetToGlobalRecord(const ir::AstNode *node, const util::StringView &name); + void StConstToGlobalRecord(const ir::AstNode *node, const util::StringView &name); + void StClassToGlobalRecord(const ir::AstNode *node, const util::StringView &name); + void StoreAccumulator(const ir::AstNode *node, VReg vreg); void LoadAccFromArgs(const ir::AstNode *node); void LoadObjProperty(const ir::AstNode *node, VReg obj, const Operand &prop); @@ -215,7 +219,7 @@ public: void LoadObjByName(const ir::AstNode *node, VReg obj, const util::StringView &prop); void StoreObjProperty(const ir::AstNode *node, VReg obj, const Operand &prop); - void StoreOwnProperty(const ir::AstNode *node, VReg obj, const Operand &prop); + void StoreOwnProperty(const ir::AstNode *node, VReg obj, const Operand &prop, bool nameSetting = false); void DeleteObjProperty(const ir::AstNode *node, VReg obj, const Operand &prop); void LoadAccumulator(const ir::AstNode *node, VReg reg); void LoadGlobalVar(const ir::AstNode *node, const util::StringView &name); @@ -234,6 +238,7 @@ public: void LoadAccumulatorFloat(const ir::AstNode *node, double num); void LoadAccumulatorInt(const ir::AstNode *node, int32_t num); void LoadAccumulatorInt(const ir::AstNode *node, size_t num); + void LoadAccumulatorBigInt(const ir::AstNode *node, const util::StringView &num); void LoadConst(const ir::AstNode *node, Constant id); void StoreConst(const ir::AstNode *node, VReg reg, Constant id); @@ -250,12 +255,13 @@ public: void Binary(const ir::AstNode *node, lexer::TokenType op, VReg lhs); void BranchIfUndefined(const ir::AstNode *node, class Label *target); + void BranchIfStrictNotUndefined(const ir::AstNode *node, class Label *target); void BranchIfNotUndefined(const ir::AstNode *node, class Label *target); void BranchIfHole(const ir::AstNode *node, class Label *target); void BranchIfTrue(const ir::AstNode *node, class Label *target); void BranchIfNotTrue(const ir::AstNode *node, class Label *target); void BranchIfFalse(const ir::AstNode *node, class Label *target); - void BranchIfCoercible(const ir::AstNode *node, class Label *target); + void BranchIfNotFalse(const ir::AstNode *node, class Label *target); void EmitThrow(const ir::AstNode *node); void EmitRethrow(const ir::AstNode *node); @@ -281,7 +287,6 @@ public: void GetUnmappedArgs(const ir::AstNode *node); void Negate(const ir::AstNode *node); - void ToBoolean(const ir::AstNode *node); void ToNumber(const ir::AstNode *node, VReg arg); void CreateGeneratorObj(const ir::AstNode *node, VReg funcObj); @@ -289,16 +294,15 @@ public: void GetResumeMode(const ir::AstNode *node, VReg genObj); void AsyncFunctionEnter(const ir::AstNode *node); - void AsyncFunctionAwait(const ir::AstNode *node, VReg asyncFuncObj); - void AsyncFunctionResolve(const ir::AstNode *node, VReg asyncFuncObj); - void AsyncFunctionReject(const ir::AstNode *node, VReg asyncFuncObj); + void AsyncFunctionAwait(const ir::AstNode *node, VReg asyncFuncObj, VReg retVal); + void AsyncFunctionResolve(const ir::AstNode *node, VReg asyncFuncObj, VReg value, VReg canSuspend); + void AsyncFunctionReject(const ir::AstNode *node, VReg asyncFuncObj, VReg value, VReg canSuspend); - void GetMethod(const ir::AstNode *node, VReg obj, const util::StringView &name); void GeneratorYield(const ir::AstNode *node, VReg genObj); void GeneratorComplete(const ir::AstNode *node, VReg genObj); void CreateAsyncGeneratorObj(const ir::AstNode *node, VReg funcObj); - void CreateIterResultObject(const ir::AstNode *node, bool done); - void SuspendGenerator(const ir::AstNode *node, VReg genObj); + void CreateIterResultObject(const ir::AstNode *node, VReg value, VReg done); + void SuspendGenerator(const ir::AstNode *node, VReg genObj, VReg iterResult); void SuspendAsyncGenerator(const ir::AstNode *node, VReg asyncGenObj); void AsyncGeneratorResolve(const ir::AstNode *node, VReg asyncGenObj); @@ -321,7 +325,7 @@ public: void CreateArrayWithBuffer(const ir::AstNode *node, uint32_t idx); void StoreArraySpread(const ir::AstNode *node, VReg array, VReg index); - void ThrowIfNotObject(const ir::AstNode *node); + void ThrowIfNotObject(const ir::AstNode *node, VReg obj); void ThrowThrowNotExist(const ir::AstNode *node); void GetIterator(const ir::AstNode *node); void GetAsyncIterator(const ir::AstNode *node); @@ -350,6 +354,7 @@ public: void NewLexEnv(const ir::AstNode *node, uint32_t num); void LoadLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot); void StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot); + void StoreLexicalVar(const ir::AstNode *node, uint32_t level, uint32_t slot, VReg value); void ThrowIfSuperNotCorrectCall(const ir::AstNode *node, int64_t num); void ThrowUndefinedIfHole(const ir::AstNode *node, const util::StringView &name); @@ -366,8 +371,8 @@ public: void StoreObjByIndex(const ir::AstNode *node, VReg obj, int64_t index); void StoreObjByValue(const ir::AstNode *node, VReg obj, VReg prop); - void StOwnByName(const ir::AstNode *node, VReg obj, const util::StringView &prop); - void StOwnByValue(const ir::AstNode *node, VReg obj, VReg prop); + void StOwnByName(const ir::AstNode *node, VReg obj, const util::StringView &prop, bool nameSetting = false); + void StOwnByValue(const ir::AstNode *node, VReg obj, VReg prop, bool nameSetting = false); void StOwnByIndex(const ir::AstNode *node, VReg obj, int64_t index); static Operand ToNamedPropertyKey(const ir::Expression *prop, bool isComputed); diff --git a/es2panda/compiler/function/asyncFunctionBuilder.cpp b/es2panda/compiler/function/asyncFunctionBuilder.cpp index acbbc790ab449ea78e45f907ad6cc3d527c0c3d5..170db3207315506a56f354e901c50a69a9fe9dc7 100644 --- a/es2panda/compiler/function/asyncFunctionBuilder.cpp +++ b/es2panda/compiler/function/asyncFunctionBuilder.cpp @@ -23,7 +23,15 @@ namespace panda::es2panda::compiler { void AsyncFunctionBuilder::DirectReturn(const ir::AstNode *node) const { - pg_->AsyncFunctionResolve(node, funcObj_); + RegScope rs(pg_); + VReg retVal = pg_->AllocReg(); + VReg canSuspend = pg_->AllocReg(); + + pg_->StoreAccumulator(node, retVal); + pg_->LoadConst(node, Constant::JS_TRUE); + pg_->StoreAccumulator(node, canSuspend); + pg_->AsyncFunctionResolve(node, funcObj_, retVal, canSuspend); + pg_->LoadAccumulator(node, retVal); pg_->EmitReturn(node); } @@ -33,7 +41,7 @@ void AsyncFunctionBuilder::ImplicitReturn(const ir::AstNode *node) const DirectReturn(node); } -void AsyncFunctionBuilder::Prepare(const ir::ScriptFunction *node) const +void AsyncFunctionBuilder::Prepare(const ir::ScriptFunction *node) { pg_->AsyncFunctionEnter(node); pg_->StoreAccumulator(node, funcObj_); @@ -42,11 +50,16 @@ void AsyncFunctionBuilder::Prepare(const ir::ScriptFunction *node) const void AsyncFunctionBuilder::CleanUp(const ir::ScriptFunction *node) const { + RegScope rs(pg_); const auto &labelSet = catchTable_->LabelSet(); pg_->SetLabel(node, labelSet.TryEnd()); pg_->SetLabel(node, labelSet.CatchBegin()); - pg_->AsyncFunctionReject(node, funcObj_); + VReg exception = pg_->AllocReg(); + VReg canSuspend = pg_->AllocReg(); + pg_->StoreAccumulator(node, exception); + pg_->StoreConst(node, canSuspend, Constant::JS_TRUE); + pg_->AsyncFunctionReject(node, funcObj_, exception, canSuspend); pg_->EmitReturn(node); pg_->SetLabel(node, labelSet.CatchEnd()); } diff --git a/es2panda/compiler/function/asyncFunctionBuilder.h b/es2panda/compiler/function/asyncFunctionBuilder.h index bd7f38a81456a69877e83c58318ab9670dec20ba..68bdd99433f8cf94781f210ba5ca6842d8af09cb 100644 --- a/es2panda/compiler/function/asyncFunctionBuilder.h +++ b/es2panda/compiler/function/asyncFunctionBuilder.h @@ -30,7 +30,7 @@ public: NO_COPY_SEMANTIC(AsyncFunctionBuilder); NO_MOVE_SEMANTIC(AsyncFunctionBuilder); - void Prepare(const ir::ScriptFunction *node) const override; + void Prepare(const ir::ScriptFunction *node) override; void CleanUp(const ir::ScriptFunction *node) const override; void DirectReturn(const ir::AstNode *node) const override; diff --git a/es2panda/compiler/function/asyncGeneratorFunctionBuilder.cpp b/es2panda/compiler/function/asyncGeneratorFunctionBuilder.cpp index c4360cd87af39409aa8692c5872f7498320848e7..a74eea46df994ebcf77a2c6e04bdbe664a8b0831 100644 --- a/es2panda/compiler/function/asyncGeneratorFunctionBuilder.cpp +++ b/es2panda/compiler/function/asyncGeneratorFunctionBuilder.cpp @@ -20,13 +20,13 @@ #include namespace panda::es2panda::compiler { -void AsyncGeneratorFunctionBuilder::Prepare(const ir::ScriptFunction *node) const +void AsyncGeneratorFunctionBuilder::Prepare(const ir::ScriptFunction *node) { VReg callee = FunctionReg(node); pg_->CreateAsyncGeneratorObj(node, callee); pg_->StoreAccumulator(node, funcObj_); - pg_->SuspendGenerator(node, funcObj_); + // pg_->SuspendGenerator(node, funcObj_); TODO implement this part correctly while implementing async generator pg_->SetLabel(node, catchTable_->LabelSet().TryBegin()); } @@ -72,7 +72,7 @@ void AsyncGeneratorFunctionBuilder::Yield(const ir::AstNode *node) pg_->Condition(node, lexer::TokenType::PUNCTUATOR_EQUAL, completionType, notReturnCompletion); // 27.6.3.8.8.b. Let awaited be Await(resumptionValue.[[Value]]). pg_->LoadAccumulator(node, completionValue); - pg_->AsyncFunctionAwait(node, funcObj_); + pg_->AsyncFunctionAwait(node, funcObj_, completionValue); SuspendResumeExecution(node, completionType, completionValue); // 27.6.3.8.8.c. If awaited.[[Type]] is throw, return Completion(awaited). diff --git a/es2panda/compiler/function/asyncGeneratorFunctionBuilder.h b/es2panda/compiler/function/asyncGeneratorFunctionBuilder.h index f492da49d1f4428945821d5f1a4fae51c75c7b91..8ae591a79c41b90324fb45d62f41ed5284df1f29 100644 --- a/es2panda/compiler/function/asyncGeneratorFunctionBuilder.h +++ b/es2panda/compiler/function/asyncGeneratorFunctionBuilder.h @@ -30,7 +30,7 @@ public: NO_COPY_SEMANTIC(AsyncGeneratorFunctionBuilder); NO_MOVE_SEMANTIC(AsyncGeneratorFunctionBuilder); - void Prepare(const ir::ScriptFunction *node) const override; + void Prepare(const ir::ScriptFunction *node) override; void CleanUp(const ir::ScriptFunction *node) const override; void DirectReturn(const ir::AstNode *node) const override; diff --git a/es2panda/compiler/function/functionBuilder.cpp b/es2panda/compiler/function/functionBuilder.cpp index eaba22a71aaada4722e54db98adba4d474341bc6..47184ca1f557a1cbed483deb7641eac1ad3da9cb 100644 --- a/es2panda/compiler/function/functionBuilder.cpp +++ b/es2panda/compiler/function/functionBuilder.cpp @@ -68,7 +68,10 @@ void FunctionBuilder::SuspendResumeExecution(const ir::AstNode *node, VReg compl ASSERT(BuilderKind() == BuilderType::ASYNC || BuilderKind() == BuilderType::ASYNC_GENERATOR || BuilderKind() == BuilderType::GENERATOR); - pg_->SuspendGenerator(node, funcObj_); + RegScope rs(pg_); + VReg iterResult = pg_->AllocReg(); + pg_->StoreAccumulator(node, iterResult); + pg_->SuspendGenerator(node, funcObj_, iterResult); resumeGenerator(node, completionType, completionValue); } @@ -103,8 +106,10 @@ void FunctionBuilder::Await(const ir::AstNode *node) RegScope rs(pg_); VReg completionType = pg_->AllocReg(); VReg completionValue = pg_->AllocReg(); + VReg retVal = pg_->AllocReg(); - pg_->AsyncFunctionAwait(node, funcObj_); + pg_->StoreAccumulator(node, retVal); + pg_->AsyncFunctionAwait(node, funcObj_, retVal); SuspendResumeExecution(node, completionType, completionValue); HandleCompletion(node, completionType, completionValue); @@ -239,7 +244,7 @@ void FunctionBuilder::YieldStar(const ir::AstNode *node) // ii. If Type(innerResult) is not Object, throw a TypeError exception. // 4. If Type(innerResult) is not Object, throw a TypeError exception. // vi. If Type(innerReturnResult) is not Object, throw a TypeError exception. - pg_->ThrowIfNotObject(node); + pg_->ThrowIfNotObject(node, receivedValue); // iv. Let done be ? IteratorComplete(innerResult). // v. Let done be ? IteratorComplete(innerResult). @@ -264,8 +269,7 @@ void FunctionBuilder::YieldStar(const ir::AstNode *node) pg_->Condition(node, lexer::TokenType::PUNCTUATOR_EQUAL, receivedType, loopStart); // b. Let awaited be Await(resumptionValue.[[Value]]). - pg_->LoadAccumulator(node, receivedValue); - pg_->AsyncFunctionAwait(node, funcObj_); + pg_->AsyncFunctionAwait(node, funcObj_, receivedValue); SuspendResumeExecution(node, receivedType, receivedValue); // c. If awaited.[[Type]] is throw, return Completion(awaited). diff --git a/es2panda/compiler/function/functionBuilder.h b/es2panda/compiler/function/functionBuilder.h index 4147c49577a673a71ea7f8ee198bc1e2158443ce..63abf6f78e5cd054a2064fe9340ff85ee66d1f20 100644 --- a/es2panda/compiler/function/functionBuilder.h +++ b/es2panda/compiler/function/functionBuilder.h @@ -49,7 +49,7 @@ public: NO_COPY_SEMANTIC(FunctionBuilder); NO_MOVE_SEMANTIC(FunctionBuilder); - virtual void Prepare([[maybe_unused]] const ir::ScriptFunction *node) const {}; + virtual void Prepare([[maybe_unused]] const ir::ScriptFunction *node) {}; virtual void CleanUp([[maybe_unused]] const ir::ScriptFunction *node) const {}; virtual void DirectReturn(const ir::AstNode *node) const; diff --git a/es2panda/compiler/function/generatorFunctionBuilder.cpp b/es2panda/compiler/function/generatorFunctionBuilder.cpp index a4d71b3fd2dac50aded1c33cabc31d89dac78a15..e302dfe9846fa2b1d6be422225399a35fc3ccc1a 100644 --- a/es2panda/compiler/function/generatorFunctionBuilder.cpp +++ b/es2panda/compiler/function/generatorFunctionBuilder.cpp @@ -21,14 +21,17 @@ namespace panda::es2panda::compiler { -void GeneratorFunctionBuilder::Prepare(const ir::ScriptFunction *node) const +void GeneratorFunctionBuilder::Prepare(const ir::ScriptFunction *node) { VReg callee = FunctionReg(node); + VReg completionType = pg_->AllocReg(); + VReg completionValue = pg_->AllocReg(); pg_->CreateGeneratorObj(node, callee); pg_->StoreAccumulator(node, funcObj_); - pg_->SuspendGenerator(node, funcObj_); - pg_->SetLabel(node, catchTable_->LabelSet().TryBegin()); + pg_->LoadConst(node, Constant::JS_UNDEFINED); + SuspendResumeExecution(node, completionType, completionValue); + HandleCompletion(node, completionType, completionValue); } void GeneratorFunctionBuilder::CleanUp(const ir::ScriptFunction *node) const @@ -44,8 +47,6 @@ void GeneratorFunctionBuilder::CleanUp(const ir::ScriptFunction *node) const void GeneratorFunctionBuilder::DirectReturn(const ir::AstNode *node) const { - pg_->GeneratorComplete(node, funcObj_); - pg_->CreateIterResultObject(node, true); pg_->EmitReturn(node); } @@ -58,11 +59,15 @@ void GeneratorFunctionBuilder::ImplicitReturn(const ir::AstNode *node) const void GeneratorFunctionBuilder::Yield(const ir::AstNode *node) { RegScope rs(pg_); + VReg value = pg_->AllocReg(); + VReg done = pg_->AllocReg(); VReg completionType = pg_->AllocReg(); VReg completionValue = pg_->AllocReg(); - pg_->CreateIterResultObject(node, false); - pg_->GeneratorYield(node, funcObj_); + pg_->StoreAccumulator(node, value); + pg_->LoadConst(node, Constant::JS_FALSE); + pg_->StoreAccumulator(node, done); + pg_->CreateIterResultObject(node, value, done); SuspendResumeExecution(node, completionType, completionValue); HandleCompletion(node, completionType, completionValue); diff --git a/es2panda/compiler/function/generatorFunctionBuilder.h b/es2panda/compiler/function/generatorFunctionBuilder.h index a1a12295654cff025fcd0754b8d1cd116074ecff..6b3b96acb38608325ffc00b5426909e807f617db 100644 --- a/es2panda/compiler/function/generatorFunctionBuilder.h +++ b/es2panda/compiler/function/generatorFunctionBuilder.h @@ -44,7 +44,7 @@ public: NO_COPY_SEMANTIC(GeneratorFunctionBuilder); NO_MOVE_SEMANTIC(GeneratorFunctionBuilder); - void Prepare(const ir::ScriptFunction *node) const override; + void Prepare(const ir::ScriptFunction *node) override; void CleanUp(const ir::ScriptFunction *node) const override; void DirectReturn(const ir::AstNode *node) const override; diff --git a/es2panda/es2abc_config.gni b/es2panda/es2abc_config.gni new file mode 100644 index 0000000000000000000000000000000000000000..008466806f5076e43604f814f5fece83d3b0c401 --- /dev/null +++ b/es2panda/es2abc_config.gni @@ -0,0 +1,91 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_frontend/ets_frontend_config.gni") +if (defined(ark_independent_build)) { + import("$build_root/ark.gni") + es2abc_root = "//ets_frontend/es2panda" +} else { + import("//build/ohos.gni") + build_root = "//build" + es2abc_root = "//arkcompiler/ets_frontend/es2panda" +} + +es2abc_build_path = "" +es2abc_build_deps = "" +es2abc_out_root = "" + +if (host_toolchain == toolchain_mac) { + es2abc_out_root = + get_label_info("$es2abc_root:es2panda($toolchain_mac)", "root_out_dir") + es2abc_build_deps = [ "$es2abc_root:es2panda($toolchain_mac)" ] +} else if (host_toolchain == toolchain_win) { + es2abc_out_root = + get_label_info("$es2abc_root:es2panda($toolchain_win)", "root_out_dir") + es2abc_build_deps = [ "$es2abc_root:es2panda($toolchain_win)" ] +} else { + es2abc_out_root = + get_label_info("$es2abc_root:es2panda($toolchain_linux)", "root_out_dir") + es2abc_build_deps = [ "$es2abc_root:es2panda($toolchain_linux)" ] +} +es2abc_build_path = es2abc_out_root + "/ark/ark" + +# Generate abc. +# +# Mandatory arguments: +# plugin_path -- plugin js file path +# plugin_name -- name of js file, ex: BatteryPlugin.js +# generat_file -- name of generated file +# package_name -- name of generated file's package +# extra_dependencies -- a list of files that should be considered as dependencies, must be label +# out_puts +template("es2abc_gen_abc") { + assert(defined(invoker.src_js), "src_js is required!") + assert(defined(invoker.dst_file), "dst_file is required!") + assert(defined(invoker.out_puts), "out_puts is required!") + + extra_dependencies = [] + if (defined(invoker.extra_dependencies)) { + extra_dependencies += invoker.extra_dependencies + } + + action("$target_name") { + if (defined(invoker.extra_visibility)) { + visibility = invoker.extra_visibility + } + + script = "${es2abc_root}/scripts/generate_js_bytecode.py" + + deps = extra_dependencies + deps += es2abc_build_deps + + args = [ + "--src-js", + invoker.src_js, + "--dst-file", + invoker.dst_file, + "--frontend-tool-path", + rebase_path("${es2abc_build_path}"), + ] + + if (defined(invoker.extra_args)) { + args += invoker.extra_args + } + + if (defined(invoker.in_puts)) { + inputs = invoker.in_puts + } + + outputs = invoker.out_puts + } +} diff --git a/es2panda/ir/base/classDefinition.cpp b/es2panda/ir/base/classDefinition.cpp index bd18a40d3425b32ea918bd40b81e76f83b0d36a3..260910e252d47833b4f7ce1bc7ccf1c74bf22fe2 100644 --- a/es2panda/ir/base/classDefinition.cpp +++ b/es2panda/ir/base/classDefinition.cpp @@ -120,6 +120,7 @@ int32_t ClassDefinition::CreateClassStaticProperties(compiler::PandaGen *pg, uti auto *buf = pg->NewLiteralBuffer(); compiler::LiteralBuffer staticBuf(pg->Allocator()); bool seenComputed = false; + uint32_t instancePropertyCount = 0; std::unordered_map propNameMap; std::unordered_map staticPropNameMap; @@ -131,12 +132,15 @@ int32_t ClassDefinition::CreateClassStaticProperties(compiler::PandaGen *pg, uti } const ir::MethodDefinition *prop = properties[i]->AsMethodDefinition(); - if (!util::Helpers::IsConstantPropertyKey(prop->Key(), prop->Computed()) || - (prop->Computed() && util::Helpers::IsSpecialPropertyKey(prop->Key()))) { + if (prop->Computed()) { seenComputed = true; continue; } + if (prop->IsAccessor()) { + break; + } + util::StringView name = util::Helpers::LiteralToPropName(prop->Key()); compiler::LiteralBuffer *literalBuf = prop->IsStatic() ? &staticBuf : buf; auto &nameMap = prop->IsStatic() ? staticPropNameMap : propNameMap; @@ -149,7 +153,8 @@ int32_t ClassDefinition::CreateClassStaticProperties(compiler::PandaGen *pg, uti } literalBuf->Add(pg->Allocator()->New(name)); - literalBuf->Add(nullptr); + literalBuf->Add(nullptr); // save for method internalname + literalBuf->Add(nullptr); // save for method affiliate } else { bufferPos = res.first->second; } @@ -162,12 +167,18 @@ int32_t ClassDefinition::CreateClassStaticProperties(compiler::PandaGen *pg, uti const util::StringView &internalName = func->Function()->Scope()->InternalName(); value = pg->Allocator()->New(LiteralTag::METHOD, internalName); + literalBuf->ResetLiteral(bufferPos + 1, value); + Literal *methodAffiliate = pg->Allocator()->New(LiteralTag::METHODAFFILIATE, + func->Function()->FormalParamsLength()); + literalBuf->ResetLiteral(bufferPos + 2, methodAffiliate); // bufferPos + 2 is saved for method affiliate compiled.Set(i); break; } + // TODO refactor this part later case ir::MethodDefinitionKind::GET: case ir::MethodDefinitionKind::SET: { value = pg->Allocator()->New(); + literalBuf->ResetLiteral(bufferPos + 1, value); break; } default: { @@ -175,17 +186,17 @@ int32_t ClassDefinition::CreateClassStaticProperties(compiler::PandaGen *pg, uti } } - literalBuf->ResetLiteral(bufferPos + 1, value); + if (!prop->IsStatic()) { + instancePropertyCount++; + } } - uint32_t litPairs = buf->Size() / 2; - /* Static items are stored at the end of the buffer */ buf->Insert(&staticBuf); /* The last literal item represents the offset of the first static property. The regular property literal count * is divided by 2 as key/value pairs count as one. */ - buf->Add(pg->Allocator()->New(litPairs)); + buf->Add(pg->Allocator()->New(instancePropertyCount)); return pg->AddLiteralBuffer(buf); } @@ -217,7 +228,7 @@ void ClassDefinition::CompileMissingProperties(compiler::PandaGen *pg, const uti const ir::FunctionExpression *func = prop->Value()->AsFunctionExpression(); func->Compile(pg); - pg->StoreOwnProperty(prop->Value()->Parent(), dest, key); + pg->StoreOwnProperty(prop->Value()->Parent(), dest, key, prop->Computed()); break; } case ir::MethodDefinitionKind::GET: @@ -269,9 +280,7 @@ void ClassDefinition::Compile(compiler::PandaGen *pg) const int32_t bufIdx = CreateClassStaticProperties(pg, compiled); pg->DefineClassWithBuffer(this, ctorId, bufIdx, lexenv, baseReg); - if (scope_->Parent()->IsGlobalScope() && ident_) { - pg->StoreGlobalLet(this, ident_->Name()); - } + pg->StoreAccumulator(this, classReg); InitializeClassName(pg); diff --git a/es2panda/ir/base/methodDefinition.h b/es2panda/ir/base/methodDefinition.h index e304cd084e23e350d8457da1bb9b7e676f6fc26b..1170e01693b500da39d45e68134bcc105aed9a82 100644 --- a/es2panda/ir/base/methodDefinition.h +++ b/es2panda/ir/base/methodDefinition.h @@ -80,6 +80,11 @@ public: return (modifiers_ & ModifierFlags::STATIC) != 0; } + bool IsAccessor() const + { + return (kind_ == MethodDefinitionKind::GET) || (kind_ == MethodDefinitionKind::SET); + } + bool IsOptional() const { return (modifiers_ & ModifierFlags::OPTIONAL) != 0; diff --git a/es2panda/ir/expressions/binaryExpression.cpp b/es2panda/ir/expressions/binaryExpression.cpp index 7423a2dfb2b77762dd586c92af91a76d97420630..5621dfe8e527df72cfb90a74986ce8464631a8d4 100644 --- a/es2panda/ir/expressions/binaryExpression.cpp +++ b/es2panda/ir/expressions/binaryExpression.cpp @@ -56,7 +56,6 @@ void BinaryExpression::CompileLogical(compiler::PandaGen *pg) const // left -> acc -> lhs -> toboolean -> acc -> bool_lhs left_->Compile(pg); pg->StoreAccumulator(this, lhs); - pg->ToBoolean(this); if (operator_ == lexer::TokenType::PUNCTUATOR_LOGICAL_AND) { pg->BranchIfFalse(this, skipRight); diff --git a/es2panda/ir/expressions/chainExpression.cpp b/es2panda/ir/expressions/chainExpression.cpp index 0869146030a2790ec4ab1515f6a239faffe2a89e..16e2b3a29991f70cf1ba27f16a050a5a195fcf9e 100644 --- a/es2panda/ir/expressions/chainExpression.cpp +++ b/es2panda/ir/expressions/chainExpression.cpp @@ -1,4 +1,4 @@ -/** +/* * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/es2panda/ir/expressions/literal.cpp b/es2panda/ir/expressions/literal.cpp index 48cb9a94d4317a7940cc7c06ae92c416f03258de..4a021f470ff5a8323d89922856ed064cf09c6ec9 100644 --- a/es2panda/ir/expressions/literal.cpp +++ b/es2panda/ir/expressions/literal.cpp @@ -52,4 +52,10 @@ const util::StringView &Literal::GetMethod() const return AsTaggedLiteral()->Method(); } +uint16_t Literal::GetMethodAffiliate() const +{ + ASSERT(IsTaggedLiteral()); + return AsTaggedLiteral()->MethodAffiliate(); +} + } // namespace panda::es2panda::ir diff --git a/es2panda/ir/expressions/literal.h b/es2panda/ir/expressions/literal.h index ee6bc7af23e6d239b26b2b8275c6cb6428c67bb2..c38869152df2e7338db52a515f8029cdae40e525 100644 --- a/es2panda/ir/expressions/literal.h +++ b/es2panda/ir/expressions/literal.h @@ -37,11 +37,12 @@ enum class LiteralTag { FLOAT, DOUBLE, STRING, - ACCESSOR, METHOD, GENERATOR_METHOD, + ACCESSOR, + METHODAFFILIATE, ASYNC_GENERATOR_METHOD, - NULL_VALUE, + NULL_VALUE = 255, }; class Literal : public Expression { @@ -58,6 +59,7 @@ public: double GetDouble() const; const util::StringView &GetString() const; const util::StringView &GetMethod() const; + uint16_t GetMethodAffiliate() const; protected: explicit Literal(AstNodeType type) : Expression(type) {} diff --git a/es2panda/ir/expressions/literals/bigIntLiteral.cpp b/es2panda/ir/expressions/literals/bigIntLiteral.cpp index 7d3a149f8fad46f96cb87d6e174d1f78383d3cab..19290522c68df50fa8b494509ed8d2985891361f 100644 --- a/es2panda/ir/expressions/literals/bigIntLiteral.cpp +++ b/es2panda/ir/expressions/literals/bigIntLiteral.cpp @@ -30,8 +30,8 @@ void BigIntLiteral::Dump(ir::AstDumper *dumper) const void BigIntLiteral::Compile(compiler::PandaGen *pg) const { - // TODO() - pg->Unimplemented(); + util::StringView bigIntValue = src_.Substr(0, src_.Length()-1); + pg->LoadAccumulatorBigInt(this, bigIntValue); } checker::Type *BigIntLiteral::Check(checker::Checker *checker) const diff --git a/es2panda/ir/expressions/literals/taggedLiteral.h b/es2panda/ir/expressions/literals/taggedLiteral.h index 69a4b6486a38bd9e10ad389b8551b24fcf30fcea..c8ecd27e70eb55ca5392b6ff75ddfeb348adee47 100644 --- a/es2panda/ir/expressions/literals/taggedLiteral.h +++ b/es2panda/ir/expressions/literals/taggedLiteral.h @@ -37,6 +37,11 @@ public: { } + explicit TaggedLiteral(LiteralTag tag, uint16_t num) + : Literal(AstNodeType::TAGGED_LITERAL), num_(num), tag_(tag) + { + } + const util::StringView &Str() const { return str_; @@ -59,12 +64,19 @@ public: return str_; } + uint16_t MethodAffiliate() const + { + ASSERT(tag_ == LiteralTag::METHODAFFILIATE); + return num_; + } + void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; checker::Type *Check([[maybe_unused]] checker::Checker *checker) const override; private: + uint16_t num_ {}; util::StringView str_ {}; LiteralTag tag_ {LiteralTag::NULL_VALUE}; }; diff --git a/es2panda/parser/statementParser.cpp b/es2panda/parser/statementParser.cpp index 2a06a84efb4e124c1b1a3521b5c7cc7e675ef83a..c1e63e01d48f552c25d9f51ea0a9d6d625c6ff3a 100644 --- a/es2panda/parser/statementParser.cpp +++ b/es2panda/parser/statementParser.cpp @@ -388,7 +388,7 @@ ir::Statement *ParserImpl::ParseVarStatement(bool isDeclare) ir::Statement *ParserImpl::ParseLetStatement(StatementParsingFlags flags, bool isDeclare) { if (!(flags & StatementParsingFlags::ALLOW_LEXICAL)) { - ThrowSyntaxError("Lexical declaration is not allowed in single statement context"); + ThrowSyntaxError("The 'let' declarations can only be declared at the top level or inside a block."); } auto *variableDecl = ParseVariableDeclaration(VariableParsingFlags::LET, isDeclare); @@ -399,7 +399,7 @@ ir::Statement *ParserImpl::ParseLetStatement(StatementParsingFlags flags, bool i ir::Statement *ParserImpl::ParseConstStatement(StatementParsingFlags flags, bool isDeclare) { if (!(flags & StatementParsingFlags::ALLOW_LEXICAL)) { - ThrowSyntaxError("Lexical declaration is not allowed in single statement context"); + ThrowSyntaxError("The 'const' declarations can only be declared at the top level or inside a block."); } lexer::SourcePosition constVarStar = lexer_->GetToken().Start(); @@ -488,7 +488,7 @@ ir::ClassDeclaration *ParserImpl::ParseClassStatement(StatementParsingFlags flag ArenaVector &&decorators, bool isAbstract) { if (!(flags & StatementParsingFlags::ALLOW_LEXICAL)) { - ThrowSyntaxError("Lexical declaration is not allowed in single statement context"); + ThrowSyntaxError("Lexical 'class' declaration is not allowed in single statement context"); } return ParseClassDeclaration(true, std::move(decorators), isDeclare, isAbstract); @@ -501,7 +501,7 @@ ir::ClassDeclaration *ParserImpl::ParseClassDeclaration(bool idRequired, ArenaVe ir::ClassDefinition *classDefinition = ParseClassDefinition(true, idRequired, isDeclare, isAbstract); auto *decl = - Binder()->AddDecl(classDefinition->Ident()->Start(), classDefinition->Ident()->Name()); + Binder()->AddDecl(classDefinition->Ident()->Start(), classDefinition->Ident()->Name()); decl->BindNode(classDefinition); lexer::SourcePosition endLoc = classDefinition->End(); @@ -671,23 +671,19 @@ ir::TSInterfaceDeclaration *ParserImpl::ParseTsInterfaceDeclaration() void ParserImpl::CheckFunctionDeclaration(StatementParsingFlags flags) { - if (flags & StatementParsingFlags::LABELLED) { - ThrowSyntaxError( - "In strict mode code, functions can only be " - "declared at top level, inside a block, " - "or " - "as the body of an if statement"); + if (flags & StatementParsingFlags::ALLOW_LEXICAL) { + return; } - if (!(flags & StatementParsingFlags::ALLOW_LEXICAL)) { - if (!(flags & (StatementParsingFlags::IF_ELSE | StatementParsingFlags::LABELLED))) { - ThrowSyntaxError("Lexical declaration is not allowed in single statement context"); - } - - if (lexer_->Lookahead() == LEX_CHAR_ASTERISK) { - ThrowSyntaxError("Generators can only be declared at the top level or inside a block"); - } + if (lexer_->Lookahead() == LEX_CHAR_ASTERISK) { + ThrowSyntaxError("Generators can only be declared at the top level or inside a block."); } + + ThrowSyntaxError( + "In strict mode code, functions can only be " + "declared at top level, inside a block, " + "or " + "as the body of an if statement"); } void ParserImpl::ConsumeSemicolon(ir::Statement *statement) @@ -790,11 +786,11 @@ ir::BreakStatement *ParserImpl::ParseBreakStatement() } lexer::SourcePosition startLoc = lexer_->GetToken().Start(); - lexer::SourcePosition endLoc = lexer_->GetToken().End(); lexer_->NextToken(); if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON || - lexer_->GetToken().Type() == lexer::TokenType::EOS || lexer_->GetToken().NewLine()) { + lexer_->GetToken().Type() == lexer::TokenType::EOS || lexer_->GetToken().NewLine() || + lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { if (!allowBreak) { if (Extension() == ScriptExtension::JS) { ThrowSyntaxError("Illegal break statement"); @@ -808,24 +804,10 @@ ir::BreakStatement *ParserImpl::ParseBreakStatement() auto *breakStatement = AllocNode(); breakStatement->SetRange({startLoc, lexer_->GetToken().End()}); - lexer_->NextToken(); - return breakStatement; - } - - if (lexer_->GetToken().NewLine() || lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { - if (!allowBreak) { - if (Extension() == ScriptExtension::JS) { - ThrowSyntaxError("Illegal break statement"); - } - if (Extension() == ScriptExtension::TS) { - ThrowSyntaxError( - "A 'break' statement can only be used within an " - "enclosing iteration or switch statement"); - } + if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_SEMI_COLON) { + lexer_->NextToken(); } - auto *breakStatement = AllocNode(); - breakStatement->SetRange({startLoc, endLoc}); return breakStatement; } @@ -1019,7 +1001,7 @@ ir::Statement *ParserImpl::ParseExpressionStatement(StatementParsingFlags flags) if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_FUNCTION && !lexer_->GetToken().NewLine()) { if (!(flags & StatementParsingFlags::ALLOW_LEXICAL)) { - ThrowSyntaxError("Lexical declaration is not allowed in single statement context"); + ThrowSyntaxError("Async functions can only be declared at the top level or inside a block."); } ir::FunctionDeclaration *functionDecl = ParseFunctionDeclaration(false, ParserStatus::ASYNC_FUNCTION); @@ -1341,7 +1323,7 @@ ir::IfStatement *ParserImpl::ParseIfStatement() } lexer_->NextToken(); - ir::Statement *consequent = ParseStatement(StatementParsingFlags::IF_ELSE | StatementParsingFlags::ALLOW_LEXICAL); + ir::Statement *consequent = ParseStatement(StatementParsingFlags::IF_ELSE); if (Extension() == ScriptExtension::TS && consequent->IsEmptyStatement()) { ThrowSyntaxError("The body of an if statement cannot be the empty statement"); @@ -1352,7 +1334,7 @@ ir::IfStatement *ParserImpl::ParseIfStatement() if (lexer_->GetToken().Type() == lexer::TokenType::KEYW_ELSE) { lexer_->NextToken(); // eat ELSE keyword - alternate = ParseStatement(StatementParsingFlags::IF_ELSE | StatementParsingFlags::ALLOW_LEXICAL); + alternate = ParseStatement(StatementParsingFlags::IF_ELSE); endLoc = alternate->End(); } @@ -1816,6 +1798,11 @@ ir::Statement *ParserImpl::ParseVariableDeclaration(VariableParsingFlags flags, lexer_->NextToken(); } + if ((flags & VariableParsingFlags::LET) && util::Helpers::IsGlobalIdentifier(lexer_->GetToken().Ident())) { + ThrowSyntaxError("Declaration name conflicts with built-in global identifier '" + + lexer_->GetToken().Ident().Mutf8() + "'."); + } + if (Extension() == ScriptExtension::TS && lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_ENUM) { if (!(flags & VariableParsingFlags::CONST)) { ThrowSyntaxError("Variable declaration expected."); diff --git a/es2panda/scripts/gen_isa.sh b/es2panda/scripts/gen_isa.sh new file mode 100755 index 0000000000000000000000000000000000000000..28ab703f1b0856e7efe47de9712beceff7e0d30c --- /dev/null +++ b/es2panda/scripts/gen_isa.sh @@ -0,0 +1,52 @@ +#!/bin/bash +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e + +while getopts "g:t:a:o:d:r:h" arg +do + case "${arg}" in + "g") + GENERATOR=${OPTARG} + ;; + "t") + TEMPLATE=${OPTARG} + ;; + "a") + DATA=${OPTARG} + ;; + "o") + OUTPUT=${OPTARG} + ;; + "d") + OUTDIR=${OPTARG} + ;; + "r") + REQUIRE=${OPTARG} + ;; + "h") + echo "help" + ;; + ?) + echo "unkonw argument" + exit 1 + ;; + esac +done + +if [ ! -d ${OUTDIR} ]; then + mkdir -p ${OUTDIR} +fi +echo "${GENERATOR} --template ${TEMPLATE} --data ${DATA} --output ${OUTDIR}/${OUTPUT} --require ${REQUIRE}" +${GENERATOR} --template ${TEMPLATE} --data ${DATA} --output ${OUTDIR}/${OUTPUT} --require ${REQUIRE} diff --git a/es2panda/scripts/gen_keywords.sh b/es2panda/scripts/gen_keywords.sh new file mode 100755 index 0000000000000000000000000000000000000000..43f4069f464845de95f1f72ed85e44f8e22c908f --- /dev/null +++ b/es2panda/scripts/gen_keywords.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e + +while getopts "g:t:o:d:h" arg +do + case "${arg}" in + "g") + GENERATOR=${OPTARG} + ;; + "t") + TEMPLATE=${OPTARG} + ;; + "o") + OUTPUT=${OPTARG} + ;; + "d") + OUTDIR=${OPTARG} + ;; + "h") + echo "help" + ;; + ?) + echo "unkonw argument" + exit 1 + ;; + esac +done + +if [ ! -d ${OUTDIR} ]; then + mkdir -p ${OUTDIR} +fi + +ruby ${GENERATOR} ${TEMPLATE} ${OUTDIR}/${OUTPUT} diff --git a/es2panda/scripts/generate_js_bytecode.py b/es2panda/scripts/generate_js_bytecode.py new file mode 100755 index 0000000000000000000000000000000000000000..f3afc4dfc80bba611baf18c3a1627e661080be8d --- /dev/null +++ b/es2panda/scripts/generate_js_bytecode.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +# coding: utf-8 + +""" +Copyright (c) 2021 Huawei Device Co., Ltd. +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Description: Generate javascript byte code using es2abc +""" + +import os +import subprocess +import platform +import argparse + + +def parse_args(): + parser = argparse.ArgumentParser() + parser.add_argument('--src-js', + help = 'js source file') + parser.add_argument('--dst-file', + help = 'the converted target file') + parser.add_argument('--frontend-tool-path', + help = 'path of the frontend conversion tool') + parser.add_argument("--debug", action='store_true', + help='whether add debuginfo') + parser.add_argument("--module", action='store_true', + help='whether is module') + parser.add_argument("--commonjs", action='store_true', + help='whether is commonjs') + arguments = parser.parse_args() + return arguments + +def run_command(cmd, execution_path): + print(" ".join(cmd) + " | execution_path: " + execution_path) + proc = subprocess.Popen(cmd, cwd=execution_path) + proc.wait() + + +def gen_abc_info(input_arguments): + frontend_tool_path = input_arguments.frontend_tool_path + + (path, name) = os.path.split(frontend_tool_path) + + cmd = [os.path.join("./", name, "es2abc"), + '--output', input_arguments.dst_file, + input_arguments.src_js] + + if input_arguments.debug: + src_index = cmd.index(input_arguments.src_js) + cmd.insert(src_index, '--debug-info') + if input_arguments.module: + src_index = cmd.index(input_arguments.src_js) + cmd.insert(src_index, '--module') + if input_arguments.commonjs: + src_index = cmd.index(input_arguments.src_js) + # insert commonjs option to cmd later + run_command(cmd, path) + + +if __name__ == '__main__': + gen_abc_info(parse_args()) \ No newline at end of file diff --git a/es2panda/util/ustring.h b/es2panda/util/ustring.h index 1801234961d79bdf1a60ad245dffd650e0e2c007..41146010871fa6c5e2b6e95b927e217353af6abd 100644 --- a/es2panda/util/ustring.h +++ b/es2panda/util/ustring.h @@ -109,6 +109,11 @@ public: return StringView(std::string_view(sv_.data() + begin, end - begin)); } + constexpr size_t Find(const char *str) + { + return sv_.find(str); + } + static bool IsHighSurrogate(char32_t cp) { return (cp >= Constants::SURROGATE_HIGH_MIN && cp < Constants::SURROGATE_HIGH_MAX); diff --git a/ets_frontend_config.gni b/ets_frontend_config.gni new file mode 100644 index 0000000000000000000000000000000000000000..b4a3c1928a180a9b5d115404362e4f3fb50ec4b0 --- /dev/null +++ b/ets_frontend_config.gni @@ -0,0 +1,27 @@ +# Copyright (c) 2021 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +if (defined(ark_independent_build)) { + ets_frontend_root = "//ets_frontend" +} else { + build_root = "//build" + ets_frontend_root = "//arkcompiler/ets_frontend" +} + +toolchain_linux = "$build_root/toolchain/linux:clang_x64" +if (host_cpu == "arm64") { + toolchain_mac = "$build_root/toolchain/mac:clang_arm64" +} else { + toolchain_mac = "$build_root/toolchain/mac:clang_x64" +} +toolchain_win = "$build_root/toolchain/mingw:mingw_x86_64" diff --git a/test262/config.py b/test262/config.py index a2f738b18977d4f0c98a33985d7933d7e55865cb..f2a1d8836ed8243c3ccd41292389f2bcb88a3484 100755 --- a/test262/config.py +++ b/test262/config.py @@ -43,7 +43,6 @@ TEST_ES2021_DIR = os.path.join(DATA_DIR, "test_es2021") TEST_INTL_DIR = os.path.join(DATA_DIR, "test_intl") TEST_CI_DIR = os.path.join(DATA_DIR, "test_CI") -DEFAULT_ARK_FRONTEND_TOOL = os.path.join(ARK_DIR, "build", "src", "index.js") DEFAULT_ARK_TOOL = os.path.join(ARK_JS_RUNTIME_DIR, "ark_js_vm") DEFAULT_ARK_AOT_TOOL = os.path.join(ARK_JS_RUNTIME_DIR, "ark_aot_compiler") DEFAULT_LIBS_DIR = f"{ARK_DIR}:{ICUI_DIR}:{LLVM_DIR}:{ARK_JS_RUNTIME_DIR}" @@ -81,7 +80,14 @@ ARK_FRONTEND_LIST = [ "ts2panda", "es2panda" ] + +ARK_FRONTEND_BINARY_LIST = [ + os.path.join(ARK_DIR, "build", "src", "index.js"), + os.path.join(ARK_DIR, "es2abc") +] + DEFAULT_ARK_FRONTEND = ARK_FRONTEND_LIST[0] +DEFAULT_ARK_FRONTEND_BINARY = ARK_FRONTEND_BINARY_LIST[0] ARK_ARCH_LIST = [ "x64", @@ -90,3 +96,5 @@ ARK_ARCH_LIST = [ ] DEFAULT_ARK_ARCH = ARK_ARCH_LIST[0] +DEFAULT_OPT_LEVEL = 2 +DEFAULT_ES2ABC_THREAD_COUNT = 0 diff --git a/test262/es2021_tests.txt b/test262/es2021_tests.txt index da3af6dfd5659e29505e1ede7c7df376ad33a5c6..c467b241f54c9117143f5e5da77adcaae2878e05 100644 --- a/test262/es2021_tests.txt +++ b/test262/es2021_tests.txt @@ -354,6 +354,12 @@ built-ins/Promise/prototype/finally/this-value-then-poisoned.js built-ins/Promise/prototype/finally/this-value-then-throws.js built-ins/Promise/prototype/finally/this-value-thenable.js built-ins/Promise/prototype/finally/this-value-then-not-callable.js +built-ins/JSON/stringify/value-bigint.js +built-ins/JSON/stringify/value-bigint-cross-realm.js +built-ins/JSON/stringify/value-bigint-order.js +built-ins/JSON/stringify/value-bigint-replacer.js +built-ins/JSON/stringify/value-bigint-tojson.js +built-ins/JSON/stringify/value-bigint-tojson-receiver.js built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x003C.js built-ins/String/prototype/replaceAll/getSubstitution-0x0024-0x0027.js built-ins/String/prototype/replaceAll/getSubstitution-0x0024N.js diff --git a/test262/run_sunspider.py b/test262/run_sunspider.py index 73e6228c93d8669b54275c0e177ff111557908a9..f2802d8e9ce496b343169d14f4a2332b014b56a7 100755 --- a/test262/run_sunspider.py +++ b/test262/run_sunspider.py @@ -43,10 +43,6 @@ def parse_args(): default=DEFAULT_ARK_AOT_TOOL, required=False, help="ark's aot tool") - parser.add_argument('--ark-frontend-tool', - default=DEFAULT_ARK_FRONTEND_TOOL, - required=False, - help="ark frontend conversion tool") parser.add_argument("--libs-dir", default=DEFAULT_LIBS_DIR, required=False, @@ -59,6 +55,10 @@ def parse_args(): required=False, nargs='?', choices=ARK_FRONTEND_LIST, type=str, help="Choose one of them") + parser.add_argument('--ark-frontend-binary', + default=DEFAULT_ARK_FRONTEND_BINARY, + required=False, + help="ark frontend conversion binary tool") parser.add_argument('--module-list', required=True, help="module file list") @@ -71,6 +71,14 @@ def parse_args(): default=DEFAULT_ARK_ARCH, required=False, help="the root path for qemu-aarch64 or qemu-arm") + parser.add_argument('--opt-level', + default=DEFAULT_OPT_LEVEL, + required=False, + help="the opt level for es2abc") + parser.add_argument('--es2abc-thread-count', + default=DEFAULT_ES2ABC_THREAD_COUNT, + required=False, + help="the thread count for es2abc") arguments = parser.parse_args() return arguments @@ -79,10 +87,10 @@ ICU_PATH = f"--icu-data-path={CODE_ROOT}/third_party/icu/ohos_icu4j/data" if platform.system() == "Windows" : ICU_PATH = ICU_PATH.replace("/","\\") ARK_TOOL = DEFAULT_ARK_TOOL -ARK_FRONTEND_TOOL = DEFAULT_ARK_FRONTEND_TOOL LIBS_DIR = DEFAULT_LIBS_DIR ARK_AOT_TOOL = DEFAULT_ARK_AOT_TOOL ARK_FRONTEND = DEFAULT_ARK_FRONTEND +ARK_FRONTEND_BINARY = DEFAULT_ARK_FRONTEND_BINARY ARK_ARCH = DEFAULT_ARK_ARCH @@ -144,7 +152,7 @@ def exec_command(cmd_args, timeout=DEFAULT_TIMEOUT): def print_command(cmd_args): sys.stderr.write("\n") for arg in cmd_args: - sys.stderr.write(arg + " ") + sys.stderr.write("%s%s"%(arg, " ")) sys.stderr.write("\n") def run_command(cmd_args): @@ -152,7 +160,7 @@ def run_command(cmd_args): cmd = f"timeout {timeout} " for arg in cmd_args: cmd += f"{arg} " - return os.system(cmd) + return subprocess.run(cmd) class ArkProgram(): def __init__(self, args): @@ -160,15 +168,17 @@ class ArkProgram(): self.ark_tool = ARK_TOOL self.ark_aot = False self.ark_aot_tool = ARK_AOT_TOOL - self.ark_frontend_tool = ARK_FRONTEND_TOOL self.libs_dir = LIBS_DIR self.ark_frontend = ARK_FRONTEND + self.ark_frontend_binary = ARK_FRONTEND_BINARY self.module_list = [] self.js_file = "" self.module = False self.abc_file = "" self.arch = ARK_ARCH self.arch_root = "" + self.opt_level = DEFAULT_OPT_LEVEL + self.es2abc_thread_count = DEFAULT_ES2ABC_THREAD_COUNT def proce_parameters(self): if self.args.ark_tool: @@ -180,8 +190,8 @@ class ArkProgram(): if self.args.ark_aot_tool: self.ark_aot_tool = self.args.ark_aot_tool - if self.args.ark_frontend_tool: - self.ark_frontend_tool = self.args.ark_frontend_tool + if self.args.ark_frontend_binary: + self.ark_frontend_binary = self.args.ark_frontend_binary if self.args.libs_dir: self.libs_dir = self.args.libs_dir @@ -189,6 +199,12 @@ class ArkProgram(): if self.args.ark_frontend: self.ark_frontend = self.args.ark_frontend + if self.args.opt_level: + self.opt_level = self.args.opt_level + + if self.args.es2abc_thread_count: + self.es2abc_thread_count = self.args.es2abc_thread_count + self.module_list = self.args.module_list.splitlines() self.js_file = self.args.js_file @@ -205,21 +221,23 @@ class ArkProgram(): self.abc_file = out_file mod_opt_index = 0 cmd_args = [] - frontend_tool = self.ark_frontend_tool + frontend_tool = self.ark_frontend_binary if self.ark_frontend == ARK_FRONTEND_LIST[0]: mod_opt_index = 3 cmd_args = ['node', '--expose-gc', frontend_tool, js_file, '-o', out_file] + if file_name in self.module_list: + cmd_args.insert(mod_opt_index, "-m") + self.module = True elif self.ark_frontend == ARK_FRONTEND_LIST[1]: mod_opt_index = 1 - cmd_args = [frontend_tool, '-c', - '-e', 'js', '-o', out_file, '-i', js_file] - - if file_name in self.module_list: - cmd_args.insert(mod_opt_index, "-m") - self.module = True + cmd_args = [frontend_tool, '--opt-level=' + str(self.opt_level), + '--thread=' + str(self.es2abc_thread_count), '--output', out_file, js_file] + if file_name in self.module_list: + cmd_args.insert(mod_opt_index, "--module") + self.module = True if self.ark_aot: - os.system(f'''sed -i 's/;$262.destroy();/\/\/;$262.destroy();/g' {js_file}''') + subprocess.run(f'''sed -i 's/;$262.destroy();/\/\/;$262.destroy();/g' {js_file}''') if self.module: js_dir = os.path.dirname(js_file) for line in fileinput.input(js_file): @@ -295,7 +313,7 @@ class ArkProgram(): retcode = run_command(cmd_args) if retcode: - os.system(f'cp {self.js_file} {BASE_OUT_DIR}/../') + subprocess.run(f'cp {self.js_file} {BASE_OUT_DIR}/../') print_command(cmd_args) return retcode @@ -308,7 +326,7 @@ class ArkProgram(): elif platform.system() == "Linux" : os.environ["LD_LIBRARY_PATH"] = self.libs_dir else : - sys.exit(f" test262 on {platform.system()} not supported"); + sys.exit(f" test262 on {platform.system()} not supported"); file_name_pre = os.path.splitext(self.js_file)[0] cmd_args = [] if self.arch == ARK_ARCH_LIST[1]: diff --git a/test262/run_test262.py b/test262/run_test262.py index f5dae7b0187e7878ffa59d0eb570c7ba5dde651c..8b6aac20d9227b2c079fa44a933167e548cc3a60 100755 --- a/test262/run_test262.py +++ b/test262/run_test262.py @@ -27,7 +27,7 @@ import sys import subprocess from multiprocessing import Pool import platform -from utils import * +from utils import * from config import * @@ -78,13 +78,13 @@ def parse_args(): help="Run test262 with aot") parser.add_argument('--ark-aot-tool', help="ark's aot tool") - parser.add_argument('--ark-frontend-tool', - help="ark frontend conversion tool") parser.add_argument("--libs-dir", help="The path collection of dependent so has been divided by':'") parser.add_argument('--ark-frontend', nargs='?', choices=ARK_FRONTEND_LIST, type=str, help="Choose one of them") + parser.add_argument('--ark-frontend-binary', + help="ark frontend conversion binary tool") parser.add_argument('--ark-arch', default=DEFAULT_ARK_ARCH, nargs='?', choices=ARK_ARCH_LIST, type=str, @@ -92,6 +92,12 @@ def parse_args(): parser.add_argument('--ark-arch-root', default=DEFAULT_ARK_ARCH, help="the root path for qemu-aarch64 or qemu-arm") + parser.add_argument('--opt-level', + default=DEFAULT_OPT_LEVEL, + help="the opt level for es2abc") + parser.add_argument('--es2abc-thread-count', + default=DEFAULT_ES2ABC_THREAD_COUNT, + help="the thread count for es2abc") return parser.parse_args() @@ -113,15 +119,15 @@ def excuting_npm_install(args): if args.ark_frontend: ark_frontend = args.ark_frontend - if ark_frontend != DEFAULT_ARK_FRONTEND: + if ark_frontend != ARK_FRONTEND_LIST[0]: return - ark_frontend_tool = os.path.join(DEFAULT_ARK_FRONTEND_TOOL) - if args.ark_frontend_tool: - ark_frontend_tool = os.path.join(args.ark_frontend_tool) + ark_frontend_binary = os.path.join(ARK_FRONTEND_BINARY_LIST[0]) + if args.ark_frontend_binary: + ark_frontend_binary = os.path.join(args.ark_frontend_binary) ts2abc_build_dir = os.path.join(os.path.dirname( - os.path.realpath(ark_frontend_tool)), "..") + os.path.realpath(ark_frontend_binary)), "..") if os.path.exists(os.path.join(ts2abc_build_dir, "package.json")): npm_install(ts2abc_build_dir) @@ -337,7 +343,7 @@ class TestPrepare(): if self.args.intl: files = self.get_tests_from_file(INTL_LIST_FILE) return files - + def prepare_es2015_tests(self): files = [] files = self.collect_tests() @@ -473,11 +479,13 @@ def get_host_args(args, host_type): host_args = "" ark_tool = DEFAULT_ARK_TOOL ark_aot_tool = DEFAULT_ARK_AOT_TOOL - ark_frontend_tool = DEFAULT_ARK_FRONTEND_TOOL libs_dir = DEFAULT_LIBS_DIR ark_frontend = DEFAULT_ARK_FRONTEND + ark_frontend_binary = DEFAULT_ARK_FRONTEND_BINARY ark_arch = DEFAULT_ARK_ARCH module_list = '' + opt_level = DEFAULT_OPT_LEVEL + es2abc_thread_count = DEFAULT_ES2ABC_THREAD_COUNT with open(MODULE_FILES_LIST) as fopen: module_list = fopen.read() @@ -490,25 +498,33 @@ def get_host_args(args, host_type): if args.ark_aot_tool: ark_aot_tool = args.ark_aot_tool - if args.ark_frontend_tool: - ark_frontend_tool = args.ark_frontend_tool - if args.libs_dir: libs_dir = args.libs_dir if args.ark_frontend: ark_frontend = args.ark_frontend + if args.ark_frontend_binary: + ark_frontend_binary = args.ark_frontend_binary + + if args.opt_level: + opt_level = args.opt_level + + if args.es2abc_thread_count: + es2abc_thread_count = args.es2abc_thread_count + if host_type == DEFAULT_HOST_TYPE: host_args = f"-B test262/run_sunspider.py " host_args += f"--ark-tool={ark_tool} " if args.ark_aot: host_args += f"--ark-aot " host_args += f"--ark-aot-tool={ark_aot_tool} " - host_args += f"--ark-frontend-tool={ark_frontend_tool} " host_args += f"--libs-dir={libs_dir} " host_args += f"--ark-frontend={ark_frontend} " + host_args += f"--ark-frontend-binary={ark_frontend_binary} " host_args += f"--module-list={module_list} " + host_args += f"--opt-level={opt_level} " + host_args += f"--es2abc-thread-count={es2abc_thread_count} " if args.ark_arch != ark_arch: host_args += f"--ark-arch={args.ark_arch} " diff --git a/testTs/config.py b/testTs/config.py index 3412291c9dfae66f603737a3f758348a72823b06..14ec255458a172911fbceae19250d417407903cc 100644 --- a/testTs/config.py +++ b/testTs/config.py @@ -34,7 +34,7 @@ IMPORT_FILE_PATH = os.path.join("testTs", "import_tests.json") CUR_FILE_DIR = os.path.dirname(__file__) CODE_ROOT = os.path.abspath(os.path.join(CUR_FILE_DIR, "../../..")) ARK_DIR = f"{CODE_ROOT}/out/hispark_taurus/clang_x64/ark/ark" -WORK_PATH = f'{CODE_ROOT}/ark/ts2abc' +WORK_PATH = f'{CODE_ROOT}/arkcompiler/ets_frontend' DEFAULT_ARK_FRONTEND_TOOL = os.path.join(ARK_DIR, "build", "src", "index.js") diff --git a/ts2panda/BUILD.gn b/ts2panda/BUILD.gn index 6ef40ce0dfc33e0efa0616a46ea16d355b4095ea..815bcb1def6f07baca8e3dd1e441d8fbd364e5ce 100755 --- a/ts2panda/BUILD.gn +++ b/ts2panda/BUILD.gn @@ -11,8 +11,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -import("//ark/runtime_core/ark_config.gni") -import("//ark/ts2abc/ts2panda/ts2abc_config.gni") +import("//arkcompiler/ets_frontend/ts2panda/ts2abc_config.gni") +import("//arkcompiler/runtime_core/ark_config.gni") import("//build/config/clang/clang.gni") import("//build/ohos.gni") @@ -223,21 +223,21 @@ group("ark_ts2abc_build") { deps = [] if (host_os != "mac") { deps += [ - "${ts2abc_root}:ts2abc_build(${buildtool_linux})", - "${ts2abc_root}:ts2abc_build_ets(${buildtool_linux})", + "${ts2abc_root}:ts2abc_build(${toolchain_linux})", + "${ts2abc_root}:ts2abc_build_ets(${toolchain_linux})", ] } else { deps += [ - "${ts2abc_root}:ts2abc_build_mac(${buildtool_mac})", - "${ts2abc_root}:ts2abc_build_mac_ets(${buildtool_mac})", + "${ts2abc_root}:ts2abc_build_mac(${toolchain_mac})", + "${ts2abc_root}:ts2abc_build_mac_ets(${toolchain_mac})", ] } } group("ark_ts2abc_build_win") { deps = [ - "${ts2abc_root}:ts2abc_build_win(${buildtool_win})", - "${ts2abc_root}:ts2abc_build_win_ets(${buildtool_win})", + "${ts2abc_root}:ts2abc_build_win(${toolchain_win})", + "${ts2abc_root}:ts2abc_build_win_ets(${toolchain_win})", ] } @@ -252,13 +252,13 @@ ohos_copy("copy_ts2abc_tests") { group("ts2abc_unittests") { if (host_os == "linux") { testonly = true - deps = [ "tests:ts2abc_tests(${buildtool_linux})" ] + deps = [ "tests:ts2abc_tests(${toolchain_linux})" ] } } group("ts2abc_type_adapter_unit_tests") { if (host_os == "linux") { testonly = true - deps = [ "${ts2abc_root}/ts2abc/tests/type_adapter_test:ts2abc_type_adapter_unit_tests(${buildtool_linux})" ] + deps = [ "${ts2abc_root}/ts2abc/tests/type_adapter_test:ts2abc_type_adapter_unit_tests(${toolchain_linux})" ] } } diff --git a/ts2panda/scripts/npm-install.sh b/ts2panda/scripts/npm-install.sh index f669e0589b6bd7ff918f4f9903fa33142cfd5123..479a7c40a705e71c07cc6e7573d78911bc8c43e6 100755 --- a/ts2panda/scripts/npm-install.sh +++ b/ts2panda/scripts/npm-install.sh @@ -37,4 +37,4 @@ if [ -d "${code_dir}/prebuilts/build-tools/common/ts2abc" ]; then fi mkdir -p ${code_dir}/prebuilts/build-tools/common/ts2abc -/bin/cp -rf ${code_dir}/ark/ts2abc/ts2panda/node_modules ${code_dir}/prebuilts/build-tools/common/ts2abc/ || echo "skip copying due to other thread" +/bin/cp -rf ${code_dir}/arkcompiler/ets_frontend/ts2panda/node_modules ${code_dir}/prebuilts/build-tools/common/ts2abc/ || echo "skip copying due to other thread" diff --git a/ts2panda/scripts/run.py b/ts2panda/scripts/run.py index c405cf71cefdfa34f01ef1caf01463efc79fa7dd..039c92e5847a78ace2148187364adbf1f42f6eb5 100755 --- a/ts2panda/scripts/run.py +++ b/ts2panda/scripts/run.py @@ -110,6 +110,8 @@ def npm_run_build(options): cmd = [webpack, '--config', 'webpack.config.js', '--progress', '--env', 'buildMode={}'.format(options.buildMode)] + if os.getenv("NO_DEVTOOL"): + cmd += ['--no-devtool'] run_command(cmd, options.dist_dir) if plat_form == "linux": per_platform_config(options, "build") diff --git a/ts2panda/scripts/run_tests.py b/ts2panda/scripts/run_tests.py index ed38d57f9980f592e7387d8c8f3a85dfe60ee60a..5ef38c453a5fc003719096a978a7f72ccf0a6210 100755 --- a/ts2panda/scripts/run_tests.py +++ b/ts2panda/scripts/run_tests.py @@ -27,7 +27,7 @@ CUR_FILE_DIR = os.path.dirname(__file__) TS2PANDA_DIR = os.path.abspath(os.path.join(CUR_FILE_DIR, "..")) CODE_ROOT = os.path.abspath(os.path.join(TS2PANDA_DIR, "../../..")) DEFAULT_TARGET_DIR = os.path.join( - CODE_ROOT, "out/hispark_taurus/clang_x64/obj/ark/ts2abc/ts2panda") + CODE_ROOT, "out/hispark_taurus/clang_x64/obj/arkcompiler/ets_frontend/ts2panda") DEFAULT_NODE_MODULE = os.path.join( CODE_ROOT, "prebuilts/build-tools/common/ts2abc/node_modules") diff --git a/ts2panda/src/cmdOptions.ts b/ts2panda/src/cmdOptions.ts index 4e108670db4789dfb4ba0e5bde0af7bc345a089b..bd302d1ea3f0f86c426a2a26618d598f7a637684 100644 --- a/ts2panda/src/cmdOptions.ts +++ b/ts2panda/src/cmdOptions.ts @@ -34,7 +34,7 @@ const ts2pandaOptions = [ { name: 'timeout', alias: 't', type: Number, defaultValue: 0, description: "js to abc timeout threshold(unit: seconds)." }, { name: 'opt-log-level', type: String, defaultValue: "error", description: "specifie optimizer log level. Possible values: ['debug', 'info', 'error', 'fatal']" }, { - name: 'opt-level', type: Number, defaultValue: 1, description: "Optimization level. Possible values: [0, 1, 2]. Default: 0\n 0: no optimizations\n \ + name: 'opt-level', type: Number, defaultValue: 2, description: "Optimization level. Possible values: [0, 1, 2]. Default: 0\n 0: no optimizations\n \ 1: basic bytecode optimizations, including valueNumber, lowering, constantResolver, regAccAllocator\n \ 2: other bytecode optimizations, unimplemented yet"}, { name: 'help', alias: 'h', type: Boolean, description: "Show usage guide." }, @@ -45,7 +45,6 @@ const ts2pandaOptions = [ { name: 'dts-type-record', alias: 'q', type: Boolean, defaultValue: false, description: "Record type info for .d.ts files. Default: false" }, { name: 'debug-type', alias: 'g', type: Boolean, defaultValue: false, description: "Print type-related log. Default: false" }, { name: 'output-type', type: Boolean, defaultValue: false, description: "set output type."}, - { name: 'enable-typeinfo', type: Boolean, defaultValue: false, description: "Enable typeinfo of pairs of instruction orders and types" }, { name: 'display-typeinfo', type: Boolean, defaultValue: false, description: "Display typeinfo of pairs of instruction orders and types when enable-typeinfo is true" } ] @@ -55,13 +54,6 @@ export class CmdOptions { private static parsedResult: ts.ParsedCommandLine; private static options: commandLineArgs.CommandLineOptions; - static getEnableTypeinfo(): boolean { - if (!this.options) { - return false; - } - return this.options["enable-typeinfo"]; - } - static getDisplayTypeinfo(): boolean { if (!this.options) { return false; diff --git a/ts2panda/src/compiler.ts b/ts2panda/src/compiler.ts index 59cd1d776e4b8f12eee2ec123589307599e8cb86..fcc8536e3665dbe5dce8a7feb01cddd381d9a792 100644 --- a/ts2panda/src/compiler.ts +++ b/ts2panda/src/compiler.ts @@ -1210,7 +1210,7 @@ export class Compiler { // lvalue var = acc +/- 1 lref.setValue(); // acc = operand_old - pandaGen.toNumber(expr, operandReg); + pandaGen.toNumeric(expr, operandReg); pandaGen.freeTemps(operandReg); } diff --git a/ts2panda/src/ignoreSyntaxError.ts b/ts2panda/src/ignoreSyntaxError.ts new file mode 100644 index 0000000000000000000000000000000000000000..de947ee61b9e0777f6736c5c128aaddf7db6c1d0 --- /dev/null +++ b/ts2panda/src/ignoreSyntaxError.ts @@ -0,0 +1,4 @@ +const BigInt_literals_are_not_available_when_targeting_lower_than_ES2020: number = 2737; +export const IGNORE_ERROR_CODE: number[] = [ + BigInt_literals_are_not_available_when_targeting_lower_than_ES2020 +]; \ No newline at end of file diff --git a/ts2panda/src/index.ts b/ts2panda/src/index.ts index 866827b25dd93dc2907a5b0c25728ea2c2624410..e1b34e285c1ffe9fa790adb63fb0443608df4e23 100644 --- a/ts2panda/src/index.ts +++ b/ts2panda/src/index.ts @@ -24,6 +24,7 @@ import { LOGE } from "./log"; import { setGlobalDeclare, setGlobalStrict } from "./strictMode"; import { TypeChecker } from "./typeChecker"; import { setPos, isBase64Str, transformCommonjsModule } from "./base/util"; +import { IGNORE_ERROR_CODE } from './ignoreSyntaxError' function checkIsGlobalDeclaration(sourceFile: ts.SourceFile) { for (let statement of sourceFile.statements) { @@ -65,6 +66,10 @@ function main(fileNames: string[], options: ts.CompilerOptions) { } } + if (checkDiagnosticsError(program)) { + return; + } + let emitResult = program.emit( undefined, undefined, @@ -120,6 +125,10 @@ function main(fileNames: string[], options: ts.CompilerOptions) { .concat(emitResult.diagnostics); allDiagnostics.forEach(diagnostic => { + let ignoerErrorSet = new Set(IGNORE_ERROR_CODE); + if (ignoerErrorSet.has(diagnostic.code)) { + return; + } diag.printDiagnostic(diagnostic); }); } @@ -245,12 +254,29 @@ function keepWatchingFiles(filePath: string, parsed: ts.ParsedCommandLine | unde }); } +function checkDiagnosticsError(program: ts.Program) { + let diagnosticsFlag = false; + let allDiagnostics = ts + .getPreEmitDiagnostics(program); + allDiagnostics.forEach(diagnostic => { + let ignoerErrorSet = new Set(IGNORE_ERROR_CODE); + if (ignoerErrorSet.has(diagnostic.code)) { + diagnosticsFlag = false; + return; + } + diagnosticsFlag = true; + diag.printDiagnostic(diagnostic); + }); + + return diagnosticsFlag; +} + namespace Compiler { export namespace Options { export let Default: ts.CompilerOptions = { outDir: "../tmp/build", allowJs: true, - noEmitOnError: true, + noEmitOnError: false, noImplicitAny: true, target: ts.ScriptTarget.ES2017, module: ts.ModuleKind.ES2015, diff --git a/ts2panda/src/pandagen.ts b/ts2panda/src/pandagen.ts index 0db314b6bdbce401e9834dfa2bf3396a3089eed1..65834994a59213dc421946a26277d79324a86a13 100644 --- a/ts2panda/src/pandagen.ts +++ b/ts2panda/src/pandagen.ts @@ -163,6 +163,7 @@ import { EcmaSub2dyn, EcmaSuspendgenerator, EcmaTonumber, + EcmaTonumeric, EcmaTypeofdyn, EcmaXor2dyn, Imm, @@ -1002,6 +1003,10 @@ export class PandaGen { this.add(node, new EcmaTonumber(arg)); } + toNumeric(node: ts.Node, arg: VReg) { + this.add(node, new EcmaTonumeric(arg)); + } + createGeneratorObj(node: ts.Node, funcObj: VReg) { this.add(node, new EcmaCreategeneratorobj(funcObj)); } diff --git a/ts2panda/src/scope.ts b/ts2panda/src/scope.ts index 24e7ebb4689801e9859e3e29c7567321025b4613..3c8b01a1c502da35fbf26e29f44ea11e277d39f5 100644 --- a/ts2panda/src/scope.ts +++ b/ts2panda/src/scope.ts @@ -420,7 +420,7 @@ export class ModuleScope extends VariableScope { setExportDecl(exportedLocalName: string) { let decl = this.getDecl(exportedLocalName); - if (decl) { + if (decl && decl.isModule != ModuleVarKind.IMPORTED) { decl.isModule = ModuleVarKind.EXPORTED; } } diff --git a/ts2panda/src/statement/classStatement.ts b/ts2panda/src/statement/classStatement.ts index ed9498afbf8359bcb57673c151c9b11f60caad3e..7bbe9b877020ed634ea40123d38c8ffb2b68a124 100644 --- a/ts2panda/src/statement/classStatement.ts +++ b/ts2panda/src/statement/classStatement.ts @@ -137,8 +137,12 @@ export function compileClassDeclaration(compiler: Compiler, stmt: ts.ClassLikeDe pandaGen.stClassToGlobalRecord(stmt, className); } else { let classInfo = classScope.find(className); - (classInfo.v).initialize(); - pandaGen.storeAccToLexEnv(stmt, classInfo.scope!, classInfo.level, classInfo.v!, true); + (classInfo.v).initialize(); + if (classInfo.v instanceof ModuleVariable) { + pandaGen.storeModuleVariable(stmt, className); + } else { + pandaGen.storeAccToLexEnv(stmt, classInfo.scope!, classInfo.level, classInfo.v!, true); + } } } else { // throw SyntaxError in SyntaxChecker @@ -416,10 +420,11 @@ function loadCtorObj(node: ts.CallExpression, compiler: Compiler) { return; } - let nearestFuncScope = recorder.getScopeOfNode(nearestFunc); - if (!nearestFuncScope) { - return; - } + // TODO the design needs to be reconsidered + // let nearestFuncScope = recorder.getScopeOfNode(nearestFunc); + // if (!nearestFuncScope) { + // return; + // } if (ts.isConstructorDeclaration(nearestFunc)) { pandaGen.loadAccumulator(node, getVregisterCache(pandaGen, CacheList.FUNC)); diff --git a/ts2panda/src/ts2panda.ts b/ts2panda/src/ts2panda.ts index 52c1823865835a38e28d28a55d222b7401e51aeb..39c62abb7aad19b20d68123d04af339b8e22db65 100644 --- a/ts2panda/src/ts2panda.ts +++ b/ts2panda/src/ts2panda.ts @@ -195,7 +195,6 @@ export class Ts2Panda { "log_enabled": CmdOptions.isEnableDebugLog(), "opt_level": CmdOptions.getOptLevel(), "opt_log_level": CmdOptions.getOptLogLevel(), - "enable_typeinfo": CmdOptions.getEnableTypeinfo(), "display_typeinfo": CmdOptions.getDisplayTypeinfo() }; let jsonOpt = JSON.stringify(options, null, 2); diff --git a/ts2panda/tests/BUILD.gn b/ts2panda/tests/BUILD.gn index a08b272f0f1028510769f297a77f76df6ba42b52..1da6e41ffb2c63c016baa55517c34c55c9c664fe 100644 --- a/ts2panda/tests/BUILD.gn +++ b/ts2panda/tests/BUILD.gn @@ -11,7 +11,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -import("//ark/ts2abc/ts2panda/ts2abc_config.gni") +import("//arkcompiler/ets_frontend/ts2panda/ts2abc_config.gni") import("//build/config/clang/clang.gni") import("//build/ohos.gni") @@ -28,12 +28,12 @@ action("ts2abc_tests") { rebase_path("${node_modules}"), ] - if (host_toolchain == buildtool_linux) { + if (host_toolchain == toolchain_linux) { args += [ "--platform", "linux", ] - } else if (host_toolchain == buildtool_mac) { + } else if (host_toolchain == toolchain_mac) { args += [ "--platform", "mac", diff --git a/ts2panda/tests/esmodule.test.ts b/ts2panda/tests/esmodule.test.ts new file mode 100644 index 0000000000000000000000000000000000000000..e28b9b6db430b7b7535d080121fb5d35d76fe466 --- /dev/null +++ b/ts2panda/tests/esmodule.test.ts @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + expect +} from 'chai'; +import 'mocha'; +import { checkInstructions, SnippetCompiler } from "./utils/base"; +import { + EcmaDefineclasswithbuffer, + EcmaLdmodulevar, + EcmaReturnundefined, + EcmaStmodulevar, + EcmaThrowundefinedifhole, + Imm, + LdaDyn, + LdaStr, + MovDyn, + StaDyn, + VReg +} from "../src/irnodes"; +import { CmdOptions } from '../src/cmdOptions'; + + +describe("ExportDeclaration", function () { + + it("exportClassTest ", function() { + CmdOptions.isModules = () => {return true}; + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile(`class C {}; export {C}`); + CmdOptions.isModules = () => {return false}; + let funcMainInsns = snippetCompiler.getGlobalInsns(); + let classReg = new VReg(); + let expected = [ + new MovDyn(new VReg(), new VReg()), + new EcmaDefineclasswithbuffer("#1#C", new Imm(0), new Imm(0), new VReg(), new VReg()), + new StaDyn(classReg), + new LdaDyn(classReg), + new EcmaStmodulevar('C'), + new EcmaReturnundefined(), + ]; + expect(checkInstructions(funcMainInsns, expected)).to.be.true; + }); + + it("Re-exportImportVarTest ", function() { + CmdOptions.isModules = () => {return true}; + let snippetCompiler = new SnippetCompiler(); + snippetCompiler.compile(`import a from 'test.js'; let v = a; export {a};`); + CmdOptions.isModules = () => {return false}; + let funcMainInsns = snippetCompiler.getGlobalInsns(); + let a = new VReg(); + let v = new VReg(); + let name = new VReg(); + let expected = [ + new EcmaLdmodulevar("a", new Imm(0)), + new StaDyn(a), + new LdaStr("a"), + new StaDyn(name), + new EcmaThrowundefinedifhole(a, name), + new LdaDyn(a), + new StaDyn(v), + new EcmaReturnundefined(), + ]; + expect(checkInstructions(funcMainInsns, expected)).to.be.true; + }); +}); \ No newline at end of file diff --git a/ts2panda/tests/expression/cmpBinary.test.ts b/ts2panda/tests/expression/cmpBinary.test.ts index 55ad541245f8bf01c18086dab0ed541b8c0f5b3f..9d9c6dd63575ea48064238fea5bdf9c58eae26dc 100644 --- a/ts2panda/tests/expression/cmpBinary.test.ts +++ b/ts2panda/tests/expression/cmpBinary.test.ts @@ -33,7 +33,7 @@ import { EcmaStlettoglobalrecord, EcmaStricteqdyn, EcmaStrictnoteqdyn, - EcmaTonumber, + EcmaTonumeric, EcmaTryldglobalbyname, EcmaTrystglobalbyname, EcmaXor2dyn, @@ -295,7 +295,7 @@ describe("CmpBinaryOperators", function () { new StaDyn(lhs), new EcmaIncdyn(lhs), new EcmaTrystglobalbyname('x'), - new EcmaTonumber(variable), + new EcmaTonumeric(variable), new StaDyn(rhs), new EcmaTryldglobalbyname('x'), new EcmaTrystglobalbyname('x'), diff --git a/ts2panda/tests/expression/postfixOperations.test.ts b/ts2panda/tests/expression/postfixOperations.test.ts index 355649dc9c7d26a9db246a38ecbe9c54dead2e39..fdd7ad6d1c04cb478ee9290bd367c9eaddcc845a 100644 --- a/ts2panda/tests/expression/postfixOperations.test.ts +++ b/ts2panda/tests/expression/postfixOperations.test.ts @@ -22,7 +22,7 @@ import { EcmaIncdyn, EcmaReturnundefined, EcmaStlettoglobalrecord, - EcmaTonumber, + EcmaTonumeric, EcmaTryldglobalbyname, EcmaTrystglobalbyname, Imm, @@ -45,7 +45,7 @@ describe("PostfixOperationsTest", function () { new StaDyn(temp), new EcmaIncdyn(temp), new EcmaTrystglobalbyname('i'), - new EcmaTonumber(i), + new EcmaTonumeric(i), new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; @@ -62,7 +62,7 @@ describe("PostfixOperationsTest", function () { new StaDyn(temp), new EcmaDecdyn(temp), new EcmaTrystglobalbyname('i'), - new EcmaTonumber(i), + new EcmaTonumeric(i), new EcmaReturnundefined() ]; expect(checkInstructions(insns, expected)).to.be.true; diff --git a/ts2panda/tests/lexenv.test.ts b/ts2panda/tests/lexenv.test.ts index c54daff6d00751d077d620e81c2db47364e8a815..a2180a6a1511f1bc8197ec3c4b22298636f52c9a 100644 --- a/ts2panda/tests/lexenv.test.ts +++ b/ts2panda/tests/lexenv.test.ts @@ -32,7 +32,7 @@ import { EcmaStlexvardyn, EcmaThrowconstassignment, EcmaThrowundefinedifhole, - EcmaTonumber, + EcmaTonumeric, EcmaTrystglobalbyname, Imm, IRNode, @@ -520,7 +520,7 @@ describe("lexenv-compile-testcase in lexenv.test.ts", function () { new EcmaIncdyn(new VReg()), new StaDyn(new VReg()), ...MicroStoreLexVar(1, 0), - new EcmaTonumber(new VReg()), // this is redundant load varialbe + new EcmaTonumeric(new VReg()), // this is redundant load varialbe ...MicroLoadLexVar(1, 0), new StaDyn(new VReg), ...MicroLoadLexVar(1, 1), diff --git a/ts2panda/tests/statements/for.test.ts b/ts2panda/tests/statements/for.test.ts index de8617947f7084aafdefbd1defb8b9dc550d820d..47bfce8d474592af88a61a45ad9f402f01c0e100 100644 --- a/ts2panda/tests/statements/for.test.ts +++ b/ts2panda/tests/statements/for.test.ts @@ -21,7 +21,7 @@ import { EcmaIncdyn, EcmaLessdyn, EcmaReturnundefined, - EcmaTonumber, + EcmaTonumeric, Imm, Jeqz, Jmp, @@ -228,7 +228,7 @@ describe("LoopWithLabelTests", function () { new StaDyn(j), new EcmaIncdyn(j), new StaDyn(j), - new EcmaTonumber(j), + new EcmaTonumeric(j), // jump to the loop header new Jmp(labelPre1), labelPost1, @@ -299,7 +299,7 @@ describe("LoopWithLabelTests", function () { new StaDyn(j), new EcmaIncdyn(j), new StaDyn(j), - new EcmaTonumber(j), + new EcmaTonumeric(j), // jump to the loop header new Jmp(labelPre1), labelPost1, diff --git a/ts2panda/tests/watch_expression/addWatch.test.ts b/ts2panda/tests/watch_expression/addWatch.test.ts index 7eacad422c8e907f5a3cd0b631a78cdf3e967afd..53ccee36959bc3f8a2227104b964e161407d4731 100644 --- a/ts2panda/tests/watch_expression/addWatch.test.ts +++ b/ts2panda/tests/watch_expression/addWatch.test.ts @@ -48,7 +48,7 @@ import { EcmaStricteqdyn, EcmaSuspendgenerator, EcmaThrowdyn, - EcmaTonumber, + EcmaTonumeric, EcmaTypeofdyn, FldaiDyn, Imm, @@ -661,7 +661,7 @@ describe("WatchExpressions", function () { new LdaStr('a'), new StaDyn(new VReg()), new EcmaCallargs2dyn(new VReg(), new VReg(), new VReg()), - new EcmaTonumber(new VReg()), + new EcmaTonumeric(new VReg()), new ReturnDyn() ]; diff --git a/ts2panda/ts2abc/BUILD.gn b/ts2panda/ts2abc/BUILD.gn index 54dffea6511fd2de85ee49deb71abc0771f2f7ff..7e723caf01bfcc095669284ce680668e04f63a47 100755 --- a/ts2panda/ts2abc/BUILD.gn +++ b/ts2panda/ts2abc/BUILD.gn @@ -12,7 +12,7 @@ # limitations under the License. if (!defined(ark_independent_build)) { - import("//ark/runtime_core/ark_config.gni") + import("//arkcompiler/runtime_core/ark_config.gni") import("//build/ohos.gni") } else { import("//runtime_core/ark_config.gni") diff --git a/ts2panda/ts2abc/tests/BUILD.gn b/ts2panda/ts2abc/tests/BUILD.gn index f5b42a5d9d87ee5d33459eedb2851f4bce7393cc..0e580974779cd495834227aff75201e99631ae12 100644 --- a/ts2panda/ts2abc/tests/BUILD.gn +++ b/ts2panda/ts2abc/tests/BUILD.gn @@ -11,8 +11,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -import("//ark/runtime_core/ark_config.gni") -import("//ark/ts2abc/ts2panda/ts2abc_config.gni") +import("//arkcompiler/ets_frontend/ts2panda/ts2abc_config.gni") +import("//arkcompiler/runtime_core/ark_config.gni") # ts2abc_unittest_action("DebugLogTest") { # sources = [ "debuglog_test.cpp" ] diff --git a/ts2panda/ts2abc/tests/type_adapter_test/BUILD.gn b/ts2panda/ts2abc/tests/type_adapter_test/BUILD.gn index 117b88df4cddec4b958b26c10857c36e40d4614a..cf9904458cde61776b5c6c59db4e39db9cbc8681 100644 --- a/ts2panda/ts2abc/tests/type_adapter_test/BUILD.gn +++ b/ts2panda/ts2abc/tests/type_adapter_test/BUILD.gn @@ -11,16 +11,16 @@ # See the License for the specific language governing permissions and # limitations under the License. -import("//ark/runtime_core/ark_config.gni") -import("//ark/ts2abc/ts2panda/ts2abc_config.gni") +import("//arkcompiler/ets_frontend/ts2panda/ts2abc_config.gni") +import("//arkcompiler/runtime_core/ark_config.gni") ohos_executable("ts2abc_type_adapter_unit_tests") { sources = [ - "//ark/ts2abc/ts2panda/ts2abc/type_adapter.cpp", + "//arkcompiler/ets_frontend/ts2panda/ts2abc/type_adapter.cpp", "type_adapter_test.cpp", ] - configs = [ "//ark/ts2abc/ts2panda/ts2abc:ts2abc_config" ] + configs = [ "//arkcompiler/ets_frontend/ts2panda/ts2abc:ts2abc_config" ] cflags = [ "-Wno-c++20-designator", diff --git a/ts2panda/ts2abc/tests/type_adapter_test/type_adapter_test.cpp b/ts2panda/ts2abc/tests/type_adapter_test/type_adapter_test.cpp index 4e8bf2f9a2bc80c2d4682405b9a7af9466a17dd5..9f989d125d29469b75932608015618dce95b5ed4 100644 --- a/ts2panda/ts2abc/tests/type_adapter_test/type_adapter_test.cpp +++ b/ts2panda/ts2abc/tests/type_adapter_test/type_adapter_test.cpp @@ -100,7 +100,7 @@ void TypeAdapterTest::TestVariablesArgsType() const panda::pandasm::Parser p; auto res = p.Parse(source); auto &program = res.Value(); - auto it = program.function_table.find("foo"); + auto it = program.function_table.find("foo:(any,any)"); TestAssertNotEqual(it, program.function_table.end()); auto &foo = it->second; diff --git a/ts2panda/ts2abc/ts2abc.cpp b/ts2panda/ts2abc/ts2abc.cpp index f66e50ce9f674b76c53e2e5425e966c79f8519ee..5f79472eaa201bda3dec39c404d4ada15249b2ef 100644 --- a/ts2panda/ts2abc/ts2abc.cpp +++ b/ts2panda/ts2abc/ts2abc.cpp @@ -900,14 +900,6 @@ static void ParseOptLevel(const Json::Value &rootValue) } } -static void ParseEnableTypeinfo(const Json::Value &rootValue) -{ - Logd("-----------------parse enable_typeinfo-----------------"); - if (rootValue.isMember("enable_typeinfo") && rootValue["enable_typeinfo"].isBool()) { - g_enableTypeinfo = rootValue["enable_typeinfo"].asBool(); - } -} - static void ParseDisplayTypeinfo(const Json::Value &rootValue) { Logd("-----------------parse enable_typeinfo-----------------"); @@ -944,7 +936,6 @@ static void ParseOptions(const Json::Value &rootValue, panda::pandasm::Program & ParseLogEnable(rootValue); ParseDebugMode(rootValue); ParseOptLevel(rootValue); - ParseEnableTypeinfo(rootValue); ParseDisplayTypeinfo(rootValue); ParseOptLogLevel(rootValue); } @@ -1318,18 +1309,20 @@ bool GenerateProgram([[maybe_unused]] const std::string &data, const std::string Logd("parsing done, calling pandasm\n"); - if (g_enableTypeinfo) { - TypeAdapter ada(g_displayTypeinfo); - ada.AdaptTypeForProgram(&prog); - } + TypeAdapter ada(g_displayTypeinfo); + ada.AdaptTypeForProgram(&prog); #ifdef ENABLE_BYTECODE_OPT if (g_optLevel != static_cast(OptLevel::O_LEVEL0) || optLevel != static_cast(OptLevel::O_LEVEL0)) { optLogLevel = (optLogLevel != "error") ? optLogLevel : g_optLogLevel; - const uint32_t componentMask = panda::Logger::Component::CLASS2PANDA | panda::Logger::Component::ASSEMBLER | - panda::Logger::Component::BYTECODE_OPTIMIZER | panda::Logger::Component::COMPILER; - panda::Logger::InitializeStdLogging(panda::Logger::LevelFromString(optLogLevel), componentMask); + if (g_optLogLevel != "error") { + panda::Logger::ComponentMask mask; + mask.set(panda::Logger::Component::ASSEMBLER); + mask.set(panda::Logger::Component::BYTECODE_OPTIMIZER); + mask.set(panda::Logger::Component::COMPILER); + panda::Logger::InitializeStdLogging(panda::Logger::LevelFromString(optLogLevel), mask); + } bool emitDebugInfo = true; std::map stat; diff --git a/ts2panda/ts2abc/type_adapter.cpp b/ts2panda/ts2abc/type_adapter.cpp index 1ab1e303fc4515455e509c88e5101dbf51dafeb8..a0ae080162e2fe91ded247d95191fea82c36b2bc 100644 --- a/ts2panda/ts2abc/type_adapter.cpp +++ b/ts2panda/ts2abc/type_adapter.cpp @@ -92,7 +92,7 @@ void TypeAdapter::HandleTypeForFunction(panda::pandasm::Function *func, size_t a auto it = vreg_type_map.find(vreg); if (it != vreg_type_map.end()) { ASSERT(std::find(finished_vregs.begin(), finished_vregs.end(), vreg) == finished_vregs.end()); - int32_t arg_order = func->regs_num - arg - 1; + int32_t arg_order = static_cast(func->regs_num) - static_cast(arg) - 1; order_type_map.emplace(arg_order, it->second); finished_vregs.emplace_back(vreg); } diff --git a/ts2panda/ts2abc_config.gni b/ts2panda/ts2abc_config.gni index e77f4a2714494652f1ed9b4685e76c8145d3124d..01d9002487e336478430b860b36fbc909642af8a 100755 --- a/ts2panda/ts2abc_config.gni +++ b/ts2panda/ts2abc_config.gni @@ -10,26 +10,18 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. - +import("//arkcompiler/ets_frontend/ets_frontend_config.gni") if (!defined(ark_independent_build)) { import("//build/ohos.gni") import("//build/test.gni") build_root = "//build" - ts2abc_root = "//ark/ts2abc/ts2panda" + ts2abc_root = "//arkcompiler/ets_frontend/ts2panda" } else { import("$build_root/ark.gni") - ts2abc_root = "//ts2abc/ts2panda" + ts2abc_root = "//arkcompiler/ets_frontend/ts2panda" } declare_args() { - buildtool_linux = "$build_root/toolchain/linux:clang_x64" - if (host_cpu == "arm64") { - buildtool_mac = "$build_root/toolchain/mac:clang_arm64" - } else { - buildtool_mac = "$build_root/toolchain/mac:clang_x64" - } - buildtool_win = "$build_root/toolchain/mingw:mingw_x86_64" - nodejs_dir = "" node_path = "" node_modules = "" @@ -45,22 +37,25 @@ if (build_public_version) { nodejs_dir = "//prebuilts/ace-toolkit/nodejs" } -if (host_toolchain == buildtool_mac) { - ts2abc_build_deps = [ "$ts2abc_root:ts2abc_build_mac($buildtool_mac)" ] +if (host_toolchain == toolchain_mac) { + ts2abc_build_deps = [ "$ts2abc_root:ts2abc_build_mac($toolchain_mac)" ] ts2abc_build_path = - get_label_info("$ts2abc_root:ts2abc_build_mac($buildtool_mac)", - "root_out_dir") + "/obj/ark/ts2abc/ts2panda/build-mac" + get_label_info("$ts2abc_root:ts2abc_build_mac($toolchain_mac)", + "root_out_dir") + + "/obj/arkcompiler/ets_frontend/ts2panda/build-mac" node_path = "${nodejs_dir}/node-v12.18.4-darwin-x64/bin/" -} else if (host_toolchain == buildtool_win) { - ts2abc_build_deps = [ "$ts2abc_root:ts2abc_build_win($buildtool_win)" ] +} else if (host_toolchain == toolchain_win) { + ts2abc_build_deps = [ "$ts2abc_root:ts2abc_build_win($toolchain_win)" ] ts2abc_build_path = - get_label_info("$ts2abc_root:ts2abc_build_win($buildtool_win)", - "root_out_dir") + "/obj/ark/ts2abc/ts2panda/build_win" + get_label_info("$ts2abc_root:ts2abc_build_win($toolchain_win)", + "root_out_dir") + + "/obj/arkcompiler/ets_frontend/ts2panda/build_win" } else { - ts2abc_build_deps = [ "$ts2abc_root:ts2abc_build($buildtool_linux)" ] + ts2abc_build_deps = [ "$ts2abc_root:ts2abc_build($toolchain_linux)" ] ts2abc_build_path = - get_label_info("$ts2abc_root:ts2abc_build($buildtool_linux)", - "root_out_dir") + "/obj/ark/ts2abc/ts2panda/build" + get_label_info("$ts2abc_root:ts2abc_build($toolchain_linux)", + "root_out_dir") + + "/obj/arkcompiler/ets_frontend/ts2panda/build" node_path = "${nodejs_dir}/node-v12.18.4-linux-x64/bin/" } @@ -218,12 +213,12 @@ template("ts2abc_unittest") { "--gn-build", ] - if (host_toolchain == buildtool_linux) { + if (host_toolchain == toolchain_linux) { args += [ "--platform", "linux", ] - } else if (host_toolchain == buildtool_mac) { + } else if (host_toolchain == toolchain_mac) { args += [ "--platform", "mac",