1 | //===- ExecutionEngine.cpp - C API for MLIR JIT ---------------------------===// |
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 "mlir-c/ExecutionEngine.h" |
10 | #include "mlir/CAPI/ExecutionEngine.h" |
11 | #include "mlir/CAPI/IR.h" |
12 | #include "mlir/CAPI/Support.h" |
13 | #include "mlir/ExecutionEngine/OptUtils.h" |
14 | #include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h" |
15 | #include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h" |
16 | #include "mlir/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.h" |
17 | #include "llvm/ExecutionEngine/Orc/Mangling.h" |
18 | #include "llvm/Support/TargetSelect.h" |
19 | |
20 | using namespace mlir; |
21 | |
22 | extern "C" MlirExecutionEngine |
23 | mlirExecutionEngineCreate(MlirModule op, int optLevel, int numPaths, |
24 | const MlirStringRef *sharedLibPaths, |
25 | bool enableObjectDump) { |
26 | static bool initOnce = [] { |
27 | llvm::InitializeNativeTarget(); |
28 | llvm::InitializeNativeTargetAsmParser(); // needed for inline_asm |
29 | llvm::InitializeNativeTargetAsmPrinter(); |
30 | return true; |
31 | }(); |
32 | (void)initOnce; |
33 | |
34 | auto &ctx = *unwrap(op)->getContext(); |
35 | mlir::registerBuiltinDialectTranslation(ctx); |
36 | mlir::registerLLVMDialectTranslation(ctx); |
37 | mlir::registerOpenMPDialectTranslation(ctx); |
38 | |
39 | auto tmBuilderOrError = llvm::orc::JITTargetMachineBuilder::detectHost(); |
40 | if (!tmBuilderOrError) { |
41 | llvm::errs() << "Failed to create a JITTargetMachineBuilder for the host\n" ; |
42 | return MlirExecutionEngine{.ptr: nullptr}; |
43 | } |
44 | auto tmOrError = tmBuilderOrError->createTargetMachine(); |
45 | if (!tmOrError) { |
46 | llvm::errs() << "Failed to create a TargetMachine for the host\n" ; |
47 | return MlirExecutionEngine{.ptr: nullptr}; |
48 | } |
49 | |
50 | SmallVector<StringRef> libPaths; |
51 | for (unsigned i = 0; i < static_cast<unsigned>(numPaths); ++i) |
52 | libPaths.push_back(Elt: sharedLibPaths[i].data); |
53 | |
54 | // Create a transformer to run all LLVM optimization passes at the |
55 | // specified optimization level. |
56 | auto transformer = mlir::makeOptimizingTransformer( |
57 | optLevel, /*sizeLevel=*/0, /*targetMachine=*/tmOrError->get()); |
58 | ExecutionEngineOptions jitOptions; |
59 | jitOptions.transformer = transformer; |
60 | jitOptions.jitCodeGenOptLevel = static_cast<llvm::CodeGenOptLevel>(optLevel); |
61 | jitOptions.sharedLibPaths = libPaths; |
62 | jitOptions.enableObjectDump = enableObjectDump; |
63 | auto jitOrError = ExecutionEngine::create(op: unwrap(op), options: jitOptions); |
64 | if (!jitOrError) { |
65 | consumeError(jitOrError.takeError()); |
66 | return MlirExecutionEngine{.ptr: nullptr}; |
67 | } |
68 | return wrap(jitOrError->release()); |
69 | } |
70 | |
71 | extern "C" void mlirExecutionEngineDestroy(MlirExecutionEngine jit) { |
72 | delete (unwrap(c: jit)); |
73 | } |
74 | |
75 | extern "C" MlirLogicalResult |
76 | mlirExecutionEngineInvokePacked(MlirExecutionEngine jit, MlirStringRef name, |
77 | void **arguments) { |
78 | const std::string ifaceName = ("_mlir_ciface_" + unwrap(ref: name)).str(); |
79 | llvm::Error error = unwrap(c: jit)->invokePacked( |
80 | name: ifaceName, args: MutableArrayRef<void *>{arguments, (size_t)0}); |
81 | if (error) |
82 | return wrap(res: failure()); |
83 | return wrap(res: success()); |
84 | } |
85 | |
86 | extern "C" void *mlirExecutionEngineLookupPacked(MlirExecutionEngine jit, |
87 | MlirStringRef name) { |
88 | auto expectedFPtr = unwrap(c: jit)->lookupPacked(name: unwrap(ref: name)); |
89 | if (!expectedFPtr) |
90 | return nullptr; |
91 | return reinterpret_cast<void *>(*expectedFPtr); |
92 | } |
93 | |
94 | extern "C" void *mlirExecutionEngineLookup(MlirExecutionEngine jit, |
95 | MlirStringRef name) { |
96 | auto expectedFPtr = unwrap(c: jit)->lookup(name: unwrap(ref: name)); |
97 | if (!expectedFPtr) |
98 | return nullptr; |
99 | return reinterpret_cast<void *>(*expectedFPtr); |
100 | } |
101 | |
102 | extern "C" void mlirExecutionEngineRegisterSymbol(MlirExecutionEngine jit, |
103 | MlirStringRef name, |
104 | void *sym) { |
105 | unwrap(c: jit)->registerSymbols(symbolMap: [&](llvm::orc::MangleAndInterner interner) { |
106 | llvm::orc::SymbolMap symbolMap; |
107 | symbolMap[interner(unwrap(ref: name))] = |
108 | { llvm::orc::ExecutorAddr::fromPtr(Ptr: sym), |
109 | llvm::JITSymbolFlags::Exported }; |
110 | return symbolMap; |
111 | }); |
112 | } |
113 | |
114 | extern "C" void mlirExecutionEngineDumpToObjectFile(MlirExecutionEngine jit, |
115 | MlirStringRef name) { |
116 | unwrap(c: jit)->dumpToObjectFile(filename: unwrap(ref: name)); |
117 | } |
118 | |