xref: /llvm-project/mlir/unittests/ExecutionEngine/Invoke.cpp (revision 0d9dc421143a0acd414a23f343b555c965a471f1)
1d6efb6fcSMehdi Amini //===- Invoke.cpp ------------------------------------*- C++ -*-===//
2d6efb6fcSMehdi Amini //
3d6efb6fcSMehdi Amini // This file is licensed under the Apache License v2.0 with LLVM Exceptions.
4d6efb6fcSMehdi Amini // See https://llvm.org/LICENSE.txt for license information.
5d6efb6fcSMehdi Amini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6d6efb6fcSMehdi Amini //
7d6efb6fcSMehdi Amini //===----------------------------------------------------------------------===//
8d6efb6fcSMehdi Amini 
9abc362a1SJakub Kuderski #include "mlir/Conversion/ArithToLLVM/ArithToLLVM.h"
105a7b9194SRiver Riddle #include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVMPass.h"
1175e5f0aaSAlex Zinenko #include "mlir/Conversion/MemRefToLLVM/MemRefToLLVM.h"
128b58ab8cSAlex Zinenko #include "mlir/Conversion/ReconcileUnrealizedCasts/ReconcileUnrealizedCasts.h"
13d6efb6fcSMehdi Amini #include "mlir/Conversion/VectorToLLVM/ConvertVectorToLLVM.h"
14d6efb6fcSMehdi Amini #include "mlir/Conversion/VectorToSCF/VectorToSCF.h"
1536550692SRiver Riddle #include "mlir/Dialect/Func/IR/FuncOps.h"
16d6efb6fcSMehdi Amini #include "mlir/Dialect/Linalg/Passes.h"
17d6efb6fcSMehdi Amini #include "mlir/ExecutionEngine/CRunnerUtils.h"
18d6efb6fcSMehdi Amini #include "mlir/ExecutionEngine/ExecutionEngine.h"
199680ea5cSMehdi Amini #include "mlir/ExecutionEngine/MemRefUtils.h"
20d6efb6fcSMehdi Amini #include "mlir/ExecutionEngine/RunnerUtils.h"
21d6efb6fcSMehdi Amini #include "mlir/IR/MLIRContext.h"
22d6efb6fcSMehdi Amini #include "mlir/InitAllDialects.h"
239eaff423SRiver Riddle #include "mlir/Parser/Parser.h"
24d6efb6fcSMehdi Amini #include "mlir/Pass/PassManager.h"
250e9523efSSergio Afonso #include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h"
2619db802eSAlex Zinenko #include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
2719db802eSAlex Zinenko #include "mlir/Target/LLVMIR/Export.h"
28d6efb6fcSMehdi Amini #include "llvm/Support/TargetSelect.h"
29d6efb6fcSMehdi Amini #include "llvm/Support/raw_ostream.h"
30d6efb6fcSMehdi Amini 
31d6efb6fcSMehdi Amini #include "gmock/gmock.h"
32d6efb6fcSMehdi Amini 
33ca98e0ddSRainer Orth // SPARC currently lacks JIT support.
34ca98e0ddSRainer Orth #ifdef __sparc__
35ca98e0ddSRainer Orth #define SKIP_WITHOUT_JIT(x) DISABLED_##x
36ca98e0ddSRainer Orth #else
37ca98e0ddSRainer Orth #define SKIP_WITHOUT_JIT(x) x
38ca98e0ddSRainer Orth #endif
39ca98e0ddSRainer Orth 
40d6efb6fcSMehdi Amini using namespace mlir;
41d6efb6fcSMehdi Amini 
42dc3b9365SAlexandre Ganea // The JIT isn't supported on Windows at that time
43dc3b9365SAlexandre Ganea #ifndef _WIN32
44dc3b9365SAlexandre Ganea 
45d6efb6fcSMehdi Amini static struct LLVMInitializer {
46d6efb6fcSMehdi Amini   LLVMInitializer() {
47d6efb6fcSMehdi Amini     llvm::InitializeNativeTarget();
48d6efb6fcSMehdi Amini     llvm::InitializeNativeTargetAsmPrinter();
49d6efb6fcSMehdi Amini   }
50d6efb6fcSMehdi Amini } initializer;
51d6efb6fcSMehdi Amini 
52d6efb6fcSMehdi Amini /// Simple conversion pipeline for the purpose of testing sources written in
53d6efb6fcSMehdi Amini /// dialects lowering to LLVM Dialect.
54d6efb6fcSMehdi Amini static LogicalResult lowerToLLVMDialect(ModuleOp module) {
5594a30928Srkayaith   PassManager pm(module->getName());
56cb4ccd38SQuentin Colombet   pm.addPass(mlir::createFinalizeMemRefToLLVMConversionPass());
57abc362a1SJakub Kuderski   pm.addNestedPass<func::FuncOp>(mlir::createArithToLLVMConversionPass());
585a7b9194SRiver Riddle   pm.addPass(mlir::createConvertFuncToLLVMPass());
598b58ab8cSAlex Zinenko   pm.addPass(mlir::createReconcileUnrealizedCastsPass());
60d6efb6fcSMehdi Amini   return pm.run(module);
61d6efb6fcSMehdi Amini }
62d6efb6fcSMehdi Amini 
63ca98e0ddSRainer Orth TEST(MLIRExecutionEngine, SKIP_WITHOUT_JIT(AddInteger)) {
64*0d9dc421SJonas Paulsson #ifdef __s390__
65*0d9dc421SJonas Paulsson   std::string moduleStr = R"mlir(
66*0d9dc421SJonas Paulsson   func.func @foo(%arg0 : i32 {llvm.signext}) -> (i32 {llvm.signext}) attributes { llvm.emit_c_interface } {
67*0d9dc421SJonas Paulsson     %res = arith.addi %arg0, %arg0 : i32
68*0d9dc421SJonas Paulsson     return %res : i32
69*0d9dc421SJonas Paulsson   }
70*0d9dc421SJonas Paulsson   )mlir";
71*0d9dc421SJonas Paulsson #else
72d6efb6fcSMehdi Amini   std::string moduleStr = R"mlir(
7363237cddSRiver Riddle   func.func @foo(%arg0 : i32) -> i32 attributes { llvm.emit_c_interface } {
74a54f4eaeSMogball     %res = arith.addi %arg0, %arg0 : i32
75d6efb6fcSMehdi Amini     return %res : i32
76d6efb6fcSMehdi Amini   }
77d6efb6fcSMehdi Amini   )mlir";
78*0d9dc421SJonas Paulsson #endif
79b77bac05SAlex Zinenko   DialectRegistry registry;
80b77bac05SAlex Zinenko   registerAllDialects(registry);
810e9523efSSergio Afonso   registerBuiltinDialectTranslation(registry);
82b77bac05SAlex Zinenko   registerLLVMDialectTranslation(registry);
83b77bac05SAlex Zinenko   MLIRContext context(registry);
84dfaadf6bSChristian Sigg   OwningOpRef<ModuleOp> module =
85dfaadf6bSChristian Sigg       parseSourceString<ModuleOp>(moduleStr, &context);
86d6efb6fcSMehdi Amini   ASSERT_TRUE(!!module);
87d6efb6fcSMehdi Amini   ASSERT_TRUE(succeeded(lowerToLLVMDialect(*module)));
88d6efb6fcSMehdi Amini   auto jitOrError = ExecutionEngine::create(*module);
89d6efb6fcSMehdi Amini   ASSERT_TRUE(!!jitOrError);
90d6efb6fcSMehdi Amini   std::unique_ptr<ExecutionEngine> jit = std::move(jitOrError.get());
91d6efb6fcSMehdi Amini   // The result of the function must be passed as output argument.
92d6efb6fcSMehdi Amini   int result = 0;
93d6efb6fcSMehdi Amini   llvm::Error error =
94d6efb6fcSMehdi Amini       jit->invoke("foo", 42, ExecutionEngine::Result<int>(result));
95d6efb6fcSMehdi Amini   ASSERT_TRUE(!error);
96d6efb6fcSMehdi Amini   ASSERT_EQ(result, 42 + 42);
97d6efb6fcSMehdi Amini }
98d6efb6fcSMehdi Amini 
99ca98e0ddSRainer Orth TEST(MLIRExecutionEngine, SKIP_WITHOUT_JIT(SubtractFloat)) {
100d6efb6fcSMehdi Amini   std::string moduleStr = R"mlir(
10163237cddSRiver Riddle   func.func @foo(%arg0 : f32, %arg1 : f32) -> f32 attributes { llvm.emit_c_interface } {
102a54f4eaeSMogball     %res = arith.subf %arg0, %arg1 : f32
103d6efb6fcSMehdi Amini     return %res : f32
104d6efb6fcSMehdi Amini   }
105d6efb6fcSMehdi Amini   )mlir";
106b77bac05SAlex Zinenko   DialectRegistry registry;
107b77bac05SAlex Zinenko   registerAllDialects(registry);
1080e9523efSSergio Afonso   registerBuiltinDialectTranslation(registry);
109b77bac05SAlex Zinenko   registerLLVMDialectTranslation(registry);
110b77bac05SAlex Zinenko   MLIRContext context(registry);
111dfaadf6bSChristian Sigg   OwningOpRef<ModuleOp> module =
112dfaadf6bSChristian Sigg       parseSourceString<ModuleOp>(moduleStr, &context);
113d6efb6fcSMehdi Amini   ASSERT_TRUE(!!module);
114d6efb6fcSMehdi Amini   ASSERT_TRUE(succeeded(lowerToLLVMDialect(*module)));
115d6efb6fcSMehdi Amini   auto jitOrError = ExecutionEngine::create(*module);
116d6efb6fcSMehdi Amini   ASSERT_TRUE(!!jitOrError);
117d6efb6fcSMehdi Amini   std::unique_ptr<ExecutionEngine> jit = std::move(jitOrError.get());
118d6efb6fcSMehdi Amini   // The result of the function must be passed as output argument.
119d6efb6fcSMehdi Amini   float result = -1;
120d6efb6fcSMehdi Amini   llvm::Error error =
121d6efb6fcSMehdi Amini       jit->invoke("foo", 43.0f, 1.0f, ExecutionEngine::result(result));
122d6efb6fcSMehdi Amini   ASSERT_TRUE(!error);
123d6efb6fcSMehdi Amini   ASSERT_EQ(result, 42.f);
124d6efb6fcSMehdi Amini }
125d6efb6fcSMehdi Amini 
126ca98e0ddSRainer Orth TEST(NativeMemRefJit, SKIP_WITHOUT_JIT(ZeroRankMemref)) {
12702b6fb21SMehdi Amini   OwningMemRef<float, 0> a({});
12802b6fb21SMehdi Amini   a[{}] = 42.;
12902b6fb21SMehdi Amini   ASSERT_EQ(*a->data, 42);
13002b6fb21SMehdi Amini   a[{}] = 0;
1319680ea5cSMehdi Amini   std::string moduleStr = R"mlir(
13263237cddSRiver Riddle   func.func @zero_ranked(%arg0 : memref<f32>) attributes { llvm.emit_c_interface } {
133a54f4eaeSMogball     %cst42 = arith.constant 42.0 : f32
134e2310704SJulian Gross     memref.store %cst42, %arg0[] : memref<f32>
1359680ea5cSMehdi Amini     return
1369680ea5cSMehdi Amini   }
1379680ea5cSMehdi Amini   )mlir";
138b77bac05SAlex Zinenko   DialectRegistry registry;
139b77bac05SAlex Zinenko   registerAllDialects(registry);
1400e9523efSSergio Afonso   registerBuiltinDialectTranslation(registry);
141b77bac05SAlex Zinenko   registerLLVMDialectTranslation(registry);
142b77bac05SAlex Zinenko   MLIRContext context(registry);
143dfaadf6bSChristian Sigg   auto module = parseSourceString<ModuleOp>(moduleStr, &context);
1449680ea5cSMehdi Amini   ASSERT_TRUE(!!module);
1459680ea5cSMehdi Amini   ASSERT_TRUE(succeeded(lowerToLLVMDialect(*module)));
1469680ea5cSMehdi Amini   auto jitOrError = ExecutionEngine::create(*module);
1479680ea5cSMehdi Amini   ASSERT_TRUE(!!jitOrError);
1489680ea5cSMehdi Amini   auto jit = std::move(jitOrError.get());
1499680ea5cSMehdi Amini 
15002b6fb21SMehdi Amini   llvm::Error error = jit->invoke("zero_ranked", &*a);
1519680ea5cSMehdi Amini   ASSERT_TRUE(!error);
15202b6fb21SMehdi Amini   EXPECT_EQ((a[{}]), 42.);
15302b6fb21SMehdi Amini   for (float &elt : *a)
15402b6fb21SMehdi Amini     EXPECT_EQ(&elt, &(a[{}]));
1559680ea5cSMehdi Amini }
1569680ea5cSMehdi Amini 
157ca98e0ddSRainer Orth TEST(NativeMemRefJit, SKIP_WITHOUT_JIT(RankOneMemref)) {
1589680ea5cSMehdi Amini   int64_t shape[] = {9};
15902b6fb21SMehdi Amini   OwningMemRef<float, 1> a(shape);
1609680ea5cSMehdi Amini   int count = 1;
16102b6fb21SMehdi Amini   for (float &elt : *a) {
16202b6fb21SMehdi Amini     EXPECT_EQ(&elt, &(a[{count - 1}]));
1639680ea5cSMehdi Amini     elt = count++;
1649680ea5cSMehdi Amini   }
1659680ea5cSMehdi Amini 
1669680ea5cSMehdi Amini   std::string moduleStr = R"mlir(
16763237cddSRiver Riddle   func.func @one_ranked(%arg0 : memref<?xf32>) attributes { llvm.emit_c_interface } {
168a54f4eaeSMogball     %cst42 = arith.constant 42.0 : f32
169a54f4eaeSMogball     %cst5 = arith.constant 5 : index
170e2310704SJulian Gross     memref.store %cst42, %arg0[%cst5] : memref<?xf32>
1719680ea5cSMehdi Amini     return
1729680ea5cSMehdi Amini   }
1739680ea5cSMehdi Amini   )mlir";
174b77bac05SAlex Zinenko   DialectRegistry registry;
175b77bac05SAlex Zinenko   registerAllDialects(registry);
1760e9523efSSergio Afonso   registerBuiltinDialectTranslation(registry);
177b77bac05SAlex Zinenko   registerLLVMDialectTranslation(registry);
178b77bac05SAlex Zinenko   MLIRContext context(registry);
179dfaadf6bSChristian Sigg   auto module = parseSourceString<ModuleOp>(moduleStr, &context);
1809680ea5cSMehdi Amini   ASSERT_TRUE(!!module);
1819680ea5cSMehdi Amini   ASSERT_TRUE(succeeded(lowerToLLVMDialect(*module)));
1829680ea5cSMehdi Amini   auto jitOrError = ExecutionEngine::create(*module);
1839680ea5cSMehdi Amini   ASSERT_TRUE(!!jitOrError);
1849680ea5cSMehdi Amini   auto jit = std::move(jitOrError.get());
1859680ea5cSMehdi Amini 
18602b6fb21SMehdi Amini   llvm::Error error = jit->invoke("one_ranked", &*a);
1879680ea5cSMehdi Amini   ASSERT_TRUE(!error);
1889680ea5cSMehdi Amini   count = 1;
18902b6fb21SMehdi Amini   for (float &elt : *a) {
1909680ea5cSMehdi Amini     if (count == 6)
1919680ea5cSMehdi Amini       EXPECT_EQ(elt, 42.);
1929680ea5cSMehdi Amini     else
1939680ea5cSMehdi Amini       EXPECT_EQ(elt, count);
1949680ea5cSMehdi Amini     count++;
1959680ea5cSMehdi Amini   }
1969680ea5cSMehdi Amini }
1979680ea5cSMehdi Amini 
198ca98e0ddSRainer Orth TEST(NativeMemRefJit, SKIP_WITHOUT_JIT(BasicMemref)) {
19902b6fb21SMehdi Amini   constexpr int k = 3;
20002b6fb21SMehdi Amini   constexpr int m = 7;
2019680ea5cSMehdi Amini   // Prepare arguments beforehand.
2029680ea5cSMehdi Amini   auto init = [=](float &elt, ArrayRef<int64_t> indices) {
2039680ea5cSMehdi Amini     assert(indices.size() == 2);
20402b6fb21SMehdi Amini     elt = m * indices[0] + indices[1];
2059680ea5cSMehdi Amini   };
20602b6fb21SMehdi Amini   int64_t shape[] = {k, m};
20702b6fb21SMehdi Amini   int64_t shapeAlloc[] = {k + 1, m + 1};
20802b6fb21SMehdi Amini   OwningMemRef<float, 2> a(shape, shapeAlloc, init);
20902b6fb21SMehdi Amini   ASSERT_EQ(a->sizes[0], k);
21002b6fb21SMehdi Amini   ASSERT_EQ(a->sizes[1], m);
21102b6fb21SMehdi Amini   ASSERT_EQ(a->strides[0], m + 1);
21202b6fb21SMehdi Amini   ASSERT_EQ(a->strides[1], 1);
21302b6fb21SMehdi Amini   for (int i = 0; i < k; ++i) {
21402b6fb21SMehdi Amini     for (int j = 0; j < m; ++j) {
21502b6fb21SMehdi Amini       EXPECT_EQ((a[{i, j}]), i * m + j);
21602b6fb21SMehdi Amini       EXPECT_EQ(&(a[{i, j}]), &((*a)[i][j]));
21781987396SMehdi Amini     }
21881987396SMehdi Amini   }
2199680ea5cSMehdi Amini   std::string moduleStr = R"mlir(
22063237cddSRiver Riddle   func.func @rank2_memref(%arg0 : memref<?x?xf32>, %arg1 : memref<?x?xf32>) attributes { llvm.emit_c_interface } {
221a54f4eaeSMogball     %x = arith.constant 2 : index
222a54f4eaeSMogball     %y = arith.constant 1 : index
223a54f4eaeSMogball     %cst42 = arith.constant 42.0 : f32
224e2310704SJulian Gross     memref.store %cst42, %arg0[%y, %x] : memref<?x?xf32>
225e2310704SJulian Gross     memref.store %cst42, %arg1[%x, %y] : memref<?x?xf32>
2269680ea5cSMehdi Amini     return
2279680ea5cSMehdi Amini   }
2289680ea5cSMehdi Amini   )mlir";
229b77bac05SAlex Zinenko   DialectRegistry registry;
230b77bac05SAlex Zinenko   registerAllDialects(registry);
2310e9523efSSergio Afonso   registerBuiltinDialectTranslation(registry);
232b77bac05SAlex Zinenko   registerLLVMDialectTranslation(registry);
233b77bac05SAlex Zinenko   MLIRContext context(registry);
234dfaadf6bSChristian Sigg   OwningOpRef<ModuleOp> module =
235dfaadf6bSChristian Sigg       parseSourceString<ModuleOp>(moduleStr, &context);
2369680ea5cSMehdi Amini   ASSERT_TRUE(!!module);
2379680ea5cSMehdi Amini   ASSERT_TRUE(succeeded(lowerToLLVMDialect(*module)));
2389680ea5cSMehdi Amini   auto jitOrError = ExecutionEngine::create(*module);
2399680ea5cSMehdi Amini   ASSERT_TRUE(!!jitOrError);
2409680ea5cSMehdi Amini   std::unique_ptr<ExecutionEngine> jit = std::move(jitOrError.get());
2419680ea5cSMehdi Amini 
24202b6fb21SMehdi Amini   llvm::Error error = jit->invoke("rank2_memref", &*a, &*a);
2439680ea5cSMehdi Amini   ASSERT_TRUE(!error);
24402b6fb21SMehdi Amini   EXPECT_EQ(((*a)[1][2]), 42.);
24502b6fb21SMehdi Amini   EXPECT_EQ((a[{2, 1}]), 42.);
2469680ea5cSMehdi Amini }
2479680ea5cSMehdi Amini 
2489680ea5cSMehdi Amini // A helper function that will be called from the JIT
24902b6fb21SMehdi Amini static void memrefMultiply(::StridedMemRefType<float, 2> *memref,
2509680ea5cSMehdi Amini                            int32_t coefficient) {
2519680ea5cSMehdi Amini   for (float &elt : *memref)
2529680ea5cSMehdi Amini     elt *= coefficient;
2539680ea5cSMehdi Amini }
2549680ea5cSMehdi Amini 
2550d70bc99SVitaly Buka // MSAN does not work with JIT.
2560d70bc99SVitaly Buka #if __has_feature(memory_sanitizer)
2570d70bc99SVitaly Buka #define MAYBE_JITCallback DISABLED_JITCallback
2580d70bc99SVitaly Buka #else
259ca98e0ddSRainer Orth #define MAYBE_JITCallback SKIP_WITHOUT_JIT(JITCallback)
2600d70bc99SVitaly Buka #endif
2610d70bc99SVitaly Buka TEST(NativeMemRefJit, MAYBE_JITCallback) {
26202b6fb21SMehdi Amini   constexpr int k = 2;
26302b6fb21SMehdi Amini   constexpr int m = 2;
26402b6fb21SMehdi Amini   int64_t shape[] = {k, m};
26502b6fb21SMehdi Amini   int64_t shapeAlloc[] = {k + 1, m + 1};
26602b6fb21SMehdi Amini   OwningMemRef<float, 2> a(shape, shapeAlloc);
2679680ea5cSMehdi Amini   int count = 1;
26802b6fb21SMehdi Amini   for (float &elt : *a)
2699680ea5cSMehdi Amini     elt = count++;
2709680ea5cSMehdi Amini 
271*0d9dc421SJonas Paulsson #ifdef __s390__
272*0d9dc421SJonas Paulsson   std::string moduleStr = R"mlir(
273*0d9dc421SJonas Paulsson   func.func private @callback(%arg0: memref<?x?xf32>, %coefficient: i32 {llvm.signext})  attributes { llvm.emit_c_interface }
274*0d9dc421SJonas Paulsson   func.func @caller_for_callback(%arg0: memref<?x?xf32>, %coefficient: i32 {llvm.signext}) attributes { llvm.emit_c_interface } {
275*0d9dc421SJonas Paulsson     %unranked = memref.cast %arg0: memref<?x?xf32> to memref<*xf32>
276*0d9dc421SJonas Paulsson     call @callback(%arg0, %coefficient) : (memref<?x?xf32>, i32) -> ()
277*0d9dc421SJonas Paulsson     return
278*0d9dc421SJonas Paulsson   }
279*0d9dc421SJonas Paulsson   )mlir";
280*0d9dc421SJonas Paulsson #else
2819680ea5cSMehdi Amini   std::string moduleStr = R"mlir(
28263237cddSRiver Riddle   func.func private @callback(%arg0: memref<?x?xf32>, %coefficient: i32)  attributes { llvm.emit_c_interface }
28363237cddSRiver Riddle   func.func @caller_for_callback(%arg0: memref<?x?xf32>, %coefficient: i32) attributes { llvm.emit_c_interface } {
284e2310704SJulian Gross     %unranked = memref.cast %arg0: memref<?x?xf32> to memref<*xf32>
2859680ea5cSMehdi Amini     call @callback(%arg0, %coefficient) : (memref<?x?xf32>, i32) -> ()
2869680ea5cSMehdi Amini     return
2879680ea5cSMehdi Amini   }
2889680ea5cSMehdi Amini   )mlir";
289*0d9dc421SJonas Paulsson #endif
290*0d9dc421SJonas Paulsson 
291b77bac05SAlex Zinenko   DialectRegistry registry;
292b77bac05SAlex Zinenko   registerAllDialects(registry);
2930e9523efSSergio Afonso   registerBuiltinDialectTranslation(registry);
294b77bac05SAlex Zinenko   registerLLVMDialectTranslation(registry);
295b77bac05SAlex Zinenko   MLIRContext context(registry);
296dfaadf6bSChristian Sigg   auto module = parseSourceString<ModuleOp>(moduleStr, &context);
2979680ea5cSMehdi Amini   ASSERT_TRUE(!!module);
2989680ea5cSMehdi Amini   ASSERT_TRUE(succeeded(lowerToLLVMDialect(*module)));
2999680ea5cSMehdi Amini   auto jitOrError = ExecutionEngine::create(*module);
3009680ea5cSMehdi Amini   ASSERT_TRUE(!!jitOrError);
3019680ea5cSMehdi Amini   auto jit = std::move(jitOrError.get());
3029680ea5cSMehdi Amini   // Define any extra symbols so they're available at runtime.
3039680ea5cSMehdi Amini   jit->registerSymbols([&](llvm::orc::MangleAndInterner interner) {
3049680ea5cSMehdi Amini     llvm::orc::SymbolMap symbolMap;
30552556c8eSNicolas Vasilache     symbolMap[interner("_mlir_ciface_callback")] = {
30652556c8eSNicolas Vasilache         llvm::orc::ExecutorAddr::fromPtr(memrefMultiply),
307151b58d8SLang Hames         llvm::JITSymbolFlags::Exported};
3089680ea5cSMehdi Amini     return symbolMap;
3099680ea5cSMehdi Amini   });
3109680ea5cSMehdi Amini 
3119680ea5cSMehdi Amini   int32_t coefficient = 3.;
31202b6fb21SMehdi Amini   llvm::Error error = jit->invoke("caller_for_callback", &*a, coefficient);
3139680ea5cSMehdi Amini   ASSERT_TRUE(!error);
3149680ea5cSMehdi Amini   count = 1;
31502b6fb21SMehdi Amini   for (float elt : *a)
3169680ea5cSMehdi Amini     ASSERT_EQ(elt, coefficient * count++);
3179680ea5cSMehdi Amini }
3189680ea5cSMehdi Amini 
319d6efb6fcSMehdi Amini #endif // _WIN32
320