diff --git a/ts2panda/BUILD.gn b/ts2panda/BUILD.gn index 411b0ff37b9984edecb44122d652a245a5337dc8..6ef40ce0dfc33e0efa0616a46ea16d355b4095ea 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 1224946ba0afa900d56e72b90d6d9463c9a5ef26..4e108670db4789dfb4ba0e5bde0af7bc345a089b 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 d07d50d18d93755beca1f34616056e7c3131c518..52c1823865835a38e28d28a55d222b7401e51aeb 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 8718d3e7a178be3e01d9ce36771e2ccf7de7f7f4..54dffea6511fd2de85ee49deb71abc0771f2f7ff 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 4631de5527fb4be9d86c58e0ec7ffc703524bb27..f5b42a5d9d87ee5d33459eedb2851f4bce7393cc 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 0000000000000000000000000000000000000000..117b88df4cddec4b958b26c10857c36e40d4614a --- /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 0000000000000000000000000000000000000000..74fa91fa82214c99d57e71bbd5f1d55348ec21a6 --- /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 277d29d21b1fa5dd4627b61d499063b41595ea5c..802ac449b896c5e5152e441e991b5429b90273f4 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 0000000000000000000000000000000000000000..8c383f175dc1bb79df23c39b460e1a7c5e972104 --- /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 0000000000000000000000000000000000000000..fb767c78ee5a23319121b0c92469ac2f283436d3 --- /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