1c6590128SAndrea Di Biagio //===-------------------------- CodeRegion.cpp -----------------*- C++ -* -===//
2c6590128SAndrea Di Biagio //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c6590128SAndrea Di Biagio //
7c6590128SAndrea Di Biagio //===----------------------------------------------------------------------===//
8c6590128SAndrea Di Biagio /// \file
9c6590128SAndrea Di Biagio ///
10c6590128SAndrea Di Biagio /// This file implements methods from the CodeRegions interface.
11c6590128SAndrea Di Biagio ///
12c6590128SAndrea Di Biagio //===----------------------------------------------------------------------===//
13c6590128SAndrea Di Biagio 
14c6590128SAndrea Di Biagio #include "CodeRegion.h"
15c6590128SAndrea Di Biagio 
165a8fd657SFangrui Song namespace llvm {
17c6590128SAndrea Di Biagio namespace mca {
18c6590128SAndrea Di Biagio 
CodeRegions(llvm::SourceMgr & S)194e62554bSAndrea Di Biagio CodeRegions::CodeRegions(llvm::SourceMgr &S) : SM(S), FoundErrors(false) {
2086654dd8SAndrea Di Biagio   // Create a default region for the input code sequence.
21*0eaee545SJonas Devlieghere   Regions.emplace_back(std::make_unique<CodeRegion>("", SMLoc()));
2286654dd8SAndrea Di Biagio }
2386654dd8SAndrea Di Biagio 
isLocInRange(SMLoc Loc) const2486654dd8SAndrea Di Biagio bool CodeRegion::isLocInRange(SMLoc Loc) const {
25c6590128SAndrea Di Biagio   if (RangeEnd.isValid() && Loc.getPointer() > RangeEnd.getPointer())
26c6590128SAndrea Di Biagio     return false;
27c6590128SAndrea Di Biagio   if (RangeStart.isValid() && Loc.getPointer() < RangeStart.getPointer())
28c6590128SAndrea Di Biagio     return false;
29c6590128SAndrea Di Biagio   return true;
30c6590128SAndrea Di Biagio }
31c6590128SAndrea Di Biagio 
beginRegion(StringRef Description,SMLoc Loc)3286654dd8SAndrea Di Biagio void CodeRegions::beginRegion(StringRef Description, SMLoc Loc) {
334e62554bSAndrea Di Biagio   if (ActiveRegions.empty()) {
344e62554bSAndrea Di Biagio     // Remove the default region if there is at least one user defined region.
354e62554bSAndrea Di Biagio     // By construction, only the default region has an invalid start location.
364e62554bSAndrea Di Biagio     if (Regions.size() == 1 && !Regions[0]->startLoc().isValid() &&
374e62554bSAndrea Di Biagio         !Regions[0]->endLoc().isValid()) {
384e62554bSAndrea Di Biagio       ActiveRegions[Description] = 0;
39*0eaee545SJonas Devlieghere       Regions[0] = std::make_unique<CodeRegion>(Description, Loc);
404e62554bSAndrea Di Biagio       return;
414e62554bSAndrea Di Biagio     }
424e62554bSAndrea Di Biagio   } else {
434e62554bSAndrea Di Biagio     auto It = ActiveRegions.find(Description);
444e62554bSAndrea Di Biagio     if (It != ActiveRegions.end()) {
454e62554bSAndrea Di Biagio       const CodeRegion &R = *Regions[It->second];
464e62554bSAndrea Di Biagio       if (Description.empty()) {
474e62554bSAndrea Di Biagio         SM.PrintMessage(Loc, SourceMgr::DK_Error,
484e62554bSAndrea Di Biagio                         "found multiple overlapping anonymous regions");
494e62554bSAndrea Di Biagio         SM.PrintMessage(R.startLoc(), SourceMgr::DK_Note,
504e62554bSAndrea Di Biagio                         "Previous anonymous region was defined here");
514e62554bSAndrea Di Biagio         FoundErrors = true;
52c6590128SAndrea Di Biagio         return;
53c6590128SAndrea Di Biagio       }
54c6590128SAndrea Di Biagio 
554e62554bSAndrea Di Biagio       SM.PrintMessage(Loc, SourceMgr::DK_Error,
564e62554bSAndrea Di Biagio                       "overlapping regions cannot have the same name");
574e62554bSAndrea Di Biagio       SM.PrintMessage(R.startLoc(), SourceMgr::DK_Note,
584e62554bSAndrea Di Biagio                       "region " + Description + " was previously defined here");
594e62554bSAndrea Di Biagio       FoundErrors = true;
604e62554bSAndrea Di Biagio       return;
614e62554bSAndrea Di Biagio     }
624e62554bSAndrea Di Biagio   }
634e62554bSAndrea Di Biagio 
644e62554bSAndrea Di Biagio   ActiveRegions[Description] = Regions.size();
65*0eaee545SJonas Devlieghere   Regions.emplace_back(std::make_unique<CodeRegion>(Description, Loc));
66c6590128SAndrea Di Biagio }
67c6590128SAndrea Di Biagio 
endRegion(StringRef Description,SMLoc Loc)684e62554bSAndrea Di Biagio void CodeRegions::endRegion(StringRef Description, SMLoc Loc) {
694e62554bSAndrea Di Biagio   if (Description.empty()) {
704e62554bSAndrea Di Biagio     // Special case where there is only one user defined region,
714e62554bSAndrea Di Biagio     // and this LLVM-MCA-END directive doesn't provide a region name.
724e62554bSAndrea Di Biagio     // In this case, we assume that the user simply wanted to just terminate
734e62554bSAndrea Di Biagio     // the only active region.
744e62554bSAndrea Di Biagio     if (ActiveRegions.size() == 1) {
754e62554bSAndrea Di Biagio       auto It = ActiveRegions.begin();
764e62554bSAndrea Di Biagio       Regions[It->second]->setEndLocation(Loc);
774e62554bSAndrea Di Biagio       ActiveRegions.erase(It);
784e62554bSAndrea Di Biagio       return;
794e62554bSAndrea Di Biagio     }
804e62554bSAndrea Di Biagio 
814e62554bSAndrea Di Biagio     // Special case where the region end marker applies to the default region.
824e62554bSAndrea Di Biagio     if (ActiveRegions.empty() && Regions.size() == 1 &&
834e62554bSAndrea Di Biagio         !Regions[0]->startLoc().isValid() && !Regions[0]->endLoc().isValid()) {
844e62554bSAndrea Di Biagio       Regions[0]->setEndLocation(Loc);
854e62554bSAndrea Di Biagio       return;
864e62554bSAndrea Di Biagio     }
874e62554bSAndrea Di Biagio   }
884e62554bSAndrea Di Biagio 
894e62554bSAndrea Di Biagio   auto It = ActiveRegions.find(Description);
904e62554bSAndrea Di Biagio   if (It != ActiveRegions.end()) {
914e62554bSAndrea Di Biagio     Regions[It->second]->setEndLocation(Loc);
924e62554bSAndrea Di Biagio     ActiveRegions.erase(It);
934e62554bSAndrea Di Biagio     return;
944e62554bSAndrea Di Biagio   }
954e62554bSAndrea Di Biagio 
964e62554bSAndrea Di Biagio   FoundErrors = true;
974e62554bSAndrea Di Biagio   SM.PrintMessage(Loc, SourceMgr::DK_Error,
984e62554bSAndrea Di Biagio                   "found an invalid region end directive");
994e62554bSAndrea Di Biagio   if (!Description.empty()) {
1004e62554bSAndrea Di Biagio     SM.PrintMessage(Loc, SourceMgr::DK_Note,
1014e62554bSAndrea Di Biagio                     "unable to find an active region named " + Description);
1024e62554bSAndrea Di Biagio   } else {
1034e62554bSAndrea Di Biagio     SM.PrintMessage(Loc, SourceMgr::DK_Note,
1044e62554bSAndrea Di Biagio                     "unable to find an active anonymous region");
1054e62554bSAndrea Di Biagio   }
106c6590128SAndrea Di Biagio }
107c6590128SAndrea Di Biagio 
addInstruction(const MCInst & Instruction)10886654dd8SAndrea Di Biagio void CodeRegions::addInstruction(const MCInst &Instruction) {
1094e62554bSAndrea Di Biagio   SMLoc Loc = Instruction.getLoc();
1104e62554bSAndrea Di Biagio   for (UniqueCodeRegion &Region : Regions)
1114e62554bSAndrea Di Biagio     if (Region->isLocInRange(Loc))
1124e62554bSAndrea Di Biagio       Region->addInstruction(Instruction);
113c6590128SAndrea Di Biagio }
114c6590128SAndrea Di Biagio 
115c6590128SAndrea Di Biagio } // namespace mca
1165a8fd657SFangrui Song } // namespace llvm
117