
The purpose of the change is to make clear whether the user is retrieving the original function or the wrapper function, in line with the invoke commands. This new functionality is useful for users that already have defined their own packed interface, so they do not want the extra layer of indirection, or for users wanting to the look at the resulting primary function rather than the wrapper function. All locations, except the python bindings now have a `lookupPacked` method that matches the original `lookup` functionality. `lookup` still exists, but with new semantics. - `lookup` returns the function with a given name. If `bool f(int,int)` is compiled, `lookup` will return a reference to `bool(*f)(int,int)`. - `lookupPacked` returns the packed wrapper of the function with the given name. If `bool f(int,int)` is compiled, `lookupPacked` will return `void(*mlir_f)(void**)`. Differential Revision: https://reviews.llvm.org/D114352
109 lines
4.0 KiB
C++
109 lines
4.0 KiB
C++
//===- ExecutionEngine.cpp - C API for MLIR JIT ---------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "mlir-c/ExecutionEngine.h"
|
|
#include "mlir/CAPI/ExecutionEngine.h"
|
|
#include "mlir/CAPI/IR.h"
|
|
#include "mlir/CAPI/Support.h"
|
|
#include "mlir/ExecutionEngine/OptUtils.h"
|
|
#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
|
|
#include "llvm/ExecutionEngine/Orc/Mangling.h"
|
|
#include "llvm/Support/TargetSelect.h"
|
|
|
|
using namespace mlir;
|
|
|
|
extern "C" MlirExecutionEngine
|
|
mlirExecutionEngineCreate(MlirModule op, int optLevel, int numPaths,
|
|
const MlirStringRef *sharedLibPaths) {
|
|
static bool initOnce = [] {
|
|
llvm::InitializeNativeTarget();
|
|
llvm::InitializeNativeTargetAsmParser(); // needed for inline_asm
|
|
llvm::InitializeNativeTargetAsmPrinter();
|
|
return true;
|
|
}();
|
|
(void)initOnce;
|
|
|
|
mlir::registerLLVMDialectTranslation(*unwrap(op)->getContext());
|
|
|
|
auto tmBuilderOrError = llvm::orc::JITTargetMachineBuilder::detectHost();
|
|
if (!tmBuilderOrError) {
|
|
llvm::errs() << "Failed to create a JITTargetMachineBuilder for the host\n";
|
|
return MlirExecutionEngine{nullptr};
|
|
}
|
|
auto tmOrError = tmBuilderOrError->createTargetMachine();
|
|
if (!tmOrError) {
|
|
llvm::errs() << "Failed to create a TargetMachine for the host\n";
|
|
return MlirExecutionEngine{nullptr};
|
|
}
|
|
|
|
SmallVector<StringRef> libPaths;
|
|
for (unsigned i = 0; i < static_cast<unsigned>(numPaths); ++i)
|
|
libPaths.push_back(sharedLibPaths[i].data);
|
|
|
|
// Create a transformer to run all LLVM optimization passes at the
|
|
// specified optimization level.
|
|
auto llvmOptLevel = static_cast<llvm::CodeGenOpt::Level>(optLevel);
|
|
auto transformer = mlir::makeLLVMPassesTransformer(
|
|
/*passes=*/{}, llvmOptLevel, /*targetMachine=*/tmOrError->get());
|
|
auto jitOrError =
|
|
ExecutionEngine::create(unwrap(op), /*llvmModuleBuilder=*/{}, transformer,
|
|
llvmOptLevel, libPaths);
|
|
if (!jitOrError) {
|
|
consumeError(jitOrError.takeError());
|
|
return MlirExecutionEngine{nullptr};
|
|
}
|
|
return wrap(jitOrError->release());
|
|
}
|
|
|
|
extern "C" void mlirExecutionEngineDestroy(MlirExecutionEngine jit) {
|
|
delete (unwrap(jit));
|
|
}
|
|
|
|
extern "C" MlirLogicalResult
|
|
mlirExecutionEngineInvokePacked(MlirExecutionEngine jit, MlirStringRef name,
|
|
void **arguments) {
|
|
const std::string ifaceName = ("_mlir_ciface_" + unwrap(name)).str();
|
|
llvm::Error error = unwrap(jit)->invokePacked(
|
|
ifaceName, MutableArrayRef<void *>{arguments, (size_t)0});
|
|
if (error)
|
|
return wrap(failure());
|
|
return wrap(success());
|
|
}
|
|
|
|
extern "C" void *mlirExecutionEngineLookupPacked(MlirExecutionEngine jit,
|
|
MlirStringRef name) {
|
|
auto expectedFPtr = unwrap(jit)->lookupPacked(unwrap(name));
|
|
if (!expectedFPtr)
|
|
return nullptr;
|
|
return reinterpret_cast<void *>(*expectedFPtr);
|
|
}
|
|
|
|
extern "C" void *mlirExecutionEngineLookup(MlirExecutionEngine jit,
|
|
MlirStringRef name) {
|
|
auto expectedFPtr = unwrap(jit)->lookup(unwrap(name));
|
|
if (!expectedFPtr)
|
|
return nullptr;
|
|
return reinterpret_cast<void *>(*expectedFPtr);
|
|
}
|
|
|
|
extern "C" void mlirExecutionEngineRegisterSymbol(MlirExecutionEngine jit,
|
|
MlirStringRef name,
|
|
void *sym) {
|
|
unwrap(jit)->registerSymbols([&](llvm::orc::MangleAndInterner interner) {
|
|
llvm::orc::SymbolMap symbolMap;
|
|
symbolMap[interner(unwrap(name))] =
|
|
llvm::JITEvaluatedSymbol::fromPointer(sym);
|
|
return symbolMap;
|
|
});
|
|
}
|
|
|
|
extern "C" void mlirExecutionEngineDumpToObjectFile(MlirExecutionEngine jit,
|
|
MlirStringRef name) {
|
|
unwrap(jit)->dumpToObjectFile(unwrap(name));
|
|
}
|