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
 |