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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// \file 9 /// 10 /// This file implements methods from the CodeRegions interface. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #include "CodeRegion.h" 15 16 namespace llvm { 17 namespace mca { 18 19 bool 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 27 void 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 34 AnalysisRegions::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 39 void 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 75 void 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 terminate 80 // 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 115 InstrumentRegions::InstrumentRegions(llvm::SourceMgr &S) : CodeRegions(S) {} 116 117 void InstrumentRegions::beginRegion(StringRef Description, SMLoc Loc, 118 SharedInstrument 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 = ActiveRegions.find(Description); 127 if (It != ActiveRegions.end()) { 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 ActiveRegions[Description] = Regions.size(); 140 Regions.emplace_back(std::make_unique<InstrumentRegion>(Description, Loc, I)); 141 } 142 143 void 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 161 const SmallVector<SharedInstrument> 162 InstrumentRegions::getActiveInstruments(SMLoc Loc) const { 163 SmallVector<SharedInstrument> AI; 164 for (auto &R : Regions) { 165 if (R->isLocInRange(Loc)) { 166 InstrumentRegion *IR = static_cast<InstrumentRegion *>(R.get()); 167 AI.emplace_back(IR->getInstrument()); 168 } 169 } 170 return AI; 171 } 172 173 } // namespace mca 174 } // namespace llvm 175