1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef ECMASCRIPT_COMPILER_GATE_H 17 #define ECMASCRIPT_COMPILER_GATE_H 18 19 #include <array> 20 #include <iostream> 21 #include <map> 22 #include <optional> 23 #include <set> 24 #include <sstream> 25 #include <string> 26 #include <type_traits> 27 #include <vector> 28 29 #include "ecmascript/compiler/gate_meta_data.h" 30 #include "ecmascript/compiler/type.h" 31 32 #include "libpandabase/macros.h" 33 34 namespace panda::ecmascript::kungfu { 35 using BitField = uint64_t; 36 using GateRef = int32_t; // for external users 37 using GateId = uint32_t; 38 using GateOp = uint8_t; 39 using GateMark = uint8_t; 40 using TimeStamp = uint8_t; 41 using SecondaryOp = uint8_t; 42 using OutIdx = uint32_t; 43 class Gate; 44 class BytecodeCircuitBuilder; 45 46 enum MarkCode : GateMark { 47 NO_MARK, 48 VISITED, 49 FINISHED, 50 }; 51 52 class Out { 53 public: 54 Out() = default; 55 void SetNextOut(const Out *ptr); 56 [[nodiscard]] Out *GetNextOut(); 57 [[nodiscard]] const Out *GetNextOutConst() const; 58 void SetPrevOut(const Out *ptr); 59 [[nodiscard]] Out *GetPrevOut(); 60 [[nodiscard]] const Out *GetPrevOutConst() const; 61 void SetIndex(OutIdx idx); 62 [[nodiscard]] OutIdx GetIndex() const; 63 [[nodiscard]] Gate *GetGate(); 64 [[nodiscard]] const Gate *GetGateConst() const; 65 void SetPrevOutNull(); 66 [[nodiscard]] bool IsPrevOutNull() const; 67 void SetNextOutNull(); 68 [[nodiscard]] bool IsNextOutNull() const; 69 [[nodiscard]] bool IsStateEdge() const; 70 ~Out() = default; 71 72 private: 73 GateRef nextOut_; 74 GateRef prevOut_; 75 OutIdx idx_; 76 }; 77 78 class In { 79 public: 80 In() = default; 81 void SetGate(const Gate *ptr); 82 [[nodiscard]] Gate *GetGate(); 83 [[nodiscard]] const Gate *GetGateConst() const; 84 void SetGateNull(); 85 [[nodiscard]] bool IsGateNull() const; 86 ~In() = default; 87 88 private: 89 GateRef gatePtr_; 90 }; 91 92 // Gate structure 93 // for example: 94 // ``` 95 // g0 = op0(...) 96 // g1 = op1(...) 97 // g2 = op2(g0, g1) 98 // g3 = op3(g2) 99 // g4 = op4(g2, g0, g1) 100 // g5 = op5(g3, g4) 101 102 // +---- out[1] ----+---- out[0] ----+-------- g2 --------+-- in[0] --+-- in[1] --+ 103 // | | | | | | 104 // | next=null | next=null | ... | | | 105 // | idx=1 | idx=0 | | g0 | g1 | 106 // | prev=g4.out[2] | prev=g4.out[1] | firstOut=g4.out[0] | | | 107 // | | | | | | 108 // +----------------+----------------+--------------------+-----------+-----------+ 109 // ^ ^ 110 // | | 111 // | | 112 // | | +---- out[0] ----+-------- g3 --------+-- in[0] --+ 113 // | | | | | | 114 // | | | next=null | ... | | 115 // | | | idx=0 | | g2 | 116 // | | | prev=g4.out[0] | firstOut=g5.out[0] | | 117 // | | | | | | 118 // | | +----------------+--------------------+-----------+ 119 // | | ^ 120 // | | | 121 // | | | 122 // V V V 123 // +---- out[2] ----+---- out[1] ----+---- out[0] ----+-------- g4 --------+-- in[0] --+-- in[1] --+-- in[2] --+ 124 // | | | | | | | | 125 // | next=g2.out[1] | next=g2.out[0] | next=g3.out[0] | ... | | | | 126 // | idx=2 | idx=1 | idx=0 | | g2 | g0 | g1 | 127 // | prev=null | prev=null | prev=null | firstOut=g5.out[1] | | | | 128 // | | | | | | | | 129 // +----------------+----------------+----------------+--------------------+-----------+-----------+-----------+ 130 // ``` 131 132 class Gate { 133 public: 134 // NOLINTNEXTLINE(modernize-avoid-c-arrays) 135 Gate(const GateMetaData* meta, GateId id, Gate *inList[], MachineType machineType, GateType type); GetGateSize(size_t numIns)136 static size_t GetGateSize(size_t numIns) 137 { 138 numIns = (numIns == 0) ? 1 : numIns; 139 return numIns * (sizeof(In) + sizeof(Out)) + sizeof(Gate); 140 } GetOutListSize(size_t numIns)141 static size_t GetOutListSize(size_t numIns) 142 { 143 numIns = (numIns == 0) ? 1 : numIns; 144 return numIns * sizeof(Out); 145 } 146 void NewIn(size_t idx, Gate *in); 147 void ModifyIn(size_t idx, Gate *in); 148 void DeleteIn(size_t idx); 149 void DeleteGate(); 150 static constexpr GateRef InvalidGateRef = -1; 151 [[nodiscard]] Out *GetOut(size_t idx); 152 [[nodiscard]] Out *GetFirstOut(); 153 [[nodiscard]] const Out *GetOutConst(size_t idx) const; 154 [[nodiscard]] const Out *GetFirstOutConst() const; 155 // note: GetFirstOut() is not equal to GetOut(0) 156 // note: behavior of GetFirstOut() is undefined when there are no Outs 157 // note: use IsFirstOutNull() to check first if there may be no Outs 158 void SetFirstOut(const Out *firstOut); 159 void SetFirstOutNull(); 160 [[nodiscard]] bool IsFirstOutNull() const; 161 [[nodiscard]] In *GetIn(size_t idx); 162 [[nodiscard]] const In *GetInConst(size_t idx) const; 163 [[nodiscard]] Gate *GetInGate(size_t idx); 164 [[nodiscard]] const Gate *GetInGateConst(size_t idx) const; 165 // note: behavior of GetInGate(idx) is undefined when Ins[idx] is deleted or not assigned 166 // note: use IsInGateNull(idx) to check first if Ins[idx] may be deleted or not assigned 167 [[nodiscard]] bool IsInGateNull(size_t idx) const; 168 [[nodiscard]] OpCode GetOpCode() const; 169 [[nodiscard]] GateId GetId() const; 170 [[nodiscard]] size_t GetNumIns() const; 171 [[nodiscard]] size_t GetStateCount() const; 172 [[nodiscard]] size_t GetDependCount() const; 173 [[nodiscard]] size_t GetInValueCount() const; 174 [[nodiscard]] size_t GetInFrameStateCount() const; 175 [[nodiscard]] size_t GetInValueStarts() const; 176 [[nodiscard]] size_t GetRootCount() const; 177 [[nodiscard]] size_t GetInFrameStateStarts() const; 178 void AppendIn(const Gate *in); // considered very slow 179 void Print(std::string bytecode = "", bool inListPreview = false, size_t highlightIdx = -1) const; 180 void ShortPrint(std::string bytecode = "", bool inListPreview = false, size_t highlightIdx = -1) const; 181 size_t PrintInGate(size_t numIns, size_t idx, size_t size, bool inListPreview, size_t highlightIdx, 182 std::string &log, bool isEnd = false) const; 183 void PrintByteCode(std::string bytecode) const; 184 void CheckNullInput() const; 185 void CheckStateInput() const; 186 void CheckValueInput(bool isArch64) const; 187 void CheckDependInput() const; 188 void CheckRootInput() const; 189 void CheckFrameStateInput() const; 190 void CheckStateOutput() const; 191 void CheckBranchOutput() const; 192 void CheckNOP() const; 193 void CheckSelector() const; 194 void CheckRelay() const; 195 void Verify(bool isArch64) const; 196 [[nodiscard]] MarkCode GetMark(TimeStamp stamp) const; 197 void SetMark(MarkCode mark, TimeStamp stamp); GetMachineType()198 MachineType GetMachineType() const 199 { 200 return machineType_; 201 } SetMachineType(MachineType machineType)202 void SetMachineType(MachineType machineType) 203 { 204 machineType_ = machineType; 205 } GetGateType()206 GateType GetGateType() const 207 { 208 return type_; 209 } SetGateType(GateType type)210 void SetGateType(GateType type) 211 { 212 type_ = type; 213 } GetMetaData()214 const GateMetaData* GetMetaData() const 215 { 216 return meta_; 217 } 218 GetOneParameterMetaData()219 const OneParameterMetaData* GetOneParameterMetaData() const 220 { 221 return OneParameterMetaData::Cast(meta_); 222 } 223 GetTypedBinaryMegaData()224 const TypedBinaryMegaData* GetTypedBinaryMegaData() const 225 { 226 return TypedBinaryMegaData::Cast(meta_); 227 } 228 GetJSBytecodeMetaData()229 const JSBytecodeMetaData* GetJSBytecodeMetaData() const 230 { 231 return JSBytecodeMetaData::Cast(meta_); 232 } 233 234 std::string MachineTypeStr(MachineType machineType) const; 235 std::string GateTypeStr(GateType gateType) const; 236 ~Gate() = default; 237 238 private: 239 friend class Circuit; 240 friend class GateAccessor; 241 void CheckInputOpcode(size_t i, OpCode expected) const; 242 void CheckInputMachineType(size_t i, MachineType expected, bool isArch64) const; 243 void CheckGeneralState(size_t idx) const; 244 void CheckFailed(std::string errorString, size_t highlightIdx) const; SetMetaData(const GateMetaData * meta)245 void SetMetaData(const GateMetaData* meta) 246 { 247 meta_ = meta; 248 } TryGetValue()249 uint64_t TryGetValue() const 250 { 251 if (meta_->IsOneParameterKind()) { 252 return GetOneParameterMetaData()->GetValue(); 253 } 254 return 0; 255 } 256 // ... 257 // out(2) 258 // out(1) 259 // out(0) 260 const GateMetaData *meta_ { nullptr }; // uintptr_t 261 GateId id_ { 0 }; // uint32_t 262 GateType type_ { GateType::Empty() }; // uint32_t 263 MachineType machineType_ { MachineType::NOVALUE }; // uint8_t 264 TimeStamp stamp_ { 0 }; // uint8_t 265 MarkCode mark_ { MarkCode::NO_MARK }; // uint8_t 266 uint8_t bitField_ { 0 }; 267 GateRef firstOut_ { 0 }; // int32_t 268 // in(0) 269 // in(1) 270 // in(2) 271 // ... 272 }; 273 } // namespace panda::ecmascript::kungfu 274 275 #endif // ECMASCRIPT_COMPILER_GATE_H