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