/*
 * 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 branchs 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) const {
    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: {}
    }
    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;
  }

  // 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
