mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 08:03:29 +00:00
description: rewrite recursive functions in verifier,to avoid the Segmentation fault.
details: rewrite three dfs-functions in Verifier::RunCFGIsDAGCheck(), Verifier::RunFlowCyclesFind(), and Verifier::Run(). use the non-recursive implementation of recursive function. issue: https://gitee.com/openharmony/arkcompiler_ets_runtime/issues/I5J8C2 Signed-off-by: K0u1hw <wangchunyang15@huawei.com>
This commit is contained in:
parent
eb7e273942
commit
20998bc449
@ -34,6 +34,31 @@ void GateAccessor::SetMark(GateRef gate, MarkCode mark)
|
|||||||
circuit_->SetMark(gate, mark);
|
circuit_->SetMark(gate, mark);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GateAccessor::IsFinished(GateRef gate) const
|
||||||
|
{
|
||||||
|
return GetMark(gate) == MarkCode::FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GateAccessor::IsVisited(GateRef gate) const
|
||||||
|
{
|
||||||
|
return GetMark(gate) == MarkCode::VISITED;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GateAccessor::IsNotMarked(GateRef gate) const
|
||||||
|
{
|
||||||
|
return GetMark(gate) == MarkCode::NO_MARK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GateAccessor::SetFinished(GateRef gate)
|
||||||
|
{
|
||||||
|
SetMark(gate, MarkCode::FINISHED);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GateAccessor::SetVisited(GateRef gate)
|
||||||
|
{
|
||||||
|
SetMark(gate, MarkCode::VISITED);
|
||||||
|
}
|
||||||
|
|
||||||
OpCode GateAccessor::GetOpCode(GateRef gate) const
|
OpCode GateAccessor::GetOpCode(GateRef gate) const
|
||||||
{
|
{
|
||||||
Gate *gatePtr = circuit_->LoadGatePtr(gate);
|
Gate *gatePtr = circuit_->LoadGatePtr(gate);
|
||||||
@ -138,6 +163,21 @@ bool GateAccessor::IsLoopHead(GateRef gate) const
|
|||||||
return circuit_->IsLoopHead(gate);
|
return circuit_->IsLoopHead(gate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GateAccessor::IsLoopBack(GateRef gate) const
|
||||||
|
{
|
||||||
|
return GetOpCode(gate) == OpCode::LOOP_BACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GateAccessor::IsState(GateRef gate) const
|
||||||
|
{
|
||||||
|
return GetOpCode(gate).IsState();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GateAccessor::IsSchedulable(GateRef gate) const
|
||||||
|
{
|
||||||
|
return GetOpCode(gate).IsSchedulable();
|
||||||
|
}
|
||||||
|
|
||||||
GateRef GateAccessor::GetDep(GateRef gate, size_t idx) const
|
GateRef GateAccessor::GetDep(GateRef gate, size_t idx) const
|
||||||
{
|
{
|
||||||
Gate *gatePtr = circuit_->LoadGatePtr(gate);
|
Gate *gatePtr = circuit_->LoadGatePtr(gate);
|
||||||
|
@ -335,8 +335,16 @@ public:
|
|||||||
bool IsSelector(GateRef g) const;
|
bool IsSelector(GateRef g) const;
|
||||||
bool IsControlCase(GateRef gate) const;
|
bool IsControlCase(GateRef gate) const;
|
||||||
bool IsLoopHead(GateRef gate) const;
|
bool IsLoopHead(GateRef gate) const;
|
||||||
|
bool IsLoopBack(GateRef gate) const;
|
||||||
|
bool IsState(GateRef gate) const;
|
||||||
|
bool IsSchedulable(GateRef gate) const;
|
||||||
MarkCode GetMark(GateRef gate) const;
|
MarkCode GetMark(GateRef gate) const;
|
||||||
void SetMark(GateRef gate, MarkCode mark);
|
void SetMark(GateRef gate, MarkCode mark);
|
||||||
|
bool IsFinished(GateRef gate) const;
|
||||||
|
bool IsVisited(GateRef gate) const;
|
||||||
|
bool IsNotMarked(GateRef gate) const;
|
||||||
|
void SetFinished(GateRef gate);
|
||||||
|
void SetVisited(GateRef gate);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ConstUseIterator ConstUseBegin(GateRef gate) const
|
ConstUseIterator ConstUseBegin(GateRef gate) const
|
||||||
|
@ -139,40 +139,47 @@ bool Verifier::RunCFGSoundnessCheck(const Circuit *circuit, const std::vector<Ga
|
|||||||
bool Verifier::RunCFGIsDAGCheck(const Circuit *circuit)
|
bool Verifier::RunCFGIsDAGCheck(const Circuit *circuit)
|
||||||
{
|
{
|
||||||
circuit->AdvanceTime();
|
circuit->AdvanceTime();
|
||||||
std::function<bool(GateRef)> dfs = [&](GateRef cur) -> bool {
|
struct DFSState {
|
||||||
if (circuit->GetOpCode(cur) == OpCode::LOOP_BACK) {
|
GateRef cur;
|
||||||
return true;
|
GateAccessor::ConstUseWrapper uses;
|
||||||
}
|
GateAccessor::ConstUseIterator use;
|
||||||
circuit->SetMark(cur, MarkCode::VISITED);
|
|
||||||
GateAccessor gateAcc(const_cast<Circuit *>(circuit));
|
|
||||||
auto uses = gateAcc.ConstUses(cur);
|
|
||||||
for (auto use = uses.begin(); use != uses.end(); ++use) {
|
|
||||||
if (circuit->GetOpCode(*use).IsState() && use.GetIndex() < circuit->GetOpCode(*use).GetStateCount(
|
|
||||||
circuit->LoadGatePtrConst(*use)->GetBitField())) {
|
|
||||||
if (circuit->GetMark(*use) == MarkCode::VISITED) {
|
|
||||||
LOG_COMPILER(ERROR) <<
|
|
||||||
"[Verifier][Error] CFG without loop back edges is not a directed acyclic graph";
|
|
||||||
LOG_COMPILER(ERROR) << "Proof:";
|
|
||||||
LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(*use) << ") is succ of "
|
|
||||||
<< "(id=" << circuit->GetId(cur) << ")";
|
|
||||||
LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(cur) << ") is reachable from "
|
|
||||||
<< "(id=" << circuit->GetId(*use) << ") without loop back edges";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (circuit->GetMark(*use) == MarkCode::FINISHED) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!dfs(*use)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
circuit->SetMark(cur, MarkCode::FINISHED);
|
|
||||||
return true;
|
|
||||||
};
|
};
|
||||||
|
std::stack<DFSState> dfsStack;
|
||||||
auto root = Circuit::GetCircuitRoot(OpCode(OpCode::STATE_ENTRY));
|
auto root = Circuit::GetCircuitRoot(OpCode(OpCode::STATE_ENTRY));
|
||||||
if (!dfs(root)) {
|
GateAccessor gateAcc(const_cast<Circuit *>(circuit));
|
||||||
return false;
|
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;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
if (gateAcc.IsFinished(*use) || gateAcc.IsLoopBack(*use)) {
|
||||||
|
++use;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
gateAcc.SetVisited(*use);
|
||||||
|
auto newUses = gateAcc.ConstUses(*use);
|
||||||
|
dfsStack.push({*use, newUses, newUses.begin()});
|
||||||
|
}
|
||||||
|
++use;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -275,52 +282,66 @@ bool Verifier::RunFlowCyclesFind(const Circuit *circuit, std::vector<GateRef> *s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
circuit->AdvanceTime();
|
circuit->AdvanceTime();
|
||||||
|
GateAccessor gateAcc(const_cast<Circuit *>(circuit));
|
||||||
std::vector<GateRef> cycleGatesList;
|
std::vector<GateRef> cycleGatesList;
|
||||||
GateRef meet = -1;
|
GateRef meet = -1;
|
||||||
std::function<bool(GateRef)> dfs = [&](GateRef cur) -> bool {
|
struct DFSState {
|
||||||
circuit->SetMark(cur, MarkCode::VISITED);
|
GateRef cur;
|
||||||
schedulableGatesListPtr->push_back(cur);
|
size_t numIns;
|
||||||
size_t numIns = circuit->LoadGatePtrConst(cur)->GetNumIns();
|
size_t idx;
|
||||||
for (size_t idx = 0; idx < numIns; idx++) {
|
};
|
||||||
const auto prev = circuit->GetIn(cur, idx);
|
for (const auto &startGate : startGateList) {
|
||||||
if (circuit->GetOpCode(prev).IsSchedulable()) {
|
if (!gateAcc.IsNotMarked(startGate)) {
|
||||||
if (circuit->GetMark(prev) == MarkCode::VISITED) {
|
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)) {
|
||||||
LOG_COMPILER(ERROR) <<
|
LOG_COMPILER(ERROR) <<
|
||||||
"[Verifier][Error] Found a data or depend flow cycle without passing selectors";
|
"[Verifier][Error] Found a data or depend flow cycle without passing selectors";
|
||||||
LOG_COMPILER(ERROR) << "Proof:";
|
LOG_COMPILER(ERROR) << "Proof:";
|
||||||
LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(prev) << ") is prev of "
|
LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(prev) << ") is prev of "
|
||||||
<< "(id=" << circuit->GetId(cur) << ")";
|
<< "(id=" << circuit->GetId(cur) << ")";
|
||||||
LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(prev) << ") is reachable from "
|
LOG_COMPILER(ERROR) << "(id=" << circuit->GetId(prev) << ") is reachable from "
|
||||||
<< "(id=" << circuit->GetId(cur) << ") without passing selectors";
|
<< "(id=" << circuit->GetId(cur) << ") without passing selectors";
|
||||||
meet = prev;
|
meet = prev;
|
||||||
cycleGatesList.push_back(cur);
|
break;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
if (circuit->GetMark(prev) != MarkCode::FINISHED) {
|
if (!gateAcc.IsFinished(prev)) {
|
||||||
if (!dfs(prev)) {
|
size_t newNumIns = gateAcc.GetNumIns(prev);
|
||||||
if (meet != -1) {
|
dfsStack.push({prev, newNumIns, 0});
|
||||||
cycleGatesList.push_back(cur);
|
gateAcc.SetVisited(prev);
|
||||||
}
|
schedulableGatesListPtr->push_back(prev);
|
||||||
if (meet == cur) {
|
|
||||||
meet = -1;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
idx++;
|
||||||
}
|
}
|
||||||
circuit->SetMark(cur, MarkCode::FINISHED);
|
if (meet != -1) {
|
||||||
return true;
|
while (dfsStack.top().cur != meet) {
|
||||||
};
|
cycleGatesList.push_back(dfsStack.top().cur);
|
||||||
for (const auto &startGate : startGateList) {
|
dfsStack.pop();
|
||||||
if (circuit->GetMark(startGate) == MarkCode::NO_MARK) {
|
|
||||||
if (!dfs(startGate)) {
|
|
||||||
LOG_COMPILER(ERROR) << "Path:";
|
|
||||||
for (const auto &cycleGate : cycleGatesList) {
|
|
||||||
circuit->Print(cycleGate);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
cycleGatesList.push_back(meet);
|
||||||
|
LOG_COMPILER(ERROR) << "Path:";
|
||||||
|
for (const auto &cycleGate : cycleGatesList) {
|
||||||
|
gateAcc.Print(cycleGate);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -440,19 +461,40 @@ bool Verifier::Run(const Circuit *circuit, bool enableLog)
|
|||||||
jumpUp.assign(bbGatesList.size(), std::vector<size_t>(sizeLog + 1));
|
jumpUp.assign(bbGatesList.size(), std::vector<size_t>(sizeLog + 1));
|
||||||
{
|
{
|
||||||
size_t timestamp = 0;
|
size_t timestamp = 0;
|
||||||
std::function<void(size_t, size_t)> dfs = [&](size_t cur, size_t prev) {
|
struct DFSState {
|
||||||
timeIn[cur] = timestamp++;
|
size_t cur;
|
||||||
jumpUp[cur][0] = prev;
|
std::vector<size_t> &succList;
|
||||||
for (size_t stepSize = 1; stepSize <= sizeLog; stepSize++) {
|
size_t idx;
|
||||||
jumpUp[cur][stepSize] = jumpUp[jumpUp[cur][stepSize - 1]][stepSize - 1];
|
|
||||||
}
|
|
||||||
for (const auto &succ : sonList[cur]) {
|
|
||||||
dfs(succ, cur);
|
|
||||||
}
|
|
||||||
timeOut[cur] = timestamp++;
|
|
||||||
};
|
};
|
||||||
|
std::stack<DFSState> dfsStack;
|
||||||
size_t root = 0;
|
size_t root = 0;
|
||||||
dfs(root, root);
|
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++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
auto isAncestor = [timeIn, timeOut](size_t nodeA, size_t nodeB) -> bool {
|
auto isAncestor = [timeIn, timeOut](size_t nodeA, size_t nodeB) -> bool {
|
||||||
return timeIn[nodeA] <= timeIn[nodeB] && timeOut[nodeA] >= timeOut[nodeB];
|
return timeIn[nodeA] <= timeIn[nodeB] && timeOut[nodeA] >= timeOut[nodeB];
|
||||||
|
Loading…
Reference in New Issue
Block a user