1 /*
2 * Copyright (c) 2021 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 "ecmascript/compiler/circuit_builder_helper.h"
17
18 namespace panda::ecmascript::kungfu {
19
Environment(size_t arguments,CircuitBuilder * builder)20 Environment::Environment(size_t arguments, CircuitBuilder *builder)
21 : circuit_(builder->GetCircuit()), circuitBuilder_(builder), arguments_(arguments)
22 {
23 circuitBuilder_->SetEnvironment(this);
24 SetCompilationConfig(circuitBuilder_->GetCompilationConfig());
25 for (size_t i = 0; i < arguments; i++) {
26 arguments_[i] = circuitBuilder_->Arguments(i);
27 }
28 entry_ = Label(NewLabel(this, circuit_->GetStateRoot()));
29 currentLabel_ = &entry_;
30 currentLabel_->Seal();
31 auto depend_entry = circuit_->GetDependRoot();
32 currentLabel_->SetDepend(depend_entry);
33 }
34
Environment(GateRef hir,Circuit * circuit,CircuitBuilder * builder)35 Environment::Environment(GateRef hir, Circuit *circuit, CircuitBuilder *builder)
36 : circuit_(circuit), circuitBuilder_(builder)
37 {
38 circuitBuilder_->SetEnvironment(this);
39 SetCompilationConfig(circuitBuilder_->GetCompilationConfig());
40 GateAccessor acc(circuit);
41 entry_ = Label(NewLabel(this, acc.GetIn(hir, 0)));
42 currentLabel_ = &entry_;
43 currentLabel_->Seal();
44 auto dependEntry = acc.GetDep(hir);
45 currentLabel_->SetDepend(dependEntry);
46 for (size_t i = 2; i < acc.GetNumIns(hir); i++) {
47 inputList_.emplace_back(acc.GetIn(hir, i));
48 }
49 }
50
Environment(GateRef stateEntry,GateRef dependEntry,const std::initializer_list<GateRef> & args,Circuit * circuit,CircuitBuilder * builder)51 Environment::Environment(GateRef stateEntry, GateRef dependEntry,
52 const std::initializer_list<GateRef>& args, Circuit *circuit, CircuitBuilder *builder)
53 : circuit_(circuit), circuitBuilder_(builder)
54 {
55 circuitBuilder_->SetEnvironment(this);
56 SetCompilationConfig(circuitBuilder_->GetCompilationConfig());
57 entry_ = Label(NewLabel(this, stateEntry));
58 currentLabel_ = &entry_;
59 currentLabel_->Seal();
60 currentLabel_->SetDepend(dependEntry);
61 for (auto in : args) {
62 inputList_.emplace_back(in);
63 }
64 }
65
~Environment()66 Environment::~Environment()
67 {
68 circuitBuilder_->SetEnvironment(nullptr);
69 for (auto label : rawLabels_) {
70 delete label;
71 }
72 }
73
Label(Environment * env)74 Label::Label(Environment *env)
75 {
76 impl_ = env->NewLabel(env);
77 }
78
Label(CircuitBuilder * cirBuilder)79 Label::Label(CircuitBuilder *cirBuilder)
80 {
81 auto env = cirBuilder->GetCurrentEnvironment();
82 impl_ = env->NewLabel(env);
83 }
84
Seal()85 void Label::LabelImpl::Seal()
86 {
87 for (auto &[variable, gate] : incompletePhis_) {
88 variable->AddPhiOperand(gate);
89 }
90 isSealed_ = true;
91 }
92
WriteVariable(Variable * var,GateRef value)93 void Label::LabelImpl::WriteVariable(Variable *var, GateRef value)
94 {
95 valueMap_[var] = value;
96 }
97
ReadVariable(Variable * var)98 GateRef Label::LabelImpl::ReadVariable(Variable *var)
99 {
100 if (valueMap_.find(var) != valueMap_.end()) {
101 auto result = valueMap_.at(var);
102 GateAccessor acc(env_->GetCircuit());
103 if (!acc.IsNop(result)) {
104 return result;
105 }
106 }
107 return ReadVariableRecursive(var);
108 }
109
ReadVariableRecursive(Variable * var)110 GateRef Label::LabelImpl::ReadVariableRecursive(Variable *var)
111 {
112 GateRef val;
113 MachineType machineType = CircuitBuilder::GetMachineTypeFromVariableType(var->Type());
114 if (!IsSealed()) {
115 // only loopheader gate will be not sealed
116 int valueCounts = static_cast<int>(this->predecessors_.size()) + 1;
117 if (machineType == MachineType::NOVALUE) {
118 val = env_->GetBuilder()->Selector(OpCode::DEPEND_SELECTOR,
119 predeControl_, {}, valueCounts, var->Type());
120 } else {
121 val = env_->GetBuilder()->Selector(OpCode::VALUE_SELECTOR,
122 machineType, predeControl_, {}, valueCounts, var->Type());
123 }
124 env_->AddSelectorToLabel(val, Label(this));
125 incompletePhis_[var] = val;
126 } else if (predecessors_.size() == 1) {
127 val = predecessors_[0]->ReadVariable(var);
128 } else {
129 if (machineType == MachineType::NOVALUE) {
130 val = env_->GetBuilder()->Selector(OpCode::DEPEND_SELECTOR,
131 predeControl_, {}, this->predecessors_.size(), var->Type());
132 } else {
133 val = env_->GetBuilder()->Selector(OpCode::VALUE_SELECTOR, machineType,
134 predeControl_, {}, this->predecessors_.size(), var->Type());
135 }
136 env_->AddSelectorToLabel(val, Label(this));
137 WriteVariable(var, val);
138 val = var->AddPhiOperand(val);
139 }
140 WriteVariable(var, val);
141 return val;
142 }
143
Bind()144 void Label::LabelImpl::Bind()
145 {
146 ASSERT(!predecessors_.empty());
147 if (IsLoopHead()) {
148 // 2 means input number of depend selector gate
149 loopDepend_ = env_->GetBuilder()->Selector(OpCode::DEPEND_SELECTOR, predeControl_, {}, 2);
150 GateAccessor(env_->GetCircuit()).NewIn(loopDepend_, 1, predecessors_[0]->GetDepend());
151 depend_ = loopDepend_;
152 }
153 if (IsNeedSeal()) {
154 Seal();
155 MergeAllControl();
156 MergeAllDepend();
157 }
158 }
159
MergeAllControl()160 void Label::LabelImpl::MergeAllControl()
161 {
162 if (predecessors_.size() < 2) { // 2 : Loop Head only support two predecessors_
163 return;
164 }
165
166 if (IsLoopHead()) {
167 ASSERT(predecessors_.size() == 2); // 2 : Loop Head only support two predecessors_
168 ASSERT(otherPredeControls_.size() == 1);
169 GateAccessor(env_->GetCircuit()).NewIn(predeControl_, 1, otherPredeControls_[0]);
170 return;
171 }
172
173 // merge all control of predecessors_
174 std::vector<GateRef> inGates(predecessors_.size());
175 size_t i = 0;
176 ASSERT(predeControl_ != -1);
177 ASSERT((otherPredeControls_.size() + 1) == predecessors_.size());
178 inGates[i++] = predeControl_;
179 for (auto in : otherPredeControls_) {
180 inGates[i++] = in;
181 }
182
183 GateRef merge = env_->GetBuilder()->Merge(inGates);
184 predeControl_ = merge;
185 control_ = merge;
186 }
187
MergeAllDepend()188 void Label::LabelImpl::MergeAllDepend()
189 {
190 if (predecessors_.size() < 2) { // 2 : Loop Head only support two predecessors_
191 depend_ = predecessors_[0]->GetDepend();
192 if (IsControlCase()) {
193 // Add depend_relay to current label
194 depend_ = env_->GetBuilder()->DependRelay(predeControl_, depend_);
195 }
196 return;
197 }
198 if (IsLoopHead()) {
199 ASSERT(predecessors_.size() == 2); // 2 : Loop Head only support two predecessors_
200 // Add loop depend to in of depend_seclector
201 ASSERT(loopDepend_ != -1);
202 // 2 mean 3rd input gate for loopDepend_(depend_selector)
203 GateAccessor(env_->GetCircuit()).NewIn(loopDepend_, 2, predecessors_[1]->GetDepend());
204 return;
205 }
206
207 // Merge all depends to depend_seclector
208 std::vector<GateRef> dependsList;
209 for (auto prede : this->GetPredecessors()) {
210 dependsList.push_back(prede->GetDepend());
211 }
212 depend_ = env_->GetBuilder()->Selector(OpCode::DEPEND_SELECTOR,
213 predeControl_, dependsList, dependsList.size());
214 }
215
AppendPredecessor(Label::LabelImpl * predecessor)216 void Label::LabelImpl::AppendPredecessor(Label::LabelImpl *predecessor)
217 {
218 if (predecessor != nullptr) {
219 predecessors_.push_back(predecessor);
220 }
221 }
222
IsNeedSeal() const223 bool Label::LabelImpl::IsNeedSeal() const
224 {
225 auto stateCount = GateAccessor(env_->GetCircuit()).GetStateCount(predeControl_);
226 return predecessors_.size() >= stateCount;
227 }
228
IsLoopHead() const229 bool Label::LabelImpl::IsLoopHead() const
230 {
231 return GateAccessor(env_->GetCircuit()).IsLoopHead(predeControl_);
232 }
233
IsControlCase() const234 bool Label::LabelImpl::IsControlCase() const
235 {
236 return GateAccessor(env_->GetCircuit()).IsControlCase(predeControl_);
237 }
238 }