1/*
2 * Copyright (c) 2023 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_RANGE_GUARD_H
17#define ECMASCRIPT_COMPILER_RANGE_GUARD_H
18
19#include "ecmascript/compiler/circuit_builder.h"
20#include "ecmascript/compiler/gate_accessor.h"
21#include "ecmascript/compiler/pass_manager.h"
22#include "ecmascript/compiler/base/depend_chain_helper.h"
23#include "ecmascript/mem/chunk_containers.h"
24#include "ecmascript/compiler/number_gate_info.h"
25#include "ecmascript/compiler/combined_pass_visitor.h"
26
27namespace panda::ecmascript::kungfu {
28class RangeGuard : public PassVisitor {
29public:
30    RangeGuard(Circuit* circuit, RPOVisitor* visitor, Chunk* chunk)
31        : PassVisitor(circuit, chunk, visitor), circuit_(circuit),
32        builder_(circuit), acc_(circuit), dependChains_(chunk) {}
33
34    ~RangeGuard() = default;
35
36    void Initialize() override;
37    GateRef VisitGate(GateRef gate) override;
38    bool CheckInputSource(GateRef lhs, GateRef rhs);
39    uint32_t CheckIndexCheckLengthInput(GateRef lhs, GateRef rhs) const;
40    uint32_t CheckIndexCheckIndexInput(GateRef lhs, GateRef rhs) const;
41private:
42
43    DependChains* GetDependChain(GateRef dependIn)
44    {
45        size_t idx = acc_.GetId(dependIn);
46        ASSERT(idx <= circuit_->GetMaxGateId());
47        return dependChains_[idx];
48    }
49
50    uint32_t FoundIndexCheckedForLength(DependChains* dependChain, GateRef input) const
51    {
52        for (auto iter = dependChain->begin(); iter != dependChain->end(); ++iter) {
53            uint32_t length = CheckIndexCheckLengthInput(iter.GetCurrentGate(), input);
54            if (length > 0) { // found !!!
55                return length;
56            }
57        }
58
59        return 0;
60    }
61
62    uint32_t FoundIndexCheckedForIndex(DependChains* dependChain, GateRef input) const
63    {
64        for (auto iter = dependChain->begin(); iter != dependChain->end(); ++iter) {
65            uint32_t length = CheckIndexCheckIndexInput(iter.GetCurrentGate(), input);
66            if (length > 0) { // found !!!
67                return length;
68            }
69        }
70
71        return 0;
72    }
73
74    GateRef VisitDependEntry(GateRef gate);
75    GateRef UpdateDependChain(GateRef gate, DependChains* dependInfo);
76    GateRef TryApplyRangeGuardForLength(DependChains* dependInfo, GateRef gate, GateRef input);
77    GateRef TryApplyRangeGuardForIndex(DependChains* dependInfo, GateRef gate, GateRef input);
78    GateRef TryApplyRangeGuardGate(GateRef gate);
79    GateRef TraverseOthers(GateRef gate);
80    GateRef TraverseDependSelector(GateRef gate);
81
82    Circuit* circuit_;
83    CircuitBuilder builder_;
84    GateAccessor acc_;
85    ChunkVector<DependChains*> dependChains_;
86
87    friend class RangeInfo;
88};
89}  // panda::ecmascript::kungfu
90#endif  // ECMASCRIPT_COMPILER_RANGE_GUARD_H