view llvm/tools/llvm-exegesis/lib/LlvmState.cpp @ 266:00f31e85ec16 default tip

Added tag current for changeset 31d058e83c98
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sat, 14 Oct 2023 10:13:55 +0900
parents 1f2b6ac9f198
children
line wrap: on
line source

//===-- LlvmState.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
//
//===----------------------------------------------------------------------===//

#include "LlvmState.h"
#include "Target.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCFixup.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/TargetParser/Host.h"

namespace llvm {
namespace exegesis {

Expected<LLVMState> LLVMState::Create(std::string TripleName,
                                      std::string CpuName,
                                      const StringRef Features,
                                      bool UseDummyPerfCounters) {
  if (TripleName.empty())
    TripleName = Triple::normalize(sys::getDefaultTargetTriple());

  Triple TheTriple(TripleName);

  // Get the target specific parser.
  std::string Error;
  const Target *TheTarget =
      TargetRegistry::lookupTarget(/*MArch=*/"", TheTriple, Error);
  if (!TheTarget) {
    return llvm::make_error<llvm::StringError>("no LLVM target for triple " +
                                                   TripleName,
                                               llvm::inconvertibleErrorCode());
  }

  // Update Triple with the updated triple from the target lookup.
  TripleName = TheTriple.str();

  if (CpuName == "native")
    CpuName = std::string(llvm::sys::getHostCPUName());

  std::unique_ptr<MCSubtargetInfo> STI(
      TheTarget->createMCSubtargetInfo(TripleName, CpuName, ""));
  assert(STI && "Unable to create subtarget info!");
  if (!STI->isCPUStringValid(CpuName)) {
    return llvm::make_error<llvm::StringError>(Twine("invalid CPU name (")
                                                   .concat(CpuName)
                                                   .concat(") for triple ")
                                                   .concat(TripleName),
                                               llvm::inconvertibleErrorCode());
  }
  const TargetOptions Options;
  std::unique_ptr<const TargetMachine> TM(
      static_cast<LLVMTargetMachine *>(TheTarget->createTargetMachine(
          TripleName, CpuName, Features, Options, Reloc::Model::Static)));
  if (!TM) {
    return llvm::make_error<llvm::StringError>(
        "unable to create target machine", llvm::inconvertibleErrorCode());
  }

  const ExegesisTarget *ET =
      TripleName.empty() ? &ExegesisTarget::getDefault()
                         : ExegesisTarget::lookup(TM->getTargetTriple());
  if (!ET) {
    return llvm::make_error<llvm::StringError>(
        "no Exegesis target for triple " + TripleName,
        llvm::inconvertibleErrorCode());
  }
  const PfmCountersInfo &PCI = UseDummyPerfCounters
                                   ? ET->getDummyPfmCounters()
                                   : ET->getPfmCounters(CpuName);
  return LLVMState(std::move(TM), ET, &PCI);
}

LLVMState::LLVMState(std::unique_ptr<const TargetMachine> TM,
                     const ExegesisTarget *ET, const PfmCountersInfo *PCI)
    : TheExegesisTarget(ET), TheTargetMachine(std::move(TM)), PfmCounters(PCI),
      OpcodeNameToOpcodeIdxMapping(createOpcodeNameToOpcodeIdxMapping()),
      RegNameToRegNoMapping(createRegNameToRegNoMapping()) {
  BitVector ReservedRegs = getFunctionReservedRegs(getTargetMachine());
  for (const unsigned Reg : TheExegesisTarget->getUnavailableRegisters())
    ReservedRegs.set(Reg);
  RATC.reset(
      new RegisterAliasingTrackerCache(getRegInfo(), std::move(ReservedRegs)));
  IC.reset(new InstructionsCache(getInstrInfo(), getRATC()));
}

std::unique_ptr<LLVMTargetMachine> LLVMState::createTargetMachine() const {
  return std::unique_ptr<LLVMTargetMachine>(static_cast<LLVMTargetMachine *>(
      TheTargetMachine->getTarget().createTargetMachine(
          TheTargetMachine->getTargetTriple().normalize(),
          TheTargetMachine->getTargetCPU(),
          TheTargetMachine->getTargetFeatureString(), TheTargetMachine->Options,
          Reloc::Model::Static)));
}

std::unique_ptr<const DenseMap<StringRef, unsigned>>
LLVMState::createOpcodeNameToOpcodeIdxMapping() const {
  const MCInstrInfo &InstrInfo = getInstrInfo();
  auto Map = std::make_unique<DenseMap<StringRef, unsigned>>(
      InstrInfo.getNumOpcodes());
  for (unsigned I = 0, E = InstrInfo.getNumOpcodes(); I < E; ++I)
    (*Map)[InstrInfo.getName(I)] = I;
  assert(Map->size() == InstrInfo.getNumOpcodes() && "Size prediction failed");
  return std::move(Map);
}

std::unique_ptr<const DenseMap<StringRef, unsigned>>
LLVMState::createRegNameToRegNoMapping() const {
  const MCRegisterInfo &RegInfo = getRegInfo();
  auto Map =
      std::make_unique<DenseMap<StringRef, unsigned>>(RegInfo.getNumRegs());
  // Special-case RegNo 0, which would otherwise be spelled as ''.
  (*Map)[kNoRegister] = 0;
  for (unsigned I = 1, E = RegInfo.getNumRegs(); I < E; ++I)
    (*Map)[RegInfo.getName(I)] = I;
  assert(Map->size() == RegInfo.getNumRegs() && "Size prediction failed");
  return std::move(Map);
}

bool LLVMState::canAssemble(const MCInst &Inst) const {
  MCContext Context(TheTargetMachine->getTargetTriple(),
                    TheTargetMachine->getMCAsmInfo(),
                    TheTargetMachine->getMCRegisterInfo(),
                    TheTargetMachine->getMCSubtargetInfo());
  std::unique_ptr<const MCCodeEmitter> CodeEmitter(
      TheTargetMachine->getTarget().createMCCodeEmitter(
          *TheTargetMachine->getMCInstrInfo(), Context));
  assert(CodeEmitter && "unable to create code emitter");
  SmallVector<char, 16> Tmp;
  SmallVector<MCFixup, 4> Fixups;
  CodeEmitter->encodeInstruction(Inst, Tmp, Fixups,
                                 *TheTargetMachine->getMCSubtargetInfo());
  return Tmp.size() > 0;
}

} // namespace exegesis
} // namespace llvm