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