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/share_gate_meta_data.h" 30 #include "ecmascript/compiler/hcr_gate_meta_data.h" 31 #include "ecmascript/compiler/mcr_gate_meta_data.h" 32 #include "ecmascript/compiler/lcr_gate_meta_data.h" 33 #include "ecmascript/compiler/type.h" 34 35 #include "libpandabase/macros.h" 36 37 namespace panda::ecmascript::kungfu { 38 using BitField = uint64_t; 39 using GateRef = int32_t; // for external users 40 using GateId = uint32_t; 41 using GateOp = uint8_t; 42 using GateMark = uint8_t; 43 using TimeStamp = uint8_t; 44 using SecondaryOp = uint8_t; 45 using OutIdx = uint32_t; 46 class Gate; 47 class BytecodeCircuitBuilder; 48 49 enum MarkCode : GateMark { 50 NO_MARK = 0, 51 PREVISIT, 52 VISITED, 53 FINISHED, 54 }; 55 56 class Out { 57 public: 58 Out() = default; 59 void SetNextOut(const Out *ptr); 60 [[nodiscard]] Out *GetNextOut(); 61 [[nodiscard]] const Out *GetNextOutConst() const; 62 void SetPrevOut(const Out *ptr); 63 [[nodiscard]] Out *GetPrevOut(); 64 [[nodiscard]] const Out *GetPrevOutConst() const; 65 void SetIndex(OutIdx idx); 66 [[nodiscard]] OutIdx GetIndex() const; 67 [[nodiscard]] Gate *GetGate(); 68 [[nodiscard]] const Gate *GetGateConst() const; 69 void SetPrevOutNull(); 70 [[nodiscard]] bool IsPrevOutNull() const; 71 void SetNextOutNull(); 72 [[nodiscard]] bool IsNextOutNull() const; 73 [[nodiscard]] bool IsStateEdge() const; 74 ~Out() = default; 75 76 private: 77 GateRef nextOut_; 78 GateRef prevOut_; 79 OutIdx idx_; 80 }; 81 82 class In { 83 public: 84 In() = default; 85 void SetGate(const Gate *ptr); 86 [[nodiscard]] Gate *GetGate(); 87 [[nodiscard]] const Gate *GetGateConst() const; 88 void SetGateNull(); 89 [[nodiscard]] bool IsGateNull() const; 90 ~In() = default; 91 92 private: 93 GateRef gatePtr_; 94 }; 95 96 // Gate structure 97 // for example: 98 // ``` 99 // g0 = op0(...) 100 // g1 = op1(...) 101 // g2 = op2(g0, g1) 102 // g3 = op3(g2) 103 // g4 = op4(g2, g0, g1) 104 // g5 = op5(g3, g4) 105 106 // +---- out[1] ----+---- out[0] ----+-------- g2 --------+-- in[0] --+-- in[1] --+ 107 // | | | | | | 108 // | next=null | next=null | ... | | | 109 // | idx=1 | idx=0 | | g0 | g1 | 110 // | prev=g4.out[2] | prev=g4.out[1] | firstOut=g4.out[0] | | | 111 // | | | | | | 112 // +----------------+----------------+--------------------+-----------+-----------+ 113 // ^ ^ 114 // | | 115 // | | 116 // | | +---- out[0] ----+-------- g3 --------+-- in[0] --+ 117 // | | | | | | 118 // | | | next=null | ... | | 119 // | | | idx=0 | | g2 | 120 // | | | prev=g4.out[0] | firstOut=g5.out[0] | | 121 // | | | | | | 122 // | | +----------------+--------------------+-----------+ 123 // | | ^ 124 // | | | 125 // | | | 126 // V V V 127 // +---- out[2] ----+---- out[1] ----+---- out[0] ----+-------- g4 --------+-- in[0] --+-- in[1] --+-- in[2] --+ 128 // | | | | | | | | 129 // | next=g2.out[1] | next=g2.out[0] | next=g3.out[0] | ... | | | | 130 // | idx=2 | idx=1 | idx=0 | | g2 | g0 | g1 | 131 // | prev=null | prev=null | prev=null | firstOut=g5.out[1] | | | | 132 // | | | | | | | | 133 // +----------------+----------------+----------------+--------------------+-----------+-----------+-----------+ 134 // ``` 135 136 class Gate { 137 public: 138 // NOLINTNEXTLINE(modernize-avoid-c-arrays) 139 Gate(const GateMetaData* meta, GateId id, Gate *inList[], MachineType machineType, GateType type); GetGateSize(size_t numIns)140 static size_t GetGateSize(size_t numIns) 141 { 142 numIns = (numIns == 0) ? 1 : numIns; 143 return numIns * (sizeof(In) + sizeof(Out)) + sizeof(Gate); 144 } GetOutListSize(size_t numIns)145 static size_t GetOutListSize(size_t numIns) 146 { 147 numIns = (numIns == 0) ? 1 : numIns; 148 return numIns * sizeof(Out); 149 } 150 void NewIn(size_t idx, Gate *in); 151 void ModifyIn(size_t idx, Gate *in); 152 void DeleteIn(size_t idx); 153 void DeleteGate(); 154 static constexpr GateRef InvalidGateRef = -1; 155 [[nodiscard]] Out *GetOut(size_t idx); 156 [[nodiscard]] Out *GetFirstOut(); 157 [[nodiscard]] const Out *GetOutConst(size_t idx) const; 158 [[nodiscard]] const Out *GetFirstOutConst() const; 159 // note: GetFirstOut() is not equal to GetOut(0) 160 // note: behavior of GetFirstOut() is undefined when there are no Outs 161 // note: use IsFirstOutNull() to check first if there may be no Outs 162 void SetFirstOut(const Out *firstOut); 163 void SetFirstOutNull(); 164 [[nodiscard]] bool IsFirstOutNull() const; 165 [[nodiscard]] In *GetIn(size_t idx); 166 [[nodiscard]] const In *GetInConst(size_t idx) const; 167 [[nodiscard]] Gate *GetInGate(size_t idx); 168 [[nodiscard]] const Gate *GetInGateConst(size_t idx) const; 169 // note: behavior of GetInGate(idx) is undefined when Ins[idx] is deleted or not assigned 170 // note: use IsInGateNull(idx) to check first if Ins[idx] may be deleted or not assigned 171 [[nodiscard]] bool IsInGateNull(size_t idx) const; 172 [[nodiscard]] OpCode GetOpCode() const; 173 [[nodiscard]] GateId GetId() const; 174 [[nodiscard]] size_t GetNumIns() const; 175 [[nodiscard]] size_t GetStateCount() const; 176 [[nodiscard]] size_t GetDependCount() const; 177 [[nodiscard]] size_t GetInValueCount() const; 178 [[nodiscard]] size_t GetInFrameStateCount() const; 179 [[nodiscard]] size_t GetInValueStarts() const; 180 [[nodiscard]] size_t GetRootCount() const; 181 [[nodiscard]] size_t GetInFrameStateStarts() const; 182 void AppendIn(const Gate *in); // considered very slow 183 void Print(std::string bytecode = "", bool inListPreview = false, size_t highlightIdx = -1) const; 184 void ShortPrint(std::string bytecode = "", bool inListPreview = false, size_t highlightIdx = -1) const; 185 size_t PrintInGate(size_t numIns, size_t idx, size_t size, bool inListPreview, size_t highlightIdx, 186 std::string &log, bool isEnd = false) const; 187 void PrintGateWithAdditionOp(std::string additionOp) const; 188 void PrintWithBytecode() const; 189 void CheckNullInput() const; 190 void CheckStateInput() const; 191 void CheckValueInput(bool isArch64) const; 192 void CheckDependInput() const; 193 void CheckRootInput() const; 194 void CheckFrameStateInput() const; 195 void CheckStateOutput() const; 196 void CheckBranchOutput() const; 197 void CheckNOP() const; 198 void CheckSelector() const; 199 void CheckRelay() const; 200 void Verify(bool isArch64) const; 201 [[nodiscard]] MarkCode GetMark(TimeStamp stamp) const; 202 void SetMark(MarkCode mark, TimeStamp stamp); GetMachineType()203 MachineType GetMachineType() const 204 { 205 return machineType_; 206 } SetMachineType(MachineType machineType)207 void SetMachineType(MachineType machineType) 208 { 209 machineType_ = machineType; 210 } GetGateType()211 GateType GetGateType() const 212 { 213 return type_; 214 } SetGateType(GateType type)215 void SetGateType(GateType type) 216 { 217 type_ = type; 218 } GetMetaData()219 const GateMetaData* GetMetaData() const 220 { 221 return meta_; 222 } 223 GetOneParameterMetaData()224 const OneParameterMetaData* GetOneParameterMetaData() const 225 { 226 return OneParameterMetaData::Cast(meta_); 227 } 228 GetTypedBinaryMetaData()229 const TypedBinaryMetaData* GetTypedBinaryMetaData() const 230 { 231 return TypedBinaryMetaData::Cast(meta_); 232 } 233 GetTypedCallTargetCheckMetaData()234 const TypedCallTargetCheckMetaData* GetTypedCallTargetCheckMetaData() const 235 { 236 return TypedCallTargetCheckMetaData::Cast(meta_); 237 } 238 GetStringMetaData()239 const StringMetaData* GetStringMetaData() const 240 { 241 ASSERT(meta_->IsStringType()); 242 return static_cast<const StringMetaData*>(meta_); 243 } 244 GetJSBytecodeMetaData()245 const JSBytecodeMetaData* GetJSBytecodeMetaData() const 246 { 247 return JSBytecodeMetaData::Cast(meta_); 248 } 249 GetBoolMetaData()250 const BoolMetaData* GetBoolMetaData() const 251 { 252 return BoolMetaData::Cast(meta_); 253 } 254 GetTypedCallMetaData()255 const TypedCallMetaData* GetTypedCallMetaData() const 256 { 257 return TypedCallMetaData::Cast(meta_); 258 } 259 260 std::string MachineTypeStr(MachineType machineType) const; 261 std::string GateTypeStr(GateType gateType) const; 262 ~Gate() = default; 263 264 private: 265 friend class Circuit; 266 friend class GateAccessor; 267 void CheckInputOpcode(size_t idx, OpCode expected) const; 268 void CheckInputMachineType(size_t idx, MachineType expected, bool isArch64) const; 269 void CheckNotInputMachineType(size_t idx, MachineType notExpected) const; 270 void CheckState(size_t idx) const; 271 void CheckGeneralState(size_t idx) const; 272 void CheckFailed(std::string errorString, size_t highlightIdx) const; SetMetaData(const GateMetaData * meta)273 void SetMetaData(const GateMetaData* meta) 274 { 275 meta_ = meta; 276 } TryGetValue()277 uint64_t TryGetValue() const 278 { 279 if (meta_->IsOneParameterKind()) { 280 return GetOneParameterMetaData()->GetValue(); 281 } 282 return 0; 283 } 284 // ... 285 // out(2) 286 // out(1) 287 // out(0) 288 const GateMetaData *meta_ { nullptr }; // uintptr_t 289 GateId id_ { 0 }; // uint32_t 290 GateType type_ { GateType::Empty() }; // uint32_t 291 MachineType machineType_ { MachineType::NOVALUE }; // uint8_t 292 TimeStamp stamp_ { 0 }; // uint8_t 293 MarkCode mark_ { MarkCode::NO_MARK }; // uint8_t 294 uint8_t bitField_ { 0 }; 295 GateRef firstOut_ { 0 }; // int32_t 296 // in(0) 297 // in(1) 298 // in(2) 299 // ... 300 }; 301 } // namespace panda::ecmascript::kungfu 302 303 #endif // ECMASCRIPT_COMPILER_GATE_H 304