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