I’m having hard times in finding out how to properly use the ExecutionEngine.
I have a function with the following signature:
llvm.func @main(%arg0: i32, %arg1: i32) -> !llvm.struct<(ptr<i32>, i64, array<2 x i64>)>
Thus, its wrapper has signature:
llvm.func @_mlir_ciface_main(%arg0: !llvm.ptr<struct<(ptr<i32>, i64, array<2 x i64>)>>, %arg1: i32, %arg2: i32)
Right now, this is the way I use the ExecutionEngine:
auto maybeEngine = ExecutionEngine::create(module, nullptr, optPipeline, llvm::None, allLibraries);
// ... error checking ...
auto engine = std::move(maybeEngine.get());
int arg0 = 1;
int arg1 = 2;
struct {
int* ptr;
long dim;
long v[2];
} result;
auto* resultPtr = &result;
engine->invoke("main", ExecutionEngine::Result(resultPtr), arg0, arg1);
Given the fact that the struct is originally a return value, and not a pointer, I would expect to just pass result wrapped in the ExecutionEngine::Result class, instead of the wrapped resultPtr. Instead, I had to inspect the generated wrapper to understand that the struct was moved to the arguments list as a pointer, thus needing to pass resultPtr. Is there any way to avoid the need of resultPtr? I also don’t understand why the struct is moved to the arguments list at first, and secondly why it becomes a pointer.