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
16 namespace llvm {
17 namespace mca {
18
isLocInRange(SMLoc Loc) const19 bool CodeRegion::isLocInRange(SMLoc Loc) const {
20 if (RangeEnd.isValid() && Loc.getPointer() > RangeEnd.getPointer())
21 return false;
22 if (RangeStart.isValid() && Loc.getPointer() < RangeStart.getPointer())
23 return false;
24 return true;
25 }
26
addInstruction(const MCInst & Instruction)27 void CodeRegions::addInstruction(const MCInst &Instruction) {
28 SMLoc Loc = Instruction.getLoc();
29 for (UniqueCodeRegion &Region : Regions)
30 if (Region->isLocInRange(Loc))
31 Region->addInstruction(Instruction);
32 }
33
AnalysisRegions(llvm::SourceMgr & S)34 AnalysisRegions::AnalysisRegions(llvm::SourceMgr &S) : CodeRegions(S) {
35 // Create a default region for the input code sequence.
36 Regions.emplace_back(std::make_unique<CodeRegion>("", SMLoc()));
37 }
38
beginRegion(StringRef Description,SMLoc Loc)39 void AnalysisRegions::beginRegion(StringRef Description, SMLoc Loc) {
40 if (ActiveRegions.empty()) {
41 // Remove the default region if there is at least one user defined region.
42 // By construction, only the default region has an invalid start location.
43 if (Regions.size() == 1 && !Regions[0]->startLoc().isValid() &&
44 !Regions[0]->endLoc().isValid()) {
45 ActiveRegions[Description] = 0;
46 Regions[0] = std::make_unique<CodeRegion>(Description, Loc);
47 return;
48 }
49 } else {
50 auto It = ActiveRegions.find(Description);
51 if (It != ActiveRegions.end()) {
52 const CodeRegion &R = *Regions[It->second];
53 if (Description.empty()) {
54 SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
55 "found multiple overlapping anonymous regions");
56 SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,
57 "Previous anonymous region was defined here");
58 FoundErrors = true;
59 return;
60 }
61
62 SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
63 "overlapping regions cannot have the same name");
64 SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,
65 "region " + Description + " was previously defined here");
66 FoundErrors = true;
67 return;
68 }
69 }
70
71 ActiveRegions[Description] = Regions.size();
72 Regions.emplace_back(std::make_unique<CodeRegion>(Description, Loc));
73 }
74
endRegion(StringRef Description,SMLoc Loc)75 void AnalysisRegions::endRegion(StringRef Description, SMLoc Loc) {
76 if (Description.empty()) {
77 // Special case where there is only one user defined region,
78 // and this LLVM-MCA-END directive doesn't provide a region name.
79 // In this case, we assume that the user simply wanted to just terminate
80 // the only active region.
81 if (ActiveRegions.size() == 1) {
82 auto It = ActiveRegions.begin();
83 Regions[It->second]->setEndLocation(Loc);
84 ActiveRegions.erase(It);
85 return;
86 }
87
88 // Special case where the region end marker applies to the default region.
89 if (ActiveRegions.empty() && Regions.size() == 1 &&
90 !Regions[0]->startLoc().isValid() && !Regions[0]->endLoc().isValid()) {
91 Regions[0]->setEndLocation(Loc);
92 return;
93 }
94 }
95
96 auto It = ActiveRegions.find(Description);
97 if (It != ActiveRegions.end()) {
98 Regions[It->second]->setEndLocation(Loc);
99 ActiveRegions.erase(It);
100 return;
101 }
102
103 FoundErrors = true;
104 SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
105 "found an invalid region end directive");
106 if (!Description.empty()) {
107 SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,
108 "unable to find an active region named " + Description);
109 } else {
110 SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,
111 "unable to find an active anonymous region");
112 }
113 }
114
InstrumentRegions(llvm::SourceMgr & S)115 InstrumentRegions::InstrumentRegions(llvm::SourceMgr &S) : CodeRegions(S) {}
116
beginRegion(StringRef Description,SMLoc Loc,UniqueInstrument I)117 void InstrumentRegions::beginRegion(StringRef Description, SMLoc Loc,
118 UniqueInstrument I) {
119 if (Description.empty()) {
120 SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
121 "anonymous instrumentation regions are not permitted");
122 FoundErrors = true;
123 return;
124 }
125
126 auto It = ActiveRegions.find(Description);
127 if (It != ActiveRegions.end()) {
128 const CodeRegion &R = *Regions[It->second];
129 SM.PrintMessage(
130 Loc, llvm::SourceMgr::DK_Error,
131 "overlapping instrumentation regions cannot be of the same kind");
132 SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,
133 "instrumentation region " + Description +
134 " was previously defined here");
135 FoundErrors = true;
136 return;
137 }
138
139 ActiveRegions[Description] = Regions.size();
140 Regions.emplace_back(
141 std::make_unique<InstrumentRegion>(Description, Loc, std::move(I)));
142 }
143
endRegion(StringRef Description,SMLoc Loc)144 void InstrumentRegions::endRegion(StringRef Description, SMLoc Loc) {
145 auto It = ActiveRegions.find(Description);
146 if (It != ActiveRegions.end()) {
147 Regions[It->second]->setEndLocation(Loc);
148 ActiveRegions.erase(It);
149 return;
150 }
151
152 FoundErrors = true;
153 SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
154 "found an invalid instrumentation region end directive");
155 if (!Description.empty()) {
156 SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,
157 "unable to find an active instrumentation region named " +
158 Description);
159 }
160 }
161
162 const SmallVector<Instrument *>
getActiveInstruments(SMLoc Loc) const163 InstrumentRegions::getActiveInstruments(SMLoc Loc) const {
164 SmallVector<Instrument *> AI;
165 for (auto &R : Regions) {
166 if (R->isLocInRange(Loc)) {
167 InstrumentRegion *IR = static_cast<InstrumentRegion *>(R.get());
168 AI.push_back(IR->getInstrument());
169 }
170 }
171 return AI;
172 }
173
174 } // namespace mca
175 } // namespace llvm
176