1//===-------------------------- CodeRegion.h -------------------*- C++ -* -===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9///
10/// This file implements class CodeRegion and CodeRegions.
11///
12/// A CodeRegion describes a region of assembly code guarded by special LLVM-MCA
13/// comment directives.
14///
15///   # LLVM-MCA-BEGIN foo
16///     ...  ## asm
17///   # LLVM-MCA-END
18///
19/// A comment starting with substring LLVM-MCA-BEGIN marks the beginning of a
20/// new region of code.
21/// A comment starting with substring LLVM-MCA-END marks the end of the
22/// last-seen region of code.
23///
24/// Code regions are not allowed to overlap. Each region can have a optional
25/// description; internally, regions are described by a range of source
26/// locations (SMLoc objects).
27///
28/// An instruction (a MCInst) is added to a region R only if its location is in
29/// range [R.RangeStart, R.RangeEnd].
30//
31//===----------------------------------------------------------------------===//
32
33#ifndef LLVM_TOOLS_LLVM_MCA_CODEREGION_H
34#define LLVM_TOOLS_LLVM_MCA_CODEREGION_H
35
36#include "llvm/ADT/ArrayRef.h"
37#include "llvm/ADT/SmallVector.h"
38#include "llvm/ADT/StringMap.h"
39#include "llvm/ADT/StringRef.h"
40#include "llvm/MC/MCInst.h"
41#include "llvm/Support/Error.h"
42#include "llvm/Support/SMLoc.h"
43#include "llvm/Support/SourceMgr.h"
44#include <vector>
45
46namespace llvm {
47namespace mca {
48
49/// A region of assembly code.
50///
51/// It identifies a sequence of machine instructions.
52class CodeRegion {
53  // An optional descriptor for this region.
54  llvm::StringRef Description;
55  // Instructions that form this region.
56  llvm::SmallVector<llvm::MCInst, 8> Instructions;
57  // Source location range.
58  llvm::SMLoc RangeStart;
59  llvm::SMLoc RangeEnd;
60
61  CodeRegion(const CodeRegion &) = delete;
62  CodeRegion &operator=(const CodeRegion &) = delete;
63
64public:
65  CodeRegion(llvm::StringRef Desc, llvm::SMLoc Start)
66      : Description(Desc), RangeStart(Start), RangeEnd() {}
67
68  void addInstruction(const llvm::MCInst &Instruction) {
69    Instructions.emplace_back(Instruction);
70  }
71
72  llvm::SMLoc startLoc() const { return RangeStart; }
73  llvm::SMLoc endLoc() const { return RangeEnd; }
74
75  void setEndLocation(llvm::SMLoc End) { RangeEnd = End; }
76  bool empty() const { return Instructions.empty(); }
77  bool isLocInRange(llvm::SMLoc Loc) const;
78
79  llvm::ArrayRef<llvm::MCInst> getInstructions() const { return Instructions; }
80
81  llvm::StringRef getDescription() const { return Description; }
82};
83
84class CodeRegionParseError final : public Error {};
85
86class CodeRegions {
87  // A source manager. Used by the tool to generate meaningful warnings.
88  llvm::SourceMgr &SM;
89
90  using UniqueCodeRegion = std::unique_ptr<CodeRegion>;
91  std::vector<UniqueCodeRegion> Regions;
92  llvm::StringMap<unsigned> ActiveRegions;
93  bool FoundErrors;
94
95  CodeRegions(const CodeRegions &) = delete;
96  CodeRegions &operator=(const CodeRegions &) = delete;
97
98public:
99  CodeRegions(llvm::SourceMgr &S);
100
101  typedef std::vector<UniqueCodeRegion>::iterator iterator;
102  typedef std::vector<UniqueCodeRegion>::const_iterator const_iterator;
103
104  iterator begin() { return Regions.begin(); }
105  iterator end() { return Regions.end(); }
106  const_iterator begin() const { return Regions.cbegin(); }
107  const_iterator end() const { return Regions.cend(); }
108
109  void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc);
110  void endRegion(llvm::StringRef Description, llvm::SMLoc Loc);
111  void addInstruction(const llvm::MCInst &Instruction);
112  llvm::SourceMgr &getSourceMgr() const { return SM; }
113
114  llvm::ArrayRef<llvm::MCInst> getInstructionSequence(unsigned Idx) const {
115    return Regions[Idx]->getInstructions();
116  }
117
118  bool empty() const {
119    return llvm::all_of(Regions, [](const UniqueCodeRegion &Region) {
120      return Region->empty();
121    });
122  }
123
124  bool isValid() const { return !FoundErrors; }
125};
126
127} // namespace mca
128} // namespace llvm
129
130#endif
131