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