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