#ifndef wasm_dataflow_utils_h
#define wasm_dataflow_utils_h
#include "dataflow/graph.h"
#include "dataflow/node.h"
#include "wasm.h"
namespace wasm::DataFlow {
inline std::ostream& dump(Node* node, std::ostream& o, size_t indent = 0) {
auto doIndent = [&]() { o << std::string(indent, ' '); };
doIndent();
o << '[' << node << ' ';
switch (node->type) {
case Node::Type::Var:
o << "var " << node->wasmType << ' ' << node;
break;
case Node::Type::Expr: {
o << "expr ";
o << *node->expr << '\n';
break;
}
case Node::Type::Phi:
o << "phi " << node->index;
break;
case Node::Type::Cond:
o << "cond " << node->index;
break;
case Node::Type::Block: {
o << "block (" << node->values.size() << " conds)]\n";
return o;
}
case Node::Type::Zext:
o << "zext";
break;
case Node::Type::Bad:
o << "bad";
break;
}
if (!node->values.empty()) {
o << '\n';
for (auto* value : node->values) {
dump(value, o, indent + 1);
}
doIndent();
}
o << "] (origin: " << (void*)(node->origin) << ")\n";
return o;
}
inline std::ostream& dump(Graph& graph, std::ostream& o) {
for (auto& node : graph.nodes) {
o << "NODE " << node.get() << ": ";
dump(node.get(), o);
if (auto* set = graph.getSet(node.get())) {
o << " and that is set to local " << set->index << '\n';
}
}
return o;
}
inline bool allInputsIdentical(Node* node) {
switch (node->type) {
case Node::Type::Expr: {
if (node->expr->is<Binary>()) {
return *(node->getValue(0)) == *(node->getValue(1));
} else if (node->expr->is<Select>()) {
return *(node->getValue(1)) == *(node->getValue(2));
}
break;
}
case Node::Type::Phi: {
auto* first = node->getValue(1);
for (Index i = 2; i < node->values.size(); i++) {
auto* curr = node->getValue(i);
if (*first != *curr) {
return false;
}
}
return true;
}
default: {}
}
return false;
}
inline bool allInputsConstant(Node* node) {
switch (node->type) {
case Node::Type::Expr: {
if (node->expr->is<Unary>()) {
return node->getValue(0)->isConst();
} else if (node->expr->is<Binary>()) {
return node->getValue(0)->isConst() && node->getValue(1)->isConst();
} else if (node->expr->is<Select>()) {
return node->getValue(0)->isConst() && node->getValue(1)->isConst() &&
node->getValue(2)->isConst();
}
break;
}
case Node::Type::Phi: {
for (Index i = 1; i < node->values.size(); i++) {
if (!node->getValue(i)->isConst()) {
return false;
}
}
return true;
}
default: {}
}
return false;
}
}
#endif