1/* 2 * Copyright (c) 2021 - 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#include "regSpiller.h" 17#include "compiler/core/codeGen.h" 18#include "checker/types/type.h" 19 20namespace ark::es2panda::compiler { 21 22CodeGen *RegSpiller::GetCodeGen() const noexcept 23{ 24 return cg_; 25} 26 27std::pair<RegSpiller::SpillInfo, const checker::Type *> RegSpiller::New() noexcept 28{ 29 const VReg origin {VReg::REG_START - spillIndex_++}; 30 const auto *const originType = cg_->GetVRegType(origin); 31 const SpillInfo spillInfo {origin, cg_->AllocRegWithType(originType)}; 32 return std::make_pair(spillInfo, originType); 33} 34 35void RegSpiller::Adjust(const std::unordered_set<VReg> ®s) noexcept 36{ 37 while (true) { 38 const VReg origin {VReg::REG_START - spillIndex_}; 39 40 if (regs.count(origin) == 0) { 41 break; 42 } 43 44 ++spillIndex_; 45 } 46} 47 48void RegSpiller::SetCodeGen(CodeGen &cg) noexcept 49{ 50 cg_ = &cg; 51} 52 53std::uint32_t RegSpiller::SpillIndex() const noexcept 54{ 55 return spillIndex_; 56} 57 58std::uint32_t &RegSpiller::SpillIndex() noexcept 59{ 60 return spillIndex_; 61} 62 63RegScope DynamicRegSpiller::Start(CodeGen &cg) 64{ 65 SetCodeGen(cg); 66 regEnd_ = GetCodeGen()->NextReg().GetIndex(); 67 return RegScope {&cg}; 68} 69 70RegSpiller::SpillInfo DynamicRegSpiller::Restore() 71{ 72 const auto newSpillIndex = --SpillIndex(); 73 return RegSpiller::SpillInfo(VReg {VReg::REG_START - newSpillIndex}, VReg {regEnd_ - SpillIndex()}); 74} 75 76bool DynamicRegSpiller::Restored() const 77{ 78 return SpillIndex() == 0; 79} 80 81IRNode *DynamicRegSpiller::MoveReg(const ir::AstNode *const node, const VReg vd, const VReg vs, 82 [[maybe_unused]] const bool spillMov) 83{ 84 return GetCodeGen()->AllocMov(node, vd, vs); 85} 86 87void DynamicRegSpiller::Finalize() noexcept 88{ 89 ASSERT(SpillIndex() == 0); 90} 91 92RegScope StaticRegSpiller::Start(CodeGen &cg) 93{ 94 SetCodeGen(cg); 95 return RegScope {&cg}; 96} 97 98RegSpiller::SpillInfo StaticRegSpiller::Restore() 99{ 100 ASSERT(spills_.size() <= VReg::REG_START); 101 ASSERT(!spills_.empty()); 102 const auto last = spills_.back().Reversed(); 103 spills_.pop_back(); 104 return last; 105} 106 107bool StaticRegSpiller::Restored() const 108{ 109 return spills_.empty(); 110} 111 112IRNode *StaticRegSpiller::MoveReg(const ir::AstNode *const node, const VReg vd, const VReg vs, const bool spillMov) 113{ 114 if (vd == vs) { 115 return nullptr; 116 } 117 118 const auto *const sourceType = GetCodeGen()->GetVRegType(vs); 119 if (sourceType == nullptr) { 120 return nullptr; 121 } 122 123 GetCodeGen()->SetVRegType(vd, sourceType); 124 if (spillMov) { 125 spills_.emplace_back(vd, vs); 126 } 127 128 return GetCodeGen()->AllocMov(node, vd, vs); 129} 130 131void StaticRegSpiller::Finalize() noexcept 132{ 133 SpillIndex() = 0; 134} 135 136} // namespace ark::es2panda::compiler 137