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(Str: 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=*/ArchName: "" , TheTriple, Error); |
37 | if (!TheTarget) { |
38 | return make_error<StringError>(Args: "no LLVM target for triple " + TripleName, |
39 | Args: 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(TheTriple: TripleName, CPU: CpuName, Features: "" )); |
50 | assert(STI && "Unable to create subtarget info!" ); |
51 | if (!STI->isCPUStringValid(CPU: CpuName)) { |
52 | return make_error<StringError>(Args: Twine("invalid CPU name (" ) |
53 | .concat(Suffix: CpuName) |
54 | .concat(Suffix: ") for triple " ) |
55 | .concat(Suffix: TripleName), |
56 | Args: inconvertibleErrorCode()); |
57 | } |
58 | const TargetOptions Options; |
59 | std::unique_ptr<const TargetMachine> TM( |
60 | static_cast<LLVMTargetMachine *>(TheTarget->createTargetMachine( |
61 | TT: TripleName, CPU: CpuName, Features, Options, RM: Reloc::Model::Static))); |
62 | if (!TM) { |
63 | return make_error<StringError>(Args: "unable to create target machine" , |
64 | Args: inconvertibleErrorCode()); |
65 | } |
66 | |
67 | const ExegesisTarget *ET = |
68 | TripleName.empty() ? &ExegesisTarget::getDefault() |
69 | : ExegesisTarget::lookup(TT: TM->getTargetTriple()); |
70 | if (!ET) { |
71 | return make_error<StringError>(Args: "no Exegesis target for triple " + |
72 | TripleName, |
73 | Args: inconvertibleErrorCode()); |
74 | } |
75 | const PfmCountersInfo &PCI = UseDummyPerfCounters |
76 | ? ET->getDummyPfmCounters() |
77 | : ET->getPfmCounters(CpuName); |
78 | return LLVMState(std::move(TM), ET, &PCI); |
79 | } |
80 | |
81 | LLVMState::LLVMState(std::unique_ptr<const TargetMachine> TM, |
82 | const ExegesisTarget *ET, const PfmCountersInfo *PCI) |
83 | : TheExegesisTarget(ET), TheTargetMachine(std::move(TM)), PfmCounters(PCI), |
84 | OpcodeNameToOpcodeIdxMapping(createOpcodeNameToOpcodeIdxMapping()), |
85 | RegNameToRegNoMapping(createRegNameToRegNoMapping()) { |
86 | BitVector ReservedRegs = getFunctionReservedRegs(TM: getTargetMachine()); |
87 | for (const unsigned Reg : TheExegesisTarget->getUnavailableRegisters()) |
88 | ReservedRegs.set(Reg); |
89 | RATC.reset( |
90 | p: new RegisterAliasingTrackerCache(getRegInfo(), std::move(ReservedRegs))); |
91 | IC.reset(p: new InstructionsCache(getInstrInfo(), getRATC())); |
92 | } |
93 | |
94 | std::unique_ptr<LLVMTargetMachine> LLVMState::createTargetMachine() const { |
95 | return std::unique_ptr<LLVMTargetMachine>(static_cast<LLVMTargetMachine *>( |
96 | TheTargetMachine->getTarget().createTargetMachine( |
97 | TT: TheTargetMachine->getTargetTriple().normalize(), |
98 | CPU: TheTargetMachine->getTargetCPU(), |
99 | Features: TheTargetMachine->getTargetFeatureString(), Options: TheTargetMachine->Options, |
100 | RM: Reloc::Model::Static))); |
101 | } |
102 | |
103 | std::unique_ptr<const DenseMap<StringRef, unsigned>> |
104 | LLVMState::createOpcodeNameToOpcodeIdxMapping() const { |
105 | const MCInstrInfo &InstrInfo = getInstrInfo(); |
106 | auto Map = std::make_unique<DenseMap<StringRef, unsigned>>( |
107 | args: InstrInfo.getNumOpcodes()); |
108 | for (unsigned I = 0, E = InstrInfo.getNumOpcodes(); I < E; ++I) |
109 | (*Map)[InstrInfo.getName(Opcode: 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>> |
115 | LLVMState::createRegNameToRegNoMapping() const { |
116 | const MCRegisterInfo &RegInfo = getRegInfo(); |
117 | auto Map = |
118 | std::make_unique<DenseMap<StringRef, unsigned>>(args: 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(RegNo: I)] = I; |
123 | assert(Map->size() == RegInfo.getNumRegs() && "Size prediction failed" ); |
124 | return std::move(Map); |
125 | } |
126 | |
127 | 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 | II: *TheTargetMachine->getMCInstrInfo(), Ctx&: Context)); |
135 | assert(CodeEmitter && "unable to create code emitter" ); |
136 | SmallVector<char, 16> Tmp; |
137 | SmallVector<MCFixup, 4> Fixups; |
138 | CodeEmitter->encodeInstruction(Inst, CB&: Tmp, Fixups, |
139 | STI: *TheTargetMachine->getMCSubtargetInfo()); |
140 | return Tmp.size() > 0; |
141 | } |
142 | |
143 | } // namespace exegesis |
144 | } // namespace llvm |
145 | |