/src/WasmEdge/lib/llvm/llvm.cpp
Line | Count | Source |
1 | | // SPDX-License-Identifier: Apache-2.0 |
2 | | // SPDX-FileCopyrightText: Copyright The WasmEdge Authors |
3 | | |
4 | | #include "llvm.h" |
5 | | |
6 | | #include <llvm/IR/GlobalValue.h> |
7 | | #include <llvm/Object/ObjectFile.h> |
8 | | #include <llvm/Transforms/Utils/BasicBlockUtils.h> |
9 | | #if LLVM_VERSION_MAJOR < 12 || WASMEDGE_OS_WINDOWS |
10 | | #include <llvm/ExecutionEngine/Orc/Core.h> |
11 | | #endif |
12 | | #if LLVM_VERSION_MAJOR < 12 |
13 | | #include <llvm/Target/TargetMachine.h> |
14 | | #endif |
15 | | #if LLVM_VERSION_MAJOR < 13 |
16 | | #include <llvm/ExecutionEngine/Orc/LLJIT.h> |
17 | | #include <llvm/Support/CBindingWrapping.h> |
18 | | #include <llvm/Support/Error.h> |
19 | | #endif |
20 | | #if LLVM_VERSION_MAJOR < 10 |
21 | | #include <llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h> |
22 | | #include <llvm/ExecutionEngine/SectionMemoryManager.h> |
23 | | #include <llvm/MC/SubtargetFeature.h> |
24 | | #include <llvm/Support/Host.h> |
25 | | #endif |
26 | | #if LLVM_VERSION_MAJOR < 18 |
27 | | #include <llvm/IR/Instructions.h> |
28 | | #include <llvm/Support/CBindingWrapping.h> |
29 | | #endif |
30 | | |
31 | | #if WASMEDGE_OS_WINDOWS |
32 | | #include "common/spdlog.h" |
33 | | #include <llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h> |
34 | | #include <llvm/ExecutionEngine/SectionMemoryManager.h> |
35 | | #include <llvm/Support/Process.h> |
36 | | #include <system/winapi.h> |
37 | | #endif |
38 | | |
39 | | namespace llvm { |
40 | | #if WASMEDGE_OS_WINDOWS |
41 | | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::ExecutionSession, |
42 | | LLVMOrcExecutionSessionRef) |
43 | | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::ObjectLayer, LLVMOrcObjectLayerRef) |
44 | | #endif |
45 | | #if LLVM_VERSION_MAJOR < 11 |
46 | | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::ThreadSafeContext, |
47 | | LLVMOrcThreadSafeContextRef) |
48 | | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::JITDylib, LLVMOrcJITDylibRef) |
49 | | #endif |
50 | | #if LLVM_VERSION_MAJOR < 12 |
51 | | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::LLJITBuilder, LLVMOrcLLJITBuilderRef) |
52 | | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::JITTargetMachineBuilder, |
53 | | LLVMOrcJITTargetMachineBuilderRef) |
54 | | #endif |
55 | | #if LLVM_VERSION_MAJOR < 13 |
56 | | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::ThreadSafeModule, |
57 | | LLVMOrcThreadSafeModuleRef) |
58 | | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::IRTransformLayer, |
59 | | LLVMOrcIRTransformLayerRef) |
60 | 0 | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::MaterializationResponsibility, |
61 | 0 | LLVMOrcMaterializationResponsibilityRef) |
62 | 0 | DEFINE_SIMPLE_CONVERSION_FUNCTIONS(orc::LLJIT, LLVMOrcLLJITRef) |
63 | 0 | #endif |
64 | 0 | } // namespace llvm |
65 | 0 |
|
66 | 0 | #if LLVM_VERSION_MAJOR < 18 |
67 | 0 | LLVMTailCallKind LLVMGetTailCallKind(LLVMValueRef Call) { |
68 | 0 | return static_cast<LLVMTailCallKind>( |
69 | 0 | llvm::unwrap<llvm::CallInst>(Call)->getTailCallKind()); |
70 | 0 | } |
71 | | |
72 | 5.59k | void LLVMSetTailCallKind(LLVMValueRef Call, LLVMTailCallKind kind) { |
73 | 5.59k | llvm::unwrap<llvm::CallInst>(Call)->setTailCallKind( |
74 | 5.59k | static_cast<llvm::CallInst::TailCallKind>(kind)); |
75 | 5.59k | } |
76 | | #endif |
77 | | #if LLVM_VERSION_MAJOR < 10 |
78 | | LLVMBool LLVMGetWeak(LLVMValueRef CmpXchgInst) noexcept { |
79 | | return llvm::unwrap<llvm::AtomicCmpXchgInst>(CmpXchgInst)->isWeak(); |
80 | | } |
81 | | |
82 | | void LLVMSetWeak(LLVMValueRef CmpXchgInst, LLVMBool IsWeak) noexcept { |
83 | | llvm::unwrap<llvm::AtomicCmpXchgInst>(CmpXchgInst)->setWeak(IsWeak); |
84 | | } |
85 | | #endif |
86 | | |
87 | | namespace WasmEdge::LLVM { |
88 | | |
89 | 22.4k | void Value::setDSOLocal(bool Local) noexcept { |
90 | 22.4k | llvm::cast<llvm::GlobalValue>(reinterpret_cast<llvm::Value *>(Ref)) |
91 | 22.4k | ->setDSOLocal(Local); |
92 | 22.4k | } |
93 | | |
94 | 10.3k | void Value::eliminateUnreachableBlocks() noexcept { |
95 | 10.3k | llvm::EliminateUnreachableBlocks( |
96 | 10.3k | *llvm::cast<llvm::Function>(reinterpret_cast<llvm::Value *>(Ref))); |
97 | 10.3k | } |
98 | | |
99 | 58.6k | bool SectionIterator::isText() const noexcept { |
100 | 58.6k | auto *S = reinterpret_cast<const llvm::object::section_iterator *>(Ref); |
101 | 58.6k | return (*S)->isText(); |
102 | 58.6k | } |
103 | | |
104 | 54.3k | bool SectionIterator::isData() const noexcept { |
105 | 54.3k | auto *S = reinterpret_cast<const llvm::object::section_iterator *>(Ref); |
106 | 54.3k | return (*S)->isData(); |
107 | 54.3k | } |
108 | | |
109 | 45.5k | bool SectionIterator::isBSS() const noexcept { |
110 | 45.5k | auto *S = reinterpret_cast<const llvm::object::section_iterator *>(Ref); |
111 | 45.5k | return (*S)->isBSS(); |
112 | 45.5k | } |
113 | | |
114 | 58.6k | bool SectionIterator::isPData() const noexcept { |
115 | | #if WASMEDGE_OS_WINDOWS |
116 | | using namespace std::literals; |
117 | | return ".pdata"sv == getName(); |
118 | | #else |
119 | 58.6k | return false; |
120 | 58.6k | #endif |
121 | 58.6k | } |
122 | | |
123 | 62.9k | bool SectionIterator::isEHFrame() const noexcept { |
124 | 62.9k | #if WASMEDGE_OS_LINUX |
125 | 62.9k | using namespace std::literals; |
126 | 62.9k | return ".eh_frame"sv == getName(); |
127 | | #elif WASMEDGE_OS_MACOS |
128 | | using namespace std::literals; |
129 | | return "__eh_frame"sv == getName(); |
130 | | #else |
131 | | return false; |
132 | | #endif |
133 | 62.9k | } |
134 | | |
135 | 31.4k | bool SectionIterator::isVirtual() const noexcept { |
136 | 31.4k | auto *S = reinterpret_cast<const llvm::object::section_iterator *>(Ref); |
137 | 31.4k | return (*S)->isVirtual(); |
138 | 31.4k | } |
139 | | |
140 | | #if WASMEDGE_OS_WINDOWS |
141 | | namespace { |
142 | | class DefaultMMapper final : public llvm::SectionMemoryManager::MemoryMapper { |
143 | | public: |
144 | | llvm::sys::MemoryBlock allocateMappedMemory( |
145 | | llvm::SectionMemoryManager::AllocationPurpose /*Purpose*/, |
146 | | size_t NumBytes, const llvm::sys::MemoryBlock *const NearBlock, |
147 | | unsigned Flags, std::error_code &EC) override { |
148 | | return llvm::sys::Memory::allocateMappedMemory(NumBytes, NearBlock, Flags, |
149 | | EC); |
150 | | } |
151 | | std::error_code protectMappedMemory(const llvm::sys::MemoryBlock &Block, |
152 | | unsigned Flags) override { |
153 | | return llvm::sys::Memory::protectMappedMemory(Block, Flags); |
154 | | } |
155 | | |
156 | | std::error_code releaseMappedMemory(llvm::sys::MemoryBlock &M) override { |
157 | | return llvm::sys::Memory::releaseMappedMemory(M); |
158 | | } |
159 | | }; |
160 | | |
161 | | class ContiguousSectionMemoryManager : public llvm::RTDyldMemoryManager { |
162 | | public: |
163 | | explicit ContiguousSectionMemoryManager( |
164 | | llvm::SectionMemoryManager::MemoryMapper *UnownedMM = nullptr) |
165 | | : MMapper(UnownedMM), OwnedMMapper(nullptr) { |
166 | | if (!MMapper) { |
167 | | OwnedMMapper = std::make_unique<DefaultMMapper>(); |
168 | | MMapper = OwnedMMapper.get(); |
169 | | } |
170 | | } |
171 | | |
172 | | ~ContiguousSectionMemoryManager() noexcept override { |
173 | | using namespace std::literals; |
174 | | if (Preallocated.allocatedSize() != 0) { |
175 | | auto EC = MMapper->releaseMappedMemory(Preallocated); |
176 | | if (EC) { |
177 | | spdlog::error("releaseMappedMemory failed with error: {}"sv, |
178 | | EC.message()); |
179 | | } |
180 | | } |
181 | | } |
182 | | |
183 | | bool needsToReserveAllocationSpace() override { return true; } |
184 | | |
185 | | void reserveAllocationSpace(uintptr_t CodeSize, llvm::Align CodeAlign, |
186 | | uintptr_t RODataSize, llvm::Align RODataAlign, |
187 | | uintptr_t RWDataSize, |
188 | | llvm::Align RWDataAlign) override { |
189 | | using namespace std::literals; |
190 | | assuming(Preallocated.allocatedSize() == 0); |
191 | | |
192 | | static const size_t PageSize = llvm::sys::Process::getPageSizeEstimate(); |
193 | | assuming(CodeAlign.value() <= PageSize); |
194 | | assuming(RODataAlign.value() <= PageSize); |
195 | | assuming(RWDataAlign.value() <= PageSize); |
196 | | CodeSize = roundUpTo(CodeSize + CodeAlign.value(), PageSize); |
197 | | RODataSize = roundUpTo(RODataSize + RODataAlign.value(), PageSize); |
198 | | RWDataSize = roundUpTo(RWDataSize + RWDataAlign.value(), PageSize); |
199 | | const uintptr_t TotalSize = |
200 | | CodeSize + RODataSize + RWDataSize + PageSize * 3; |
201 | | |
202 | | std::error_code EC; |
203 | | Preallocated = MMapper->allocateMappedMemory( |
204 | | llvm::SectionMemoryManager::AllocationPurpose::Code, TotalSize, nullptr, |
205 | | llvm::sys::Memory::MF_READ | llvm::sys::Memory::MF_WRITE, EC); |
206 | | if (EC) { |
207 | | spdlog::error("allocateMappedMemory failed with error: {}"sv, |
208 | | EC.message()); |
209 | | return; |
210 | | } |
211 | | |
212 | | auto base = reinterpret_cast<std::uintptr_t>(Preallocated.base()); |
213 | | CodeMem = CodeFree = |
214 | | llvm::sys::MemoryBlock(reinterpret_cast<void *>(base), CodeSize); |
215 | | base += CodeSize; |
216 | | RODataMem = RODataFree = |
217 | | llvm::sys::MemoryBlock(reinterpret_cast<void *>(base), RODataSize); |
218 | | base += RODataSize; |
219 | | RWDataMem = RWDataFree = |
220 | | llvm::sys::MemoryBlock(reinterpret_cast<void *>(base), RWDataSize); |
221 | | } |
222 | | |
223 | | uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, |
224 | | unsigned /*SectionID*/, |
225 | | llvm::StringRef /*SectionName*/, |
226 | | bool IsReadOnly) override { |
227 | | if (IsReadOnly) { |
228 | | return Allocate(RODataFree, Size, Alignment); |
229 | | } else { |
230 | | return Allocate(RWDataFree, Size, Alignment); |
231 | | } |
232 | | } |
233 | | |
234 | | uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, |
235 | | unsigned /*SectionID*/, |
236 | | llvm::StringRef /*SectionName*/) override { |
237 | | return Allocate(CodeFree, Size, Alignment); |
238 | | } |
239 | | |
240 | | bool finalizeMemory(std::string *ErrMsg) override { |
241 | | std::error_code EC; |
242 | | |
243 | | EC = MMapper->protectMappedMemory(CodeMem, llvm::sys::Memory::MF_READ | |
244 | | llvm::sys::Memory::MF_EXEC); |
245 | | if (EC) { |
246 | | if (ErrMsg) { |
247 | | *ErrMsg = EC.message(); |
248 | | } |
249 | | return true; |
250 | | } |
251 | | EC = MMapper->protectMappedMemory(RODataMem, llvm::sys::Memory::MF_READ); |
252 | | if (EC) { |
253 | | if (ErrMsg) { |
254 | | *ErrMsg = EC.message(); |
255 | | } |
256 | | return true; |
257 | | } |
258 | | |
259 | | llvm::sys::Memory::InvalidateInstructionCache(CodeMem.base(), |
260 | | CodeMem.allocatedSize()); |
261 | | return false; |
262 | | } |
263 | | |
264 | | private: |
265 | | llvm::sys::MemoryBlock Preallocated; |
266 | | |
267 | | // Sections must be in the order code < rodata < rwdata. |
268 | | llvm::sys::MemoryBlock CodeMem; |
269 | | llvm::sys::MemoryBlock RODataMem; |
270 | | llvm::sys::MemoryBlock RWDataMem; |
271 | | |
272 | | llvm::sys::MemoryBlock CodeFree; |
273 | | llvm::sys::MemoryBlock RODataFree; |
274 | | llvm::sys::MemoryBlock RWDataFree; |
275 | | |
276 | | llvm::SectionMemoryManager::MemoryMapper *MMapper; |
277 | | std::unique_ptr<llvm::SectionMemoryManager::MemoryMapper> OwnedMMapper; |
278 | | |
279 | | uint8_t *Allocate(llvm::sys::MemoryBlock &FreeBlock, std::uintptr_t Size, |
280 | | unsigned alignment) { |
281 | | using namespace std::literals; |
282 | | const auto Base = reinterpret_cast<uintptr_t>(FreeBlock.base()); |
283 | | const auto Start = roundUpTo(Base, alignment); |
284 | | const uintptr_t PaddedSize = (Start - Base) + Size; |
285 | | if (PaddedSize > FreeBlock.allocatedSize()) { |
286 | | spdlog::error("Failed to satisfy suballocation request for {}"sv, Size); |
287 | | return nullptr; |
288 | | } |
289 | | FreeBlock = |
290 | | llvm::sys::MemoryBlock(reinterpret_cast<void *>(Base + PaddedSize), |
291 | | FreeBlock.allocatedSize() - PaddedSize); |
292 | | return reinterpret_cast<uint8_t *>(Start); |
293 | | } |
294 | | |
295 | | static uintptr_t roundUpTo(uintptr_t Value, uintptr_t Divisor) noexcept { |
296 | | return ((Value + (Divisor - 1)) / Divisor) * Divisor; |
297 | | } |
298 | | }; |
299 | | |
300 | | // Register stack unwind info for JIT functions |
301 | | class Win64EHManager : public ContiguousSectionMemoryManager { |
302 | | using Base = ContiguousSectionMemoryManager; |
303 | | uint64_t CodeAddress = 0; |
304 | | |
305 | | public: |
306 | | ~Win64EHManager() noexcept override {} |
307 | | |
308 | | uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, |
309 | | unsigned SectionID, |
310 | | llvm::StringRef SectionName) override { |
311 | | using namespace std::literals; |
312 | | const auto Allocated = |
313 | | Base::allocateCodeSection(Size, Alignment, SectionID, SectionName); |
314 | | if (SectionName == llvm::StringRef(".text"sv)) { |
315 | | CodeAddress = reinterpret_cast<uint64_t>(Allocated); |
316 | | } |
317 | | return Allocated; |
318 | | } |
319 | | |
320 | | void registerEHFrames(uint8_t *Addr, uint64_t /*LoadAddr*/, |
321 | | size_t Size) noexcept override { |
322 | | using namespace std::literals; |
323 | | winapi::RUNTIME_FUNCTION_ *const FunctionTable = |
324 | | reinterpret_cast<winapi::RUNTIME_FUNCTION_ *>(Addr); |
325 | | const uint32_t EntryCount = |
326 | | static_cast<uint32_t>(Size / sizeof(winapi::RUNTIME_FUNCTION_)); |
327 | | if (EntryCount == 0) |
328 | | return; |
329 | | // Calculate the object image base address by assuming that the address of |
330 | | // the first function is equal to the address of the code section. |
331 | | const auto ImageBase = CodeAddress - FunctionTable[0].BeginAddress; |
332 | | winapi::RtlAddFunctionTable(FunctionTable, EntryCount, ImageBase); |
333 | | EHFrames.push_back({Addr, Size}); |
334 | | } |
335 | | void deregisterEHFrames() noexcept override { |
336 | | using namespace std::literals; |
337 | | for (auto &Frame : EHFrames) { |
338 | | winapi::RtlDeleteFunctionTable( |
339 | | reinterpret_cast<winapi::RUNTIME_FUNCTION_ *>(Frame.Addr)); |
340 | | } |
341 | | EHFrames.clear(); |
342 | | } |
343 | | }; |
344 | | } // namespace |
345 | | |
346 | | LLVMOrcLLJITBuilderRef OrcLLJIT::getBuilder() noexcept { |
347 | | using llvm::unwrap; |
348 | | using llvm::wrap; |
349 | | const LLVMOrcLLJITBuilderRef Builder = LLVMOrcCreateLLJITBuilder(); |
350 | | LLVMOrcLLJITBuilderSetObjectLinkingLayerCreator( |
351 | | Builder, |
352 | | [](void *, LLVMOrcExecutionSessionRef ES, const char *) noexcept { |
353 | | auto Layer = std::make_unique<llvm::orc::RTDyldObjectLinkingLayer>( |
354 | | *unwrap(ES), []( |
355 | | #if LLVM_VERSION_MAJOR < 21 |
356 | | #else |
357 | | const llvm::MemoryBuffer & |
358 | | #endif |
359 | | ) { return std::make_unique<Win64EHManager>(); }); |
360 | | Layer->setOverrideObjectFlagsWithResponsibilityFlags(true); |
361 | | Layer->setAutoClaimResponsibilityForObjectSymbols(true); |
362 | | return wrap(static_cast<llvm::orc::ObjectLayer *>(Layer.release())); |
363 | | }, |
364 | | nullptr); |
365 | | return Builder; |
366 | | } |
367 | | #elif LLVM_VERSION_MAJOR < 10 |
368 | | namespace { |
369 | | class EHFrameDeregisteringMemoryManager : public llvm::SectionMemoryManager { |
370 | | public: |
371 | | ~EHFrameDeregisteringMemoryManager() noexcept override { |
372 | | deregisterEHFrames(); |
373 | | } |
374 | | }; |
375 | | } // namespace |
376 | | |
377 | | LLVMOrcLLJITBuilderRef OrcLLJIT::getBuilder() noexcept { |
378 | | using llvm::unwrap; |
379 | | const LLVMOrcLLJITBuilderRef Builder = LLVMOrcCreateLLJITBuilder(); |
380 | | if (auto JTMB = llvm::orc::JITTargetMachineBuilder::detectHost()) { |
381 | | llvm::StringMap<bool> FeatureMap; |
382 | | llvm::sys::getHostCPUFeatures(FeatureMap); |
383 | | for (auto &Feature : FeatureMap) { |
384 | | JTMB->getFeatures().AddFeature(Feature.first(), Feature.second); |
385 | | } |
386 | | JTMB->setCPU(llvm::sys::getHostCPUName().str()); |
387 | | unwrap(Builder)->setJITTargetMachineBuilder(std::move(*JTMB)); |
388 | | } else { |
389 | | llvm::consumeError(JTMB.takeError()); |
390 | | } |
391 | | unwrap(Builder)->setObjectLinkingLayerCreator( |
392 | | [](llvm::orc::ExecutionSession &ES) { |
393 | | return std::make_unique<llvm::orc::RTDyldObjectLinkingLayer>(ES, []() { |
394 | | return std::make_unique<EHFrameDeregisteringMemoryManager>(); |
395 | | }); |
396 | | }); |
397 | | return Builder; |
398 | | } |
399 | | #else |
400 | 0 | LLVMOrcLLJITBuilderRef OrcLLJIT::getBuilder() noexcept { return nullptr; } |
401 | | #endif |
402 | | |
403 | | } // namespace WasmEdge::LLVM |
404 | | |
405 | | #if LLVM_VERSION_MAJOR < 12 && WASMEDGE_OS_WINDOWS |
406 | | void LLVMOrcLLJITBuilderSetObjectLinkingLayerCreator( |
407 | | LLVMOrcLLJITBuilderRef Builder, |
408 | | LLVMOrcLLJITBuilderObjectLinkingLayerCreatorFunction F, |
409 | | void *Ctx) noexcept { |
410 | | using llvm::unwrap; |
411 | | using llvm::wrap; |
412 | | unwrap(Builder)->setObjectLinkingLayerCreator( |
413 | | [=](llvm::orc::ExecutionSession &ES, const llvm::Triple &TT) { |
414 | | auto TTStr = TT.str(); |
415 | | return std::unique_ptr<llvm::orc::ObjectLayer>( |
416 | | unwrap(F(Ctx, wrap(&ES), TTStr.c_str()))); |
417 | | }); |
418 | | } |
419 | | #endif |
420 | | #if LLVM_VERSION_MAJOR < 11 |
421 | | LLVMOrcThreadSafeContextRef LLVMOrcCreateNewThreadSafeContext() noexcept { |
422 | | using llvm::wrap; |
423 | | return wrap( |
424 | | new llvm::orc::ThreadSafeContext(std::make_unique<llvm::LLVMContext>())); |
425 | | } |
426 | | |
427 | | LLVMContextRef |
428 | | LLVMOrcThreadSafeContextGetContext(LLVMOrcThreadSafeContextRef TSCtx) noexcept { |
429 | | using llvm::unwrap; |
430 | | using llvm::wrap; |
431 | | return wrap(unwrap(TSCtx)->getContext()); |
432 | | } |
433 | | |
434 | | void LLVMOrcDisposeThreadSafeContext( |
435 | | LLVMOrcThreadSafeContextRef TSCtx) noexcept { |
436 | | delete llvm::unwrap(TSCtx); |
437 | | } |
438 | | |
439 | | LLVMOrcThreadSafeModuleRef |
440 | | LLVMOrcCreateNewThreadSafeModule(LLVMModuleRef M, |
441 | | LLVMOrcThreadSafeContextRef TSCtx) noexcept { |
442 | | using llvm::unwrap; |
443 | | using llvm::wrap; |
444 | | return wrap(new llvm::orc::ThreadSafeModule( |
445 | | std::unique_ptr<llvm::Module>(unwrap(M)), *unwrap(TSCtx))); |
446 | | } |
447 | | |
448 | | void LLVMOrcDisposeThreadSafeModule(LLVMOrcThreadSafeModuleRef TSM) noexcept { |
449 | | delete llvm::unwrap(TSM); |
450 | | } |
451 | | |
452 | | LLVMOrcLLJITBuilderRef LLVMOrcCreateLLJITBuilder() noexcept { |
453 | | return llvm::wrap(new llvm::orc::LLJITBuilder()); |
454 | | } |
455 | | |
456 | | void LLVMOrcDisposeLLJITBuilder(LLVMOrcLLJITBuilderRef Builder) noexcept { |
457 | | delete llvm::unwrap(Builder); |
458 | | } |
459 | | |
460 | | void LLVMOrcLLJITBuilderSetJITTargetMachineBuilder( |
461 | | LLVMOrcLLJITBuilderRef Builder, |
462 | | LLVMOrcJITTargetMachineBuilderRef JTMB) noexcept { |
463 | | using llvm::unwrap; |
464 | | unwrap(Builder)->setJITTargetMachineBuilder(std::move(*unwrap(JTMB))); |
465 | | delete unwrap(JTMB); |
466 | | } |
467 | | |
468 | | LLVMErrorRef LLVMOrcCreateLLJIT(LLVMOrcLLJITRef *Result, |
469 | | LLVMOrcLLJITBuilderRef Builder) noexcept { |
470 | | using llvm::unwrap; |
471 | | using llvm::wrap; |
472 | | if (!Builder) { |
473 | | Builder = LLVMOrcCreateLLJITBuilder(); |
474 | | } |
475 | | auto J = unwrap(Builder)->create(); |
476 | | LLVMOrcDisposeLLJITBuilder(Builder); |
477 | | if (!J) { |
478 | | *Result = nullptr; |
479 | | return wrap(J.takeError()); |
480 | | } |
481 | | *Result = wrap(J->release()); |
482 | | return LLVMErrorSuccess; |
483 | | } |
484 | | |
485 | | LLVMErrorRef LLVMOrcDisposeLLJIT(LLVMOrcLLJITRef J) noexcept { |
486 | | delete llvm::unwrap(J); |
487 | | return LLVMErrorSuccess; |
488 | | } |
489 | | |
490 | | LLVMOrcJITDylibRef LLVMOrcLLJITGetMainJITDylib(LLVMOrcLLJITRef J) noexcept { |
491 | | using llvm::unwrap; |
492 | | using llvm::wrap; |
493 | | return wrap(&unwrap(J)->getMainJITDylib()); |
494 | | } |
495 | | |
496 | | LLVMErrorRef |
497 | | LLVMOrcLLJITAddLLVMIRModule(LLVMOrcLLJITRef J, LLVMOrcJITDylibRef JD, |
498 | | LLVMOrcThreadSafeModuleRef TSM) noexcept { |
499 | | using llvm::unwrap; |
500 | | using llvm::wrap; |
501 | | std::unique_ptr<llvm::orc::ThreadSafeModule> TmpTSM(unwrap(TSM)); |
502 | | return wrap(unwrap(J)->addIRModule(*unwrap(JD), std::move(*TmpTSM))); |
503 | | } |
504 | | |
505 | | LLVMErrorRef LLVMOrcLLJITLookup(LLVMOrcLLJITRef J, |
506 | | LLVMOrcJITTargetAddress *Result, |
507 | | const char *Name) noexcept { |
508 | | using llvm::unwrap; |
509 | | using llvm::wrap; |
510 | | auto Sym = unwrap(J)->lookup(Name); |
511 | | if (!Sym) { |
512 | | *Result = 0; |
513 | | return wrap(Sym.takeError()); |
514 | | } |
515 | | *Result = Sym->getAddress(); |
516 | | return LLVMErrorSuccess; |
517 | | } |
518 | | #endif |
519 | | #if LLVM_VERSION_MAJOR < 12 |
520 | | LLVMOrcJITTargetMachineBuilderRef |
521 | | LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(LLVMTargetMachineRef TM) { |
522 | | using llvm::wrap; |
523 | | auto *TemplateTM = reinterpret_cast<llvm::TargetMachine *>(TM); |
524 | | auto JTMB = std::make_unique<llvm::orc::JITTargetMachineBuilder>( |
525 | | TemplateTM->getTargetTriple()); |
526 | | JTMB->setCPU(TemplateTM->getTargetCPU().str()) |
527 | | .setRelocationModel(TemplateTM->getRelocationModel()) |
528 | | .setCodeModel(TemplateTM->getCodeModel()) |
529 | | .setCodeGenOptLevel(TemplateTM->getOptLevel()); |
530 | | #if LLVM_VERSION_MAJOR < 10 |
531 | | JTMB->getFeatures() = |
532 | | llvm::SubtargetFeatures(TemplateTM->getTargetFeatureString()); |
533 | | JTMB->getOptions() = TemplateTM->Options; |
534 | | #else |
535 | | JTMB->setFeatures(TemplateTM->getTargetFeatureString()) |
536 | | .setOptions(TemplateTM->Options); |
537 | | #endif |
538 | | LLVMDisposeTargetMachine(TM); |
539 | | return wrap(JTMB.release()); |
540 | | } |
541 | | |
542 | | LLVMOrcResourceTrackerRef |
543 | | LLVMOrcJITDylibCreateResourceTracker(LLVMOrcJITDylibRef JD) noexcept { |
544 | | return reinterpret_cast<LLVMOrcResourceTrackerRef>(JD); |
545 | | } |
546 | | |
547 | | void LLVMOrcReleaseResourceTracker(LLVMOrcResourceTrackerRef) noexcept {} |
548 | | |
549 | | LLVMErrorRef LLVMOrcResourceTrackerRemove(LLVMOrcResourceTrackerRef) noexcept { |
550 | | return LLVMErrorSuccess; |
551 | | } |
552 | | |
553 | | LLVMErrorRef |
554 | | LLVMOrcLLJITAddLLVMIRModuleWithRT(LLVMOrcLLJITRef J, |
555 | | LLVMOrcResourceTrackerRef RT, |
556 | | LLVMOrcThreadSafeModuleRef TSM) noexcept { |
557 | | return LLVMOrcLLJITAddLLVMIRModule( |
558 | | J, reinterpret_cast<LLVMOrcJITDylibRef>(RT), TSM); |
559 | | } |
560 | | #endif |
561 | | #if LLVM_VERSION_MAJOR < 11 |
562 | | #elif LLVM_VERSION_MAJOR < 13 |
563 | | LLVMOrcIRTransformLayerRef |
564 | 0 | LLVMOrcLLJITGetIRTransformLayer(LLVMOrcLLJITRef J) noexcept { |
565 | 0 | using llvm::unwrap; |
566 | 0 | using llvm::wrap; |
567 | 0 | return wrap(&(unwrap(J)->getIRTransformLayer())); |
568 | 0 | } |
569 | | void LLVMOrcIRTransformLayerSetTransform( |
570 | | LLVMOrcIRTransformLayerRef IRTransformLayer, |
571 | | LLVMOrcIRTransformLayerTransformFunction TransformFunction, |
572 | 0 | void *Ctx) noexcept { |
573 | 0 | using llvm::unwrap; |
574 | 0 | using llvm::wrap; |
575 | 0 | unwrap(IRTransformLayer) |
576 | 0 | ->setTransform([=](llvm::orc::ThreadSafeModule TSM, |
577 | 0 | llvm::orc::MaterializationResponsibility &R) |
578 | 0 | -> llvm::Expected<llvm::orc::ThreadSafeModule> { |
579 | 0 | LLVMOrcThreadSafeModuleRef TSMRef = |
580 | 0 | wrap(new llvm::orc::ThreadSafeModule(std::move(TSM))); |
581 | 0 | if (LLVMErrorRef Err = TransformFunction(Ctx, &TSMRef, wrap(&R))) { |
582 | 0 | return unwrap(Err); |
583 | 0 | } |
584 | 0 | return std::move(*unwrap(TSMRef)); |
585 | 0 | }); |
586 | 0 | } |
587 | | #endif |
588 | | #if LLVM_VERSION_MAJOR < 13 |
589 | | LLVMErrorRef |
590 | | LLVMOrcThreadSafeModuleWithModuleDo(LLVMOrcThreadSafeModuleRef TSM, |
591 | | LLVMOrcGenericIRModuleOperationFunction F, |
592 | 0 | void *Ctx) noexcept { |
593 | 0 | using llvm::unwrap; |
594 | 0 | using llvm::wrap; |
595 | | #if LLVM_VERSION_MAJOR < 10 |
596 | | auto Lock = unwrap(TSM)->getContextLock(); |
597 | | return F(Ctx, wrap(unwrap(TSM)->getModule())); |
598 | | #else |
599 | 0 | return wrap(unwrap(TSM)->withModuleDo( |
600 | 0 | [&](llvm::Module &M) { return unwrap(F(Ctx, wrap(&M))); })); |
601 | 0 | #endif |
602 | 0 | } |
603 | | #endif |