1 //===--------------- OrcV2CBindings.cpp - C bindings OrcV2 APIs -----------===//
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 "llvm-c/Orc.h"
10 #include "llvm-c/TargetMachine.h"
11 
12 #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
13 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
14 
15 using namespace llvm;
16 using namespace llvm::orc;
17 
18 namespace llvm {
19 namespace orc {
20 
21 class OrcV2CAPIHelper {
22 public:
23   using PoolEntry = SymbolStringPtr::PoolEntry;
24   using PoolEntryPtr = SymbolStringPtr::PoolEntryPtr;
25 
26   static PoolEntryPtr releaseSymbolStringPtr(SymbolStringPtr S) {
27     PoolEntryPtr Result = nullptr;
28     std::swap(Result, S.S);
29     return Result;
30   }
31 
32   static PoolEntryPtr getRawPoolEntryPtr(const SymbolStringPtr &S) {
33     return S.S;
34   }
35 
36   static void releasePoolEntry(PoolEntryPtr P) {
37     SymbolStringPtr S;
38     S.S = P;
39   }
40 };
41 
42 } // end namespace orc
43 } // end namespace llvm
44 
45 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ExecutionSession, LLVMOrcExecutionSessionRef)
46 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcV2CAPIHelper::PoolEntry,
47                                    LLVMOrcSymbolStringPoolEntryRef)
48 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(JITDylib, LLVMOrcJITDylibRef)
49 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(JITDylib::DefinitionGenerator,
50                                    LLVMOrcJITDylibDefinitionGeneratorRef)
51 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThreadSafeContext,
52                                    LLVMOrcThreadSafeContextRef)
53 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThreadSafeModule, LLVMOrcThreadSafeModuleRef)
54 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(JITTargetMachineBuilder,
55                                    LLVMOrcJITTargetMachineBuilderRef)
56 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLJITBuilder, LLVMOrcLLJITBuilderRef)
57 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLJIT, LLVMOrcLLJITRef)
58 
59 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
60 
61 LLVMOrcSymbolStringPoolEntryRef
62 LLVMOrcExecutionSessionIntern(LLVMOrcExecutionSessionRef ES, const char *Name) {
63   return wrap(
64       OrcV2CAPIHelper::releaseSymbolStringPtr(unwrap(ES)->intern(Name)));
65 }
66 
67 void LLVMOrcReleaseSymbolStringPoolEntry(LLVMOrcSymbolStringPoolEntryRef S) {
68   OrcV2CAPIHelper::releasePoolEntry(unwrap(S));
69 }
70 
71 void LLVMOrcDisposeJITDylibDefinitionGenerator(
72     LLVMOrcJITDylibDefinitionGeneratorRef DG) {
73   delete unwrap(DG);
74 }
75 
76 void LLVMOrcJITDylibAddGenerator(LLVMOrcJITDylibRef JD,
77                                  LLVMOrcJITDylibDefinitionGeneratorRef DG) {
78   unwrap(JD)->addGenerator(
79       std::unique_ptr<JITDylib::DefinitionGenerator>(unwrap(DG)));
80 }
81 
82 LLVMErrorRef LLVMOrcCreateDynamicLibrarySearchGeneratorForProcess(
83     LLVMOrcJITDylibDefinitionGeneratorRef *Result, char GlobalPrefix,
84     LLVMOrcSymbolPredicate Filter, void *FilterCtx) {
85   assert(Result && "Result can not be null");
86   assert((Filter || !FilterCtx) &&
87          "if Filter is null then FilterCtx must also be null");
88 
89   DynamicLibrarySearchGenerator::SymbolPredicate Pred;
90   if (Filter)
91     Pred = [=](const SymbolStringPtr &Name) -> bool {
92       return Filter(wrap(OrcV2CAPIHelper::getRawPoolEntryPtr(Name)), FilterCtx);
93     };
94 
95   auto ProcessSymsGenerator =
96       DynamicLibrarySearchGenerator::GetForCurrentProcess(GlobalPrefix, Pred);
97 
98   if (!ProcessSymsGenerator) {
99     *Result = 0;
100     return wrap(ProcessSymsGenerator.takeError());
101   }
102 
103   *Result = wrap(ProcessSymsGenerator->release());
104   return LLVMErrorSuccess;
105 }
106 
107 LLVMOrcThreadSafeContextRef LLVMOrcCreateNewThreadSafeContext(void) {
108   return wrap(new ThreadSafeContext(std::make_unique<LLVMContext>()));
109 }
110 
111 LLVMContextRef
112 LLVMOrcThreadSafeContextGetContext(LLVMOrcThreadSafeContextRef TSCtx) {
113   return wrap(unwrap(TSCtx)->getContext());
114 }
115 
116 void LLVMOrcDisposeThreadSafeContext(LLVMOrcThreadSafeContextRef TSCtx) {
117   delete unwrap(TSCtx);
118 }
119 
120 LLVMOrcThreadSafeModuleRef
121 LLVMOrcCreateNewThreadSafeModule(LLVMModuleRef M,
122                                  LLVMOrcThreadSafeContextRef TSCtx) {
123   return wrap(
124       new ThreadSafeModule(std::unique_ptr<Module>(unwrap(M)), *unwrap(TSCtx)));
125 }
126 
127 void LLVMOrcDisposeThreadSafeModule(LLVMOrcThreadSafeModuleRef TSM) {
128   delete unwrap(TSM);
129 }
130 
131 LLVMErrorRef LLVMOrcJITTargetMachineBuilderDetectHost(
132     LLVMOrcJITTargetMachineBuilderRef *Result) {
133   assert(Result && "Result can not be null");
134 
135   auto JTMB = JITTargetMachineBuilder::detectHost();
136   if (!JTMB) {
137     Result = 0;
138     return wrap(JTMB.takeError());
139   }
140 
141   *Result = wrap(new JITTargetMachineBuilder(std::move(*JTMB)));
142   return LLVMErrorSuccess;
143 }
144 
145 LLVMOrcJITTargetMachineBuilderRef
146 LLVMOrcJITTargetMachineBuilderFromTargetMachine(LLVMTargetMachineRef TM) {
147   auto *TemplateTM = unwrap(TM);
148 
149   auto JTMB =
150       std::make_unique<JITTargetMachineBuilder>(TemplateTM->getTargetTriple());
151 
152   (*JTMB)
153       .setCPU(TemplateTM->getTargetCPU().str())
154       .setRelocationModel(TemplateTM->getRelocationModel())
155       .setCodeModel(TemplateTM->getCodeModel())
156       .setCodeGenOptLevel(TemplateTM->getOptLevel())
157       .setFeatures(TemplateTM->getTargetFeatureString())
158       .setOptions(TemplateTM->Options);
159 
160   LLVMDisposeTargetMachine(TM);
161 
162   return wrap(JTMB.release());
163 }
164 
165 void LLVMOrcDisposeJITTargetMachineBuilder(
166     LLVMOrcJITTargetMachineBuilderRef JTMB) {
167   delete unwrap(JTMB);
168 }
169 
170 LLVMOrcLLJITBuilderRef LLVMOrcCreateLLJITBuilder(void) {
171   return wrap(new LLJITBuilder());
172 }
173 
174 void LLVMOrcDisposeLLJITBuilder(LLVMOrcLLJITBuilderRef Builder) {
175   delete unwrap(Builder);
176 }
177 
178 void LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(
179     LLVMOrcLLJITBuilderRef Builder, LLVMOrcJITTargetMachineBuilderRef JTMB) {
180   unwrap(Builder)->setJITTargetMachineBuilder(*unwrap(JTMB));
181 }
182 
183 LLVMErrorRef LLVMOrcCreateLLJIT(LLVMOrcLLJITRef *Result,
184                                 LLVMOrcLLJITBuilderRef Builder) {
185   assert(Result && "Result can not be null");
186 
187   if (!Builder)
188     Builder = LLVMOrcCreateLLJITBuilder();
189 
190   auto J = unwrap(Builder)->create();
191   LLVMOrcDisposeLLJITBuilder(Builder);
192 
193   if (!J) {
194     Result = 0;
195     return wrap(J.takeError());
196   }
197 
198   *Result = wrap(J->release());
199   return LLVMErrorSuccess;
200 }
201 
202 LLVMErrorRef LLVMOrcDisposeLLJIT(LLVMOrcLLJITRef J) {
203   delete unwrap(J);
204   return LLVMErrorSuccess;
205 }
206 
207 LLVMOrcExecutionSessionRef LLVMOrcLLJITGetExecutionSession(LLVMOrcLLJITRef J) {
208   return wrap(&unwrap(J)->getExecutionSession());
209 }
210 
211 LLVMOrcJITDylibRef LLVMOrcLLJITGetMainJITDylib(LLVMOrcLLJITRef J) {
212   return wrap(&unwrap(J)->getMainJITDylib());
213 }
214 
215 const char *LLVMOrcLLJITGetTripleString(LLVMOrcLLJITRef J) {
216   return unwrap(J)->getTargetTriple().str().c_str();
217 }
218 
219 char LLVMOrcLLJITGetGlobalPrefix(LLVMOrcLLJITRef J) {
220   return unwrap(J)->getDataLayout().getGlobalPrefix();
221 }
222 
223 LLVMOrcSymbolStringPoolEntryRef
224 LLVMOrcLLJITMangleAndIntern(LLVMOrcLLJITRef J, const char *UnmangledName) {
225   return wrap(OrcV2CAPIHelper::releaseSymbolStringPtr(
226       unwrap(J)->mangleAndIntern(UnmangledName)));
227 }
228 
229 LLVMErrorRef LLVMOrcLLJITAddObjectFile(LLVMOrcLLJITRef J, LLVMOrcJITDylibRef JD,
230                                        LLVMMemoryBufferRef ObjBuffer) {
231   return wrap(unwrap(J)->addObjectFile(
232       *unwrap(JD), std::unique_ptr<MemoryBuffer>(unwrap(ObjBuffer))));
233 }
234 
235 LLVMErrorRef LLVMOrcLLJITAddLLVMIRModule(LLVMOrcLLJITRef J,
236                                          LLVMOrcJITDylibRef JD,
237                                          LLVMOrcThreadSafeModuleRef TSM) {
238   return wrap(unwrap(J)->addIRModule(*unwrap(JD), std::move(*unwrap(TSM))));
239 }
240 
241 LLVMErrorRef LLVMOrcLLJITLookup(LLVMOrcLLJITRef J,
242                                 LLVMOrcJITTargetAddress *Result,
243                                 const char *Name) {
244   assert(Result && "Result can not be null");
245 
246   auto Sym = unwrap(J)->lookup(Name);
247   if (!Sym) {
248     *Result = 0;
249     return wrap(Sym.takeError());
250   }
251 
252   *Result = Sym->getAddress();
253   return LLVMErrorSuccess;
254 }
255