blob: ba5188076c2e746a9bce34d0214ddff8c0f6446e [file] [log] [blame]
//===-------------------------- CodeRegion.cpp -----------------*- C++ -* -===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
/// \file
///
/// This file implements methods from the CodeRegions interface.
///
//===----------------------------------------------------------------------===//
#include "CodeRegion.h"
namespace llvm {
namespace mca {
bool CodeRegion::isLocInRange(SMLoc Loc) const {
if (RangeEnd.isValid() && Loc.getPointer() > RangeEnd.getPointer())
return false;
if (RangeStart.isValid() && Loc.getPointer() < RangeStart.getPointer())
return false;
return true;
}
void CodeRegions::addInstruction(const MCInst &Instruction) {
SMLoc Loc = Instruction.getLoc();
for (UniqueCodeRegion &Region : Regions)
if (Region->isLocInRange(Loc))
Region->addInstruction(Instruction);
}
AnalysisRegions::AnalysisRegions(llvm::SourceMgr &S) : CodeRegions(S) {
// Create a default region for the input code sequence.
Regions.emplace_back(std::make_unique<CodeRegion>("", SMLoc()));
}
void AnalysisRegions::beginRegion(StringRef Description, SMLoc Loc) {
if (ActiveRegions.empty()) {
// Remove the default region if there is at least one user defined region.
// By construction, only the default region has an invalid start location.
if (Regions.size() == 1 && !Regions[0]->startLoc().isValid() &&
!Regions[0]->endLoc().isValid()) {
ActiveRegions[Description] = 0;
Regions[0] = std::make_unique<CodeRegion>(Description, Loc);
return;
}
} else {
auto It = ActiveRegions.find(Description);
if (It != ActiveRegions.end()) {
const CodeRegion &R = *Regions[It->second];
if (Description.empty()) {
SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
"found multiple overlapping anonymous regions");
SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,
"Previous anonymous region was defined here");
FoundErrors = true;
return;
}
SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
"overlapping regions cannot have the same name");
SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,
"region " + Description + " was previously defined here");
FoundErrors = true;
return;
}
}
ActiveRegions[Description] = Regions.size();
Regions.emplace_back(std::make_unique<CodeRegion>(Description, Loc));
}
void AnalysisRegions::endRegion(StringRef Description, SMLoc Loc) {
if (Description.empty()) {
// Special case where there is only one user defined region,
// and this LLVM-MCA-END directive doesn't provide a region name.
// In this case, we assume that the user simply wanted to just terminate
// the only active region.
if (ActiveRegions.size() == 1) {
auto It = ActiveRegions.begin();
Regions[It->second]->setEndLocation(Loc);
ActiveRegions.erase(It);
return;
}
// Special case where the region end marker applies to the default region.
if (ActiveRegions.empty() && Regions.size() == 1 &&
!Regions[0]->startLoc().isValid() && !Regions[0]->endLoc().isValid()) {
Regions[0]->setEndLocation(Loc);
return;
}
}
auto It = ActiveRegions.find(Description);
if (It != ActiveRegions.end()) {
Regions[It->second]->setEndLocation(Loc);
ActiveRegions.erase(It);
return;
}
FoundErrors = true;
SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
"found an invalid region end directive");
if (!Description.empty()) {
SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,
"unable to find an active region named " + Description);
} else {
SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,
"unable to find an active anonymous region");
}
}
InstrumentRegions::InstrumentRegions(llvm::SourceMgr &S) : CodeRegions(S) {}
void InstrumentRegions::beginRegion(StringRef Description, SMLoc Loc,
UniqueInstrument I) {
if (Description.empty()) {
SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
"anonymous instrumentation regions are not permitted");
FoundErrors = true;
return;
}
auto It = ActiveRegions.find(Description);
if (It != ActiveRegions.end()) {
const CodeRegion &R = *Regions[It->second];
SM.PrintMessage(
Loc, llvm::SourceMgr::DK_Error,
"overlapping instrumentation regions cannot be of the same kind");
SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,
"instrumentation region " + Description +
" was previously defined here");
FoundErrors = true;
return;
}
ActiveRegions[Description] = Regions.size();
Regions.emplace_back(
std::make_unique<InstrumentRegion>(Description, Loc, std::move(I)));
}
void InstrumentRegions::endRegion(StringRef Description, SMLoc Loc) {
auto It = ActiveRegions.find(Description);
if (It != ActiveRegions.end()) {
Regions[It->second]->setEndLocation(Loc);
ActiveRegions.erase(It);
return;
}
FoundErrors = true;
SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
"found an invalid instrumentation region end directive");
if (!Description.empty()) {
SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,
"unable to find an active instrumentation region named " +
Description);
}
}
const SmallVector<Instrument *>
InstrumentRegions::getActiveInstruments(SMLoc Loc) const {
SmallVector<Instrument *> AI;
for (auto &R : Regions) {
if (R->isLocInRange(Loc)) {
InstrumentRegion *IR = static_cast<InstrumentRegion *>(R.get());
AI.push_back(IR->getInstrument());
}
}
return AI;
}
} // namespace mca
} // namespace llvm