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