From fc544205e1a35fa2fba55400d1d816b2bbd86d33 Mon Sep 17 00:00:00 2001 From: huangyu Date: Wed, 14 Jun 2023 18:52:55 +0800 Subject: [PATCH] Record type index for module variable instruction for es2abc Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/I7DJ9U Test: es2panda/test/type_extractor/testcases_with_assert/projects Signed-off-by: huangyu Change-Id: I459bbb8f4a85a202caf23b1a2178e8995bb3bfc6 --- es2panda/compiler/core/compilerContext.cpp | 5 ++ es2panda/compiler/core/compilerContext.h | 8 +++ es2panda/compiler/core/compilerImpl.cpp | 1 + es2panda/compiler/core/pandagen.cpp | 18 +++++++ es2panda/test/runner.py | 23 +++++--- .../projects/test-import-export/export.ts | 54 +++++++++++++++++++ .../test-import-export/import-main.ts | 44 +++++++++++++++ .../typescript/extractor/typeExtractor.cpp | 1 + es2panda/typescript/extractor/typeExtractor.h | 2 +- .../typescript/extractor/typeRecorder.cpp | 6 +-- 10 files changed, 150 insertions(+), 12 deletions(-) create mode 100644 es2panda/test/type_extractor/testcases_with_assert/projects/test-import-export/export.ts create mode 100644 es2panda/test/type_extractor/testcases_with_assert/projects/test-import-export/import-main.ts diff --git a/es2panda/compiler/core/compilerContext.cpp b/es2panda/compiler/core/compilerContext.cpp index 31a7a09c2c..78edb8abbd 100644 --- a/es2panda/compiler/core/compilerContext.cpp +++ b/es2panda/compiler/core/compilerContext.cpp @@ -38,4 +38,9 @@ void CompilerContext::SetTypeRecorder(extractor::TypeRecorder *recorder) recorder_ = recorder; } +void CompilerContext::SetTypeExtractor(extractor::TypeExtractor *extractor) +{ + extractor_ = extractor; +} + } // namespace panda::es2panda::compiler diff --git a/es2panda/compiler/core/compilerContext.h b/es2panda/compiler/core/compilerContext.h index 27118a322f..0581f4c2d1 100644 --- a/es2panda/compiler/core/compilerContext.h +++ b/es2panda/compiler/core/compilerContext.h @@ -33,6 +33,7 @@ class Binder; namespace panda::es2panda::extractor { class TypeRecorder; +class TypeExtractor; } // namespace panda::es2panda::extractor namespace panda::es2panda::compiler { @@ -120,7 +121,13 @@ public: return recorder_; } + extractor::TypeExtractor *TypeExtractor() const + { + return extractor_; + } + void SetTypeRecorder(extractor::TypeRecorder *recorder); + void SetTypeExtractor(extractor::TypeExtractor *extractor); bool IsJsonInputFile() const { @@ -139,6 +146,7 @@ private: // true when input file is json file bool isJsonInputFile_; extractor::TypeRecorder *recorder_ {}; + extractor::TypeExtractor *extractor_ {}; std::string sourceFile_; std::string pkgName_; util::StringView recordName_; diff --git a/es2panda/compiler/core/compilerImpl.cpp b/es2panda/compiler/core/compilerImpl.cpp index 880a25bf51..1d2c8bffc5 100644 --- a/es2panda/compiler/core/compilerImpl.cpp +++ b/es2panda/compiler/core/compilerImpl.cpp @@ -53,6 +53,7 @@ panda::pandasm::Program *CompilerImpl::Compile(parser::Program *program, const e extractor_->StartTypeExtractor(program); context.SetTypeRecorder(extractor_->Recorder()); + context.SetTypeExtractor(extractor_.get()); } queue_ = new CompileFuncQueue(threadCount_, &context); diff --git a/es2panda/compiler/core/pandagen.cpp b/es2panda/compiler/core/pandagen.cpp index 9aea7f5dd2..70f9fb5a59 100644 --- a/es2panda/compiler/core/pandagen.cpp +++ b/es2panda/compiler/core/pandagen.cpp @@ -1691,6 +1691,16 @@ void PandaGen::LoadLocalModuleVariable(const ir::AstNode *node, const binder::Mo void PandaGen::LoadExternalModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable) { auto index = variable->Index(); + if (Context()->IsTypeExtractorEnabled()) { + const ir::Identifier *identifier = nullptr; + const ir::AstNode *declareNode = Context()->TypeExtractor()->GetDeclNodeFromIdentifier(node->AsIdentifier(), &identifier); + int64_t typeIndex = Context()->TypeRecorder()->GetNodeTypeIndex(declareNode); + if (typeIndex != extractor::TypeRecorder::PRIMITIVETYPE_ANY) { + index <= util::Helpers::MAX_INT8 ? ra_.EmitWithType(node, typeIndex, index) : + ra_.EmitWithType(node, typeIndex, index); + return; + } + } index <= util::Helpers::MAX_INT8 ? ra_.Emit(node, index) : ra_.Emit(node, index); } @@ -1698,6 +1708,14 @@ void PandaGen::LoadExternalModuleVariable(const ir::AstNode *node, const binder: void PandaGen::StoreModuleVariable(const ir::AstNode *node, const binder::ModuleVariable *variable) { auto index = variable->Index(); + if (Context()->IsTypeExtractorEnabled()) { + int64_t typeIndex = Context()->TypeRecorder()->GetNodeTypeIndex(node); + if (typeIndex != extractor::TypeRecorder::PRIMITIVETYPE_ANY) { + index <= util::Helpers::MAX_INT8 ? ra_.EmitWithType(node, typeIndex, index) : + ra_.EmitWithType(node, typeIndex, index); + return; + } + } index <= util::Helpers::MAX_INT8 ? ra_.Emit(node, index) : ra_.Emit(node, index); } diff --git a/es2panda/test/runner.py b/es2panda/test/runner.py index 27b384ec05..328560bd58 100755 --- a/es2panda/test/runner.py +++ b/es2panda/test/runner.py @@ -1250,6 +1250,7 @@ class TypeExtractorRunner(Runner): self.add_directory("testcases", []) self.add_directory("dts-testcases", [], True) self.add_directory("testcases_with_assert", []) + self.add_directory("testcases_with_assert/projects", [], False, True) self.add_directory("testcases_with_running", []) def add_tsc_directory(self, directory, flags): @@ -1266,21 +1267,22 @@ class TypeExtractorRunner(Runner): test = TypeExtractorTest(f, flags) self.tests.append(test) - def add_directory(self, directory, flags, is_dts_test=False): + def add_directory(self, directory, flags, is_dts_test=False, is_project=False): ts_suite_dir = path.join(self.test_root, 'type_extractor') - if is_dts_test: + if is_project: + glob_expression = path.join(ts_suite_dir, directory, "**/*-main.ts") + elif is_dts_test: glob_expression = path.join(ts_suite_dir, directory, "**/*.d.ts") else: - glob_expression = path.join(ts_suite_dir, directory, "**/*.ts") + glob_expression = path.join(ts_suite_dir, directory, "*.ts") files = glob(glob_expression, recursive=True) files = fnmatch.filter(files, ts_suite_dir + '**' + self.args.filter) - for f in files: - if directory.endswith("testcases_with_assert") or directory.endswith("testcases_with_running"): + if directory.startswith("testcases_with_assert") or directory.startswith("testcases_with_running"): if (self.ld_library_path == "" or self.ark_aot_compiler == ""): break - test = TypeExtractorWithAOTTest(f, flags, directory.endswith("testcases_with_running")) + test = TypeExtractorWithAOTTest(f, flags, directory.startswith("testcases_with_running"), directory.endswith("projects")) self.tests.append(test) else: test = TypeExtractorTest(f, flags, is_dts_test) @@ -1341,9 +1343,10 @@ class TypeExtractorTest(Test): class TypeExtractorWithAOTTest(Test): - def __init__(self, test_path, flags, with_running=False): + def __init__(self, test_path, flags, with_running=False, is_project=False): Test.__init__(self, test_path, flags) self.with_running = with_running + self.is_project = is_project def run_js_vm(self, runner, file_name, test_abc_name): expected_path = "%s-expected.txt" % (file_name) @@ -1378,7 +1381,11 @@ class TypeExtractorWithAOTTest(Test): '--module', '--merge-abc', '--opt-level=2', '--type-extractor'] cmd.extend(self.flags) cmd.extend(["--output=" + test_abc_name]) - cmd.append(self.path) + if self.is_project: + cmd.append("--extension=ts") + cmd.append(path.dirname(self.path)) + else: + cmd.append(self.path) self.log_cmd(cmd) process = subprocess.Popen( diff --git a/es2panda/test/type_extractor/testcases_with_assert/projects/test-import-export/export.ts b/es2panda/test/type_extractor/testcases_with_assert/projects/test-import-export/export.ts new file mode 100644 index 0000000000..13d24280ce --- /dev/null +++ b/es2panda/test/type_extractor/testcases_with_assert/projects/test-import-export/export.ts @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023 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. + */ + + +declare function AssertType(value: any, type: string): void; + +export default function add(a: number, b: number): number { + return a + b; +} + +function subtract(a: number, b: number): number { + return a - b; +} + +export function multiply(a: number, b: number): number { + return a * b; +} + +export { multiply as times }; + +export const PI: number = 3.14; + +export class Student { + name: string; + age: number; + constructor(name: string, age: number) { + this.name = name; + this.age = age; + }; +} + +interface Lesson { + id: number, + date: string +} + +type customType = string; + +export { subtract, customType, Lesson }; + +AssertType(add, "(number, number) => number"); +AssertType(subtract(PI, PI), "number"); diff --git a/es2panda/test/type_extractor/testcases_with_assert/projects/test-import-export/import-main.ts b/es2panda/test/type_extractor/testcases_with_assert/projects/test-import-export/import-main.ts new file mode 100644 index 0000000000..3733026c90 --- /dev/null +++ b/es2panda/test/type_extractor/testcases_with_assert/projects/test-import-export/import-main.ts @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023 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. + */ + + +declare function AssertType(value: any, type: string): void; + +import add from './export'; +import { multiply, times } from './export'; +import { PI, Student } from './export'; +import { subtract, Lesson } from './export'; +import type { customType } from './export'; + +let xiaoming = new Student("xiaoming", 12); +let xiaohong: Student = new Student("xiaohong", 11); +var value: customType = "hello"; +const factor: number = 5; +let equal = (times(factor, PI) == multiply(factor, PI)); +let math: Lesson = { + id: 1, + date: "2023" +} + +AssertType(add, "(number, number) => number"); +AssertType(PI, "number"); +AssertType(xiaoming, "Student"); +AssertType(xiaoming.name, "string"); +AssertType(xiaohong.age, "number"); +AssertType(equal, "boolean"); +AssertType(subtract(xiaohong.age, factor), "number"); +AssertType(value, "string"); +AssertType(math.id, "number"); +AssertType(math.date, "string"); diff --git a/es2panda/typescript/extractor/typeExtractor.cpp b/es2panda/typescript/extractor/typeExtractor.cpp index 17dfc58ee5..ac01658f61 100644 --- a/es2panda/typescript/extractor/typeExtractor.cpp +++ b/es2panda/typescript/extractor/typeExtractor.cpp @@ -179,6 +179,7 @@ void TypeExtractor::ExtractImport(const parser::Program *program) for (const auto &t : namespaceImportEntries) { const auto &redirectPath = moduleRecord->GetModuleRequestIdxMap().at(t->moduleRequestIdx_); ExternalType externalType(this, "*", redirectPath); + recorder_->SetNodeTypeIndex(t->localId_->Parent(), externalType.GetTypeIndexShift()); recorder_->SetNamespaceType(std::string(t->localName_), externalType.GetTypeIndexShift()); recorder_->SetNamespacePath(std::string(t->localName_), std::string(redirectPath)); } diff --git a/es2panda/typescript/extractor/typeExtractor.h b/es2panda/typescript/extractor/typeExtractor.h index e51345e28f..56d7e52da2 100644 --- a/es2panda/typescript/extractor/typeExtractor.h +++ b/es2panda/typescript/extractor/typeExtractor.h @@ -41,6 +41,7 @@ public: TypeRecorder *Recorder() const; const ir::Identifier *GetIdentifierFromExpression(const ir::Expression *expression); + const ir::AstNode *GetDeclNodeFromIdentifier(const ir::Identifier *identifier, const ir::Identifier **variable); int64_t GetTypeIndexFromAnnotation(const ir::Expression *typeAnnotation, bool isNewInstance = true); int64_t GetTypeIndexFromIdentifier(const ir::Identifier *identifier); int64_t GetTypeIndexFromInitializer(const ir::Expression *initializer); @@ -73,7 +74,6 @@ private: void ExtractImport(const parser::Program *program); void ExtractExport(const parser::Program *program); - const ir::AstNode *GetDeclNodeFromIdentifier(const ir::Identifier *identifier, const ir::Identifier **variable); const ir::AstNode *GetDeclNodeFromInitializer(const ir::Expression *initializer, const ir::Identifier **variable); int64_t GetTypeIndexFromDeclNode(const ir::AstNode *node, bool isNewInstance); diff --git a/es2panda/typescript/extractor/typeRecorder.cpp b/es2panda/typescript/extractor/typeRecorder.cpp index fa9964eb5e..e2716437e3 100644 --- a/es2panda/typescript/extractor/typeRecorder.cpp +++ b/es2panda/typescript/extractor/typeRecorder.cpp @@ -141,7 +141,7 @@ int64_t TypeRecorder::GetNodeTypeIndex(const ir::AstNode *node) const void TypeRecorder::SetNodeTypeIndex(const ir::AstNode *node, int64_t index) { - if (node == nullptr || GetNodeTypeIndex(node) != PRIMITIVETYPE_ANY) { + if (node == nullptr || GetNodeTypeIndex(node) != PRIMITIVETYPE_ANY || index == PRIMITIVETYPE_ANY) { return; } @@ -166,7 +166,7 @@ int64_t TypeRecorder::GetVariableTypeIndex(const binder::Variable *variable) con void TypeRecorder::SetVariableTypeIndex(const binder::Variable *variable, int64_t index) { - if (variable == nullptr || GetVariableTypeIndex(variable) != PRIMITIVETYPE_ANY) { + if (variable == nullptr || GetVariableTypeIndex(variable) != PRIMITIVETYPE_ANY || index == PRIMITIVETYPE_ANY) { return; } @@ -176,7 +176,7 @@ void TypeRecorder::SetVariableTypeIndex(const binder::Variable *variable, int64_ void TypeRecorder::SetIdentifierTypeIndex(const ir::Identifier *identifier, int64_t index) { - if (identifier == nullptr) { + if (identifier == nullptr || index == PRIMITIVETYPE_ANY) { return; } SetNodeTypeIndex(identifier, index); -- Gitee