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_ACCESSOR_H
17#define ECMASCRIPT_COMPILER_GATE_ACCESSOR_H
18
19#include "ecmascript/compiler/circuit.h"
20#include "ecmascript/compiler/mcr_gate_meta_data.h"
21#include "ecmascript/elements.h"
22#include "ecmascript/pgo_profiler/types/pgo_profiler_type.h"
23
24namespace panda::ecmascript::kungfu {
25
26class StateDepend {
27public:
28    StateDepend()
29        : state_(Circuit::NullGate()), depend_(Circuit::NullGate()) {}
30
31    explicit StateDepend(GateRef state, GateRef depend)
32        : state_(state), depend_(depend) {}
33
34    GateRef State() const
35    {
36        return state_;
37    }
38
39    GateRef Depend() const
40    {
41        return depend_;
42    }
43
44    void SetState(GateRef state)
45    {
46        state_ = state;
47    }
48
49    void SetDepend(GateRef depend)
50    {
51        depend_ = depend;
52    }
53
54    void Reset()
55    {
56        state_ = Circuit::NullGate();
57        depend_ = Circuit::NullGate();
58    }
59
60private:
61    GateRef state_;
62    GateRef depend_;
63};
64
65class Edge {
66public:
67    explicit Edge(GateRef gate, size_t index) : gate_(gate), index_(static_cast<uint32_t>(index)) {}
68
69    GateRef GetGate() const
70    {
71        return gate_;
72    }
73
74    size_t GetIndex() const
75    {
76        return static_cast<size_t>(index_);
77    }
78
79    void SetIndex(size_t index)
80    {
81        index_ = static_cast<uint32_t>(index);
82    }
83
84private:
85    GateRef gate_;
86    uint32_t index_;
87};
88
89class GateAccessor {
90public:
91    constexpr static uint32_t INVALID_BC_INDEX = 0;
92
93    // do not create new gate or modify self during iteration
94    struct ConstUseIterator {
95        ConstUseIterator(const Circuit* circuit, const Out* out) : circuit_(circuit), out_(out)
96        {
97        }
98
99        GateRef operator*() const
100        {
101            if (out_ != nullptr) {
102                return circuit_->GetGateRef(out_->GetGateConst());
103            }
104            return 0;
105        }
106
107        const ConstUseIterator operator++()
108        {
109            ASSERT(out_ != nullptr);
110            if (!out_->IsNextOutNull()) {
111                out_ = out_->GetNextOutConst();
112                return *this;
113            }
114            out_ = nullptr;
115            return *this;
116        }
117        const ConstUseIterator operator++(int)
118        {
119            ConstUseIterator tmp = *this;
120            ++(*this);
121            return tmp;
122        }
123
124        size_t GetIndex() const
125        {
126            ASSERT(out_ != nullptr);
127            return out_->GetIndex();
128        }
129
130        OpCode GetOpCode() const
131        {
132            ASSERT(out_ != nullptr);
133            return out_->GetGateConst()->GetOpCode();
134        }
135
136        friend bool operator == (const ConstUseIterator& a, const ConstUseIterator& b)
137        {
138            return a.out_ == b.out_;
139        };
140        friend bool operator != (const ConstUseIterator& a, const ConstUseIterator& b)
141        {
142            return a.out_ != b.out_;
143        };
144
145    private:
146        const Circuit* circuit_;
147        const Out* out_;
148    };
149
150    // do not create new gate or modify self during iteration
151    struct UseIterator {
152        UseIterator(Circuit* circuit, Out* out) : circuit_(circuit), out_(out)
153        {
154        }
155
156        GateRef operator*() const
157        {
158            if (out_ != nullptr) {
159                return circuit_->GetGateRef(out_->GetGate());
160            }
161            return 0;
162        }
163
164        const UseIterator& operator++()
165        {
166            ASSERT(out_ != nullptr);
167            out_ = out_->IsNextOutNull() ? nullptr
168                                         : out_->GetNextOut();
169            return *this;
170        }
171
172        UseIterator operator++(int)
173        {
174            UseIterator tmp = *this;
175            ++(*this);
176            return tmp;
177        }
178
179        size_t GetIndex() const
180        {
181            ASSERT(out_ != nullptr);
182            return out_->GetIndex();
183        }
184
185        Edge GetEdge()
186        {
187            ASSERT(out_ != nullptr);
188            UseIterator it = *this;
189            return Edge(*it, GetIndex());
190        }
191
192        OpCode GetOpCode() const
193        {
194            ASSERT(out_ != nullptr);
195            return out_->GetGateConst()->GetOpCode();
196        }
197
198        friend bool operator == (const UseIterator& a, const UseIterator& b)
199        {
200            return a.out_ == b.out_;
201        };
202        friend bool operator != (const UseIterator& a, const UseIterator& b)
203        {
204            return a.out_ != b.out_;
205        };
206
207    private:
208        Circuit* circuit_;
209        Out* out_;
210    };
211
212    struct ConstInsIterator {
213        ConstInsIterator(const Circuit* circuit, const In* in) : circuit_(circuit), in_(in)
214        {
215        }
216
217        GateRef operator*() const
218        {
219            return circuit_->GetGateRef(in_->GetGateConst());
220        }
221
222        const ConstInsIterator& operator++()
223        {
224            in_++;
225            return *this;
226        }
227        ConstInsIterator operator++(int)
228        {
229            ConstInsIterator tmp = *this;
230            ++(*this);
231            return tmp;
232        }
233
234        OpCode GetOpCode() const
235        {
236            ASSERT(in_ != nullptr);
237            return in_->GetGateConst()->GetOpCode();
238        }
239
240        friend bool operator== (const ConstInsIterator& a, const ConstInsIterator& b)
241        {
242            return a.in_ == b.in_;
243        };
244        friend bool operator!= (const ConstInsIterator& a, const ConstInsIterator& b)
245        {
246            return a.in_ != b.in_;
247        };
248
249    private:
250        const Circuit* circuit_;
251        const In* in_;
252    };
253
254    struct InsIterator {
255        InsIterator(const Circuit* circuit, In* in) : circuit_(circuit), in_(in)
256        {
257        }
258
259        GateRef operator*()
260        {
261            return circuit_->GetGateRef(in_->GetGate());
262        }
263
264        const InsIterator& operator++()
265        {
266            in_++;
267            return *this;
268        }
269        InsIterator operator++(int)
270        {
271            InsIterator tmp = *this;
272            ++(*this);
273            return tmp;
274        }
275
276        OpCode GetOpCode() const
277        {
278            ASSERT(in_ != nullptr);
279            return in_->GetGateConst()->GetOpCode();
280        }
281
282        friend bool operator== (const InsIterator& a, const InsIterator& b)
283        {
284            return a.in_ == b.in_;
285        };
286        friend bool operator!= (const InsIterator& a, const InsIterator& b)
287        {
288            return a.in_ != b.in_;
289        };
290
291    private:
292        const Circuit* circuit_;
293        In* in_;
294    };
295
296    struct ConstUseWrapper {
297        Circuit* circuit;
298        GateRef gate;
299        auto begin()
300        {
301            return GateAccessor(circuit).ConstUseBegin(gate);
302        }
303        auto end()
304        {
305            return GateAccessor(circuit).ConstUseEnd();
306        }
307    };
308
309    struct UseWrapper {
310        Circuit* circuit;
311        GateRef gate;
312        auto begin()
313        {
314            return GateAccessor(circuit).UseBegin(gate);
315        }
316        auto end()
317        {
318            return GateAccessor(circuit).UseEnd();
319        }
320    };
321
322    struct ConstInWrapper {
323        Circuit* circuit;
324        const GateRef gate;
325        auto begin()
326        {
327            return GateAccessor(circuit).ConstInBegin(gate);
328        }
329        auto end()
330        {
331            return GateAccessor(circuit).ConstInEnd(gate);
332        }
333    };
334
335    struct InWrapper {
336        Circuit* circuit;
337        GateRef gate;
338        auto begin()
339        {
340            return GateAccessor(circuit).InBegin(gate);
341        }
342        auto end()
343        {
344            return GateAccessor(circuit).InEnd(gate);
345        }
346    };
347
348    ConstInWrapper ConstIns(GateRef gate) const
349    {
350        return { circuit_, gate };
351    }
352
353    InWrapper Ins(GateRef gate) const
354    {
355        return { circuit_, gate };
356    }
357
358    ConstUseWrapper ConstUses(GateRef gate) const
359    {
360        return { circuit_, gate };
361    }
362
363    UseWrapper Uses(GateRef gate)
364    {
365        return { circuit_, gate };
366    }
367
368    explicit GateAccessor(Circuit *circuit) : circuit_(circuit)
369    {
370    }
371
372    Circuit *GetCircuit() const
373    {
374        return circuit_;
375    }
376
377    ~GateAccessor() = default;
378    void GetAllGates(std::vector<GateRef>& gates) const;
379    size_t GetNumIns(GateRef gate) const;
380    OpCode GetOpCode(GateRef gate) const;
381    bool IsGCRelated(GateRef gate) const;
382    uint64_t TryGetValue(GateRef gate) const;
383    ICmpCondition GetICmpCondition(GateRef gate) const;
384    FCmpCondition GetFCmpCondition(GateRef gate) const;
385    size_t GetOffset(GateRef gate) const;
386    size_t GetInitOffset(GateRef gate) const;
387    uint32_t GetTrueWeight(GateRef gate) const;
388    uint32_t GetFalseWeight(GateRef gate) const;
389    bool HasBranchWeight(GateRef gate) const;
390    MemoryAttribute GetMemoryAttribute(GateRef gate) const;
391    size_t GetIndex(GateRef gate) const;
392    size_t GetJSType(GateRef gate) const;
393    uint32_t GetArraySize(GateRef gate) const;
394    void SetArraySize(GateRef gate, uint32_t size);
395    uint32_t GetStringStatus(GateRef gate) const;
396    void SetStringStatus(GateRef gate, uint32_t type);
397    ElementsKind GetElementsKind(GateRef gate) const;
398    void SetElementsKind(GateRef gate, ElementsKind kind);
399    RegionSpaceFlag GetRegionSpaceFlag(GateRef gate) const;
400    size_t GetVirtualRegisterIndex(GateRef gate) const;
401    bool TypedOpIsTypedArray(GateRef gate, TypedOpKind kind) const;
402    TypedLoadOp GetTypedLoadOp(GateRef gate) const;
403    TypedStoreOp GetTypedStoreOp(GateRef gate) const;
404    MemoryType GetMemoryType(GateRef gate) const;
405    uint32_t GetHClassIndex(GateRef gate) const;
406    TypedBinOp GetTypedBinaryOp(GateRef gate) const;
407    TypedCallTargetCheckOp GetTypedCallTargetCheckOp(GateRef gate) const;
408    bool HasNumberType(GateRef gate) const;
409    bool HasStringType(GateRef gate) const;
410    GlobalTSTypeRef GetFuncGT(GateRef gate) const;
411    GateType GetParamGateType(GateRef gate) const;
412    ParamType GetParamType(GateRef gate) const;
413    TypedUnaryAccessor GetTypedUnAccessor(GateRef gate) const;
414    TypedBinaryAccessor GetTypedBinaryAccessor(GateRef gate) const;
415    TypedJumpAccessor GetTypedJumpAccessor(GateRef gate) const;
416    ArrayMetaDataAccessor GetArrayMetaDataAccessor(GateRef gate) const;
417    CreateArgumentsAccessor GetCreateArgumentsAccessor(GateRef gate) const;
418    ObjectTypeAccessor GetObjectTypeAccessor(GateRef gate) const;
419    BuiltinPrototypeHClassAccessor GetBuiltinHClassAccessor(GateRef gate) const;
420    TypedArrayMetaDataAccessor GetTypedArrayMetaDataAccessor(GateRef gate) const;
421    LoadElementAccessor GetLoadElementAccessor(GateRef gate) const;
422    StoreElementAccessor GetStoreElementAccessor(GateRef gate) const;
423    bool NeedPushArgv(GateRef gate) const;
424    uint64_t GetConstantValue(GateRef gate) const;
425    const ChunkVector<char>& GetConstantString(GateRef gate) const;
426    bool IsVtable(GateRef gate) const;
427    bool GetNoGCFlag(GateRef gate) const;
428    bool TypedCallIsNoGC(GateRef gate) const;
429    bool IsNoGC(GateRef gate) const;
430    uint32_t TryGetPcOffset(GateRef gate) const;
431    uint32_t TryGetBcIndex(GateRef gate) const;
432    uint32_t TryGetMethodOffset(GateRef gate) const;
433    GateRef GetFrameArgs(GateRef gate) const;
434    void UpdateMethodOffset(GateRef gate, uint32_t methodOffset);
435    PGOTypeRef TryGetPGOType(GateRef gate) const;
436    void TrySetPGOType(GateRef gate, PGOTypeRef type);
437    uint32_t TryGetArrayElementsLength(GateRef gate) const;
438    void TrySetArrayElementsLength(GateRef gate, uint32_t length);
439    RegionSpaceFlag TryGetRegionSpaceFlag(GateRef gate) const;
440    void TrySetRegionSpaceFlag(GateRef gate, RegionSpaceFlag length);
441    ElementsKind TryGetElementsKind(GateRef gate) const;
442    ElementsKind TryGetArrayElementsKind(GateRef gate) const;
443    ElementsKind TryGetArrayElementsKindAfterTransition(GateRef gate) const;
444    void TrySetElementsKind(GateRef gate, ElementsKind kind);
445    void TrySetTransitionElementsKind(GateRef gate, ElementsKind kind);
446    void TrySetOnHeapMode(GateRef gate, OnHeapMode onHeapMode) const;
447    OnHeapMode TryGetOnHeapMode(GateRef gate) const;
448    EcmaOpcode GetByteCodeOpcode(GateRef gate) const;
449    void Print(GateRef gate) const DUMP_API_ATTR;
450    std::string ToString(GateRef gate) const DUMP_API_ATTR;
451#ifndef NDEBUG
452    void PrintById(size_t id) const DUMP_API_ATTR ;
453#endif
454    void PrintWithBytecode(GateRef gate) const DUMP_API_ATTR;
455    void ShortPrint(GateRef gate) const;
456    GateId GetId(GateRef gate) const;
457    GateRef GetValueIn(GateRef gate, size_t idx = 0) const;
458    size_t GetNumValueIn(GateRef gate) const;
459    std::vector<GateRef> GetValueIns(GateRef gate) const;
460    GateRef GetIn(GateRef gate, size_t idx) const;
461    GateRef GetState(GateRef gate, size_t idx = 0) const;
462    GateRef GetDep(GateRef gate, size_t idx = 0) const;
463    size_t GetImmediateId(GateRef gate) const;
464    void SetDep(GateRef gate, GateRef depGate, size_t idx = 0);
465    UseIterator ReplaceIn(const UseIterator &useIt, GateRef replaceGate);
466    // Add for lowering
467    GateType GetGateType(GateRef gate) const;
468    bool IsConvertSupport(GateRef gate) const;
469    ValueType GetSrcType(GateRef gate) const;
470    ValueType GetDstType(GateRef gate) const;
471    void SetGateType(GateRef gate, GateType gt);
472    void DeleteIn(GateRef gate, size_t idx);
473    UseIterator DeleteGate(const UseIterator &useIt);
474    void DecreaseIn(const UseIterator &useIt);
475    void DecreaseIn(GateRef gate, size_t index);
476    void NewIn(GateRef gate, size_t idx, GateRef in);
477    size_t GetStateCount(GateRef gate) const;
478    size_t GetDependCount(GateRef gate) const;
479    size_t GetInValueCount(GateRef gate) const;
480    size_t GetInValueStarts(GateRef gate) const;
481    void UpdateAllUses(GateRef gate, GateRef replaceValueIn);
482    void ReplaceControlGate(GateRef gate, GateRef newState);
483    void ReplaceInAfterInsert(GateRef state, GateRef depend, GateRef newGate);
484    void GetFrameStateDependIn(GateRef gate, GateRef &dependIn);
485    void GetStateInAndDependIn(GateRef insertAfter, GateRef &stateIn, GateRef &dependIn);
486    void ReplaceIn(GateRef gate, size_t index, GateRef in);
487    void ReplaceStateIn(GateRef gate, GateRef in, size_t index = 0);
488    void ReplaceDependIn(GateRef gate, GateRef in, size_t index = 0);
489    void ReplaceOrNewDependIn(GateRef gate, GateRef in, size_t index = 0);
490    void ReplaceValueIn(GateRef gate, GateRef in, size_t index = 0);
491    void DeleteGate(GateRef gate);
492    MachineType GetMachineType(GateRef gate) const;
493    void SetMachineType(GateRef gate, MachineType type);
494    GateRef GetConstantGate(MachineType bitValue, BitField bitfield, GateType type) const;
495    GateRef GetInitialEnvGate(GateRef depend, GateRef jsFunc) const;
496    double GetFloat64FromConstant(GateRef gate) const;
497    int GetInt32FromConstant(GateRef gate) const;
498    bool IsInGateNull(GateRef gate, size_t idx) const;
499    bool IsSelector(GateRef g) const;
500    bool IsSimpleState(GateRef g) const;
501    bool IsValueSelector(GateRef g) const;
502    bool IsFrameValues(GateRef g) const;
503    bool IsControlCase(GateRef gate) const;
504    bool IsLoopExit(GateRef gate) const;
505    bool IsLoopExitRelated(GateRef gate) const;
506    bool IsLoopHead(GateRef gate) const;
507    bool IsLoopBack(GateRef gate) const;
508    bool IsState(GateRef gate) const;
509    bool IsConstant(GateRef gate) const;
510    bool IsDependSelector(GateRef gate) const;
511    bool IsConstantValue(GateRef gate, uint64_t value) const;
512    bool IsConstantTaggedValue(GateRef gate, uint64_t value) const;
513    bool IsConstantUndefined(GateRef gate) const;
514    bool IsUndefinedOrNullOrHole(GateRef gate) const;
515    bool IsConstantNumber(GateRef gate) const;
516    bool IsTypedOperator(GateRef gate) const;
517    bool IsNotWrite(GateRef gate) const;
518    bool IsDead(GateRef gate) const;
519    bool IsCheckWithOneIn(GateRef gate) const;
520    bool IsCheckWithTwoIns(GateRef gate) const;
521    bool IsSchedulable(GateRef gate) const;
522    bool IsVirtualState(GateRef gate) const;
523    bool IsGeneralState(GateRef gate) const;
524    MarkCode GetMark(GateRef gate) const;
525    void SetMark(GateRef gate, MarkCode mark);
526    bool IsFinished(GateRef gate) const;
527    bool IsVisited(GateRef gate) const;
528    bool IsPrevisit(GateRef gate) const;
529    bool IsNotMarked(GateRef gate) const;
530    void SetFinished(GateRef gate);
531    void SetPrevisit(GateRef gate);
532    void SetVisited(GateRef gate);
533    bool IsStateIn(const UseIterator &useIt) const;
534    bool IsDependIn(const UseIterator &useIt) const;
535    bool IsValueIn(const UseIterator &useIt) const;
536    bool IsFrameStateIn(const UseIterator &useIt) const;
537    bool IsStateIn(GateRef gate, size_t index) const;
538    bool IsDependIn(GateRef gate, size_t index) const;
539    bool IsValueIn(GateRef gate, size_t index) const;
540    void GetStateUses(GateRef gate, std::vector<GateRef> &stateUses);
541    void GetDependUses(GateRef gate, std::vector<GateRef> &dependUses);
542    void GetValueUses(GateRef gate, std::vector<GateRef> &valueUses);
543    size_t GetValueUsesCount(GateRef gate);
544    bool IsFrameStateIn(GateRef gate, size_t index) const;
545    void EliminateRedundantPhi();
546    void ReplaceGate(GateRef gate, GateRef state, GateRef depend, GateRef value);
547    void ReplaceGate(GateRef gate, StateDepend stateDepend, GateRef replacement);
548    void ReplaceGate(GateRef gate, GateRef replacement);
549    uint32_t GetFirstValue(GateRef gate) const;
550    uint32_t GetSecondValue(GateRef gate) const;
551    GateRef GetGlueFromArgList() const;
552    void GetArgsOuts(std::vector<GateRef>& outs) const;
553    void GetReturnOuts(std::vector<GateRef>& outs) const;
554    bool IsFixed(GateRef g) const;
555    bool IsProlog(GateRef g) const;
556    bool IsCFGMerge(GateRef g) const;
557    bool MetaDataEqu(GateRef g1, GateRef g2) const;
558    bool MetaDataValueEqu(GateRef g1, GateRef g2) const;
559    bool IsNop(GateRef g) const;
560    bool IsRoot(GateRef g) const;
561    bool HasOuts(GateRef gate) const;
562    void DeleteGateIfNoUse(GateRef gate);
563    GateRef GetDependSelectorFromMerge(GateRef gate);
564    bool HasIfExceptionUse(GateRef gate) const;
565    bool IsIn(GateRef g, GateRef in) const;
566    bool IsHeapObjectFromElementsKind(GateRef gate);
567    bool IsConstString(GateRef gate);
568    bool IsSingleCharGate(GateRef gate);
569    bool UseForTypeOpProfilerGate(GateRef gate) const;
570    uint32_t GetStringIdFromLdaStrGate(GateRef gate);
571    bool IsIfOrSwitchRelated(GateRef gate) const;
572    uint32_t GetConstpoolId(GateRef gate) const;
573    GateRef GetFrameValue(GateRef gate);
574
575    GateRef GetCircuitRoot() const
576    {
577        return GetRoot(OpCode::CIRCUIT_ROOT);
578    }
579
580    GateRef GetStateRoot() const
581    {
582        return GetRoot(OpCode::STATE_ENTRY);
583    }
584
585    GateRef GetDependRoot() const
586    {
587        return GetRoot(OpCode::DEPEND_ENTRY);
588    }
589
590    GateRef GetArgRoot() const
591    {
592        return GetRoot(OpCode::ARG_LIST);
593    }
594
595    GateRef GetReturnRoot() const
596    {
597        return GetRoot(OpCode::RETURN_LIST);
598    }
599
600    inline bool IsStateRoot(GateRef gate) const
601    {
602        return gate == GetStateRoot();
603    }
604
605    size_t GetFrameDepth(GateRef gate, OpCode op);
606    GateRef GetFrameState(GateRef gate) const;
607    void ReplaceFrameStateIn(GateRef gate, GateRef in);
608    bool HasFrameState(GateRef gate) const;
609    GateRef FindNearestFrameState(GateRef gate) const;
610    GateRef FindNearestStateSplit(GateRef gate) const;
611    void SetMetaData(GateRef gate, const GateMetaData* meta);
612
613    void ReplaceHirWithIfBranch(GateRef hirGate, StateDepend success, StateDepend exception, GateRef value);
614    void ReplaceHirDirectly(GateRef hirGate, StateDepend replacement, GateRef value);
615    void ReplaceHirAndDeleteIfException(GateRef hirGate, StateDepend replacement, GateRef value);
616
617    bool IsLoopBackUse(GateRef gate, const UseIterator &useIt) const;
618    void GetOutStates(GateRef gate, std::vector<GateRef>& outStates) const;
619    bool IsCreateArray(GateRef gate) const;
620    void SetStoreNoBarrier(GateRef gate, bool isNoBarrier);
621    bool IsNoBarrier(GateRef gate) const;
622    void GetIns(GateRef gate, std::vector<GateRef>& ins) const;
623
624    TypedBinOp GetRevCompareOpForTypedBinOp(TypedBinOp op);
625    TypedBinOp GetSwapCompareOpForTypedBinOp(TypedBinOp op);
626
627private:
628    const GateMetaData *GetMetaData(GateRef gate) const;
629    UseIterator ReplaceHirIfSuccess(const UseIterator &useIt, GateRef state);
630    UseIterator ReplaceHirIfException(const UseIterator &useIt, StateDepend replacement);
631    void ExceptionReturn(GateRef state, GateRef depend);
632
633    GateRef GetRoot(OpCode opcode) const;
634    ConstUseIterator ConstUseBegin(GateRef gate) const
635    {
636        if (circuit_->LoadGatePtrConst(gate)->IsFirstOutNull()) {
637            return ConstUseIterator(circuit_, nullptr);
638        }
639        auto use = circuit_->LoadGatePtrConst(gate)->GetFirstOutConst();
640        return ConstUseIterator(circuit_, use);
641    }
642
643    ConstUseIterator ConstUseEnd() const
644    {
645        return ConstUseIterator(circuit_, nullptr);
646    }
647
648    UseIterator UseBegin(GateRef gate) const
649    {
650        if (circuit_->LoadGatePtrConst(gate)->IsFirstOutNull()) {
651            return UseIterator(circuit_, nullptr);
652        }
653        auto use = circuit_->LoadGatePtr(gate)->GetFirstOut();
654        return UseIterator(circuit_, use);
655    }
656
657    UseIterator UseEnd() const
658    {
659        return UseIterator(circuit_, nullptr);
660    }
661
662    ConstInsIterator ConstInBegin(GateRef gate) const
663    {
664        return ConstInsIterator(circuit_, &reinterpret_cast<const In *>(circuit_->LoadGatePtrConst(gate) + 1)[0]);
665    }
666
667    ConstInsIterator ConstInEnd(GateRef gate) const
668    {
669        auto endIndex = circuit_->LoadGatePtrConst(gate)->GetNumIns();
670        return ConstInsIterator(circuit_,
671                                &reinterpret_cast<const In *>(circuit_->LoadGatePtrConst(gate) + 1)[endIndex]);
672    }
673
674    InsIterator InBegin(GateRef gate)
675    {
676        return InsIterator(circuit_, &reinterpret_cast<In *>(circuit_->LoadGatePtr(gate) + 1)[0]);
677    }
678
679    InsIterator InEnd(GateRef gate)
680    {
681        auto endIndex = circuit_->LoadGatePtrConst(gate)->GetNumIns();
682        return InsIterator(circuit_, &reinterpret_cast<In *>(circuit_->LoadGatePtr(gate) + 1)[endIndex]);
683    }
684
685    void GetOuts(GateRef gate, std::vector<GateRef>& outs) const;
686
687    void GetInStates(GateRef gate, std::vector<GateRef>& ins) const;
688
689    Circuit *circuit_;
690
691    friend class Circuit;
692    friend class CircuitBuilder;
693    friend class LLVMIRBuilder;
694    friend class LiteCGIRBuilder;
695    friend class Scheduler;
696    friend class LoopPeeling;
697};
698
699class ConstGateAccessor {
700public:
701    struct ConstInsIterator {
702        ConstInsIterator(const Circuit* circuit, const In* in) : circuit_(circuit), in_(in)
703        {
704        }
705
706        GateRef operator*() const
707        {
708            return circuit_->GetGateRef(in_->GetGateConst());
709        }
710
711        const ConstInsIterator& operator++()
712        {
713            in_++;
714            return *this;
715        }
716        ConstInsIterator operator++(int)
717        {
718            ConstInsIterator tmp = *this;
719            ++(*this);
720            return tmp;
721        }
722
723        OpCode GetOpCode() const
724        {
725            ASSERT(in_ != nullptr);
726            return in_->GetGateConst()->GetOpCode();
727        }
728
729        friend bool operator== (const ConstInsIterator& a, const ConstInsIterator& b)
730        {
731            return a.in_ == b.in_;
732        };
733        friend bool operator!= (const ConstInsIterator& a, const ConstInsIterator& b)
734        {
735            return a.in_ != b.in_;
736        };
737
738    private:
739        const Circuit* circuit_;
740        const In* in_;
741    };
742
743    struct ConstInWrapper {
744        const Circuit* circuit;
745        const GateRef gate;
746        auto begin()
747        {
748            return ConstGateAccessor(circuit).ConstInBegin(gate);
749        }
750        auto end()
751        {
752            return ConstGateAccessor(circuit).ConstInEnd(gate);
753        }
754    };
755
756    ConstInWrapper Ins(GateRef gate) const
757    {
758        return { circuit_, gate };
759    }
760
761    explicit ConstGateAccessor(const Circuit *circuit) : circuit_(circuit)
762    {
763    }
764
765    ~ConstGateAccessor() = default;
766
767    bool IsFixed(GateRef g) const;
768    bool IsProlog(GateRef g) const;
769    bool IsSchedulable(GateRef g) const;
770
771private:
772    ConstInsIterator ConstInBegin(GateRef gate) const
773    {
774        return ConstInsIterator(circuit_, &reinterpret_cast<const In *>(circuit_->LoadGatePtrConst(gate) + 1)[0]);
775    }
776
777    ConstInsIterator ConstInEnd(GateRef gate) const
778    {
779        auto endIndex = circuit_->LoadGatePtrConst(gate)->GetNumIns();
780        return ConstInsIterator(circuit_,
781                                &reinterpret_cast<const In *>(circuit_->LoadGatePtrConst(gate) + 1)[endIndex]);
782    }
783    const GateMetaData *GetMetaData(GateRef g) const;
784
785    const Circuit *circuit_;
786    friend struct ConstInWrapper;
787};
788}
789#endif  // ECMASCRIPT_COMPILER_GATE_ACCESSOR_H
790