//===-------------------------- CodeRegion.h -------------------*- C++ -* -===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
/// \file
///
/// This file implements class CodeRegion and CodeRegions.
///
/// A CodeRegion describes a region of assembly code guarded by special LLVM-MCA
/// comment directives.
///
///   # LLVM-MCA-BEGIN foo
///     ...  ## asm
///   # LLVM-MCA-END
///
/// A comment starting with substring LLVM-MCA-BEGIN marks the beginning of a
/// new region of code.
/// A comment starting with substring LLVM-MCA-END marks the end of the
/// last-seen region of code.
///
/// Code regions are not allowed to overlap. Each region can have a optional
/// description; internally, regions are described by a range of source
/// locations (SMLoc objects).
///
/// An instruction (a MCInst) is added to a region R only if its location is in
/// range [R.RangeStart, R.RangeEnd].
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_TOOLS_LLVM_MCA_CODEREGION_H
#define LLVM_TOOLS_LLVM_MCA_CODEREGION_H

#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCInst.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/SourceMgr.h"
#include <vector>

namespace mca {

/// A region of assembly code.
///
/// It identifies a sequence of machine instructions.
class CodeRegion {
  // An optional descriptor for this region.
  llvm::StringRef Description;
  // Instructions that form this region.
  std::vector<std::unique_ptr<const llvm::MCInst>> Instructions;
  // Source location range.
  llvm::SMLoc RangeStart;
  llvm::SMLoc RangeEnd;

  CodeRegion(const CodeRegion &) = delete;
  CodeRegion &operator=(const CodeRegion &) = delete;

public:
  CodeRegion(llvm::StringRef Desc, llvm::SMLoc Start)
      : Description(Desc), RangeStart(Start), RangeEnd() {}

  void addInstruction(std::unique_ptr<const llvm::MCInst> Instruction) {
    Instructions.emplace_back(std::move(Instruction));
  }

  llvm::SMLoc startLoc() const { return RangeStart; }
  llvm::SMLoc endLoc() const { return RangeEnd; }

  void setEndLocation(llvm::SMLoc End) { RangeEnd = End; }
  bool empty() const { return Instructions.empty(); }
  bool isLocInRange(llvm::SMLoc Loc) const;

  const std::vector<std::unique_ptr<const llvm::MCInst>> &
  getInstructions() const {
    return Instructions;
  }

  llvm::StringRef getDescription() const { return Description; }
};

class CodeRegions {
  // A source manager. Used by the tool to generate meaningful warnings.
  llvm::SourceMgr &SM;

  std::vector<std::unique_ptr<CodeRegion>> Regions;

  // Construct a new region of code guarded by LLVM-MCA comments.
  void addRegion(llvm::StringRef Description, llvm::SMLoc Loc) {
    Regions.emplace_back(llvm::make_unique<CodeRegion>(Description, Loc));
  }

  CodeRegions(const CodeRegions &) = delete;
  CodeRegions &operator=(const CodeRegions &) = delete;

public:
  typedef std::vector<std::unique_ptr<CodeRegion>>::iterator iterator;
  typedef std::vector<std::unique_ptr<CodeRegion>>::const_iterator
      const_iterator;

  iterator begin() { return Regions.begin(); }
  iterator end() { return Regions.end(); }
  const_iterator begin() const { return Regions.cbegin(); }
  const_iterator end() const { return Regions.cend(); }

  void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc);
  void endRegion(llvm::SMLoc Loc);
  void addInstruction(std::unique_ptr<const llvm::MCInst> Instruction);

  CodeRegions(llvm::SourceMgr &S) : SM(S) {
    // Create a default region for the input code sequence.
    addRegion("Default", llvm::SMLoc());
  }

  const std::vector<std::unique_ptr<const llvm::MCInst>> &
  getInstructionSequence(unsigned Idx) const {
    return Regions[Idx]->getInstructions();
  }

  bool empty() const {
    return std::all_of(Regions.begin(), Regions.end(),
                       [](const std::unique_ptr<CodeRegion> &Region) {
                         return Region->empty();
                       });
  }
};

} // namespace mca

#endif
