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.
|
|
|
|
*/
|
|
|
|
|
2021-09-07 14:24:16 +00:00
|
|
|
#ifndef ECMASCRIPT_COMPILER_GATE_H
|
|
|
|
#define ECMASCRIPT_COMPILER_GATE_H
|
2021-09-04 08:06:49 +00:00
|
|
|
|
|
|
|
#include <array>
|
|
|
|
#include <iostream>
|
|
|
|
#include <map>
|
|
|
|
#include <optional>
|
|
|
|
#include <set>
|
|
|
|
#include <sstream>
|
|
|
|
#include <string>
|
|
|
|
#include <type_traits>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include "libpandabase/macros.h"
|
|
|
|
#include "ecmascript/compiler/type.h"
|
|
|
|
|
2021-12-23 06:55:22 +00:00
|
|
|
namespace panda::ecmascript::kungfu {
|
2021-12-17 09:18:10 +00:00
|
|
|
using GateRef = int32_t; // for external users
|
2021-09-04 08:06:49 +00:00
|
|
|
using GateId = uint32_t;
|
|
|
|
using GateOp = uint8_t;
|
|
|
|
using GateMark = uint8_t;
|
|
|
|
using TimeStamp = uint8_t;
|
2022-01-11 13:09:24 +00:00
|
|
|
using SecondaryOp = uint8_t;
|
2021-09-04 08:06:49 +00:00
|
|
|
using BitField = uint64_t;
|
|
|
|
using OutIdx = uint32_t;
|
|
|
|
class Gate;
|
2021-12-23 06:55:22 +00:00
|
|
|
struct Properties;
|
2021-09-04 08:06:49 +00:00
|
|
|
|
|
|
|
enum ValueCode {
|
|
|
|
NOVALUE,
|
|
|
|
ANYVALUE,
|
2022-01-11 13:09:24 +00:00
|
|
|
ARCH,
|
|
|
|
FLEX,
|
2021-09-04 08:06:49 +00:00
|
|
|
INT1,
|
|
|
|
INT8,
|
|
|
|
INT16,
|
|
|
|
INT32,
|
|
|
|
INT64,
|
|
|
|
FLOAT32,
|
|
|
|
FLOAT64,
|
|
|
|
};
|
|
|
|
|
|
|
|
std::string ValueCodeToStr(ValueCode valueCode);
|
|
|
|
|
|
|
|
class OpCode {
|
|
|
|
public:
|
|
|
|
enum Op : GateOp {
|
|
|
|
// SHARED
|
|
|
|
NOP,
|
|
|
|
CIRCUIT_ROOT,
|
|
|
|
STATE_ENTRY,
|
|
|
|
DEPEND_ENTRY,
|
|
|
|
FRAMESTATE_ENTRY,
|
|
|
|
RETURN_LIST,
|
|
|
|
THROW_LIST,
|
|
|
|
CONSTANT_LIST,
|
|
|
|
ALLOCA_LIST,
|
|
|
|
ARG_LIST,
|
|
|
|
RETURN,
|
2021-12-17 09:18:10 +00:00
|
|
|
RETURN_VOID,
|
2021-09-04 08:06:49 +00:00
|
|
|
THROW,
|
|
|
|
ORDINARY_BLOCK,
|
|
|
|
IF_BRANCH,
|
|
|
|
SWITCH_BRANCH,
|
|
|
|
IF_TRUE,
|
|
|
|
IF_FALSE,
|
2021-12-30 17:38:35 +00:00
|
|
|
IF_SUCCESS,
|
|
|
|
IF_EXCEPTION,
|
2021-09-04 08:06:49 +00:00
|
|
|
SWITCH_CASE,
|
|
|
|
DEFAULT_CASE,
|
|
|
|
MERGE,
|
|
|
|
LOOP_BEGIN,
|
|
|
|
LOOP_BACK,
|
2022-01-11 13:09:24 +00:00
|
|
|
VALUE_SELECTOR,
|
2021-09-04 08:06:49 +00:00
|
|
|
DEPEND_SELECTOR,
|
|
|
|
DEPEND_RELAY,
|
|
|
|
DEPEND_AND,
|
|
|
|
// High Level IR
|
2021-12-30 17:38:35 +00:00
|
|
|
JS_BYTECODE,
|
2021-09-04 08:06:49 +00:00
|
|
|
// Middle Level IR
|
|
|
|
CALL,
|
|
|
|
ALLOCA,
|
2022-01-11 13:09:24 +00:00
|
|
|
ARG,
|
2021-09-04 08:06:49 +00:00
|
|
|
MUTABLE_DATA,
|
|
|
|
CONST_DATA,
|
2022-01-11 13:09:24 +00:00
|
|
|
CONSTANT,
|
|
|
|
ZEXT_TO_INT64,
|
|
|
|
ZEXT_TO_INT32,
|
|
|
|
SEXT_TO_INT64,
|
|
|
|
SEXT_TO_INT32,
|
|
|
|
TRUNC_TO_INT32,
|
|
|
|
TRUNC_TO_INT1,
|
|
|
|
REV,
|
|
|
|
ADD,
|
|
|
|
SUB,
|
|
|
|
MUL,
|
|
|
|
EXP,
|
|
|
|
SDIV,
|
|
|
|
SMOD,
|
|
|
|
UDIV,
|
|
|
|
UMOD,
|
|
|
|
FDIV,
|
|
|
|
FMOD,
|
|
|
|
AND,
|
|
|
|
XOR,
|
|
|
|
OR,
|
|
|
|
LSL,
|
|
|
|
LSR,
|
|
|
|
ASR,
|
|
|
|
SLT,
|
|
|
|
SLE,
|
|
|
|
SGT,
|
|
|
|
SGE,
|
|
|
|
ULT,
|
|
|
|
ULE,
|
|
|
|
UGT,
|
|
|
|
UGE,
|
|
|
|
FLT,
|
|
|
|
FLE,
|
|
|
|
FGT,
|
|
|
|
FGE,
|
|
|
|
EQ,
|
|
|
|
NE,
|
|
|
|
LOAD,
|
|
|
|
STORE,
|
|
|
|
TAGGED_TO_INT64,
|
|
|
|
SIGNED_INT_TO_FLOAT,
|
|
|
|
UNSIGNED_INT_TO_FLOAT,
|
|
|
|
FLOAT_TO_SIGNED_INT,
|
|
|
|
UNSIGNED_FLOAT_TO_INT,
|
|
|
|
BITCAST,
|
2021-09-04 08:06:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
OpCode() = default;
|
2021-12-17 09:18:10 +00:00
|
|
|
explicit constexpr OpCode(Op op) : op_(op) {}
|
2021-09-04 08:06:49 +00:00
|
|
|
operator Op() const
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
return op_;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
explicit operator bool() const = delete;
|
|
|
|
[[nodiscard]] Properties GetProperties() const;
|
|
|
|
[[nodiscard]] std::array<size_t, 4> GetOpCodeNumInsArray(BitField bitfield) const;
|
|
|
|
[[nodiscard]] size_t GetOpCodeNumIns(BitField bitfield) const;
|
|
|
|
[[nodiscard]] ValueCode GetValueCode() const;
|
|
|
|
[[nodiscard]] ValueCode GetInValueCode(BitField bitfield, size_t idx) const;
|
|
|
|
[[nodiscard]] OpCode GetInStateCode(size_t idx) const;
|
|
|
|
[[nodiscard]] std::string Str() const;
|
|
|
|
[[nodiscard]] bool IsRoot() const;
|
|
|
|
[[nodiscard]] bool IsProlog() const;
|
|
|
|
[[nodiscard]] bool IsFixed() const;
|
|
|
|
[[nodiscard]] bool IsSchedulable() const;
|
|
|
|
[[nodiscard]] bool IsState() const; // note: IsState(STATE_ENTRY) == false
|
|
|
|
[[nodiscard]] bool IsGeneralState() const;
|
|
|
|
[[nodiscard]] bool IsTerminalState() const;
|
|
|
|
[[nodiscard]] bool IsCFGMerge() const;
|
2021-09-26 06:47:20 +00:00
|
|
|
[[nodiscard]] bool IsControlCase() const;
|
|
|
|
[[nodiscard]] bool IsLoopHead() const;
|
2021-10-28 07:06:25 +00:00
|
|
|
[[nodiscard]] bool IsNop() const;
|
2021-09-04 08:06:49 +00:00
|
|
|
~OpCode() = default;
|
|
|
|
|
|
|
|
private:
|
2021-12-17 09:18:10 +00:00
|
|
|
Op op_;
|
2021-09-04 08:06:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct Properties {
|
|
|
|
ValueCode returnValue;
|
|
|
|
std::optional<std::pair<std::vector<OpCode>, bool>> statesIn;
|
|
|
|
size_t dependsIn;
|
|
|
|
std::optional<std::pair<std::vector<ValueCode>, bool>> valuesIn;
|
|
|
|
std::optional<OpCode> states;
|
|
|
|
};
|
|
|
|
|
|
|
|
enum MarkCode : GateMark {
|
|
|
|
EMPTY,
|
|
|
|
VISITED,
|
|
|
|
FINISHED,
|
|
|
|
};
|
|
|
|
|
|
|
|
ValueCode JSValueCode();
|
|
|
|
ValueCode PtrValueCode();
|
|
|
|
size_t GetValueBits(ValueCode valueCode);
|
|
|
|
|
|
|
|
class Out {
|
|
|
|
public:
|
|
|
|
Out() = default;
|
|
|
|
void SetNextOut(const Out *ptr);
|
|
|
|
[[nodiscard]] Out *GetNextOut();
|
|
|
|
[[nodiscard]] const Out *GetNextOutConst() const;
|
|
|
|
void SetPrevOut(const Out *ptr);
|
|
|
|
[[nodiscard]] Out *GetPrevOut();
|
|
|
|
[[nodiscard]] const Out *GetPrevOutConst() const;
|
|
|
|
void SetIndex(OutIdx idx);
|
|
|
|
[[nodiscard]] OutIdx GetIndex() const;
|
|
|
|
[[nodiscard]] Gate *GetGate();
|
|
|
|
[[nodiscard]] const Gate *GetGateConst() const;
|
|
|
|
void SetPrevOutNull();
|
|
|
|
[[nodiscard]] bool IsPrevOutNull() const;
|
|
|
|
void SetNextOutNull();
|
|
|
|
[[nodiscard]] bool IsNextOutNull() const;
|
|
|
|
~Out() = default;
|
|
|
|
|
|
|
|
private:
|
2021-12-17 09:18:10 +00:00
|
|
|
OutIdx idx_;
|
|
|
|
GateRef nextOut_;
|
|
|
|
GateRef prevOut_;
|
2021-09-04 08:06:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class In {
|
|
|
|
public:
|
|
|
|
In() = default;
|
|
|
|
void SetGate(const Gate *ptr);
|
|
|
|
[[nodiscard]] Gate *GetGate();
|
|
|
|
[[nodiscard]] const Gate *GetGateConst() const;
|
|
|
|
void SetGateNull();
|
|
|
|
[[nodiscard]] bool IsGateNull() const;
|
|
|
|
~In() = default;
|
|
|
|
|
|
|
|
private:
|
2021-12-17 09:18:10 +00:00
|
|
|
GateRef gatePtr_;
|
2021-09-04 08:06:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class Gate {
|
|
|
|
public:
|
|
|
|
// NOLINTNEXTLINE(modernize-avoid-c-arrays)
|
2022-01-11 13:09:24 +00:00
|
|
|
Gate(GateId id, OpCode opcode, ValueCode bitValue, BitField bitfield, Gate *inList[], TypeCode type, MarkCode mark,
|
|
|
|
SecondaryOp secondaryOp = 0);
|
|
|
|
Gate(GateId id, OpCode opcode, BitField bitfield, Gate *inList[], TypeCode type, MarkCode mark,
|
|
|
|
SecondaryOp secondaryOp = 0);
|
2021-09-04 08:06:49 +00:00
|
|
|
[[nodiscard]] static size_t GetGateSize(size_t numIns);
|
|
|
|
[[nodiscard]] size_t GetGateSize() const;
|
|
|
|
[[nodiscard]] static size_t GetOutListSize(size_t numIns);
|
|
|
|
[[nodiscard]] size_t GetOutListSize() const;
|
|
|
|
[[nodiscard]] static size_t GetInListSize(size_t numIns);
|
|
|
|
[[nodiscard]] size_t GetInListSize() const;
|
|
|
|
void NewIn(size_t idx, Gate *in);
|
|
|
|
void ModifyIn(size_t idx, Gate *in);
|
|
|
|
void DeleteIn(size_t idx);
|
|
|
|
void DeleteGate();
|
|
|
|
[[nodiscard]] Out *GetOut(size_t idx);
|
|
|
|
[[nodiscard]] Out *GetFirstOut();
|
|
|
|
[[nodiscard]] const Out *GetFirstOutConst() const;
|
|
|
|
// note: GetFirstOut() is not equal to GetOut(0)
|
|
|
|
// note: behavior of GetFirstOut() is undefined when there are no Outs
|
|
|
|
// note: use IsFirstOutNull() to check first if there may be no Outs
|
|
|
|
void SetFirstOut(const Out *firstOut);
|
|
|
|
void SetFirstOutNull();
|
|
|
|
[[nodiscard]] bool IsFirstOutNull() const;
|
|
|
|
[[nodiscard]] In *GetIn(size_t idx);
|
|
|
|
[[nodiscard]] const In *GetInConst(size_t idx) const;
|
|
|
|
[[nodiscard]] Gate *GetInGate(size_t idx);
|
|
|
|
[[nodiscard]] const Gate *GetInGateConst(size_t idx) const;
|
|
|
|
// note: behavior of GetInGate(idx) is undefined when Ins[idx] is deleted or not assigned
|
|
|
|
// note: use IsInGateNull(idx) to check first if Ins[idx] may be deleted or not assigned
|
|
|
|
[[nodiscard]] bool IsInGateNull(size_t idx) const;
|
|
|
|
[[nodiscard]] OpCode GetOpCode() const;
|
|
|
|
void SetOpCode(OpCode opcode);
|
2021-12-17 09:18:10 +00:00
|
|
|
[[nodiscard]] TypeCode GetTypeCode() const;
|
|
|
|
void SetTypeCode(TypeCode type);
|
2021-09-04 08:06:49 +00:00
|
|
|
[[nodiscard]] GateId GetId() const;
|
|
|
|
[[nodiscard]] size_t GetNumIns() const;
|
|
|
|
[[nodiscard]] std::array<size_t, 4> GetNumInsArray() const;
|
|
|
|
[[nodiscard]] BitField GetBitField() const;
|
|
|
|
void SetBitField(BitField bitfield);
|
|
|
|
void AppendIn(const Gate *in); // considered very slow
|
|
|
|
void Print(bool inListPreview = false, size_t highlightIdx = -1) const;
|
|
|
|
std::optional<std::pair<std::string, size_t>> CheckNullInput() const;
|
|
|
|
std::optional<std::pair<std::string, size_t>> CheckStateInput() const;
|
|
|
|
std::optional<std::pair<std::string, size_t>> CheckValueInput() const;
|
|
|
|
std::optional<std::pair<std::string, size_t>> CheckDependInput() const;
|
|
|
|
std::optional<std::pair<std::string, size_t>> CheckStateOutput() const;
|
|
|
|
std::optional<std::pair<std::string, size_t>> CheckBranchOutput() const;
|
|
|
|
std::optional<std::pair<std::string, size_t>> CheckNOP() const;
|
|
|
|
std::optional<std::pair<std::string, size_t>> CheckSelector() const;
|
|
|
|
std::optional<std::pair<std::string, size_t>> CheckRelay() const;
|
|
|
|
std::optional<std::pair<std::string, size_t>> SpecialCheck() const;
|
|
|
|
[[nodiscard]] bool Verify() const;
|
|
|
|
[[nodiscard]] MarkCode GetMark(TimeStamp stamp) const;
|
|
|
|
void SetMark(MarkCode mark, TimeStamp stamp);
|
2022-01-11 13:09:24 +00:00
|
|
|
[[nodiscard]] ValueCode GetValueCode() const;
|
|
|
|
void SetValueCode(ValueCode valueCode);
|
|
|
|
std::string ValueCodeStr(ValueCode valCode) const;
|
2021-09-04 08:06:49 +00:00
|
|
|
~Gate() = default;
|
|
|
|
|
|
|
|
private:
|
|
|
|
// ...
|
|
|
|
// out(2)
|
|
|
|
// out(1)
|
|
|
|
// out(0)
|
2021-12-17 09:18:10 +00:00
|
|
|
GateId id_;
|
|
|
|
OpCode opcode_;
|
2022-01-11 13:09:24 +00:00
|
|
|
ValueCode bitValue_ = ValueCode::NOVALUE;
|
2021-12-17 09:18:10 +00:00
|
|
|
TypeCode type_;
|
2022-01-11 13:09:24 +00:00
|
|
|
SecondaryOp secondaryOp_;
|
2021-12-17 09:18:10 +00:00
|
|
|
TimeStamp stamp_;
|
|
|
|
MarkCode mark_;
|
|
|
|
BitField bitfield_;
|
|
|
|
GateRef firstOut_;
|
2021-09-04 08:06:49 +00:00
|
|
|
// in(0)
|
|
|
|
// in(1)
|
|
|
|
// in(2)
|
|
|
|
// ...
|
|
|
|
};
|
2021-12-23 06:55:22 +00:00
|
|
|
} // namespace panda::ecmascript::kungfu
|
2021-09-04 08:06:49 +00:00
|
|
|
|
2021-09-07 14:24:16 +00:00
|
|
|
#endif // ECMASCRIPT_COMPILER_GATE_H
|