2021-09-04 08:06:49 +00:00
|
|
|
/*
|
|
|
|
* 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 "ecmascript/compiler/gate.h"
|
|
|
|
|
2021-12-23 06:55:22 +00:00
|
|
|
namespace panda::ecmascript::kungfu {
|
2021-09-04 08:06:49 +00:00
|
|
|
constexpr size_t ONE_DEPEND = 1;
|
|
|
|
constexpr size_t MANY_DEPEND = 2;
|
|
|
|
constexpr size_t NO_DEPEND = 0;
|
|
|
|
// NOLINTNEXTLINE(readability-function-size)
|
|
|
|
Properties OpCode::GetProperties() const
|
|
|
|
{
|
|
|
|
// general schema: [STATE]s + [DEPEND]s + [VALUE]s + [ROOT]
|
|
|
|
// GENERAL_STATE for any opcode match in
|
|
|
|
// {IF_TRUE, IF_FALSE, SWITCH_CASE, DEFAULT_CASE, MERGE, LOOP_BEGIN, STATE_ENTRY}
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
|
|
|
#define STATE(...) (std::make_pair(std::vector<OpCode>{__VA_ARGS__}, false))
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
2022-01-27 08:46:57 +00:00
|
|
|
#define VALUE(...) (std::make_pair(std::vector<MachineType>{__VA_ARGS__}, false))
|
2021-09-04 08:06:49 +00:00
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
|
|
|
#define MANY_STATE(...) (std::make_pair(std::vector<OpCode>{__VA_ARGS__}, true))
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
2022-01-27 08:46:57 +00:00
|
|
|
#define MANY_VALUE(...) (std::make_pair(std::vector<MachineType>{__VA_ARGS__}, true))
|
2021-09-04 08:06:49 +00:00
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
|
|
|
#define NO_STATE (std::nullopt)
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
|
|
|
#define NO_VALUE (std::nullopt)
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
|
|
|
#define NO_ROOT (std::nullopt)
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
|
|
|
|
#define GENERAL_STATE (NOP)
|
2021-12-17 09:18:10 +00:00
|
|
|
switch (op_) {
|
2021-09-04 08:06:49 +00:00
|
|
|
// SHARED
|
|
|
|
case NOP:
|
|
|
|
case CIRCUIT_ROOT:
|
|
|
|
return {NOVALUE, NO_STATE, NO_DEPEND, NO_VALUE, NO_ROOT};
|
|
|
|
case STATE_ENTRY:
|
|
|
|
case DEPEND_ENTRY:
|
|
|
|
case FRAMESTATE_ENTRY:
|
|
|
|
case RETURN_LIST:
|
|
|
|
case THROW_LIST:
|
|
|
|
case CONSTANT_LIST:
|
|
|
|
case ALLOCA_LIST:
|
|
|
|
case ARG_LIST:
|
|
|
|
return {NOVALUE, NO_STATE, NO_DEPEND, NO_VALUE, OpCode(CIRCUIT_ROOT)};
|
|
|
|
case RETURN:
|
2021-09-26 06:47:20 +00:00
|
|
|
return {NOVALUE, STATE(OpCode(GENERAL_STATE)), ONE_DEPEND, VALUE(ANYVALUE), OpCode(RETURN_LIST)};
|
2022-02-19 02:09:52 +00:00
|
|
|
case RETURN_VOID:
|
|
|
|
return {NOVALUE, STATE(OpCode(GENERAL_STATE)), ONE_DEPEND, NO_VALUE, OpCode(RETURN_LIST)};
|
2021-09-04 08:06:49 +00:00
|
|
|
case THROW:
|
2022-01-27 08:46:57 +00:00
|
|
|
return {NOVALUE, STATE(OpCode(GENERAL_STATE)), ONE_DEPEND, VALUE(JSMachineType()), OpCode(THROW_LIST)};
|
2021-09-04 08:06:49 +00:00
|
|
|
case ORDINARY_BLOCK:
|
|
|
|
return {NOVALUE, STATE(OpCode(GENERAL_STATE)), NO_DEPEND, NO_VALUE, NO_ROOT};
|
|
|
|
case IF_BRANCH:
|
2022-02-09 08:51:58 +00:00
|
|
|
return {NOVALUE, STATE(OpCode(GENERAL_STATE)), NO_DEPEND, VALUE(I1), NO_ROOT};
|
2021-09-04 08:06:49 +00:00
|
|
|
case SWITCH_BRANCH:
|
2022-01-11 13:09:24 +00:00
|
|
|
return {NOVALUE, STATE(OpCode(GENERAL_STATE)), NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
|
2021-09-04 08:06:49 +00:00
|
|
|
case IF_TRUE:
|
|
|
|
case IF_FALSE:
|
|
|
|
return {NOVALUE, STATE(OpCode(IF_BRANCH)), NO_DEPEND, NO_VALUE, NO_ROOT};
|
|
|
|
case SWITCH_CASE:
|
|
|
|
case DEFAULT_CASE:
|
|
|
|
return {NOVALUE, STATE(OpCode(SWITCH_BRANCH)), NO_DEPEND, NO_VALUE, NO_ROOT};
|
|
|
|
case MERGE:
|
|
|
|
return {NOVALUE, MANY_STATE(OpCode(GENERAL_STATE)), NO_DEPEND, NO_VALUE, NO_ROOT};
|
|
|
|
case LOOP_BEGIN:
|
|
|
|
return {NOVALUE, STATE(OpCode(GENERAL_STATE), OpCode(LOOP_BACK)), NO_DEPEND, NO_VALUE, NO_ROOT};
|
|
|
|
case LOOP_BACK:
|
|
|
|
return {NOVALUE, STATE(OpCode(GENERAL_STATE)), NO_DEPEND, NO_VALUE, NO_ROOT};
|
2022-01-11 13:09:24 +00:00
|
|
|
case VALUE_SELECTOR:
|
|
|
|
return {FLEX, STATE(OpCode(GENERAL_STATE)), NO_DEPEND, MANY_VALUE(FLEX), NO_ROOT};
|
2021-09-04 08:06:49 +00:00
|
|
|
case DEPEND_SELECTOR:
|
|
|
|
return {NOVALUE, STATE(OpCode(GENERAL_STATE)), MANY_DEPEND, NO_VALUE, NO_ROOT};
|
|
|
|
case DEPEND_RELAY:
|
|
|
|
return {NOVALUE, STATE(OpCode(GENERAL_STATE)), ONE_DEPEND, NO_VALUE, NO_ROOT};
|
|
|
|
case DEPEND_AND:
|
|
|
|
return {NOVALUE, NO_STATE, MANY_DEPEND, NO_VALUE, NO_ROOT};
|
|
|
|
// High Level IR
|
2021-12-30 17:38:35 +00:00
|
|
|
case JS_BYTECODE:
|
2022-01-27 08:46:57 +00:00
|
|
|
return {FLEX, STATE(OpCode(GENERAL_STATE)), ONE_DEPEND, MANY_VALUE(ANYVALUE), NO_ROOT};
|
|
|
|
case IF_SUCCESS:
|
|
|
|
case IF_EXCEPTION:
|
|
|
|
return {NOVALUE, STATE(OpCode(GENERAL_STATE)), NO_DEPEND, NO_VALUE, NO_ROOT};
|
2022-02-10 02:03:48 +00:00
|
|
|
case GET_EXCEPTION:
|
|
|
|
return {I64, NO_STATE, ONE_DEPEND, NO_VALUE, NO_ROOT};
|
2021-09-04 08:06:49 +00:00
|
|
|
// Middle Level IR
|
2022-02-18 06:03:24 +00:00
|
|
|
case RUNTIME_CALL:
|
2022-02-23 08:50:04 +00:00
|
|
|
case NOGC_RUNTIME_CALL:
|
2022-02-19 02:09:52 +00:00
|
|
|
case BYTECODE_CALL:
|
2022-04-21 12:58:15 +00:00
|
|
|
case DEBUGGER_BYTECODE_CALL:
|
2021-09-04 08:06:49 +00:00
|
|
|
case CALL:
|
Implement Proxy Lowering on x86
when function need call another js function, it will lowering to call "JSCall" trampoline function
JSCall trampoline function will check calltarget function, then correct the arguments, finally jump
the native or optimized code address of the target function.
JSCall(glue, argc, calltarget, ....)
then proxy call(glue, argc, callTarget, argv[])
if proxy->GetHandler is function
tail call JSCall(glue, argc, callTarget, argv); // consider performance
else
//Call(trap, handler, «target, thisArgument, argArray»)
call CreateArrayFromList(glue, argc, argv[]) ---> arrHandle // maybe trigger GC, construct OptimizedWithArgvLeaveFrame, visitor argv[0]..argv[argc-1]
call JSCall(glue, argc, method, argv[])
issue:https://gitee.com/openharmony/ark_js_runtime/issues/I52T6B?from=project-issue
Signed-off-by: songzhengchao <songzhengchao@huawei.com>
Change-Id: I994aae1eb9cbf51982348ae6e203c24c326f617e
2022-04-14 13:54:03 +00:00
|
|
|
case RUNTIME_CALL_WITH_ARGV:
|
2022-01-11 13:09:24 +00:00
|
|
|
return {FLEX, NO_STATE, ONE_DEPEND, MANY_VALUE(ANYVALUE, ANYVALUE), NO_ROOT};
|
2021-09-04 08:06:49 +00:00
|
|
|
case ALLOCA:
|
2022-01-11 13:09:24 +00:00
|
|
|
return {ARCH, NO_STATE, NO_DEPEND, NO_VALUE, OpCode(ALLOCA_LIST)};
|
|
|
|
case ARG:
|
|
|
|
return {FLEX, NO_STATE, NO_DEPEND, NO_VALUE, OpCode(ARG_LIST)};
|
2021-09-04 08:06:49 +00:00
|
|
|
case MUTABLE_DATA:
|
|
|
|
case CONST_DATA:
|
2022-01-11 13:09:24 +00:00
|
|
|
return {ARCH, NO_STATE, NO_DEPEND, NO_VALUE, OpCode(CONSTANT_LIST)};
|
2022-01-25 09:12:04 +00:00
|
|
|
case RELOCATABLE_DATA:
|
|
|
|
return {ARCH, NO_STATE, NO_DEPEND, NO_VALUE, OpCode(CONSTANT_LIST)};
|
2022-01-11 13:09:24 +00:00
|
|
|
case CONSTANT:
|
|
|
|
return {FLEX, NO_STATE, NO_DEPEND, NO_VALUE, OpCode(CONSTANT_LIST)};
|
|
|
|
case ZEXT_TO_INT64:
|
2022-02-09 08:51:58 +00:00
|
|
|
return {I64, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
|
2022-01-11 13:09:24 +00:00
|
|
|
case ZEXT_TO_INT32:
|
2022-02-09 08:51:58 +00:00
|
|
|
return {I32, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
|
2022-02-19 02:09:52 +00:00
|
|
|
case ZEXT_TO_INT16:
|
|
|
|
return {I16, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
|
2022-03-11 03:51:10 +00:00
|
|
|
case ZEXT_TO_ARCH:
|
|
|
|
return {ARCH, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
|
2022-01-11 13:09:24 +00:00
|
|
|
case SEXT_TO_INT64:
|
2022-02-09 08:51:58 +00:00
|
|
|
return {I64, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
|
2022-01-11 13:09:24 +00:00
|
|
|
case SEXT_TO_INT32:
|
2022-02-09 08:51:58 +00:00
|
|
|
return {I32, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
|
2022-03-11 03:51:10 +00:00
|
|
|
case SEXT_TO_ARCH:
|
|
|
|
return {ARCH, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
|
2022-01-11 13:09:24 +00:00
|
|
|
case TRUNC_TO_INT32:
|
2022-02-09 08:51:58 +00:00
|
|
|
return {I32, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
|
2022-01-11 13:09:24 +00:00
|
|
|
case TRUNC_TO_INT1:
|
2022-02-09 08:51:58 +00:00
|
|
|
return {I1, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
|
2022-04-01 06:33:39 +00:00
|
|
|
case TRUNC_TO_INT16:
|
|
|
|
return {I16, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
|
2022-01-11 13:09:24 +00:00
|
|
|
case REV:
|
|
|
|
return {FLEX, NO_STATE, NO_DEPEND, VALUE(FLEX), NO_ROOT};
|
|
|
|
case ADD:
|
|
|
|
case SUB:
|
|
|
|
case MUL:
|
|
|
|
case EXP:
|
|
|
|
case SDIV:
|
|
|
|
case SMOD:
|
|
|
|
case UDIV:
|
|
|
|
case UMOD:
|
|
|
|
case FDIV:
|
|
|
|
case FMOD:
|
|
|
|
case AND:
|
|
|
|
case XOR:
|
|
|
|
case OR:
|
|
|
|
case LSL:
|
|
|
|
case LSR:
|
|
|
|
case ASR:
|
|
|
|
return {FLEX, NO_STATE, NO_DEPEND, VALUE(FLEX, FLEX), NO_ROOT};
|
|
|
|
case SLT:
|
|
|
|
case SLE:
|
|
|
|
case SGT:
|
|
|
|
case SGE:
|
|
|
|
case ULT:
|
|
|
|
case ULE:
|
|
|
|
case UGT:
|
|
|
|
case UGE:
|
|
|
|
case FLT:
|
|
|
|
case FLE:
|
|
|
|
case FGT:
|
|
|
|
case FGE:
|
|
|
|
case EQ:
|
|
|
|
case NE:
|
2022-02-09 08:51:58 +00:00
|
|
|
return {I1, NO_STATE, NO_DEPEND, VALUE(ANYVALUE, ANYVALUE), NO_ROOT};
|
2022-01-11 13:09:24 +00:00
|
|
|
case LOAD:
|
|
|
|
return {FLEX, NO_STATE, ONE_DEPEND, VALUE(ARCH), NO_ROOT};
|
|
|
|
case STORE:
|
|
|
|
return {NOVALUE, NO_STATE, ONE_DEPEND, VALUE(ANYVALUE, ARCH), NO_ROOT};
|
|
|
|
case TAGGED_TO_INT64:
|
2022-02-09 08:51:58 +00:00
|
|
|
return {I64, NO_STATE, NO_DEPEND, VALUE(I64), NO_ROOT};
|
2022-02-19 02:09:52 +00:00
|
|
|
case INT64_TO_TAGGED:
|
|
|
|
return {I64, NO_STATE, NO_DEPEND, VALUE(I64), NO_ROOT};
|
2022-01-11 13:09:24 +00:00
|
|
|
case SIGNED_INT_TO_FLOAT:
|
|
|
|
case UNSIGNED_INT_TO_FLOAT:
|
|
|
|
return {FLEX, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
|
|
|
|
case FLOAT_TO_SIGNED_INT:
|
|
|
|
case UNSIGNED_FLOAT_TO_INT:
|
|
|
|
return {FLEX, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
|
|
|
|
case BITCAST:
|
|
|
|
return {FLEX, NO_STATE, NO_DEPEND, VALUE(ANYVALUE), NO_ROOT};
|
2022-06-06 09:41:17 +00:00
|
|
|
// suspend relate HIR
|
|
|
|
case RESTORE_REGISTER:
|
|
|
|
return {FLEX, NO_STATE, ONE_DEPEND, NO_VALUE, NO_ROOT};
|
|
|
|
case SAVE_REGISTER:
|
|
|
|
return {NOVALUE, NO_STATE, ONE_DEPEND, VALUE(ANYVALUE), NO_ROOT};
|
2021-09-04 08:06:49 +00:00
|
|
|
default:
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "Please complete OpCode properties (OpCode=" << op_ << ")";
|
2021-09-04 08:06:49 +00:00
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
#undef STATE
|
|
|
|
#undef VALUE
|
|
|
|
#undef MANY_STATE
|
|
|
|
#undef MANY_VALUE
|
|
|
|
#undef NO_STATE
|
|
|
|
#undef NO_VALUE
|
|
|
|
#undef NO_ROOT
|
|
|
|
#undef GENERAL_STATE
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string OpCode::Str() const
|
|
|
|
{
|
|
|
|
const std::map<GateOp, const char *> strMap = {
|
|
|
|
{NOP, "NOP"},
|
|
|
|
{CIRCUIT_ROOT, "CIRCUIT_ROOT"},
|
|
|
|
{STATE_ENTRY, "STATE_ENTRY"},
|
|
|
|
{DEPEND_ENTRY, "DEPEND_ENTRY"},
|
|
|
|
{FRAMESTATE_ENTRY, "FRAMESTATE_ENTRY"},
|
|
|
|
{RETURN_LIST, "RETURN_LIST"},
|
|
|
|
{THROW_LIST, "THROW_LIST"},
|
|
|
|
{CONSTANT_LIST, "CONSTANT_LIST"},
|
|
|
|
{ALLOCA_LIST, "ALLOCA_LIST"},
|
|
|
|
{ARG_LIST, "ARG_LIST"},
|
|
|
|
{RETURN, "RETURN"},
|
2021-12-17 09:18:10 +00:00
|
|
|
{RETURN_VOID, "RETURN_VOID"},
|
2021-09-04 08:06:49 +00:00
|
|
|
{THROW, "THROW"},
|
|
|
|
{ORDINARY_BLOCK, "ORDINARY_BLOCK"},
|
|
|
|
{IF_BRANCH, "IF_BRANCH"},
|
|
|
|
{SWITCH_BRANCH, "SWITCH_BRANCH"},
|
|
|
|
{IF_TRUE, "IF_TRUE"},
|
|
|
|
{IF_FALSE, "IF_FALSE"},
|
|
|
|
{SWITCH_CASE, "SWITCH_CASE"},
|
|
|
|
{DEFAULT_CASE, "DEFAULT_CASE"},
|
|
|
|
{MERGE, "MERGE"},
|
|
|
|
{LOOP_BEGIN, "LOOP_BEGIN"},
|
|
|
|
{LOOP_BACK, "LOOP_BACK"},
|
2022-01-11 13:09:24 +00:00
|
|
|
{VALUE_SELECTOR, "VALUE_SELECTOR"},
|
2021-09-04 08:06:49 +00:00
|
|
|
{DEPEND_SELECTOR, "DEPEND_SELECTOR"},
|
|
|
|
{DEPEND_RELAY, "DEPEND_RELAY"},
|
|
|
|
{DEPEND_AND, "DEPEND_AND"},
|
2021-12-30 17:38:35 +00:00
|
|
|
{JS_BYTECODE, "JS_BYTECODE"},
|
2022-01-27 08:46:57 +00:00
|
|
|
{IF_SUCCESS, "IF_SUCCESS"},
|
|
|
|
{IF_EXCEPTION, "IF_EXCEPTION"},
|
2022-02-10 02:03:48 +00:00
|
|
|
{GET_EXCEPTION, "GET_EXCEPTION"},
|
2022-02-25 07:43:36 +00:00
|
|
|
{RUNTIME_CALL, "RUNTIME_CALL"},
|
2022-02-23 08:50:04 +00:00
|
|
|
{NOGC_RUNTIME_CALL, "NOGC_RUNTIME_CALL"},
|
2021-09-04 08:06:49 +00:00
|
|
|
{CALL, "CALL"},
|
2022-02-19 02:09:52 +00:00
|
|
|
{BYTECODE_CALL, "BYTECODE_CALL"},
|
2022-04-21 12:58:15 +00:00
|
|
|
{DEBUGGER_BYTECODE_CALL, "DEBUGGER_BYTECODE_CALL"},
|
2021-09-04 08:06:49 +00:00
|
|
|
{ALLOCA, "ALLOCA"},
|
2022-01-11 13:09:24 +00:00
|
|
|
{ARG, "ARG"},
|
2021-09-04 08:06:49 +00:00
|
|
|
{MUTABLE_DATA, "MUTABLE_DATA"},
|
2022-01-25 09:12:04 +00:00
|
|
|
{RELOCATABLE_DATA, "RELOCATABLE_DATA"},
|
2021-09-04 08:06:49 +00:00
|
|
|
{CONST_DATA, "CONST_DATA"},
|
2022-01-11 13:09:24 +00:00
|
|
|
{CONSTANT, "CONSTANT"},
|
|
|
|
{ZEXT_TO_INT64, "ZEXT_TO_INT64"},
|
|
|
|
{ZEXT_TO_INT32, "ZEXT_TO_INT32"},
|
2022-02-19 02:09:52 +00:00
|
|
|
{ZEXT_TO_INT16, "ZEXT_TO_INT16"},
|
2022-03-11 03:51:10 +00:00
|
|
|
{ZEXT_TO_ARCH, "ZEXT_TO_ARCH"},
|
2022-01-11 13:09:24 +00:00
|
|
|
{SEXT_TO_INT64, "SEXT_TO_INT64"},
|
|
|
|
{SEXT_TO_INT32, "SEXT_TO_INT32"},
|
2022-03-11 03:51:10 +00:00
|
|
|
{SEXT_TO_ARCH, "SEXT_TO_ARCH"},
|
2022-01-11 13:09:24 +00:00
|
|
|
{TRUNC_TO_INT32, "TRUNC_TO_INT32"},
|
|
|
|
{TRUNC_TO_INT1, "TRUNC_TO_INT1"},
|
2022-04-01 06:33:39 +00:00
|
|
|
{TRUNC_TO_INT16, "TRUNC_TO_INT16"},
|
2022-01-11 13:09:24 +00:00
|
|
|
{REV, "REV"},
|
|
|
|
{ADD, "ADD"},
|
|
|
|
{SUB, "SUB"},
|
|
|
|
{MUL, "MUL"},
|
|
|
|
{EXP, "EXP"},
|
|
|
|
{SDIV, "SDIV"},
|
|
|
|
{SMOD, "SMOD"},
|
|
|
|
{UDIV, "UDIV"},
|
|
|
|
{UMOD, "UMOD"},
|
|
|
|
{FDIV, "FDIV"},
|
|
|
|
{FMOD, "FMOD"},
|
|
|
|
{AND, "AND"},
|
|
|
|
{XOR, "XOR"},
|
|
|
|
{OR, "OR"},
|
|
|
|
{LSL, "LSL"},
|
|
|
|
{LSR, "LSR"},
|
|
|
|
{ASR, "ASR"},
|
|
|
|
{SLT, "SLT"},
|
|
|
|
{SLE, "SLE"},
|
|
|
|
{SGT, "SGT"},
|
|
|
|
{SGE, "SGE"},
|
|
|
|
{ULT, "ULT"},
|
|
|
|
{ULE, "ULE"},
|
|
|
|
{UGT, "UGT"},
|
|
|
|
{UGE, "UGE"},
|
|
|
|
{FLT, "FLT"},
|
|
|
|
{FLE, "FLE"},
|
|
|
|
{FGT, "FGT"},
|
|
|
|
{FGE, "FGE"},
|
|
|
|
{EQ, "EQ"},
|
|
|
|
{NE, "NE"},
|
|
|
|
{LOAD, "LOAD"},
|
|
|
|
{STORE, "STORE"},
|
|
|
|
{TAGGED_TO_INT64, "TAGGED_TO_INT64"},
|
2022-02-19 02:09:52 +00:00
|
|
|
{INT64_TO_TAGGED, "INT64_TO_TAGGED"},
|
2022-01-11 13:09:24 +00:00
|
|
|
{SIGNED_INT_TO_FLOAT, "SIGNED_INT_TO_FLOAT"},
|
|
|
|
{UNSIGNED_INT_TO_FLOAT, "UNSIGNED_INT_TO_FLOAT"},
|
|
|
|
{FLOAT_TO_SIGNED_INT, "FLOAT_TO_SIGNED_INT"},
|
|
|
|
{UNSIGNED_FLOAT_TO_INT, "UNSIGNED_FLOAT_TO_INT"},
|
|
|
|
{BITCAST, "BITCAST"},
|
2022-06-06 09:41:17 +00:00
|
|
|
{RESTORE_REGISTER, "RESTORE_REGISTER"},
|
|
|
|
{SAVE_REGISTER, "SAVE_REGISTER"},
|
2021-09-04 08:06:49 +00:00
|
|
|
};
|
2021-12-17 09:18:10 +00:00
|
|
|
if (strMap.count(op_) > 0) {
|
|
|
|
return strMap.at(op_);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
2021-12-17 09:18:10 +00:00
|
|
|
return "OP-" + std::to_string(op_);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
2022-03-02 08:06:19 +00:00
|
|
|
|
|
|
|
size_t OpCode::GetStateCount(BitField bitfield) const
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
auto properties = GetProperties();
|
2021-09-04 08:06:49 +00:00
|
|
|
auto stateProp = properties.statesIn;
|
2022-03-02 08:06:19 +00:00
|
|
|
return stateProp.has_value() ? (stateProp->second ? bitfield : stateProp->first.size()) : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t OpCode::GetDependCount(BitField bitfield) const
|
|
|
|
{
|
|
|
|
auto properties = GetProperties();
|
2021-09-04 08:06:49 +00:00
|
|
|
auto dependProp = properties.dependsIn;
|
2022-06-06 09:41:17 +00:00
|
|
|
return (dependProp == MANY_DEPEND) ? bitfield : dependProp;
|
2022-03-02 08:06:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t OpCode::GetInValueCount(BitField bitfield) const
|
|
|
|
{
|
|
|
|
auto properties = GetProperties();
|
2021-09-04 08:06:49 +00:00
|
|
|
auto valueProp = properties.valuesIn;
|
2022-03-02 08:06:19 +00:00
|
|
|
return valueProp.has_value() ? (valueProp->second ? bitfield : valueProp->first.size()) : 0;
|
|
|
|
}
|
|
|
|
|
2022-03-25 01:31:39 +00:00
|
|
|
size_t OpCode::GetRootCount([[maybe_unused]] BitField bitfield) const
|
2022-03-02 08:06:19 +00:00
|
|
|
{
|
|
|
|
auto properties = GetProperties();
|
|
|
|
auto rootProp = properties.root;
|
|
|
|
return rootProp.has_value() ? 1 : 0;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t OpCode::GetOpCodeNumIns(BitField bitfield) const
|
|
|
|
{
|
2022-03-02 08:06:19 +00:00
|
|
|
return GetStateCount(bitfield) + GetDependCount(bitfield) + GetInValueCount(bitfield) + GetRootCount(bitfield);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
2022-01-27 08:46:57 +00:00
|
|
|
MachineType OpCode::GetMachineType() const
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
return GetProperties().returnValue;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
2022-01-27 08:46:57 +00:00
|
|
|
MachineType OpCode::GetInMachineType(BitField bitfield, size_t idx) const
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
auto valueProp = GetProperties().valuesIn;
|
2022-03-02 08:06:19 +00:00
|
|
|
idx -= GetStateCount(bitfield);
|
|
|
|
idx -= GetDependCount(bitfield);
|
2021-09-04 08:06:49 +00:00
|
|
|
ASSERT(valueProp.has_value());
|
|
|
|
if (valueProp->second) {
|
|
|
|
return valueProp->first.at(std::min(idx, valueProp->first.size() - 1));
|
|
|
|
}
|
|
|
|
return valueProp->first.at(idx);
|
|
|
|
}
|
|
|
|
|
|
|
|
OpCode OpCode::GetInStateCode(size_t idx) const
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
auto stateProp = GetProperties().statesIn;
|
2021-09-04 08:06:49 +00:00
|
|
|
ASSERT(stateProp.has_value());
|
|
|
|
if (stateProp->second) {
|
|
|
|
return stateProp->first.at(std::min(idx, stateProp->first.size() - 1));
|
|
|
|
}
|
|
|
|
return stateProp->first.at(idx);
|
|
|
|
}
|
|
|
|
|
2022-01-27 08:46:57 +00:00
|
|
|
std::string MachineTypeToStr(MachineType machineType)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2022-01-27 08:46:57 +00:00
|
|
|
switch (machineType) {
|
2021-09-04 08:06:49 +00:00
|
|
|
case NOVALUE:
|
|
|
|
return "NOVALUE";
|
|
|
|
case ANYVALUE:
|
|
|
|
return "ANYVALUE";
|
2022-02-09 08:51:58 +00:00
|
|
|
case I1:
|
|
|
|
return "I1";
|
|
|
|
case I8:
|
|
|
|
return "I8";
|
|
|
|
case I16:
|
|
|
|
return "I16";
|
|
|
|
case I32:
|
|
|
|
return "I32";
|
|
|
|
case I64:
|
|
|
|
return "I64";
|
|
|
|
case F32:
|
|
|
|
return "F32";
|
|
|
|
case F64:
|
|
|
|
return "F64";
|
2021-09-04 08:06:49 +00:00
|
|
|
default:
|
|
|
|
return "???";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<std::pair<std::string, size_t>> Gate::CheckNullInput() const
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
const auto numIns = GetNumIns();
|
2021-09-04 08:06:49 +00:00
|
|
|
for (size_t idx = 0; idx < numIns; idx++) {
|
2021-12-17 09:18:10 +00:00
|
|
|
if (IsInGateNull(idx)) {
|
2021-09-04 08:06:49 +00:00
|
|
|
return std::make_pair("In list contains null", idx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<std::pair<std::string, size_t>> Gate::CheckStateInput() const
|
|
|
|
{
|
|
|
|
size_t stateStart = 0;
|
2022-03-02 08:06:19 +00:00
|
|
|
size_t stateEnd = GetStateCount();
|
2021-09-04 08:06:49 +00:00
|
|
|
for (size_t idx = stateStart; idx < stateEnd; idx++) {
|
2021-12-17 09:18:10 +00:00
|
|
|
auto stateProp = GetOpCode().GetProperties().statesIn;
|
2021-09-04 08:06:49 +00:00
|
|
|
ASSERT(stateProp.has_value());
|
2021-12-17 09:18:10 +00:00
|
|
|
auto expectedIn = GetOpCode().GetInStateCode(idx);
|
|
|
|
auto actualIn = GetInGateConst(idx)->GetOpCode();
|
2021-09-04 08:06:49 +00:00
|
|
|
if (expectedIn == OpCode::NOP) { // general
|
|
|
|
if (!actualIn.IsGeneralState()) {
|
|
|
|
return std::make_pair(
|
|
|
|
"State input does not match (expected:<General State> actual:" + actualIn.Str() + ")", idx);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (expectedIn != actualIn) {
|
|
|
|
return std::make_pair(
|
|
|
|
"State input does not match (expected:" + expectedIn.Str() + " actual:" + actualIn.Str() + ")",
|
|
|
|
idx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<std::pair<std::string, size_t>> Gate::CheckValueInput() const
|
|
|
|
{
|
2022-03-02 08:06:19 +00:00
|
|
|
size_t valueStart = GetStateCount() + GetDependCount();
|
|
|
|
size_t valueEnd = valueStart + GetInValueCount();
|
2021-09-04 08:06:49 +00:00
|
|
|
for (size_t idx = valueStart; idx < valueEnd; idx++) {
|
2022-01-27 08:46:57 +00:00
|
|
|
auto expectedIn = GetOpCode().GetInMachineType(GetBitField(), idx);
|
|
|
|
auto actualIn = GetInGateConst(idx)->GetOpCode().GetMachineType();
|
|
|
|
if (expectedIn == MachineType::FLEX) {
|
|
|
|
expectedIn = GetMachineType();
|
2022-01-11 13:09:24 +00:00
|
|
|
}
|
2022-01-27 08:46:57 +00:00
|
|
|
if (actualIn == MachineType::FLEX) {
|
|
|
|
actualIn = GetInGateConst(idx)->GetMachineType();
|
2022-01-11 13:09:24 +00:00
|
|
|
}
|
|
|
|
|
2021-09-04 08:06:49 +00:00
|
|
|
if ((expectedIn != actualIn) && (expectedIn != ANYVALUE)) {
|
2022-01-27 08:46:57 +00:00
|
|
|
return std::make_pair("Value input does not match (expected: " + MachineTypeToStr(expectedIn) +
|
|
|
|
" actual: " + MachineTypeToStr(actualIn) + ")",
|
2021-09-04 08:06:49 +00:00
|
|
|
idx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<std::pair<std::string, size_t>> Gate::CheckDependInput() const
|
|
|
|
{
|
2022-03-02 08:06:19 +00:00
|
|
|
size_t dependStart = GetStateCount();
|
|
|
|
size_t dependEnd = dependStart + GetDependCount();
|
2021-09-04 08:06:49 +00:00
|
|
|
for (size_t idx = dependStart; idx < dependEnd; idx++) {
|
2022-03-02 08:06:19 +00:00
|
|
|
if (GetInGateConst(idx)->GetDependCount() == 0 &&
|
2021-12-17 09:18:10 +00:00
|
|
|
GetInGateConst(idx)->GetOpCode() != OpCode::DEPEND_ENTRY) {
|
2021-09-04 08:06:49 +00:00
|
|
|
return std::make_pair("Depend input is side-effect free", idx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<std::pair<std::string, size_t>> Gate::CheckStateOutput() const
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
if (GetOpCode().IsState()) {
|
2021-09-04 08:06:49 +00:00
|
|
|
size_t cnt = 0;
|
|
|
|
const Gate *curGate = this;
|
|
|
|
if (!curGate->IsFirstOutNull()) {
|
|
|
|
const Out *curOut = curGate->GetFirstOutConst();
|
2022-03-02 08:06:19 +00:00
|
|
|
if (curOut->IsStateEdge() && curOut->GetGateConst()->GetOpCode().IsState()) {
|
2021-09-04 08:06:49 +00:00
|
|
|
cnt++;
|
|
|
|
}
|
|
|
|
while (!curOut->IsNextOutNull()) {
|
|
|
|
curOut = curOut->GetNextOutConst();
|
2022-03-02 08:06:19 +00:00
|
|
|
if (curOut->IsStateEdge() && curOut->GetGateConst()->GetOpCode().IsState()) {
|
2021-09-04 08:06:49 +00:00
|
|
|
cnt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
size_t expected = 0;
|
|
|
|
bool needCheck = true;
|
2021-12-17 09:18:10 +00:00
|
|
|
if (GetOpCode().IsTerminalState()) {
|
2021-09-04 08:06:49 +00:00
|
|
|
expected = 0;
|
2022-03-02 08:06:19 +00:00
|
|
|
} else if (GetOpCode() == OpCode::IF_BRANCH || GetOpCode() == OpCode::JS_BYTECODE) {
|
2021-09-04 08:06:49 +00:00
|
|
|
expected = 2; // 2: expected number of state out branches
|
2021-12-17 09:18:10 +00:00
|
|
|
} else if (GetOpCode() == OpCode::SWITCH_BRANCH) {
|
2021-09-04 08:06:49 +00:00
|
|
|
needCheck = false;
|
|
|
|
} else {
|
|
|
|
expected = 1;
|
|
|
|
}
|
|
|
|
if (needCheck && cnt != expected) {
|
|
|
|
return std::make_pair("Number of state out branches is not valid (expected:" + std::to_string(expected) +
|
|
|
|
" actual:" + std::to_string(cnt) + ")",
|
|
|
|
-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<std::pair<std::string, size_t>> Gate::CheckBranchOutput() const
|
|
|
|
{
|
|
|
|
std::map<std::pair<OpCode, BitField>, size_t> setOfOps;
|
2021-12-17 09:18:10 +00:00
|
|
|
if (GetOpCode() == OpCode::IF_BRANCH || GetOpCode() == OpCode::SWITCH_BRANCH) {
|
2021-09-04 08:06:49 +00:00
|
|
|
size_t cnt = 0;
|
|
|
|
const Gate *curGate = this;
|
|
|
|
if (!curGate->IsFirstOutNull()) {
|
|
|
|
const Out *curOut = curGate->GetFirstOutConst();
|
2022-03-02 08:06:19 +00:00
|
|
|
if (curOut->GetGateConst()->GetOpCode().IsState() && curOut->IsStateEdge()) {
|
|
|
|
ASSERT(!curOut->GetGateConst()->GetOpCode().IsFixed());
|
2021-09-04 08:06:49 +00:00
|
|
|
setOfOps[{curOut->GetGateConst()->GetOpCode(), curOut->GetGateConst()->GetBitField()}]++;
|
|
|
|
cnt++;
|
|
|
|
}
|
|
|
|
while (!curOut->IsNextOutNull()) {
|
|
|
|
curOut = curOut->GetNextOutConst();
|
2022-03-02 08:06:19 +00:00
|
|
|
if (curOut->GetGateConst()->GetOpCode().IsState() && curOut->IsStateEdge()) {
|
|
|
|
ASSERT(!curOut->GetGateConst()->GetOpCode().IsFixed());
|
2021-09-04 08:06:49 +00:00
|
|
|
setOfOps[{curOut->GetGateConst()->GetOpCode(), curOut->GetGateConst()->GetBitField()}]++;
|
|
|
|
cnt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (setOfOps.size() != cnt) {
|
|
|
|
return std::make_pair("Duplicate state out branches", -1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<std::pair<std::string, size_t>> Gate::CheckNOP() const
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
if (GetOpCode() == OpCode::NOP) {
|
|
|
|
if (!IsFirstOutNull()) {
|
2021-09-04 08:06:49 +00:00
|
|
|
return std::make_pair("NOP gate used by other gates", -1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<std::pair<std::string, size_t>> Gate::CheckSelector() const
|
|
|
|
{
|
2022-01-11 13:09:24 +00:00
|
|
|
if (GetOpCode() == OpCode::VALUE_SELECTOR || GetOpCode() == OpCode::DEPEND_SELECTOR) {
|
2021-12-17 09:18:10 +00:00
|
|
|
auto stateOp = GetInGateConst(0)->GetOpCode();
|
2021-09-04 08:06:49 +00:00
|
|
|
if (stateOp == OpCode::MERGE || stateOp == OpCode::LOOP_BEGIN) {
|
2021-12-17 09:18:10 +00:00
|
|
|
if (GetInGateConst(0)->GetNumIns() != GetNumIns() - 1) {
|
|
|
|
if (GetOpCode() == OpCode::DEPEND_SELECTOR) {
|
2021-09-04 08:06:49 +00:00
|
|
|
return std::make_pair("Number of depend flows does not match control flows (expected:" +
|
2021-12-17 09:18:10 +00:00
|
|
|
std::to_string(GetInGateConst(0)->GetNumIns()) +
|
|
|
|
" actual:" + std::to_string(GetNumIns() - 1) + ")",
|
2021-09-04 08:06:49 +00:00
|
|
|
-1);
|
|
|
|
} else {
|
|
|
|
return std::make_pair("Number of data flows does not match control flows (expected:" +
|
2021-12-17 09:18:10 +00:00
|
|
|
std::to_string(GetInGateConst(0)->GetNumIns()) +
|
|
|
|
" actual:" + std::to_string(GetNumIns() - 1) + ")",
|
2021-09-04 08:06:49 +00:00
|
|
|
-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return std::make_pair(
|
|
|
|
"State input does not match (expected:[MERGE|LOOP_BEGIN] actual:" + stateOp.Str() + ")", 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<std::pair<std::string, size_t>> Gate::CheckRelay() const
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
if (GetOpCode() == OpCode::DEPEND_RELAY) {
|
|
|
|
auto stateOp = GetInGateConst(0)->GetOpCode();
|
2021-09-04 08:06:49 +00:00
|
|
|
if (!(stateOp == OpCode::IF_TRUE || stateOp == OpCode::IF_FALSE || stateOp == OpCode::SWITCH_CASE ||
|
2022-03-02 08:06:19 +00:00
|
|
|
stateOp == OpCode::DEFAULT_CASE || stateOp == OpCode::IF_SUCCESS || stateOp == OpCode::IF_EXCEPTION ||
|
|
|
|
stateOp == OpCode::ORDINARY_BLOCK)) {
|
2022-01-19 01:11:02 +00:00
|
|
|
return std::make_pair("State input does not match ("
|
2022-03-02 08:06:19 +00:00
|
|
|
"expected:[IF_TRUE|IF_FALSE|SWITCH_CASE|DEFAULT_CASE|IF_SUCCESS|IF_EXCEPTION|ORDINARY_BLOCK] actual:" +
|
2022-01-19 01:11:02 +00:00
|
|
|
stateOp.Str() + ")", 0);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<std::pair<std::string, size_t>> Gate::SpecialCheck() const
|
|
|
|
{
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
auto ret = CheckNOP();
|
2021-09-04 08:06:49 +00:00
|
|
|
if (ret.has_value()) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
auto ret = CheckSelector();
|
2021-09-04 08:06:49 +00:00
|
|
|
if (ret.has_value()) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
auto ret = CheckRelay();
|
2021-09-04 08:06:49 +00:00
|
|
|
if (ret.has_value()) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Gate::Verify() const
|
|
|
|
{
|
|
|
|
std::string errorString;
|
|
|
|
size_t highlightIdx = -1;
|
|
|
|
bool failed = false;
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
auto ret = CheckNullInput();
|
2021-09-04 08:06:49 +00:00
|
|
|
if (ret.has_value()) {
|
|
|
|
failed = true;
|
|
|
|
std::tie(errorString, highlightIdx) = ret.value();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!failed) {
|
2021-12-17 09:18:10 +00:00
|
|
|
auto ret = CheckStateInput();
|
2021-09-04 08:06:49 +00:00
|
|
|
if (ret.has_value()) {
|
|
|
|
failed = true;
|
|
|
|
std::tie(errorString, highlightIdx) = ret.value();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!failed) {
|
2021-12-17 09:18:10 +00:00
|
|
|
auto ret = CheckValueInput();
|
2021-09-04 08:06:49 +00:00
|
|
|
if (ret.has_value()) {
|
|
|
|
failed = true;
|
|
|
|
std::tie(errorString, highlightIdx) = ret.value();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!failed) {
|
2021-12-17 09:18:10 +00:00
|
|
|
auto ret = CheckDependInput();
|
2021-09-04 08:06:49 +00:00
|
|
|
if (ret.has_value()) {
|
|
|
|
failed = true;
|
|
|
|
std::tie(errorString, highlightIdx) = ret.value();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!failed) {
|
2021-12-17 09:18:10 +00:00
|
|
|
auto ret = CheckStateOutput();
|
2021-09-04 08:06:49 +00:00
|
|
|
if (ret.has_value()) {
|
|
|
|
failed = true;
|
|
|
|
std::tie(errorString, highlightIdx) = ret.value();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!failed) {
|
2021-12-17 09:18:10 +00:00
|
|
|
auto ret = CheckBranchOutput();
|
2021-09-04 08:06:49 +00:00
|
|
|
if (ret.has_value()) {
|
|
|
|
failed = true;
|
|
|
|
std::tie(errorString, highlightIdx) = ret.value();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!failed) {
|
2021-12-17 09:18:10 +00:00
|
|
|
auto ret = SpecialCheck();
|
2021-09-04 08:06:49 +00:00
|
|
|
if (ret.has_value()) {
|
|
|
|
failed = true;
|
|
|
|
std::tie(errorString, highlightIdx) = ret.value();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (failed) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "[Verifier][Error] Gate level input list schema verify failed";
|
2022-01-22 11:09:02 +00:00
|
|
|
Print("", true, highlightIdx);
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "Note: " << errorString;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
return !failed;
|
|
|
|
}
|
|
|
|
|
2022-01-27 08:46:57 +00:00
|
|
|
MachineType JSMachineType()
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2022-02-09 08:51:58 +00:00
|
|
|
return MachineType::I64;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t GetOpCodeNumIns(OpCode opcode, BitField bitfield)
|
|
|
|
{
|
|
|
|
return opcode.GetOpCodeNumIns(bitfield);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Out::SetNextOut(const Out *ptr)
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
nextOut_ =
|
2021-09-04 08:06:49 +00:00
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
2021-12-17 09:18:10 +00:00
|
|
|
static_cast<GateRef>((reinterpret_cast<const uint8_t *>(ptr)) - (reinterpret_cast<const uint8_t *>(this)));
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Out *Out::GetNextOut()
|
|
|
|
{
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
2021-12-17 09:18:10 +00:00
|
|
|
return reinterpret_cast<Out *>((reinterpret_cast<uint8_t *>(this)) + nextOut_);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const Out *Out::GetNextOutConst() const
|
|
|
|
{
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
2021-12-17 09:18:10 +00:00
|
|
|
return reinterpret_cast<const Out *>((reinterpret_cast<const uint8_t *>(this)) + nextOut_);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Out::SetPrevOut(const Out *ptr)
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
prevOut_ =
|
2021-09-04 08:06:49 +00:00
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
2021-12-17 09:18:10 +00:00
|
|
|
static_cast<GateRef>((reinterpret_cast<const uint8_t *>(ptr)) - (reinterpret_cast<const uint8_t *>(this)));
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Out *Out::GetPrevOut()
|
|
|
|
{
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
2021-12-17 09:18:10 +00:00
|
|
|
return reinterpret_cast<Out *>((reinterpret_cast<uint8_t *>(this)) + prevOut_);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const Out *Out::GetPrevOutConst() const
|
|
|
|
{
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
2021-12-17 09:18:10 +00:00
|
|
|
return reinterpret_cast<const Out *>((reinterpret_cast<const uint8_t *>(this)) + prevOut_);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Out::SetIndex(OutIdx idx)
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
idx_ = idx;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
OutIdx Out::GetIndex() const
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
return idx_;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Gate *Out::GetGate()
|
|
|
|
{
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
2021-12-17 09:18:10 +00:00
|
|
|
return reinterpret_cast<Gate *>(&this[idx_ + 1]);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const Gate *Out::GetGateConst() const
|
|
|
|
{
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
2021-12-17 09:18:10 +00:00
|
|
|
return reinterpret_cast<const Gate *>(&this[idx_ + 1]);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Out::SetPrevOutNull()
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
prevOut_ = 0;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Out::IsPrevOutNull() const
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
return prevOut_ == 0;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Out::SetNextOutNull()
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
nextOut_ = 0;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Out::IsNextOutNull() const
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
return nextOut_ == 0;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
2022-03-02 08:06:19 +00:00
|
|
|
bool Out::IsStateEdge() const
|
|
|
|
{
|
|
|
|
return idx_ < GetGateConst()->GetStateCount();
|
|
|
|
}
|
|
|
|
|
2021-09-04 08:06:49 +00:00
|
|
|
void In::SetGate(const Gate *ptr)
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
gatePtr_ =
|
2021-09-04 08:06:49 +00:00
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
2021-12-17 09:18:10 +00:00
|
|
|
static_cast<GateRef>((reinterpret_cast<const uint8_t *>(ptr)) - (reinterpret_cast<const uint8_t *>(this)));
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Gate *In::GetGate()
|
|
|
|
{
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
2021-12-17 09:18:10 +00:00
|
|
|
return reinterpret_cast<Gate *>((reinterpret_cast<uint8_t *>(this)) + gatePtr_);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const Gate *In::GetGateConst() const
|
|
|
|
{
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
2021-12-17 09:18:10 +00:00
|
|
|
return reinterpret_cast<const Gate *>((reinterpret_cast<const uint8_t *>(this)) + gatePtr_);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void In::SetGateNull()
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
gatePtr_ = 0;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool In::IsGateNull() const
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
return gatePtr_ == 0;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// NOLINTNEXTLINE(modernize-avoid-c-arrays)
|
2022-01-27 08:46:57 +00:00
|
|
|
Gate::Gate(GateId id, OpCode opcode, MachineType bitValue, BitField bitfield, Gate *inList[], GateType type,
|
2022-01-22 11:09:02 +00:00
|
|
|
MarkCode mark)
|
2022-01-19 01:11:02 +00:00
|
|
|
: id_(id), opcode_(opcode), bitValue_(bitValue), type_(type), stamp_(1), mark_(mark), bitfield_(bitfield),
|
|
|
|
firstOut_(0)
|
2022-01-11 13:09:24 +00:00
|
|
|
{
|
|
|
|
auto numIns = GetNumIns();
|
|
|
|
for (size_t idx = 0; idx < numIns; idx++) {
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
|
|
|
auto in = inList[idx];
|
|
|
|
if (in == nullptr) {
|
|
|
|
GetIn(idx)->SetGateNull();
|
|
|
|
} else {
|
|
|
|
NewIn(idx, in);
|
|
|
|
}
|
|
|
|
auto curOut = GetOut(idx);
|
|
|
|
curOut->SetIndex(idx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-27 08:46:57 +00:00
|
|
|
Gate::Gate(GateId id, OpCode opcode, BitField bitfield, Gate *inList[], GateType type, MarkCode mark)
|
2022-01-18 04:02:20 +00:00
|
|
|
: id_(id), opcode_(opcode), type_(type), stamp_(1), mark_(mark), bitfield_(bitfield), firstOut_(0)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
auto numIns = GetNumIns();
|
2021-09-04 08:06:49 +00:00
|
|
|
for (size_t idx = 0; idx < numIns; idx++) {
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
|
|
|
auto in = inList[idx];
|
|
|
|
if (in == nullptr) {
|
2021-12-17 09:18:10 +00:00
|
|
|
GetIn(idx)->SetGateNull();
|
2021-09-04 08:06:49 +00:00
|
|
|
} else {
|
2021-12-17 09:18:10 +00:00
|
|
|
NewIn(idx, in);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
2021-12-17 09:18:10 +00:00
|
|
|
auto curOut = GetOut(idx);
|
2021-09-04 08:06:49 +00:00
|
|
|
curOut->SetIndex(idx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t Gate::GetOutListSize(size_t numIns)
|
|
|
|
{
|
|
|
|
return numIns * sizeof(Out);
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t Gate::GetOutListSize() const
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
return Gate::GetOutListSize(GetNumIns());
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t Gate::GetInListSize(size_t numIns)
|
|
|
|
{
|
|
|
|
return numIns * sizeof(In);
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t Gate::GetInListSize() const
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
return Gate::GetInListSize(GetNumIns());
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t Gate::GetGateSize(size_t numIns)
|
|
|
|
{
|
|
|
|
return Gate::GetOutListSize(numIns) + Gate::GetInListSize(numIns) + sizeof(Gate);
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t Gate::GetGateSize() const
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
return Gate::GetGateSize(GetNumIns());
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Gate::NewIn(size_t idx, Gate *in)
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
GetIn(idx)->SetGate(in);
|
|
|
|
auto curOut = GetOut(idx);
|
2021-09-04 08:06:49 +00:00
|
|
|
if (in->IsFirstOutNull()) {
|
|
|
|
curOut->SetNextOutNull();
|
|
|
|
} else {
|
|
|
|
curOut->SetNextOut(in->GetFirstOut());
|
|
|
|
in->GetFirstOut()->SetPrevOut(curOut);
|
|
|
|
}
|
|
|
|
curOut->SetPrevOutNull();
|
|
|
|
in->SetFirstOut(curOut);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Gate::ModifyIn(size_t idx, Gate *in)
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
DeleteIn(idx);
|
|
|
|
NewIn(idx, in);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Gate::DeleteIn(size_t idx)
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
if (!GetOut(idx)->IsNextOutNull() && !GetOut(idx)->IsPrevOutNull()) {
|
|
|
|
GetOut(idx)->GetPrevOut()->SetNextOut(GetOut(idx)->GetNextOut());
|
|
|
|
GetOut(idx)->GetNextOut()->SetPrevOut(GetOut(idx)->GetPrevOut());
|
|
|
|
} else if (GetOut(idx)->IsNextOutNull() && !GetOut(idx)->IsPrevOutNull()) {
|
|
|
|
GetOut(idx)->GetPrevOut()->SetNextOutNull();
|
|
|
|
} else if (!GetOut(idx)->IsNextOutNull()) { // then GetOut(idx)->IsPrevOutNull() is true
|
|
|
|
GetIn(idx)->GetGate()->SetFirstOut(GetOut(idx)->GetNextOut());
|
|
|
|
GetOut(idx)->GetNextOut()->SetPrevOutNull();
|
2021-09-04 08:06:49 +00:00
|
|
|
} else { // only this out now
|
2021-12-17 09:18:10 +00:00
|
|
|
GetIn(idx)->GetGate()->SetFirstOutNull();
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
2021-12-17 09:18:10 +00:00
|
|
|
GetIn(idx)->SetGateNull();
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Gate::DeleteGate()
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
auto numIns = GetNumIns();
|
2021-09-04 08:06:49 +00:00
|
|
|
for (size_t idx = 0; idx < numIns; idx++) {
|
2021-12-17 09:18:10 +00:00
|
|
|
DeleteIn(idx);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
2021-12-17 09:18:10 +00:00
|
|
|
SetOpCode(OpCode(OpCode::NOP));
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Out *Gate::GetOut(size_t idx)
|
|
|
|
{
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
|
|
|
return &reinterpret_cast<Out *>(this)[-1 - idx];
|
|
|
|
}
|
|
|
|
|
|
|
|
Out *Gate::GetFirstOut()
|
|
|
|
{
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
2021-12-17 09:18:10 +00:00
|
|
|
return reinterpret_cast<Out *>((reinterpret_cast<uint8_t *>(this)) + firstOut_);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const Out *Gate::GetFirstOutConst() const
|
|
|
|
{
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
2021-12-17 09:18:10 +00:00
|
|
|
return reinterpret_cast<const Out *>((reinterpret_cast<const uint8_t *>(this)) + firstOut_);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Gate::SetFirstOutNull()
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
firstOut_ = 0;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Gate::IsFirstOutNull() const
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
return firstOut_ == 0;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Gate::SetFirstOut(const Out *firstOut)
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
firstOut_ =
|
2021-09-04 08:06:49 +00:00
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
2021-12-17 09:18:10 +00:00
|
|
|
static_cast<GateRef>(reinterpret_cast<const uint8_t *>(firstOut) - reinterpret_cast<const uint8_t *>(this));
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
In *Gate::GetIn(size_t idx)
|
|
|
|
{
|
|
|
|
#ifndef NDEBUG
|
2021-12-17 09:18:10 +00:00
|
|
|
if (idx >= GetNumIns()) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(INFO) << std::dec << "Gate In access out-of-bound! (idx=" << idx << ")";
|
2021-12-17 09:18:10 +00:00
|
|
|
Print();
|
2021-09-04 08:06:49 +00:00
|
|
|
ASSERT(false);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
|
|
|
return &reinterpret_cast<In *>(this + 1)[idx];
|
|
|
|
}
|
|
|
|
|
|
|
|
const In *Gate::GetInConst(size_t idx) const
|
|
|
|
{
|
|
|
|
#ifndef NDEBUG
|
2021-12-17 09:18:10 +00:00
|
|
|
if (idx >= GetNumIns()) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(INFO) << std::dec << "Gate In access out-of-bound! (idx=" << idx << ")";
|
2021-12-17 09:18:10 +00:00
|
|
|
Print();
|
2021-09-04 08:06:49 +00:00
|
|
|
ASSERT(false);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
|
|
|
return &reinterpret_cast<const In *>(this + 1)[idx];
|
|
|
|
}
|
|
|
|
|
|
|
|
Gate *Gate::GetInGate(size_t idx)
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
return GetIn(idx)->GetGate();
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const Gate *Gate::GetInGateConst(size_t idx) const
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
return GetInConst(idx)->GetGateConst();
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Gate::IsInGateNull(size_t idx) const
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
return GetInConst(idx)->IsGateNull();
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
GateId Gate::GetId() const
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
return id_;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
OpCode Gate::GetOpCode() const
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
return opcode_;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
2022-01-27 08:46:57 +00:00
|
|
|
MachineType Gate::GetMachineType() const
|
2022-01-11 13:09:24 +00:00
|
|
|
{
|
|
|
|
return bitValue_;
|
|
|
|
}
|
|
|
|
|
2022-01-27 08:46:57 +00:00
|
|
|
void Gate::SetMachineType(MachineType MachineType)
|
2022-01-11 13:09:24 +00:00
|
|
|
{
|
2022-01-27 08:46:57 +00:00
|
|
|
bitValue_ = MachineType;
|
2022-01-11 13:09:24 +00:00
|
|
|
}
|
|
|
|
|
2021-09-04 08:06:49 +00:00
|
|
|
void Gate::SetOpCode(OpCode opcode)
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
opcode_ = opcode;
|
|
|
|
}
|
|
|
|
|
2022-01-27 08:46:57 +00:00
|
|
|
GateType Gate::GetGateType() const
|
2021-12-17 09:18:10 +00:00
|
|
|
{
|
|
|
|
return type_;
|
|
|
|
}
|
|
|
|
|
2021-09-04 08:06:49 +00:00
|
|
|
size_t Gate::GetNumIns() const
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
return GetOpCodeNumIns(GetOpCode(), GetBitField());
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
2022-03-02 08:06:19 +00:00
|
|
|
size_t Gate::GetStateCount() const
|
|
|
|
{
|
|
|
|
return GetOpCode().GetStateCount(GetBitField());
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t Gate::GetDependCount() const
|
|
|
|
{
|
|
|
|
return GetOpCode().GetDependCount(GetBitField());
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t Gate::GetInValueCount() const
|
|
|
|
{
|
|
|
|
return GetOpCode().GetInValueCount(GetBitField());
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t Gate::GetRootCount() const
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2022-03-02 08:06:19 +00:00
|
|
|
return GetOpCode().GetRootCount(GetBitField());
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BitField Gate::GetBitField() const
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
return bitfield_;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Gate::SetBitField(BitField bitfield)
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
bitfield_ = bitfield;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
2022-01-27 08:46:57 +00:00
|
|
|
std::string Gate::MachineTypeStr(MachineType machineType) const
|
2022-01-11 13:09:24 +00:00
|
|
|
{
|
2022-01-27 08:46:57 +00:00
|
|
|
const std::map<MachineType, const char *> strMap = {
|
2022-07-11 01:50:28 +00:00
|
|
|
{NOVALUE, "NOVALUE"},
|
|
|
|
{ANYVALUE, "ANYVALUE"},
|
|
|
|
{ARCH, "ARCH"},
|
|
|
|
{FLEX, "FLEX"},
|
|
|
|
{I1, "I1"},
|
|
|
|
{I8, "I8"},
|
|
|
|
{I16, "I16"},
|
|
|
|
{I32, "I32"},
|
|
|
|
{I64, "I64"},
|
|
|
|
{F32, "F32"},
|
|
|
|
{F64, "F64"},
|
2022-01-11 13:09:24 +00:00
|
|
|
};
|
2022-01-27 08:46:57 +00:00
|
|
|
if (strMap.count(machineType) > 0) {
|
|
|
|
return strMap.at(machineType);
|
|
|
|
}
|
|
|
|
return "MachineType-" + std::to_string(machineType);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string Gate::GateTypeStr(GateType gateType) const
|
|
|
|
{
|
|
|
|
const std::map<GateType, const char *> strMap = {
|
2022-06-08 11:50:21 +00:00
|
|
|
{GateType::NJSValue(), "NJS_VALUE"},
|
|
|
|
{GateType::TaggedValue(), "TAGGED_VALUE"},
|
|
|
|
{GateType::TaggedPointer(), "TAGGED_POINTER"},
|
|
|
|
{GateType::TaggedNPointer(), "TAGGED_NPOINTER"},
|
|
|
|
{GateType::Empty(), "EMPTY"},
|
|
|
|
{GateType::AnyType(), "ANY_TYPE"},
|
2022-01-27 08:46:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
if (strMap.count(gateType) > 0) {
|
|
|
|
return strMap.at(gateType);
|
2022-01-11 13:09:24 +00:00
|
|
|
}
|
2022-06-08 11:50:21 +00:00
|
|
|
return "GateType-" + std::to_string(gateType.GetType());
|
2022-01-11 13:09:24 +00:00
|
|
|
}
|
|
|
|
|
2022-01-18 04:02:20 +00:00
|
|
|
void Gate::Print(std::string bytecode, bool inListPreview, size_t highlightIdx) const
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
if (GetOpCode() != OpCode::NOP) {
|
2022-04-14 08:14:34 +00:00
|
|
|
std::string log("(id=" + std::to_string(id_) + ", op=" + GetOpCode().Str() + ", ");
|
|
|
|
log += ((bytecode.compare("") == 0) ? "" : "bytecode=") + bytecode;
|
|
|
|
log += ((bytecode.compare("") == 0) ? "" : ", ");
|
|
|
|
log += "machineType=" + MachineTypeStr(GetMachineType()) + ", ";
|
|
|
|
log += "bitfield=" + std::to_string(bitfield_) + ", ";
|
|
|
|
log += "type=" + GateTypeStr(type_) + ", ";
|
|
|
|
log += "stamp=" + std::to_string(static_cast<uint32_t>(stamp_)) + ", ";
|
|
|
|
log += "mark=" + std::to_string(static_cast<uint32_t>(mark_)) + ", ";
|
|
|
|
log += "in=[";
|
|
|
|
|
2022-01-18 04:02:20 +00:00
|
|
|
size_t idx = 0;
|
2022-03-02 08:06:19 +00:00
|
|
|
auto stateSize = GetStateCount();
|
|
|
|
auto dependSize = GetDependCount();
|
|
|
|
auto valueSize = GetInValueCount();
|
|
|
|
auto rootSize = GetRootCount();
|
2022-04-14 08:14:34 +00:00
|
|
|
idx = PrintInGate(stateSize, idx, 0, inListPreview, highlightIdx, log);
|
|
|
|
idx = PrintInGate(stateSize + dependSize, idx, stateSize, inListPreview, highlightIdx, log);
|
|
|
|
idx = PrintInGate(stateSize + dependSize + valueSize, idx, stateSize + dependSize,
|
|
|
|
inListPreview, highlightIdx, log);
|
2022-01-22 11:09:02 +00:00
|
|
|
PrintInGate(stateSize + dependSize + valueSize + rootSize, idx, stateSize + dependSize + valueSize,
|
2022-04-14 08:14:34 +00:00
|
|
|
inListPreview, highlightIdx, log, true);
|
|
|
|
|
|
|
|
log += "], out=[";
|
2022-01-18 04:02:20 +00:00
|
|
|
|
2021-12-17 09:18:10 +00:00
|
|
|
if (!IsFirstOutNull()) {
|
|
|
|
const Out *curOut = GetFirstOutConst();
|
2022-04-14 08:14:34 +00:00
|
|
|
log += std::to_string(curOut->GetGateConst()->GetId()) +
|
2021-09-04 08:06:49 +00:00
|
|
|
(inListPreview ? std::string(":" + curOut->GetGateConst()->GetOpCode().Str()) : std::string(""));
|
2022-04-14 08:14:34 +00:00
|
|
|
|
2021-09-04 08:06:49 +00:00
|
|
|
while (!curOut->IsNextOutNull()) {
|
|
|
|
curOut = curOut->GetNextOutConst();
|
2022-04-14 08:14:34 +00:00
|
|
|
log += " " + std::to_string(curOut->GetGateConst()->GetId()) +
|
|
|
|
(inListPreview ? std::string(":" + curOut->GetGateConst()->GetOpCode().Str())
|
2021-09-04 08:06:49 +00:00
|
|
|
: std::string(""));
|
|
|
|
}
|
|
|
|
}
|
2022-04-14 08:14:34 +00:00
|
|
|
log += "])";
|
2022-05-29 23:22:55 +00:00
|
|
|
log += "\n";
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(INFO) << std::dec << log;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-18 04:02:20 +00:00
|
|
|
size_t Gate::PrintInGate(size_t numIns, size_t idx, size_t size, bool inListPreview, size_t highlightIdx,
|
2022-04-14 08:14:34 +00:00
|
|
|
std::string &log, bool isEnd) const
|
2022-01-18 04:02:20 +00:00
|
|
|
{
|
2022-04-14 08:14:34 +00:00
|
|
|
log += "[";
|
2022-01-18 04:02:20 +00:00
|
|
|
for (; idx < numIns; idx++) {
|
2022-04-14 08:14:34 +00:00
|
|
|
log += ((idx == size) ? "" : " ");
|
|
|
|
log += ((idx == highlightIdx) ? "\033[4;31m" : "");
|
|
|
|
log += ((IsInGateNull(idx)
|
2022-01-18 04:02:20 +00:00
|
|
|
? "N"
|
|
|
|
: (std::to_string(GetInGateConst(idx)->GetId()) +
|
|
|
|
(inListPreview ? std::string(":" + GetInGateConst(idx)->GetOpCode().Str())
|
2022-04-14 08:14:34 +00:00
|
|
|
: std::string("")))));
|
|
|
|
log += ((idx == highlightIdx) ? "\033[0m" : "");
|
2022-01-18 04:02:20 +00:00
|
|
|
}
|
2022-04-14 08:14:34 +00:00
|
|
|
log += "]";
|
|
|
|
log += ((isEnd) ? "" : ", ");
|
2022-01-18 04:02:20 +00:00
|
|
|
return idx;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Gate::PrintByteCode(std::string bytecode) const
|
|
|
|
{
|
|
|
|
Print(bytecode);
|
|
|
|
}
|
|
|
|
|
2021-09-04 08:06:49 +00:00
|
|
|
MarkCode Gate::GetMark(TimeStamp stamp) const
|
|
|
|
{
|
2022-01-27 08:46:57 +00:00
|
|
|
return (stamp_ == stamp) ? mark_ : MarkCode::NO_MARK;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Gate::SetMark(MarkCode mark, TimeStamp stamp)
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
stamp_ = stamp;
|
|
|
|
mark_ = mark;
|
2021-10-28 07:06:25 +00:00
|
|
|
}
|
|
|
|
|
2021-09-04 08:06:49 +00:00
|
|
|
bool OpCode::IsRoot() const
|
|
|
|
{
|
2022-03-02 08:06:19 +00:00
|
|
|
return (GetProperties().root == OpCode::CIRCUIT_ROOT) || (op_ == OpCode::CIRCUIT_ROOT);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool OpCode::IsProlog() const
|
|
|
|
{
|
2022-03-02 08:06:19 +00:00
|
|
|
return (GetProperties().root == OpCode::ARG_LIST);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool OpCode::IsFixed() const
|
|
|
|
{
|
2022-03-02 08:06:19 +00:00
|
|
|
return (op_ == OpCode::VALUE_SELECTOR) || (op_ == OpCode::DEPEND_SELECTOR) || (op_ == OpCode::DEPEND_RELAY);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool OpCode::IsSchedulable() const
|
|
|
|
{
|
2022-03-02 08:06:19 +00:00
|
|
|
return (op_ != OpCode::NOP) && (!IsProlog()) && (!IsRoot()) && (!IsFixed()) && (GetStateCount(1) == 0);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool OpCode::IsState() const
|
|
|
|
{
|
2022-03-02 08:06:19 +00:00
|
|
|
return (op_ != OpCode::NOP) && (!IsProlog()) && (!IsRoot()) && (!IsFixed()) && (GetStateCount(1) > 0);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool OpCode::IsGeneralState() const
|
|
|
|
{
|
2022-03-02 08:06:19 +00:00
|
|
|
return ((op_ == OpCode::IF_TRUE) || (op_ == OpCode::IF_FALSE) || (op_ == OpCode::JS_BYTECODE) ||
|
|
|
|
(op_ == OpCode::IF_SUCCESS) || (op_ == OpCode::IF_EXCEPTION) || (op_ == OpCode::SWITCH_CASE) ||
|
2021-12-30 17:38:35 +00:00
|
|
|
(op_ == OpCode::DEFAULT_CASE) || (op_ == OpCode::MERGE) || (op_ == OpCode::LOOP_BEGIN) ||
|
|
|
|
(op_ == OpCode::ORDINARY_BLOCK) || (op_ == OpCode::STATE_ENTRY));
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool OpCode::IsTerminalState() const
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
return ((op_ == OpCode::RETURN) || (op_ == OpCode::THROW) || (op_ == OpCode::RETURN_VOID));
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool OpCode::IsCFGMerge() const
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
return (op_ == OpCode::MERGE) || (op_ == OpCode::LOOP_BEGIN);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
2021-09-26 06:47:20 +00:00
|
|
|
|
|
|
|
bool OpCode::IsControlCase() const
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
return (op_ == OpCode::IF_BRANCH) || (op_ == OpCode::SWITCH_BRANCH) || (op_ == OpCode::IF_TRUE) ||
|
2021-12-30 17:38:35 +00:00
|
|
|
(op_ == OpCode::IF_FALSE) || (op_ == OpCode::IF_SUCCESS) || (op_ == OpCode::IF_EXCEPTION) ||
|
|
|
|
(op_ == OpCode::SWITCH_CASE) || (op_ == OpCode::DEFAULT_CASE);
|
2021-09-26 06:47:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool OpCode::IsLoopHead() const
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
return (op_ == OpCode::LOOP_BEGIN);
|
2021-09-26 06:47:20 +00:00
|
|
|
}
|
2021-10-28 07:06:25 +00:00
|
|
|
|
|
|
|
bool OpCode::IsNop() const
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
return (op_ == OpCode::NOP);
|
2021-10-28 07:06:25 +00:00
|
|
|
}
|
2022-01-04 11:30:40 +00:00
|
|
|
} // namespace panda::ecmascript::kungfu
|