/*
 * Copyright 2018 WebAssembly Community Group participants
 *
 * 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.
 */

//
// DataFlow IR is an SSA representation. It can be built from the main
// Binaryen IR.
//
// THe main initial use case was an IR that could easily be converted to
// Souper IR, and the design favors that.
//

#ifndef wasm_dataflow_utils_h
#define wasm_dataflow_utils_h

#include "dataflow/node.h"
#include "wasm-printing.h"
#include "wasm.h"

namespace wasm {

namespace DataFlow {

inline std::ostream& dump(Node* node, std::ostream& o, size_t indent = 0) {
  auto doIndent = [&]() {
    for (size_t i = 0; i < indent; i++) {
      o << ' ';
    }
  };
  doIndent();
  o << '[' << node << ' ';
  switch (node->type) {
    case Node::Type::Var:
      o << "var " << node->wasmType << ' ' << node;
      break;
    case Node::Type::Expr: {
      o << "expr ";
      WasmPrinter::printExpression(node->expr, o, true);
      break;
    }
    case Node::Type::Phi:
      o << "phi " << node->index;
      break;
    case Node::Type::Cond:
      o << "cond " << node->index;
      break;
    case Node::Type::Block: {
      // don't print the conds - they would recurse
      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;
}

// Checks if the inputs are all identical - something we could
// probably optimize. Returns false if irrelevant.
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);
      // Check if any of the others are not equal
      for (Index i = 2; i < node->values.size(); i++) {
        auto* curr = node->getValue(i);
        if (*first != *curr) {
          return false;
        }
      }
      return true;
    }
    default: {}
  }
  return false;
}

// Checks if the inputs are all constant - something we could
// probably optimize. Returns false if irrelevant.
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: {
      // Check if any of the others are not equal
      for (Index i = 1; i < node->values.size(); i++) {
        if (!node->getValue(i)->isConst()) {
          return false;
        }
      }
      return true;
    }
    default: {}
  }
  return false;
}

} // namespace DataFlow

} // namespace wasm

#endif // wasm_dataflow_utils
