Skip to content

Commit c9babc4

Browse files
authored
Execution engine (#60)
1 parent 5145eb0 commit c9babc4

8 files changed

Lines changed: 597 additions & 19 deletions

File tree

‎mlir/CMakeLists.txt‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ set(SOURCES_LIST
4040
lib/Dialect/PyIR/IR/PyIROps.cpp
4141
lib/Dialect/Typing/IR/TypingOps.cpp
4242
lib/Dialect/Typing/Transforms/Interpreter.cpp
43+
lib/ExecutionEngine/ExecutionEngine.cpp
4344
lib/Pipelines/BackendPipeline.cpp
4445
lib/Pipelines/FrontendPipeline.cpp
4546
lib/Pipelines/MiddleendPipeline.cpp
@@ -72,6 +73,7 @@ set(HEADERS_LIST
7273
include/hc/Dialect/Typing/IR/TypingOps.hpp
7374
include/hc/Dialect/Typing/IR/TypingOpsInterfaces.hpp
7475
include/hc/Dialect/Typing/Transforms/Interpreter.hpp
76+
include/hc/ExecutionEngine/ExecutionEngine.hpp
7577
include/hc/InitHCDialects.hpp
7678
include/hc/InitHCPasses.hpp
7779
include/hc/Pipelines/BackendPipeline.hpp
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
// SPDX-FileCopyrightText: 2025 The HC Authors
2+
//
3+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4+
5+
#pragma once
6+
7+
#include <llvm/ExecutionEngine/Orc/Core.h>
8+
#include <llvm/IR/LLVMContext.h>
9+
#include <llvm/Support/CodeGen.h>
10+
#include <llvm/Support/Error.h>
11+
12+
#include <functional>
13+
#include <memory>
14+
15+
namespace mlir {
16+
class ModuleOp;
17+
}
18+
19+
namespace llvm {
20+
template <typename T> class Expected;
21+
class JITEventListener;
22+
23+
namespace orc {
24+
class LLJIT;
25+
class MangleAndInterner;
26+
} // namespace orc
27+
} // namespace llvm
28+
29+
namespace hc {
30+
struct ExecutionEngineOptions {
31+
/// `jitCodeGenOptLevel`, when provided, is used as the optimization level for
32+
/// target code generation.
33+
std::optional<llvm::CodeGenOptLevel> jitCodeGenOptLevel = std::nullopt;
34+
35+
/// If `enableObjectCache` is set, the JIT compiler will create one to store
36+
/// the object generated for the given module. The contents of the cache can
37+
/// be dumped to a file via the `dumpToObjectfile` method.
38+
bool enableObjectCache = false;
39+
40+
/// If enable `enableGDBNotificationListener` is set, the JIT compiler will
41+
/// notify the llvm's global GDB notification listener.
42+
bool enableGDBNotificationListener = true;
43+
44+
/// If `enablePerfNotificationListener` is set, the JIT compiler will notify
45+
/// the llvm's global Perf notification listener.
46+
bool enablePerfNotificationListener = true;
47+
48+
/// Register symbols with this ExecutionEngine.
49+
std::function<llvm::orc::SymbolMap(llvm::orc::MangleAndInterner)> symbolMap;
50+
51+
/// If `transformer` is provided, it will be called on the LLVM module during
52+
/// JIT-compilation and can be used, e.g., for reporting or optimization.
53+
std::function<llvm::Error(llvm::Module &)> transformer;
54+
55+
/// If `lateTransformer` is provided, it will be called on the LLVM module
56+
/// just before final code generation and can be used, e.g., for reporting or
57+
/// optimization.
58+
std::function<llvm::Error(llvm::Module &)> lateTransformer;
59+
60+
/// If `asmPrinter` is provided, it will be called to print resulted assembly
61+
/// just before final code generation.
62+
std::function<void(llvm::StringRef)> asmPrinter;
63+
};
64+
65+
class ExecutionEngine {
66+
class SimpleObjectCache;
67+
68+
public:
69+
using ModuleHandle = void *;
70+
71+
ExecutionEngine(const ExecutionEngineOptions &options);
72+
~ExecutionEngine();
73+
74+
/// Compiles given module, adds it to execution engine and run its contructors
75+
/// if any.
76+
llvm::Expected<ModuleHandle> loadModule(mlir::ModuleOp m);
77+
78+
/// Runs module desctructors and removes it from execution engine.
79+
void releaseModule(ModuleHandle handle);
80+
81+
/// Looks up the original function with the given name and returns a
82+
/// pointer to it. Propagates errors in case of failure.
83+
llvm::Expected<void *> lookup(ModuleHandle handle,
84+
llvm::StringRef name) const;
85+
86+
/// Dump object code to output file `filename`.
87+
void dumpToObjectFile(llvm::StringRef filename);
88+
89+
private:
90+
/// Ordering of llvmContext and jit is important for destruction purposes: the
91+
/// jit must be destroyed before the context.
92+
llvm::LLVMContext llvmContext;
93+
94+
/// Underlying LLJIT.
95+
std::unique_ptr<llvm::orc::LLJIT> jit;
96+
97+
/// Underlying cache.
98+
std::unique_ptr<SimpleObjectCache> cache;
99+
100+
/// GDB notification listener.
101+
llvm::JITEventListener *gdbListener;
102+
103+
/// Perf notification listener.
104+
llvm::JITEventListener *perfListener;
105+
106+
/// Callback to get additional symbol definitions.
107+
std::function<llvm::orc::SymbolMap(llvm::orc::MangleAndInterner)> symbolMap;
108+
109+
/// If `transformer` is provided, it will be called on the LLVM module during
110+
/// JIT-compilation and can be used, e.g., for reporting or optimization.
111+
std::function<llvm::Error(llvm::Module &)> transformer;
112+
113+
/// Id for unique module name generation.
114+
int uniqueNameCounter = 0;
115+
};
116+
} // namespace hc

0 commit comments

Comments
 (0)