• 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/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