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