14514f5e3Sopenharmony_ci/*
24514f5e3Sopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License.
54514f5e3Sopenharmony_ci * You may obtain a copy of the License at
64514f5e3Sopenharmony_ci *
74514f5e3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
84514f5e3Sopenharmony_ci *
94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and
134514f5e3Sopenharmony_ci * limitations under the License.
144514f5e3Sopenharmony_ci */
154514f5e3Sopenharmony_ci
164514f5e3Sopenharmony_ci#include "ecmascript/compiler/circuit_builder_helper.h"
174514f5e3Sopenharmony_ci#include "ecmascript/js_runtime_options.h"
184514f5e3Sopenharmony_ci
194514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu {
204514f5e3Sopenharmony_ci
214514f5e3Sopenharmony_ciCompilationConfig::CompilationConfig(const std::string &triple, const JSRuntimeOptions *options)
224514f5e3Sopenharmony_ci    : tripleStr_(triple), triple_(GetTripleFromString(triple))
234514f5e3Sopenharmony_ci{
244514f5e3Sopenharmony_ci    if (options != nullptr) {
254514f5e3Sopenharmony_ci        isTraceBc_ = options->IsTraceBC();
264514f5e3Sopenharmony_ci        profiling_ = options->GetOptCodeProfiler();
274514f5e3Sopenharmony_ci        stressDeopt_ = options->GetStressDeopt();
284514f5e3Sopenharmony_ci        verifyVTable_ = options->GetVerifyVTable();
294514f5e3Sopenharmony_ci        typedOpProfiling_ = options->GetTypedOpProfiler();
304514f5e3Sopenharmony_ci    }
314514f5e3Sopenharmony_ci}
324514f5e3Sopenharmony_ci
334514f5e3Sopenharmony_ciEnvironment::Environment(size_t arguments, CircuitBuilder *builder)
344514f5e3Sopenharmony_ci    : circuit_(builder->GetCircuit()), circuitBuilder_(builder), arguments_(arguments)
354514f5e3Sopenharmony_ci{
364514f5e3Sopenharmony_ci    circuitBuilder_->SetEnvironment(this);
374514f5e3Sopenharmony_ci    SetCompilationConfig(circuitBuilder_->GetCompilationConfig());
384514f5e3Sopenharmony_ci    for (size_t i = 0; i < arguments; i++) {
394514f5e3Sopenharmony_ci        arguments_[i] = circuitBuilder_->Arguments(i);
404514f5e3Sopenharmony_ci    }
414514f5e3Sopenharmony_ci    entry_ = Label(NewLabel(this, circuit_->GetStateRoot()));
424514f5e3Sopenharmony_ci    currentLabel_ = &entry_;
434514f5e3Sopenharmony_ci    currentLabel_->Seal();
444514f5e3Sopenharmony_ci    auto depend_entry = circuit_->GetDependRoot();
454514f5e3Sopenharmony_ci    currentLabel_->SetDepend(depend_entry);
464514f5e3Sopenharmony_ci}
474514f5e3Sopenharmony_ci
484514f5e3Sopenharmony_ciEnvironment::Environment(GateRef hir, Circuit *circuit, CircuitBuilder *builder)
494514f5e3Sopenharmony_ci    : circuit_(circuit), circuitBuilder_(builder)
504514f5e3Sopenharmony_ci{
514514f5e3Sopenharmony_ci    circuitBuilder_->SetEnvironment(this);
524514f5e3Sopenharmony_ci    SetCompilationConfig(circuitBuilder_->GetCompilationConfig());
534514f5e3Sopenharmony_ci    GateAccessor acc(circuit);
544514f5e3Sopenharmony_ci    entry_ = Label(NewLabel(this, acc.GetIn(hir, 0)));
554514f5e3Sopenharmony_ci    currentLabel_ = &entry_;
564514f5e3Sopenharmony_ci    currentLabel_->Seal();
574514f5e3Sopenharmony_ci    auto dependEntry = acc.GetDep(hir);
584514f5e3Sopenharmony_ci    currentLabel_->SetDepend(dependEntry);
594514f5e3Sopenharmony_ci    for (size_t i = 2; i < acc.GetNumIns(hir); i++) {
604514f5e3Sopenharmony_ci        inputList_.emplace_back(acc.GetIn(hir, i));
614514f5e3Sopenharmony_ci    }
624514f5e3Sopenharmony_ci}
634514f5e3Sopenharmony_ci
644514f5e3Sopenharmony_ciEnvironment::Environment(GateRef stateEntry, GateRef dependEntry,
654514f5e3Sopenharmony_ci    const std::initializer_list<GateRef>& args, Circuit *circuit, CircuitBuilder *builder)
664514f5e3Sopenharmony_ci    : circuit_(circuit), circuitBuilder_(builder)
674514f5e3Sopenharmony_ci{
684514f5e3Sopenharmony_ci    circuitBuilder_->SetEnvironment(this);
694514f5e3Sopenharmony_ci    SetCompilationConfig(circuitBuilder_->GetCompilationConfig());
704514f5e3Sopenharmony_ci    entry_ = Label(NewLabel(this, stateEntry));
714514f5e3Sopenharmony_ci    currentLabel_ = &entry_;
724514f5e3Sopenharmony_ci    currentLabel_->Seal();
734514f5e3Sopenharmony_ci    currentLabel_->SetDepend(dependEntry);
744514f5e3Sopenharmony_ci    for (auto in : args) {
754514f5e3Sopenharmony_ci        inputList_.emplace_back(in);
764514f5e3Sopenharmony_ci    }
774514f5e3Sopenharmony_ci}
784514f5e3Sopenharmony_ci
794514f5e3Sopenharmony_ciEnvironment::~Environment()
804514f5e3Sopenharmony_ci{
814514f5e3Sopenharmony_ci    circuitBuilder_->SetEnvironment(nullptr);
824514f5e3Sopenharmony_ci    for (auto label : rawLabels_) {
834514f5e3Sopenharmony_ci        delete label;
844514f5e3Sopenharmony_ci    }
854514f5e3Sopenharmony_ci}
864514f5e3Sopenharmony_ci
874514f5e3Sopenharmony_ciLabel::Label(Environment *env)
884514f5e3Sopenharmony_ci{
894514f5e3Sopenharmony_ci    ASSERT(env != nullptr);
904514f5e3Sopenharmony_ci    impl_ = env->NewLabel(env);
914514f5e3Sopenharmony_ci}
924514f5e3Sopenharmony_ci
934514f5e3Sopenharmony_ciLabel::Label(CircuitBuilder *cirBuilder)
944514f5e3Sopenharmony_ci{
954514f5e3Sopenharmony_ci    ASSERT(cirBuilder != nullptr);
964514f5e3Sopenharmony_ci    auto env = cirBuilder->GetCurrentEnvironment();
974514f5e3Sopenharmony_ci    ASSERT(env != nullptr);
984514f5e3Sopenharmony_ci    impl_ = env->NewLabel(env);
994514f5e3Sopenharmony_ci}
1004514f5e3Sopenharmony_ci
1014514f5e3Sopenharmony_civoid Label::LabelImpl::Seal()
1024514f5e3Sopenharmony_ci{
1034514f5e3Sopenharmony_ci    for (auto &[variable, gate] : incompletePhis_) {
1044514f5e3Sopenharmony_ci        variable->AddPhiOperand(gate);
1054514f5e3Sopenharmony_ci    }
1064514f5e3Sopenharmony_ci    isSealed_ = true;
1074514f5e3Sopenharmony_ci}
1084514f5e3Sopenharmony_ci
1094514f5e3Sopenharmony_civoid Label::LabelImpl::WriteVariable(Variable *var, GateRef value)
1104514f5e3Sopenharmony_ci{
1114514f5e3Sopenharmony_ci    valueMap_[var] = value;
1124514f5e3Sopenharmony_ci}
1134514f5e3Sopenharmony_ci
1144514f5e3Sopenharmony_ciGateRef Label::LabelImpl::ReadVariable(Variable *var)
1154514f5e3Sopenharmony_ci{
1164514f5e3Sopenharmony_ci    if (valueMap_.find(var) != valueMap_.end()) {
1174514f5e3Sopenharmony_ci        auto result = valueMap_.at(var);
1184514f5e3Sopenharmony_ci        GateAccessor acc(env_->GetCircuit());
1194514f5e3Sopenharmony_ci        if (!acc.IsNop(result)) {
1204514f5e3Sopenharmony_ci            return result;
1214514f5e3Sopenharmony_ci        }
1224514f5e3Sopenharmony_ci    }
1234514f5e3Sopenharmony_ci    return ReadVariableRecursive(var);
1244514f5e3Sopenharmony_ci}
1254514f5e3Sopenharmony_ci
1264514f5e3Sopenharmony_ciGateRef Label::LabelImpl::ReadVariableRecursive(Variable *var)
1274514f5e3Sopenharmony_ci{
1284514f5e3Sopenharmony_ci    GateRef val;
1294514f5e3Sopenharmony_ci    MachineType machineType = CircuitBuilder::GetMachineTypeFromVariableType(var->Type());
1304514f5e3Sopenharmony_ci    if (!IsSealed()) {
1314514f5e3Sopenharmony_ci        // only loopheader gate will be not sealed
1324514f5e3Sopenharmony_ci        int valueCounts = static_cast<int>(this->predecessors_.size()) + 1;
1334514f5e3Sopenharmony_ci        if (machineType == MachineType::NOVALUE) {
1344514f5e3Sopenharmony_ci            val = env_->GetBuilder()->Selector(OpCode::DEPEND_SELECTOR,
1354514f5e3Sopenharmony_ci                predeControl_, {}, valueCounts, var->Type());
1364514f5e3Sopenharmony_ci        } else {
1374514f5e3Sopenharmony_ci            val = env_->GetBuilder()->Selector(OpCode::VALUE_SELECTOR,
1384514f5e3Sopenharmony_ci                machineType, predeControl_, {}, valueCounts, var->Type());
1394514f5e3Sopenharmony_ci        }
1404514f5e3Sopenharmony_ci        env_->AddSelectorToLabel(val, Label(this));
1414514f5e3Sopenharmony_ci        incompletePhis_[var] = val;
1424514f5e3Sopenharmony_ci    } else if (predecessors_.size() == 1) {
1434514f5e3Sopenharmony_ci        val = predecessors_[0]->ReadVariable(var);
1444514f5e3Sopenharmony_ci    } else {
1454514f5e3Sopenharmony_ci        if (machineType == MachineType::NOVALUE) {
1464514f5e3Sopenharmony_ci            val = env_->GetBuilder()->Selector(OpCode::DEPEND_SELECTOR,
1474514f5e3Sopenharmony_ci                predeControl_, {}, this->predecessors_.size(), var->Type());
1484514f5e3Sopenharmony_ci        } else {
1494514f5e3Sopenharmony_ci            val = env_->GetBuilder()->Selector(OpCode::VALUE_SELECTOR, machineType,
1504514f5e3Sopenharmony_ci                predeControl_, {}, this->predecessors_.size(), var->Type());
1514514f5e3Sopenharmony_ci        }
1524514f5e3Sopenharmony_ci        env_->AddSelectorToLabel(val, Label(this));
1534514f5e3Sopenharmony_ci        WriteVariable(var, val);
1544514f5e3Sopenharmony_ci        val = var->AddPhiOperand(val);
1554514f5e3Sopenharmony_ci    }
1564514f5e3Sopenharmony_ci    WriteVariable(var, val);
1574514f5e3Sopenharmony_ci    return val;
1584514f5e3Sopenharmony_ci}
1594514f5e3Sopenharmony_ci
1604514f5e3Sopenharmony_civoid Label::LabelImpl::Bind()
1614514f5e3Sopenharmony_ci{
1624514f5e3Sopenharmony_ci    ASSERT(!predecessors_.empty());
1634514f5e3Sopenharmony_ci    if (IsLoopHead()) {
1644514f5e3Sopenharmony_ci        // 2 means input number of depend selector gate
1654514f5e3Sopenharmony_ci        loopDepend_ = env_->GetBuilder()->Selector(OpCode::DEPEND_SELECTOR, predeControl_, {}, 2);
1664514f5e3Sopenharmony_ci        GateAccessor(env_->GetCircuit()).NewIn(loopDepend_, 1, predecessors_[0]->GetDepend());
1674514f5e3Sopenharmony_ci        depend_ = loopDepend_;
1684514f5e3Sopenharmony_ci    }
1694514f5e3Sopenharmony_ci    if (IsNeedSeal()) {
1704514f5e3Sopenharmony_ci        Seal();
1714514f5e3Sopenharmony_ci        MergeAllControl();
1724514f5e3Sopenharmony_ci        MergeAllDepend();
1734514f5e3Sopenharmony_ci    }
1744514f5e3Sopenharmony_ci}
1754514f5e3Sopenharmony_ci
1764514f5e3Sopenharmony_civoid Label::LabelImpl::MergeAllControl()
1774514f5e3Sopenharmony_ci{
1784514f5e3Sopenharmony_ci    if (predecessors_.size() < 2) {  // 2 : Loop Head only support two predecessors_
1794514f5e3Sopenharmony_ci        return;
1804514f5e3Sopenharmony_ci    }
1814514f5e3Sopenharmony_ci
1824514f5e3Sopenharmony_ci    if (IsLoopHead()) {
1834514f5e3Sopenharmony_ci        ASSERT(predecessors_.size() == 2);  // 2 : Loop Head only support two predecessors_
1844514f5e3Sopenharmony_ci        ASSERT(otherPredeControls_.size() == 1);
1854514f5e3Sopenharmony_ci        GateAccessor(env_->GetCircuit()).NewIn(predeControl_, 1, otherPredeControls_[0]);
1864514f5e3Sopenharmony_ci        return;
1874514f5e3Sopenharmony_ci    }
1884514f5e3Sopenharmony_ci
1894514f5e3Sopenharmony_ci    // merge all control of predecessors_
1904514f5e3Sopenharmony_ci    std::vector<GateRef> inGates(predecessors_.size());
1914514f5e3Sopenharmony_ci    size_t i = 0;
1924514f5e3Sopenharmony_ci    ASSERT(predeControl_ != -1);
1934514f5e3Sopenharmony_ci    ASSERT((otherPredeControls_.size() + 1) == predecessors_.size());
1944514f5e3Sopenharmony_ci    inGates[i++] = predeControl_;
1954514f5e3Sopenharmony_ci    for (auto in : otherPredeControls_) {
1964514f5e3Sopenharmony_ci        inGates[i++] = in;
1974514f5e3Sopenharmony_ci    }
1984514f5e3Sopenharmony_ci
1994514f5e3Sopenharmony_ci    GateRef merge = env_->GetBuilder()->Merge(inGates);
2004514f5e3Sopenharmony_ci    predeControl_ = merge;
2014514f5e3Sopenharmony_ci    control_ = merge;
2024514f5e3Sopenharmony_ci}
2034514f5e3Sopenharmony_ci
2044514f5e3Sopenharmony_civoid Label::LabelImpl::MergeAllDepend()
2054514f5e3Sopenharmony_ci{
2064514f5e3Sopenharmony_ci    if (predecessors_.size() < 2) {  // 2 : Loop Head only support two predecessors_
2074514f5e3Sopenharmony_ci        depend_ = predecessors_[0]->GetDepend();
2084514f5e3Sopenharmony_ci        if (IsControlCase()) {
2094514f5e3Sopenharmony_ci            // Add depend_relay to current label
2104514f5e3Sopenharmony_ci            depend_ = env_->GetBuilder()->DependRelay(predeControl_, depend_);
2114514f5e3Sopenharmony_ci        }
2124514f5e3Sopenharmony_ci        return;
2134514f5e3Sopenharmony_ci    }
2144514f5e3Sopenharmony_ci    if (IsLoopHead()) {
2154514f5e3Sopenharmony_ci        ASSERT(predecessors_.size() == 2);  // 2 : Loop Head only support two predecessors_
2164514f5e3Sopenharmony_ci        // Add loop depend to in of depend_seclector
2174514f5e3Sopenharmony_ci        ASSERT(loopDepend_ != -1);
2184514f5e3Sopenharmony_ci        // 2 mean 3rd input gate for loopDepend_(depend_selector)
2194514f5e3Sopenharmony_ci        GateAccessor(env_->GetCircuit()).NewIn(loopDepend_, 2, predecessors_[1]->GetDepend());
2204514f5e3Sopenharmony_ci        return;
2214514f5e3Sopenharmony_ci    }
2224514f5e3Sopenharmony_ci
2234514f5e3Sopenharmony_ci    //  Merge all depends to depend_seclector
2244514f5e3Sopenharmony_ci    std::vector<GateRef> dependsList;
2254514f5e3Sopenharmony_ci    for (auto prede : this->GetPredecessors()) {
2264514f5e3Sopenharmony_ci        dependsList.push_back(prede->GetDepend());
2274514f5e3Sopenharmony_ci    }
2284514f5e3Sopenharmony_ci    depend_ = env_->GetBuilder()->Selector(OpCode::DEPEND_SELECTOR,
2294514f5e3Sopenharmony_ci        predeControl_, dependsList, dependsList.size());
2304514f5e3Sopenharmony_ci}
2314514f5e3Sopenharmony_ci
2324514f5e3Sopenharmony_civoid Label::LabelImpl::AppendPredecessor(Label::LabelImpl *predecessor)
2334514f5e3Sopenharmony_ci{
2344514f5e3Sopenharmony_ci    if (predecessor != nullptr) {
2354514f5e3Sopenharmony_ci        predecessors_.push_back(predecessor);
2364514f5e3Sopenharmony_ci    }
2374514f5e3Sopenharmony_ci}
2384514f5e3Sopenharmony_ci
2394514f5e3Sopenharmony_cibool Label::LabelImpl::IsNeedSeal() const
2404514f5e3Sopenharmony_ci{
2414514f5e3Sopenharmony_ci    auto stateCount = GateAccessor(env_->GetCircuit()).GetStateCount(predeControl_);
2424514f5e3Sopenharmony_ci    return predecessors_.size() >= stateCount;
2434514f5e3Sopenharmony_ci}
2444514f5e3Sopenharmony_ci
2454514f5e3Sopenharmony_cibool Label::LabelImpl::IsLoopHead() const
2464514f5e3Sopenharmony_ci{
2474514f5e3Sopenharmony_ci    return GateAccessor(env_->GetCircuit()).IsLoopHead(predeControl_);
2484514f5e3Sopenharmony_ci}
2494514f5e3Sopenharmony_ci
2504514f5e3Sopenharmony_cibool Label::LabelImpl::IsControlCase() const
2514514f5e3Sopenharmony_ci{
2524514f5e3Sopenharmony_ci    return GateAccessor(env_->GetCircuit()).IsControlCase(predeControl_);
2534514f5e3Sopenharmony_ci}
2544514f5e3Sopenharmony_ci}