10b57cec5SDimitry Andric //===-------------------------- CodeRegion.cpp -----------------*- C++ -* -===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric /// \file
90b57cec5SDimitry Andric ///
100b57cec5SDimitry Andric /// This file implements methods from the CodeRegions interface.
110b57cec5SDimitry Andric ///
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "CodeRegion.h"
150b57cec5SDimitry Andric
160b57cec5SDimitry Andric namespace llvm {
170b57cec5SDimitry Andric namespace mca {
180b57cec5SDimitry Andric
isLocInRange(SMLoc Loc) const190b57cec5SDimitry Andric bool CodeRegion::isLocInRange(SMLoc Loc) const {
200b57cec5SDimitry Andric if (RangeEnd.isValid() && Loc.getPointer() > RangeEnd.getPointer())
210b57cec5SDimitry Andric return false;
220b57cec5SDimitry Andric if (RangeStart.isValid() && Loc.getPointer() < RangeStart.getPointer())
230b57cec5SDimitry Andric return false;
240b57cec5SDimitry Andric return true;
250b57cec5SDimitry Andric }
260b57cec5SDimitry Andric
addInstruction(const MCInst & Instruction)27bdd1243dSDimitry Andric void CodeRegions::addInstruction(const MCInst &Instruction) {
28bdd1243dSDimitry Andric SMLoc Loc = Instruction.getLoc();
29bdd1243dSDimitry Andric for (UniqueCodeRegion &Region : Regions)
30bdd1243dSDimitry Andric if (Region->isLocInRange(Loc))
31bdd1243dSDimitry Andric Region->addInstruction(Instruction);
32bdd1243dSDimitry Andric }
33bdd1243dSDimitry Andric
AnalysisRegions(llvm::SourceMgr & S)34bdd1243dSDimitry Andric AnalysisRegions::AnalysisRegions(llvm::SourceMgr &S) : CodeRegions(S) {
35bdd1243dSDimitry Andric // Create a default region for the input code sequence.
36bdd1243dSDimitry Andric Regions.emplace_back(std::make_unique<CodeRegion>("", SMLoc()));
37bdd1243dSDimitry Andric }
38bdd1243dSDimitry Andric
beginRegion(StringRef Description,SMLoc Loc)39bdd1243dSDimitry Andric void AnalysisRegions::beginRegion(StringRef Description, SMLoc Loc) {
400b57cec5SDimitry Andric if (ActiveRegions.empty()) {
410b57cec5SDimitry Andric // Remove the default region if there is at least one user defined region.
420b57cec5SDimitry Andric // By construction, only the default region has an invalid start location.
430b57cec5SDimitry Andric if (Regions.size() == 1 && !Regions[0]->startLoc().isValid() &&
440b57cec5SDimitry Andric !Regions[0]->endLoc().isValid()) {
450b57cec5SDimitry Andric ActiveRegions[Description] = 0;
468bcb0991SDimitry Andric Regions[0] = std::make_unique<CodeRegion>(Description, Loc);
470b57cec5SDimitry Andric return;
480b57cec5SDimitry Andric }
490b57cec5SDimitry Andric } else {
500b57cec5SDimitry Andric auto It = ActiveRegions.find(Description);
510b57cec5SDimitry Andric if (It != ActiveRegions.end()) {
520b57cec5SDimitry Andric const CodeRegion &R = *Regions[It->second];
530b57cec5SDimitry Andric if (Description.empty()) {
54bdd1243dSDimitry Andric SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
550b57cec5SDimitry Andric "found multiple overlapping anonymous regions");
56bdd1243dSDimitry Andric SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,
570b57cec5SDimitry Andric "Previous anonymous region was defined here");
580b57cec5SDimitry Andric FoundErrors = true;
590b57cec5SDimitry Andric return;
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric
62bdd1243dSDimitry Andric SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
630b57cec5SDimitry Andric "overlapping regions cannot have the same name");
64bdd1243dSDimitry Andric SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,
650b57cec5SDimitry Andric "region " + Description + " was previously defined here");
660b57cec5SDimitry Andric FoundErrors = true;
670b57cec5SDimitry Andric return;
680b57cec5SDimitry Andric }
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric
710b57cec5SDimitry Andric ActiveRegions[Description] = Regions.size();
728bcb0991SDimitry Andric Regions.emplace_back(std::make_unique<CodeRegion>(Description, Loc));
730b57cec5SDimitry Andric }
740b57cec5SDimitry Andric
endRegion(StringRef Description,SMLoc Loc)75bdd1243dSDimitry Andric void AnalysisRegions::endRegion(StringRef Description, SMLoc Loc) {
760b57cec5SDimitry Andric if (Description.empty()) {
770b57cec5SDimitry Andric // Special case where there is only one user defined region,
780b57cec5SDimitry Andric // and this LLVM-MCA-END directive doesn't provide a region name.
790b57cec5SDimitry Andric // In this case, we assume that the user simply wanted to just terminate
800b57cec5SDimitry Andric // the only active region.
810b57cec5SDimitry Andric if (ActiveRegions.size() == 1) {
820b57cec5SDimitry Andric auto It = ActiveRegions.begin();
830b57cec5SDimitry Andric Regions[It->second]->setEndLocation(Loc);
840b57cec5SDimitry Andric ActiveRegions.erase(It);
850b57cec5SDimitry Andric return;
860b57cec5SDimitry Andric }
870b57cec5SDimitry Andric
880b57cec5SDimitry Andric // Special case where the region end marker applies to the default region.
890b57cec5SDimitry Andric if (ActiveRegions.empty() && Regions.size() == 1 &&
900b57cec5SDimitry Andric !Regions[0]->startLoc().isValid() && !Regions[0]->endLoc().isValid()) {
910b57cec5SDimitry Andric Regions[0]->setEndLocation(Loc);
920b57cec5SDimitry Andric return;
930b57cec5SDimitry Andric }
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric
960b57cec5SDimitry Andric auto It = ActiveRegions.find(Description);
970b57cec5SDimitry Andric if (It != ActiveRegions.end()) {
980b57cec5SDimitry Andric Regions[It->second]->setEndLocation(Loc);
990b57cec5SDimitry Andric ActiveRegions.erase(It);
1000b57cec5SDimitry Andric return;
1010b57cec5SDimitry Andric }
1020b57cec5SDimitry Andric
1030b57cec5SDimitry Andric FoundErrors = true;
104bdd1243dSDimitry Andric SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
1050b57cec5SDimitry Andric "found an invalid region end directive");
1060b57cec5SDimitry Andric if (!Description.empty()) {
107bdd1243dSDimitry Andric SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,
1080b57cec5SDimitry Andric "unable to find an active region named " + Description);
1090b57cec5SDimitry Andric } else {
110bdd1243dSDimitry Andric SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,
1110b57cec5SDimitry Andric "unable to find an active anonymous region");
1120b57cec5SDimitry Andric }
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric
InstrumentRegions(llvm::SourceMgr & S)115bdd1243dSDimitry Andric InstrumentRegions::InstrumentRegions(llvm::SourceMgr &S) : CodeRegions(S) {}
116bdd1243dSDimitry Andric
beginRegion(StringRef Description,SMLoc Loc,UniqueInstrument I)117bdd1243dSDimitry Andric void InstrumentRegions::beginRegion(StringRef Description, SMLoc Loc,
118*06c3fb27SDimitry Andric UniqueInstrument I) {
119bdd1243dSDimitry Andric if (Description.empty()) {
120bdd1243dSDimitry Andric SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
121bdd1243dSDimitry Andric "anonymous instrumentation regions are not permitted");
122bdd1243dSDimitry Andric FoundErrors = true;
123bdd1243dSDimitry Andric return;
124bdd1243dSDimitry Andric }
125bdd1243dSDimitry Andric
126bdd1243dSDimitry Andric auto It = ActiveRegions.find(Description);
127bdd1243dSDimitry Andric if (It != ActiveRegions.end()) {
128bdd1243dSDimitry Andric const CodeRegion &R = *Regions[It->second];
129bdd1243dSDimitry Andric SM.PrintMessage(
130bdd1243dSDimitry Andric Loc, llvm::SourceMgr::DK_Error,
131bdd1243dSDimitry Andric "overlapping instrumentation regions cannot be of the same kind");
132bdd1243dSDimitry Andric SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,
133bdd1243dSDimitry Andric "instrumentation region " + Description +
134bdd1243dSDimitry Andric " was previously defined here");
135bdd1243dSDimitry Andric FoundErrors = true;
136bdd1243dSDimitry Andric return;
137bdd1243dSDimitry Andric }
138bdd1243dSDimitry Andric
139bdd1243dSDimitry Andric ActiveRegions[Description] = Regions.size();
140*06c3fb27SDimitry Andric Regions.emplace_back(
141*06c3fb27SDimitry Andric std::make_unique<InstrumentRegion>(Description, Loc, std::move(I)));
142bdd1243dSDimitry Andric }
143bdd1243dSDimitry Andric
endRegion(StringRef Description,SMLoc Loc)144bdd1243dSDimitry Andric void InstrumentRegions::endRegion(StringRef Description, SMLoc Loc) {
145bdd1243dSDimitry Andric auto It = ActiveRegions.find(Description);
146bdd1243dSDimitry Andric if (It != ActiveRegions.end()) {
147bdd1243dSDimitry Andric Regions[It->second]->setEndLocation(Loc);
148bdd1243dSDimitry Andric ActiveRegions.erase(It);
149bdd1243dSDimitry Andric return;
150bdd1243dSDimitry Andric }
151bdd1243dSDimitry Andric
152bdd1243dSDimitry Andric FoundErrors = true;
153bdd1243dSDimitry Andric SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
154bdd1243dSDimitry Andric "found an invalid instrumentation region end directive");
155bdd1243dSDimitry Andric if (!Description.empty()) {
156bdd1243dSDimitry Andric SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,
157bdd1243dSDimitry Andric "unable to find an active instrumentation region named " +
158bdd1243dSDimitry Andric Description);
159bdd1243dSDimitry Andric }
160bdd1243dSDimitry Andric }
161bdd1243dSDimitry Andric
162*06c3fb27SDimitry Andric const SmallVector<Instrument *>
getActiveInstruments(SMLoc Loc) const163bdd1243dSDimitry Andric InstrumentRegions::getActiveInstruments(SMLoc Loc) const {
164*06c3fb27SDimitry Andric SmallVector<Instrument *> AI;
165bdd1243dSDimitry Andric for (auto &R : Regions) {
166bdd1243dSDimitry Andric if (R->isLocInRange(Loc)) {
167bdd1243dSDimitry Andric InstrumentRegion *IR = static_cast<InstrumentRegion *>(R.get());
168*06c3fb27SDimitry Andric AI.push_back(IR->getInstrument());
169bdd1243dSDimitry Andric }
170bdd1243dSDimitry Andric }
171bdd1243dSDimitry Andric return AI;
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric
1740b57cec5SDimitry Andric } // namespace mca
1750b57cec5SDimitry Andric } // namespace llvm
176