mirror of
https://github.com/openharmony/ark_ts2abc.git
synced 2026-07-01 09:24:57 -04:00
!309 Store type info as pairs of instruction orders and types
Merge pull request !309 from qiuyu/master
This commit is contained in:
@@ -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})" ]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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, '#$') + "$";
|
||||
|
||||
@@ -80,6 +80,7 @@ if (!defined(ark_independent_build)) {
|
||||
sources = [
|
||||
"main.cpp",
|
||||
"ts2abc.cpp",
|
||||
"type_adapter.cpp",
|
||||
]
|
||||
|
||||
configs = [ ":ts2abc_config" ]
|
||||
|
||||
@@ -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",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
@@ -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 <typename T1, typename T2>
|
||||
inline void TestAssertEqual(const T1 &left, const T2 &right) const
|
||||
{
|
||||
if (left != static_cast<T1>(right)) {
|
||||
std::cout << "assertion equal failed." << std::endl;
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline void TestAssertNotEqual(const T1 &left, const T2 &right) const
|
||||
{
|
||||
if (left == static_cast<T1>(right)) {
|
||||
std::cout << "assertion not equal failed." << std::endl;
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class TypeAdapterTest : TestBase {
|
||||
public:
|
||||
void TestVariablesArgsType() const;
|
||||
void TestBuiltinsType() const;
|
||||
|
||||
std::unordered_map<int32_t, int32_t> 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_map<int32_t, int32_t>type_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<int32_t>(), values[i + 1].GetValue<int32_t>());
|
||||
}
|
||||
return type_info;
|
||||
}
|
||||
|
||||
void CheckTypeExist(const std::unordered_map<int32_t, int32_t> &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<ScalarValue> *elements, int32_t order, int32_t type) const
|
||||
{
|
||||
ScalarValue insn_order(ScalarValue::Create<panda::pandasm::Value::Type::I32>(order));
|
||||
elements->emplace_back(std::move(insn_order));
|
||||
ScalarValue insn_type(ScalarValue::Create<panda::pandasm::Value::Type::I32>(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<ScalarValue> 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<ArrayValue>(arr));
|
||||
AnnotationData anno_data(TypeAdapter::TSTYPE_ANNO_RECORD_NAME);
|
||||
anno_data.AddElement(std::move(anno_ele));
|
||||
std::vector<panda::pandasm::AnnotationData> 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
|
||||
}
|
||||
@@ -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<panda::pandasm::ScalarValue> 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::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<panda::pandasm::ScalarValue> symbolElements;
|
||||
std::vector<panda::pandasm::ScalarValue> 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<panda::pandasm::ScalarValue> symbolElements;
|
||||
std::vector<panda::pandasm::ScalarValue> 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<int>(OptLevel::O_LEVEL0) || optLevel != static_cast<int>(OptLevel::O_LEVEL0)) {
|
||||
optLogLevel = (optLogLevel != "error") ? optLogLevel : g_optLogLevel;
|
||||
|
||||
@@ -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<int32_t, int32_t> 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<int32_t>(values[i++].GetValue<uint32_t>());
|
||||
auto type = static_cast<int32_t>(values[i++].GetValue<uint32_t>());
|
||||
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<int32_t, int32_t> &vreg_type_map) const
|
||||
{
|
||||
std::unordered_map<int32_t, int32_t> order_type_map;
|
||||
std::vector<int32_t> 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<int32_t, int32_t> &order_type_map) const
|
||||
{
|
||||
ASSERT(anno_idx <= func->metadata->GetAnnotations().size());
|
||||
if (anno_idx == func->metadata->GetAnnotations().size()) {
|
||||
std::vector<panda::pandasm::AnnotationData> added_datas;
|
||||
panda::pandasm::AnnotationData data(TSTYPE_ANNO_RECORD_NAME);
|
||||
added_datas.push_back(std::forward<panda::pandasm::AnnotationData>(data));
|
||||
func->metadata->AddAnnotations(std::forward<std::vector<panda::pandasm::AnnotationData>>(added_datas));
|
||||
ele_idx = 0;
|
||||
}
|
||||
|
||||
using ArrayValue = panda::pandasm::ArrayValue;
|
||||
using ScalarValue = panda::pandasm::ScalarValue;
|
||||
std::vector<ScalarValue> elements;
|
||||
for (const auto &[order, type] : order_type_map) {
|
||||
ScalarValue insn_order(ScalarValue::Create<panda::pandasm::Value::Type::I32>(order));
|
||||
elements.emplace_back(std::move(insn_order));
|
||||
ScalarValue insn_type(ScalarValue::Create<panda::pandasm::Value::Type::I32>(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<ArrayValue>(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<int32_t>(vars[i].GetValue<int32_t>()) << ", "
|
||||
<< static_cast<int32_t>(vars[i + 1].GetValue<uint32_t>()) << "), ";
|
||||
}
|
||||
std::cout << "\n";
|
||||
}
|
||||
}
|
||||
@@ -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<int32_t, int32_t> &vreg_type_map) const;
|
||||
void UpdateTypeAnnotation(panda::pandasm::Function *func, size_t anno_idx, size_t ele_idx,
|
||||
const std::unordered_map<int32_t, int32_t> &order_type_map) const;
|
||||
bool display_typeinfo_ = false;
|
||||
};
|
||||
|
||||
#endif // TS2PANDA_TS2ABC_TYPE_ADAPTER_H
|
||||
Reference in New Issue
Block a user