/*
 * 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_node_h
#define wasm_dataflow_node_h

#include "ir/utils.h"
#include "wasm.h"

namespace wasm::DataFlow {

//
// The core IR representation in DataFlow: a Node.
//
// We reuse the Binaryen IR as much as possible: when things are identical
// between the two IRs, we just create an Expr node, which stores the opcode and
// other details, and we can emit them to Souper by reading the Binaryen
// Expression. Other node types here are special things from Souper IR that we
// can't represent that way.
//
// * Souper comparisons return an i1. We extend them immediately if they are
//   going to be used as i32s or i64s.
// * When we use an Expression node, we just use its immediate fields, like the
//   op in a binary, alignment etc. in a load, etc. We don't look into the
//   pointers to child nodes. Instead, the DataFlow IR has its own pointers
//   directly to DataFlow children. In particular, this means that it's easy
//   to create an Expression with the info you need and not care about linking
//   it up to other Expressions.
//

struct Node {
  enum Type {
    Var,  // an unknown variable number (not to be confused with var/param/local
          // in wasm)
    Expr, // a value represented by a Binaryen Expression
    Phi,  // a phi from converging control flow
    Cond, // a blockpc, representing one of the branches for a Block
    Block, // a source of phis
    Zext, // zero-extend an i1 (from an op where Souper returns i1 but wasm does
          // not, and so we need a special way to get back to an i32/i64 if we
          // operate on that value instead of just passing it straight to
          // Souper).
    Bad   // something we can't handle and should ignore
  } type;

  Node(Type type) : type(type) {}

  // TODO: the others, if we need them
  bool isVar() { return type == Var; }
  bool isExpr() { return type == Expr; }
  bool isPhi() { return type == Phi; }
  bool isCond() { return type == Cond; }
  bool isBlock() { return type == Block; }
  bool isZext() { return type == Zext; }
  bool isBad() { return type == Bad; }

  bool isConst() { return type == Expr && expr->is<Const>(); }

  union {
    // For Var
    wasm::Type wasmType;
    // For Expr
    Expression* expr;
    // For Phi and Cond (the local index for phi, the block
    // index for cond)
    Index index;
  };

  // The wasm expression that we originate from (if such exists). A single
  // wasm instruction may be turned into multiple dataflow IR nodes, and some
  // nodes have no wasm origin (like phis).
  Expression* origin = nullptr;

  // Extra list of related nodes.
  // For Expr, these are the Nodes for the inputs to the expression (e.g.
  // a binary would have 2 in this vector here).
  // For Phi, this is the block and then the list of values to pick from.
  // For Cond, this is the block and node.
  // For Block, this is the list of Conds. Note that that block does not
  // depend on them - the Phis do, but we store them in the block so that
  // we can avoid duplication.
  // For Zext, this is the value we extend.
  std::vector<Node*> values;

  // Constructors
  static Node* makeVar(wasm::Type wasmType) {
    Node* ret = new Node(Var);
    ret->wasmType = wasmType;
    return ret;
  }
  static Node* makeExpr(Expression* expr, Expression* origin) {
    Node* ret = new Node(Expr);
    ret->expr = expr;
    ret->origin = origin;
    return ret;
  }
  static Node* makePhi(Node* block, Index index) {
    Node* ret = new Node(Phi);
    ret->addValue(block);
    ret->index = index;
    return ret;
  }
  static Node* makeCond(Node* block, Index index, Node* node) {
    Node* ret = new Node(Cond);
    ret->addValue(block);
    ret->index = index;
    ret->addValue(node);
    return ret;
  }
  static Node* makeBlock() {
    Node* ret = new Node(Block);
    return ret;
  }
  static Node* makeZext(Node* child, Expression* origin) {
    Node* ret = new Node(Zext);
    ret->addValue(child);
    ret->origin = origin;
    return ret;
  }
  static Node* makeBad() {
    Node* ret = new Node(Bad);
    return ret;
  }

  // Helpers

  void addValue(Node* value) { values.push_back(value); }
  Node* getValue(Index i) { return values.at(i); }

  // Gets the wasm type of the node. If there isn't a valid one,
  // return unreachable.
  wasm::Type getWasmType() {
    switch (type) {
      case Var:
        return wasmType;
      case Expr:
        return expr->type;
      case Phi:
        return getValue(1)->getWasmType();
      case Zext:
        return getValue(0)->getWasmType();
      case Bad:
        return wasm::Type::unreachable;
      default:
        WASM_UNREACHABLE("invalid node type");
    }
  }

  bool operator==(const Node& other) {
    if (type != other.type) {
      return false;
    }
    switch (type) {
      case Var:
      case Block:
        return this == &other;
      case Expr: {
        if (!ExpressionAnalyzer::equal(expr, other.expr)) {
          return false;
        }
        break;
      }
      case Cond: {
        if (index != other.index) {
          return false;
        }
        break;
      }
      default:
        break;
    }
    if (values.size() != other.values.size()) {
      return false;
    }
    for (Index i = 0; i < values.size(); i++) {
      if (*(values[i]) != *(other.values[i])) {
        return false;
      }
    }
    return true;
  }

  bool operator!=(const Node& other) { return !(*this == other); }

  // As mentioned above, comparisons return i1. This checks
  // if an operation is of that sort.
  bool returnsI1() {
    if (isExpr()) {
      if (auto* binary = expr->dynCast<Binary>()) {
        return binary->isRelational();
      } else if (auto* unary = expr->dynCast<Unary>()) {
        return unary->isRelational();
      }
    }
    return false;
  }
};

} // namespace wasm::DataFlow

#endif // wasm_dataflow_node
