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 37namespace panda::ecmascript::kungfu { 38using BitField = uint64_t; 39using GateRef = int32_t; // for external users 40using GateId = uint32_t; 41using GateOp = uint8_t; 42using GateMark = uint8_t; 43using TimeStamp = uint8_t; 44using SecondaryOp = uint8_t; 45using OutIdx = uint32_t; 46class Gate; 47class BytecodeCircuitBuilder; 48 49enum MarkCode : GateMark { 50 NO_MARK = 0, 51 PREVISIT, 52 VISITED, 53 FINISHED, 54}; 55 56class Out { 57public: 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 76private: 77 GateRef nextOut_; 78 GateRef prevOut_; 79 OutIdx idx_; 80}; 81 82class In { 83public: 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 92private: 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 136class Gate { 137public: 138 // NOLINTNEXTLINE(modernize-avoid-c-arrays) 139 Gate(const GateMetaData* meta, GateId id, Gate *inList[], MachineType machineType, GateType type); 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 } 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 Print(std::string bytecode = "", bool inListPreview = false, size_t highlightIdx = -1, 183 std::string_view comment = "") const; 184 std::string ToString(std::string bytecode = "", bool inListPreview = false, size_t highlightIdx = -1, 185 std::string_view comment = "") const; 186 void ShortPrint(std::string bytecode = "", bool inListPreview = false, size_t highlightIdx = -1) const; 187 size_t PrintInGate(size_t numIns, size_t idx, size_t size, bool inListPreview, size_t highlightIdx, 188 std::ostringstream &log, bool isEnd = false) const; 189 void PrintGateWithAdditionOp(std::string additionOp, std::string_view comment) const; 190 void PrintWithBytecode(std::string_view comment) const; 191 void CheckNullInput() const; 192 void CheckStateInput() const; 193 void CheckValueInput(bool isArch64) const; 194 void CheckDependInput() const; 195 void CheckRootInput() const; 196 void CheckFrameStateInput() const; 197 void CheckStateOutput(const std::string& methodName) const; 198 std::string GetValueInAndOut(bool inListPreview = false, size_t highlightIdx = -1) const; 199 void CheckBranchOutput() const; 200 void CheckNOP() const; 201 void CheckSelector() const; 202 void CheckRelay() const; 203 void Verify(bool isArch64, const std::string& methodName) const; 204 [[nodiscard]] MarkCode GetMark(TimeStamp stamp) const; 205 void SetMark(MarkCode mark, TimeStamp stamp); 206 MachineType GetMachineType() const 207 { 208 return machineType_; 209 } 210 void SetMachineType(MachineType machineType) 211 { 212 machineType_ = machineType; 213 } 214 GateType GetGateType() const 215 { 216 return type_; 217 } 218 void SetGateType(GateType type) 219 { 220 type_ = type; 221 } 222 const GateMetaData* GetMetaData() const 223 { 224 return meta_; 225 } 226 227 const OneParameterMetaData* GetOneParameterMetaData() const 228 { 229 return OneParameterMetaData::Cast(meta_); 230 } 231 232 const StringMetaData* GetStringMetaData() const 233 { 234 ASSERT(meta_->IsStringType()); 235 return static_cast<const StringMetaData*>(meta_); 236 } 237 238 const JSBytecodeMetaData* GetJSBytecodeMetaData() const 239 { 240 return JSBytecodeMetaData::Cast(meta_); 241 } 242 243 const BoolMetaData* GetBoolMetaData() const 244 { 245 return BoolMetaData::Cast(meta_); 246 } 247 248 const TypedCallMetaData* GetTypedCallMetaData() const 249 { 250 return TypedCallMetaData::Cast(meta_); 251 } 252 253 const NewConstructMetaData* GetNewConstructMetaData() const 254 { 255 return NewConstructMetaData::Cast(meta_); 256 } 257 258 std::string MachineTypeStr(MachineType machineType) const; 259 std::string GateTypeStr(GateType gateType) const; 260 ~Gate() = default; 261 262private: 263 friend class Circuit; 264 friend class GateAccessor; 265 void CheckInputOpcode(size_t idx, OpCode expected) const; 266 void CheckInputMachineType(size_t idx, MachineType expected, bool isArch64) const; 267 void CheckNotInputMachineType(size_t idx, MachineType notExpected) const; 268 void CheckState(size_t idx) const; 269 void CheckGeneralState(size_t idx) const; 270 void CheckFailed(std::string errorString, size_t highlightIdx) const; 271 void SetMetaData(const GateMetaData* meta) 272 { 273 meta_ = meta; 274 } 275 uint64_t TryGetValue() const 276 { 277 if (meta_->IsOneParameterKind()) { 278 return GetOneParameterMetaData()->GetValue(); 279 } 280 return 0; 281 } 282 void DumpHeader(std::ostringstream &oss, const std::string& additionOp) const; 283 284 void DumpInputs(std::ostringstream &oss, bool inListPreview, size_t highlightIdx) const; 285 286 void DumpOutputs(std::ostringstream &oss, bool inListPreview) const; 287 std::string GetBytecodeStr() const; 288 289 // ... 290 // out(2) 291 // out(1) 292 // out(0) 293 const GateMetaData *meta_ { nullptr }; // uintptr_t 294 GateId id_ { 0 }; // uint32_t 295 GateType type_ { GateType::Empty() }; // uint32_t 296 MachineType machineType_ { MachineType::NOVALUE }; // uint8_t 297 TimeStamp stamp_ { 0 }; // uint8_t 298 MarkCode mark_ { MarkCode::NO_MARK }; // uint8_t 299 uint8_t bitField_ { 0 }; 300 GateRef firstOut_ { 0 }; // int32_t 301 // in(0) 302 // in(1) 303 // in(2) 304 // ... 305}; 306} // namespace panda::ecmascript::kungfu 307 308#endif // ECMASCRIPT_COMPILER_GATE_H 309