14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2021 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/bytecode_circuit_builder.h" 174514f5e3Sopenharmony_ci#include "ecmascript/compiler/circuit.h" 184514f5e3Sopenharmony_ci#include "ecmascript/compiler/debug_info.h" 194514f5e3Sopenharmony_ci#include "ecmascript/compiler/ecma_opcode_des.h" 204514f5e3Sopenharmony_ci#include "ecmascript/compiler/gate_accessor.h" 214514f5e3Sopenharmony_ci#include "ecmascript/platform/map.h" 224514f5e3Sopenharmony_ci 234514f5e3Sopenharmony_cinamespace panda::ecmascript::kungfu { 244514f5e3Sopenharmony_ciCircuit::Circuit(NativeAreaAllocator* allocator, DebugInfo* debugInfo, const char* funcName, 254514f5e3Sopenharmony_ci bool isArch64, panda::ecmascript::FrameType type) 264514f5e3Sopenharmony_ci : circuitSize_(0), 274514f5e3Sopenharmony_ci gateCount_(0), 284514f5e3Sopenharmony_ci time_(1), 294514f5e3Sopenharmony_ci frameType_(type), 304514f5e3Sopenharmony_ci isArch64_(isArch64), 314514f5e3Sopenharmony_ci chunk_(allocator), 324514f5e3Sopenharmony_ci root_(Circuit::NullGate()), 334514f5e3Sopenharmony_ci metaBuilder_(chunk()), 344514f5e3Sopenharmony_ci gateToDInfo_(chunk()), 354514f5e3Sopenharmony_ci debugInfo_(debugInfo) 364514f5e3Sopenharmony_ci#ifndef NDEBUG 374514f5e3Sopenharmony_ci , allGates_(chunk()) 384514f5e3Sopenharmony_ci#endif 394514f5e3Sopenharmony_ci{ 404514f5e3Sopenharmony_ci if (funcName != nullptr && debugInfo_->IsEnable()) { 414514f5e3Sopenharmony_ci debugInfo_->AddFuncDebugInfo(funcName); 424514f5e3Sopenharmony_ci } 434514f5e3Sopenharmony_ci space_ = panda::ecmascript::PageMap(CIRCUIT_SPACE, PAGE_PROT_READWRITE).GetMem(); 444514f5e3Sopenharmony_ci InitRoot(); 454514f5e3Sopenharmony_ci} 464514f5e3Sopenharmony_ci 474514f5e3Sopenharmony_ciCircuit::~Circuit() 484514f5e3Sopenharmony_ci{ 494514f5e3Sopenharmony_ci panda::ecmascript::PageUnmap(MemMap(space_, CIRCUIT_SPACE)); 504514f5e3Sopenharmony_ci debugInfo_ = nullptr; 514514f5e3Sopenharmony_ci space_ = nullptr; 524514f5e3Sopenharmony_ci} 534514f5e3Sopenharmony_ci 544514f5e3Sopenharmony_civoid Circuit::InitRoot() 554514f5e3Sopenharmony_ci{ 564514f5e3Sopenharmony_ci root_ = NewGate(metaBuilder_.CircuitRoot(), MachineType::NOVALUE, {}, GateType::Empty()); 574514f5e3Sopenharmony_ci NewGate(metaBuilder_.StateEntry(), MachineType::NOVALUE, { root_ }, GateType::Empty()); 584514f5e3Sopenharmony_ci NewGate(metaBuilder_.DependEntry(), MachineType::NOVALUE, { root_ }, GateType::Empty()); 594514f5e3Sopenharmony_ci NewGate(metaBuilder_.ReturnList(), MachineType::NOVALUE, { root_ }, GateType::Empty()); 604514f5e3Sopenharmony_ci NewGate(metaBuilder_.ArgList(), MachineType::NOVALUE, { root_ }, GateType::Empty()); 614514f5e3Sopenharmony_ci} 624514f5e3Sopenharmony_ci 634514f5e3Sopenharmony_ciuint8_t *Circuit::AllocateSpace(size_t gateSize) 644514f5e3Sopenharmony_ci{ 654514f5e3Sopenharmony_ci circuitSize_ += gateSize; 664514f5e3Sopenharmony_ci if (circuitSize_ > CIRCUIT_SPACE) { 674514f5e3Sopenharmony_ci return nullptr; // abort compilation 684514f5e3Sopenharmony_ci } 694514f5e3Sopenharmony_ci // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 704514f5e3Sopenharmony_ci return GetDataPtr(circuitSize_ - gateSize); 714514f5e3Sopenharmony_ci} 724514f5e3Sopenharmony_ci 734514f5e3Sopenharmony_ciGate *Circuit::AllocateGateSpace(size_t numIns) 744514f5e3Sopenharmony_ci{ 754514f5e3Sopenharmony_ci // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 764514f5e3Sopenharmony_ci return reinterpret_cast<Gate *>(AllocateSpace(Gate::GetGateSize(numIns)) + Gate::GetOutListSize(numIns)); 774514f5e3Sopenharmony_ci} 784514f5e3Sopenharmony_ci 794514f5e3Sopenharmony_cibool Circuit::AddComment(GateRef g, std::string &&str) 804514f5e3Sopenharmony_ci{ 814514f5e3Sopenharmony_ci if (debugInfo_ == nullptr) { 824514f5e3Sopenharmony_ci return false; 834514f5e3Sopenharmony_ci } 844514f5e3Sopenharmony_ci if (!debugInfo_->IsEnable()) { 854514f5e3Sopenharmony_ci return false; 864514f5e3Sopenharmony_ci } 874514f5e3Sopenharmony_ci auto it = gateToDInfo_.find(g); 884514f5e3Sopenharmony_ci if (it == gateToDInfo_.end()) { 894514f5e3Sopenharmony_ci size_t index = debugInfo_->AddComment(std::move(str)); 904514f5e3Sopenharmony_ci gateToDInfo_[g] = index; 914514f5e3Sopenharmony_ci } else { 924514f5e3Sopenharmony_ci debugInfo_->AppendComment(it->second, std::move(str)); 934514f5e3Sopenharmony_ci } 944514f5e3Sopenharmony_ci return true; 954514f5e3Sopenharmony_ci} 964514f5e3Sopenharmony_ci 974514f5e3Sopenharmony_cistd::string_view Circuit::GetComment(GateRef gate) const 984514f5e3Sopenharmony_ci{ 994514f5e3Sopenharmony_ci if (debugInfo_ == nullptr || !debugInfo_->IsEnable()) { 1004514f5e3Sopenharmony_ci return ""; 1014514f5e3Sopenharmony_ci } 1024514f5e3Sopenharmony_ci size_t index; 1034514f5e3Sopenharmony_ci if (!GetDebugInfo(gate, index)) { 1044514f5e3Sopenharmony_ci return ""; 1054514f5e3Sopenharmony_ci } 1064514f5e3Sopenharmony_ci return debugInfo_->GetComment(index); 1074514f5e3Sopenharmony_ci} 1084514f5e3Sopenharmony_ci 1094514f5e3Sopenharmony_cibool Circuit::GetDebugInfo(GateRef g, size_t &index) const 1104514f5e3Sopenharmony_ci{ 1114514f5e3Sopenharmony_ci auto it = gateToDInfo_.find(g); 1124514f5e3Sopenharmony_ci if (it != gateToDInfo_.end()) { 1134514f5e3Sopenharmony_ci index = it->second; 1144514f5e3Sopenharmony_ci return true; 1154514f5e3Sopenharmony_ci } else { 1164514f5e3Sopenharmony_ci return false; 1174514f5e3Sopenharmony_ci } 1184514f5e3Sopenharmony_ci} 1194514f5e3Sopenharmony_ci 1204514f5e3Sopenharmony_ci// NOLINTNEXTLINE(modernize-avoid-c-arrays) 1214514f5e3Sopenharmony_ciGateRef Circuit::NewGate(const GateMetaData *meta, MachineType machineType, size_t numIns, 1224514f5e3Sopenharmony_ci const GateRef inList[], GateType type, const char* comment) 1234514f5e3Sopenharmony_ci{ 1244514f5e3Sopenharmony_ci#ifndef NDEBUG 1254514f5e3Sopenharmony_ci if (numIns != meta->GetNumIns()) { 1264514f5e3Sopenharmony_ci LOG_COMPILER(FATAL) << "Invalid input list!" 1274514f5e3Sopenharmony_ci << " op=" << meta->GetOpCode() 1284514f5e3Sopenharmony_ci << " expected_num_in=" << meta->GetNumIns() << " actual_num_in=" << numIns; 1294514f5e3Sopenharmony_ci UNREACHABLE(); 1304514f5e3Sopenharmony_ci } 1314514f5e3Sopenharmony_ci#endif 1324514f5e3Sopenharmony_ci std::vector<Gate *> inPtrList(numIns); 1334514f5e3Sopenharmony_ci auto gateSpace = AllocateGateSpace(numIns); 1344514f5e3Sopenharmony_ci for (size_t idx = 0; idx < numIns; idx++) { 1354514f5e3Sopenharmony_ci // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 1364514f5e3Sopenharmony_ci inPtrList[idx] = (inList[idx] == Circuit::NullGate()) ? nullptr : LoadGatePtr(inList[idx]); 1374514f5e3Sopenharmony_ci } 1384514f5e3Sopenharmony_ci auto newGate = new (gateSpace) Gate(meta, gateCount_++, inPtrList.data(), machineType, type); 1394514f5e3Sopenharmony_ci#ifndef NDEBUG 1404514f5e3Sopenharmony_ci allGates_.push_back(GetGateRef(newGate)); 1414514f5e3Sopenharmony_ci#endif 1424514f5e3Sopenharmony_ci GateRef result = GetGateRef(newGate); 1434514f5e3Sopenharmony_ci if (comment != nullptr) { 1444514f5e3Sopenharmony_ci AddComment(result, std::string(comment)); 1454514f5e3Sopenharmony_ci } 1464514f5e3Sopenharmony_ci#ifndef NDEBUG 1474514f5e3Sopenharmony_ci if (UNLIKELY(debugInfo_ != nullptr && !currentComment_.empty())) { 1484514f5e3Sopenharmony_ci AddComment(result, std::string(currentComment_)); 1494514f5e3Sopenharmony_ci } 1504514f5e3Sopenharmony_ci#endif 1514514f5e3Sopenharmony_ci return result; 1524514f5e3Sopenharmony_ci} 1534514f5e3Sopenharmony_ci 1544514f5e3Sopenharmony_ciGateRef Circuit::NewGate(const GateMetaData *meta, const std::vector<GateRef> &inList, const char* comment) 1554514f5e3Sopenharmony_ci{ 1564514f5e3Sopenharmony_ci return NewGate(meta, MachineType::NOVALUE, inList.size(), inList.data(), GateType::Empty(), comment); 1574514f5e3Sopenharmony_ci} 1584514f5e3Sopenharmony_ci 1594514f5e3Sopenharmony_ciGateRef Circuit::NewGate(const GateMetaData *meta, MachineType machineType, 1604514f5e3Sopenharmony_ci const std::initializer_list<GateRef>& args, GateType type, const char* comment) 1614514f5e3Sopenharmony_ci{ 1624514f5e3Sopenharmony_ci return NewGate(meta, machineType, args.size(), args.begin(), type, comment); 1634514f5e3Sopenharmony_ci} 1644514f5e3Sopenharmony_ci 1654514f5e3Sopenharmony_ciGateRef Circuit::NewGate(const GateMetaData *meta, MachineType machineType, 1664514f5e3Sopenharmony_ci const std::vector<GateRef>& inList, GateType type, const char* comment) 1674514f5e3Sopenharmony_ci{ 1684514f5e3Sopenharmony_ci return NewGate(meta, machineType, inList.size(), inList.data(), type, comment); 1694514f5e3Sopenharmony_ci} 1704514f5e3Sopenharmony_ci 1714514f5e3Sopenharmony_ciGateRef Circuit::NewGate(const GateMetaData *meta, MachineType machineType, GateType type, const char* comment) 1724514f5e3Sopenharmony_ci{ 1734514f5e3Sopenharmony_ci return NewGate(meta, machineType, {}, type, comment); 1744514f5e3Sopenharmony_ci} 1754514f5e3Sopenharmony_ci 1764514f5e3Sopenharmony_civoid Circuit::PrintAllGates() const 1774514f5e3Sopenharmony_ci{ 1784514f5e3Sopenharmony_ci std::vector<GateRef> gateList; 1794514f5e3Sopenharmony_ci GetAllGates(gateList); 1804514f5e3Sopenharmony_ci for (const auto &gate : gateList) { 1814514f5e3Sopenharmony_ci LoadGatePtrConst(gate)->Print(); 1824514f5e3Sopenharmony_ci } 1834514f5e3Sopenharmony_ci} 1844514f5e3Sopenharmony_ci 1854514f5e3Sopenharmony_civoid Circuit::PrintAllGatesWithBytecode() const 1864514f5e3Sopenharmony_ci{ 1874514f5e3Sopenharmony_ci std::vector<GateRef> gateList; 1884514f5e3Sopenharmony_ci GetAllGates(gateList); 1894514f5e3Sopenharmony_ci for (const auto &gate : gateList) { 1904514f5e3Sopenharmony_ci LoadGatePtrConst(gate)->PrintWithBytecode(GetComment(gate)); 1914514f5e3Sopenharmony_ci } 1924514f5e3Sopenharmony_ci} 1934514f5e3Sopenharmony_ci 1944514f5e3Sopenharmony_civoid Circuit::GetAllGates(std::vector<GateRef>& gateList) const 1954514f5e3Sopenharmony_ci{ 1964514f5e3Sopenharmony_ci gateList.clear(); 1974514f5e3Sopenharmony_ci for (size_t out = 0; out < circuitSize_; 1984514f5e3Sopenharmony_ci out += Gate::GetGateSize(reinterpret_cast<const Out *>(LoadGatePtrConst(GateRef(out)))->GetIndex() + 1)) { 1994514f5e3Sopenharmony_ci auto gatePtr = reinterpret_cast<const Out *>(LoadGatePtrConst(GateRef(out)))->GetGateConst(); 2004514f5e3Sopenharmony_ci if (!gatePtr->GetMetaData()->IsNop()) { 2014514f5e3Sopenharmony_ci gateList.push_back(GetGateRef(gatePtr)); 2024514f5e3Sopenharmony_ci } 2034514f5e3Sopenharmony_ci } 2044514f5e3Sopenharmony_ci} 2054514f5e3Sopenharmony_ci 2064514f5e3Sopenharmony_ciGateRef Circuit::GetGateRef(const Gate *gate) const 2074514f5e3Sopenharmony_ci{ 2084514f5e3Sopenharmony_ci // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 2094514f5e3Sopenharmony_ci return static_cast<GateRef>(reinterpret_cast<const uint8_t *>(gate) - GetDataPtrConst(0)); 2104514f5e3Sopenharmony_ci} 2114514f5e3Sopenharmony_ci 2124514f5e3Sopenharmony_ciGate *Circuit::LoadGatePtr(GateRef shift) 2134514f5e3Sopenharmony_ci{ 2144514f5e3Sopenharmony_ci ASSERT(shift != Circuit::NullGate()); 2154514f5e3Sopenharmony_ci // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 2164514f5e3Sopenharmony_ci return reinterpret_cast<Gate *>(GetDataPtr(shift)); 2174514f5e3Sopenharmony_ci} 2184514f5e3Sopenharmony_ci 2194514f5e3Sopenharmony_ciconst Gate *Circuit::LoadGatePtrConst(GateRef shift) const 2204514f5e3Sopenharmony_ci{ 2214514f5e3Sopenharmony_ci // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 2224514f5e3Sopenharmony_ci return reinterpret_cast<const Gate *>(GetDataPtrConst(shift)); 2234514f5e3Sopenharmony_ci} 2244514f5e3Sopenharmony_ci 2254514f5e3Sopenharmony_civoid Circuit::AdvanceTime() const 2264514f5e3Sopenharmony_ci{ 2274514f5e3Sopenharmony_ci auto &curTime = const_cast<TimeStamp &>(time_); 2284514f5e3Sopenharmony_ci curTime++; 2294514f5e3Sopenharmony_ci if (curTime == 0) { 2304514f5e3Sopenharmony_ci curTime = 1; 2314514f5e3Sopenharmony_ci ResetAllGateTimeStamps(); 2324514f5e3Sopenharmony_ci } 2334514f5e3Sopenharmony_ci} 2344514f5e3Sopenharmony_ci 2354514f5e3Sopenharmony_civoid Circuit::ResetAllGateTimeStamps() const 2364514f5e3Sopenharmony_ci{ 2374514f5e3Sopenharmony_ci std::vector<GateRef> gateList; 2384514f5e3Sopenharmony_ci GetAllGates(gateList); 2394514f5e3Sopenharmony_ci for (auto &gate : gateList) { 2404514f5e3Sopenharmony_ci const_cast<Gate *>(LoadGatePtrConst(gate))->SetMark(MarkCode::NO_MARK, 0); 2414514f5e3Sopenharmony_ci } 2424514f5e3Sopenharmony_ci} 2434514f5e3Sopenharmony_ci 2444514f5e3Sopenharmony_ciTimeStamp Circuit::GetTime() const 2454514f5e3Sopenharmony_ci{ 2464514f5e3Sopenharmony_ci return time_; 2474514f5e3Sopenharmony_ci} 2484514f5e3Sopenharmony_ci 2494514f5e3Sopenharmony_ciMarkCode Circuit::GetMark(GateRef gate) const 2504514f5e3Sopenharmony_ci{ 2514514f5e3Sopenharmony_ci return LoadGatePtrConst(gate)->GetMark(GetTime()); 2524514f5e3Sopenharmony_ci} 2534514f5e3Sopenharmony_ci 2544514f5e3Sopenharmony_civoid Circuit::SetMark(GateRef gate, MarkCode mark) const 2554514f5e3Sopenharmony_ci{ 2564514f5e3Sopenharmony_ci const_cast<Gate *>(LoadGatePtrConst(gate))->SetMark(mark, GetTime()); 2574514f5e3Sopenharmony_ci} 2584514f5e3Sopenharmony_ci 2594514f5e3Sopenharmony_civoid Circuit::Verify(GateRef gate, const std::string& methodName) const 2604514f5e3Sopenharmony_ci{ 2614514f5e3Sopenharmony_ci LoadGatePtrConst(gate)->Verify(IsArch64(), methodName); 2624514f5e3Sopenharmony_ci} 2634514f5e3Sopenharmony_ci 2644514f5e3Sopenharmony_ciGateRef Circuit::NullGate() 2654514f5e3Sopenharmony_ci{ 2664514f5e3Sopenharmony_ci return Gate::InvalidGateRef; 2674514f5e3Sopenharmony_ci} 2684514f5e3Sopenharmony_ci 2694514f5e3Sopenharmony_cibool Circuit::IsLoopHead(GateRef gate) const 2704514f5e3Sopenharmony_ci{ 2714514f5e3Sopenharmony_ci if (gate != NullGate()) { 2724514f5e3Sopenharmony_ci const Gate *curGate = LoadGatePtrConst(gate); 2734514f5e3Sopenharmony_ci return curGate->GetMetaData()->IsLoopHead(); 2744514f5e3Sopenharmony_ci } 2754514f5e3Sopenharmony_ci return false; 2764514f5e3Sopenharmony_ci} 2774514f5e3Sopenharmony_ci 2784514f5e3Sopenharmony_cibool Circuit::IsControlCase(GateRef gate) const 2794514f5e3Sopenharmony_ci{ 2804514f5e3Sopenharmony_ci if (gate != NullGate()) { 2814514f5e3Sopenharmony_ci const Gate *curGate = LoadGatePtrConst(gate); 2824514f5e3Sopenharmony_ci return curGate->GetMetaData()->IsControlCase(); 2834514f5e3Sopenharmony_ci } 2844514f5e3Sopenharmony_ci return false; 2854514f5e3Sopenharmony_ci} 2864514f5e3Sopenharmony_ci 2874514f5e3Sopenharmony_cibool Circuit::IsValueSelector(GateRef gate) const 2884514f5e3Sopenharmony_ci{ 2894514f5e3Sopenharmony_ci if (gate != NullGate()) { 2904514f5e3Sopenharmony_ci const Gate *curGate = LoadGatePtrConst(gate); 2914514f5e3Sopenharmony_ci return curGate->GetOpCode() == OpCode::VALUE_SELECTOR; 2924514f5e3Sopenharmony_ci } 2934514f5e3Sopenharmony_ci return false; 2944514f5e3Sopenharmony_ci} 2954514f5e3Sopenharmony_ci 2964514f5e3Sopenharmony_cibool Circuit::IsSelector(GateRef gate) const 2974514f5e3Sopenharmony_ci{ 2984514f5e3Sopenharmony_ci if (gate != NullGate()) { 2994514f5e3Sopenharmony_ci const Gate *curGate = LoadGatePtrConst(gate); 3004514f5e3Sopenharmony_ci OpCode op = curGate->GetOpCode(); 3014514f5e3Sopenharmony_ci return (op == OpCode::VALUE_SELECTOR) || (op == OpCode::DEPEND_SELECTOR); 3024514f5e3Sopenharmony_ci } 3034514f5e3Sopenharmony_ci return false; 3044514f5e3Sopenharmony_ci} 3054514f5e3Sopenharmony_ci 3064514f5e3Sopenharmony_ciGateRef Circuit::GetIn(GateRef gate, size_t idx) const 3074514f5e3Sopenharmony_ci{ 3084514f5e3Sopenharmony_ci ASSERT(idx < LoadGatePtrConst(gate)->GetNumIns()); 3094514f5e3Sopenharmony_ci if (IsInGateNull(gate, idx)) { 3104514f5e3Sopenharmony_ci return NullGate(); 3114514f5e3Sopenharmony_ci } 3124514f5e3Sopenharmony_ci const Gate *curGate = LoadGatePtrConst(gate); 3134514f5e3Sopenharmony_ci return GetGateRef(curGate->GetInGateConst(idx)); 3144514f5e3Sopenharmony_ci} 3154514f5e3Sopenharmony_ci 3164514f5e3Sopenharmony_cibool Circuit::IsInGateNull(GateRef gate, size_t idx) const 3174514f5e3Sopenharmony_ci{ 3184514f5e3Sopenharmony_ci const Gate *curGate = LoadGatePtrConst(gate); 3194514f5e3Sopenharmony_ci return curGate->GetInConst(idx)->IsGateNull(); 3204514f5e3Sopenharmony_ci} 3214514f5e3Sopenharmony_ci 3224514f5e3Sopenharmony_cibool Circuit::IsFirstOutNull(GateRef gate) const 3234514f5e3Sopenharmony_ci{ 3244514f5e3Sopenharmony_ci const Gate *curGate = LoadGatePtrConst(gate); 3254514f5e3Sopenharmony_ci return curGate->IsFirstOutNull(); 3264514f5e3Sopenharmony_ci} 3274514f5e3Sopenharmony_ci 3284514f5e3Sopenharmony_cistd::vector<GateRef> Circuit::GetOutVector(GateRef gate) const 3294514f5e3Sopenharmony_ci{ 3304514f5e3Sopenharmony_ci std::vector<GateRef> result; 3314514f5e3Sopenharmony_ci const Gate *curGate = LoadGatePtrConst(gate); 3324514f5e3Sopenharmony_ci if (!curGate->IsFirstOutNull()) { 3334514f5e3Sopenharmony_ci const Out *curOut = curGate->GetFirstOutConst(); 3344514f5e3Sopenharmony_ci result.push_back(GetGateRef(curOut->GetGateConst())); 3354514f5e3Sopenharmony_ci while (!curOut->IsNextOutNull()) { 3364514f5e3Sopenharmony_ci curOut = curOut->GetNextOutConst(); 3374514f5e3Sopenharmony_ci result.push_back(GetGateRef(curOut->GetGateConst())); 3384514f5e3Sopenharmony_ci } 3394514f5e3Sopenharmony_ci } 3404514f5e3Sopenharmony_ci return result; 3414514f5e3Sopenharmony_ci} 3424514f5e3Sopenharmony_ci 3434514f5e3Sopenharmony_civoid Circuit::NewIn(GateRef gate, size_t idx, GateRef in) 3444514f5e3Sopenharmony_ci{ 3454514f5e3Sopenharmony_ci#ifndef NDEBUG 3464514f5e3Sopenharmony_ci ASSERT(idx < LoadGatePtrConst(gate)->GetNumIns()); 3474514f5e3Sopenharmony_ci ASSERT(Circuit::IsInGateNull(gate, idx)); 3484514f5e3Sopenharmony_ci#endif 3494514f5e3Sopenharmony_ci LoadGatePtr(gate)->NewIn(idx, LoadGatePtr(in)); 3504514f5e3Sopenharmony_ci} 3514514f5e3Sopenharmony_ci 3524514f5e3Sopenharmony_civoid Circuit::ModifyIn(GateRef gate, size_t idx, GateRef in) 3534514f5e3Sopenharmony_ci{ 3544514f5e3Sopenharmony_ci#ifndef NDEBUG 3554514f5e3Sopenharmony_ci ASSERT(idx < LoadGatePtrConst(gate)->GetNumIns()); 3564514f5e3Sopenharmony_ci ASSERT(!Circuit::IsInGateNull(gate, idx) || (GetOpCode(gate) == OpCode::SAVE_REGISTER)); 3574514f5e3Sopenharmony_ci#endif 3584514f5e3Sopenharmony_ci LoadGatePtr(gate)->ModifyIn(idx, LoadGatePtr(in)); 3594514f5e3Sopenharmony_ci} 3604514f5e3Sopenharmony_ci 3614514f5e3Sopenharmony_civoid Circuit::DeleteIn(GateRef gate, size_t idx) 3624514f5e3Sopenharmony_ci{ 3634514f5e3Sopenharmony_ci ASSERT(idx < LoadGatePtrConst(gate)->GetNumIns()); 3644514f5e3Sopenharmony_ci ASSERT(!Circuit::IsInGateNull(gate, idx)); 3654514f5e3Sopenharmony_ci LoadGatePtr(gate)->DeleteIn(idx); 3664514f5e3Sopenharmony_ci} 3674514f5e3Sopenharmony_ci 3684514f5e3Sopenharmony_civoid Circuit::DeleteGate(GateRef gate) 3694514f5e3Sopenharmony_ci{ 3704514f5e3Sopenharmony_ci // constant in constant cache, dont delete it. 3714514f5e3Sopenharmony_ci if (GetOpCode(gate) != OpCode::CONSTANT) { 3724514f5e3Sopenharmony_ci LoadGatePtr(gate)->DeleteGate(); 3734514f5e3Sopenharmony_ci LoadGatePtr(gate)->SetMetaData(Nop()); 3744514f5e3Sopenharmony_ci } 3754514f5e3Sopenharmony_ci} 3764514f5e3Sopenharmony_ci 3774514f5e3Sopenharmony_civoid Circuit::DecreaseIn(GateRef gate, size_t idx) 3784514f5e3Sopenharmony_ci{ 3794514f5e3Sopenharmony_ci auto numIns = LoadGatePtrConst(gate)->GetNumIns(); 3804514f5e3Sopenharmony_ci ASSERT(numIns > 0); 3814514f5e3Sopenharmony_ci for (size_t i = idx; i < numIns - 1; i++) { 3824514f5e3Sopenharmony_ci ModifyIn(gate, i, GetIn(gate, i + 1)); 3834514f5e3Sopenharmony_ci } 3844514f5e3Sopenharmony_ci DeleteIn(gate, numIns - 1); 3854514f5e3Sopenharmony_ci GateMetaData *meta = const_cast<GateMetaData *>( 3864514f5e3Sopenharmony_ci LoadGatePtr(gate)->GetMetaData()); 3874514f5e3Sopenharmony_ci if (meta->GetKind() == GateMetaData::Kind::MUTABLE_WITH_SIZE) { 3884514f5e3Sopenharmony_ci meta->DecreaseIn(idx); 3894514f5e3Sopenharmony_ci } else { 3904514f5e3Sopenharmony_ci meta = metaBuilder_.NewGateMetaData(meta); 3914514f5e3Sopenharmony_ci meta->DecreaseIn(idx); 3924514f5e3Sopenharmony_ci LoadGatePtr(gate)->SetMetaData(meta); 3934514f5e3Sopenharmony_ci } 3944514f5e3Sopenharmony_ci} 3954514f5e3Sopenharmony_ci 3964514f5e3Sopenharmony_civoid Circuit::SetGateType(GateRef gate, GateType type) 3974514f5e3Sopenharmony_ci{ 3984514f5e3Sopenharmony_ci LoadGatePtr(gate)->SetGateType(type); 3994514f5e3Sopenharmony_ci} 4004514f5e3Sopenharmony_ci 4014514f5e3Sopenharmony_civoid Circuit::SetMachineType(GateRef gate, MachineType machineType) 4024514f5e3Sopenharmony_ci{ 4034514f5e3Sopenharmony_ci LoadGatePtr(gate)->SetMachineType(machineType); 4044514f5e3Sopenharmony_ci} 4054514f5e3Sopenharmony_ci 4064514f5e3Sopenharmony_ciGateType Circuit::GetGateType(GateRef gate) const 4074514f5e3Sopenharmony_ci{ 4084514f5e3Sopenharmony_ci return LoadGatePtrConst(gate)->GetGateType(); 4094514f5e3Sopenharmony_ci} 4104514f5e3Sopenharmony_ci 4114514f5e3Sopenharmony_ciMachineType Circuit::GetMachineType(GateRef gate) const 4124514f5e3Sopenharmony_ci{ 4134514f5e3Sopenharmony_ci return LoadGatePtrConst(gate)->GetMachineType(); 4144514f5e3Sopenharmony_ci} 4154514f5e3Sopenharmony_ci 4164514f5e3Sopenharmony_ciOpCode Circuit::GetOpCode(GateRef gate) const 4174514f5e3Sopenharmony_ci{ 4184514f5e3Sopenharmony_ci return LoadGatePtrConst(gate)->GetOpCode(); 4194514f5e3Sopenharmony_ci} 4204514f5e3Sopenharmony_ci 4214514f5e3Sopenharmony_ciGateId Circuit::GetId(GateRef gate) const 4224514f5e3Sopenharmony_ci{ 4234514f5e3Sopenharmony_ci return LoadGatePtrConst(gate)->GetId(); 4244514f5e3Sopenharmony_ci} 4254514f5e3Sopenharmony_ci 4264514f5e3Sopenharmony_ci#ifndef NDEBUG 4274514f5e3Sopenharmony_ciCircuit::ScopedComment::ScopedComment(std::string &&str, std::string_view *comment) 4284514f5e3Sopenharmony_ci : old_(*comment), comment_(comment) 4294514f5e3Sopenharmony_ci{ 4304514f5e3Sopenharmony_ci if (comment->empty()) { 4314514f5e3Sopenharmony_ci str_ = std::move(str); 4324514f5e3Sopenharmony_ci } else { 4334514f5e3Sopenharmony_ci str_ = std::string{*comment} + " " + std::move(str); 4344514f5e3Sopenharmony_ci } 4354514f5e3Sopenharmony_ci *comment_ = {str_}; 4364514f5e3Sopenharmony_ci} 4374514f5e3Sopenharmony_ci 4384514f5e3Sopenharmony_ciCircuit::ScopedComment Circuit::VisitGateBegin(GateRef visitedGate) 4394514f5e3Sopenharmony_ci{ 4404514f5e3Sopenharmony_ci return ScopedComment("old " + std::to_string(GetId(visitedGate)), ¤tComment_); 4414514f5e3Sopenharmony_ci} 4424514f5e3Sopenharmony_ci 4434514f5e3Sopenharmony_ciCircuit::ScopedComment Circuit::CommentBegin(std::string &&str) 4444514f5e3Sopenharmony_ci{ 4454514f5e3Sopenharmony_ci return ScopedComment(std::move(str), ¤tComment_); 4464514f5e3Sopenharmony_ci} 4474514f5e3Sopenharmony_ci#endif 4484514f5e3Sopenharmony_ci 4494514f5e3Sopenharmony_civoid Circuit::Print(GateRef gate) const 4504514f5e3Sopenharmony_ci{ 4514514f5e3Sopenharmony_ci LoadGatePtrConst(gate)->Print(); 4524514f5e3Sopenharmony_ci} 4534514f5e3Sopenharmony_ci 4544514f5e3Sopenharmony_cisize_t Circuit::GetCircuitDataSize() const 4554514f5e3Sopenharmony_ci{ 4564514f5e3Sopenharmony_ci return circuitSize_; 4574514f5e3Sopenharmony_ci} 4584514f5e3Sopenharmony_ci 4594514f5e3Sopenharmony_ciconst void *Circuit::GetSpaceDataStartPtrConst() const 4604514f5e3Sopenharmony_ci{ 4614514f5e3Sopenharmony_ci // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 4624514f5e3Sopenharmony_ci return GetDataPtrConst(0); 4634514f5e3Sopenharmony_ci} 4644514f5e3Sopenharmony_ci 4654514f5e3Sopenharmony_ciconst void *Circuit::GetSpaceDataEndPtrConst() const 4664514f5e3Sopenharmony_ci{ 4674514f5e3Sopenharmony_ci // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 4684514f5e3Sopenharmony_ci return GetDataPtrConst(circuitSize_); 4694514f5e3Sopenharmony_ci} 4704514f5e3Sopenharmony_ci 4714514f5e3Sopenharmony_ciconst uint8_t *Circuit::GetDataPtrConst(size_t offset) const 4724514f5e3Sopenharmony_ci{ 4734514f5e3Sopenharmony_ci // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 4744514f5e3Sopenharmony_ci return static_cast<uint8_t *>(space_) + offset; 4754514f5e3Sopenharmony_ci} 4764514f5e3Sopenharmony_ci 4774514f5e3Sopenharmony_ciuint8_t *Circuit::GetDataPtr(size_t offset) 4784514f5e3Sopenharmony_ci{ 4794514f5e3Sopenharmony_ci // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 4804514f5e3Sopenharmony_ci return static_cast<uint8_t *>(space_) + offset; 4814514f5e3Sopenharmony_ci} 4824514f5e3Sopenharmony_ci 4834514f5e3Sopenharmony_cipanda::ecmascript::FrameType Circuit::GetFrameType() const 4844514f5e3Sopenharmony_ci{ 4854514f5e3Sopenharmony_ci return frameType_; 4864514f5e3Sopenharmony_ci} 4874514f5e3Sopenharmony_ci 4884514f5e3Sopenharmony_civoid Circuit::SetFrameType(panda::ecmascript::FrameType type) 4894514f5e3Sopenharmony_ci{ 4904514f5e3Sopenharmony_ci frameType_ = type; 4914514f5e3Sopenharmony_ci} 4924514f5e3Sopenharmony_ci 4934514f5e3Sopenharmony_ciGateRef Circuit::GetConstantGate(MachineType machineType, uint64_t value, 4944514f5e3Sopenharmony_ci GateType type) 4954514f5e3Sopenharmony_ci{ 4964514f5e3Sopenharmony_ci auto search = constantCache_.find({machineType, value, type}); 4974514f5e3Sopenharmony_ci if (search != constantCache_.end()) { 4984514f5e3Sopenharmony_ci return search->second; 4994514f5e3Sopenharmony_ci } 5004514f5e3Sopenharmony_ci auto gate = NewGate(metaBuilder_.Constant(value), machineType, type); 5014514f5e3Sopenharmony_ci constantCache_[{machineType, value, type}] = gate; 5024514f5e3Sopenharmony_ci return gate; 5034514f5e3Sopenharmony_ci} 5044514f5e3Sopenharmony_ci 5054514f5e3Sopenharmony_ciGateRef Circuit::GetConstantGateWithoutCache(MachineType machineType, uint64_t value, GateType type) 5064514f5e3Sopenharmony_ci{ 5074514f5e3Sopenharmony_ci auto gate = NewGate(metaBuilder_.Constant(value), machineType, type); 5084514f5e3Sopenharmony_ci return gate; 5094514f5e3Sopenharmony_ci} 5104514f5e3Sopenharmony_ci 5114514f5e3Sopenharmony_civoid Circuit::ClearConstantCache(MachineType machineType, uint64_t value, GateType type) 5124514f5e3Sopenharmony_ci{ 5134514f5e3Sopenharmony_ci auto search = constantCache_.find({machineType, value, type}); 5144514f5e3Sopenharmony_ci if (search != constantCache_.end()) { 5154514f5e3Sopenharmony_ci constantCache_.erase(search); 5164514f5e3Sopenharmony_ci } 5174514f5e3Sopenharmony_ci} 5184514f5e3Sopenharmony_ci 5194514f5e3Sopenharmony_ciGateRef Circuit::GetConstantStringGate(MachineType machineType, std::string_view str, 5204514f5e3Sopenharmony_ci GateType type) 5214514f5e3Sopenharmony_ci{ 5224514f5e3Sopenharmony_ci auto gate = NewGate(metaBuilder_.ConstString(str), machineType, type); 5234514f5e3Sopenharmony_ci return gate; 5244514f5e3Sopenharmony_ci} 5254514f5e3Sopenharmony_ci 5264514f5e3Sopenharmony_ciGateRef Circuit::GetInitialEnvGate(GateRef depend, GateRef jsFunc) 5274514f5e3Sopenharmony_ci{ 5284514f5e3Sopenharmony_ci auto search = initialEnvCache_.find(jsFunc); 5294514f5e3Sopenharmony_ci if (search != initialEnvCache_.end()) { 5304514f5e3Sopenharmony_ci return initialEnvCache_.at(jsFunc); 5314514f5e3Sopenharmony_ci } 5324514f5e3Sopenharmony_ci auto gate = NewGate(GetEnv(), MachineType::I64, {depend, jsFunc}, GateType::AnyType()); 5334514f5e3Sopenharmony_ci initialEnvCache_[jsFunc] = gate; 5344514f5e3Sopenharmony_ci return gate; 5354514f5e3Sopenharmony_ci} 5364514f5e3Sopenharmony_ci 5374514f5e3Sopenharmony_ciGateRef Circuit::NewArg(MachineType machineType, size_t index, 5384514f5e3Sopenharmony_ci GateType type, GateRef argRoot) 5394514f5e3Sopenharmony_ci{ 5404514f5e3Sopenharmony_ci return NewGate(metaBuilder_.Arg(index), machineType, { argRoot }, type); 5414514f5e3Sopenharmony_ci} 5424514f5e3Sopenharmony_ci 5434514f5e3Sopenharmony_cisize_t Circuit::GetGateCount() const 5444514f5e3Sopenharmony_ci{ 5454514f5e3Sopenharmony_ci return gateCount_; 5464514f5e3Sopenharmony_ci} 5474514f5e3Sopenharmony_ci 5484514f5e3Sopenharmony_ciGateRef Circuit::GetStateRoot() const 5494514f5e3Sopenharmony_ci{ 5504514f5e3Sopenharmony_ci const GateAccessor acc(const_cast<Circuit*>(this)); 5514514f5e3Sopenharmony_ci return acc.GetStateRoot(); 5524514f5e3Sopenharmony_ci} 5534514f5e3Sopenharmony_ci 5544514f5e3Sopenharmony_ciGateRef Circuit::GetDependRoot() const 5554514f5e3Sopenharmony_ci{ 5564514f5e3Sopenharmony_ci const GateAccessor acc(const_cast<Circuit*>(this)); 5574514f5e3Sopenharmony_ci return acc.GetDependRoot(); 5584514f5e3Sopenharmony_ci} 5594514f5e3Sopenharmony_ci 5604514f5e3Sopenharmony_ciGateRef Circuit::GetArgRoot() const 5614514f5e3Sopenharmony_ci{ 5624514f5e3Sopenharmony_ci const GateAccessor acc(const_cast<Circuit*>(this)); 5634514f5e3Sopenharmony_ci return acc.GetArgRoot(); 5644514f5e3Sopenharmony_ci} 5654514f5e3Sopenharmony_ci 5664514f5e3Sopenharmony_ciGateRef Circuit::GetReturnRoot() const 5674514f5e3Sopenharmony_ci{ 5684514f5e3Sopenharmony_ci const GateAccessor acc(const_cast<Circuit*>(this)); 5694514f5e3Sopenharmony_ci return acc.GetReturnRoot(); 5704514f5e3Sopenharmony_ci} 5714514f5e3Sopenharmony_ci} // namespace panda::ecmascript::kungfu 572