• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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