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 <optional>
28
29using namespace llvm;
30
31namespace llvm {
32
33/// Options for LLVMCreateTargetMachine().
34struct LLVMTargetMachineOptions {
35 std::string CPU;
36 std::string Features;
37 std::string ABI;
38 CodeGenOptLevel OL = CodeGenOptLevel::Default;
39 std::optional<Reloc::Model> RM;
40 std::optional<CodeModel::Model> CM;
41 bool JIT;
42};
43
44} // namespace llvm
45
46DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMTargetMachineOptions,
47 LLVMTargetMachineOptionsRef)
48
49static TargetMachine *unwrap(LLVMTargetMachineRef P) {
50 return reinterpret_cast<TargetMachine *>(P);
51}
52static Target *unwrap(LLVMTargetRef P) {
53 return reinterpret_cast<Target*>(P);
54}
55static LLVMTargetMachineRef wrap(const TargetMachine *P) {
56 return reinterpret_cast<LLVMTargetMachineRef>(const_cast<TargetMachine *>(P));
57}
58static LLVMTargetRef wrap(const Target * P) {
59 return reinterpret_cast<LLVMTargetRef>(const_cast<Target*>(P));
60}
61
62LLVMTargetRef LLVMGetFirstTarget() {
63 if (TargetRegistry::targets().begin() == TargetRegistry::targets().end()) {
64 return nullptr;
65 }
66
67 const Target *target = &*TargetRegistry::targets().begin();
68 return wrap(P: target);
69}
70LLVMTargetRef LLVMGetNextTarget(LLVMTargetRef T) {
71 return wrap(P: unwrap(P: T)->getNext());
72}
73
74LLVMTargetRef LLVMGetTargetFromName(const char *Name) {
75 StringRef NameRef = Name;
76 auto I = find_if(Range: TargetRegistry::targets(),
77 P: [&](const Target &T) { return T.getName() == NameRef; });
78 return I != TargetRegistry::targets().end() ? wrap(P: &*I) : nullptr;
79}
80
81LLVMBool LLVMGetTargetFromTriple(const char* TripleStr, LLVMTargetRef *T,
82 char **ErrorMessage) {
83 std::string Error;
84
85 Triple TT(TripleStr);
86 *T = wrap(P: TargetRegistry::lookupTarget(TheTriple: TT, 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
98const char * LLVMGetTargetName(LLVMTargetRef T) {
99 return unwrap(P: T)->getName();
100}
101
102const char * LLVMGetTargetDescription(LLVMTargetRef T) {
103 return unwrap(P: T)->getShortDescription();
104}
105
106LLVMBool LLVMTargetHasJIT(LLVMTargetRef T) {
107 return unwrap(P: T)->hasJIT();
108}
109
110LLVMBool LLVMTargetHasTargetMachine(LLVMTargetRef T) {
111 return unwrap(P: T)->hasTargetMachine();
112}
113
114LLVMBool LLVMTargetHasAsmBackend(LLVMTargetRef T) {
115 return unwrap(P: T)->hasMCAsmBackend();
116}
117
118LLVMTargetMachineOptionsRef LLVMCreateTargetMachineOptions(void) {
119 return wrap(P: new LLVMTargetMachineOptions());
120}
121
122void LLVMDisposeTargetMachineOptions(LLVMTargetMachineOptionsRef Options) {
123 delete unwrap(P: Options);
124}
125
126void LLVMTargetMachineOptionsSetCPU(LLVMTargetMachineOptionsRef Options,
127 const char *CPU) {
128 unwrap(P: Options)->CPU = CPU;
129}
130
131void LLVMTargetMachineOptionsSetFeatures(LLVMTargetMachineOptionsRef Options,
132 const char *Features) {
133 unwrap(P: Options)->Features = Features;
134}
135
136void LLVMTargetMachineOptionsSetABI(LLVMTargetMachineOptionsRef Options,
137 const char *ABI) {
138 unwrap(P: Options)->ABI = ABI;
139}
140
141void 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
163void 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
193void 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
199LLVMTargetMachineRef
200LLVMCreateTargetMachineWithOptions(LLVMTargetRef T, const char *TripleStr,
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(TripleStr), CPU: Opt->CPU,
206 Features: Opt->Features, Options: TO, RM: Opt->RM,
207 CM: Opt->CM, OL: Opt->OL, JIT: Opt->JIT));
208}
209
210LLVMTargetMachineRef
211LLVMCreateTargetMachine(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, TripleStr: Triple, Options);
223
224 LLVMDisposeTargetMachineOptions(Options);
225 return Machine;
226}
227
228void LLVMDisposeTargetMachine(LLVMTargetMachineRef T) { delete unwrap(P: T); }
229
230LLVMTargetRef LLVMGetTargetMachineTarget(LLVMTargetMachineRef T) {
231 const Target* target = &(unwrap(P: T)->getTarget());
232 return wrap(P: target);
233}
234
235char* LLVMGetTargetMachineTriple(LLVMTargetMachineRef T) {
236 std::string StringRep = unwrap(P: T)->getTargetTriple().str();
237 return strdup(s: StringRep.c_str());
238}
239
240char* LLVMGetTargetMachineCPU(LLVMTargetMachineRef T) {
241 std::string StringRep = std::string(unwrap(P: T)->getTargetCPU());
242 return strdup(s: StringRep.c_str());
243}
244
245char* LLVMGetTargetMachineFeatureString(LLVMTargetMachineRef T) {
246 std::string StringRep = std::string(unwrap(P: T)->getTargetFeatureString());
247 return strdup(s: StringRep.c_str());
248}
249
250void LLVMSetTargetMachineAsmVerbosity(LLVMTargetMachineRef T,
251 LLVMBool VerboseAsm) {
252 unwrap(P: T)->Options.MCOptions.AsmVerbose = VerboseAsm;
253}
254
255void LLVMSetTargetMachineFastISel(LLVMTargetMachineRef T, LLVMBool Enable) {
256 unwrap(P: T)->setFastISel(Enable);
257}
258
259void LLVMSetTargetMachineGlobalISel(LLVMTargetMachineRef T, LLVMBool Enable) {
260 unwrap(P: T)->setGlobalISel(Enable);
261}
262
263void 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
281void LLVMSetTargetMachineMachineOutliner(LLVMTargetMachineRef T,
282 LLVMBool Enable) {
283 unwrap(P: T)->setMachineOutliner(Enable);
284}
285
286LLVMTargetDataRef LLVMCreateTargetDataLayout(LLVMTargetMachineRef T) {
287 TargetMachine *TM = unwrap(P: T);
288 return wrap(P: new DataLayout(TM->getTargetTriple().computeDataLayout(
289 ABIName: TM->Options.MCOptions.getABIName())));
290}
291
292static LLVMBool LLVMTargetMachineEmit(LLVMTargetMachineRef T, LLVMModuleRef M,
293 raw_pwrite_stream &OS,
294 LLVMCodeGenFileType codegen,
295 char **ErrorMessage) {
296 TargetMachine* TM = unwrap(P: T);
297 Module* Mod = unwrap(P: M);
298
299 legacy::PassManager pass;
300
301 std::string error;
302
303 Mod->setDataLayout(TM->getTargetTriple().computeDataLayout(
304 ABIName: TM->Options.MCOptions.getABIName()));
305
306 CodeGenFileType ft;
307 switch (codegen) {
308 case LLVMAssemblyFile:
309 ft = CodeGenFileType::AssemblyFile;
310 break;
311 default:
312 ft = CodeGenFileType::ObjectFile;
313 break;
314 }
315 if (TM->addPassesToEmitFile(pass, OS, nullptr, ft)) {
316 error = "TargetMachine can't emit a file of this type";
317 *ErrorMessage = strdup(s: error.c_str());
318 return true;
319 }
320
321 pass.run(M&: *Mod);
322
323 OS.flush();
324 return false;
325}
326
327LLVMBool LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T, LLVMModuleRef M,
328 const char *Filename,
329 LLVMCodeGenFileType codegen,
330 char **ErrorMessage) {
331 std::error_code EC;
332 raw_fd_ostream dest(Filename, EC, sys::fs::OF_None);
333 if (EC) {
334 *ErrorMessage = strdup(s: EC.message().c_str());
335 return true;
336 }
337 bool Result = LLVMTargetMachineEmit(T, M, OS&: dest, codegen, ErrorMessage);
338 dest.flush();
339 return Result;
340}
341
342LLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T,
343 LLVMModuleRef M, LLVMCodeGenFileType codegen, char** ErrorMessage,
344 LLVMMemoryBufferRef *OutMemBuf) {
345 SmallString<0> CodeString;
346 raw_svector_ostream OStream(CodeString);
347 bool Result = LLVMTargetMachineEmit(T, M, OS&: OStream, codegen, ErrorMessage);
348
349 StringRef Data = OStream.str();
350 *OutMemBuf =
351 LLVMCreateMemoryBufferWithMemoryRangeCopy(InputData: Data.data(), InputDataLength: Data.size(), BufferName: "");
352 return Result;
353}
354
355char *LLVMGetDefaultTargetTriple(void) {
356 return strdup(s: sys::getDefaultTargetTriple().c_str());
357}
358
359char *LLVMNormalizeTargetTriple(const char* triple) {
360 return strdup(s: Triple::normalize(Str: StringRef(triple)).c_str());
361}
362
363char *LLVMGetHostCPUName(void) {
364 return strdup(s: sys::getHostCPUName().data());
365}
366
367char *LLVMGetHostCPUFeatures(void) {
368 SubtargetFeatures Features;
369 for (const auto &[Feature, IsEnabled] : sys::getHostCPUFeatures())
370 Features.AddFeature(String: Feature, Enable: IsEnabled);
371
372 return strdup(s: Features.getString().c_str());
373}
374
375void LLVMAddAnalysisPasses(LLVMTargetMachineRef T, LLVMPassManagerRef PM) {
376 unwrap(P: PM)->add(
377 P: createTargetTransformInfoWrapperPass(TIRA: unwrap(P: T)->getTargetIRAnalysis()));
378}
379