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 } 67 68 void CodeRegions::endRegion(StringRef Description, SMLoc Loc) { 69 if (Description.empty()) { 70 // Special case where there is only one user defined region, 71 // and this LLVM-MCA-END directive doesn't provide a region name. 72 // In this case, we assume that the user simply wanted to just terminate 73 // the only active region. 74 if (ActiveRegions.size() == 1) { 75 auto It = ActiveRegions.begin(); 76 Regions[It->second]->setEndLocation(Loc); 77 ActiveRegions.erase(It); 78 return; 79 } 80 81 // Special case where the region end marker applies to the default region. 82 if (ActiveRegions.empty() && Regions.size() == 1 && 83 !Regions[0]->startLoc().isValid() && !Regions[0]->endLoc().isValid()) { 84 Regions[0]->setEndLocation(Loc); 85 return; 86 } 87 } 88 89 auto It = ActiveRegions.find(Description); 90 if (It != ActiveRegions.end()) { 91 Regions[It->second]->setEndLocation(Loc); 92 ActiveRegions.erase(It); 93 return; 94 } 95 96 FoundErrors = true; 97 SM.PrintMessage(Loc, SourceMgr::DK_Error, 98 "found an invalid region end directive"); 99 if (!Description.empty()) { 100 SM.PrintMessage(Loc, SourceMgr::DK_Note, 101 "unable to find an active region named " + Description); 102 } else { 103 SM.PrintMessage(Loc, SourceMgr::DK_Note, 104 "unable to find an active anonymous region"); 105 } 106 } 107 108 void CodeRegions::addInstruction(const MCInst &Instruction) { 109 SMLoc Loc = Instruction.getLoc(); 110 for (UniqueCodeRegion &Region : Regions) 111 if (Region->isLocInRange(Loc)) 112 Region->addInstruction(Instruction); 113 } 114 115 } // namespace mca 116 } // namespace llvm 117