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
30using namespace llvm;
31
32namespace llvm {
33
34/// Options for LLVMCreateTargetMachine().
35struct 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
47DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMTargetMachineOptions,
48                                   LLVMTargetMachineOptionsRef)
49
50static TargetMachine *unwrap(LLVMTargetMachineRef P) {
51  return reinterpret_cast<TargetMachine *>(P);
52}
53static Target *unwrap(LLVMTargetRef P) {
54  return reinterpret_cast<Target*>(P);
55}
56static LLVMTargetMachineRef wrap(const TargetMachine *P) {
57  return reinterpret_cast<LLVMTargetMachineRef>(const_cast<TargetMachine *>(P));
58}
59static LLVMTargetRef wrap(const Target * P) {
60  return reinterpret_cast<LLVMTargetRef>(const_cast<Target*>(P));
61}
62
63LLVMTargetRef LLVMGetFirstTarget() {
64  if (TargetRegistry::targets().begin() == TargetRegistry::targets().end()) {
65    return nullptr;
66  }
67
68  const Target *target = &*TargetRegistry::targets().begin();
69  return wrap(target);
70}
71LLVMTargetRef LLVMGetNextTarget(LLVMTargetRef T) {
72  return wrap(unwrap(T)->getNext());
73}
74
75LLVMTargetRef LLVMGetTargetFromName(const char *Name) {
76  StringRef NameRef = Name;
77  auto I = find_if(TargetRegistry::targets(),
78                   [&](const Target &T) { return T.getName() == NameRef; });
79  return I != TargetRegistry::targets().end() ? wrap(&*I) : nullptr;
80}
81
82LLVMBool LLVMGetTargetFromTriple(const char* TripleStr, LLVMTargetRef *T,
83                                 char **ErrorMessage) {
84  std::string Error;
85
86  *T = wrap(TargetRegistry::lookupTarget(TripleStr, Error));
87
88  if (!*T) {
89    if (ErrorMessage)
90      *ErrorMessage = strdup(Error.c_str());
91
92    return 1;
93  }
94
95  return 0;
96}
97
98const char * LLVMGetTargetName(LLVMTargetRef T) {
99  return unwrap(T)->getName();
100}
101
102const char * LLVMGetTargetDescription(LLVMTargetRef T) {
103  return unwrap(T)->getShortDescription();
104}
105
106LLVMBool LLVMTargetHasJIT(LLVMTargetRef T) {
107  return unwrap(T)->hasJIT();
108}
109
110LLVMBool LLVMTargetHasTargetMachine(LLVMTargetRef T) {
111  return unwrap(T)->hasTargetMachine();
112}
113
114LLVMBool LLVMTargetHasAsmBackend(LLVMTargetRef T) {
115  return unwrap(T)->hasMCAsmBackend();
116}
117
118LLVMTargetMachineOptionsRef LLVMCreateTargetMachineOptions(void) {
119  return wrap(new LLVMTargetMachineOptions());
120}
121
122void LLVMDisposeTargetMachineOptions(LLVMTargetMachineOptionsRef Options) {
123  delete unwrap(Options);
124}
125
126void LLVMTargetMachineOptionsSetCPU(LLVMTargetMachineOptionsRef Options,
127                                    const char *CPU) {
128  unwrap(Options)->CPU = CPU;
129}
130
131void LLVMTargetMachineOptionsSetFeatures(LLVMTargetMachineOptionsRef Options,
132                                         const char *Features) {
133  unwrap(Options)->Features = Features;
134}
135
136void LLVMTargetMachineOptionsSetABI(LLVMTargetMachineOptionsRef Options,
137                                    const char *ABI) {
138  unwrap(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(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(Options)->RM = RM;
191}
192
193void LLVMTargetMachineOptionsSetCodeModel(LLVMTargetMachineOptionsRef Options,
194                                          LLVMCodeModel CodeModel) {
195  auto CM = unwrap(CodeModel, unwrap(Options)->JIT);
196  unwrap(Options)->CM = CM;
197}
198
199LLVMTargetMachineRef
200LLVMCreateTargetMachineWithOptions(LLVMTargetRef T, const char *Triple,
201                                   LLVMTargetMachineOptionsRef Options) {
202  auto *Opt = unwrap(Options);
203  TargetOptions TO;
204  TO.MCOptions.ABIName = Opt->ABI;
205  return wrap(unwrap(T)->createTargetMachine(Triple, Opt->CPU, Opt->Features,
206                                             TO, Opt->RM, Opt->CM, Opt->OL,
207                                             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, Triple, Options);
223
224  LLVMDisposeTargetMachineOptions(Options);
225  return Machine;
226}
227
228void LLVMDisposeTargetMachine(LLVMTargetMachineRef T) { delete unwrap(T); }
229
230LLVMTargetRef LLVMGetTargetMachineTarget(LLVMTargetMachineRef T) {
231  const Target* target = &(unwrap(T)->getTarget());
232  return wrap(target);
233}
234
235char* LLVMGetTargetMachineTriple(LLVMTargetMachineRef T) {
236  std::string StringRep = unwrap(T)->getTargetTriple().str();
237  return strdup(StringRep.c_str());
238}
239
240char* LLVMGetTargetMachineCPU(LLVMTargetMachineRef T) {
241  std::string StringRep = std::string(unwrap(T)->getTargetCPU());
242  return strdup(StringRep.c_str());
243}
244
245char* LLVMGetTargetMachineFeatureString(LLVMTargetMachineRef T) {
246  std::string StringRep = std::string(unwrap(T)->getTargetFeatureString());
247  return strdup(StringRep.c_str());
248}
249
250void LLVMSetTargetMachineAsmVerbosity(LLVMTargetMachineRef T,
251                                      LLVMBool VerboseAsm) {
252  unwrap(T)->Options.MCOptions.AsmVerbose = VerboseAsm;
253}
254
255void LLVMSetTargetMachineFastISel(LLVMTargetMachineRef T, LLVMBool Enable) {
256  unwrap(T)->setFastISel(Enable);
257}
258
259void LLVMSetTargetMachineGlobalISel(LLVMTargetMachineRef T, LLVMBool Enable) {
260  unwrap(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(T)->setGlobalISelAbort(AM);
279}
280
281void LLVMSetTargetMachineMachineOutliner(LLVMTargetMachineRef T,
282                                         LLVMBool Enable) {
283  unwrap(T)->setMachineOutliner(Enable);
284}
285
286LLVMTargetDataRef LLVMCreateTargetDataLayout(LLVMTargetMachineRef T) {
287  return wrap(new DataLayout(unwrap(T)->createDataLayout()));
288}
289
290static LLVMBool LLVMTargetMachineEmit(LLVMTargetMachineRef T, LLVMModuleRef M,
291                                      raw_pwrite_stream &OS,
292                                      LLVMCodeGenFileType codegen,
293                                      char **ErrorMessage) {
294  TargetMachine* TM = unwrap(T);
295  Module* Mod = unwrap(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(error.c_str());
315    return true;
316  }
317
318  pass.run(*Mod);
319
320  OS.flush();
321  return false;
322}
323
324LLVMBool 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(EC.message().c_str());
332    return true;
333  }
334  bool Result = LLVMTargetMachineEmit(T, M, dest, codegen, ErrorMessage);
335  dest.flush();
336  return Result;
337}
338
339LLVMBool 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, OStream, codegen, ErrorMessage);
345
346  StringRef Data = OStream.str();
347  *OutMemBuf =
348      LLVMCreateMemoryBufferWithMemoryRangeCopy(Data.data(), Data.size(), "");
349  return Result;
350}
351
352char *LLVMGetDefaultTargetTriple(void) {
353  return strdup(sys::getDefaultTargetTriple().c_str());
354}
355
356char *LLVMNormalizeTargetTriple(const char* triple) {
357  return strdup(Triple::normalize(StringRef(triple)).c_str());
358}
359
360char *LLVMGetHostCPUName(void) {
361  return strdup(sys::getHostCPUName().data());
362}
363
364char *LLVMGetHostCPUFeatures(void) {
365  SubtargetFeatures Features;
366  StringMap<bool> HostFeatures;
367
368  if (sys::getHostCPUFeatures(HostFeatures))
369    for (const auto &[Feature, IsEnabled] : HostFeatures)
370      Features.AddFeature(Feature, IsEnabled);
371
372  return strdup(Features.getString().c_str());
373}
374
375void LLVMAddAnalysisPasses(LLVMTargetMachineRef T, LLVMPassManagerRef PM) {
376  unwrap(PM)->add(
377      createTargetTransformInfoWrapperPass(unwrap(T)->getTargetIRAnalysis()));
378}
379