From 271fd3e9623f9ba3120c847a308edd41f4620b8b Mon Sep 17 00:00:00 2001 From: qiuyu Date: Thu, 23 Jun 2022 11:58:45 +0800 Subject: [PATCH] Store type info as pairs of instruction orders and types Change AnnotationElement name from typeOfVreg to _TypeOfInstruction. Add the pass TypeAdapter. This pass can convert the typeinfo of the form of the pairs of virtual registers and types to the form of pairs of instruction orders and types. Add option --enable-typeinfo with which the pass TypeAdapter is enabled. Should be deleted when ark_js_runtime adaption is ready. Add option --display-typeinfo with which the result typeinfo will be printed. Issue: #I5E22F Signed-off-by: qiuyu Change-Id: I3c87b579d4c58cc3713263fe1e1e1d2ff953c58d --- ts2panda/BUILD.gn | 7 + ts2panda/src/cmdOptions.ts | 18 ++- ts2panda/src/ts2panda.ts | 4 +- ts2panda/ts2abc/BUILD.gn | 1 + ts2panda/ts2abc/tests/BUILD.gn | 12 ++ .../ts2abc/tests/type_adapter_test/BUILD.gn | 60 +++++++ .../type_adapter_test/type_adapter_test.cpp | 143 ++++++++++++++++ ts2panda/ts2abc/ts2abc.cpp | 38 ++++- ts2panda/ts2abc/type_adapter.cpp | 153 ++++++++++++++++++ ts2panda/ts2abc/type_adapter.h | 47 ++++++ 10 files changed, 475 insertions(+), 8 deletions(-) create mode 100644 ts2panda/ts2abc/tests/type_adapter_test/BUILD.gn create mode 100644 ts2panda/ts2abc/tests/type_adapter_test/type_adapter_test.cpp create mode 100644 ts2panda/ts2abc/type_adapter.cpp create mode 100644 ts2panda/ts2abc/type_adapter.h diff --git a/ts2panda/BUILD.gn b/ts2panda/BUILD.gn index 411b0ff37b..6ef40ce0df 100755 --- a/ts2panda/BUILD.gn +++ b/ts2panda/BUILD.gn @@ -255,3 +255,10 @@ group("ts2abc_unittests") { deps = [ "tests:ts2abc_tests(${buildtool_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})" ] + } +} diff --git a/ts2panda/src/cmdOptions.ts b/ts2panda/src/cmdOptions.ts index 1224946ba0..4e108670db 100644 --- a/ts2panda/src/cmdOptions.ts +++ b/ts2panda/src/cmdOptions.ts @@ -44,7 +44,9 @@ const ts2pandaOptions = [ { name: 'record-type', alias: 'p', type: Boolean, defaultValue: false, description: "Record type info. Default: true" }, { 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: '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" } ] @@ -53,6 +55,20 @@ 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; + } + return this.options["display-typeinfo"]; + } + static isEnableDebugLog(): boolean { if (!this.options) { return false; diff --git a/ts2panda/src/ts2panda.ts b/ts2panda/src/ts2panda.ts index d07d50d18d..52c1823865 100644 --- a/ts2panda/src/ts2panda.ts +++ b/ts2panda/src/ts2panda.ts @@ -194,7 +194,9 @@ export class Ts2Panda { "debug_mode": CmdOptions.isDebugMode(), "log_enabled": CmdOptions.isEnableDebugLog(), "opt_level": CmdOptions.getOptLevel(), - "opt_log_level": CmdOptions.getOptLogLevel() + "opt_log_level": CmdOptions.getOptLogLevel(), + "enable_typeinfo": CmdOptions.getEnableTypeinfo(), + "display_typeinfo": CmdOptions.getDisplayTypeinfo() }; let jsonOpt = JSON.stringify(options, null, 2); jsonOpt = "$" + jsonOpt.replace(dollarSign, '#$') + "$"; diff --git a/ts2panda/ts2abc/BUILD.gn b/ts2panda/ts2abc/BUILD.gn index 8718d3e7a1..54dffea651 100755 --- a/ts2panda/ts2abc/BUILD.gn +++ b/ts2panda/ts2abc/BUILD.gn @@ -80,6 +80,7 @@ if (!defined(ark_independent_build)) { sources = [ "main.cpp", "ts2abc.cpp", + "type_adapter.cpp", ] configs = [ ":ts2abc_config" ] diff --git a/ts2panda/ts2abc/tests/BUILD.gn b/ts2panda/ts2abc/tests/BUILD.gn index 4631de5527..f5b42a5d9d 100644 --- a/ts2panda/ts2abc/tests/BUILD.gn +++ b/ts2panda/ts2abc/tests/BUILD.gn @@ -30,6 +30,10 @@ import("//ark/ts2abc/ts2panda/ts2abc_config.gni") # sources = [ "functions_test.cpp" ] # } +ts2abc_unittest_action("TypeAdapterTest") { + sources = [ "type_adapter_test.cpp" ] +} + # group("unittest") { # testonly = true # deps = [ @@ -39,3 +43,11 @@ import("//ark/ts2abc/ts2panda/ts2abc_config.gni") # ":StringArrTestAction", # ] # } + +group("type_adapter_unit_tests") { + testonly = true + deps = [ + ":TypeAdapterTest", + "$ark_root/assembler:libarkassembler_frontend_static", + ] +} diff --git a/ts2panda/ts2abc/tests/type_adapter_test/BUILD.gn b/ts2panda/ts2abc/tests/type_adapter_test/BUILD.gn new file mode 100644 index 0000000000..117b88df4c --- /dev/null +++ b/ts2panda/ts2abc/tests/type_adapter_test/BUILD.gn @@ -0,0 +1,60 @@ +# Copyright (c) 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("//ark/runtime_core/ark_config.gni") +import("//ark/ts2abc/ts2panda/ts2abc_config.gni") + +ohos_executable("ts2abc_type_adapter_unit_tests") { + sources = [ + "//ark/ts2abc/ts2panda/ts2abc/type_adapter.cpp", + "type_adapter_test.cpp", + ] + + configs = [ "//ark/ts2abc/ts2panda/ts2abc:ts2abc_config" ] + + cflags = [ + "-Wno-c++20-designator", + "-Wno-c99-extensions", + "-Wno-unknown-warning-option", + ] + + deps = [ sdk_libc_secshared_dep ] + + if (is_linux || is_mingw || is_mac) { + deps += [ + "$ark_root/assembler:libarkassembler_frontend_static", + "$ark_root/libpandabase:libarkbase_frontend_static", + "$ark_root/libpandafile:libarkfile_frontend_static", + "$ark_root/libziparchive:libarkziparchive_frontend_static", + ] + } else { + deps += [ + "$ark_root/assembler:libarkassembler", + "$ark_root/libpandabase:libarkbase", + "$ark_root/libpandafile:libarkfile", + "$ark_root/libziparchive:libarkziparchive", + ] + } + + if (is_linux) { + if (build_public_version) { + ldflags = [ "-static-libstdc++" ] + } else { + libs = [ libcpp_static_lib ] + } + } + + output_name = "ts2abc_type_adapter_unit_tests" + install_enable = true + subsystem_name = "ark" +} diff --git a/ts2panda/ts2abc/tests/type_adapter_test/type_adapter_test.cpp b/ts2panda/ts2abc/tests/type_adapter_test/type_adapter_test.cpp new file mode 100644 index 0000000000..74fa91fa82 --- /dev/null +++ b/ts2panda/ts2abc/tests/type_adapter_test/type_adapter_test.cpp @@ -0,0 +1,143 @@ +/* + * 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. + */ + +#include "type_adapter.h" +#include "assembler/meta.h" +#include "assembler/assembly-parser.h" + +using ArrayValue = panda::pandasm::ArrayValue; +using ScalarValue = panda::pandasm::ScalarValue; +using AnnotationData = panda::pandasm::AnnotationData; +using AnnotationElement = panda::pandasm::AnnotationElement; + +class TestBase { +public: + template + inline void TestAssertEqual(const T1 &left, const T2 &right) const + { + if (left != static_cast(right)) { + std::cout << "assertion equal failed." << std::endl; + UNREACHABLE(); + } + } + + template + inline void TestAssertNotEqual(const T1 &left, const T2 &right) const + { + if (left == static_cast(right)) { + std::cout << "assertion not equal failed." << std::endl; + UNREACHABLE(); + } + } +}; + +class TypeAdapterTest : TestBase { +public: + void TestVariablesArgsType() const; + void TestBuiltinsType() const; + + std::unordered_map ExtractTypeinfo(const panda::pandasm::Function &fun) const + { + const auto *ele = fun.metadata->GetAnnotations()[0].GetElements()[0].GetValue(); + const auto &values = ele->GetAsArray()->GetValues(); + std::unordered_maptype_info; + const size_t pair_gap = 2; + TestAssertEqual(values.size() % pair_gap, 0); + for (size_t i = 0; i < values.size(); i += pair_gap) { + type_info.emplace(values[i].GetValue(), values[i + 1].GetValue()); + } + return type_info; + } + + void CheckTypeExist(const std::unordered_map &typeinfo, int32_t order, int32_t type) const + { + auto type_it = typeinfo.find(order); + TestAssertNotEqual(type_it, typeinfo.end()); + TestAssertEqual(type_it->second, type); + } + + void AddTypeinfo(std::vector *elements, int32_t order, int32_t type) const + { + ScalarValue insn_order(ScalarValue::Create(order)); + elements->emplace_back(std::move(insn_order)); + ScalarValue insn_type(ScalarValue::Create(type)); + elements->emplace_back(std::move(insn_type)); + } +}; + +void TypeAdapterTest::TestVariablesArgsType() const +{ + std::string source = R"( + .function any foo(any a0, any a1) { + mov.dyn v1, a1 + mov.dyn v0, a0 + ecma.ldlexenvdyn + sta.dyn v4 + lda.dyn v0 + sta.dyn v3 + lda.dyn v1 + ecma.add2dyn v3 + sta.dyn v2 + lda.dyn v2 + sta.dyn v3 + lda.dyn v3 + return.dyn + } + )"; + panda::pandasm::Parser p; + auto res = p.Parse(source); + auto &program = res.Value(); + auto it = program.function_table.find("foo"); + TestAssertNotEqual(it, program.function_table.end()); + auto &foo = it->second; + + // set up args types + std::vector elements; + AddTypeinfo(&elements, 0, 1); + AddTypeinfo(&elements, 1, 1); + // set up variable type + const int32_t var_reg = 2; + AddTypeinfo(&elements, var_reg, 1); + ArrayValue arr(panda::pandasm::Value::Type::I32, elements); + AnnotationElement anno_ele(TypeAdapter::TSTYPE_ANNO_ELEMENT_NAME, std::make_unique(arr)); + AnnotationData anno_data(TypeAdapter::TSTYPE_ANNO_RECORD_NAME); + anno_data.AddElement(std::move(anno_ele)); + std::vector annos; + annos.emplace_back(std::move(anno_data)); + foo.metadata->SetAnnotations(std::move(annos)); + + TypeAdapter ta; + ta.AdaptTypeForProgram(&program); + + // Check types + const auto typeinfo = ExtractTypeinfo(foo); + // first arg type + CheckTypeExist(typeinfo, -1, 1); + // second arg type + const int32_t second_arg = -2; + CheckTypeExist(typeinfo, second_arg, 1); + // variable type + const int32_t instruction_location = 8; + CheckTypeExist(typeinfo, instruction_location, 1); +} + +int main(int argc, const char *argv[]) +{ + TypeAdapterTest test; + std::cout << "TypeAdapterTest TestVariablesArgsType: " << std::endl; + test.TestVariablesArgsType(); + std::cout << "PASS!" << std::endl; + // should enable TestBuiltinsType when builtins adaption is ready +} diff --git a/ts2panda/ts2abc/ts2abc.cpp b/ts2panda/ts2abc/ts2abc.cpp index 277d29d21b..802ac449b8 100644 --- a/ts2panda/ts2abc/ts2abc.cpp +++ b/ts2panda/ts2abc/ts2abc.cpp @@ -24,8 +24,9 @@ #include "assembly-program.h" #include "assembly-emitter.h" #include "json/json.h" -#include "ts2abc_options.h" #include "securec.h" +#include "ts2abc_options.h" +#include "type_adapter.h" #include "ts2abc.h" #ifdef ENABLE_BYTECODE_OPT @@ -39,6 +40,8 @@ namespace { bool g_debugModeEnabled = false; bool g_debugLogEnabled = false; int g_optLevel = 0; + bool g_enableTypeinfo = false; + bool g_displayTypeinfo = false; std::string g_optLogLevel = "error"; uint32_t g_literalArrayCount = 0; @@ -626,7 +629,7 @@ static void ParseFunctionTypeInfo(const Json::Value &function, panda::pandasm::F { if (function.isMember("ti") && function["ti"].isArray()) { auto typeInfo = function["ti"]; - panda::pandasm::AnnotationData funcAnnotation("_ESTypeAnnotation"); + panda::pandasm::AnnotationData funcAnnotation(TypeAdapter::TSTYPE_ANNO_RECORD_NAME); std::vector elements; for (Json::ArrayIndex i = 0; i < typeInfo.size(); i++) { @@ -640,7 +643,7 @@ static void ParseFunctionTypeInfo(const Json::Value &function, panda::pandasm::F elements.emplace_back(std::move(tIndex)); } - std::string annotationName = "typeOfVreg"; + std::string annotationName = TypeAdapter::TSTYPE_ANNO_ELEMENT_NAME; panda::pandasm::AnnotationElement typeOfVregElement( annotationName, std::make_unique(panda::pandasm::ArrayValue( panda::pandasm::Value::Type::U32, elements))); @@ -662,7 +665,7 @@ static void ParseFunctionExportedType(const Json::Value &function, panda::pandas if (function.isMember("es2t") && function["es2t"].isArray()) { auto exportedTypes = function["es2t"]; - panda::pandasm::AnnotationData funcAnnotation("_ESTypeAnnotation"); + panda::pandasm::AnnotationData funcAnnotation(TypeAdapter::TSTYPE_ANNO_RECORD_NAME); std::vector symbolElements; std::vector symbolTypeElements; for (Json::ArrayIndex i = 0; i < exportedTypes.size(); i++) { @@ -718,7 +721,7 @@ static void ParseFunctionDeclaredType(const Json::Value &function, panda::pandas if (function.isMember("ds2t") && function["ds2t"].isArray()) { auto declaredTypes = function["ds2t"]; - panda::pandasm::AnnotationData funcAnnotation("_ESTypeAnnotation"); + panda::pandasm::AnnotationData funcAnnotation(TypeAdapter::TSTYPE_ANNO_RECORD_NAME); std::vector symbolElements; std::vector symbolTypeElements; for (Json::ArrayIndex i = 0; i < declaredTypes.size(); i++) { @@ -788,7 +791,7 @@ static void GenerateESCallTypeAnnotationRecord(panda::pandasm::Program &prog) } static void GenerateESTypeAnnotationRecord(panda::pandasm::Program &prog) { - auto tsTypeAnnotationRecord = panda::pandasm::Record("_ESTypeAnnotation", LANG_EXT); + auto tsTypeAnnotationRecord = panda::pandasm::Record(TypeAdapter::TSTYPE_ANNO_RECORD_NAME, LANG_EXT); tsTypeAnnotationRecord.metadata->SetAttribute("external"); tsTypeAnnotationRecord.metadata->SetAccessFlags(panda::ACC_ANNOTATION); prog.record_table.emplace(tsTypeAnnotationRecord.name, std::move(tsTypeAnnotationRecord)); @@ -897,6 +900,22 @@ 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-----------------"); + if (rootValue.isMember("display_typeinfo") && rootValue["display_typeinfo"].isBool()) { + g_displayTypeinfo = rootValue["display_typeinfo"].asBool(); + } +} + static void ParseOptLogLevel(const Json::Value &rootValue) { Logd("-----------------parse opt log level-----------------"); @@ -925,6 +944,8 @@ static void ParseOptions(const Json::Value &rootValue, panda::pandasm::Program & ParseLogEnable(rootValue); ParseDebugMode(rootValue); ParseOptLevel(rootValue); + ParseEnableTypeinfo(rootValue); + ParseDisplayTypeinfo(rootValue); ParseOptLogLevel(rootValue); } @@ -1297,6 +1318,11 @@ 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); + } + #ifdef ENABLE_BYTECODE_OPT if (g_optLevel != static_cast(OptLevel::O_LEVEL0) || optLevel != static_cast(OptLevel::O_LEVEL0)) { optLogLevel = (optLogLevel != "error") ? optLogLevel : g_optLogLevel; diff --git a/ts2panda/ts2abc/type_adapter.cpp b/ts2panda/ts2abc/type_adapter.cpp new file mode 100644 index 0000000000..8c383f175d --- /dev/null +++ b/ts2panda/ts2abc/type_adapter.cpp @@ -0,0 +1,153 @@ +/* + * 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. + */ + +#include "type_adapter.h" +#include "assembler/meta.h" + +void TypeAdapter::AdaptTypeForProgram(panda::pandasm::Program *prog) const +{ + for (auto &[name, func] : prog->function_table) { + if (ShouldDisplayTypeInfo()) { + std::cout << "Handle types for funtion: " << name << "\n"; + } + AdaptTypeForFunction(&func); + } +} + +void TypeAdapter::AdaptTypeForFunction(panda::pandasm::Function *func) const +{ + const auto &annos = func->metadata->GetAnnotations(); + std::unordered_map vreg_type_map; + size_t anno_idx = 0; + size_t ele_idx = 0; + for (; anno_idx < annos.size(); anno_idx++) { + const auto &anno_data = annos[anno_idx]; + if (anno_data.GetName() != TSTYPE_ANNO_RECORD_NAME) { + continue; + } + const auto &elements = anno_data.GetElements(); + for (; ele_idx < elements.size(); ele_idx++) { + const auto &element = elements[ele_idx]; + if (element.GetName() != TSTYPE_ANNO_ELEMENT_NAME) { + continue; + } + const auto *array_value = element.GetValue(); + ASSERT(array_value->IsArray()); + const auto &values = array_value->GetAsArray()->GetValues(); + size_t i = 0; + while (i < values.size()) { + auto vreg = static_cast(values[i++].GetValue()); + auto type = static_cast(values[i++].GetValue()); + vreg_type_map.emplace(vreg, type); + } + break; + } + break; + } + if (!vreg_type_map.empty()) { + HandleTypeForFunction(func, anno_idx, ele_idx, vreg_type_map); + } +} + +static bool MaybeArg(const panda::pandasm::Function *func, size_t idx) +{ + return idx < func->params.size() && func->ins[idx].opcode == panda::pandasm::Opcode::MOV_DYN; +} + +void TypeAdapter::HandleTypeForFunction(panda::pandasm::Function *func, size_t anno_idx, size_t ele_idx, + const std::unordered_map &vreg_type_map) const +{ + std::unordered_map order_type_map; + std::vector finished_vregs; + int32_t order = 0; + for (size_t i = 0; i < func->ins.size(); i++) { + const auto &insn = func->ins[i]; + if (insn.opcode == panda::pandasm::Opcode::INVALID) { + continue; + } + order++; + bool maybe_arg = MaybeArg(func, i); + if (!maybe_arg && insn.opcode != panda::pandasm::Opcode::STA_DYN) { + continue; + } + if (maybe_arg) { + auto vreg = insn.regs[0]; + auto arg = insn.regs[1]; + if (vreg >= func->params.size() || arg < func->regs_num) { + continue; // not arg + } + 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; + order_type_map.emplace(arg_order, it->second); + finished_vregs.emplace_back(vreg); + } + continue; + } + + // vregs binded with variables must be filled through sta_dyn + ASSERT(insn.opcode == panda::pandasm::Opcode::STA_DYN); + ASSERT(!insn.regs.empty()); + auto vreg = insn.regs[0]; + auto it = vreg_type_map.find(vreg); + if (it != vreg_type_map.end() && + std::find(finished_vregs.begin(), finished_vregs.end(), vreg) == finished_vregs.end()) { + order_type_map.emplace(order - 1, it->second); + finished_vregs.emplace_back(vreg); + } + } + + UpdateTypeAnnotation(func, anno_idx, ele_idx, order_type_map); +} + +void TypeAdapter::UpdateTypeAnnotation(panda::pandasm::Function *func, size_t anno_idx, size_t ele_idx, + const std::unordered_map &order_type_map) const +{ + ASSERT(anno_idx <= func->metadata->GetAnnotations().size()); + if (anno_idx == func->metadata->GetAnnotations().size()) { + std::vector added_datas; + panda::pandasm::AnnotationData data(TSTYPE_ANNO_RECORD_NAME); + added_datas.push_back(std::forward(data)); + func->metadata->AddAnnotations(std::forward>(added_datas)); + ele_idx = 0; + } + + using ArrayValue = panda::pandasm::ArrayValue; + using ScalarValue = panda::pandasm::ScalarValue; + std::vector elements; + for (const auto &[order, type] : order_type_map) { + ScalarValue insn_order(ScalarValue::Create(order)); + elements.emplace_back(std::move(insn_order)); + ScalarValue insn_type(ScalarValue::Create(type)); + elements.emplace_back(std::move(insn_type)); + } + + ArrayValue arr(panda::pandasm::Value::Type::I32, elements); + panda::pandasm::AnnotationElement anno_ele(TSTYPE_ANNO_ELEMENT_NAME, std::make_unique(arr)); + func->metadata->SetOrAddAnnotationElementByIndex(anno_idx, ele_idx, std::move(anno_ele)); + + if (ShouldDisplayTypeInfo()) { + std::cout << "(instruction order, type): "; + const auto data = func->metadata->GetAnnotations()[anno_idx]; + const auto vars = data.GetElements()[ele_idx].GetValue()->GetAsArray()->GetValues(); + size_t pair_gap = 2; + for (size_t i = 0; i < vars.size(); i += pair_gap) { + std::cout << "(" << static_cast(vars[i].GetValue()) << ", " + << static_cast(vars[i + 1].GetValue()) << "), "; + } + std::cout << "\n"; + } +} diff --git a/ts2panda/ts2abc/type_adapter.h b/ts2panda/ts2abc/type_adapter.h new file mode 100644 index 0000000000..fb767c78ee --- /dev/null +++ b/ts2panda/ts2abc/type_adapter.h @@ -0,0 +1,47 @@ +/* + * 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. + */ + +#ifndef TS2PANDA_TS2ABC_TYPE_ADAPTER_H +#define TS2PANDA_TS2ABC_TYPE_ADAPTER_H + +#include "assembler/assembly-program.h" +#include "assembler/assembly-function.h" + +class TypeAdapter { +public: + TypeAdapter() {}; + ~TypeAdapter() {}; + explicit TypeAdapter(bool display) : display_typeinfo_(display) {}; + + static constexpr const char* TSTYPE_ANNO_RECORD_NAME = "_ESTypeAnnotation"; + static constexpr const char* TSTYPE_ANNO_ELEMENT_NAME = "_TypeOfInstruction"; + + bool ShouldDisplayTypeInfo() const + { + return display_typeinfo_; + } + + void AdaptTypeForProgram(panda::pandasm::Program *prog) const; + +private: + void AdaptTypeForFunction(panda::pandasm::Function *func) const; + void HandleTypeForFunction(panda::pandasm::Function *func, size_t anno_idx, size_t ele_idx, + const std::unordered_map &vreg_type_map) const; + void UpdateTypeAnnotation(panda::pandasm::Function *func, size_t anno_idx, size_t ele_idx, + const std::unordered_map &order_type_map) const; + bool display_typeinfo_ = false; +}; + +#endif // TS2PANDA_TS2ABC_TYPE_ADAPTER_H -- Gitee