forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			118 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			118 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===-------------------------- CodeRegion.cpp -----------------*- C++ -* -===//
 | |
| //
 | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | |
| // See https://llvm.org/LICENSE.txt for license information.
 | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| /// \file
 | |
| ///
 | |
| /// This file implements methods from the CodeRegions interface.
 | |
| ///
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "CodeRegion.h"
 | |
| 
 | |
| namespace llvm {
 | |
| namespace mca {
 | |
| 
 | |
| CodeRegions::CodeRegions(llvm::SourceMgr &S) : SM(S), FoundErrors(false) {
 | |
|   // Create a default region for the input code sequence.
 | |
|   Regions.emplace_back(std::make_unique<CodeRegion>("", SMLoc()));
 | |
| }
 | |
| 
 | |
| bool CodeRegion::isLocInRange(SMLoc Loc) const {
 | |
|   if (RangeEnd.isValid() && Loc.getPointer() > RangeEnd.getPointer())
 | |
|     return false;
 | |
|   if (RangeStart.isValid() && Loc.getPointer() < RangeStart.getPointer())
 | |
|     return false;
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| void CodeRegions::beginRegion(StringRef Description, SMLoc Loc) {
 | |
|   if (ActiveRegions.empty()) {
 | |
|     // Remove the default region if there is at least one user defined region.
 | |
|     // By construction, only the default region has an invalid start location.
 | |
|     if (Regions.size() == 1 && !Regions[0]->startLoc().isValid() &&
 | |
|         !Regions[0]->endLoc().isValid()) {
 | |
|       ActiveRegions[Description] = 0;
 | |
|       Regions[0] = std::make_unique<CodeRegion>(Description, Loc);
 | |
|       return;
 | |
|     }
 | |
|   } else {
 | |
|     auto It = ActiveRegions.find(Description);
 | |
|     if (It != ActiveRegions.end()) {
 | |
|       const CodeRegion &R = *Regions[It->second];
 | |
|       if (Description.empty()) {
 | |
|         SM.PrintMessage(Loc, SourceMgr::DK_Error,
 | |
|                         "found multiple overlapping anonymous regions");
 | |
|         SM.PrintMessage(R.startLoc(), SourceMgr::DK_Note,
 | |
|                         "Previous anonymous region was defined here");
 | |
|         FoundErrors = true;
 | |
|         return;
 | |
|       }
 | |
| 
 | |
|       SM.PrintMessage(Loc, SourceMgr::DK_Error,
 | |
|                       "overlapping regions cannot have the same name");
 | |
|       SM.PrintMessage(R.startLoc(), SourceMgr::DK_Note,
 | |
|                       "region " + Description + " was previously defined here");
 | |
|       FoundErrors = true;
 | |
|       return;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   ActiveRegions[Description] = Regions.size();
 | |
|   Regions.emplace_back(std::make_unique<CodeRegion>(Description, Loc));
 | |
|   return;
 | |
| }
 | |
| 
 | |
| void CodeRegions::endRegion(StringRef Description, SMLoc Loc) {
 | |
|   if (Description.empty()) {
 | |
|     // Special case where there is only one user defined region,
 | |
|     // and this LLVM-MCA-END directive doesn't provide a region name.
 | |
|     // In this case, we assume that the user simply wanted to just terminate
 | |
|     // the only active region.
 | |
|     if (ActiveRegions.size() == 1) {
 | |
|       auto It = ActiveRegions.begin();
 | |
|       Regions[It->second]->setEndLocation(Loc);
 | |
|       ActiveRegions.erase(It);
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     // Special case where the region end marker applies to the default region.
 | |
|     if (ActiveRegions.empty() && Regions.size() == 1 &&
 | |
|         !Regions[0]->startLoc().isValid() && !Regions[0]->endLoc().isValid()) {
 | |
|       Regions[0]->setEndLocation(Loc);
 | |
|       return;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   auto It = ActiveRegions.find(Description);
 | |
|   if (It != ActiveRegions.end()) {
 | |
|     Regions[It->second]->setEndLocation(Loc);
 | |
|     ActiveRegions.erase(It);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   FoundErrors = true;
 | |
|   SM.PrintMessage(Loc, SourceMgr::DK_Error,
 | |
|                   "found an invalid region end directive");
 | |
|   if (!Description.empty()) {
 | |
|     SM.PrintMessage(Loc, SourceMgr::DK_Note,
 | |
|                     "unable to find an active region named " + Description);
 | |
|   } else {
 | |
|     SM.PrintMessage(Loc, SourceMgr::DK_Note,
 | |
|                     "unable to find an active anonymous region");
 | |
|   }
 | |
| }
 | |
| 
 | |
| void CodeRegions::addInstruction(const MCInst &Instruction) {
 | |
|   SMLoc Loc = Instruction.getLoc();
 | |
|   for (UniqueCodeRegion &Region : Regions)
 | |
|     if (Region->isLocInRange(Loc))
 | |
|       Region->addInstruction(Instruction);
 | |
| }
 | |
| 
 | |
| } // namespace mca
 | |
| } // namespace llvm
 |