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-exception
6//
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/Support/Host.h"
18#include "llvm/Support/raw_ostream.h"
19#include "llvm/Target/TargetMachine.h"
20#include "llvm/Target/TargetOptions.h"
21
22namespace llvm {
23namespace exegesis {
24
25Expected<LLVMState> LLVMState::Create(std::string TripleName,
26                                      std::string CpuName,
27                                      const StringRef Features) {
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 llvm::make_error<llvm::StringError>("no LLVM target for triple " +
39                                                   TripleName,
40                                               llvm::inconvertibleErrorCode());
41  }
42
43  // Update Triple with the updated triple from the target lookup.
44  TripleName = TheTriple.str();
45
46  if (CpuName == "native")
47    CpuName = std::string(llvm::sys::getHostCPUName());
48
49  std::unique_ptr<MCSubtargetInfo> STI(
50      TheTarget->createMCSubtargetInfo(TripleName, CpuName, ""));
51  assert(STI && "Unable to create subtarget info!");
52  if (!STI->isCPUStringValid(CpuName)) {
53    return llvm::make_error<llvm::StringError>(Twine("invalid CPU name (")
54                                                   .concat(CpuName)
55                                                   .concat(") for triple ")
56                                                   .concat(TripleName),
57                                               llvm::inconvertibleErrorCode());
58  }
59  const TargetOptions Options;
60  std::unique_ptr<const TargetMachine> TM(
61      static_cast<LLVMTargetMachine *>(TheTarget->createTargetMachine(
62          TripleName, CpuName, Features, Options, Reloc::Model::Static)));
63  if (!TM) {
64    return llvm::make_error<llvm::StringError>(
65        "unable to create target machine", llvm::inconvertibleErrorCode());
66  }
67
68  const ExegesisTarget *ET =
69      TripleName.empty() ? &ExegesisTarget::getDefault()
70                         : ExegesisTarget::lookup(TM->getTargetTriple());
71  if (!ET) {
72    return llvm::make_error<llvm::StringError>(
73        "no Exegesis target for triple " + TripleName,
74        llvm::inconvertibleErrorCode());
75  }
76  return LLVMState(std::move(TM), ET, CpuName);
77}
78
79LLVMState::LLVMState(std::unique_ptr<const TargetMachine> TM,
80                     const ExegesisTarget *ET, const StringRef CpuName)
81    : TheExegesisTarget(ET), TheTargetMachine(std::move(TM)),
82      OpcodeNameToOpcodeIdxMapping(createOpcodeNameToOpcodeIdxMapping()),
83      RegNameToRegNoMapping(createRegNameToRegNoMapping()) {
84  PfmCounters = &TheExegesisTarget->getPfmCounters(CpuName);
85
86  BitVector ReservedRegs = getFunctionReservedRegs(getTargetMachine());
87  for (const unsigned Reg : TheExegesisTarget->getUnavailableRegisters())
88    ReservedRegs.set(Reg);
89  RATC.reset(
90      new RegisterAliasingTrackerCache(getRegInfo(), std::move(ReservedRegs)));
91  IC.reset(new InstructionsCache(getInstrInfo(), getRATC()));
92}
93
94std::unique_ptr<LLVMTargetMachine> LLVMState::createTargetMachine() const {
95  return std::unique_ptr<LLVMTargetMachine>(static_cast<LLVMTargetMachine *>(
96      TheTargetMachine->getTarget().createTargetMachine(
97          TheTargetMachine->getTargetTriple().normalize(),
98          TheTargetMachine->getTargetCPU(),
99          TheTargetMachine->getTargetFeatureString(), TheTargetMachine->Options,
100          Reloc::Model::Static)));
101}
102
103std::unique_ptr<const DenseMap<StringRef, unsigned>>
104LLVMState::createOpcodeNameToOpcodeIdxMapping() const {
105  const MCInstrInfo &InstrInfo = getInstrInfo();
106  auto Map = std::make_unique<DenseMap<StringRef, unsigned>>(
107      InstrInfo.getNumOpcodes());
108  for (unsigned I = 0, E = InstrInfo.getNumOpcodes(); I < E; ++I)
109    (*Map)[InstrInfo.getName(I)] = I;
110  assert(Map->size() == InstrInfo.getNumOpcodes() && "Size prediction failed");
111  return std::move(Map);
112}
113
114std::unique_ptr<const DenseMap<StringRef, unsigned>>
115LLVMState::createRegNameToRegNoMapping() const {
116  const MCRegisterInfo &RegInfo = getRegInfo();
117  auto Map =
118      std::make_unique<DenseMap<StringRef, unsigned>>(RegInfo.getNumRegs());
119  // Special-case RegNo 0, which would otherwise be spelled as ''.
120  (*Map)[kNoRegister] = 0;
121  for (unsigned I = 1, E = RegInfo.getNumRegs(); I < E; ++I)
122    (*Map)[RegInfo.getName(I)] = I;
123  assert(Map->size() == RegInfo.getNumRegs() && "Size prediction failed");
124  return std::move(Map);
125}
126
127bool LLVMState::canAssemble(const MCInst &Inst) const {
128  MCContext Context(TheTargetMachine->getTargetTriple(),
129                    TheTargetMachine->getMCAsmInfo(),
130                    TheTargetMachine->getMCRegisterInfo(),
131                    TheTargetMachine->getMCSubtargetInfo());
132  std::unique_ptr<const MCCodeEmitter> CodeEmitter(
133      TheTargetMachine->getTarget().createMCCodeEmitter(
134          *TheTargetMachine->getMCInstrInfo(), Context));
135  assert(CodeEmitter && "unable to create code emitter");
136  SmallVector<char, 16> Tmp;
137  raw_svector_ostream OS(Tmp);
138  SmallVector<MCFixup, 4> Fixups;
139  CodeEmitter->encodeInstruction(Inst, OS, Fixups,
140                                 *TheTargetMachine->getMCSubtargetInfo());
141  return Tmp.size() > 0;
142}
143
144} // namespace exegesis
145} // namespace llvm
146