/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * 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.
 */

#ifndef ART_COMPILER_OPTIMIZING_GRAPH_VISUALIZER_H_
#define ART_COMPILER_OPTIMIZING_GRAPH_VISUALIZER_H_

#include <functional>
#include <ostream>

#include "arch/instruction_set.h"
#include "base/arena_containers.h"
#include "base/value_object.h"
#include "block_namer.h"

namespace art {

class CodeGenerator;
class DexCompilationUnit;
class HGraph;
class HInstruction;
class SlowPathCode;

/**
 * This class outputs the HGraph in the C1visualizer format.
 * Note: Currently only works if the compiler is single threaded.
 */
struct GeneratedCodeInterval {
  size_t start;
  size_t end;
};

struct SlowPathCodeInfo {
  const SlowPathCode* slow_path;
  GeneratedCodeInterval code_interval;
};

// This information is filled by the code generator. It will be used by the
// graph visualizer to associate disassembly of the generated code with the
// instructions and slow paths. We assume that the generated code follows the
// following structure:
//   - frame entry
//   - instructions
//   - slow paths
class DisassemblyInformation {
 public:
  explicit DisassemblyInformation(ArenaAllocator* allocator)
      : frame_entry_interval_({0, 0}),
        instruction_intervals_(std::less<const HInstruction*>(), allocator->Adapter()),
        slow_path_intervals_(allocator->Adapter()) {}

  void SetFrameEntryInterval(size_t start, size_t end) {
    frame_entry_interval_ = {start, end};
  }

  void AddInstructionInterval(HInstruction* instr, size_t start, size_t end) {
    instruction_intervals_.Put(instr, {start, end});
  }

  void AddSlowPathInterval(SlowPathCode* slow_path, size_t start, size_t end) {
    slow_path_intervals_.push_back({slow_path, {start, end}});
  }

  GeneratedCodeInterval GetFrameEntryInterval() const {
    return frame_entry_interval_;
  }

  GeneratedCodeInterval* GetFrameEntryInterval() {
    return &frame_entry_interval_;
  }

  const ArenaSafeMap<const HInstruction*, GeneratedCodeInterval>& GetInstructionIntervals() const {
    return instruction_intervals_;
  }

  ArenaSafeMap<const HInstruction*, GeneratedCodeInterval>* GetInstructionIntervals() {
    return &instruction_intervals_;
  }

  const ArenaVector<SlowPathCodeInfo>& GetSlowPathIntervals() const { return slow_path_intervals_; }

  ArenaVector<SlowPathCodeInfo>* GetSlowPathIntervals() { return &slow_path_intervals_; }

 private:
  GeneratedCodeInterval frame_entry_interval_;
  ArenaSafeMap<const HInstruction*, GeneratedCodeInterval> instruction_intervals_;
  ArenaVector<SlowPathCodeInfo> slow_path_intervals_;
};

class HGraphVisualizer : public ValueObject {
 public:
  HGraphVisualizer(std::ostream* output,
                   HGraph* graph,
                   const CodeGenerator* codegen,
                   std::optional<std::reference_wrapper<const BlockNamer>> namer = std::nullopt);

  void PrintHeader(const char* method_name) const;
  void DumpGraph(const char* pass_name, bool is_after_pass, bool graph_in_bad_state) const;
  void DumpGraphDebug() const;
  void DumpGraphWithDisassembly() const;

  // C1visualizer file format does not support inserting arbitrary metadata into a cfg
  // file. As a workaround a fake compilation block with the metadata in the name and the
  // method attributes is used. Such empty blocks don't break the c1visualizer parser.
  static std::string InsertMetaDataAsCompilationBlock(const std::string& meta_data);

  static void DumpInstruction(std::ostream* output, HGraph* graph, HInstruction* instruction);

 private:
  class OptionalDefaultNamer final : public BlockNamer {
   public:
    explicit OptionalDefaultNamer(std::optional<std::reference_wrapper<const BlockNamer>> inner)
        : namer_(inner) {}

    std::ostream& PrintName(std::ostream& os, HBasicBlock* blk) const override;

   private:
    std::optional<std::reference_wrapper<const BlockNamer>> namer_;
  };

  std::ostream* const output_;
  HGraph* const graph_;
  const CodeGenerator* codegen_;
  OptionalDefaultNamer namer_;

  DISALLOW_COPY_AND_ASSIGN(HGraphVisualizer);
};

}  // namespace art

#endif  // ART_COMPILER_OPTIMIZING_GRAPH_VISUALIZER_H_
