// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_TORQUE_CSA_GENERATOR_H_
#define V8_TORQUE_CSA_GENERATOR_H_

#include <iostream>

#include "src/torque/cfg.h"
#include "src/torque/declarable.h"

namespace v8 {
namespace internal {
namespace torque {

class CSAGenerator {
 public:
  CSAGenerator(const ControlFlowGraph& cfg, std::ostream& out,
               base::Optional<Builtin::Kind> linkage = base::nullopt)
      : cfg_(cfg), out_(out), linkage_(linkage) {}
  base::Optional<Stack<std::string>> EmitGraph(Stack<std::string> parameters);

  static constexpr const char* ARGUMENTS_VARIABLE_STRING = "arguments";

  static void EmitCSAValue(VisitResult result, const Stack<std::string>& values,
                           std::ostream& out);

 private:
  const ControlFlowGraph& cfg_;
  std::ostream& out_;
  size_t fresh_id_ = 0;
  base::Optional<Builtin::Kind> linkage_;

  std::string FreshNodeName() { return "tmp" + std::to_string(fresh_id_++); }
  std::string BlockName(const Block* block) {
    return "block" + std::to_string(block->id());
  }

  Stack<std::string> EmitBlock(const Block* block);
  void EmitInstruction(const Instruction& instruction,
                       Stack<std::string>* stack);
#define EMIT_INSTRUCTION_DECLARATION(T) \
  void EmitInstruction(const T& instruction, Stack<std::string>* stack);
  TORQUE_INSTRUCTION_LIST(EMIT_INSTRUCTION_DECLARATION)
#undef EMIT_INSTRUCTION_DECLARATION
};

}  // namespace torque
}  // namespace internal
}  // namespace v8

#endif  // V8_TORQUE_CSA_GENERATOR_H_
