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 
CodeRegions(llvm::SourceMgr & S)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 
isLocInRange(SMLoc Loc) const24 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 
beginRegion(StringRef Description,SMLoc Loc)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 
endRegion(StringRef Description,SMLoc Loc)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 
addInstruction(const MCInst & Instruction)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