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/verifier.h"
17
18
19 #include "ecmascript/compiler/scheduler.h"
20 #include "ecmascript/compiler/gate_accessor.h"
21 #include "ecmascript/log_wrapper.h"
22
23 namespace panda::ecmascript::kungfu {
RunDataIntegrityCheck(const Circuit * circuit)24 bool Verifier::RunDataIntegrityCheck(const Circuit *circuit)
25 {
26 std::unordered_set<GateRef> gatesSet;
27 std::vector<GateRef> gatesList;
28 GateRef prevGate = sizeof(Out);
29 gatesList.push_back(prevGate);
30 gatesSet.insert(prevGate);
31 size_t out = Gate::GetGateSize(0);
32 while (true) {
33 GateRef gate = circuit->GetGateRef(
34 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
35 reinterpret_cast<const Out *>(circuit->LoadGatePtrConst(GateRef(out)))->GetGateConst());
36 if (gate < prevGate + static_cast<int64_t>(sizeof(Gate)) ||
37 gate >= static_cast<int64_t>(circuit->GetCircuitDataSize())) {
38 LOG_COMPILER(ERROR) << "[Verifier][Error] Circuit data is corrupted (bad next gate)";
39 LOG_COMPILER(ERROR) << "at: " << std::dec << gate;
40 return false;
41 }
42 gatesList.push_back(gate);
43 gatesSet.insert(gate);
44 prevGate = gate;
45 out += Gate::GetGateSize(
46 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
47 reinterpret_cast<const Out *>(circuit->LoadGatePtrConst(GateRef(out)))->GetIndex() + 1);
48 if (out == circuit->GetCircuitDataSize()) {
49 break;
50 }
51 if (out > circuit->GetCircuitDataSize() || out < 0) {
52 LOG_COMPILER(ERROR) << "[Verifier][Error] Circuit data is corrupted (out of bound access)";
53 LOG_COMPILER(ERROR) << "at: " << std::dec << out;
54 return false;
55 }
56 }
57 for (const auto &gate : gatesList) {
58 for (size_t idx = 0; idx < circuit->LoadGatePtrConst(gate)->GetNumIns(); idx++) {
59 const In *curIn = circuit->LoadGatePtrConst(gate)->GetInConst(idx);
60 if (!(circuit->GetSpaceDataStartPtrConst() < curIn && curIn < circuit->GetSpaceDataEndPtrConst())) {
61 LOG_COMPILER(ERROR) << "[Verifier][Error] Circuit data is corrupted (corrupted in list)";
62 LOG_COMPILER(ERROR) << "id: " << std::dec << circuit->GetId(gate);
63 return false;
64 }
65 if (gatesSet.count(circuit->GetGateRef(curIn->GetGateConst())) == 0) {
66 LOG_COMPILER(ERROR) << "[Verifier][Error] Circuit data is corrupted (invalid in address)";
67 LOG_COMPILER(ERROR) << "id: " << std::dec << circuit->GetId(gate);
68 return false;
69 }
70 }
71 {
72 const Gate *curGate = circuit->LoadGatePtrConst(gate);
73 if (!curGate->IsFirstOutNull()) {
74 const Out *curOut = curGate->GetFirstOutConst();
75 if (!(circuit->GetSpaceDataStartPtrConst() < curOut && curOut < circuit->GetSpaceDataEndPtrConst())) {
76 LOG_COMPILER(ERROR) << "[Verifier][Error] Circuit data is corrupted (corrupted out list)";
77 LOG_COMPILER(ERROR) << "id: " << std::dec << circuit->GetId(gate);
78 return false;
79 }
80 if (gatesSet.count(circuit->GetGateRef(curOut->GetGateConst())) == 0) {
81 LOG_COMPILER(ERROR) << "[Verifier][Error] Circuit data is corrupted (invalid out address)";
82 LOG_COMPILER(ERROR) << "id: " << std::dec << circuit->GetId(gate);
83 return false;
84 }
85 while (!curOut->IsNextOutNull()) {
86 curOut = curOut->GetNextOutConst();
87 if (!(circuit->GetSpaceDataStartPtrConst() < curOut &&
88 curOut < circuit->GetSpaceDataEndPtrConst())) {
89 LOG_COMPILER(ERROR) << "[Verifier][Error] Circuit data is corrupted (corrupted out list)";
90 LOG_COMPILER(ERROR) << "id: " << std::dec << circuit->GetId(gate);
91 return false;
92 }
93 if (gatesSet.count(circuit->GetGateRef(curOut->GetGateConst())) == 0) {
94 LOG_COMPILER(ERROR) << "[Verifier][Error] Circuit data is corrupted (invalid out address)";
95 LOG_COMPILER(ERROR) << "id: " << std::dec << circuit->GetId(gate);
96 return false;
97 }
98 }
99 }
100 }
101 }
102 return true;
103 }
104
RunStateGatesCheck(const Circuit * circuit,const std::vector<GateRef> & bbGatesList,const std::string & methodName)105 bool Verifier::RunStateGatesCheck(const Circuit *circuit, const std::vector<GateRef> &bbGatesList,
106 const std::string& methodName)
107 {
108 for (const auto &bbGate : bbGatesList) {
109 circuit->Verify(bbGate, methodName);
110 }
111 return true;
112 }
113
RunCFGSoundnessCheck(const Circuit * circuit,const std::vector<GateRef> & bbGatesList,const std::unordered_map<GateRef,size_t> & bbGatesAddrToIdx)114 bool Verifier::RunCFGSoundnessCheck(const Circuit *circuit, const std::vector<GateRef> &bbGatesList,
115 const std::unordered_map<GateRef, size_t> &bbGatesAddrToIdx)
116 {
117 for (const auto &bbGate : bbGatesList) {
118 GateAccessor gateAcc(const_cast<Circuit *>(circuit));
119 for (const auto &predGate : gateAcc.ConstIns(bbGate)) {
120 if (gateAcc.IsState(predGate) || circuit->GetOpCode(predGate) == OpCode::STATE_ENTRY) {
121 if (bbGatesAddrToIdx.count(predGate) == 0) {
122 LOG_COMPILER(ERROR) << "[Verifier][Error] CFG is not sound";
123 LOG_COMPILER(ERROR) << "Proof:";
124 LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(predGate) << ") is pred of "
125 << "(id=" << circuit->GetId(bbGate) << ")";
126 LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(bbGate) << ") is reachable from entry";
127 LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(predGate) << ") is unreachable from entry";
128 return false;
129 }
130 }
131 }
132 }
133 return true;
134 }
135
RunCFGIsDAGCheck(const Circuit * circuit)136 bool Verifier::RunCFGIsDAGCheck(const Circuit *circuit)
137 {
138 circuit->AdvanceTime();
139 struct DFSState {
140 GateRef cur;
141 GateAccessor::ConstUseWrapper uses;
142 GateAccessor::ConstUseIterator use;
143 };
144 std::stack<DFSState> dfsStack;
145 GateAccessor gateAcc(const_cast<Circuit *>(circuit));
146 auto root = gateAcc.GetStateRoot();
147 gateAcc.SetVisited(root);
148 auto rootUses = gateAcc.ConstUses(root);
149 dfsStack.push({root, rootUses, rootUses.begin()});
150 while (!dfsStack.empty()) {
151 auto &curState = dfsStack.top();
152 auto &cur = curState.cur;
153 auto &uses = curState.uses;
154 auto &use = curState.use;
155 if (use == uses.end()) {
156 gateAcc.SetFinished(cur);
157 dfsStack.pop();
158 continue;
159 }
160 if (gateAcc.IsState(*use) && use.GetIndex() < gateAcc.GetStateCount(*use)) {
161 if (gateAcc.IsVisited(*use)) {
162 LOG_COMPILER(ERROR) <<
163 "[Verifier][Error] CFG without loop back edges is not a directed acyclic graph";
164 LOG_COMPILER(ERROR) << "Proof:";
165 LOG_COMPILER(ERROR) << "(id=" << gateAcc.GetId(*use) << ") is succ of "
166 << "(id=" << gateAcc.GetId(cur) << ")";
167 LOG_COMPILER(ERROR) << "(id=" << gateAcc.GetId(cur) << ") is reachable from "
168 << "(id=" << gateAcc.GetId(*use) << ") without loop back edges";
169 return false;
170 }
171 if (gateAcc.IsFinished(*use) || gateAcc.IsLoopBack(*use)) {
172 ++use;
173 continue;
174 }
175 gateAcc.SetVisited(*use);
176 auto newUses = gateAcc.ConstUses(*use);
177 dfsStack.push({*use, newUses, newUses.begin()});
178 }
179 ++use;
180 }
181 return true;
182 }
183
RunCFGReducibilityCheck(const Circuit * circuit,const std::vector<GateRef> & bbGatesList,const std::unordered_map<GateRef,size_t> & bbGatesAddrToIdx,const std::function<bool (size_t,size_t)> & isAncestor)184 bool Verifier::RunCFGReducibilityCheck(const Circuit *circuit, const std::vector<GateRef> &bbGatesList,
185 const std::unordered_map<GateRef, size_t> &bbGatesAddrToIdx,
186 const std::function<bool(size_t, size_t)> &isAncestor)
187 {
188 for (const auto &curGate : bbGatesList) {
189 if (circuit->GetOpCode(curGate) == OpCode::LOOP_BACK) {
190 GateAccessor gateAcc(const_cast<Circuit *>(circuit));
191 auto uses = gateAcc.ConstUses(curGate);
192 for (auto use = uses.begin(); use != uses.end(); use++) {
193 if (use.GetIndex() >= circuit->LoadGatePtrConst(*use)->GetStateCount()) {
194 continue;
195 }
196 ASSERT(gateAcc.IsState(*use));
197 bool isDom = isAncestor(bbGatesAddrToIdx.at(*use), bbGatesAddrToIdx.at(curGate));
198 if (!isDom) {
199 LOG_COMPILER(ERROR) << "[Verifier][Error] CFG is not reducible";
200 LOG_COMPILER(ERROR) << "Proof:";
201 LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(*use) << ") is loop back succ of "
202 << "(id=" << circuit->GetId(curGate) << ")";
203 LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(*use) << ") does not dominate "
204 << "(id=" << circuit->GetId(curGate) << ")";
205 return false;
206 }
207 }
208 }
209 }
210 return true;
211 }
212
RunFixedGatesCheck(const Circuit * circuit,const std::vector<GateRef> & fixedGatesList)213 bool Verifier::RunFixedGatesCheck(const Circuit *circuit, const std::vector<GateRef> &fixedGatesList)
214 {
215 for (const auto &fixedGate : fixedGatesList) {
216 circuit->Verify(fixedGate);
217 }
218 return true;
219 }
220
RunFixedGatesRelationsCheck(const Circuit * circuit,const std::vector<GateRef> & fixedGatesList,const std::unordered_map<GateRef,size_t> & bbGatesAddrToIdx,const std::function<bool (size_t,size_t)> & isAncestor)221 bool Verifier::RunFixedGatesRelationsCheck(const Circuit *circuit, const std::vector<GateRef> &fixedGatesList,
222 const std::unordered_map<GateRef, size_t> &bbGatesAddrToIdx,
223 const std::function<bool(size_t, size_t)> &isAncestor)
224 {
225 ConstGateAccessor ac(circuit);
226 for (const auto &fixedGate : fixedGatesList) {
227 size_t cnt = 0;
228 auto ins = ac.Ins(fixedGate);
229 for (auto i = ins.begin(); i != ins.end(); i++) {
230 GateRef predGate = *i;
231 if (ac.IsFixed(predGate) &&
232 // 2: Judge equality
233 (circuit->GetOpCode(circuit->GetIn(fixedGate, 0)) == OpCode::LOOP_BEGIN && cnt == 2)) {
234 ASSERT(cnt > 0);
235 auto a = bbGatesAddrToIdx.at(circuit->GetIn(predGate, 0));
236 auto b = bbGatesAddrToIdx.at(circuit->GetIn(circuit->GetIn(fixedGate, 0),
237 static_cast<size_t>(cnt - 1)));
238 if (!isAncestor(a, b)) {
239 LOG_COMPILER(ERROR) << "[Verifier][Error] Fixed gates relationship is not consistent";
240 LOG_COMPILER(ERROR) << "Proof:";
241 LOG_COMPILER(ERROR) << "Fixed gate (id="
242 << circuit->GetId(predGate)
243 << ") is pred of fixed gate (id="
244 << circuit->GetId(fixedGate) << ")";
245 LOG_COMPILER(ERROR) << "BB_" << bbGatesAddrToIdx.at(circuit->GetIn(predGate, 0))
246 << " does not dominate BB_"
247 << bbGatesAddrToIdx.at(circuit->GetIn(circuit->GetIn(fixedGate, 0),
248 static_cast<size_t>(cnt - 1)));
249 return false;
250 }
251 }
252 cnt++;
253 }
254 }
255 return true;
256 }
257
RunFlowCyclesFind(const Circuit * circuit,std::vector<GateRef> * schedulableGatesListPtr,const std::vector<GateRef> & bbGatesList,const std::vector<GateRef> & fixedGatesList)258 bool Verifier::RunFlowCyclesFind(const Circuit *circuit, std::vector<GateRef> *schedulableGatesListPtr,
259 const std::vector<GateRef> &bbGatesList, const std::vector<GateRef> &fixedGatesList)
260 {
261 circuit->AdvanceTime();
262 ConstGateAccessor ac(circuit);
263 std::vector<GateRef> startGateList;
264 for (const auto &gate : bbGatesList) {
265 auto ins = ac.Ins(gate);
266 for (auto i = ins.begin(); i != ins.end(); i++) {
267 GateRef predGate = *i;
268 if (ac.IsSchedulable(predGate)) {
269 if (circuit->GetMark(predGate) == MarkCode::NO_MARK) {
270 startGateList.push_back(predGate);
271 circuit->SetMark(predGate, MarkCode::VISITED);
272 }
273 }
274 }
275 }
276 for (const auto &gate : fixedGatesList) {
277 auto ins = ac.Ins(gate);
278 for (auto i = ins.begin(); i != ins.end(); i++) {
279 GateRef predGate = *i;
280 if (ac.IsSchedulable(predGate)) {
281 if (circuit->GetMark(predGate) == MarkCode::NO_MARK) {
282 startGateList.push_back(predGate);
283 circuit->SetMark(predGate, MarkCode::VISITED);
284 }
285 }
286 }
287 }
288 circuit->AdvanceTime();
289 GateAccessor gateAcc(const_cast<Circuit *>(circuit));
290 std::vector<GateRef> cycleGatesList;
291 GateRef meet = -1;
292 struct DFSState {
293 GateRef cur;
294 size_t numIns;
295 size_t idx;
296 };
297 for (const auto &startGate : startGateList) {
298 if (!gateAcc.IsNotMarked(startGate)) {
299 continue;
300 }
301 std::stack<DFSState> dfsStack;
302 size_t startNumIns = gateAcc.GetNumIns(startGate);
303 dfsStack.push({startGate, startNumIns, 0});
304 gateAcc.SetVisited(startGate);
305 schedulableGatesListPtr->push_back(startGate);
306 while (!dfsStack.empty()) {
307 auto &curState = dfsStack.top();
308 auto &cur = curState.cur;
309 auto &numIns = curState.numIns;
310 auto &idx = curState.idx;
311 if (idx == numIns) {
312 gateAcc.SetFinished(cur);
313 dfsStack.pop();
314 continue;
315 }
316 const auto prev = gateAcc.GetIn(cur, idx);
317 if (gateAcc.IsSchedulable(prev)) {
318 if (gateAcc.IsVisited(prev)) {
319 LOG_COMPILER(ERROR) <<
320 "[Verifier][Error] Found a data or depend flow cycle without passing selectors";
321 LOG_COMPILER(ERROR) << "Proof:";
322 LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(prev) << ") is prev of "
323 << "(id=" << circuit->GetId(cur) << ")";
324 LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(prev) << ") is reachable from "
325 << "(id=" << circuit->GetId(cur) << ") without passing selectors";
326 meet = prev;
327 break;
328 }
329 if (!gateAcc.IsFinished(prev)) {
330 size_t newNumIns = gateAcc.GetNumIns(prev);
331 dfsStack.push({prev, newNumIns, 0});
332 gateAcc.SetVisited(prev);
333 schedulableGatesListPtr->push_back(prev);
334 }
335 }
336 idx++;
337 }
338 if (meet != -1) {
339 while (dfsStack.top().cur != meet) {
340 cycleGatesList.push_back(dfsStack.top().cur);
341 dfsStack.pop();
342 }
343 cycleGatesList.push_back(meet);
344 LOG_COMPILER(ERROR) << "Path:";
345 for (const auto &cycleGate : cycleGatesList) {
346 gateAcc.Print(cycleGate);
347 }
348 return false;
349 }
350 }
351 return true;
352 }
353
RunSchedulableGatesCheck(const Circuit * circuit,const std::vector<GateRef> & schedulableGatesList)354 bool Verifier::RunSchedulableGatesCheck(const Circuit *circuit, const std::vector<GateRef> &schedulableGatesList)
355 {
356 for (const auto &schedulableGate : schedulableGatesList) {
357 circuit->Verify(schedulableGate);
358 }
359 return true;
360 }
361
RunPrologGatesCheck(const Circuit * circuit,const std::vector<GateRef> & schedulableGatesList)362 bool Verifier::RunPrologGatesCheck(const Circuit *circuit, const std::vector<GateRef> &schedulableGatesList)
363 {
364 ConstGateAccessor ac(circuit);
365 for (const auto &schedulableGate : schedulableGatesList) {
366 auto ins = ac.Ins(schedulableGate);
367 for (auto i = ins.begin(); i != ins.end(); i++) {
368 GateRef r = *i;
369 if (ac.IsProlog(r)) {
370 circuit->Verify(r);
371 }
372 }
373 }
374 return true;
375 }
376
RunSchedulingBoundsCheck(const Circuit * circuit,const std::vector<GateRef> & schedulableGatesList,const std::unordered_map<GateRef,size_t> & bbGatesAddrToIdx,const std::function<bool (size_t,size_t)> & isAncestor,const std::function<size_t (size_t,size_t)> & lowestCommonAncestor)377 bool Verifier::RunSchedulingBoundsCheck(const Circuit *circuit,
378 const std::vector<GateRef> &schedulableGatesList,
379 const std::unordered_map<GateRef, size_t> &bbGatesAddrToIdx,
380 const std::function<bool(size_t, size_t)> &isAncestor,
381 const std::function<size_t(size_t, size_t)> &lowestCommonAncestor)
382 {
383 // check existence of scheduling upper bound
384 std::unordered_map<GateRef, size_t> upperBound;
385 {
386 if (!Scheduler::CalculateSchedulingUpperBound(circuit, bbGatesAddrToIdx, isAncestor,
387 schedulableGatesList, upperBound)) {
388 return false;
389 }
390 }
391 // check existence of scheduling lower bound
392 std::unordered_map<GateRef, size_t> lowerBound;
393 {
394 Scheduler::CalculateSchedulingLowerBound(circuit, bbGatesAddrToIdx, lowestCommonAncestor, lowerBound);
395 }
396 // check consistency of lower bound and upper bound
397 {
398 ASSERT(upperBound.size() == lowerBound.size());
399 for (const auto &item : lowerBound) {
400 if (!isAncestor(upperBound.at(item.first), lowerBound.at(item.first))) {
401 LOG_COMPILER(ERROR) << "[Verifier][Error] Bounds of gate (id="
402 << circuit->GetId(item.first) << ") is not consistent";
403 LOG_COMPILER(ERROR) << "Proof:";
404 LOG_COMPILER(ERROR) << "Upper bound is BB_" << upperBound.at(item.first);
405 LOG_COMPILER(ERROR) << "Lower bound is BB_" << lowerBound.at(item.first);
406 return false;
407 }
408 }
409 }
410 return true;
411 }
412
FindFixedGates(const Circuit * circuit,const std::vector<GateRef> & bbGatesList,std::vector<GateRef> & fixedGatesList)413 void Verifier::FindFixedGates(const Circuit *circuit, const std::vector<GateRef> &bbGatesList,
414 std::vector<GateRef> &fixedGatesList)
415 {
416 ConstGateAccessor ac(circuit);
417 for (const auto &bbGate : bbGatesList) {
418 for (const auto &succGate : circuit->GetOutVector(bbGate)) {
419 if (ac.IsFixed(succGate)) {
420 fixedGatesList.push_back(succGate);
421 }
422 }
423 }
424 }
425
RunFlowCyclesFind(const Circuit * circuit)426 bool Verifier::RunFlowCyclesFind(const Circuit* circuit)
427 {
428 GateAccessor acc(const_cast<Circuit *>(circuit));
429 circuit->AdvanceTime();
430 struct DFSStack {
431 GateRef gate;
432 GateAccessor::UseIterator it;
433 GateAccessor::UseIterator end;
434 };
435 std::stack<DFSStack> st;
436 auto root = acc.GetCircuitRoot();
437 auto rootUse = acc.Uses(root);
438 st.push({root, rootUse.begin(), rootUse.end()});
439 acc.SetVisited(root);
440 while (!st.empty()) {
441 auto& cur = st.top();
442 if (cur.it == cur.end) {
443 st.pop();
444 acc.SetFinished(cur.gate);
445 continue;
446 }
447 auto succ = *cur.it;
448 if (acc.IsLoopBackUse(cur.gate, cur.it)) {
449 cur.it++;
450 continue;
451 }
452 if (acc.IsNotMarked(succ)) {
453 auto succUse = acc.Uses(succ);
454 st.push({succ, succUse.begin(), succUse.end()});
455 acc.SetVisited(succ);
456 } else if (acc.IsVisited(succ)) {
457 LOG_COMPILER(ERROR) << "====================== Cycle Found ======================";
458 std::string log = "";
459 while (st.top().gate != succ) {
460 log += std::to_string(acc.GetId(st.top().gate)) + " < ";
461 st.pop();
462 }
463 log += std::to_string(acc.GetId(st.top().gate));
464 LOG_COMPILER(ERROR) << log;
465 return true;
466 }
467 cur.it++;
468 }
469 return false;
470 }
471
Run(const Circuit * circuit,const std::string & methodName,bool enableLog)472 bool Verifier::Run(const Circuit *circuit, const std::string& methodName, bool enableLog)
473 {
474 if (!RunDataIntegrityCheck(circuit)) {
475 if (enableLog) {
476 LOG_COMPILER(ERROR) << "[Verifier][Fail] Circuit data integrity verifier failed, " << methodName;
477 }
478 return false;
479 }
480 std::vector<GateRef> bbGatesList;
481 std::unordered_map<GateRef, size_t> bbGatesAddrToIdx;
482 std::vector<size_t> immDom;
483 Scheduler::CalculateDominatorTree(circuit, bbGatesList, bbGatesAddrToIdx, immDom);
484 if (!RunStateGatesCheck(circuit, bbGatesList, methodName)) {
485 if (enableLog) {
486 LOG_COMPILER(ERROR) << "[Verifier][Fail] RunStateGatesCheck failed";
487 }
488 return false;
489 }
490 if (!RunCFGSoundnessCheck(circuit, bbGatesList, bbGatesAddrToIdx)) {
491 if (enableLog) {
492 LOG_COMPILER(ERROR) << "[Verifier][Fail] RunCFGSoundnessCheck failed";
493 }
494 return false;
495 }
496 if (!RunCFGIsDAGCheck(circuit)) {
497 if (enableLog) {
498 LOG_COMPILER(ERROR) << "[Verifier][Fail] RunCFGIsDAGCheck failed";
499 }
500 return false;
501 }
502 std::vector<std::vector<size_t>> sonList(bbGatesList.size());
503 for (size_t idx = 1; idx < immDom.size(); idx++) {
504 sonList[immDom[idx]].push_back(idx);
505 }
506 const size_t sizeLog = std::ceil(std::log2(static_cast<double>(bbGatesList.size())) + 1);
507 std::vector<size_t> timeIn(bbGatesList.size());
508 std::vector<size_t> timeOut(bbGatesList.size());
509 std::vector<std::vector<size_t>> jumpUp;
510 jumpUp.assign(bbGatesList.size(), std::vector<size_t>(sizeLog + 1));
511 {
512 size_t timestamp = 0;
513 struct DFSState {
514 size_t cur;
515 std::vector<size_t> &succList;
516 size_t idx;
517 };
518 std::stack<DFSState> dfsStack;
519 size_t root = 0;
520 dfsStack.push({root, sonList[root], 0});
521 timeIn[root] = timestamp++;
522 jumpUp[root][0] = root;
523 for (size_t stepSize = 1; stepSize <= sizeLog; stepSize++) {
524 auto jumpUpHalf = jumpUp[root][stepSize - 1];
525 jumpUp[root][stepSize] = jumpUp[jumpUpHalf][stepSize - 1];
526 }
527 while (!dfsStack.empty()) {
528 auto &curState = dfsStack.top();
529 auto &cur = curState.cur;
530 auto &succList = curState.succList;
531 auto &idx = curState.idx;
532 if (idx == succList.size()) {
533 timeOut[cur] = timestamp++;
534 dfsStack.pop();
535 continue;
536 }
537 const auto &succ = succList[idx];
538 dfsStack.push({succ, sonList[succ], 0});
539 timeIn[succ] = timestamp++;
540 jumpUp[succ][0] = cur;
541 for (size_t stepSize = 1; stepSize <= sizeLog; stepSize++) {
542 auto jumpUpHalf = jumpUp[succ][stepSize - 1];
543 jumpUp[succ][stepSize] = jumpUp[jumpUpHalf][stepSize - 1];
544 }
545 idx++;
546 }
547 }
548 auto isAncestor = [timeIn, timeOut](size_t nodeA, size_t nodeB) -> bool {
549 return timeIn[nodeA] <= timeIn[nodeB] && timeOut[nodeA] >= timeOut[nodeB];
550 };
551 auto lowestCommonAncestor = [&](size_t nodeA, size_t nodeB) -> size_t {
552 if (isAncestor(nodeA, nodeB)) {
553 return nodeA;
554 }
555 if (isAncestor(nodeB, nodeA)) {
556 return nodeB;
557 }
558 for (size_t stepSize = sizeLog + 1; stepSize > 0; stepSize--) {
559 if (!isAncestor(jumpUp[nodeA][stepSize - 1], nodeB)) {
560 nodeA = jumpUp[nodeA][stepSize - 1];
561 }
562 }
563 return jumpUp[nodeA][0];
564 };
565 if (!RunCFGReducibilityCheck(circuit, bbGatesList, bbGatesAddrToIdx, isAncestor)) {
566 if (enableLog) {
567 LOG_COMPILER(ERROR) << "[Verifier][Fail] RunCFGReducibilityCheck failed";
568 }
569 return false;
570 }
571 std::vector<GateRef> fixedGatesList;
572 FindFixedGates(circuit, bbGatesList, fixedGatesList);
573 if (!RunFixedGatesCheck(circuit, fixedGatesList)) {
574 if (enableLog) {
575 LOG_COMPILER(ERROR) << "[Verifier][Fail] RunFixedGatesCheck failed";
576 }
577 return false;
578 }
579 if (!RunFixedGatesRelationsCheck(circuit, fixedGatesList, bbGatesAddrToIdx, isAncestor)) {
580 if (enableLog) {
581 LOG_COMPILER(ERROR) << "[Verifier][Fail] RunFixedGatesRelationsCheck failed";
582 }
583 return false;
584 }
585 std::vector<GateRef> schedulableGatesList;
586 if (!RunFlowCyclesFind(circuit, &schedulableGatesList, bbGatesList, fixedGatesList)) {
587 if (enableLog) {
588 LOG_COMPILER(ERROR) << "[Verifier][Fail] RunFlowCyclesFind failed";
589 }
590 return false;
591 }
592 if (!RunSchedulableGatesCheck(circuit, fixedGatesList)) {
593 if (enableLog) {
594 LOG_COMPILER(ERROR) << "[Verifier][Fail] RunSchedulableGatesCheck failed";
595 }
596 return false;
597 }
598 if (!RunPrologGatesCheck(circuit, fixedGatesList)) {
599 if (enableLog) {
600 LOG_COMPILER(ERROR) << "[Verifier][Fail] RunPrologGatesCheck failed";
601 }
602 return false;
603 }
604 if (!RunSchedulingBoundsCheck(circuit, schedulableGatesList, bbGatesAddrToIdx, isAncestor, lowestCommonAncestor)) {
605 if (enableLog) {
606 LOG_COMPILER(ERROR) << "[Verifier][Fail] RunSchedulingBoundsCheck failed";
607 }
608 return false;
609 }
610
611 if (enableLog) {
612 LOG_COMPILER(INFO) << "[Verifier][Pass] Verifier success";
613 }
614
615 return true;
616 }
617 } // namespace panda::ecmascript::kungfu
618