2021-09-04 08:06:49 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "ecmascript/compiler/verifier.h"
|
|
|
|
|
2021-09-11 03:05:55 +00:00
|
|
|
#include <cmath>
|
2022-08-17 02:09:16 +00:00
|
|
|
#include <stack>
|
2023-04-28 08:37:17 +00:00
|
|
|
#include <string>
|
2021-09-04 08:06:49 +00:00
|
|
|
#include <unordered_set>
|
2023-04-28 08:37:17 +00:00
|
|
|
#include <vector>
|
2021-09-04 08:06:49 +00:00
|
|
|
|
2023-04-28 08:37:17 +00:00
|
|
|
#include "ecmascript/compiler/gate_meta_data.h"
|
2021-09-04 08:06:49 +00:00
|
|
|
#include "ecmascript/compiler/scheduler.h"
|
2022-03-02 08:06:19 +00:00
|
|
|
#include "ecmascript/compiler/gate_accessor.h"
|
2022-04-14 08:14:34 +00:00
|
|
|
#include "ecmascript/ecma_macros.h"
|
2023-04-28 08:37:17 +00:00
|
|
|
#include "ecmascript/log_wrapper.h"
|
2021-09-04 08:06:49 +00:00
|
|
|
|
2021-12-23 06:55:22 +00:00
|
|
|
namespace panda::ecmascript::kungfu {
|
2021-09-04 08:06:49 +00:00
|
|
|
bool Verifier::RunDataIntegrityCheck(const Circuit *circuit)
|
|
|
|
{
|
2021-12-17 09:18:10 +00:00
|
|
|
std::unordered_set<GateRef> gatesSet;
|
|
|
|
std::vector<GateRef> gatesList;
|
2022-11-29 09:25:20 +00:00
|
|
|
GateRef prevGate = sizeof(Out);
|
|
|
|
gatesList.push_back(prevGate);
|
|
|
|
gatesSet.insert(prevGate);
|
|
|
|
size_t out = Gate::GetGateSize(0);
|
2021-09-04 08:06:49 +00:00
|
|
|
while (true) {
|
2022-07-18 11:54:48 +00:00
|
|
|
GateRef gate = circuit->GetGateRef(
|
2021-09-04 08:06:49 +00:00
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
2021-12-17 09:18:10 +00:00
|
|
|
reinterpret_cast<const Out *>(circuit->LoadGatePtrConst(GateRef(out)))->GetGateConst());
|
2021-09-04 08:06:49 +00:00
|
|
|
if (gate < prevGate + static_cast<int64_t>(sizeof(Gate)) ||
|
|
|
|
gate >= static_cast<int64_t>(circuit->GetCircuitDataSize())) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "[Verifier][Error] Circuit data is corrupted (bad next gate)";
|
|
|
|
LOG_COMPILER(ERROR) << "at: " << std::dec << gate;
|
2021-09-04 08:06:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
gatesList.push_back(gate);
|
|
|
|
gatesSet.insert(gate);
|
|
|
|
prevGate = gate;
|
|
|
|
out += Gate::GetGateSize(
|
|
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
2021-12-17 09:18:10 +00:00
|
|
|
reinterpret_cast<const Out *>(circuit->LoadGatePtrConst(GateRef(out)))->GetIndex() + 1);
|
2021-09-04 08:06:49 +00:00
|
|
|
if (out == circuit->GetCircuitDataSize()) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (out > circuit->GetCircuitDataSize() || out < 0) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "[Verifier][Error] Circuit data is corrupted (out of bound access)";
|
|
|
|
LOG_COMPILER(ERROR) << "at: " << std::dec << out;
|
2021-09-04 08:06:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (const auto &gate : gatesList) {
|
|
|
|
for (size_t idx = 0; idx < circuit->LoadGatePtrConst(gate)->GetNumIns(); idx++) {
|
|
|
|
const In *curIn = circuit->LoadGatePtrConst(gate)->GetInConst(idx);
|
|
|
|
if (!(circuit->GetSpaceDataStartPtrConst() < curIn && curIn < circuit->GetSpaceDataEndPtrConst())) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "[Verifier][Error] Circuit data is corrupted (corrupted in list)";
|
|
|
|
LOG_COMPILER(ERROR) << "id: " << std::dec << circuit->GetId(gate);
|
2021-09-04 08:06:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
2022-07-18 11:54:48 +00:00
|
|
|
if (gatesSet.count(circuit->GetGateRef(curIn->GetGateConst())) == 0) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "[Verifier][Error] Circuit data is corrupted (invalid in address)";
|
|
|
|
LOG_COMPILER(ERROR) << "id: " << std::dec << circuit->GetId(gate);
|
2021-09-04 08:06:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
{
|
|
|
|
const Gate *curGate = circuit->LoadGatePtrConst(gate);
|
|
|
|
if (!curGate->IsFirstOutNull()) {
|
|
|
|
const Out *curOut = curGate->GetFirstOutConst();
|
|
|
|
if (!(circuit->GetSpaceDataStartPtrConst() < curOut && curOut < circuit->GetSpaceDataEndPtrConst())) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "[Verifier][Error] Circuit data is corrupted (corrupted out list)";
|
|
|
|
LOG_COMPILER(ERROR) << "id: " << std::dec << circuit->GetId(gate);
|
2021-09-04 08:06:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
2022-07-18 11:54:48 +00:00
|
|
|
if (gatesSet.count(circuit->GetGateRef(curOut->GetGateConst())) == 0) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "[Verifier][Error] Circuit data is corrupted (invalid out address)";
|
|
|
|
LOG_COMPILER(ERROR) << "id: " << std::dec << circuit->GetId(gate);
|
2021-09-04 08:06:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
while (!curOut->IsNextOutNull()) {
|
|
|
|
curOut = curOut->GetNextOutConst();
|
|
|
|
if (!(circuit->GetSpaceDataStartPtrConst() < curOut &&
|
2021-09-07 14:24:16 +00:00
|
|
|
curOut < circuit->GetSpaceDataEndPtrConst())) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "[Verifier][Error] Circuit data is corrupted (corrupted out list)";
|
|
|
|
LOG_COMPILER(ERROR) << "id: " << std::dec << circuit->GetId(gate);
|
2021-09-04 08:06:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
2022-07-18 11:54:48 +00:00
|
|
|
if (gatesSet.count(circuit->GetGateRef(curOut->GetGateConst())) == 0) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "[Verifier][Error] Circuit data is corrupted (invalid out address)";
|
|
|
|
LOG_COMPILER(ERROR) << "id: " << std::dec << circuit->GetId(gate);
|
2021-09-04 08:06:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-12-17 09:18:10 +00:00
|
|
|
bool Verifier::RunStateGatesCheck(const Circuit *circuit, const std::vector<GateRef> &bbGatesList)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
|
|
|
for (const auto &bbGate : bbGatesList) {
|
2022-12-01 08:50:20 +00:00
|
|
|
circuit->Verify(bbGate);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-12-17 09:18:10 +00:00
|
|
|
bool Verifier::RunCFGSoundnessCheck(const Circuit *circuit, const std::vector<GateRef> &bbGatesList,
|
|
|
|
const std::unordered_map<GateRef, size_t> &bbGatesAddrToIdx)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
|
|
|
for (const auto &bbGate : bbGatesList) {
|
2022-03-02 08:06:19 +00:00
|
|
|
GateAccessor gateAcc(const_cast<Circuit *>(circuit));
|
|
|
|
for (const auto &predGate : gateAcc.ConstIns(bbGate)) {
|
2023-05-08 07:50:22 +00:00
|
|
|
if (gateAcc.IsState(predGate) || circuit->GetOpCode(predGate) == OpCode::STATE_ENTRY) {
|
2021-09-04 08:06:49 +00:00
|
|
|
if (bbGatesAddrToIdx.count(predGate) == 0) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "[Verifier][Error] CFG is not sound";
|
|
|
|
LOG_COMPILER(ERROR) << "Proof:";
|
|
|
|
LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(predGate) << ") is pred of "
|
2022-04-14 08:14:34 +00:00
|
|
|
<< "(id=" << circuit->GetId(bbGate) << ")";
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(bbGate) << ") is reachable from entry";
|
|
|
|
LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(predGate) << ") is unreachable from entry";
|
2021-09-04 08:06:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Verifier::RunCFGIsDAGCheck(const Circuit *circuit)
|
|
|
|
{
|
|
|
|
circuit->AdvanceTime();
|
2022-07-27 10:21:16 +00:00
|
|
|
struct DFSState {
|
|
|
|
GateRef cur;
|
|
|
|
GateAccessor::ConstUseWrapper uses;
|
|
|
|
GateAccessor::ConstUseIterator use;
|
|
|
|
};
|
|
|
|
std::stack<DFSState> dfsStack;
|
|
|
|
GateAccessor gateAcc(const_cast<Circuit *>(circuit));
|
2022-12-01 08:50:20 +00:00
|
|
|
auto root = gateAcc.GetStateRoot();
|
2022-07-27 10:21:16 +00:00
|
|
|
gateAcc.SetVisited(root);
|
|
|
|
auto rootUses = gateAcc.ConstUses(root);
|
|
|
|
dfsStack.push({root, rootUses, rootUses.begin()});
|
|
|
|
while (!dfsStack.empty()) {
|
|
|
|
auto &curState = dfsStack.top();
|
|
|
|
auto &cur = curState.cur;
|
|
|
|
auto &uses = curState.uses;
|
|
|
|
auto &use = curState.use;
|
|
|
|
if (use == uses.end()) {
|
|
|
|
gateAcc.SetFinished(cur);
|
|
|
|
dfsStack.pop();
|
|
|
|
continue;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
2022-07-27 10:21:16 +00:00
|
|
|
if (gateAcc.IsState(*use) && use.GetIndex() < gateAcc.GetStateCount(*use)) {
|
|
|
|
if (gateAcc.IsVisited(*use)) {
|
|
|
|
LOG_COMPILER(ERROR) <<
|
|
|
|
"[Verifier][Error] CFG without loop back edges is not a directed acyclic graph";
|
|
|
|
LOG_COMPILER(ERROR) << "Proof:";
|
|
|
|
LOG_COMPILER(ERROR) << "(id=" << gateAcc.GetId(*use) << ") is succ of "
|
|
|
|
<< "(id=" << gateAcc.GetId(cur) << ")";
|
|
|
|
LOG_COMPILER(ERROR) << "(id=" << gateAcc.GetId(cur) << ") is reachable from "
|
|
|
|
<< "(id=" << gateAcc.GetId(*use) << ") without loop back edges";
|
|
|
|
return false;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
2022-07-27 10:21:16 +00:00
|
|
|
if (gateAcc.IsFinished(*use) || gateAcc.IsLoopBack(*use)) {
|
|
|
|
++use;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
gateAcc.SetVisited(*use);
|
|
|
|
auto newUses = gateAcc.ConstUses(*use);
|
|
|
|
dfsStack.push({*use, newUses, newUses.begin()});
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
2022-07-27 10:21:16 +00:00
|
|
|
++use;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-12-17 09:18:10 +00:00
|
|
|
bool Verifier::RunCFGReducibilityCheck(const Circuit *circuit, const std::vector<GateRef> &bbGatesList,
|
|
|
|
const std::unordered_map<GateRef, size_t> &bbGatesAddrToIdx,
|
2021-09-04 08:06:49 +00:00
|
|
|
const std::function<bool(size_t, size_t)> &isAncestor)
|
|
|
|
{
|
|
|
|
for (const auto &curGate : bbGatesList) {
|
|
|
|
if (circuit->GetOpCode(curGate) == OpCode::LOOP_BACK) {
|
2022-03-02 08:06:19 +00:00
|
|
|
GateAccessor gateAcc(const_cast<Circuit *>(circuit));
|
|
|
|
auto uses = gateAcc.ConstUses(curGate);
|
|
|
|
for (auto use = uses.begin(); use != uses.end(); use++) {
|
|
|
|
if (use.GetIndex() >= circuit->LoadGatePtrConst(*use)->GetStateCount()) {
|
|
|
|
continue;
|
|
|
|
}
|
2023-05-08 07:50:22 +00:00
|
|
|
ASSERT(gateAcc.IsState(*use));
|
2022-03-02 08:06:19 +00:00
|
|
|
bool isDom = isAncestor(bbGatesAddrToIdx.at(*use), bbGatesAddrToIdx.at(curGate));
|
|
|
|
if (!isDom) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "[Verifier][Error] CFG is not reducible";
|
|
|
|
LOG_COMPILER(ERROR) << "Proof:";
|
|
|
|
LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(*use) << ") is loop back succ of "
|
2022-04-14 08:14:34 +00:00
|
|
|
<< "(id=" << circuit->GetId(curGate) << ")";
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(*use) << ") does not dominate "
|
2022-04-14 08:14:34 +00:00
|
|
|
<< "(id=" << circuit->GetId(curGate) << ")";
|
2022-03-02 08:06:19 +00:00
|
|
|
return false;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-12-17 09:18:10 +00:00
|
|
|
bool Verifier::RunFixedGatesCheck(const Circuit *circuit, const std::vector<GateRef> &fixedGatesList)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
|
|
|
for (const auto &fixedGate : fixedGatesList) {
|
2022-12-01 08:50:20 +00:00
|
|
|
circuit->Verify(fixedGate);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-12-17 09:18:10 +00:00
|
|
|
bool Verifier::RunFixedGatesRelationsCheck(const Circuit *circuit, const std::vector<GateRef> &fixedGatesList,
|
2022-11-15 05:06:13 +00:00
|
|
|
const std::unordered_map<GateRef, size_t> &bbGatesAddrToIdx,
|
|
|
|
const std::function<bool(size_t, size_t)> &isAncestor)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2022-11-15 05:06:13 +00:00
|
|
|
ConstGateAccessor ac(circuit);
|
2021-09-04 08:06:49 +00:00
|
|
|
for (const auto &fixedGate : fixedGatesList) {
|
|
|
|
size_t cnt = 0;
|
2022-11-15 05:06:13 +00:00
|
|
|
auto ins = ac.Ins(fixedGate);
|
|
|
|
for (auto i = ins.begin(); i != ins.end(); i++) {
|
|
|
|
GateRef predGate = *i;
|
2023-05-08 07:50:22 +00:00
|
|
|
if (ac.IsFixed(predGate) &&
|
2022-04-24 17:17:29 +00:00
|
|
|
(circuit->GetOpCode(circuit->GetIn(fixedGate, 0)) == OpCode::LOOP_BEGIN && cnt == 2)) {
|
2021-09-04 08:06:49 +00:00
|
|
|
ASSERT(cnt > 0);
|
|
|
|
auto a = bbGatesAddrToIdx.at(circuit->GetIn(predGate, 0));
|
2022-04-15 06:42:30 +00:00
|
|
|
auto b = bbGatesAddrToIdx.at(circuit->GetIn(circuit->GetIn(fixedGate, 0),
|
|
|
|
static_cast<size_t>(cnt - 1)));
|
2021-09-04 08:06:49 +00:00
|
|
|
if (!isAncestor(a, b)) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "[Verifier][Error] Fixed gates relationship is not consistent";
|
|
|
|
LOG_COMPILER(ERROR) << "Proof:";
|
|
|
|
LOG_COMPILER(ERROR) << "Fixed gate (id="
|
2022-04-24 17:17:29 +00:00
|
|
|
<< circuit->GetId(predGate)
|
|
|
|
<< ") is pred of fixed gate (id="
|
|
|
|
<< circuit->GetId(fixedGate) << ")";
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "BB_" << bbGatesAddrToIdx.at(circuit->GetIn(predGate, 0))
|
2022-04-14 08:14:34 +00:00
|
|
|
<< " does not dominate BB_"
|
2022-04-15 06:42:30 +00:00
|
|
|
<< bbGatesAddrToIdx.at(circuit->GetIn(circuit->GetIn(fixedGate, 0),
|
|
|
|
static_cast<size_t>(cnt - 1)));
|
2021-09-04 08:06:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cnt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-12-17 09:18:10 +00:00
|
|
|
bool Verifier::RunFlowCyclesFind(const Circuit *circuit, std::vector<GateRef> *schedulableGatesListPtr,
|
|
|
|
const std::vector<GateRef> &bbGatesList, const std::vector<GateRef> &fixedGatesList)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
|
|
|
circuit->AdvanceTime();
|
2022-11-15 05:06:13 +00:00
|
|
|
ConstGateAccessor ac(circuit);
|
2021-12-17 09:18:10 +00:00
|
|
|
std::vector<GateRef> startGateList;
|
2021-09-04 08:06:49 +00:00
|
|
|
for (const auto &gate : bbGatesList) {
|
2022-11-15 05:06:13 +00:00
|
|
|
auto ins = ac.Ins(gate);
|
|
|
|
for (auto i = ins.begin(); i != ins.end(); i++) {
|
|
|
|
GateRef predGate = *i;
|
2023-05-08 07:50:22 +00:00
|
|
|
if (ac.IsSchedulable(predGate)) {
|
2022-01-27 08:46:57 +00:00
|
|
|
if (circuit->GetMark(predGate) == MarkCode::NO_MARK) {
|
2021-09-04 08:06:49 +00:00
|
|
|
startGateList.push_back(predGate);
|
|
|
|
circuit->SetMark(predGate, MarkCode::VISITED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (const auto &gate : fixedGatesList) {
|
2022-11-15 05:06:13 +00:00
|
|
|
auto ins = ac.Ins(gate);
|
|
|
|
for (auto i = ins.begin(); i != ins.end(); i++) {
|
|
|
|
GateRef predGate = *i;
|
2023-05-08 07:50:22 +00:00
|
|
|
if (ac.IsSchedulable(predGate)) {
|
2022-01-27 08:46:57 +00:00
|
|
|
if (circuit->GetMark(predGate) == MarkCode::NO_MARK) {
|
2021-09-04 08:06:49 +00:00
|
|
|
startGateList.push_back(predGate);
|
|
|
|
circuit->SetMark(predGate, MarkCode::VISITED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
circuit->AdvanceTime();
|
2022-07-27 10:21:16 +00:00
|
|
|
GateAccessor gateAcc(const_cast<Circuit *>(circuit));
|
2021-12-17 09:18:10 +00:00
|
|
|
std::vector<GateRef> cycleGatesList;
|
|
|
|
GateRef meet = -1;
|
2022-07-27 10:21:16 +00:00
|
|
|
struct DFSState {
|
|
|
|
GateRef cur;
|
|
|
|
size_t numIns;
|
|
|
|
size_t idx;
|
|
|
|
};
|
|
|
|
for (const auto &startGate : startGateList) {
|
|
|
|
if (!gateAcc.IsNotMarked(startGate)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
std::stack<DFSState> dfsStack;
|
|
|
|
size_t startNumIns = gateAcc.GetNumIns(startGate);
|
|
|
|
dfsStack.push({startGate, startNumIns, 0});
|
|
|
|
gateAcc.SetVisited(startGate);
|
|
|
|
schedulableGatesListPtr->push_back(startGate);
|
|
|
|
while (!dfsStack.empty()) {
|
|
|
|
auto &curState = dfsStack.top();
|
|
|
|
auto &cur = curState.cur;
|
|
|
|
auto &numIns = curState.numIns;
|
|
|
|
auto &idx = curState.idx;
|
|
|
|
if (idx == numIns) {
|
|
|
|
gateAcc.SetFinished(cur);
|
|
|
|
dfsStack.pop();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
const auto prev = gateAcc.GetIn(cur, idx);
|
|
|
|
if (gateAcc.IsSchedulable(prev)) {
|
|
|
|
if (gateAcc.IsVisited(prev)) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) <<
|
2022-04-14 08:14:34 +00:00
|
|
|
"[Verifier][Error] Found a data or depend flow cycle without passing selectors";
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "Proof:";
|
|
|
|
LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(prev) << ") is prev of "
|
2022-07-27 10:21:16 +00:00
|
|
|
<< "(id=" << circuit->GetId(cur) << ")";
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(prev) << ") is reachable from "
|
2022-07-27 10:21:16 +00:00
|
|
|
<< "(id=" << circuit->GetId(cur) << ") without passing selectors";
|
2021-09-04 08:06:49 +00:00
|
|
|
meet = prev;
|
2022-07-27 10:21:16 +00:00
|
|
|
break;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
2022-07-27 10:21:16 +00:00
|
|
|
if (!gateAcc.IsFinished(prev)) {
|
|
|
|
size_t newNumIns = gateAcc.GetNumIns(prev);
|
|
|
|
dfsStack.push({prev, newNumIns, 0});
|
|
|
|
gateAcc.SetVisited(prev);
|
|
|
|
schedulableGatesListPtr->push_back(prev);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
}
|
2022-07-27 10:21:16 +00:00
|
|
|
idx++;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
2022-07-27 10:21:16 +00:00
|
|
|
if (meet != -1) {
|
|
|
|
while (dfsStack.top().cur != meet) {
|
|
|
|
cycleGatesList.push_back(dfsStack.top().cur);
|
|
|
|
dfsStack.pop();
|
|
|
|
}
|
|
|
|
cycleGatesList.push_back(meet);
|
|
|
|
LOG_COMPILER(ERROR) << "Path:";
|
|
|
|
for (const auto &cycleGate : cycleGatesList) {
|
|
|
|
gateAcc.Print(cycleGate);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
2022-07-27 10:21:16 +00:00
|
|
|
return false;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-12-17 09:18:10 +00:00
|
|
|
bool Verifier::RunSchedulableGatesCheck(const Circuit *circuit, const std::vector<GateRef> &schedulableGatesList)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
|
|
|
for (const auto &schedulableGate : schedulableGatesList) {
|
2022-12-01 08:50:20 +00:00
|
|
|
circuit->Verify(schedulableGate);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-12-17 09:18:10 +00:00
|
|
|
bool Verifier::RunPrologGatesCheck(const Circuit *circuit, const std::vector<GateRef> &schedulableGatesList)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2022-11-15 05:06:13 +00:00
|
|
|
ConstGateAccessor ac(circuit);
|
2021-09-04 08:06:49 +00:00
|
|
|
for (const auto &schedulableGate : schedulableGatesList) {
|
2022-11-15 05:06:13 +00:00
|
|
|
auto ins = ac.Ins(schedulableGate);
|
|
|
|
for (auto i = ins.begin(); i != ins.end(); i++) {
|
|
|
|
GateRef r = *i;
|
2023-05-08 07:50:22 +00:00
|
|
|
if (ac.IsProlog(r)) {
|
2022-12-01 08:50:20 +00:00
|
|
|
circuit->Verify(r);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-11-23 06:29:06 +00:00
|
|
|
bool Verifier::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)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
|
|
|
// check existence of scheduling upper bound
|
2021-12-17 09:18:10 +00:00
|
|
|
std::unordered_map<GateRef, size_t> upperBound;
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2022-11-23 06:29:06 +00:00
|
|
|
if (!Scheduler::CalculateSchedulingUpperBound(circuit, bbGatesAddrToIdx, isAncestor,
|
|
|
|
schedulableGatesList, upperBound)) {
|
2021-09-04 08:06:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// check existence of scheduling lower bound
|
2021-12-17 09:18:10 +00:00
|
|
|
std::unordered_map<GateRef, size_t> lowerBound;
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2022-11-23 06:29:06 +00:00
|
|
|
Scheduler::CalculateSchedulingLowerBound(circuit, bbGatesAddrToIdx, lowestCommonAncestor, lowerBound);
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
// check consistency of lower bound and upper bound
|
|
|
|
{
|
|
|
|
ASSERT(upperBound.size() == lowerBound.size());
|
|
|
|
for (const auto &item : lowerBound) {
|
|
|
|
if (!isAncestor(upperBound.at(item.first), lowerBound.at(item.first))) {
|
2023-04-28 07:13:05 +00:00
|
|
|
LOG_COMPILER(ERROR) << "[Verifier][Error] Bounds of gate (id="
|
|
|
|
<< circuit->GetId(item.first) << ") is not consistent";
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "Proof:";
|
|
|
|
LOG_COMPILER(ERROR) << "Upper bound is BB_" << upperBound.at(item.first);
|
|
|
|
LOG_COMPILER(ERROR) << "Lower bound is BB_" << lowerBound.at(item.first);
|
2022-08-05 09:00:14 +00:00
|
|
|
return false;
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-11-15 05:06:13 +00:00
|
|
|
void Verifier::FindFixedGates(const Circuit *circuit, const std::vector<GateRef> &bbGatesList,
|
|
|
|
std::vector<GateRef> &fixedGatesList)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
2023-05-08 07:50:22 +00:00
|
|
|
ConstGateAccessor ac(circuit);
|
2021-09-04 08:06:49 +00:00
|
|
|
for (const auto &bbGate : bbGatesList) {
|
|
|
|
for (const auto &succGate : circuit->GetOutVector(bbGate)) {
|
2023-05-08 07:50:22 +00:00
|
|
|
if (ac.IsFixed(succGate)) {
|
2021-09-04 08:06:49 +00:00
|
|
|
fixedGatesList.push_back(succGate);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-09 07:53:21 +00:00
|
|
|
bool Verifier::Run(const Circuit *circuit, const std::string& methodName, bool enableLog)
|
2021-09-04 08:06:49 +00:00
|
|
|
{
|
|
|
|
if (!RunDataIntegrityCheck(circuit)) {
|
2022-04-14 08:14:34 +00:00
|
|
|
if (enableLog) {
|
2022-10-09 07:53:21 +00:00
|
|
|
LOG_COMPILER(ERROR) << "[Verifier][Fail] Circuit data integrity verifier failed, " << methodName;
|
2022-04-14 08:14:34 +00:00
|
|
|
}
|
2021-09-04 08:06:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
2021-12-17 09:18:10 +00:00
|
|
|
std::vector<GateRef> bbGatesList;
|
|
|
|
std::unordered_map<GateRef, size_t> bbGatesAddrToIdx;
|
2021-09-04 08:06:49 +00:00
|
|
|
std::vector<size_t> immDom;
|
2022-10-20 12:30:52 +00:00
|
|
|
Scheduler::CalculateDominatorTree(circuit, bbGatesList, bbGatesAddrToIdx, immDom);
|
2021-09-04 08:06:49 +00:00
|
|
|
if (!RunStateGatesCheck(circuit, bbGatesList)) {
|
2022-04-14 08:14:34 +00:00
|
|
|
if (enableLog) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "[Verifier][Fail] RunStateGatesCheck failed";
|
2022-04-14 08:14:34 +00:00
|
|
|
}
|
2021-09-04 08:06:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!RunCFGSoundnessCheck(circuit, bbGatesList, bbGatesAddrToIdx)) {
|
2022-04-14 08:14:34 +00:00
|
|
|
if (enableLog) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "[Verifier][Fail] RunCFGSoundnessCheck failed";
|
2022-04-14 08:14:34 +00:00
|
|
|
}
|
2021-09-04 08:06:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!RunCFGIsDAGCheck(circuit)) {
|
2022-04-14 08:14:34 +00:00
|
|
|
if (enableLog) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "[Verifier][Fail] RunCFGIsDAGCheck failed";
|
2022-04-14 08:14:34 +00:00
|
|
|
}
|
2021-09-04 08:06:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
std::vector<std::vector<size_t>> sonList(bbGatesList.size());
|
|
|
|
for (size_t idx = 1; idx < immDom.size(); idx++) {
|
|
|
|
sonList[immDom[idx]].push_back(idx);
|
|
|
|
}
|
2021-09-07 14:24:16 +00:00
|
|
|
const size_t sizeLog = std::ceil(std::log2(static_cast<double>(bbGatesList.size())) + 1);
|
2021-09-04 08:06:49 +00:00
|
|
|
std::vector<size_t> timeIn(bbGatesList.size());
|
|
|
|
std::vector<size_t> timeOut(bbGatesList.size());
|
|
|
|
std::vector<std::vector<size_t>> jumpUp;
|
|
|
|
jumpUp.assign(bbGatesList.size(), std::vector<size_t>(sizeLog + 1));
|
|
|
|
{
|
|
|
|
size_t timestamp = 0;
|
2022-07-27 10:21:16 +00:00
|
|
|
struct DFSState {
|
|
|
|
size_t cur;
|
|
|
|
std::vector<size_t> &succList;
|
|
|
|
size_t idx;
|
2021-09-04 08:06:49 +00:00
|
|
|
};
|
2022-07-27 10:21:16 +00:00
|
|
|
std::stack<DFSState> dfsStack;
|
2021-09-04 08:06:49 +00:00
|
|
|
size_t root = 0;
|
2022-07-27 10:21:16 +00:00
|
|
|
dfsStack.push({root, sonList[root], 0});
|
|
|
|
timeIn[root] = timestamp++;
|
|
|
|
jumpUp[root][0] = root;
|
|
|
|
for (size_t stepSize = 1; stepSize <= sizeLog; stepSize++) {
|
|
|
|
auto jumpUpHalf = jumpUp[root][stepSize - 1];
|
|
|
|
jumpUp[root][stepSize] = jumpUp[jumpUpHalf][stepSize - 1];
|
|
|
|
}
|
|
|
|
while (!dfsStack.empty()) {
|
|
|
|
auto &curState = dfsStack.top();
|
|
|
|
auto &cur = curState.cur;
|
|
|
|
auto &succList = curState.succList;
|
|
|
|
auto &idx = curState.idx;
|
|
|
|
if (idx == succList.size()) {
|
|
|
|
timeOut[cur] = timestamp++;
|
|
|
|
dfsStack.pop();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
const auto &succ = succList[idx];
|
|
|
|
dfsStack.push({succ, sonList[succ], 0});
|
|
|
|
timeIn[succ] = timestamp++;
|
|
|
|
jumpUp[succ][0] = cur;
|
|
|
|
for (size_t stepSize = 1; stepSize <= sizeLog; stepSize++) {
|
|
|
|
auto jumpUpHalf = jumpUp[succ][stepSize - 1];
|
|
|
|
jumpUp[succ][stepSize] = jumpUp[jumpUpHalf][stepSize - 1];
|
|
|
|
}
|
|
|
|
idx++;
|
|
|
|
}
|
2021-09-04 08:06:49 +00:00
|
|
|
}
|
|
|
|
auto isAncestor = [timeIn, timeOut](size_t nodeA, size_t nodeB) -> bool {
|
|
|
|
return timeIn[nodeA] <= timeIn[nodeB] && timeOut[nodeA] >= timeOut[nodeB];
|
|
|
|
};
|
|
|
|
auto lowestCommonAncestor = [&](size_t nodeA, size_t nodeB) -> size_t {
|
|
|
|
if (isAncestor(nodeA, nodeB)) {
|
|
|
|
return nodeA;
|
|
|
|
}
|
|
|
|
if (isAncestor(nodeB, nodeA)) {
|
|
|
|
return nodeB;
|
|
|
|
}
|
|
|
|
for (size_t stepSize = sizeLog + 1; stepSize > 0; stepSize--) {
|
|
|
|
if (!isAncestor(jumpUp[nodeA][stepSize - 1], nodeB)) {
|
|
|
|
nodeA = jumpUp[nodeA][stepSize - 1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return jumpUp[nodeA][0];
|
|
|
|
};
|
|
|
|
if (!RunCFGReducibilityCheck(circuit, bbGatesList, bbGatesAddrToIdx, isAncestor)) {
|
2022-04-14 08:14:34 +00:00
|
|
|
if (enableLog) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "[Verifier][Fail] RunCFGReducibilityCheck failed";
|
2022-04-14 08:14:34 +00:00
|
|
|
}
|
2021-09-04 08:06:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
2022-11-15 05:06:13 +00:00
|
|
|
std::vector<GateRef> fixedGatesList;
|
|
|
|
FindFixedGates(circuit, bbGatesList, fixedGatesList);
|
2021-09-04 08:06:49 +00:00
|
|
|
if (!RunFixedGatesCheck(circuit, fixedGatesList)) {
|
2022-04-14 08:14:34 +00:00
|
|
|
if (enableLog) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "[Verifier][Fail] RunFixedGatesCheck failed";
|
2022-04-14 08:14:34 +00:00
|
|
|
}
|
2021-09-04 08:06:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!RunFixedGatesRelationsCheck(circuit, fixedGatesList, bbGatesAddrToIdx, isAncestor)) {
|
2022-04-14 08:14:34 +00:00
|
|
|
if (enableLog) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "[Verifier][Fail] RunFixedGatesRelationsCheck failed";
|
2022-04-14 08:14:34 +00:00
|
|
|
}
|
2021-09-04 08:06:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
2021-12-17 09:18:10 +00:00
|
|
|
std::vector<GateRef> schedulableGatesList;
|
2021-09-04 08:06:49 +00:00
|
|
|
if (!RunFlowCyclesFind(circuit, &schedulableGatesList, bbGatesList, fixedGatesList)) {
|
2022-04-14 08:14:34 +00:00
|
|
|
if (enableLog) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "[Verifier][Fail] RunFlowCyclesFind failed";
|
2022-04-14 08:14:34 +00:00
|
|
|
}
|
2021-09-04 08:06:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!RunSchedulableGatesCheck(circuit, fixedGatesList)) {
|
2022-04-14 08:14:34 +00:00
|
|
|
if (enableLog) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "[Verifier][Fail] RunSchedulableGatesCheck failed";
|
2022-04-14 08:14:34 +00:00
|
|
|
}
|
2021-09-04 08:06:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!RunPrologGatesCheck(circuit, fixedGatesList)) {
|
2022-04-14 08:14:34 +00:00
|
|
|
if (enableLog) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "[Verifier][Fail] RunPrologGatesCheck failed";
|
2022-04-14 08:14:34 +00:00
|
|
|
}
|
2021-09-04 08:06:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!RunSchedulingBoundsCheck(circuit, schedulableGatesList, bbGatesAddrToIdx, isAncestor, lowestCommonAncestor)) {
|
2022-04-14 08:14:34 +00:00
|
|
|
if (enableLog) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(ERROR) << "[Verifier][Fail] RunSchedulingBoundsCheck failed";
|
2022-04-14 08:14:34 +00:00
|
|
|
}
|
2021-09-04 08:06:49 +00:00
|
|
|
return false;
|
|
|
|
}
|
2022-04-14 08:14:34 +00:00
|
|
|
|
|
|
|
if (enableLog) {
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(INFO) << "[Verifier][Pass] Verifier success";
|
2022-04-14 08:14:34 +00:00
|
|
|
}
|
|
|
|
|
2021-09-04 08:06:49 +00:00
|
|
|
return true;
|
|
|
|
}
|
2022-08-17 02:09:16 +00:00
|
|
|
} // namespace panda::ecmascript::kungfu
|