175 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8/// \file9///10/// This file implements methods from the CodeRegions interface.11///12//===----------------------------------------------------------------------===//13 14#include "CodeRegion.h"15 16namespace llvm {17namespace mca {18 19bool 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 27void 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 34AnalysisRegions::AnalysisRegions(llvm::SourceMgr &S) : CodeRegions(S) {35 // Create a default region for the input code sequence.36 Regions.emplace_back(std::make_unique<CodeRegion>("", SMLoc()));37}38 39void 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>(Description, Loc);47 return;48 }49 } else {50 auto It = ActiveRegions.find(Description);51 if (It != ActiveRegions.end()) {52 const CodeRegion &R = *Regions[It->second];53 if (Description.empty()) {54 SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,55 "found multiple overlapping anonymous regions");56 SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,57 "Previous anonymous region was defined here");58 FoundErrors = true;59 return;60 }61 62 SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,63 "overlapping regions cannot have the same name");64 SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,65 "region " + Description + " was previously defined here");66 FoundErrors = true;67 return;68 }69 }70 71 ActiveRegions[Description] = Regions.size();72 Regions.emplace_back(std::make_unique<CodeRegion>(Description, Loc));73}74 75void 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 terminate80 // the only active region.81 if (ActiveRegions.size() == 1) {82 auto It = ActiveRegions.begin();83 Regions[It->second]->setEndLocation(Loc);84 ActiveRegions.erase(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(Description);97 if (It != ActiveRegions.end()) {98 Regions[It->second]->setEndLocation(Loc);99 ActiveRegions.erase(It);100 return;101 }102 103 FoundErrors = true;104 SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,105 "found an invalid region end directive");106 if (!Description.empty()) {107 SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,108 "unable to find an active region named " + Description);109 } else {110 SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,111 "unable to find an active anonymous region");112 }113}114 115InstrumentRegions::InstrumentRegions(llvm::SourceMgr &S) : CodeRegions(S) {}116 117void InstrumentRegions::beginRegion(StringRef Description, SMLoc Loc,118 UniqueInstrument I) {119 if (Description.empty()) {120 SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,121 "anonymous instrumentation regions are not permitted");122 FoundErrors = true;123 return;124 }125 126 auto [It, Inserted] = ActiveRegions.try_emplace(Description, Regions.size());127 if (!Inserted) {128 const CodeRegion &R = *Regions[It->second];129 SM.PrintMessage(130 Loc, llvm::SourceMgr::DK_Error,131 "overlapping instrumentation regions cannot be of the same kind");132 SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,133 "instrumentation region " + Description +134 " was previously defined here");135 FoundErrors = true;136 return;137 }138 139 Regions.emplace_back(140 std::make_unique<InstrumentRegion>(Description, Loc, std::move(I)));141}142 143void InstrumentRegions::endRegion(StringRef Description, SMLoc Loc) {144 auto It = ActiveRegions.find(Description);145 if (It != ActiveRegions.end()) {146 Regions[It->second]->setEndLocation(Loc);147 ActiveRegions.erase(It);148 return;149 }150 151 FoundErrors = true;152 SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,153 "found an invalid instrumentation region end directive");154 if (!Description.empty()) {155 SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,156 "unable to find an active instrumentation region named " +157 Description);158 }159}160 161SmallVector<Instrument *>162InstrumentRegions::getActiveInstruments(SMLoc Loc) const {163 SmallVector<Instrument *> AI;164 for (auto &R : Regions) {165 if (R->isLocInRange(Loc)) {166 InstrumentRegion *IR = static_cast<InstrumentRegion *>(R.get());167 AI.push_back(IR->getInstrument());168 }169 }170 return AI;171}172 173} // namespace mca174} // namespace llvm175