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 | |
19 | 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 | |
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 | |
34 | AnalysisRegions::AnalysisRegions(llvm::SourceMgr &S) : CodeRegions(S) { |
35 | // Create a default region for the input code sequence. |
36 | Regions.emplace_back(args: std::make_unique<CodeRegion>(args: "" , args: SMLoc())); |
37 | } |
38 | |
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>(args&: Description, args&: Loc); |
47 | return; |
48 | } |
49 | } else { |
50 | auto It = ActiveRegions.find(Key: Description); |
51 | if (It != ActiveRegions.end()) { |
52 | const CodeRegion &R = *Regions[It->second]; |
53 | if (Description.empty()) { |
54 | SM.PrintMessage(Loc, Kind: llvm::SourceMgr::DK_Error, |
55 | Msg: "found multiple overlapping anonymous regions" ); |
56 | SM.PrintMessage(Loc: R.startLoc(), Kind: llvm::SourceMgr::DK_Note, |
57 | Msg: "Previous anonymous region was defined here" ); |
58 | FoundErrors = true; |
59 | return; |
60 | } |
61 | |
62 | SM.PrintMessage(Loc, Kind: llvm::SourceMgr::DK_Error, |
63 | Msg: "overlapping regions cannot have the same name" ); |
64 | SM.PrintMessage(Loc: R.startLoc(), Kind: llvm::SourceMgr::DK_Note, |
65 | Msg: "region " + Description + " was previously defined here" ); |
66 | FoundErrors = true; |
67 | return; |
68 | } |
69 | } |
70 | |
71 | ActiveRegions[Description] = Regions.size(); |
72 | Regions.emplace_back(args: std::make_unique<CodeRegion>(args&: Description, args&: Loc)); |
73 | } |
74 | |
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(I: 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(Key: Description); |
97 | if (It != ActiveRegions.end()) { |
98 | Regions[It->second]->setEndLocation(Loc); |
99 | ActiveRegions.erase(I: It); |
100 | return; |
101 | } |
102 | |
103 | FoundErrors = true; |
104 | SM.PrintMessage(Loc, Kind: llvm::SourceMgr::DK_Error, |
105 | Msg: "found an invalid region end directive" ); |
106 | if (!Description.empty()) { |
107 | SM.PrintMessage(Loc, Kind: llvm::SourceMgr::DK_Note, |
108 | Msg: "unable to find an active region named " + Description); |
109 | } else { |
110 | SM.PrintMessage(Loc, Kind: llvm::SourceMgr::DK_Note, |
111 | Msg: "unable to find an active anonymous region" ); |
112 | } |
113 | } |
114 | |
115 | InstrumentRegions::InstrumentRegions(llvm::SourceMgr &S) : CodeRegions(S) {} |
116 | |
117 | void InstrumentRegions::beginRegion(StringRef Description, SMLoc Loc, |
118 | UniqueInstrument I) { |
119 | if (Description.empty()) { |
120 | SM.PrintMessage(Loc, Kind: llvm::SourceMgr::DK_Error, |
121 | Msg: "anonymous instrumentation regions are not permitted" ); |
122 | FoundErrors = true; |
123 | return; |
124 | } |
125 | |
126 | auto It = ActiveRegions.find(Key: Description); |
127 | if (It != ActiveRegions.end()) { |
128 | const CodeRegion &R = *Regions[It->second]; |
129 | SM.PrintMessage( |
130 | Loc, Kind: llvm::SourceMgr::DK_Error, |
131 | Msg: "overlapping instrumentation regions cannot be of the same kind" ); |
132 | SM.PrintMessage(Loc: R.startLoc(), Kind: llvm::SourceMgr::DK_Note, |
133 | Msg: "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 | args: std::make_unique<InstrumentRegion>(args&: Description, args&: Loc, args: std::move(I))); |
142 | } |
143 | |
144 | void InstrumentRegions::endRegion(StringRef Description, SMLoc Loc) { |
145 | auto It = ActiveRegions.find(Key: Description); |
146 | if (It != ActiveRegions.end()) { |
147 | Regions[It->second]->setEndLocation(Loc); |
148 | ActiveRegions.erase(I: It); |
149 | return; |
150 | } |
151 | |
152 | FoundErrors = true; |
153 | SM.PrintMessage(Loc, Kind: llvm::SourceMgr::DK_Error, |
154 | Msg: "found an invalid instrumentation region end directive" ); |
155 | if (!Description.empty()) { |
156 | SM.PrintMessage(Loc, Kind: llvm::SourceMgr::DK_Note, |
157 | Msg: "unable to find an active instrumentation region named " + |
158 | Description); |
159 | } |
160 | } |
161 | |
162 | const SmallVector<Instrument *> |
163 | 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(Elt: IR->getInstrument()); |
169 | } |
170 | } |
171 | return AI; |
172 | } |
173 | |
174 | } // namespace mca |
175 | } // namespace llvm |
176 | |