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 
22 namespace llvm {
23 namespace exegesis {
24 
Create(std::string TripleName,std::string CpuName,const StringRef Features)25 Expected<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 
LLVMState(std::unique_ptr<const TargetMachine> TM,const ExegesisTarget * ET,const StringRef CpuName)79 LLVMState::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 
createTargetMachine() const94 std::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 
103 std::unique_ptr<const DenseMap<StringRef, unsigned>>
createOpcodeNameToOpcodeIdxMapping() const104 LLVMState::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 
114 std::unique_ptr<const DenseMap<StringRef, unsigned>>
createRegNameToRegNoMapping() const115 LLVMState::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 
canAssemble(const MCInst & Inst) const127 bool 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