• 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/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