• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }