CodeRegion.cpp revision 360784
1//===-------------------------- CodeRegion.cpp -----------------*- 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 methods from the CodeRegions interface.
11///
12//===----------------------------------------------------------------------===//
13
14#include "CodeRegion.h"
15
16namespace llvm {
17namespace mca {
18
19CodeRegions::CodeRegions(llvm::SourceMgr &S) : SM(S), FoundErrors(false) {
20  // Create a default region for the input code sequence.
21  Regions.emplace_back(std::make_unique<CodeRegion>("", SMLoc()));
22}
23
24bool CodeRegion::isLocInRange(SMLoc Loc) const {
25  if (RangeEnd.isValid() && Loc.getPointer() > RangeEnd.getPointer())
26    return false;
27  if (RangeStart.isValid() && Loc.getPointer() < RangeStart.getPointer())
28    return false;
29  return true;
30}
31
32void CodeRegions::beginRegion(StringRef Description, SMLoc Loc) {
33  if (ActiveRegions.empty()) {
34    // Remove the default region if there is at least one user defined region.
35    // By construction, only the default region has an invalid start location.
36    if (Regions.size() == 1 && !Regions[0]->startLoc().isValid() &&
37        !Regions[0]->endLoc().isValid()) {
38      ActiveRegions[Description] = 0;
39      Regions[0] = std::make_unique<CodeRegion>(Description, Loc);
40      return;
41    }
42  } else {
43    auto It = ActiveRegions.find(Description);
44    if (It != ActiveRegions.end()) {
45      const CodeRegion &R = *Regions[It->second];
46      if (Description.empty()) {
47        SM.PrintMessage(Loc, SourceMgr::DK_Error,
48                        "found multiple overlapping anonymous regions");
49        SM.PrintMessage(R.startLoc(), SourceMgr::DK_Note,
50                        "Previous anonymous region was defined here");
51        FoundErrors = true;
52        return;
53      }
54
55      SM.PrintMessage(Loc, SourceMgr::DK_Error,
56                      "overlapping regions cannot have the same name");
57      SM.PrintMessage(R.startLoc(), SourceMgr::DK_Note,
58                      "region " + Description + " was previously defined here");
59      FoundErrors = true;
60      return;
61    }
62  }
63
64  ActiveRegions[Description] = Regions.size();
65  Regions.emplace_back(std::make_unique<CodeRegion>(Description, Loc));
66  return;
67}
68
69void CodeRegions::endRegion(StringRef Description, SMLoc Loc) {
70  if (Description.empty()) {
71    // Special case where there is only one user defined region,
72    // and this LLVM-MCA-END directive doesn't provide a region name.
73    // In this case, we assume that the user simply wanted to just terminate
74    // the only active region.
75    if (ActiveRegions.size() == 1) {
76      auto It = ActiveRegions.begin();
77      Regions[It->second]->setEndLocation(Loc);
78      ActiveRegions.erase(It);
79      return;
80    }
81
82    // Special case where the region end marker applies to the default region.
83    if (ActiveRegions.empty() && Regions.size() == 1 &&
84        !Regions[0]->startLoc().isValid() && !Regions[0]->endLoc().isValid()) {
85      Regions[0]->setEndLocation(Loc);
86      return;
87    }
88  }
89
90  auto It = ActiveRegions.find(Description);
91  if (It != ActiveRegions.end()) {
92    Regions[It->second]->setEndLocation(Loc);
93    ActiveRegions.erase(It);
94    return;
95  }
96
97  FoundErrors = true;
98  SM.PrintMessage(Loc, SourceMgr::DK_Error,
99                  "found an invalid region end directive");
100  if (!Description.empty()) {
101    SM.PrintMessage(Loc, SourceMgr::DK_Note,
102                    "unable to find an active region named " + Description);
103  } else {
104    SM.PrintMessage(Loc, SourceMgr::DK_Note,
105                    "unable to find an active anonymous region");
106  }
107}
108
109void CodeRegions::addInstruction(const MCInst &Instruction) {
110  SMLoc Loc = Instruction.getLoc();
111  for (UniqueCodeRegion &Region : Regions)
112    if (Region->isLocInRange(Loc))
113      Region->addInstruction(Instruction);
114}
115
116} // namespace mca
117} // namespace llvm
118