1 | //===-- TargetMachine.cpp -------------------------------------------------===// |
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 | // This file implements the LLVM-C part of TargetMachine.h |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "llvm-c/Core.h" |
14 | #include "llvm-c/TargetMachine.h" |
15 | #include "llvm/Analysis/TargetTransformInfo.h" |
16 | #include "llvm/IR/DataLayout.h" |
17 | #include "llvm/IR/LegacyPassManager.h" |
18 | #include "llvm/IR/Module.h" |
19 | #include "llvm/MC/TargetRegistry.h" |
20 | #include "llvm/Support/CBindingWrapping.h" |
21 | #include "llvm/Support/FileSystem.h" |
22 | #include "llvm/Support/raw_ostream.h" |
23 | #include "llvm/Target/CodeGenCWrappers.h" |
24 | #include "llvm/Target/TargetMachine.h" |
25 | #include "llvm/TargetParser/Host.h" |
26 | #include "llvm/TargetParser/SubtargetFeature.h" |
27 | #include <cstring> |
28 | #include <optional> |
29 | |
30 | using namespace llvm; |
31 | |
32 | namespace llvm { |
33 | |
34 | /// Options for LLVMCreateTargetMachine(). |
35 | struct LLVMTargetMachineOptions { |
36 | std::string CPU; |
37 | std::string Features; |
38 | std::string ABI; |
39 | CodeGenOptLevel OL = CodeGenOptLevel::Default; |
40 | std::optional<Reloc::Model> RM; |
41 | std::optional<CodeModel::Model> CM; |
42 | bool JIT; |
43 | }; |
44 | |
45 | } // namespace llvm |
46 | |
47 | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMTargetMachineOptions, |
48 | LLVMTargetMachineOptionsRef) |
49 | |
50 | static TargetMachine *unwrap(LLVMTargetMachineRef P) { |
51 | return reinterpret_cast<TargetMachine *>(P); |
52 | } |
53 | static Target *unwrap(LLVMTargetRef P) { |
54 | return reinterpret_cast<Target*>(P); |
55 | } |
56 | static LLVMTargetMachineRef wrap(const TargetMachine *P) { |
57 | return reinterpret_cast<LLVMTargetMachineRef>(const_cast<TargetMachine *>(P)); |
58 | } |
59 | static LLVMTargetRef wrap(const Target * P) { |
60 | return reinterpret_cast<LLVMTargetRef>(const_cast<Target*>(P)); |
61 | } |
62 | |
63 | LLVMTargetRef LLVMGetFirstTarget() { |
64 | if (TargetRegistry::targets().begin() == TargetRegistry::targets().end()) { |
65 | return nullptr; |
66 | } |
67 | |
68 | const Target *target = &*TargetRegistry::targets().begin(); |
69 | return wrap(P: target); |
70 | } |
71 | LLVMTargetRef LLVMGetNextTarget(LLVMTargetRef T) { |
72 | return wrap(P: unwrap(P: T)->getNext()); |
73 | } |
74 | |
75 | LLVMTargetRef LLVMGetTargetFromName(const char *Name) { |
76 | StringRef NameRef = Name; |
77 | auto I = find_if(Range: TargetRegistry::targets(), |
78 | P: [&](const Target &T) { return T.getName() == NameRef; }); |
79 | return I != TargetRegistry::targets().end() ? wrap(P: &*I) : nullptr; |
80 | } |
81 | |
82 | LLVMBool LLVMGetTargetFromTriple(const char* TripleStr, LLVMTargetRef *T, |
83 | char **ErrorMessage) { |
84 | std::string Error; |
85 | |
86 | *T = wrap(P: TargetRegistry::lookupTarget(Triple: TripleStr, Error)); |
87 | |
88 | if (!*T) { |
89 | if (ErrorMessage) |
90 | *ErrorMessage = strdup(s: Error.c_str()); |
91 | |
92 | return 1; |
93 | } |
94 | |
95 | return 0; |
96 | } |
97 | |
98 | const char * LLVMGetTargetName(LLVMTargetRef T) { |
99 | return unwrap(P: T)->getName(); |
100 | } |
101 | |
102 | const char * LLVMGetTargetDescription(LLVMTargetRef T) { |
103 | return unwrap(P: T)->getShortDescription(); |
104 | } |
105 | |
106 | LLVMBool LLVMTargetHasJIT(LLVMTargetRef T) { |
107 | return unwrap(P: T)->hasJIT(); |
108 | } |
109 | |
110 | LLVMBool LLVMTargetHasTargetMachine(LLVMTargetRef T) { |
111 | return unwrap(P: T)->hasTargetMachine(); |
112 | } |
113 | |
114 | LLVMBool LLVMTargetHasAsmBackend(LLVMTargetRef T) { |
115 | return unwrap(P: T)->hasMCAsmBackend(); |
116 | } |
117 | |
118 | LLVMTargetMachineOptionsRef LLVMCreateTargetMachineOptions(void) { |
119 | return wrap(P: new LLVMTargetMachineOptions()); |
120 | } |
121 | |
122 | void LLVMDisposeTargetMachineOptions(LLVMTargetMachineOptionsRef Options) { |
123 | delete unwrap(P: Options); |
124 | } |
125 | |
126 | void LLVMTargetMachineOptionsSetCPU(LLVMTargetMachineOptionsRef Options, |
127 | const char *CPU) { |
128 | unwrap(P: Options)->CPU = CPU; |
129 | } |
130 | |
131 | void LLVMTargetMachineOptionsSetFeatures(LLVMTargetMachineOptionsRef Options, |
132 | const char *Features) { |
133 | unwrap(P: Options)->Features = Features; |
134 | } |
135 | |
136 | void LLVMTargetMachineOptionsSetABI(LLVMTargetMachineOptionsRef Options, |
137 | const char *ABI) { |
138 | unwrap(P: Options)->ABI = ABI; |
139 | } |
140 | |
141 | void LLVMTargetMachineOptionsSetCodeGenOptLevel( |
142 | LLVMTargetMachineOptionsRef Options, LLVMCodeGenOptLevel Level) { |
143 | CodeGenOptLevel OL; |
144 | |
145 | switch (Level) { |
146 | case LLVMCodeGenLevelNone: |
147 | OL = CodeGenOptLevel::None; |
148 | break; |
149 | case LLVMCodeGenLevelLess: |
150 | OL = CodeGenOptLevel::Less; |
151 | break; |
152 | case LLVMCodeGenLevelAggressive: |
153 | OL = CodeGenOptLevel::Aggressive; |
154 | break; |
155 | case LLVMCodeGenLevelDefault: |
156 | OL = CodeGenOptLevel::Default; |
157 | break; |
158 | } |
159 | |
160 | unwrap(P: Options)->OL = OL; |
161 | } |
162 | |
163 | void LLVMTargetMachineOptionsSetRelocMode(LLVMTargetMachineOptionsRef Options, |
164 | LLVMRelocMode Reloc) { |
165 | std::optional<Reloc::Model> RM; |
166 | |
167 | switch (Reloc) { |
168 | case LLVMRelocStatic: |
169 | RM = Reloc::Static; |
170 | break; |
171 | case LLVMRelocPIC: |
172 | RM = Reloc::PIC_; |
173 | break; |
174 | case LLVMRelocDynamicNoPic: |
175 | RM = Reloc::DynamicNoPIC; |
176 | break; |
177 | case LLVMRelocROPI: |
178 | RM = Reloc::ROPI; |
179 | break; |
180 | case LLVMRelocRWPI: |
181 | RM = Reloc::RWPI; |
182 | break; |
183 | case LLVMRelocROPI_RWPI: |
184 | RM = Reloc::ROPI_RWPI; |
185 | break; |
186 | case LLVMRelocDefault: |
187 | break; |
188 | } |
189 | |
190 | unwrap(P: Options)->RM = RM; |
191 | } |
192 | |
193 | void LLVMTargetMachineOptionsSetCodeModel(LLVMTargetMachineOptionsRef Options, |
194 | LLVMCodeModel CodeModel) { |
195 | auto CM = unwrap(Model: CodeModel, JIT&: unwrap(P: Options)->JIT); |
196 | unwrap(P: Options)->CM = CM; |
197 | } |
198 | |
199 | LLVMTargetMachineRef |
200 | LLVMCreateTargetMachineWithOptions(LLVMTargetRef T, const char *Triple, |
201 | LLVMTargetMachineOptionsRef Options) { |
202 | auto *Opt = unwrap(P: Options); |
203 | TargetOptions TO; |
204 | TO.MCOptions.ABIName = Opt->ABI; |
205 | return wrap(P: unwrap(P: T)->createTargetMachine(TT: Triple, CPU: Opt->CPU, Features: Opt->Features, |
206 | Options: TO, RM: Opt->RM, CM: Opt->CM, OL: Opt->OL, |
207 | JIT: Opt->JIT)); |
208 | } |
209 | |
210 | LLVMTargetMachineRef |
211 | LLVMCreateTargetMachine(LLVMTargetRef T, const char *Triple, const char *CPU, |
212 | const char *Features, LLVMCodeGenOptLevel Level, |
213 | LLVMRelocMode Reloc, LLVMCodeModel CodeModel) { |
214 | auto *Options = LLVMCreateTargetMachineOptions(); |
215 | |
216 | LLVMTargetMachineOptionsSetCPU(Options, CPU); |
217 | LLVMTargetMachineOptionsSetFeatures(Options, Features); |
218 | LLVMTargetMachineOptionsSetCodeGenOptLevel(Options, Level); |
219 | LLVMTargetMachineOptionsSetRelocMode(Options, Reloc); |
220 | LLVMTargetMachineOptionsSetCodeModel(Options, CodeModel); |
221 | |
222 | auto *Machine = LLVMCreateTargetMachineWithOptions(T, Triple, Options); |
223 | |
224 | LLVMDisposeTargetMachineOptions(Options); |
225 | return Machine; |
226 | } |
227 | |
228 | void LLVMDisposeTargetMachine(LLVMTargetMachineRef T) { delete unwrap(P: T); } |
229 | |
230 | LLVMTargetRef LLVMGetTargetMachineTarget(LLVMTargetMachineRef T) { |
231 | const Target* target = &(unwrap(P: T)->getTarget()); |
232 | return wrap(P: target); |
233 | } |
234 | |
235 | char* LLVMGetTargetMachineTriple(LLVMTargetMachineRef T) { |
236 | std::string StringRep = unwrap(P: T)->getTargetTriple().str(); |
237 | return strdup(s: StringRep.c_str()); |
238 | } |
239 | |
240 | char* LLVMGetTargetMachineCPU(LLVMTargetMachineRef T) { |
241 | std::string StringRep = std::string(unwrap(P: T)->getTargetCPU()); |
242 | return strdup(s: StringRep.c_str()); |
243 | } |
244 | |
245 | char* LLVMGetTargetMachineFeatureString(LLVMTargetMachineRef T) { |
246 | std::string StringRep = std::string(unwrap(P: T)->getTargetFeatureString()); |
247 | return strdup(s: StringRep.c_str()); |
248 | } |
249 | |
250 | void LLVMSetTargetMachineAsmVerbosity(LLVMTargetMachineRef T, |
251 | LLVMBool VerboseAsm) { |
252 | unwrap(P: T)->Options.MCOptions.AsmVerbose = VerboseAsm; |
253 | } |
254 | |
255 | void LLVMSetTargetMachineFastISel(LLVMTargetMachineRef T, LLVMBool Enable) { |
256 | unwrap(P: T)->setFastISel(Enable); |
257 | } |
258 | |
259 | void LLVMSetTargetMachineGlobalISel(LLVMTargetMachineRef T, LLVMBool Enable) { |
260 | unwrap(P: T)->setGlobalISel(Enable); |
261 | } |
262 | |
263 | void LLVMSetTargetMachineGlobalISelAbort(LLVMTargetMachineRef T, |
264 | LLVMGlobalISelAbortMode Mode) { |
265 | GlobalISelAbortMode AM = GlobalISelAbortMode::Enable; |
266 | switch (Mode) { |
267 | case LLVMGlobalISelAbortDisable: |
268 | AM = GlobalISelAbortMode::Disable; |
269 | break; |
270 | case LLVMGlobalISelAbortEnable: |
271 | AM = GlobalISelAbortMode::Enable; |
272 | break; |
273 | case LLVMGlobalISelAbortDisableWithDiag: |
274 | AM = GlobalISelAbortMode::DisableWithDiag; |
275 | break; |
276 | } |
277 | |
278 | unwrap(P: T)->setGlobalISelAbort(AM); |
279 | } |
280 | |
281 | void LLVMSetTargetMachineMachineOutliner(LLVMTargetMachineRef T, |
282 | LLVMBool Enable) { |
283 | unwrap(P: T)->setMachineOutliner(Enable); |
284 | } |
285 | |
286 | LLVMTargetDataRef LLVMCreateTargetDataLayout(LLVMTargetMachineRef T) { |
287 | return wrap(P: new DataLayout(unwrap(P: T)->createDataLayout())); |
288 | } |
289 | |
290 | static LLVMBool LLVMTargetMachineEmit(LLVMTargetMachineRef T, LLVMModuleRef M, |
291 | raw_pwrite_stream &OS, |
292 | LLVMCodeGenFileType codegen, |
293 | char **ErrorMessage) { |
294 | TargetMachine* TM = unwrap(P: T); |
295 | Module* Mod = unwrap(P: M); |
296 | |
297 | legacy::PassManager pass; |
298 | |
299 | std::string error; |
300 | |
301 | Mod->setDataLayout(TM->createDataLayout()); |
302 | |
303 | CodeGenFileType ft; |
304 | switch (codegen) { |
305 | case LLVMAssemblyFile: |
306 | ft = CodeGenFileType::AssemblyFile; |
307 | break; |
308 | default: |
309 | ft = CodeGenFileType::ObjectFile; |
310 | break; |
311 | } |
312 | if (TM->addPassesToEmitFile(pass, OS, nullptr, ft)) { |
313 | error = "TargetMachine can't emit a file of this type" ; |
314 | *ErrorMessage = strdup(s: error.c_str()); |
315 | return true; |
316 | } |
317 | |
318 | pass.run(M&: *Mod); |
319 | |
320 | OS.flush(); |
321 | return false; |
322 | } |
323 | |
324 | LLVMBool LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T, LLVMModuleRef M, |
325 | const char *Filename, |
326 | LLVMCodeGenFileType codegen, |
327 | char **ErrorMessage) { |
328 | std::error_code EC; |
329 | raw_fd_ostream dest(Filename, EC, sys::fs::OF_None); |
330 | if (EC) { |
331 | *ErrorMessage = strdup(s: EC.message().c_str()); |
332 | return true; |
333 | } |
334 | bool Result = LLVMTargetMachineEmit(T, M, OS&: dest, codegen, ErrorMessage); |
335 | dest.flush(); |
336 | return Result; |
337 | } |
338 | |
339 | LLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T, |
340 | LLVMModuleRef M, LLVMCodeGenFileType codegen, char** ErrorMessage, |
341 | LLVMMemoryBufferRef *OutMemBuf) { |
342 | SmallString<0> CodeString; |
343 | raw_svector_ostream OStream(CodeString); |
344 | bool Result = LLVMTargetMachineEmit(T, M, OS&: OStream, codegen, ErrorMessage); |
345 | |
346 | StringRef Data = OStream.str(); |
347 | *OutMemBuf = |
348 | LLVMCreateMemoryBufferWithMemoryRangeCopy(InputData: Data.data(), InputDataLength: Data.size(), BufferName: "" ); |
349 | return Result; |
350 | } |
351 | |
352 | char *LLVMGetDefaultTargetTriple(void) { |
353 | return strdup(s: sys::getDefaultTargetTriple().c_str()); |
354 | } |
355 | |
356 | char *LLVMNormalizeTargetTriple(const char* triple) { |
357 | return strdup(s: Triple::normalize(Str: StringRef(triple)).c_str()); |
358 | } |
359 | |
360 | char *LLVMGetHostCPUName(void) { |
361 | return strdup(s: sys::getHostCPUName().data()); |
362 | } |
363 | |
364 | char *LLVMGetHostCPUFeatures(void) { |
365 | SubtargetFeatures Features; |
366 | for (const auto &[Feature, IsEnabled] : sys::getHostCPUFeatures()) |
367 | Features.AddFeature(String: Feature, Enable: IsEnabled); |
368 | |
369 | return strdup(s: Features.getString().c_str()); |
370 | } |
371 | |
372 | void LLVMAddAnalysisPasses(LLVMTargetMachineRef T, LLVMPassManagerRef PM) { |
373 | unwrap(P: PM)->add( |
374 | P: createTargetTransformInfoWrapperPass(TIRA: unwrap(P: T)->getTargetIRAnalysis())); |
375 | } |
376 | |