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