mirror of
https://github.com/openharmony/ark_runtime_core.git
synced 2026-07-01 13:17:23 -04:00
!6 Remove builtins from ISA
Merge pull request !6 from bolshov.maxim/master
This commit is contained in:
@@ -25,7 +25,6 @@ config("arkassembler_public_config") {
|
||||
}
|
||||
|
||||
libarkassembler_sources = [
|
||||
"$target_gen_dir/builtin_parsing.cpp",
|
||||
"$target_gen_dir/ins_to_string.cpp",
|
||||
"annotation.cpp",
|
||||
"assembly-emitter.cpp",
|
||||
@@ -55,9 +54,7 @@ ohos_shared_library("libarkassembler") {
|
||||
|
||||
deps = [
|
||||
":ark_asm_ecmascript_meta_gen_h",
|
||||
":ark_asm_ins_create_builtins_api_h",
|
||||
":ark_asm_meta_gen_h",
|
||||
":builtin_parsing_cpp",
|
||||
":isa_gen_libarkassembler_ins_create_api_h",
|
||||
":isa_gen_libarkassembler_ins_emit_h",
|
||||
":isa_gen_libarkassembler_ins_to_string_cpp",
|
||||
@@ -82,9 +79,7 @@ ohos_static_library("libarkassembler_frontend_static") {
|
||||
|
||||
deps = [
|
||||
":ark_asm_ecmascript_meta_gen_h",
|
||||
":ark_asm_ins_create_builtins_api_h",
|
||||
":ark_asm_meta_gen_h",
|
||||
":builtin_parsing_cpp",
|
||||
":isa_gen_libarkassembler_ins_create_api_h",
|
||||
":isa_gen_libarkassembler_ins_emit_h",
|
||||
":isa_gen_libarkassembler_ins_to_string_cpp",
|
||||
@@ -140,11 +135,6 @@ ark_isa_gen("isa_gen_libarkassembler") {
|
||||
"asm_isapi.rb",
|
||||
"../libpandafile/pandafile_isapi.rb",
|
||||
]
|
||||
extra_dependencies = [
|
||||
":ark_asm_ins_create_builtins_api_h",
|
||||
":builtin_parsing_cpp",
|
||||
":builtin_parsing_tests_cpp",
|
||||
]
|
||||
}
|
||||
|
||||
ark_gen_file("ark_asm_meta_gen_h") {
|
||||
@@ -154,27 +144,6 @@ ark_gen_file("ark_asm_meta_gen_h") {
|
||||
output_file = "$target_gen_dir/meta_gen.h"
|
||||
}
|
||||
|
||||
ark_gen_file("ark_asm_ins_create_builtins_api_h") {
|
||||
template_file = "templates/ins_create_builtins_api.h.erb"
|
||||
data_file = "../isa/builtins.yaml"
|
||||
requires = [ "../isa/builtinsapi.rb" ]
|
||||
output_file = "$target_gen_dir/ins_create_builtins_api.h"
|
||||
}
|
||||
|
||||
ark_gen_file("builtin_parsing_cpp") {
|
||||
template_file = "templates/builtin_parsing.cpp.erb"
|
||||
data_file = "../isa/builtins.yaml"
|
||||
requires = [ "../isa/builtinsapi.rb" ]
|
||||
output_file = "$target_gen_dir/builtin_parsing.cpp"
|
||||
}
|
||||
|
||||
ark_gen_file("builtin_parsing_tests_cpp") {
|
||||
template_file = "templates/builtin_parsing_tests.cpp.erb"
|
||||
data_file = "../isa/builtins.yaml"
|
||||
requires = [ "../isa/builtinsapi.rb" ]
|
||||
output_file = "$target_gen_dir/builtin_parsing_tests.cpp"
|
||||
}
|
||||
|
||||
ark_gen_file("ark_asm_ecmascript_meta_gen_h") {
|
||||
template_file = "templates/meta_gen.cpp.erb"
|
||||
data_file = "extensions/ecmascript/metadata.yaml"
|
||||
|
||||
@@ -16,33 +16,9 @@ project(assembler CXX)
|
||||
|
||||
panda_add_executable(ark_asm pandasm.cpp)
|
||||
|
||||
set(INS_CREATE_BUILTINS_API_H ${CMAKE_CURRENT_BINARY_DIR}/ins_create_builtins_api.h)
|
||||
panda_gen_file(
|
||||
DATAFILE ${PANDA_ROOT}/isa/builtins.yaml
|
||||
TEMPLATE ${CMAKE_CURRENT_SOURCE_DIR}/templates/ins_create_builtins_api.h.erb
|
||||
REQUIRES ${PANDA_ROOT}/isa/builtinsapi.rb
|
||||
OUTPUTFILE ${INS_CREATE_BUILTINS_API_H}
|
||||
)
|
||||
|
||||
set(BUILTIN_PARSING_CPP ${CMAKE_CURRENT_BINARY_DIR}/builtin_parsing.cpp)
|
||||
panda_gen_file(
|
||||
DATAFILE ${PANDA_ROOT}/isa/builtins.yaml
|
||||
TEMPLATE ${CMAKE_CURRENT_SOURCE_DIR}/templates/builtin_parsing.cpp.erb
|
||||
REQUIRES ${PANDA_ROOT}/isa/builtinsapi.rb
|
||||
OUTPUTFILE ${BUILTIN_PARSING_CPP}
|
||||
)
|
||||
|
||||
set(PANDASM_BIN_TESTS ${CMAKE_CURRENT_BINARY_DIR}/tests)
|
||||
file(MAKE_DIRECTORY "${PANDASM_BIN_TESTS}")
|
||||
|
||||
set(BUILTIN_PARSING_TESTS_CPP ${PANDASM_BIN_TESTS}/builtin_parsing_tests.cpp)
|
||||
panda_gen_file(
|
||||
DATAFILE ${PANDA_ROOT}/isa/builtins.yaml
|
||||
TEMPLATE ${CMAKE_CURRENT_SOURCE_DIR}/templates/builtin_parsing_tests.cpp.erb
|
||||
REQUIRES ${PANDA_ROOT}/isa/builtinsapi.rb
|
||||
OUTPUTFILE ${BUILTIN_PARSING_TESTS_CPP}
|
||||
)
|
||||
|
||||
panda_isa_gen(
|
||||
TEMPLATES
|
||||
"isa.h.erb"
|
||||
@@ -54,10 +30,6 @@ panda_isa_gen(
|
||||
REQUIRES
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/asm_isapi.rb"
|
||||
"${PANDA_ROOT}/libpandafile/pandafile_isapi.rb"
|
||||
EXTRA_DEPENDENCIES
|
||||
${INS_CREATE_BUILTINS_API_H}
|
||||
${BUILTIN_PARSING_CPP}
|
||||
${BUILTIN_PARSING_TESTS_CPP}
|
||||
)
|
||||
|
||||
add_library(arkassembler ${PANDA_DEFAULT_LIB_TYPE}
|
||||
@@ -73,7 +45,6 @@ add_library(arkassembler ${PANDA_DEFAULT_LIB_TYPE}
|
||||
ins_to_string.cpp
|
||||
extensions/extensions.cpp
|
||||
extensions/ecmascript/ecmascript_meta.cpp
|
||||
builtin_parsing.cpp
|
||||
)
|
||||
|
||||
add_dependencies(arkassembler isa_gen_assembler arkfile)
|
||||
@@ -122,7 +93,6 @@ panda_add_gtest(
|
||||
tests/parser_test.cpp
|
||||
tests/emitter_test.cpp
|
||||
tests/mangling_tests.cpp
|
||||
${PANDASM_BIN_TESTS}/builtin_parsing_tests.cpp
|
||||
LIBRARIES
|
||||
arkbase arkassembler
|
||||
SANITIZERS
|
||||
|
||||
@@ -17,10 +17,6 @@ Instruction.class_eval do
|
||||
mnemonic.tr('.', '_').upcase
|
||||
end
|
||||
|
||||
def builtin?
|
||||
stripped_mnemonic == 'builtin'
|
||||
end
|
||||
|
||||
def call?
|
||||
properties.include?('call') || stripped_mnemonic == 'initobj'
|
||||
end
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "assembly-parser.h"
|
||||
|
||||
// Autogenerated file -- DO NOT EDIT!
|
||||
|
||||
namespace panda::pandasm {
|
||||
|
||||
int64_t Parser::MnemonicToBuiltinId() {
|
||||
[[maybe_unused]] const auto token = context_.GiveToken();
|
||||
|
||||
--context_;
|
||||
[[maybe_unused]] const auto ins = context_.GiveToken();
|
||||
++context_;
|
||||
|
||||
% PandaBuiltins::builtins.each_with_index do |builtin, i|
|
||||
%
|
||||
<%= i != 0 ? "else " : "" %>if (token == "<%= builtin.mnemonic%>" && ins == "<%= builtin.insn%>") {
|
||||
return static_cast<int64_t>(<%= builtin.id%>);
|
||||
}
|
||||
%
|
||||
% end
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool Parser::ParseOperandBuiltinMnemonic() {
|
||||
if (context_.err.err != Error::ErrorType::ERR_NONE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*context_ != Token::Type::ID) {
|
||||
context_.err = GetError("Expected Mnemonic", Error::ErrorType::ERR_BAD_OPERAND);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto builtin_id = MnemonicToBuiltinId();
|
||||
if (builtin_id != -1) {
|
||||
curr_ins_->imms.insert(curr_ins_->imms.begin(), builtin_id);
|
||||
} else {
|
||||
context_.err = GetError("The non-public extension of ISA does not contain such a builtin", Error::ErrorType::ERR_BAD_MNEMONIC_NAME);
|
||||
return false;
|
||||
}
|
||||
|
||||
++context_;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace panda::pandasm
|
||||
@@ -1,146 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include "assembly-parser.h"
|
||||
#include "define.h"
|
||||
#include "lexer.h"
|
||||
#include "operand_types_print.h"
|
||||
|
||||
using namespace panda::pandasm;
|
||||
|
||||
% PandaBuiltins::builtins.each do |builtin|
|
||||
%
|
||||
TEST(builtinparsingtests, builtins_<%=builtin.insn.tr('.', '_')%>_id<%=builtin.id%>)
|
||||
{
|
||||
Parser p;
|
||||
std::string src = std::string(R"(
|
||||
.function void g() {
|
||||
<%=builtin.insn%> <%=builtin.mnemonic%>)"
|
||||
% PandaBuiltins::instructions.each do |insn|
|
||||
%
|
||||
% if (insn.mnemonic == builtin.insn)
|
||||
%
|
||||
% insn.sig.split(', ').each_with_index do |op, i|
|
||||
% if (i != 0)
|
||||
% if (op.start_with?('v'))
|
||||
", v<%=i%>"
|
||||
% elsif (op.start_with?('imm'))
|
||||
", <%=i%>"
|
||||
% elsif (op == 'type_id')
|
||||
", A"
|
||||
% elsif (op == 'method_id')
|
||||
", g"
|
||||
% elsif (op == 'string_id')
|
||||
", \"string_string\""
|
||||
% elsif (op == 'field_id')
|
||||
", A.B"
|
||||
% end
|
||||
% end
|
||||
% end
|
||||
%
|
||||
% end
|
||||
% end
|
||||
"\nreturn.void\n}\n");
|
||||
|
||||
auto res = p.Parse(src);
|
||||
|
||||
Error e = p.ShowError();
|
||||
|
||||
ASSERT_EQ(e.err, Error::ErrorType::ERR_NONE);
|
||||
}
|
||||
%
|
||||
% end
|
||||
|
||||
% PandaBuiltins::instructions.each do |insn|
|
||||
%
|
||||
TEST(builtinparsingtests, builtins_<%=insn.mnemonic.tr('.', '_')%>_bad_mnemonic_name) {
|
||||
{
|
||||
Parser p;
|
||||
std::string src = std::string(R"(
|
||||
.function void g() {
|
||||
<%=insn.mnemonic%> wrong_mnemonic)"
|
||||
% insn.sig.split(', ').each_with_index do |op, i|
|
||||
% if (i != 0)
|
||||
% if (op.start_with?('v'))
|
||||
", v<%=i%>"
|
||||
% elsif (op == 'imm')
|
||||
", <%=i%>"
|
||||
% elsif (op == 'type_id')
|
||||
", A"
|
||||
% elsif (op == 'method_id')
|
||||
", g"
|
||||
% elsif (op == 'string_id')
|
||||
", \"string_string\""
|
||||
% elsif (op == 'field_id')
|
||||
", A.B"
|
||||
% end
|
||||
% end
|
||||
% end
|
||||
"\nreturn.void\n}\n");
|
||||
|
||||
auto res = p.Parse(src);
|
||||
|
||||
Error e = p.ShowError();
|
||||
|
||||
ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_MNEMONIC_NAME);
|
||||
}
|
||||
}
|
||||
%
|
||||
% end
|
||||
|
||||
% PandaBuiltins::instructions.each do |insn|
|
||||
%
|
||||
TEST(builtinparsingtests, builtins_<%=insn.mnemonic.tr('.', '_')%>_bad_operand) {
|
||||
{
|
||||
Parser p;
|
||||
std::string src = std::string(R"(
|
||||
.record A {
|
||||
u1 B
|
||||
}
|
||||
.function void g() {
|
||||
<%=insn.mnemonic%> "")"
|
||||
% insn.sig.split(', ').each_with_index do |op, i|
|
||||
% if (i != 0)
|
||||
% if (op.start_with?('v'))
|
||||
", v<%=i%>"
|
||||
% elsif (op == 'imm')
|
||||
", <%=i%>"
|
||||
% elsif (op == 'type_id')
|
||||
", A"
|
||||
% elsif (op == 'method_id')
|
||||
", g"
|
||||
% elsif (op == 'string_id')
|
||||
", \"string_string\""
|
||||
% elsif (op == 'field_id')
|
||||
", A.B"
|
||||
% end
|
||||
% end
|
||||
% end
|
||||
"\nreturn.void\n}\n");
|
||||
|
||||
auto res = p.Parse(src);
|
||||
|
||||
Error e = p.ShowError();
|
||||
|
||||
ASSERT_EQ(e.err, Error::ErrorType::ERR_BAD_OPERAND);
|
||||
}
|
||||
}
|
||||
%
|
||||
% end
|
||||
|
||||
@@ -59,5 +59,3 @@ inline Ins Create_<%= insn.asm_token %>(<%= signature_str %>)
|
||||
|
||||
|
||||
} // namespace panda::pandasm
|
||||
|
||||
#include <ins_create_builtins_api.h>
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
// Autogenerated file -- DO NOT EDIT!
|
||||
|
||||
namespace panda::pandasm {
|
||||
|
||||
% PandaBuiltins::builtins.each do |builtin|
|
||||
% i_mnemo = builtin.insn.tr('.', '_').upcase
|
||||
% b_mnemo = builtin.mnemonic.tr('.', '_').upcase
|
||||
% sig = []
|
||||
% args = ['BUILTIN_ID']
|
||||
%
|
||||
% # NB! This logic below is very simplistic. May need proper
|
||||
% # work with formats in builtinsapi.rb some day.
|
||||
% format_list = builtin.format.split("_");
|
||||
% format_list.each_index do |i|
|
||||
% next if i == 0
|
||||
% if format_list[i] == "v4" then
|
||||
% sig << "uint16_t v" + i.to_s
|
||||
% args << "v" + i.to_s
|
||||
% elsif format_list[i] == "v8" then
|
||||
% sig << "uint16_t v" + i.to_s
|
||||
% args << "v" + i.to_s
|
||||
% elsif format_list[i] == "id16"
|
||||
% sig << "std::string& id" + i.to_s
|
||||
% args << "id" + i.to_s
|
||||
% elsif format_list[i] == "id32"
|
||||
% sig << "std::string& id" + i.to_s
|
||||
% args << "id" + i.to_s
|
||||
|
||||
% elsif format_list[i] == "imm8"
|
||||
% sig << "uint8_t imm" + i.to_s
|
||||
% args << "imm" + i.to_s
|
||||
% elsif format_list[i] == "imm16"
|
||||
% sig << "uint16_t imm" + i.to_s
|
||||
% args << "imm" + i.to_s
|
||||
% end
|
||||
% end
|
||||
inline Ins Create_BUILTIN_<%= b_mnemo %>(<%= sig.join(', ') %>)
|
||||
{
|
||||
constexpr uint8_t BUILTIN_ID = <%= builtin.id %>;
|
||||
return panda::pandasm::Create_<%= i_mnemo %>(<%= args.join(', ') %>);
|
||||
}
|
||||
|
||||
% end
|
||||
|
||||
} // namespace panda::pandasm
|
||||
@@ -83,9 +83,7 @@ bool Parser::ParseOperands()
|
||||
|
||||
ParseOperandVreg();
|
||||
% elsif op.imm?
|
||||
% if (insn.builtin? && j == 0)
|
||||
ParseOperandBuiltinMnemonic();
|
||||
% elsif properties.include?("jump")
|
||||
% if properties.include?("jump")
|
||||
ParseOperandLabel();
|
||||
% else
|
||||
% if properties.include?("float")
|
||||
|
||||
@@ -21,7 +21,6 @@ config("arkdisassembler_public_config") {
|
||||
arkdisassembler_sources = [
|
||||
"$target_gen_dir/bc_ins_to_pandasm_ins.cpp",
|
||||
"$target_gen_dir/get_ins_info.cpp",
|
||||
"$target_gen_dir/get_instructions.cpp",
|
||||
"$target_gen_dir/opcode_translator.cpp",
|
||||
"$target_gen_dir/type_to_pandasm_type.cpp",
|
||||
"disassembler.cpp",
|
||||
@@ -44,7 +43,6 @@ ohos_shared_library("arkdisassembler") {
|
||||
configs = arkdisassembler_configs
|
||||
|
||||
deps = [
|
||||
":get_instructions_cpp",
|
||||
":isa_gen_ark_disam_bc_ins_to_pandasm_ins_cpp",
|
||||
":isa_gen_ark_disam_get_ins_info_cpp",
|
||||
":isa_gen_ark_disam_opcode_translator_cpp",
|
||||
@@ -69,7 +67,6 @@ ohos_static_library("arkdisassembler_frontend_static") {
|
||||
configs = arkdisassembler_configs
|
||||
|
||||
deps = [
|
||||
":get_instructions_cpp",
|
||||
":isa_gen_ark_disam_bc_ins_to_pandasm_ins_cpp",
|
||||
":isa_gen_ark_disam_get_ins_info_cpp",
|
||||
":isa_gen_ark_disam_opcode_translator_cpp",
|
||||
@@ -123,13 +120,6 @@ ark_isa_gen("isa_gen_ark_disam") {
|
||||
]
|
||||
}
|
||||
|
||||
ark_gen_file("get_instructions_cpp") {
|
||||
template_file = "$ark_root/disassembler/templates/get_instructions.cpp.erb"
|
||||
data_file = "$ark_root/isa/builtins.yaml"
|
||||
requires = [ "$ark_root/isa/builtinsapi.rb" ]
|
||||
output_file = "$target_gen_dir/get_instructions.cpp"
|
||||
}
|
||||
|
||||
ark_gen_file("type_to_pandasm_type_cpp") {
|
||||
template_file =
|
||||
"$ark_root/disassembler/templates/type_to_pandasm_type.cpp.erb"
|
||||
|
||||
@@ -28,14 +28,6 @@ panda_isa_gen(
|
||||
${GET_INSTRUCTIONS_CPP}
|
||||
)
|
||||
|
||||
set(GET_INSTRUCTIONS_CPP ${CMAKE_CURRENT_BINARY_DIR}/get_instructions.cpp)
|
||||
panda_gen_file(
|
||||
DATAFILE ${PANDA_ROOT}/isa/builtins.yaml
|
||||
TEMPLATE ${CMAKE_CURRENT_SOURCE_DIR}/templates/get_instructions.cpp.erb
|
||||
REQUIRES ${PANDA_ROOT}/isa/builtinsapi.rb
|
||||
OUTPUTFILE ${GET_INSTRUCTIONS_CPP}
|
||||
)
|
||||
|
||||
set(GENERATOR ${PANDA_ROOT}/libpandafile/types.rb)
|
||||
set(TEMPLATE ${CMAKE_CURRENT_LIST_DIR}/templates/type_to_pandasm_type.cpp.erb)
|
||||
set(DATAFILE ${PANDA_ROOT}/libpandafile/types.yaml)
|
||||
@@ -53,7 +45,6 @@ add_library(arkdisassembler ${PANDA_DEFAULT_LIB_TYPE}
|
||||
bc_ins_to_pandasm_ins.cpp
|
||||
get_ins_info.cpp
|
||||
type_to_pandasm_type.cpp
|
||||
get_instructions.cpp
|
||||
)
|
||||
|
||||
target_include_directories(arkdisassembler
|
||||
|
||||
@@ -1348,4 +1348,89 @@ pandasm::extensions::Language Disassembler::GetClassLanguage(panda_file::File::E
|
||||
return PFLangToPandasmLang(cda.GetSourceLang());
|
||||
}
|
||||
|
||||
IdList Disassembler::GetInstructions(pandasm::Function *method, panda_file::File::EntityId method_id,
|
||||
panda_file::File::EntityId code_id) const
|
||||
{
|
||||
panda_file::CodeDataAccessor code_accessor(*file_, code_id);
|
||||
|
||||
const auto ins_sz = code_accessor.GetCodeSize();
|
||||
const auto ins_arr = code_accessor.GetInstructions();
|
||||
|
||||
method->regs_num = code_accessor.GetNumVregs();
|
||||
|
||||
auto bc_ins = BytecodeInstruction(ins_arr);
|
||||
const auto bc_ins_last = bc_ins.JumpTo(ins_sz);
|
||||
|
||||
LabelTable label_table = GetExceptions(method, method_id, code_id);
|
||||
|
||||
IdList unknown_external_methods {};
|
||||
|
||||
while (bc_ins.GetAddress() != bc_ins_last.GetAddress()) {
|
||||
if (bc_ins.GetAddress() > bc_ins_last.GetAddress()) {
|
||||
LOG(ERROR, DISASSEMBLER) << "> error encountered at " << std::dec << code_id.GetOffset() << " ("
|
||||
<< "0x" << std::hex << code_id.GetOffset()
|
||||
<< "). bytecode instructions sequence corrupted for method " << method->name
|
||||
<< "! went out of bounds";
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
auto pa_ins = BytecodeInstructionToPandasmInstruction(bc_ins, method_id, method->language);
|
||||
// alter instructions operands depending on instruction type
|
||||
if (pa_ins.IsConditionalJump() || pa_ins.IsJump()) {
|
||||
const int32_t jmp_offset = std::get<int64_t>(pa_ins.imms.at(0));
|
||||
const auto bc_ins_dest = bc_ins.JumpTo(jmp_offset);
|
||||
if (bc_ins_last.GetAddress() > bc_ins_dest.GetAddress()) {
|
||||
size_t idx = GetBytecodeInstructionNumber(BytecodeInstruction(ins_arr), bc_ins_dest);
|
||||
|
||||
if (idx != std::numeric_limits<size_t>::max()) {
|
||||
if (label_table.find(idx) == label_table.end()) {
|
||||
std::stringstream ss {};
|
||||
ss << "jump_label_" << label_table.size();
|
||||
label_table[idx] = ss.str();
|
||||
}
|
||||
|
||||
pa_ins.imms.clear();
|
||||
pa_ins.ids.push_back(label_table[idx]);
|
||||
} else {
|
||||
LOG(ERROR, DISASSEMBLER)
|
||||
<< "> error encountered at " << std::dec << code_id.GetOffset() << " ("
|
||||
<< "0x" << std::hex << code_id.GetOffset() << "). incorrect instruction at offset "
|
||||
<< (bc_ins.GetAddress() - ins_arr) << ": invalid jump offset " << jmp_offset
|
||||
<< " - jumping in the middle of another instruction!";
|
||||
}
|
||||
} else {
|
||||
LOG(ERROR, DISASSEMBLER) << "> error encountered at " << std::dec << code_id.GetOffset() << " ("
|
||||
<< "0x" << std::hex << code_id.GetOffset()
|
||||
<< "). incorrect instruction at offset: " << (bc_ins.GetAddress() - ins_arr)
|
||||
<< ": invalid jump offset " << jmp_offset << " - jumping out of bounds!";
|
||||
}
|
||||
}
|
||||
|
||||
// check if method id is unknown external method. if so, emplace it in table
|
||||
if (bc_ins.HasFlag(BytecodeInstruction::Flags::METHOD_ID)) {
|
||||
const auto arg_method_idx = bc_ins.GetId().AsIndex();
|
||||
const auto arg_method_id = file_->ResolveMethodIndex(method_id, arg_method_idx);
|
||||
|
||||
const auto arg_method_name = GetFullMethodName(arg_method_id, method->language);
|
||||
|
||||
const bool is_present = prog_.function_table.find(arg_method_name) != prog_.function_table.cend();
|
||||
const bool is_external = file_->IsExternal(arg_method_id);
|
||||
if (is_external && !is_present) {
|
||||
unknown_external_methods.push_back(arg_method_id);
|
||||
}
|
||||
}
|
||||
|
||||
method->ins.push_back(pa_ins);
|
||||
bc_ins = bc_ins.GetNext();
|
||||
}
|
||||
|
||||
for (const auto &pair : label_table) {
|
||||
method->ins[pair.first].label = pair.second;
|
||||
method->ins[pair.first].set_label = true;
|
||||
}
|
||||
|
||||
return unknown_external_methods;
|
||||
}
|
||||
|
||||
} // namespace panda::disasm
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "disassembler.h"
|
||||
|
||||
namespace panda::disasm {
|
||||
|
||||
IdList Disassembler::GetInstructions(pandasm::Function *method, panda_file::File::EntityId method_id,
|
||||
panda_file::File::EntityId code_id) const {
|
||||
panda_file::CodeDataAccessor code_accessor(*file_, code_id);
|
||||
|
||||
const auto ins_sz = code_accessor.GetCodeSize();
|
||||
const auto ins_arr = code_accessor.GetInstructions();
|
||||
|
||||
method->regs_num = code_accessor.GetNumVregs();
|
||||
|
||||
auto bc_ins = BytecodeInstruction(ins_arr);
|
||||
const auto bc_ins_last = bc_ins.JumpTo(ins_sz);
|
||||
|
||||
LabelTable label_table = GetExceptions(method, method_id, code_id);
|
||||
|
||||
IdList unknown_external_methods{};
|
||||
|
||||
while (bc_ins.GetAddress() != bc_ins_last.GetAddress()) {
|
||||
if (bc_ins.GetAddress() > bc_ins_last.GetAddress()) {
|
||||
LOG(ERROR, DISASSEMBLER) << "> error encountered at " << std::dec << code_id.GetOffset() << " (" << "0x" << std::hex
|
||||
<< code_id.GetOffset() << "). bytecode instructions sequence corrupted for method "
|
||||
<< method->name << "! went out of bounds";
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
auto pa_ins = BytecodeInstructionToPandasmInstruction(bc_ins, method_id, method->language);
|
||||
|
||||
// alter instructions operands depending on instruction type
|
||||
if (pa_ins.IsConditionalJump() || pa_ins.IsJump()) {
|
||||
const int32_t jmp_offset = std::get<int64_t>(pa_ins.imms.at(0));
|
||||
const auto bc_ins_dest = bc_ins.JumpTo(jmp_offset);
|
||||
if (bc_ins_last.GetAddress() > bc_ins_dest.GetAddress()) {
|
||||
size_t idx = GetBytecodeInstructionNumber(BytecodeInstruction(ins_arr), bc_ins_dest);
|
||||
|
||||
if (idx != std::numeric_limits<size_t>::max()) {
|
||||
if (label_table.find(idx) == label_table.end()) {
|
||||
std::stringstream ss{};
|
||||
ss << "jump_label_" << label_table.size();
|
||||
label_table[idx] = ss.str();
|
||||
}
|
||||
|
||||
pa_ins.imms.clear();
|
||||
pa_ins.ids.push_back(label_table[idx]);
|
||||
} else {
|
||||
LOG(ERROR, DISASSEMBLER) << "> error encountered at " << std::dec << code_id.GetOffset() << " ("
|
||||
<< "0x" << std::hex << code_id.GetOffset() << "). incorrect instruction at offset "
|
||||
<< (bc_ins.GetAddress() - ins_arr) << ": invalid jump offset "
|
||||
<< jmp_offset << " - jumping in the middle of another instruction!";
|
||||
|
||||
}
|
||||
} else {
|
||||
LOG(ERROR, DISASSEMBLER) << "> error encountered at " << std::dec << code_id.GetOffset() << " ("
|
||||
<< "0x" << std::hex << code_id.GetOffset()
|
||||
<< "). incorrect instruction at offset: " << (bc_ins.GetAddress() - ins_arr)
|
||||
<< ": invalid jump offset " << jmp_offset << " - jumping out of bounds!";
|
||||
}
|
||||
}
|
||||
|
||||
// if builtin - change imm to mnemonic
|
||||
switch (pa_ins.opcode) {
|
||||
% PandaBuiltins::instructions.each do |insn|
|
||||
case pandasm::Opcode::<%=insn.mnemonic.tr('.', '_').upcase%>:
|
||||
switch(pa_ins.imms[0].index()) {
|
||||
// contains int64_t
|
||||
case 0:
|
||||
switch (std::get<int64_t>(pa_ins.imms[0])) {
|
||||
% PandaBuiltins::builtins.each do |builtin|
|
||||
% if (builtin.insn == insn.mnemonic)
|
||||
case <%= builtin.id%>:
|
||||
pa_ins.ids.insert(pa_ins.ids.begin(), std::string("<%=builtin.mnemonic%>"));
|
||||
break;
|
||||
% end
|
||||
% end
|
||||
default:
|
||||
LOG(ERROR, DISASSEMBLER) << "> error encountered at " << std::dec << code_id.GetOffset() << " ("
|
||||
<< "0x" << std::hex << code_id.GetOffset()
|
||||
<< "). incorrect builtin mnemonic id!";
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
// float or nothing - throw error
|
||||
default:
|
||||
LOG(ERROR, DISASSEMBLER) << "> error encountered at " << std::dec << code_id.GetOffset() << " ("
|
||||
<< "0x" << std::hex << code_id.GetOffset()
|
||||
<< "). incorrect type of builtin mnemonic id! expected integer, but "
|
||||
"float (or nothing) received!";
|
||||
break;
|
||||
}
|
||||
pa_ins.imms.erase(pa_ins.imms.begin());
|
||||
|
||||
break;
|
||||
% end
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// check if method id is unknown external method. if so, emplace it in table
|
||||
if (bc_ins.HasFlag(BytecodeInstruction::Flags::METHOD_ID)) {
|
||||
const auto arg_method_idx = bc_ins.GetId().AsIndex();
|
||||
const auto arg_method_id = file_->ResolveMethodIndex(method_id, arg_method_idx);
|
||||
|
||||
const auto arg_method_name = GetFullMethodName(arg_method_id, method->language);
|
||||
|
||||
const bool is_present = prog_.function_table.find(arg_method_name) != prog_.function_table.cend();
|
||||
const bool is_external = file_->IsExternal(arg_method_id);
|
||||
if (is_external && !is_present) {
|
||||
unknown_external_methods.push_back(arg_method_id);
|
||||
}
|
||||
}
|
||||
|
||||
method->ins.push_back(pa_ins);
|
||||
bc_ins = bc_ins.GetNext();
|
||||
}
|
||||
|
||||
for (const auto& pair : label_table) {
|
||||
method->ins[pair.first].label = pair.second;
|
||||
method->ins[pair.first].set_label = true;
|
||||
}
|
||||
|
||||
return unknown_external_methods;
|
||||
}
|
||||
|
||||
} // namespace panda::disasm
|
||||
@@ -1,30 +0,0 @@
|
||||
# Copyright (c) 2021 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.
|
||||
|
||||
.function void g(f32 a0, f32 a1) {
|
||||
builtin.acc i32tof32
|
||||
builtin.acc i64tof32
|
||||
builtin.acc f64tof32
|
||||
builtin.acc monitorenter
|
||||
builtin.acc monitorexit
|
||||
|
||||
builtin.bin2 fadd2f32, a1
|
||||
builtin.bin2 fsub2f32, v13
|
||||
builtin.bin2 fmul2f32, v13
|
||||
builtin.bin2 fdiv2f32, v13
|
||||
builtin.bin2 fmod2f32, v13
|
||||
builtin.bin2 fcmpl2f32, a0
|
||||
builtin.bin2 fcmpg2f32, v13
|
||||
|
||||
return.void
|
||||
}
|
||||
@@ -1,398 +0,0 @@
|
||||
# Copyright (c) 2021 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.
|
||||
|
||||
---
|
||||
|
||||
# This is a non-public extension of Panda instruction set architecture.
|
||||
# Each group from the section below defines a single 'builtin.*' instruction
|
||||
# without predefined semantics. Each 'builtin.*' instruction can be
|
||||
# dispatched to maximum 256 handlers, each executing in the interpreter's
|
||||
# context (like all public instruction handlers do). These extension handlers
|
||||
# are called builtins. Dispatching 'builtin.*' instructions to actual handlers
|
||||
# is achieved via first immediate operand of each 'builtin.*' instruction.
|
||||
#
|
||||
# Following restrictions apply to the 'groups' section:
|
||||
#
|
||||
# * The entire 'groups' section must have exactly the same format as isa.yaml.
|
||||
# * Each group must define exactly one 'builtin.*' instruction.
|
||||
# * Each 'builtin.*' instruction must have exactly one encoding format.
|
||||
# This limitation is introduced to avoid writing complex and untestable
|
||||
# code generation routines -- currently "one instruction <=> one format"
|
||||
# is enough. Feel free to remove this constraint on demand.
|
||||
# * There must be no 'builtin.*' instructions with the same signature
|
||||
# (consult with the API for signature validation rules).
|
||||
#
|
||||
# Following restrtictions apply to the 'builtins' section:
|
||||
#
|
||||
# * All builtin names must be unique
|
||||
# * Signature of each builtin must match exactly one signature of some
|
||||
# 'builtin.*' instruction (consult with the API for signature matching rules).
|
||||
# Please note that there is no need to specify correspondence between
|
||||
# builtins and 'builtin.*' instructions explicitly, this done by the API.
|
||||
#
|
||||
# Following runtime restrictions apply to builtins handlers:
|
||||
#
|
||||
# * Builtin handler is not expected to run in parallel with GC at STW phase
|
||||
# * Builtin handler must not trigger runtime operations that start GC
|
||||
#
|
||||
# NB! Important note about ordering and dispatch table layout.
|
||||
# The order of builtin definitions in this file is not important. However,
|
||||
# API may reorder these definitions to guarantee following layout
|
||||
# for the dispatch table:
|
||||
#
|
||||
# public_opcode_01
|
||||
# public_opcode_02
|
||||
# ...
|
||||
# builtin_opcode_01
|
||||
# builtin_opcode_02
|
||||
# ...
|
||||
# builtin_01_for_builtin_opcode_01 \
|
||||
# builtin_02_for_builtin_opcode_01 | All builtins with signature of builtin_opcode_01
|
||||
# builtin_03_for_builtin_opcode_01 /
|
||||
# builtin_01_for_builtin_opcode_02 \
|
||||
# ... | All builtins with signature of builtin_opcode_02
|
||||
# builtin_NN_for_builtin_opcode_02 /
|
||||
#
|
||||
|
||||
groups:
|
||||
- title: Built-in operations without explicit operands
|
||||
description: Non-public extension of the instruction set.
|
||||
verification:
|
||||
- none
|
||||
exceptions:
|
||||
- x_none
|
||||
properties:
|
||||
- acc_read
|
||||
- acc_write
|
||||
pseudo: |
|
||||
builtin = resolve_builtin(imm)
|
||||
acc = builtin(acc)
|
||||
semantics: |
|
||||
skip
|
||||
instructions:
|
||||
- sig: builtin.acc imm
|
||||
acc: inout:top
|
||||
format: [op_imm_8]
|
||||
|
||||
- title: Built-in two address binary operations on accumulator
|
||||
description: Non-public extension of the instruction set.
|
||||
verification:
|
||||
- none
|
||||
exceptions:
|
||||
- x_none
|
||||
properties:
|
||||
- acc_read
|
||||
- acc_write
|
||||
pseudo: |
|
||||
builtin = resolve_builtin(imm)
|
||||
acc = builtin(acc, v)
|
||||
semantics: |
|
||||
skip
|
||||
instructions:
|
||||
- sig: builtin.bin2 imm, v:in:top
|
||||
acc: inout:top
|
||||
format: [op_imm_8_v_8]
|
||||
|
||||
- title: Built-in three address operations on accumulator
|
||||
description: Non-public extension of the instruction set.
|
||||
verification:
|
||||
- none
|
||||
exceptions:
|
||||
- x_none
|
||||
properties:
|
||||
- acc_read
|
||||
- acc_write
|
||||
pseudo: |
|
||||
builtin = resolve_builtin(imm)
|
||||
acc = builtin(acc, v1, v2)
|
||||
semantics: |
|
||||
skip
|
||||
instructions:
|
||||
- sig: builtin.tern3 imm, v1:in:top, v2:in:top
|
||||
acc: inout:top
|
||||
format: [op_imm_8_v1_8_v2_8]
|
||||
|
||||
- title: Built-in four address operations on accumulator
|
||||
description: Non-public extension of the instruction set.
|
||||
verification:
|
||||
- none
|
||||
exceptions:
|
||||
- x_none
|
||||
properties:
|
||||
- acc_read
|
||||
- acc_write
|
||||
pseudo: |
|
||||
builtin = resolve_builtin(imm)
|
||||
acc = builtin(acc, v1, v2, v3)
|
||||
semantics: |
|
||||
skip
|
||||
instructions:
|
||||
- sig: builtin.quatern4 imm, v1:in:top, v2:in:top, v3:in:top
|
||||
acc: inout:top
|
||||
format: [op_imm_8_v1_8_v2_8_v3_8]
|
||||
|
||||
- title: Built-in five address operations on accumulator
|
||||
description: Non-public extension of the instruction set.
|
||||
verification:
|
||||
- none
|
||||
exceptions:
|
||||
- x_none
|
||||
properties:
|
||||
- acc_read
|
||||
- acc_write
|
||||
pseudo: |
|
||||
builtin = resolve_builtin(imm)
|
||||
acc = builtin(acc, v1, v2, v3, v4)
|
||||
semantics: |
|
||||
skip
|
||||
instructions:
|
||||
- sig: builtin.quin5 imm, v1:in:top, v2:in:top, v3:in:top, v4:in:top
|
||||
acc: inout:top
|
||||
format: [op_imm_8_v1_8_v2_8_v3_8_v4_8]
|
||||
|
||||
- title: Built-in opcode for imm8_v
|
||||
description: Non-public extension of the instruction set.
|
||||
verification:
|
||||
- none
|
||||
exceptions:
|
||||
- x_none
|
||||
properties:
|
||||
- acc_read
|
||||
- acc_write
|
||||
pseudo: |
|
||||
builtin = resolve_builtin(imm1)
|
||||
acc = builtin(imm2, acc, v)
|
||||
semantics: |
|
||||
skip
|
||||
instructions:
|
||||
- sig: builtin.r2i imm1, imm2, v:in:top
|
||||
acc: inout:top
|
||||
format: [op_imm1_8_imm2_16_v_8]
|
||||
|
||||
- title: Built-in opcode for imm8_v1_v2
|
||||
description: Non-public extension of the instruction set.
|
||||
verification:
|
||||
- none
|
||||
exceptions:
|
||||
- x_none
|
||||
properties:
|
||||
- acc_read
|
||||
- acc_write
|
||||
pseudo: |
|
||||
builtin = resolve_builtin(imm1)
|
||||
acc = builtin(imm2, acc, v1, v2)
|
||||
semantics: |
|
||||
skip
|
||||
instructions:
|
||||
- sig: builtin.r3i imm1, imm2, v1:in:top, v2:in:top
|
||||
acc: inout:top
|
||||
format: [op_imm1_8_imm2_16_v1_8_v2_8]
|
||||
|
||||
- title: Built-in opcode for imm8_v1_v2_v3
|
||||
description: Non-public extension of the instruction set.
|
||||
verification:
|
||||
- none
|
||||
exceptions:
|
||||
- x_none
|
||||
properties:
|
||||
- acc_read
|
||||
- acc_write
|
||||
pseudo: |
|
||||
builtin = resolve_builtin(imm1)
|
||||
acc = builtin(imm2, acc, v1, v2, v3)
|
||||
semantics: |
|
||||
skip
|
||||
instructions:
|
||||
- sig: builtin.r4i imm1, imm2, v1:in:top, v2:in:top, v3:in:top
|
||||
acc: inout:top
|
||||
format: [op_imm1_8_imm2_16_v1_8_v2_8_v3_8]
|
||||
|
||||
- title: Built-in opcode for id_32
|
||||
description: Non-public extension of the instruction set.
|
||||
verification:
|
||||
- none
|
||||
exceptions:
|
||||
- x_none
|
||||
properties:
|
||||
- string_id
|
||||
- acc_read
|
||||
- acc_write
|
||||
pseudo: |
|
||||
builtin = resolve_builtin(imm)
|
||||
acc = builtin(acc, id)
|
||||
semantics: |
|
||||
skip
|
||||
instructions:
|
||||
- sig: builtin.id imm, string_id
|
||||
acc: inout:top
|
||||
format: [op_imm_8_id_32]
|
||||
|
||||
- title: Built-in opcode for method_id_v_8
|
||||
description: Non-public extension of the instruction set.
|
||||
verification:
|
||||
- method_id_static
|
||||
exceptions:
|
||||
- x_none
|
||||
properties:
|
||||
- method_id
|
||||
- acc_read
|
||||
- acc_write
|
||||
pseudo: |
|
||||
builtin = resolve_builtin(imm)
|
||||
acc = builtin(acc, method_id, v)
|
||||
semantics: |
|
||||
skip
|
||||
instructions:
|
||||
- sig: builtin.midr imm, method_id, v:in:top
|
||||
acc: inout:top
|
||||
format: [op_imm_8_id_16_v_8]
|
||||
|
||||
- title: Built-in opcode for id_32_imm_16
|
||||
description: Non-public extension of the instruction set.
|
||||
verification:
|
||||
- none
|
||||
exceptions:
|
||||
- x_none
|
||||
properties:
|
||||
- string_id
|
||||
- acc_read
|
||||
- acc_write
|
||||
pseudo: |
|
||||
builtin = resolve_builtin(imm1)
|
||||
acc = builtin(acc, id, imm2)
|
||||
semantics: |
|
||||
skip
|
||||
instructions:
|
||||
- sig: builtin.idi imm1, string_id, imm2
|
||||
acc: inout:top
|
||||
format: [op_imm1_8_id_32_imm2_16]
|
||||
|
||||
- title: Built-in opcode for id_32_imm_16_v_8
|
||||
description: Non-public extension of the instruction set.
|
||||
verification:
|
||||
- none
|
||||
exceptions:
|
||||
- x_none
|
||||
properties:
|
||||
- string_id
|
||||
- acc_read
|
||||
- acc_write
|
||||
pseudo: |
|
||||
builtin = resolve_builtin(imm1)
|
||||
acc = builtin(acc, id, imm2, v)
|
||||
semantics: |
|
||||
skip
|
||||
instructions:
|
||||
- sig: builtin.idr3i imm1, string_id, imm2, v:in:top
|
||||
acc: inout:top
|
||||
format: [op_imm1_8_id_32_imm2_16_v_8]
|
||||
|
||||
- title: Built-in opcode for id_32_imm_16_v1_8_v2_8
|
||||
description: Non-public extension of the instruction set.
|
||||
verification:
|
||||
- none
|
||||
exceptions:
|
||||
- x_none
|
||||
properties:
|
||||
- string_id
|
||||
- acc_read
|
||||
- acc_write
|
||||
pseudo: |
|
||||
builtin = resolve_builtin(imm1)
|
||||
acc = builtin(acc, id, imm2, v1, v2)
|
||||
semantics: |
|
||||
skip
|
||||
instructions:
|
||||
- sig: builtin.idr4i imm1, string_id, imm2, v1:in:top, v2:in:top
|
||||
acc: inout:top
|
||||
format: [op_imm1_8_id_32_imm2_16_v1_8_v2_8]
|
||||
|
||||
- title: Built-in opcode for imm_16_imm_16_v_8
|
||||
description: Non-public extension of the instruction set.
|
||||
verification:
|
||||
- none
|
||||
exceptions:
|
||||
- x_none
|
||||
properties:
|
||||
- acc_read
|
||||
- acc_write
|
||||
pseudo: |
|
||||
builtin = resolve_builtin(imm1)
|
||||
acc = builtin(acc, imm2, imm3, v)
|
||||
semantics: |
|
||||
skip
|
||||
instructions:
|
||||
- sig: builtin.i2r3 imm1, imm2, imm3, v:in:top
|
||||
acc: inout:top
|
||||
format: [op_imm1_8_imm2_16_imm3_16_v_8]
|
||||
|
||||
- title: Built-in opcode for imm_16_imm_16
|
||||
description: Non-public extension of the instruction set.
|
||||
verification:
|
||||
- none
|
||||
exceptions:
|
||||
- x_none
|
||||
properties:
|
||||
- acc_read
|
||||
- acc_write
|
||||
pseudo: |
|
||||
builtin = resolve_builtin(imm1)
|
||||
acc = builtin(acc, imm2, imm3)
|
||||
semantics: |
|
||||
skip
|
||||
instructions:
|
||||
- sig: builtin.i2r2 imm1, imm2, imm3
|
||||
acc: inout:top
|
||||
format: [op_imm1_8_imm2_16_imm3_16]
|
||||
|
||||
- title: Built-in opcode for imm_16
|
||||
description: Non-public extension of the instruction set.
|
||||
verification:
|
||||
- none
|
||||
exceptions:
|
||||
- x_none
|
||||
properties:
|
||||
- acc_read
|
||||
- acc_write
|
||||
pseudo: |
|
||||
builtin = resolve_builtin(imm1)
|
||||
acc = builtin(acc, imm2)
|
||||
semantics: |
|
||||
skip
|
||||
instructions:
|
||||
- sig: builtin.imm imm1, imm2
|
||||
acc: inout:top
|
||||
format: [op_imm1_8_imm2_16]
|
||||
|
||||
- title: Built-in opcode with method id imm16 and two regs
|
||||
description: Non-public extension of the instruction set.
|
||||
verification:
|
||||
- none
|
||||
exceptions:
|
||||
- x_none
|
||||
properties:
|
||||
- acc_write
|
||||
- method_id
|
||||
pseudo: |
|
||||
pseudo: |
|
||||
builtin = resolve_builtin(imm1)
|
||||
acc = builtin(id, imm2, v1, v2)
|
||||
semantics: |
|
||||
skip
|
||||
instructions:
|
||||
- sig: builtin.imr2 imm1, method_id, imm2, v1:in:top, v2:in:top
|
||||
acc: out:top
|
||||
format: [op_imm1_8_id_16_imm2_16_v1_8_v2_8]
|
||||
|
||||
builtins: [ ]
|
||||
#
|
||||
@@ -1,224 +0,0 @@
|
||||
# Copyright (c) 2021 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.
|
||||
|
||||
require 'delegate'
|
||||
require 'ostruct'
|
||||
|
||||
class BuiltinInstruction < SimpleDelegator
|
||||
def mnemonic
|
||||
sig.split(' ')[0]
|
||||
end
|
||||
|
||||
def opcode
|
||||
mnemonic.sub('.', '_') + self[:format]
|
||||
end
|
||||
|
||||
def format
|
||||
self[:format].length() == 0 ? 'NONE' : self[:format].sub('_', '')
|
||||
end
|
||||
end
|
||||
|
||||
class Builtin < SimpleDelegator
|
||||
def mnemonic
|
||||
sig.split(' ')[0]
|
||||
end
|
||||
|
||||
def opcode
|
||||
mnemonic.sub('.', '_') + self[:format]
|
||||
end
|
||||
|
||||
def format
|
||||
self[:format].length() == 0 ? 'NONE' : self[:format].sub('_', '')
|
||||
end
|
||||
|
||||
def stripped_mnemonic
|
||||
mnemonic.split('.')[0]
|
||||
end
|
||||
|
||||
def throwing?
|
||||
throwable = ['monitorenter', 'monitorexit']
|
||||
throwable.include?(stripped_mnemonic) || self[:exception] == true
|
||||
end
|
||||
|
||||
def ins
|
||||
self[:insn].sub('.', '_')
|
||||
end
|
||||
|
||||
def id
|
||||
self[:id]
|
||||
end
|
||||
|
||||
def language_context
|
||||
self[:space]
|
||||
end
|
||||
end
|
||||
|
||||
module PandaBuiltins
|
||||
module_function
|
||||
|
||||
def instructions
|
||||
insns = []
|
||||
@data["groups"].each do |group|
|
||||
group.instructions[0][:format].each do |f|
|
||||
props = group.instructions[0].to_h
|
||||
props[:format] = f.sub('op', '').gsub(/imm[0-9]+?/, 'imm').gsub(/v[0-9]+?/, 'v').gsub(/_([0-9]+)/, '\1')
|
||||
|
||||
insns << BuiltinInstruction.new(OpenStruct.new(props))
|
||||
end
|
||||
end
|
||||
insns
|
||||
end
|
||||
|
||||
def builtins
|
||||
all_builtins = []
|
||||
@data["builtins"].each do |b|
|
||||
b[:format].each do |f|
|
||||
props = b.to_h
|
||||
props[:format] = f.sub('op', '').gsub(/imm[0-9]+?/, 'imm').gsub(/v[0-9]+?/, 'v').gsub(/_([0-9]+)/, '\1')
|
||||
|
||||
all_builtins << Builtin.new(OpenStruct.new(props))
|
||||
end
|
||||
end
|
||||
|
||||
# Assign an ID to each builtin.
|
||||
# NB! IDs are unique only for builtins corresponding
|
||||
# to a *single* 'builtin.*' instruction!
|
||||
id = 0
|
||||
for i in 1 .. all_builtins.length() - 1
|
||||
all_builtins[i - 1][:id] = id
|
||||
id += 1
|
||||
|
||||
id = 0 unless all_builtins[i - 1][:insn] == all_builtins[i][:insn]
|
||||
end
|
||||
all_builtins[all_builtins.length() - 1][:id] = id if all_builtins.any?
|
||||
|
||||
all_builtins
|
||||
end
|
||||
|
||||
# Delegating part of module
|
||||
#
|
||||
def wrap_data(data)
|
||||
@data = data
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def prepare_data(data)
|
||||
insn_ids = []
|
||||
mnemos = {} # insn id => mnemonics
|
||||
formats = {} # insn id => supported encoding formats
|
||||
counts = {} # insn id => number of corresponding builtins (counting different formats)
|
||||
ordered = {} # insn id => list of corresponding builtins in order of definition
|
||||
|
||||
raise 'Number of builtin.* instructions is too high' if data["groups"].length() > 20
|
||||
|
||||
insn_names = {}
|
||||
data["groups"].each do |group|
|
||||
|
||||
raise 'Expecting exactly one instruction per builtin.* group' unless group["instructions"].length() == 1
|
||||
|
||||
group["instructions"].each do |insn|
|
||||
|
||||
sig = insn["sig"]
|
||||
args = sig.split(/,?\s+/)
|
||||
args_len = args.length()
|
||||
|
||||
raise 'Expecting at least one argument for a builtin' if args_len < 2
|
||||
raise "Expecting 'builtin.' prefix for the mnemonic" unless /^builtin\./.match(args[0])
|
||||
|
||||
raise "Expecting an imm as the builtin's first argument" unless args[1].start_with?('imm')
|
||||
|
||||
raise "Duplicate builtin instruction name '#{args[0]}'" if insn_names.key?(args[0])
|
||||
insn_names[args[0]] = 1
|
||||
|
||||
insn_id = args[2 .. args_len - 1].map{ |arg| arg =~ /^([^:]+):?/; $1 }.join('_')
|
||||
|
||||
raise "Non-unique signature is detected while parsing instruction '#{sig}'" if formats.key?(insn_id)
|
||||
|
||||
# Currently a single format per instruction is enough, so the assert below just guards status quo
|
||||
raise 'Expecting exactly one encoding format per instruction' unless insn["format"].length() == 1
|
||||
|
||||
insn_ids << insn_id
|
||||
mnemos[insn_id] = args[0]
|
||||
formats[insn_id] = insn["format"]
|
||||
counts[insn_id] = 0
|
||||
ordered[insn_id] = []
|
||||
end
|
||||
end
|
||||
|
||||
builtin_names = {}
|
||||
data["builtins"].each do |builtin|
|
||||
raise "'sig' property is missing" unless builtin['sig']
|
||||
raise "'acc' property is missing" unless builtin['acc']
|
||||
raise "Unexpected 'insn' property" if builtin['insn']
|
||||
raise "Unexpected 'format' property" if builtin['format']
|
||||
|
||||
sig = builtin["sig"]
|
||||
args = sig.split(/,?\s+/)
|
||||
args_len = args.length()
|
||||
|
||||
raise "Malformed signature of a builtin" if args_len < 1
|
||||
|
||||
raise "Duplicate builtin name '#{args[0]}'" if builtin_names.key?(args[0])
|
||||
builtin_names[args[0]] = 1
|
||||
|
||||
insn_id = args[1 .. args_len - 1].map{ |arg| arg =~ /^([^:]+):?/; $1 }.join('_')
|
||||
|
||||
raise "Signature for builtin '#{sig}' does not match any builtin.* instruction" unless formats.key?(insn_id)
|
||||
|
||||
builtin["insn"] = mnemos[insn_id]
|
||||
builtin["format"] = formats[insn_id].clone
|
||||
counts[insn_id] += builtin["format"].length()
|
||||
ordered[insn_id] << builtin
|
||||
|
||||
raise "Number of builtins for '#{insn_id}' exceeds builtin_id" if counts[insn_id] > 256
|
||||
end
|
||||
|
||||
# Enforce order of builtins and add "delta" property, defined as follows:
|
||||
# builtin1.delta = 0
|
||||
# builtin2.delta = num_builtins_with_sig_of(builtin1)
|
||||
# builtin3.delta = num_builtins_with_sig_of(builtin1) + num_builtins_with_sig_of(builtin2)
|
||||
# ...
|
||||
# builtinN.delta = num_builtins_with_sig_of(builtin1) + num_builtins_with_sig_of(builtin2) + ... + num_builtins_with_sig_of(builtinN_1)
|
||||
builtins = []
|
||||
for i in 0 .. data["groups"].length() - 1
|
||||
curr_insn = data["groups"][i]["instructions"][0]
|
||||
curr_insn_id = insn_ids[i]
|
||||
|
||||
if i > 0
|
||||
prev_insn = data["groups"][i - 1]["instructions"][0]
|
||||
prev_insn_id = insn_ids[i - 1]
|
||||
|
||||
curr_insn["delta"] = prev_insn["delta"] + counts[prev_insn_id]
|
||||
else
|
||||
curr_insn["delta"] = 0
|
||||
end
|
||||
|
||||
ordered[curr_insn_id].each do |builtin|
|
||||
builtins << builtin
|
||||
end
|
||||
end
|
||||
|
||||
{"groups" => data["groups"], "builtins" => builtins}
|
||||
end
|
||||
|
||||
module ExtBuiltins
|
||||
def self.load_ecma_builtins(data); end
|
||||
end
|
||||
|
||||
def Gen.on_require(data)
|
||||
ExtBuiltins.load_ecma_builtins(data)
|
||||
prepared_data = prepare_data(data)
|
||||
PandaBuiltins.wrap_data(prepared_data)
|
||||
end
|
||||
|
||||
@@ -533,12 +533,5 @@ module Panda
|
||||
end
|
||||
|
||||
def Gen.on_require(data)
|
||||
builtins_fname = File.expand_path(File.join(File.dirname(__FILE__), 'builtins.yaml'))
|
||||
builtins = YAML.load_file(builtins_fname)
|
||||
builtins = JSON.parse(builtins.to_json, object_class: OpenStruct)
|
||||
builtins.groups.each do |group|
|
||||
data.groups << group
|
||||
end
|
||||
|
||||
Panda.wrap_data(data)
|
||||
end
|
||||
|
||||
@@ -66,7 +66,6 @@ ohos_shared_library("libarkfile") {
|
||||
":isa_gen_libarkfile_bytecode_instruction_enum_gen_h",
|
||||
":isa_gen_libarkfile_file_format_version_h",
|
||||
":isa_gen_libarkfile_tests_bytecode_emitter_tests_gen_h",
|
||||
":libarkfile_bytecode_builtin_enum_gen_h",
|
||||
":libarkfile_type_gen_h",
|
||||
"$ark_root/libpandabase:libarkbase",
|
||||
"$ark_root/libziparchive:libarkziparchive",
|
||||
@@ -92,7 +91,6 @@ ohos_static_library("libarkfile_frontend_static") {
|
||||
":isa_gen_libarkfile_bytecode_instruction_enum_gen_h",
|
||||
":isa_gen_libarkfile_file_format_version_h",
|
||||
":isa_gen_libarkfile_tests_bytecode_emitter_tests_gen_h",
|
||||
":libarkfile_bytecode_builtin_enum_gen_h",
|
||||
":libarkfile_type_gen_h",
|
||||
"$ark_root/libpandabase:libarkbase_frontend_static",
|
||||
"$ark_root/libziparchive:libarkziparchive_frontend_static",
|
||||
@@ -107,13 +105,6 @@ ark_gen_file("libarkfile_type_gen_h") {
|
||||
output_file = "$target_gen_dir/type.h"
|
||||
}
|
||||
|
||||
ark_gen_file("libarkfile_bytecode_builtin_enum_gen_h") {
|
||||
template_file = "templates/bytecode_builtin_enum_gen.h.erb"
|
||||
data_file = "$ark_root/isa/builtins.yaml"
|
||||
requires = [ "$ark_root/isa/builtinsapi.rb" ]
|
||||
output_file = "$target_gen_dir/bytecode_builtin_enum_gen.h"
|
||||
}
|
||||
|
||||
ark_isa_gen("isa_gen_libarkfile") {
|
||||
template_files = [
|
||||
"bytecode_instruction_enum_gen.h.erb",
|
||||
@@ -126,5 +117,4 @@ ark_isa_gen("isa_gen_libarkfile") {
|
||||
sources = "templates" ## ark_root/templates
|
||||
destination = "$target_gen_dir/include" ## target_gen_dir/include
|
||||
requires = [ "pandafile_isapi.rb" ]
|
||||
extra_dependencies = [ ":libarkfile_bytecode_builtin_enum_gen_h" ]
|
||||
}
|
||||
|
||||
@@ -28,14 +28,6 @@ set(TEMPLATES
|
||||
tests/bytecode_emitter_tests_gen.h.erb
|
||||
)
|
||||
|
||||
set(output "${CMAKE_CURRENT_BINARY_DIR}/include/bytecode_builtin_enum_gen.h")
|
||||
panda_gen_file(
|
||||
DATAFILE "${PANDA_ROOT}/isa/builtins.yaml"
|
||||
REQUIRES "${PANDA_ROOT}/isa/builtinsapi.rb"
|
||||
TEMPLATE "${CMAKE_CURRENT_SOURCE_DIR}/templates/bytecode_builtin_enum_gen.h.erb"
|
||||
OUTPUTFILE ${output}
|
||||
)
|
||||
|
||||
panda_isa_gen(TEMPLATES ${TEMPLATES}
|
||||
SOURCE ${CMAKE_CURRENT_LIST_DIR}/templates
|
||||
DESTINATION ${GEN_INCLUDE_DIR}
|
||||
|
||||
@@ -209,8 +209,6 @@ class BytecodeInst : public BytecodeInstBase<Mode> {
|
||||
public:
|
||||
#include <bytecode_instruction_enum_gen.h>
|
||||
|
||||
#include <bytecode_builtin_enum_gen.h>
|
||||
|
||||
BytecodeInst() = default;
|
||||
|
||||
~BytecodeInst() = default;
|
||||
@@ -349,8 +347,6 @@ public:
|
||||
|
||||
bool CanThrow() const;
|
||||
|
||||
bool IsBuiltin() const;
|
||||
|
||||
bool IsTerminator() const
|
||||
{
|
||||
return HasFlag(Flags::RETURN) || HasFlag(Flags::JUMP) || (GetOpcode() == Opcode::THROW_V8);
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
% PandaBuiltins::instructions.each do |instr|
|
||||
enum <%= instr.mnemonic.tr('.','_').upcase %> {
|
||||
% PandaBuiltins::builtins.select{ |b| b.insn == instr.mnemonic }.each do |builtin|
|
||||
<%= builtin.opcode.tr('.','_').upcase %>,
|
||||
% end
|
||||
};
|
||||
% end
|
||||
@@ -359,21 +359,6 @@ std::ostream& operator<<(std::ostream& os, const typename BytecodeInst<Mode>::Op
|
||||
return os;
|
||||
}
|
||||
|
||||
template <const BytecodeInstMode Mode>
|
||||
inline bool BytecodeInst<Mode>::IsBuiltin() const
|
||||
{
|
||||
switch (GetOpcode()) {
|
||||
% Panda::instructions.each do |inst|
|
||||
% if inst["sig"].include? "builtin"
|
||||
case BytecodeInst<Mode>::Opcode::<%= inst.opcode.upcase %>:
|
||||
% end
|
||||
% end
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <const BytecodeInstMode Mode>
|
||||
inline bool BytecodeInst<Mode>::IsPrimaryOpcodeValid() const
|
||||
{
|
||||
|
||||
@@ -212,7 +212,6 @@ ohos_static_library("libarkruntime_static") {
|
||||
"$ark_root/verification/gen:isa_gen_verification_gen_abs_int_inl_gen_h",
|
||||
"$ark_root/verification/gen:isa_gen_verification_gen_cflow_iterate_inl_gen_h",
|
||||
"$ark_root/verification/gen:isa_gen_verification_gen_job_fill_gen_h",
|
||||
"$ark_root/verification/gen:verification_abs_int_builtin_handlers_h",
|
||||
"$ark_root/verification/gen:verification_abs_int_inl_compat_checks_h",
|
||||
"$ark_root/verification/gen:verification_verifier_messages_h",
|
||||
sdk_libc_secshared_dep,
|
||||
@@ -358,24 +357,6 @@ gen_intrinsics_yaml("arkruntime_gen_intrinsics_yaml") {
|
||||
output_file = "$target_gen_dir/intrinsics.yaml"
|
||||
}
|
||||
|
||||
builtin_templates = [
|
||||
"builtin_count",
|
||||
"builtin_dispatch",
|
||||
"builtin_handlers",
|
||||
"builtin_insn_handlers",
|
||||
]
|
||||
builtin_labels = []
|
||||
foreach(t, builtin_templates) {
|
||||
output = "$target_gen_dir/include/${t}.h"
|
||||
builtin_labels += [ ":${t}" ]
|
||||
ark_gen_file(t) {
|
||||
data_file = "$ark_root/isa/builtins.yaml"
|
||||
requires = [ "$ark_root/isa/builtinsapi.rb" ]
|
||||
template_file = "interpreter/templates/${t}.h.erb"
|
||||
output_file = output
|
||||
}
|
||||
}
|
||||
|
||||
gen_include_dir = "$target_gen_dir/include"
|
||||
|
||||
ark_isa_gen("isa_gen_libarkruntime") {
|
||||
@@ -386,7 +367,6 @@ ark_isa_gen("isa_gen_libarkruntime") {
|
||||
]
|
||||
sources = "interpreter/templates"
|
||||
destination = gen_include_dir
|
||||
extra_dependencies = builtin_labels
|
||||
}
|
||||
|
||||
isa = "$root_gen_dir/isa/isa.yaml"
|
||||
|
||||
@@ -179,25 +179,6 @@ set(INTERPRETER_IMPL_SOURCES
|
||||
add_library(arkruntime_interpreter_impl OBJECT ${INTERPRETER_IMPL_SOURCES})
|
||||
panda_set_lib_32bit_property(arkruntime_interpreter_impl)
|
||||
|
||||
set(builtin_templates
|
||||
builtin_count
|
||||
builtin_dispatch
|
||||
builtin_handlers
|
||||
builtin_insn_handlers
|
||||
)
|
||||
|
||||
set(builtin_headers)
|
||||
foreach(template ${builtin_templates})
|
||||
set(output "${CMAKE_CURRENT_BINARY_DIR}/include/${template}.h")
|
||||
panda_gen_file(
|
||||
DATAFILE "${PANDA_ROOT}/isa/builtins.yaml"
|
||||
REQUIRES "${PANDA_ROOT}/isa/builtinsapi.rb"
|
||||
TEMPLATE "${CMAKE_CURRENT_SOURCE_DIR}/interpreter/templates/${template}.h.erb"
|
||||
OUTPUTFILE ${output}
|
||||
)
|
||||
list(APPEND builtin_headers ${output})
|
||||
endforeach()
|
||||
|
||||
set(ISA_TEMPLATES
|
||||
interpreter-inl_gen.h.erb
|
||||
isa_constants_gen.h.erb
|
||||
@@ -209,7 +190,6 @@ panda_isa_gen(
|
||||
TEMPLATES ${ISA_TEMPLATES}
|
||||
SOURCE ${CMAKE_CURRENT_LIST_DIR}/interpreter/templates
|
||||
DESTINATION ${GEN_INCLUDE_DIR}
|
||||
EXTRA_DEPENDENCIES ${builtin_headers}
|
||||
)
|
||||
|
||||
set(ISA "${CMAKE_BINARY_DIR}/isa/isa.yaml")
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 PANDA_RUNTIME_INCLUDE_BUILTIN_COUNT_H_
|
||||
#define PANDA_RUNTIME_INCLUDE_BUILTIN_COUNT_H_
|
||||
|
||||
constexpr size_t NUM_BUILTINS = <%= PandaBuiltins::builtins.length() %>;
|
||||
|
||||
#endif // PANDA_RUNTIME_INCLUDE_BUILTIN_COUNT_H_
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 PANDA_RUNTIME_INCLUDE_BUILTIN_DISPATCH_H_
|
||||
#define PANDA_RUNTIME_INCLUDE_BUILTIN_DISPATCH_H_
|
||||
|
||||
% PandaBuiltins::builtins.each do |builtin|
|
||||
&&HANDLE_BUILTIN_<%= builtin.opcode.tr('.','_').upcase %>,
|
||||
% end
|
||||
|
||||
#endif // PANDA_RUNTIME_INCLUDE_BUILTIN_DISPATCH_H_
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 PANDA_RUNTIME_INCLUDE_BUILTIN_HANDLERS_H_
|
||||
#define PANDA_RUNTIME_INCLUDE_BUILTIN_HANDLERS_H_
|
||||
|
||||
% PandaBuiltins::builtins.each do |builtin|
|
||||
HANDLE_BUILTIN_<%= builtin.opcode.tr('.','_').upcase %>: {
|
||||
% if builtin.language_context == 'ecmascript'
|
||||
ecmascript::InstructionHandler<RuntimeIfaceT, enable_instrumentation> handler(&state);
|
||||
% elsif builtin.language_context == 'java'
|
||||
java::InstructionHandler<RuntimeIfaceT, enable_instrumentation> handler(&state);
|
||||
% else
|
||||
InstructionHandler<RuntimeIfaceT, enable_instrumentation> handler(&state);
|
||||
% end
|
||||
% mnemonic = builtin.mnemonic.split('.').map { |p| p == '64' ? 'Wide' : p.capitalize }.join
|
||||
handler.DumpVRegs();
|
||||
handler.InstrumentInstruction();
|
||||
|
||||
ASSERT(PandaVM::GetCurrent()->GetLanguageContext().GetLanguage() == panda_file::SourceLang::ECMASCRIPT ||
|
||||
!PandaVM::GetCurrent()->GetGC()->IsGCRunning() || Locks::mutator_lock->HasLock());
|
||||
|
||||
handler.template HandleBuiltin<%= mnemonic %><BytecodeInstruction::Format::<%= builtin.format.upcase %>>();
|
||||
|
||||
ASSERT(PandaVM::GetCurrent()->GetLanguageContext().GetLanguage() == panda_file::SourceLang::ECMASCRIPT ||
|
||||
!PandaVM::GetCurrent()->GetGC()->IsGCRunning() || Locks::mutator_lock->HasLock());
|
||||
|
||||
if (enable_instrumentation) {
|
||||
frame->GetAcc() = handler.GetAcc();
|
||||
}
|
||||
% if builtin['sig'].include?('Return') || builtin['sig'].include?('suspendGenerator')
|
||||
return;
|
||||
% else
|
||||
% if builtin.throwing?
|
||||
ASSERT(handler.GetExceptionOpcode() < dispatch_table.size());
|
||||
DISPATCH(GetDispatchTable(dispatch_table), handler.GetExceptionOpcode(), label);
|
||||
% else
|
||||
ASSERT(handler.GetPrimaryOpcode() < dispatch_table.size());
|
||||
DISPATCH(GetDispatchTable(dispatch_table), handler.GetPrimaryOpcode(), label);
|
||||
% end
|
||||
% end
|
||||
}
|
||||
% end
|
||||
|
||||
#endif // PANDA_RUNTIME_INCLUDE_BUILTIN_HANDLERS_H_
|
||||
@@ -1,30 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 PANDA_RUNTIME_INCLUDE_BUILTIN_INSN_HANDLERS_H_
|
||||
#define PANDA_RUNTIME_INCLUDE_BUILTIN_INSN_HANDLERS_H_
|
||||
|
||||
% PandaBuiltins::instructions.each do |insn|
|
||||
HANDLE_<%= insn.opcode.upcase %>: {
|
||||
const auto builtin_id = state.GetInst().template GetImm<BytecodeInstruction::Format::<%= insn.format.upcase %>>();
|
||||
|
||||
LOG(DEBUG, INTERPRETER) << "Subdispatch: " << "<%= insn.mnemonic %>, " << builtin_id
|
||||
<< " (NUM_PREFIXED=" << NUM_PREFIXED
|
||||
<< ", delta=" << <%= insn.delta %> << ")";
|
||||
DISPATCH(GetDispatchTable(dispatch_table), 256 + NUM_PREFIXED + 1 + <%= insn.delta %> + builtin_id, label);
|
||||
}
|
||||
% end
|
||||
|
||||
#endif // PANDA_RUNTIME_INCLUDE_BUILTIN_INSN_HANDLERS_H_
|
||||
@@ -34,7 +34,6 @@ void ExecuteImpl(ManagedThread* thread, const uint8_t *pc, Frame* frame) {
|
||||
#define INSTRUMENT_FRAME() do { if (enable_instrumentation && (handler.GetFrame()->IsForcePop() || handler.GetFrame()->IsRetryInstruction())) { goto INSTRUMENT_FRAME_HANDLER; } } while (0)
|
||||
|
||||
ASSERT(!thread->IsCurrentFrameCompiled());
|
||||
#include <builtin_count.h>
|
||||
|
||||
EVENT_METHOD_ENTER(frame->GetMethod()->GetFullName(), events::MethodEnterKind::INTERP, thread->RecordMethodEnter());
|
||||
|
||||
@@ -45,12 +44,11 @@ void ExecuteImpl(ManagedThread* thread, const uint8_t *pc, Frame* frame) {
|
||||
PandaUniquePtr<void, decltype(method_exit_event)> method_exit(&method_exit_event, method_exit_event);
|
||||
#endif
|
||||
|
||||
static std::array<const void*, 256 + NUM_PREFIXED + 1 + NUM_BUILTINS> dispatch_table{
|
||||
static std::array<const void*, 256 + NUM_PREFIXED + 1> dispatch_table{
|
||||
% Panda::dispatch_table.handler_names.each do |name|
|
||||
&&HANDLE_<%= name %>,
|
||||
% end
|
||||
&&EXCEPTION_HANDLER,
|
||||
#include <builtin_dispatch.h>
|
||||
};
|
||||
|
||||
SetDispatchTable(dispatch_table);
|
||||
@@ -64,7 +62,7 @@ void ExecuteImpl(ManagedThread* thread, const uint8_t *pc, Frame* frame) {
|
||||
const void *label;
|
||||
DISPATCH(GetDispatchTable(dispatch_table), state.GetPrimaryOpcode(), label);
|
||||
|
||||
% Panda::instructions.reject(&:builtin?).each do |i|
|
||||
% Panda::instructions.each do |i|
|
||||
% mnemonic = i.mnemonic.split('.').map { |p| p == '64' ? 'Wide' : p.capitalize }.join
|
||||
HANDLE_<%= i.handler_name %>: {
|
||||
% namespace = i.namespace == 'core' ? '' : "#{i.namespace}::"
|
||||
@@ -117,10 +115,6 @@ HANDLE_<%= p.handler_name %>: {
|
||||
}
|
||||
% end
|
||||
|
||||
#include <builtin_insn_handlers.h>
|
||||
|
||||
#include <builtin_handlers.h>
|
||||
|
||||
INSTRUMENT_FRAME_HANDLER: {
|
||||
InstructionHandler<RuntimeIfaceT, enable_instrumentation> handler(&state);
|
||||
|
||||
|
||||
@@ -3800,65 +3800,6 @@ public:
|
||||
return inst_;
|
||||
}
|
||||
|
||||
template <BytecodeInstructionSafe::Format format>
|
||||
bool HandleBuiltinCall_polymorphic_short()
|
||||
{
|
||||
LOG_INST();
|
||||
DBGBRK();
|
||||
Sync();
|
||||
return true;
|
||||
}
|
||||
|
||||
template <BytecodeInstructionSafe::Format format>
|
||||
bool HandleBuiltinMonitorenter()
|
||||
{
|
||||
LOG_VERIFIER_DEBUG_BUILTIN("monitorenter");
|
||||
DBGBRK();
|
||||
Sync();
|
||||
auto &&acc_type = GetAccType();
|
||||
if (acc_type.ForAllTypes([&](Type acc_type1) { return acc_type1 == Types().NullRefType(); })) {
|
||||
// treat it as always throw NPE
|
||||
SHOW_MSG(AlwaysNpeAccumulator)
|
||||
LOG_VERIFIER_ALWAYS_NPE_ACCUMULATOR();
|
||||
END_SHOW_MSG();
|
||||
SET_STATUS_FOR_MSG(AlwaysNpeAccumulator);
|
||||
return false;
|
||||
}
|
||||
if (!CheckTypes(acc_type, {Types().RefType()})) {
|
||||
SET_STATUS_FOR_MSG(BadRegisterType);
|
||||
SET_STATUS_FOR_MSG(UndefinedRegister);
|
||||
return false;
|
||||
}
|
||||
MoveToNextInst<format>();
|
||||
return true;
|
||||
}
|
||||
|
||||
template <BytecodeInstructionSafe::Format format>
|
||||
bool HandleBuiltinMonitorexit()
|
||||
{
|
||||
LOG_VERIFIER_DEBUG_BUILTIN("monitorexit");
|
||||
DBGBRK();
|
||||
Sync();
|
||||
auto &&acc_type = GetAccType();
|
||||
if (acc_type.ForAllTypes([&](Type acc_type1) { return acc_type1 == Types().NullRefType(); })) {
|
||||
// treat it as always throw NPE
|
||||
SHOW_MSG(AlwaysNpeAccumulator)
|
||||
LOG_VERIFIER_ALWAYS_NPE_ACCUMULATOR();
|
||||
END_SHOW_MSG();
|
||||
SET_STATUS_FOR_MSG(AlwaysNpeAccumulator);
|
||||
return false;
|
||||
}
|
||||
if (!CheckTypes(acc_type, {Types().RefType()})) {
|
||||
SET_STATUS_FOR_MSG(BadRegisterType);
|
||||
SET_STATUS_FOR_MSG(UndefinedRegister);
|
||||
return false;
|
||||
}
|
||||
MoveToNextInst<format>();
|
||||
return true;
|
||||
}
|
||||
|
||||
#include "abs_int_builtin_handlers.h"
|
||||
|
||||
static PandaString RegisterName(int reg_idx, bool capitalize = false)
|
||||
{
|
||||
if (reg_idx == ACC) {
|
||||
|
||||
@@ -22,21 +22,6 @@ config("verification_public_config") {
|
||||
]
|
||||
}
|
||||
|
||||
ark_gen_file("verification_abs_int_builtin_handlers_h") {
|
||||
template_file = "templates/abs_int_builtin_handlers.h.erb"
|
||||
data_file = "$ark_root/isa/builtins.yaml"
|
||||
requires = [ "$ark_root/isa/builtinsapi.rb" ]
|
||||
output_file = "$target_gen_dir/include/abs_int_builtin_handlers.h"
|
||||
}
|
||||
|
||||
ark_gen_file("verification_cflow_iterate_inl_gen_builtin_handlers_h") {
|
||||
template_file = "templates/cflow_iterate_inl_gen_builtin_handlers.h.erb"
|
||||
data_file = "$ark_root/isa/builtins.yaml"
|
||||
requires = [ "$ark_root/isa/builtinsapi.rb" ]
|
||||
output_file =
|
||||
"$target_gen_dir/include/cflow_iterate_inl_gen_builtin_handlers.h"
|
||||
}
|
||||
|
||||
ark_gen_file("verification_abs_int_inl_compat_checks_h") {
|
||||
template_file = "templates/abs_int_inl_compat_checks.h.erb"
|
||||
data_file = "$ark_root/verification/verification.yaml"
|
||||
@@ -53,9 +38,7 @@ ark_isa_gen("isa_gen_verification_gen") {
|
||||
sources = "templates" ## ark_root/templates
|
||||
destination = "$target_gen_dir/include" ## target_gen_dir/include
|
||||
extra_dependencies = [
|
||||
":verification_abs_int_builtin_handlers_h",
|
||||
":verification_abs_int_inl_compat_checks_h",
|
||||
":verification_cflow_iterate_inl_gen_builtin_handlers_h",
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -15,22 +15,6 @@ cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
project(pandaverification_gen)
|
||||
|
||||
set(abs_int_builtin_templates
|
||||
abs_int_builtin_handlers
|
||||
cflow_iterate_inl_gen_builtin_handlers
|
||||
)
|
||||
set(abs_int_builtin_headers)
|
||||
foreach(template ${abs_int_builtin_templates})
|
||||
set(output "${CMAKE_CURRENT_BINARY_DIR}/include/${template}.h")
|
||||
panda_gen_file(
|
||||
DATAFILE "${PANDA_ROOT}/isa/builtins.yaml"
|
||||
REQUIRES "${PANDA_ROOT}/isa/builtinsapi.rb"
|
||||
TEMPLATE "${CMAKE_CURRENT_SOURCE_DIR}/templates/${template}.h.erb"
|
||||
OUTPUTFILE ${output}
|
||||
)
|
||||
list(APPEND abs_int_builtin_headers ${output})
|
||||
endforeach()
|
||||
|
||||
set(ABS_INT_EXTRA_HEADERS)
|
||||
set(ABS_INT_TEMPLATES
|
||||
abs_int_inl_compat_checks
|
||||
@@ -57,7 +41,7 @@ panda_isa_gen(
|
||||
TEMPLATES ${ISA_TEMPLATES}
|
||||
SOURCE ${CMAKE_CURRENT_LIST_DIR}/templates
|
||||
DESTINATION ${GEN_INCLUDE_DIR}
|
||||
EXTRA_DEPENDENCIES ${abs_int_builtin_headers};${ABS_INT_EXTRA_HEADERS}
|
||||
EXTRA_DEPENDENCIES ${ABS_INT_EXTRA_HEADERS}
|
||||
)
|
||||
|
||||
panda_gen_messages(
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
% builtin_kinds = PandaBuiltins::builtins.map(&:insn).uniq
|
||||
% builtin_mnemonics = PandaBuiltins::instructions.map { |instruction| instruction.sig.split(' ').at(0) }
|
||||
% undefined_builtins = builtin_mnemonics.select { |mnemonic| not builtin_kinds.include?(mnemonic) }.uniq
|
||||
% builtin_kinds.each do |kind|
|
||||
% mnemonic = kind.split('.').map { |p| p == '64' ? 'Wide' : p.capitalize }.join
|
||||
% builtins = PandaBuiltins::builtins.select { |builtin| builtin.insn == kind }.sort_by(&:id)
|
||||
template <BytecodeInstructionSafe::Format format>
|
||||
bool Handle<%= mnemonic %>() {
|
||||
LOG_INST();
|
||||
const auto builtin_id = GetInst().template GetImm<format>();
|
||||
switch (builtin_id) {
|
||||
% builtins.each do |builtin|
|
||||
case <%= builtin.id %>: return HandleBuiltin<%= builtin.mnemonic.capitalize.tr('.', '_') %><format>();
|
||||
% end
|
||||
default:
|
||||
LOG(DEBUG, VERIFIER) << "Incorrect builtin id 0x" << std::hex << builtin_id << " for '<%= kind %>'";
|
||||
}
|
||||
status_ = VerificationStatus::ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
% end
|
||||
% undefined_builtins.each do |builtin|
|
||||
% mnemonic = builtin.split('.').map { |p| p == '64' ? 'Wide' : p.capitalize }.join
|
||||
template <BytecodeInstructionSafe::Format format>
|
||||
bool Handle<%= mnemonic %>() {
|
||||
LOG_INST();
|
||||
LOG(DEBUG, VERIFIER) << "ABSINT: "
|
||||
<< "<%= builtin %>";
|
||||
return true;
|
||||
}
|
||||
|
||||
%end
|
||||
@@ -35,8 +35,6 @@ public:
|
||||
return inst_.IsPrimaryOpcodeValid();
|
||||
}
|
||||
|
||||
#include "cflow_iterate_inl_gen_builtin_handlers.h"
|
||||
|
||||
% Panda::instructions.uniq{|i| i.mnemonic}.each do |i|
|
||||
% mnemonic = i.mnemonic.split('.').map { |p| p == '64' ? 'Wide' : p.capitalize }.join
|
||||
template <BytecodeInstructionSafe::Format format>
|
||||
@@ -47,10 +45,7 @@ public:
|
||||
}
|
||||
const uint8_t* pc = inst_.GetAddress();
|
||||
const size_t sz = inst_.Size(format);
|
||||
% if i.mnemonic.split('.').at(0) == 'builtin'
|
||||
bool const EXC_SRC = IsExceptionSource<%= mnemonic %><format>();
|
||||
% elsif i.properties.include?('call') or i.stripped_mnemonic == 'throw' or !i.exceptions.include?('x_none')
|
||||
// TOOD: add support of builtins: monitorenter monitorexit
|
||||
% if !i.exceptions.include?('x_none')
|
||||
bool const EXC_SRC = true;
|
||||
% else
|
||||
bool const EXC_SRC = false;
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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.
|
||||
*/
|
||||
|
||||
% throwing_builtins = [ "monitorenter", "monitorexit" ]
|
||||
% builtin_kinds = PandaBuiltins::builtins.map(&:insn).uniq
|
||||
% builtin_mnemonics = PandaBuiltins::instructions.map { |instruction| instruction.sig.split(' ').at(0) }
|
||||
% undefined_builtins = builtin_mnemonics.select { |mnemonic| not builtin_kinds.include?(mnemonic) }.uniq
|
||||
% builtin_kinds.each do |kind|
|
||||
% mnemonic = kind.split('.').map { |p| p == '64' ? 'Wide' : p.capitalize }.join
|
||||
% builtins = PandaBuiltins::builtins.select { |builtin| builtin.insn == kind }.sort_by(&:id)
|
||||
% builtins.each do |builtin|
|
||||
bool IsExceptionSourceBuiltin<%= builtin.mnemonic.capitalize %>() {
|
||||
% if throwing_builtins.include?(builtin.mnemonic)
|
||||
return true;
|
||||
% else
|
||||
return false;
|
||||
% end
|
||||
}
|
||||
% end
|
||||
|
||||
template <BytecodeInstructionSafe::Format format>
|
||||
bool IsExceptionSource<%= mnemonic %>() {
|
||||
const auto builtin_id = inst_.template GetImm<format>();
|
||||
switch (builtin_id) {
|
||||
% builtins.each do |builtin|
|
||||
case <%= builtin.id %>: return IsExceptionSourceBuiltin<%= builtin.mnemonic.capitalize %>();
|
||||
% end
|
||||
default:
|
||||
LOG(DEBUG, VERIFIER) << "Incorrect builtin id 0x" << std::hex << builtin_id << " for '<%= kind %>'";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
% end
|
||||
% undefined_builtins.each do |builtin|
|
||||
template <BytecodeInstructionSafe::Format format>
|
||||
bool IsExceptionSource<%= builtin.split('.').map { |p| p == '64' ? 'Wide' : p.capitalize }.join %>() {
|
||||
return false;
|
||||
}
|
||||
% end
|
||||
@@ -51,12 +51,6 @@ messages:
|
||||
args: method
|
||||
message: ( method is '${method}' )
|
||||
|
||||
DebugBuiltin:
|
||||
number: 306
|
||||
level: debug
|
||||
args: name
|
||||
message: "builtin: ${name}"
|
||||
|
||||
DebugResult:
|
||||
number: 307
|
||||
level: debug
|
||||
|
||||
Reference in New Issue
Block a user