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 CodeRegions::CodeRegions(llvm::SourceMgr &S) : SM(S), FoundErrors(false) { 20 // Create a default region for the input code sequence. 21 Regions.emplace_back(std::make_unique<CodeRegion>("", SMLoc())); 22 } 23 24 bool CodeRegion::isLocInRange(SMLoc Loc) const { 25 if (RangeEnd.isValid() && Loc.getPointer() > RangeEnd.getPointer()) 26 return false; 27 if (RangeStart.isValid() && Loc.getPointer() < RangeStart.getPointer()) 28 return false; 29 return true; 30 } 31 32 void CodeRegions::beginRegion(StringRef Description, SMLoc Loc) { 33 if (ActiveRegions.empty()) { 34 // Remove the default region if there is at least one user defined region. 35 // By construction, only the default region has an invalid start location. 36 if (Regions.size() == 1 && !Regions[0]->startLoc().isValid() && 37 !Regions[0]->endLoc().isValid()) { 38 ActiveRegions[Description] = 0; 39 Regions[0] = std::make_unique<CodeRegion>(Description, Loc); 40 return; 41 } 42 } else { 43 auto It = ActiveRegions.find(Description); 44 if (It != ActiveRegions.end()) { 45 const CodeRegion &R = *Regions[It->second]; 46 if (Description.empty()) { 47 SM.PrintMessage(Loc, SourceMgr::DK_Error, 48 "found multiple overlapping anonymous regions"); 49 SM.PrintMessage(R.startLoc(), SourceMgr::DK_Note, 50 "Previous anonymous region was defined here"); 51 FoundErrors = true; 52 return; 53 } 54 55 SM.PrintMessage(Loc, SourceMgr::DK_Error, 56 "overlapping regions cannot have the same name"); 57 SM.PrintMessage(R.startLoc(), SourceMgr::DK_Note, 58 "region " + Description + " was previously defined here"); 59 FoundErrors = true; 60 return; 61 } 62 } 63 64 ActiveRegions[Description] = Regions.size(); 65 Regions.emplace_back(std::make_unique<CodeRegion>(Description, Loc)); 66 return; 67 } 68 69 void CodeRegions::endRegion(StringRef Description, SMLoc Loc) { 70 if (Description.empty()) { 71 // Special case where there is only one user defined region, 72 // and this LLVM-MCA-END directive doesn't provide a region name. 73 // In this case, we assume that the user simply wanted to just terminate 74 // the only active region. 75 if (ActiveRegions.size() == 1) { 76 auto It = ActiveRegions.begin(); 77 Regions[It->second]->setEndLocation(Loc); 78 ActiveRegions.erase(It); 79 return; 80 } 81 82 // Special case where the region end marker applies to the default region. 83 if (ActiveRegions.empty() && Regions.size() == 1 && 84 !Regions[0]->startLoc().isValid() && !Regions[0]->endLoc().isValid()) { 85 Regions[0]->setEndLocation(Loc); 86 return; 87 } 88 } 89 90 auto It = ActiveRegions.find(Description); 91 if (It != ActiveRegions.end()) { 92 Regions[It->second]->setEndLocation(Loc); 93 ActiveRegions.erase(It); 94 return; 95 } 96 97 FoundErrors = true; 98 SM.PrintMessage(Loc, SourceMgr::DK_Error, 99 "found an invalid region end directive"); 100 if (!Description.empty()) { 101 SM.PrintMessage(Loc, SourceMgr::DK_Note, 102 "unable to find an active region named " + Description); 103 } else { 104 SM.PrintMessage(Loc, SourceMgr::DK_Note, 105 "unable to find an active anonymous region"); 106 } 107 } 108 109 void CodeRegions::addInstruction(const MCInst &Instruction) { 110 SMLoc Loc = Instruction.getLoc(); 111 for (UniqueCodeRegion &Region : Regions) 112 if (Region->isLocInRange(Loc)) 113 Region->addInstruction(Instruction); 114 } 115 116 } // namespace mca 117 } // namespace llvm 118