1 /*
2 * Copyright (c) 2021-2025 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
20 namespace ark::es2panda::compiler {
21
GetCodeGen() const22 CodeGen *RegSpiller::GetCodeGen() const noexcept
23 {
24 return cg_;
25 }
26
New()27 std::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
Adjust(const std::unordered_set<VReg> & regs)35 void 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
SetCodeGen(CodeGen & cg)48 void RegSpiller::SetCodeGen(CodeGen &cg) noexcept
49 {
50 cg_ = &cg;
51 }
52
SpillIndex() const53 std::uint32_t RegSpiller::SpillIndex() const noexcept
54 {
55 return spillIndex_;
56 }
57
SpillIndex()58 std::uint32_t &RegSpiller::SpillIndex() noexcept
59 {
60 return spillIndex_;
61 }
62
Start(CodeGen & cg)63 RegScope DynamicRegSpiller::Start(CodeGen &cg)
64 {
65 SetCodeGen(cg);
66 regEnd_ = GetCodeGen()->NextReg().GetIndex();
67 return RegScope {&cg};
68 }
69
Restore()70 RegSpiller::SpillInfo DynamicRegSpiller::Restore()
71 {
72 const auto newSpillIndex = --SpillIndex();
73 return RegSpiller::SpillInfo(VReg {VReg::REG_START - newSpillIndex}, VReg {regEnd_ - SpillIndex()});
74 }
75
Restored() const76 bool DynamicRegSpiller::Restored() const
77 {
78 return SpillIndex() == 0;
79 }
80
MoveReg(const ir::AstNode * const node,const VReg vd,const VReg vs,const bool spillMov)81 IRNode *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
Finalize()87 void DynamicRegSpiller::Finalize() noexcept
88 {
89 ES2PANDA_ASSERT(SpillIndex() == 0);
90 }
91
Start(CodeGen & cg)92 RegScope StaticRegSpiller::Start(CodeGen &cg)
93 {
94 SetCodeGen(cg);
95 return RegScope {&cg};
96 }
97
Restore()98 RegSpiller::SpillInfo StaticRegSpiller::Restore()
99 {
100 ES2PANDA_ASSERT(spills_.size() <= VReg::REG_START);
101 ES2PANDA_ASSERT(!spills_.empty());
102 const auto last = spills_.back().Reversed();
103 spills_.pop_back();
104 return last;
105 }
106
Restored() const107 bool StaticRegSpiller::Restored() const
108 {
109 return spills_.empty();
110 }
111
MoveReg(const ir::AstNode * const node,const VReg vd,const VReg vs,const bool spillMov)112 IRNode *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
Finalize()131 void StaticRegSpiller::Finalize() noexcept
132 {
133 SpillIndex() = 0;
134 }
135
136 } // namespace ark::es2panda::compiler
137