Following discussions in #110443, and the following earlier discussions in https://lists.llvm.org/pipermail/llvm-dev/2017-October/117907.html, https://reviews.llvm.org/D38482, https://reviews.llvm.org/D38489, this PR attempts to overhaul the `TargetMachine` and `LLVMTargetMachine` interface classes. More specifically: 1. Makes `TargetMachine` the only class implemented under `TargetMachine.h` in the `Target` library. 2. `TargetMachine` contains target-specific interface functions that relate to IR/CodeGen/MC constructs, whereas before (at least on paper) it was supposed to have only IR/MC constructs. Any Target that doesn't want to use the independent code generator simply does not implement them, and returns either `false` or `nullptr`. 3. Renames `LLVMTargetMachine` to `CodeGenCommonTMImpl`. This renaming aims to make the purpose of `LLVMTargetMachine` clearer. Its interface was moved under the CodeGen library, to further emphasis its usage in Targets that use CodeGen directly. 4. Makes `TargetMachine` the only interface used across LLVM and its projects. With these changes, `CodeGenCommonTMImpl` is simply a set of shared function implementations of `TargetMachine`, and CodeGen users don't need to static cast to `LLVMTargetMachine` every time they need a CodeGen-specific feature of the `TargetMachine`. 5. More importantly, does not change any requirements regarding library linking. cc @arsenm @aeubanks
152 lines
6.0 KiB
C++
152 lines
6.0 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 make_error<StringError>("no LLVM target for triple " + TripleName,
|
|
inconvertibleErrorCode());
|
|
}
|
|
|
|
// Update Triple with the updated triple from the target lookup.
|
|
TripleName = TheTriple.str();
|
|
|
|
if (CpuName == "native")
|
|
CpuName = std::string(sys::getHostCPUName());
|
|
|
|
std::unique_ptr<MCSubtargetInfo> STI(
|
|
TheTarget->createMCSubtargetInfo(TripleName, CpuName, ""));
|
|
assert(STI && "Unable to create subtarget info!");
|
|
if (!STI->isCPUStringValid(CpuName)) {
|
|
return make_error<StringError>(Twine("invalid CPU name (")
|
|
.concat(CpuName)
|
|
.concat(") for triple ")
|
|
.concat(TripleName),
|
|
inconvertibleErrorCode());
|
|
}
|
|
const TargetOptions Options;
|
|
std::unique_ptr<const TargetMachine> TM(TheTarget->createTargetMachine(
|
|
TripleName, CpuName, Features, Options, Reloc::Model::Static));
|
|
if (!TM) {
|
|
return make_error<StringError>("unable to create target machine",
|
|
inconvertibleErrorCode());
|
|
}
|
|
|
|
const ExegesisTarget *ET =
|
|
TripleName.empty() ? &ExegesisTarget::getDefault()
|
|
: ExegesisTarget::lookup(TM->getTargetTriple());
|
|
if (!ET) {
|
|
return make_error<StringError>("no Exegesis target for triple " +
|
|
TripleName,
|
|
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<TargetMachine> LLVMState::createTargetMachine() const {
|
|
return std::unique_ptr<TargetMachine>(
|
|
TheTargetMachine->getTarget().createTargetMachine(
|
|
TheTargetMachine->getTargetTriple().normalize(),
|
|
TheTargetMachine->getTargetCPU(),
|
|
TheTargetMachine->getTargetFeatureString(), TheTargetMachine->Options,
|
|
Reloc::Model::Static));
|
|
}
|
|
|
|
std::optional<MCRegister>
|
|
LLVMState::getRegisterNumberFromName(StringRef RegisterName) const {
|
|
auto RegisterIt = RegNameToRegNoMapping->find(RegisterName);
|
|
if (RegisterIt == RegNameToRegNoMapping->end())
|
|
return std::nullopt;
|
|
return RegisterIt->second;
|
|
}
|
|
|
|
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, MCRegister>>
|
|
LLVMState::createRegNameToRegNoMapping() const {
|
|
const MCRegisterInfo &RegInfo = getRegInfo();
|
|
auto Map =
|
|
std::make_unique<DenseMap<StringRef, MCRegister>>(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
|