146 lines
6 KiB
C++
146 lines
6 KiB
C++
|
//===-- 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
|