dawn-cmake/src/tint/ir/debug.cc
dan sinclair 4957327cc9 [ir] Add explicit continue branches.
This CL adds a `Continue` instruction into the IR and uses it when
branching into the continue block.

Bug: tint:1718
Change-Id: If54afe6f53b587f1d8a99afd920b94ebdcb608e5
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/134462
Reviewed-by: Ben Clayton <bclayton@google.com>
Reviewed-by: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
2023-05-26 04:33:30 +00:00

96 lines
3.2 KiB
C++

// Copyright 2022 The Tint Authors.
//
// 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 "src/tint/ir/debug.h"
#include <unordered_map>
#include <unordered_set>
#include "src/tint/ir/block.h"
#include "src/tint/ir/continue.h"
#include "src/tint/ir/if.h"
#include "src/tint/ir/loop.h"
#include "src/tint/ir/return.h"
#include "src/tint/ir/switch.h"
#include "src/tint/switch.h"
#include "src/tint/utils/string_stream.h"
namespace tint::ir {
// static
std::string Debug::AsDotGraph(const Module* mod) {
size_t block_count = 0;
std::unordered_set<const Block*> visited;
std::unordered_set<const Block*> merge_blocks;
std::unordered_map<const Block*, std::string> block_to_name;
utils::StringStream out;
auto name_for = [&](const Block* blk) -> std::string {
if (block_to_name.count(blk) > 0) {
return block_to_name[blk];
}
std::string name = "blk_" + std::to_string(block_count);
block_count += 1;
block_to_name[blk] = name;
return name;
};
std::function<void(const Block*)> Graph = [&](const Block* blk) {
if (visited.count(blk) > 0) {
return;
}
visited.insert(blk);
tint::Switch(blk, //
[&](const ir::Block* b) {
if (block_to_name.count(b) == 0) {
out << name_for(b) << R"( [label="block"])" << std::endl;
}
out << name_for(b) << " -> " << name_for(b->Branch()->To());
// Dashed lines to merge blocks
if (merge_blocks.count(b->Branch()->To()) != 0) {
out << " [style=dashed]";
}
out << std::endl;
if (b->Branch()->Is<ir::Return>()) {
return;
} else if (auto* cont = b->Branch()->As<ir::Continue>()) {
Graph(cont->Loop()->Continuing());
} else {
Graph(b->Branch()->To());
}
});
};
out << "digraph G {" << std::endl;
for (const auto* func : mod->functions) {
// Cluster each function to label and draw a box around it.
out << "subgraph cluster_" << mod->NameOf(func).Name() << " {" << std::endl;
out << R"(label=")" << mod->NameOf(func).Name() << R"(")" << std::endl;
out << name_for(func->StartTarget()) << R"( [label="start"])" << std::endl;
Graph(func->StartTarget());
out << "}" << std::endl;
}
out << "}";
return out.str();
}
} // namespace tint::ir