blob: 7662538e3b68aa327639db63eb15e81ed4769d75 [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 {
CodeRegions::CodeRegions(llvm::SourceMgr &S) : SM(S), FoundErrors(false) {
// Create a default region for the input code sequence.
Regions.emplace_back(std::make_unique<CodeRegion>("", SMLoc()));
}
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::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, SourceMgr::DK_Error,
"found multiple overlapping anonymous regions");
SM.PrintMessage(R.startLoc(), SourceMgr::DK_Note,
"Previous anonymous region was defined here");
FoundErrors = true;
return;
}
SM.PrintMessage(Loc, SourceMgr::DK_Error,
"overlapping regions cannot have the same name");
SM.PrintMessage(R.startLoc(), 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 CodeRegions::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, SourceMgr::DK_Error,
"found an invalid region end directive");
if (!Description.empty()) {
SM.PrintMessage(Loc, SourceMgr::DK_Note,
"unable to find an active region named " + Description);
} else {
SM.PrintMessage(Loc, SourceMgr::DK_Note,
"unable to find an active anonymous region");
}
}
void CodeRegions::addInstruction(const MCInst &Instruction) {
SMLoc Loc = Instruction.getLoc();
for (UniqueCodeRegion &Region : Regions)
if (Region->isLocInRange(Loc))
Region->addInstruction(Instruction);
}
} // namespace mca
} // namespace llvm