Serene Runtime 1.0.0-dev
C runtime for the Serene programming language
Loading...
Searching...
No Matches
jit.cpp
Go to the documentation of this file.
1/* -*- C++ -*-
2 * Serene programming language
3 * Copyright (C) 2019-2026 Sameer Rahmani <lxsameer@lxsameer.com>
4 *
5 * This library is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this library. If not, see <https://www.gnu.org/licenses/>.
17 */
18
19#include "serene/jit/jit.h"
20
21#include <llvm/ExecutionEngine/JITEventListener.h>
22#include <llvm/ExecutionEngine/ObjectCache.h>
23#include <llvm/ExecutionEngine/Orc/LLJIT.h>
24#include <llvm/Support/Error.h>
25#include <llvm/Support/TargetSelect.h>
26
27#include <memory>
28#include <string>
29#include <utility>
30
31struct srn_object_cache_t : public llvm::ObjectCache {
32 /// Cache the given `objBuffer` for the given module `m`. The buffer contains
33 /// the combiled objects of the module
34 void notifyObjectCompiled(const llvm::Module *m, llvm::MemoryBufferRef objBuffer) override;
35
36 // Lookup the cache for the given module `m` or returen a nullptr.
37 std::unique_ptr<llvm::MemoryBuffer> getObject(const llvm::Module *m) override;
38
39 /// Dump cached object to output file `filename`.
40 void dumpToObjectFile(llvm::StringRef filename);
41
42private:
43 llvm::StringMap<std::unique_ptr<llvm::MemoryBuffer>> cachedObjects;
44};
45
46// The JIT engine handle. It is a C++ object owning the ORC session, so it is
47// allocated with `new` and freed with `delete` rather than through the arena:
48// the LLJIT and the cached strings need their destructors to run. `mm` is
49// retained for the memory-manager-backed allocations a later JITLink
50// integration will make.
51struct srn_jit_t {
53 std::unique_ptr<llvm::orc::LLJIT> jit;
54 std::unique_ptr<srn_object_cache_t> cache;
55
56 /// GDB notification listener.
57 llvm::JITEventListener *gdbListener;
58
59 /// Perf notification listener.
60 llvm::JITEventListener *perfListener;
61
62 llvm::orc::JITTargetMachineBuilder jtmb;
63 llvm::DataLayout &data_layout;
65
66 llvm::Triple triple;
67 srn_jit_config_t config;
68};
69
70extern "C" {
71
72srn_jit_t *srn_jit_create(srn_mm_t *mm, const srn_jit_config_t *config) {
73 if (mm == nullptr) {
74 return nullptr;
75 }
76
77 // TODO(lxsameer): long term, we might want to check the binfmt and enable none
78 // native targets here as well.
79 llvm::InitializeNativeTarget();
80 llvm::InitializeNativeTargetAsmPrinter();
81
82 auto jit_or_err = llvm::orc::LLJITBuilder().create();
83 if (!jit_or_err) {
84 llvm::consumeError(jit_or_err.takeError());
85 return nullptr;
86 }
87
88 auto *self = new srn_jit_t{};
89 self->mm = mm;
90 self->jit = std::move(*jit_or_err);
91 self->data_layout = self->jit->getDataLayout().getStringRepresentation();
92 self->triple = self->jit->getTargetTriple();
93 self->config = (config != nullptr)
94 ? *config
95 : srn_jit_config_t{.opt_level = 2, .install_default_pipeline = true};
96
97 return self;
98}
99
100void srn_jit_destroy(srn_jit_t *jit) { delete jit; }
101
102const char *srn_jit_data_layout(srn_jit_t *jit) { return jit->data_layout.c_str(); }
103
104const char *srn_jit_triple(srn_jit_t *jit) { return jit->triple.c_str(); }
105
107srn_jit_add_ir(srn_jit_t *, srn_context_t *ctx, const char *, size_t, srn_jit_module_t **) {
108 return srn_errors_make(ctx, NOT_IMPLEMENTED, "srn_jit_add_ir is not yet implemented");
109}
110
113 return srn_errors_make(ctx, NOT_IMPLEMENTED, "srn_jit_add_bitcode is not yet implemented");
114}
115
116srn_error_t *srn_jit_define(srn_jit_t *, srn_context_t *ctx, const char *, void *) {
117 return srn_errors_make(ctx, NOT_IMPLEMENTED, "srn_jit_define is not yet implemented");
118}
119
121 return srn_errors_make(
122 ctx, NOT_IMPLEMENTED, "srn_jit_expose_process_symbols is not yet implemented"
123 );
124}
125
126srn_error_t *srn_jit_lookup(srn_jit_t *, srn_context_t *ctx, const char *, void **) {
127 return srn_errors_make(ctx, NOT_IMPLEMENTED, "srn_jit_lookup is not yet implemented");
128}
129
131 return srn_errors_make(ctx, NOT_IMPLEMENTED, "srn_jit_remove is not yet implemented");
132}
133
134} // extern "C"
srn_error_t * srn_errors_make(const srn_context_t *ctx, srn_error_tag_t tag, const char *msg, void *caller)
Build an error in ctx's memory, tagged tag and carrying msg.
Definition errors.c:196
@ NOT_IMPLEMENTED
Definition errors.h:94
srn_jit_t * srn_jit_create(srn_mm_t *mm, const srn_jit_config_t *config)
Definition jit.cpp:72
const char * srn_jit_data_layout(srn_jit_t *jit)
Definition jit.cpp:102
const char * srn_jit_triple(srn_jit_t *jit)
Definition jit.cpp:104
srn_error_t * srn_jit_remove(srn_jit_t *, srn_context_t *ctx, srn_jit_module_t *)
Definition jit.cpp:130
void srn_jit_destroy(srn_jit_t *jit)
Definition jit.cpp:100
srn_error_t * srn_jit_expose_process_symbols(srn_jit_t *, srn_context_t *ctx)
Definition jit.cpp:120
srn_error_t * srn_jit_lookup(srn_jit_t *, srn_context_t *ctx, const char *, void **)
Definition jit.cpp:126
srn_error_t * srn_jit_add_ir(srn_jit_t *, srn_context_t *ctx, const char *, size_t, srn_jit_module_t **)
Definition jit.cpp:107
srn_error_t * srn_jit_add_bitcode(srn_jit_t *, srn_context_t *ctx, const void *, size_t, srn_jit_module_t **)
Definition jit.cpp:112
srn_error_t * srn_jit_define(srn_jit_t *, srn_context_t *ctx, const char *, void *)
Definition jit.cpp:116
A runtime error, a tag classifying the failure and a human-readable message.
Definition errors.h:173
srn_context_t & root_ctx
Definition jit.cpp:64
llvm::JITEventListener * perfListener
Perf notification listener.
Definition jit.cpp:60
srn_jit_config_t config
Definition jit.cpp:67
srn_mm_t * mm
Definition jit.cpp:52
llvm::Triple triple
Definition jit.cpp:66
llvm::JITEventListener * gdbListener
GDB notification listener.
Definition jit.cpp:57
std::unique_ptr< llvm::orc::LLJIT > jit
Definition jit.cpp:53
std::unique_ptr< srn_object_cache_t > cache
Definition jit.cpp:54
llvm::DataLayout & data_layout
Definition jit.cpp:63
llvm::orc::JITTargetMachineBuilder jtmb
Definition jit.cpp:62
Main memory manager structure that will own all the allocated blocks and data.
Definition interface.h:112
std::unique_ptr< llvm::MemoryBuffer > getObject(const llvm::Module *m) override
void dumpToObjectFile(llvm::StringRef filename)
Dump cached object to output file filename.
llvm::StringMap< std::unique_ptr< llvm::MemoryBuffer > > cachedObjects
Definition jit.cpp:43
void notifyObjectCompiled(const llvm::Module *m, llvm::MemoryBufferRef objBuffer) override
Cache the given objBuffer for the given module m.