diff --git a/ts2panda/BUILD.gn b/ts2panda/BUILD.gn index 1424e00fcd110f0a11150b0a3640173a219eff2f..635a2fb82c7aab705a2a48d3800510fd05e4d9f5 100755 --- a/ts2panda/BUILD.gn +++ b/ts2panda/BUILD.gn @@ -267,10 +267,3 @@ group("ts2abc_unittests") { 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(${toolchain_linux})" ] - } -} diff --git a/ts2panda/src/lexenv.ts b/ts2panda/src/lexenv.ts index e6864a8e07ae4f8e9199c15da11d94534dd70f92..a5d2e2308ce0d3e35ecf1c04a9ba8e0589d539b2 100644 --- a/ts2panda/src/lexenv.ts +++ b/ts2panda/src/lexenv.ts @@ -174,7 +174,9 @@ export class VariableAcessStore extends VariableAccessBase { // save the value first let valueReg: VReg = pandaGen.getTemp(); - insns.push(storeAccumulator(valueReg)); + let storeAccInst: IRNode = storeAccumulator(valueReg); + pandaGen.setInstType(storeAccInst, v.getTypeIndex()); + insns.push(storeAccInst); let slot = v.idxLex; if (v.isLetOrConst() || v.isClass()) { diff --git a/ts2panda/src/pandagen.ts b/ts2panda/src/pandagen.ts index 394206fe833b49d37a7d15ea60962dcac83fb64f..4a43d4f83d5b46553b850b201c07508640606c77 100644 --- a/ts2panda/src/pandagen.ts +++ b/ts2panda/src/pandagen.ts @@ -200,6 +200,7 @@ export class PandaGen { private locals: VReg[] = []; private temps: VReg[] = []; private insns: IRNode[] = []; + private instTypeMap: Map = new Map(); private scope: Scope | undefined; private vregisterCache: VregisterCache; private catchMap: Map = new Map(); @@ -408,6 +409,10 @@ export class PandaGen { this.locals = locals; } + getInstTypeMap() { + return this.instTypeMap; + } + getLocals(): VReg[] { return this.locals; } @@ -1360,4 +1365,10 @@ export class PandaGen { this.insns.push(...insns); } + + public setInstType(inst: IRNode, typeId: number | undefined): void { + if (typeId != undefined && TypeRecorder.getInstance() != undefined) { + this.instTypeMap.set(inst, typeId); + } + } } diff --git a/ts2panda/src/ts2panda.ts b/ts2panda/src/ts2panda.ts index 384f5fb0dc27feff742140de28ab6f0698baa389..0a7f54dc144c659c64b333da6204f4e6e7fe483c 100644 --- a/ts2panda/src/ts2panda.ts +++ b/ts2panda/src/ts2panda.ts @@ -48,7 +48,7 @@ import { LiteralBuffer } from "./base/literal"; import { CompilerDriver } from "./compilerDriver"; import { ModuleScope } from "./scope"; import { getRecordTypeFlag } from "./base/util"; -import { TypeSummary } from "./base/typeSystem"; +import { PrimitiveType, BuiltinType } from "./base/typeSystem"; import { TypeRecorder } from "./typeRecorder"; import { isGlobalDeclare } from "./strictMode"; @@ -207,6 +207,67 @@ export class Ts2Panda { ts2abc.stdio[3].write(jsonOpt + '\n'); } + // @ts-ignore + static dumpInstTypeMap(pg: PandaGen): any { + let insts = pg.getInsns(); + let locals = pg.getLocals(); + + // build instidx - typeidx map + let handledSet: Set = new Set(); + let instTypeMap: Map = new Map(); + let paraCount = pg.getParametersCount(); + let vregCount = pg.getTotalRegsNum() - paraCount; + for (let i = 0; i < insts.length; i++) { + let inst = insts[i]; + let typeIdx = pg.getInstTypeMap().get(inst); + if (typeIdx != undefined) { + instTypeMap.set(i, typeIdx); + continue; + } + + // get builtin type for tryloadglobal instruction + if (inst.kind == IRNodeKind.ECMA_TRYLDGLOBALBYNAME) { + let name = inst.operands[0] as string; + if (name in BuiltinType) { + typeIdx = BuiltinType[name]; + instTypeMap.set(i, typeIdx); + } + continue; + } + + // local vreg -> inst + let vreg = undefined; + let instIdx = i; + if (i < paraCount && inst.kind == IRNodeKind.MOV_DYN) { + vreg = (inst.operands[0] as VReg).num; + let arg = (inst.operands[1] as VReg).num; + if (vreg >= paraCount || arg < vregCount) { + continue; // not arg + } + // param's inst idx start from -1 + instIdx = vregCount - arg - 1; + } else if (inst.kind == IRNodeKind.STA_DYN) { + vreg = (inst.operands[0] as VReg).num; + } + if (vreg != undefined && vreg < locals.length && !handledSet.has(vreg)) { + typeIdx = locals[vreg].getTypeIndex(); + instTypeMap.set(instIdx, typeIdx); + handledSet.add(vreg); + } + } + + // sort and save type info + let typeInfo = new Array(); + [...instTypeMap].sort((a, b) => a[0] - b[0]).forEach(([instIdx, typeIdx]) => { + if (typeIdx != PrimitiveType.ANY) { + typeInfo.push(instIdx); + typeInfo.push(typeIdx); + } + }); + + return typeInfo; + } + // @ts-ignore static dumpPandaGen(pg: PandaGen, ts2abc: any, recordType?: boolean): void { let funcName = pg.internalName; @@ -219,16 +280,16 @@ export class Ts2Panda { let exportedSymbol2Types: undefined | Array = undefined; let declaredSymbol2Types: undefined | Array = undefined; if (CmdOptions.needRecordType() && CompilerDriver.isTsFile) { - typeInfo = new Array(); - typeRecord.forEach((vreg) => { - typeInfo.push(vreg.getTypeIndex()); - if (CmdOptions.enableTypeLog()) { + if (CmdOptions.enableTypeLog()) { + console.log("[", funcName, "]"); + typeRecord.forEach((vreg) => { console.log("---------------------------------------"); console.log("- vreg name:", vreg.getVariableName()); console.log("- vreg local num:", vreg.num); console.log("- vreg type:", vreg.getTypeIndex()); - } - }); + }); + } + typeInfo = Ts2Panda.dumpInstTypeMap(pg); if (funcName == "func_main_0") { let exportedTypes = PandaGen.getExportedTypes(); diff --git a/ts2panda/ts2abc/BUILD.gn b/ts2panda/ts2abc/BUILD.gn index 0abc5e79b96348768bde35e4f7872e06a2044319..a6ee96c5ab999a41c2bc54b2fa9d5ae469e53536 100755 --- a/ts2panda/ts2abc/BUILD.gn +++ b/ts2panda/ts2abc/BUILD.gn @@ -81,7 +81,6 @@ if (!defined(ark_independent_build)) { sources = [ "main.cpp", "ts2abc.cpp", - "type_adapter.cpp", ] configs = [ ":ts2abc_config" ] diff --git a/ts2panda/ts2abc/tests/type_adapter_test/BUILD.gn b/ts2panda/ts2abc/tests/type_adapter_test/BUILD.gn deleted file mode 100644 index cf9904458cde61776b5c6c59db4e39db9cbc8681..0000000000000000000000000000000000000000 --- a/ts2panda/ts2abc/tests/type_adapter_test/BUILD.gn +++ /dev/null @@ -1,60 +0,0 @@ -# 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("//arkcompiler/ets_frontend/ts2panda/ts2abc_config.gni") -import("//arkcompiler/runtime_core/ark_config.gni") - -ohos_executable("ts2abc_type_adapter_unit_tests") { - sources = [ - "//arkcompiler/ets_frontend/ts2panda/ts2abc/type_adapter.cpp", - "type_adapter_test.cpp", - ] - - configs = [ "//arkcompiler/ets_frontend/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 deleted file mode 100644 index 9f989d125d29469b75932608015618dce95b5ed4..0000000000000000000000000000000000000000 --- a/ts2panda/ts2abc/tests/type_adapter_test/type_adapter_test.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - * 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" - -namespace ts2abc_type_adapter::type_adapter_test { -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:(any,any)"); - 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); -} -} // namespace ts2abc_type_adapter::type_adapter_test - -int main() -{ - ts2abc_type_adapter::type_adapter_test::TypeAdapterTest test; - std::cout << "TypeAdapterTest TestVariablesArgsType: " << std::endl; - test.TestVariablesArgsType(); - std::cout << "PASS!" << std::endl; - return 0; - // should enable TestBuiltinsType when builtins adaption is ready -} diff --git a/ts2panda/ts2abc/ts2abc.cpp b/ts2panda/ts2abc/ts2abc.cpp index 0fdb1b1b4c067b147656d751ba9453a56ef5787f..ebd96d2f48ed0c7b34cb6b6d9a3aa652fe951d03 100644 --- a/ts2panda/ts2abc/ts2abc.cpp +++ b/ts2panda/ts2abc/ts2abc.cpp @@ -27,7 +27,6 @@ #include "securec.h" #include "ts2abc_options.h" #include "ts2abc.h" -#include "type_adapter.h" #include "protobufSnapshotGenerator.h" #ifdef ENABLE_BYTECODE_OPT @@ -46,7 +45,8 @@ bool g_displayTypeinfo = false; bool g_isDtsFile = false; std::string g_optLogLevel = "error"; uint32_t g_literalArrayCount = 0; -using ts2abc_type_adapter::TypeAdapter; +static constexpr const char* TSTYPE_ANNO_RECORD_NAME = "_ESTypeAnnotation"; +static constexpr const char* TSTYPE_ANNO_ELEMENT_NAME = "_TypeOfInstruction"; std::string g_compilerOutputProto = ""; constexpr std::size_t BOUND_LEFT = 0; @@ -602,27 +602,66 @@ static void ParseFunctionCallType(const Json::Value &function, panda::pandasm::F pandaFunc.metadata->GetAnnotations()).push_back(std::move(callTypeAnnotation)); } -static void ParseFunctionTypeInfo(const Json::Value &function, panda::pandasm::Function &pandaFunc) +static std::vector> GetInstTypeMap(const Json::Value &function, + panda::pandasm::Function &pandaFunc) { - if (function.isMember("ti") && function["ti"].isArray()) { - auto typeInfo = function["ti"]; - panda::pandasm::AnnotationData funcAnnotation(TypeAdapter::TSTYPE_ANNO_RECORD_NAME); - std::vector elements; + constexpr const char* TYPE_INFO = "ti"; + std::vector> instTypeMap; + if (!function.isMember(TYPE_INFO) || !function[TYPE_INFO].isArray()) { + return instTypeMap; + } - for (Json::ArrayIndex i = 0; i < typeInfo.size(); i++) { - auto typeIndex = typeInfo[i].asUInt(); + // must be instidx <-> typeidx pair + auto sourceTypeMap = function[TYPE_INFO]; + constexpr size_t TYPE_MAP_ELEMENT_SIZE = 2; + ASSERT(sourceTypeMap.size() % TYPE_MAP_ELEMENT_SIZE == 0); + instTypeMap.reserve(sourceTypeMap.size() / TYPE_MAP_ELEMENT_SIZE); - panda::pandasm::ScalarValue vNum( - panda::pandasm::ScalarValue::Create(i)); - elements.emplace_back(std::move(vNum)); - panda::pandasm::ScalarValue tIndex( - panda::pandasm::ScalarValue::Create(typeIndex)); - elements.emplace_back(std::move(tIndex)); + // fix inst index since invalid inst won't be emit + int32_t start = 0; + int32_t remove = 0; + for (Json::ArrayIndex i = 0; i < sourceTypeMap.size(); i += TYPE_MAP_ELEMENT_SIZE) { + auto instIndex = sourceTypeMap[i].asInt(); + auto typeIndex = sourceTypeMap[i + 1].asUInt(); + if (instIndex < 0) { // para + instTypeMap.emplace_back(instIndex, typeIndex); + continue; + } + + // remove the invalid instruction + for (; start < instIndex; start++) { + if (pandaFunc.ins[start].opcode == panda::pandasm::Opcode::INVALID) { + remove++; + } + } + instTypeMap.emplace_back(instIndex - remove, typeIndex); + } + + if (g_displayTypeinfo) { + std::cout << "Handle types for function: " << pandaFunc.name << std::endl; + std::cout << "(instruction order, type): "; + for (auto &it : instTypeMap) { + std::cout << "(" << it.first << ", " << it.second << "), "; + } + std::cout << std::endl; + } + + return instTypeMap; +} + +static void ParseFunctionTypeInfo(const Json::Value &function, panda::pandasm::Function &pandaFunc) +{ + auto instTypeMap = GetInstTypeMap(function, pandaFunc); + if (!instTypeMap.empty()) { + std::vector elements; + for (auto &it : instTypeMap) { + elements.emplace_back(panda::pandasm::ScalarValue::Create(it.first)); + elements.emplace_back(panda::pandasm::ScalarValue::Create(it.second)); } - std::string annotationName = TypeAdapter::TSTYPE_ANNO_ELEMENT_NAME; + panda::pandasm::AnnotationData funcAnnotation(TSTYPE_ANNO_RECORD_NAME); panda::pandasm::AnnotationElement typeOfVregElement( - annotationName, std::make_unique(panda::pandasm::ArrayValue( + TSTYPE_ANNO_ELEMENT_NAME, std::make_unique(panda::pandasm::ArrayValue( panda::pandasm::Value::Type::U32, elements))); funcAnnotation.AddElement(std::move(typeOfVregElement)); const_cast&>(pandaFunc.metadata->GetAnnotations()).push_back( @@ -642,7 +681,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(TypeAdapter::TSTYPE_ANNO_RECORD_NAME); + panda::pandasm::AnnotationData funcAnnotation(TSTYPE_ANNO_RECORD_NAME); std::vector symbolElements; std::vector symbolTypeElements; for (Json::ArrayIndex i = 0; i < exportedTypes.size(); i++) { @@ -698,7 +737,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(TypeAdapter::TSTYPE_ANNO_RECORD_NAME); + panda::pandasm::AnnotationData funcAnnotation(TSTYPE_ANNO_RECORD_NAME); std::vector symbolElements; std::vector symbolTypeElements; for (Json::ArrayIndex i = 0; i < declaredTypes.size(); i++) { @@ -772,7 +811,7 @@ static void GenerateESCallTypeAnnotationRecord(panda::pandasm::Program &prog) } static void GenerateESTypeAnnotationRecord(panda::pandasm::Program &prog) { - auto tsTypeAnnotationRecord = panda::pandasm::Record(TypeAdapter::TSTYPE_ANNO_RECORD_NAME, LANG_EXT); + auto tsTypeAnnotationRecord = panda::pandasm::Record(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)); @@ -1315,9 +1354,6 @@ bool GenerateProgram([[maybe_unused]] const std::string &data, const std::string compilerOutputProto = options.GetCompilerOutputProto(); } - 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 deleted file mode 100644 index 41b66dd75eea342c3de0c8fe7d45a26ba1001d27..0000000000000000000000000000000000000000 --- a/ts2panda/ts2abc/type_adapter.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* - * 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" - -namespace ts2abc_type_adapter { -void TypeAdapter::AdaptTypeForProgram(panda::pandasm::Program *prog) const -{ - for (auto &[name, func] : prog->function_table) { - if (ShouldDisplayTypeInfo()) { - std::cout << "Handle types for function: " << 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++; - - FillInBuiltinType(insn, order_type_map, 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 = static_cast(func->regs_num) - static_cast(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::FillInBuiltinType(const panda::pandasm::Ins &insn, - std::unordered_map &order_type_map, - const int32_t order) const -{ - if (insn.opcode != panda::pandasm::Opcode::ECMA_TRYLDGLOBALBYNAME) { - return; - } - - auto objName = insn.ids[0]; - auto typeIter = std::find(builtinTypes.begin(), builtinTypes.end(), objName); - if (typeIter != builtinTypes.end()) { - int builtinTypeIdx = typeIter - builtinTypes.begin() + builtinTypeOffset; - order_type_map.emplace(order - 1, builtinTypeIdx); - } -} - -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"; - } -} -} // namespace ts2abc_type_adapter diff --git a/ts2panda/ts2abc/type_adapter.h b/ts2panda/ts2abc/type_adapter.h deleted file mode 100644 index 35a8ea423dea4d63eb7b6192c5c4ada8f21a4271..0000000000000000000000000000000000000000 --- a/ts2panda/ts2abc/type_adapter.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * 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" - -namespace ts2abc_type_adapter { -const int builtinTypeOffset = 21; -const std::vector builtinTypes { - "Function", - "RangeError", - "Error", - "Object", - "SyntaxError", - "TypeError", - "ReferenceError", - "URIError", - "Symbol", - "EvalError", - "Number", - "parseFloat", - "Date", - "Boolean", - "BigInt", - "parseInt", - "WeakMap", - "RegExp", - "Set", - "Map", - "WeakRef", - "WeakSet", - "FinalizationRegistry", - "Array", - "Uint8ClampedArray", - "Uint8Array", - "TypedArray", - "Int8Array", - "Uint16Array", - "Uint32Array", - "Int16Array", - "Int32Array", - "Float32Array", - "Float64Array", - "BigInt64Array", - "BigUint64Array", - "SharedArrayBuffer", - "DataView", - "String", - "ArrayBuffer", - "eval", - "isFinite", - "ArkPrivate", - "print", - "decodeURI", - "decodeURIComponent", - "isNaN", - "encodeURI", - "NaN", - "globalThis", - "encodeURIComponent", - "Infinity", - "Math", - "JSON", - "Atomics", - "undefined", - "Reflect", - "Promise", - "Proxy", - "GeneratorFunction", - "Intl", -}; - -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 FillInBuiltinType(const panda::pandasm::Ins &insn, std::unordered_map &order_type_map, - const int32_t order) 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; -}; -} // namespace ts2abc_type_adapter - -#endif // TS2PANDA_TS2ABC_TYPE_ADAPTER_H