//===-------------------------- 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("", 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(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(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(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 InstrumentRegions::getActiveInstruments(SMLoc Loc) const { SmallVector AI; for (auto &R : Regions) { if (R->isLocInRange(Loc)) { InstrumentRegion *IR = static_cast(R.get()); AI.push_back(IR->getInstrument()); } } return AI; } } // namespace mca } // namespace llvm