xref: /freebsd/contrib/llvm-project/llvm/lib/Target/TargetMachineC.cpp (revision af23369a6deaaeb612ab266eb88b8bb8d560c322)
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/SubtargetFeature.h"
20 #include "llvm/MC/TargetRegistry.h"
21 #include "llvm/Support/FileSystem.h"
22 #include "llvm/Support/Host.h"
23 #include "llvm/Support/raw_ostream.h"
24 #include "llvm/Target/CodeGenCWrappers.h"
25 #include "llvm/Target/TargetMachine.h"
26 #include <cstring>
27 
28 using namespace llvm;
29 
30 static TargetMachine *unwrap(LLVMTargetMachineRef P) {
31   return reinterpret_cast<TargetMachine *>(P);
32 }
33 static Target *unwrap(LLVMTargetRef P) {
34   return reinterpret_cast<Target*>(P);
35 }
36 static LLVMTargetMachineRef wrap(const TargetMachine *P) {
37   return reinterpret_cast<LLVMTargetMachineRef>(const_cast<TargetMachine *>(P));
38 }
39 static LLVMTargetRef wrap(const Target * P) {
40   return reinterpret_cast<LLVMTargetRef>(const_cast<Target*>(P));
41 }
42 
43 LLVMTargetRef LLVMGetFirstTarget() {
44   if (TargetRegistry::targets().begin() == TargetRegistry::targets().end()) {
45     return nullptr;
46   }
47 
48   const Target *target = &*TargetRegistry::targets().begin();
49   return wrap(target);
50 }
51 LLVMTargetRef LLVMGetNextTarget(LLVMTargetRef T) {
52   return wrap(unwrap(T)->getNext());
53 }
54 
55 LLVMTargetRef LLVMGetTargetFromName(const char *Name) {
56   StringRef NameRef = Name;
57   auto I = find_if(TargetRegistry::targets(),
58                    [&](const Target &T) { return T.getName() == NameRef; });
59   return I != TargetRegistry::targets().end() ? wrap(&*I) : nullptr;
60 }
61 
62 LLVMBool LLVMGetTargetFromTriple(const char* TripleStr, LLVMTargetRef *T,
63                                  char **ErrorMessage) {
64   std::string Error;
65 
66   *T = wrap(TargetRegistry::lookupTarget(TripleStr, Error));
67 
68   if (!*T) {
69     if (ErrorMessage)
70       *ErrorMessage = strdup(Error.c_str());
71 
72     return 1;
73   }
74 
75   return 0;
76 }
77 
78 const char * LLVMGetTargetName(LLVMTargetRef T) {
79   return unwrap(T)->getName();
80 }
81 
82 const char * LLVMGetTargetDescription(LLVMTargetRef T) {
83   return unwrap(T)->getShortDescription();
84 }
85 
86 LLVMBool LLVMTargetHasJIT(LLVMTargetRef T) {
87   return unwrap(T)->hasJIT();
88 }
89 
90 LLVMBool LLVMTargetHasTargetMachine(LLVMTargetRef T) {
91   return unwrap(T)->hasTargetMachine();
92 }
93 
94 LLVMBool LLVMTargetHasAsmBackend(LLVMTargetRef T) {
95   return unwrap(T)->hasMCAsmBackend();
96 }
97 
98 LLVMTargetMachineRef LLVMCreateTargetMachine(LLVMTargetRef T,
99         const char *Triple, const char *CPU, const char *Features,
100         LLVMCodeGenOptLevel Level, LLVMRelocMode Reloc,
101         LLVMCodeModel CodeModel) {
102   Optional<Reloc::Model> RM;
103   switch (Reloc){
104     case LLVMRelocStatic:
105       RM = Reloc::Static;
106       break;
107     case LLVMRelocPIC:
108       RM = Reloc::PIC_;
109       break;
110     case LLVMRelocDynamicNoPic:
111       RM = Reloc::DynamicNoPIC;
112       break;
113     case LLVMRelocROPI:
114       RM = Reloc::ROPI;
115       break;
116     case LLVMRelocRWPI:
117       RM = Reloc::RWPI;
118       break;
119     case LLVMRelocROPI_RWPI:
120       RM = Reloc::ROPI_RWPI;
121       break;
122     default:
123       break;
124   }
125 
126   bool JIT;
127   Optional<CodeModel::Model> CM = unwrap(CodeModel, JIT);
128 
129   CodeGenOpt::Level OL;
130   switch (Level) {
131     case LLVMCodeGenLevelNone:
132       OL = CodeGenOpt::None;
133       break;
134     case LLVMCodeGenLevelLess:
135       OL = CodeGenOpt::Less;
136       break;
137     case LLVMCodeGenLevelAggressive:
138       OL = CodeGenOpt::Aggressive;
139       break;
140     default:
141       OL = CodeGenOpt::Default;
142       break;
143   }
144 
145   TargetOptions opt;
146   return wrap(unwrap(T)->createTargetMachine(Triple, CPU, Features, opt, RM, CM,
147                                              OL, JIT));
148 }
149 
150 void LLVMDisposeTargetMachine(LLVMTargetMachineRef T) { delete unwrap(T); }
151 
152 LLVMTargetRef LLVMGetTargetMachineTarget(LLVMTargetMachineRef T) {
153   const Target* target = &(unwrap(T)->getTarget());
154   return wrap(target);
155 }
156 
157 char* LLVMGetTargetMachineTriple(LLVMTargetMachineRef T) {
158   std::string StringRep = unwrap(T)->getTargetTriple().str();
159   return strdup(StringRep.c_str());
160 }
161 
162 char* LLVMGetTargetMachineCPU(LLVMTargetMachineRef T) {
163   std::string StringRep = std::string(unwrap(T)->getTargetCPU());
164   return strdup(StringRep.c_str());
165 }
166 
167 char* LLVMGetTargetMachineFeatureString(LLVMTargetMachineRef T) {
168   std::string StringRep = std::string(unwrap(T)->getTargetFeatureString());
169   return strdup(StringRep.c_str());
170 }
171 
172 void LLVMSetTargetMachineAsmVerbosity(LLVMTargetMachineRef T,
173                                       LLVMBool VerboseAsm) {
174   unwrap(T)->Options.MCOptions.AsmVerbose = VerboseAsm;
175 }
176 
177 LLVMTargetDataRef LLVMCreateTargetDataLayout(LLVMTargetMachineRef T) {
178   return wrap(new DataLayout(unwrap(T)->createDataLayout()));
179 }
180 
181 static LLVMBool LLVMTargetMachineEmit(LLVMTargetMachineRef T, LLVMModuleRef M,
182                                       raw_pwrite_stream &OS,
183                                       LLVMCodeGenFileType codegen,
184                                       char **ErrorMessage) {
185   TargetMachine* TM = unwrap(T);
186   Module* Mod = unwrap(M);
187 
188   legacy::PassManager pass;
189 
190   std::string error;
191 
192   Mod->setDataLayout(TM->createDataLayout());
193 
194   CodeGenFileType ft;
195   switch (codegen) {
196     case LLVMAssemblyFile:
197       ft = CGFT_AssemblyFile;
198       break;
199     default:
200       ft = CGFT_ObjectFile;
201       break;
202   }
203   if (TM->addPassesToEmitFile(pass, OS, nullptr, ft)) {
204     error = "TargetMachine can't emit a file of this type";
205     *ErrorMessage = strdup(error.c_str());
206     return true;
207   }
208 
209   pass.run(*Mod);
210 
211   OS.flush();
212   return false;
213 }
214 
215 LLVMBool LLVMTargetMachineEmitToFile(LLVMTargetMachineRef T, LLVMModuleRef M,
216                                      const char *Filename,
217                                      LLVMCodeGenFileType codegen,
218                                      char **ErrorMessage) {
219   std::error_code EC;
220   raw_fd_ostream dest(Filename, EC, sys::fs::OF_None);
221   if (EC) {
222     *ErrorMessage = strdup(EC.message().c_str());
223     return true;
224   }
225   bool Result = LLVMTargetMachineEmit(T, M, dest, codegen, ErrorMessage);
226   dest.flush();
227   return Result;
228 }
229 
230 LLVMBool LLVMTargetMachineEmitToMemoryBuffer(LLVMTargetMachineRef T,
231   LLVMModuleRef M, LLVMCodeGenFileType codegen, char** ErrorMessage,
232   LLVMMemoryBufferRef *OutMemBuf) {
233   SmallString<0> CodeString;
234   raw_svector_ostream OStream(CodeString);
235   bool Result = LLVMTargetMachineEmit(T, M, OStream, codegen, ErrorMessage);
236 
237   StringRef Data = OStream.str();
238   *OutMemBuf =
239       LLVMCreateMemoryBufferWithMemoryRangeCopy(Data.data(), Data.size(), "");
240   return Result;
241 }
242 
243 char *LLVMGetDefaultTargetTriple(void) {
244   return strdup(sys::getDefaultTargetTriple().c_str());
245 }
246 
247 char *LLVMNormalizeTargetTriple(const char* triple) {
248   return strdup(Triple::normalize(StringRef(triple)).c_str());
249 }
250 
251 char *LLVMGetHostCPUName(void) {
252   return strdup(sys::getHostCPUName().data());
253 }
254 
255 char *LLVMGetHostCPUFeatures(void) {
256   SubtargetFeatures Features;
257   StringMap<bool> HostFeatures;
258 
259   if (sys::getHostCPUFeatures(HostFeatures))
260     for (auto &F : HostFeatures)
261       Features.AddFeature(F.first(), F.second);
262 
263   return strdup(Features.getString().c_str());
264 }
265 
266 void LLVMAddAnalysisPasses(LLVMTargetMachineRef T, LLVMPassManagerRef PM) {
267   unwrap(PM)->add(
268       createTargetTransformInfoWrapperPass(unwrap(T)->getTargetIRAnalysis()));
269 }
270