166 lines · cpp
1//===-- LlvmState.cpp -------------------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "LlvmState.h"10#include "Target.h"11#include "llvm/ADT/SmallVector.h"12#include "llvm/MC/MCCodeEmitter.h"13#include "llvm/MC/MCContext.h"14#include "llvm/MC/MCFixup.h"15#include "llvm/MC/MCObjectFileInfo.h"16#include "llvm/MC/TargetRegistry.h"17#include "llvm/Target/TargetMachine.h"18#include "llvm/Target/TargetOptions.h"19#include "llvm/TargetParser/Host.h"20 21namespace llvm {22namespace exegesis {23 24Expected<LLVMState> LLVMState::Create(std::string TripleName,25 std::string CpuName,26 const StringRef Features,27 bool UseDummyPerfCounters) {28 if (TripleName.empty())29 TripleName = Triple::normalize(sys::getDefaultTargetTriple());30 31 Triple TheTriple(TripleName);32 33 // Get the target specific parser.34 std::string Error;35 const Target *TheTarget =36 TargetRegistry::lookupTarget(/*MArch=*/"", TheTriple, Error);37 if (!TheTarget) {38 return make_error<StringError>("no LLVM target for triple " + TripleName,39 inconvertibleErrorCode());40 }41 42 // Update Triple with the updated triple from the target lookup.43 TripleName = TheTriple.str();44 45 if (CpuName == "native") {46 // case for cross generating, when native arch and target mismatch47 if ((Triple(sys::getProcessTriple()).getArch() !=48 Triple(TripleName).getArch()))49 return make_error<StringError>(50 "A CPU must be explicitly specified when cross compiling. To see all "51 "possible options for " +52 TripleName + " triple use -mcpu=help",53 inconvertibleErrorCode());54 CpuName = std::string(sys::getHostCPUName());55 }56 57 std::unique_ptr<MCSubtargetInfo> STI(58 TheTarget->createMCSubtargetInfo(TheTriple, CpuName, ""));59 if (!STI) {60 return make_error<StringError>("unable to create subtarget info",61 inconvertibleErrorCode());62 }63 64 assert(STI && "Unable to create subtarget info!");65 if (!STI->isCPUStringValid(CpuName)) {66 return make_error<StringError>(Twine("invalid CPU name (")67 .concat(CpuName)68 .concat(") for triple ")69 .concat(TripleName),70 inconvertibleErrorCode());71 }72 const TargetOptions Options;73 std::unique_ptr<const TargetMachine> TM(TheTarget->createTargetMachine(74 TheTriple, CpuName, Features, Options, Reloc::Model::Static));75 if (!TM) {76 return make_error<StringError>("unable to create target machine",77 inconvertibleErrorCode());78 }79 80 const ExegesisTarget *ET =81 TripleName.empty() ? &ExegesisTarget::getDefault()82 : ExegesisTarget::lookup(TM->getTargetTriple());83 if (!ET) {84 return make_error<StringError>("no Exegesis target for triple " +85 TripleName,86 inconvertibleErrorCode());87 }88 const PfmCountersInfo &PCI = UseDummyPerfCounters89 ? ET->getDummyPfmCounters()90 : ET->getPfmCounters(CpuName);91 return LLVMState(std::move(TM), ET, &PCI);92}93 94LLVMState::LLVMState(std::unique_ptr<const TargetMachine> TM,95 const ExegesisTarget *ET, const PfmCountersInfo *PCI)96 : TheExegesisTarget(ET), TheTargetMachine(std::move(TM)), PfmCounters(PCI),97 OpcodeNameToOpcodeIdxMapping(createOpcodeNameToOpcodeIdxMapping()),98 RegNameToRegNoMapping(createRegNameToRegNoMapping()) {99 BitVector ReservedRegs = getFunctionReservedRegs(getTargetMachine());100 for (const MCPhysReg Reg : TheExegesisTarget->getUnavailableRegisters())101 ReservedRegs.set(Reg);102 RATC.reset(103 new RegisterAliasingTrackerCache(getRegInfo(), std::move(ReservedRegs)));104 IC.reset(new InstructionsCache(getInstrInfo(), getRATC()));105}106 107std::unique_ptr<TargetMachine> LLVMState::createTargetMachine() const {108 return std::unique_ptr<TargetMachine>(109 TheTargetMachine->getTarget().createTargetMachine(110 Triple(TheTargetMachine->getTargetTriple().normalize()),111 TheTargetMachine->getTargetCPU(),112 TheTargetMachine->getTargetFeatureString(), TheTargetMachine->Options,113 Reloc::Model::Static));114}115 116std::optional<MCRegister>117LLVMState::getRegisterNumberFromName(StringRef RegisterName) const {118 auto RegisterIt = RegNameToRegNoMapping->find(RegisterName);119 if (RegisterIt == RegNameToRegNoMapping->end())120 return std::nullopt;121 return RegisterIt->second;122}123 124std::unique_ptr<const DenseMap<StringRef, unsigned>>125LLVMState::createOpcodeNameToOpcodeIdxMapping() const {126 const MCInstrInfo &InstrInfo = getInstrInfo();127 auto Map = std::make_unique<DenseMap<StringRef, unsigned>>(128 InstrInfo.getNumOpcodes());129 for (unsigned I = 0, E = InstrInfo.getNumOpcodes(); I < E; ++I)130 (*Map)[InstrInfo.getName(I)] = I;131 assert(Map->size() == InstrInfo.getNumOpcodes() && "Size prediction failed");132 return std::move(Map);133}134 135std::unique_ptr<const DenseMap<StringRef, MCRegister>>136LLVMState::createRegNameToRegNoMapping() const {137 const MCRegisterInfo &RegInfo = getRegInfo();138 auto Map =139 std::make_unique<DenseMap<StringRef, MCRegister>>(RegInfo.getNumRegs());140 // Special-case RegNo 0, which would otherwise be spelled as ''.141 (*Map)[kNoRegister] = 0;142 for (unsigned I = 1, E = RegInfo.getNumRegs(); I < E; ++I)143 (*Map)[RegInfo.getName(I)] = I;144 assert(Map->size() == RegInfo.getNumRegs() && "Size prediction failed");145 return std::move(Map);146}147 148bool LLVMState::canAssemble(const MCInst &Inst) const {149 MCContext Context(TheTargetMachine->getTargetTriple(),150 TheTargetMachine->getMCAsmInfo(),151 TheTargetMachine->getMCRegisterInfo(),152 TheTargetMachine->getMCSubtargetInfo());153 std::unique_ptr<const MCCodeEmitter> CodeEmitter(154 TheTargetMachine->getTarget().createMCCodeEmitter(155 *TheTargetMachine->getMCInstrInfo(), Context));156 assert(CodeEmitter && "unable to create code emitter");157 SmallVector<char, 16> Tmp;158 SmallVector<MCFixup, 4> Fixups;159 CodeEmitter->encodeInstruction(Inst, Tmp, Fixups,160 *TheTargetMachine->getMCSubtargetInfo());161 return Tmp.size() > 0;162}163 164} // namespace exegesis165} // namespace llvm166