]>
Commit | Line | Data |
---|---|---|
48b0b56d JP |
1 | From 90eb343ef3929a0cce5b6940781680cd4f7801f2 Mon Sep 17 00:00:00 2001 |
2 | From: Andres Freund <andres@anarazel.de> | |
3 | Date: Mon, 9 Nov 2020 20:01:33 -0800 | |
4 | Subject: [PATCH] backpatch "jit: Add support for LLVM 12." | |
5 | ||
6 | As there haven't been problem on the buildfarm due to this change, | |
7 | backpatch 6c57f2ed16e now. | |
8 | ||
9 | Author: Andres Freund | |
10 | Discussion: https://postgr.es/m/20201016011244.pmyvr3ee2gbzplq4@alap3.anarazel.de | |
11 | Backpatch: 11-, where jit support was added | |
12 | --- | |
13 | src/backend/jit/llvm/llvmjit.c | 458 +++++++++++++++++++++++++------ | |
14 | src/tools/pgindent/typedefs.list | 1 + | |
15 | 2 files changed, 374 insertions(+), 85 deletions(-) | |
16 | ||
17 | diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c | |
18 | index 929873cb49..78c0b9385c 100644 | |
19 | --- a/src/backend/jit/llvm/llvmjit.c | |
20 | +++ b/src/backend/jit/llvm/llvmjit.c | |
21 | @@ -29,7 +29,13 @@ | |
22 | #include <llvm-c/BitWriter.h> | |
23 | #include <llvm-c/Core.h> | |
24 | #include <llvm-c/ExecutionEngine.h> | |
25 | +#if LLVM_VERSION_MAJOR > 11 | |
26 | +#include <llvm-c/Orc.h> | |
27 | +#include <llvm-c/OrcEE.h> | |
28 | +#include <llvm-c/LLJIT.h> | |
29 | +#else | |
30 | #include <llvm-c/OrcBindings.h> | |
31 | +#endif | |
32 | #include <llvm-c/Support.h> | |
33 | #include <llvm-c/Target.h> | |
34 | #include <llvm-c/Transforms/IPO.h> | |
35 | @@ -43,8 +49,13 @@ | |
36 | /* Handle of a module emitted via ORC JIT */ | |
37 | typedef struct LLVMJitHandle | |
38 | { | |
39 | +#if LLVM_VERSION_MAJOR > 11 | |
40 | + LLVMOrcLLJITRef lljit; | |
41 | + LLVMOrcResourceTrackerRef resource_tracker; | |
42 | +#else | |
43 | LLVMOrcJITStackRef stack; | |
44 | LLVMOrcModuleHandle orc_handle; | |
45 | +#endif | |
46 | } LLVMJitHandle; | |
47 | ||
48 | ||
49 | @@ -94,12 +105,15 @@ static const char *llvm_triple = NULL; | |
50 | static const char *llvm_layout = NULL; | |
51 | ||
52 | ||
53 | -static LLVMTargetMachineRef llvm_opt0_targetmachine; | |
54 | -static LLVMTargetMachineRef llvm_opt3_targetmachine; | |
55 | - | |
56 | static LLVMTargetRef llvm_targetref; | |
57 | +#if LLVM_VERSION_MAJOR > 11 | |
58 | +static LLVMOrcThreadSafeContextRef llvm_ts_context; | |
59 | +static LLVMOrcLLJITRef llvm_opt0_orc; | |
60 | +static LLVMOrcLLJITRef llvm_opt3_orc; | |
61 | +#else /* LLVM_VERSION_MAJOR > 11 */ | |
62 | static LLVMOrcJITStackRef llvm_opt0_orc; | |
63 | static LLVMOrcJITStackRef llvm_opt3_orc; | |
64 | +#endif /* LLVM_VERSION_MAJOR > 11 */ | |
65 | ||
66 | ||
67 | static void llvm_release_context(JitContext *context); | |
68 | @@ -111,6 +125,10 @@ static void llvm_optimize_module(LLVMJitContext *context, LLVMModuleRef module); | |
69 | static void llvm_create_types(void); | |
70 | static uint64_t llvm_resolve_symbol(const char *name, void *ctx); | |
71 | ||
72 | +#if LLVM_VERSION_MAJOR > 11 | |
73 | +static LLVMOrcLLJITRef llvm_create_jit_instance(LLVMTargetMachineRef tm); | |
74 | +static char *llvm_error_message(LLVMErrorRef error); | |
75 | +#endif /* LLVM_VERSION_MAJOR > 11 */ | |
76 | ||
77 | PG_MODULE_MAGIC; | |
78 | ||
79 | @@ -170,24 +188,47 @@ llvm_release_context(JitContext *context) | |
80 | * have occurred from within LLVM, we do not want to risk reentering. All | |
81 | * resource cleanup is going to happen through process exit. | |
82 | */ | |
83 | - if (!proc_exit_inprogress) | |
84 | + if (proc_exit_inprogress) | |
85 | + return; | |
86 | + | |
87 | + if (llvm_context->module) | |
88 | { | |
89 | - if (llvm_context->module) | |
90 | - { | |
91 | - LLVMDisposeModule(llvm_context->module); | |
92 | - llvm_context->module = NULL; | |
93 | - } | |
94 | + LLVMDisposeModule(llvm_context->module); | |
95 | + llvm_context->module = NULL; | |
96 | + } | |
97 | ||
98 | - while (llvm_context->handles != NIL) | |
99 | - { | |
100 | - LLVMJitHandle *jit_handle; | |
101 | + while (llvm_context->handles != NIL) | |
102 | + { | |
103 | + LLVMJitHandle *jit_handle; | |
104 | ||
105 | - jit_handle = (LLVMJitHandle *) linitial(llvm_context->handles); | |
106 | - llvm_context->handles = list_delete_first(llvm_context->handles); | |
107 | + jit_handle = (LLVMJitHandle *) linitial(llvm_context->handles); | |
108 | + llvm_context->handles = list_delete_first(llvm_context->handles); | |
109 | ||
110 | +#if LLVM_VERSION_MAJOR > 11 | |
111 | + { | |
112 | + LLVMOrcExecutionSessionRef ee; | |
113 | + LLVMOrcSymbolStringPoolRef sp; | |
114 | + | |
115 | + LLVMOrcResourceTrackerRemove(jit_handle->resource_tracker); | |
116 | + LLVMOrcReleaseResourceTracker(jit_handle->resource_tracker); | |
117 | + | |
118 | + /* | |
119 | + * Without triggering cleanup of the string pool, we'd leak | |
120 | + * memory. It'd be sufficient to do this far less often, but in | |
121 | + * experiments the required time was small enough to just always | |
122 | + * do it. | |
123 | + */ | |
124 | + ee = LLVMOrcLLJITGetExecutionSession(jit_handle->lljit); | |
125 | + sp = LLVMOrcExecutionSessionGetSymbolStringPool(ee); | |
126 | + LLVMOrcSymbolStringPoolClearDeadEntries(sp); | |
127 | + } | |
128 | +#else /* LLVM_VERSION_MAJOR > 11 */ | |
129 | + { | |
130 | LLVMOrcRemoveModule(jit_handle->stack, jit_handle->orc_handle); | |
131 | - pfree(jit_handle); | |
132 | } | |
133 | +#endif /* LLVM_VERSION_MAJOR > 11 */ | |
134 | + | |
135 | + pfree(jit_handle); | |
136 | } | |
137 | } | |
138 | ||
139 | @@ -243,8 +284,8 @@ llvm_expand_funcname(struct LLVMJitContext *context, const char *basename) | |
140 | void * | |
141 | llvm_get_function(LLVMJitContext *context, const char *funcname) | |
142 | { | |
143 | - LLVMOrcTargetAddress addr = 0; | |
144 | -#if defined(HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN) && HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN | |
145 | +#if LLVM_VERSION_MAJOR > 11 || \ | |
146 | + defined(HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN) && HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN | |
147 | ListCell *lc; | |
148 | #endif | |
149 | ||
150 | @@ -264,9 +305,40 @@ llvm_get_function(LLVMJitContext *context, const char *funcname) | |
151 | * to mangle here. | |
152 | */ | |
153 | ||
154 | -#if defined(HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN) && HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN | |
155 | +#if LLVM_VERSION_MAJOR > 11 | |
156 | + foreach(lc, context->handles) | |
157 | + { | |
158 | + LLVMJitHandle *handle = (LLVMJitHandle *) lfirst(lc); | |
159 | + instr_time starttime; | |
160 | + instr_time endtime; | |
161 | + LLVMErrorRef error; | |
162 | + LLVMOrcJITTargetAddress addr; | |
163 | + | |
164 | + INSTR_TIME_SET_CURRENT(starttime); | |
165 | + | |
166 | + addr = 0; | |
167 | + error = LLVMOrcLLJITLookup(handle->lljit, &addr, funcname); | |
168 | + if (error) | |
169 | + elog(ERROR, "failed to look up symbol \"%s\": %s", | |
170 | + funcname, llvm_error_message(error)); | |
171 | + | |
172 | + /* | |
173 | + * LLJIT only actually emits code the first time a symbol is | |
174 | + * referenced. Thus add lookup time to emission time. That's counting | |
175 | + * a bit more than with older LLVM versions, but unlikely to ever | |
176 | + * matter. | |
177 | + */ | |
178 | + INSTR_TIME_SET_CURRENT(endtime); | |
179 | + INSTR_TIME_ACCUM_DIFF(context->base.instr.emission_counter, | |
180 | + endtime, starttime); | |
181 | + | |
182 | + if (addr) | |
183 | + return (void *) (uintptr_t) addr; | |
184 | + } | |
185 | +#elif defined(HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN) && HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN | |
186 | foreach(lc, context->handles) | |
187 | { | |
188 | + LLVMOrcTargetAddress addr; | |
189 | LLVMJitHandle *handle = (LLVMJitHandle *) lfirst(lc); | |
190 | ||
191 | addr = 0; | |
192 | @@ -275,26 +347,29 @@ llvm_get_function(LLVMJitContext *context, const char *funcname) | |
193 | if (addr) | |
194 | return (void *) (uintptr_t) addr; | |
195 | } | |
196 | +#elif LLVM_VERSION_MAJOR < 5 | |
197 | + { | |
198 | + LLVMOrcTargetAddress addr; | |
199 | ||
200 | + if ((addr = LLVMOrcGetSymbolAddress(llvm_opt0_orc, funcname))) | |
201 | + return (void *) (uintptr_t) addr; | |
202 | + if ((addr = LLVMOrcGetSymbolAddress(llvm_opt3_orc, funcname))) | |
203 | + return (void *) (uintptr_t) addr; | |
204 | + } | |
205 | #else | |
206 | + { | |
207 | + LLVMOrcTargetAddress addr; | |
208 | ||
209 | -#if LLVM_VERSION_MAJOR < 5 | |
210 | - if ((addr = LLVMOrcGetSymbolAddress(llvm_opt0_orc, funcname))) | |
211 | - return (void *) (uintptr_t) addr; | |
212 | - if ((addr = LLVMOrcGetSymbolAddress(llvm_opt3_orc, funcname))) | |
213 | - return (void *) (uintptr_t) addr; | |
214 | -#else | |
215 | - if (LLVMOrcGetSymbolAddress(llvm_opt0_orc, &addr, funcname)) | |
216 | - elog(ERROR, "failed to look up symbol \"%s\"", funcname); | |
217 | - if (addr) | |
218 | - return (void *) (uintptr_t) addr; | |
219 | - if (LLVMOrcGetSymbolAddress(llvm_opt3_orc, &addr, funcname)) | |
220 | - elog(ERROR, "failed to look up symbol \"%s\"", funcname); | |
221 | - if (addr) | |
222 | - return (void *) (uintptr_t) addr; | |
223 | -#endif /* LLVM_VERSION_MAJOR */ | |
224 | - | |
225 | -#endif /* HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN */ | |
226 | + if (LLVMOrcGetSymbolAddress(llvm_opt0_orc, &addr, funcname)) | |
227 | + elog(ERROR, "failed to look up symbol \"%s\"", funcname); | |
228 | + if (addr) | |
229 | + return (void *) (uintptr_t) addr; | |
230 | + if (LLVMOrcGetSymbolAddress(llvm_opt3_orc, &addr, funcname)) | |
231 | + elog(ERROR, "failed to look up symbol \"%s\"", funcname); | |
232 | + if (addr) | |
233 | + return (void *) (uintptr_t) addr; | |
234 | + } | |
235 | +#endif | |
236 | ||
237 | elog(ERROR, "failed to JIT: %s", funcname); | |
238 | ||
239 | @@ -425,6 +500,8 @@ llvm_function_reference(LLVMJitContext *context, | |
240 | v_fn = LLVMAddGlobal(mod, TypePGFunction, funcname); | |
241 | LLVMSetInitializer(v_fn, v_fn_addr); | |
242 | LLVMSetGlobalConstant(v_fn, true); | |
243 | + LLVMSetLinkage(v_fn, LLVMPrivateLinkage); | |
244 | + LLVMSetUnnamedAddr(v_fn, true); | |
245 | ||
246 | return LLVMBuildLoad(builder, v_fn, ""); | |
247 | } | |
248 | @@ -516,11 +593,15 @@ llvm_optimize_module(LLVMJitContext *context, LLVMModuleRef module) | |
249 | static void | |
250 | llvm_compile_module(LLVMJitContext *context) | |
251 | { | |
252 | - LLVMOrcModuleHandle orc_handle; | |
253 | + LLVMJitHandle *handle; | |
254 | MemoryContext oldcontext; | |
255 | - static LLVMOrcJITStackRef compile_orc; | |
256 | instr_time starttime; | |
257 | instr_time endtime; | |
258 | +#if LLVM_VERSION_MAJOR > 11 | |
259 | + LLVMOrcLLJITRef compile_orc; | |
260 | +#else | |
261 | + LLVMOrcJITStackRef compile_orc; | |
262 | +#endif | |
263 | ||
264 | if (context->base.flags & PGJIT_OPT3) | |
265 | compile_orc = llvm_opt3_orc; | |
266 | @@ -567,6 +648,9 @@ llvm_compile_module(LLVMJitContext *context) | |
267 | pfree(filename); | |
268 | } | |
269 | ||
270 | + handle = (LLVMJitHandle *) | |
271 | + MemoryContextAlloc(TopMemoryContext, sizeof(LLVMJitHandle)); | |
272 | + | |
273 | /* | |
274 | * Emit the code. Note that this can, depending on the optimization | |
275 | * settings, take noticeable resources as code emission executes low-level | |
276 | @@ -574,13 +658,42 @@ llvm_compile_module(LLVMJitContext *context) | |
277 | * faster instruction selection mechanism is used. | |
278 | */ | |
279 | INSTR_TIME_SET_CURRENT(starttime); | |
280 | -#if LLVM_VERSION_MAJOR > 6 | |
281 | +#if LLVM_VERSION_MAJOR > 11 | |
282 | + { | |
283 | + LLVMOrcThreadSafeModuleRef ts_module; | |
284 | + LLVMErrorRef error; | |
285 | + LLVMOrcJITDylibRef jd = LLVMOrcLLJITGetMainJITDylib(compile_orc); | |
286 | + | |
287 | + ts_module = LLVMOrcCreateNewThreadSafeModule(context->module, llvm_ts_context); | |
288 | + | |
289 | + handle->lljit = compile_orc; | |
290 | + handle->resource_tracker = LLVMOrcJITDylibCreateResourceTracker(jd); | |
291 | + | |
292 | + /* | |
293 | + * NB: This doesn't actually emit code. That happens lazily the first | |
294 | + * time a symbol defined in the module is requested. Due to that | |
295 | + * llvm_get_function() also accounts for emission time. | |
296 | + */ | |
297 | + | |
298 | + context->module = NULL; /* will be owned by LLJIT */ | |
299 | + error = LLVMOrcLLJITAddLLVMIRModuleWithRT(compile_orc, | |
300 | + handle->resource_tracker, | |
301 | + ts_module); | |
302 | + | |
303 | + if (error) | |
304 | + elog(ERROR, "failed to JIT module: %s", | |
305 | + llvm_error_message(error)); | |
306 | + | |
307 | + handle->lljit = compile_orc; | |
308 | + | |
309 | + /* LLVMOrcLLJITAddLLVMIRModuleWithRT takes ownership of the module */ | |
310 | + } | |
311 | +#elif LLVM_VERSION_MAJOR > 6 | |
312 | { | |
313 | - if (LLVMOrcAddEagerlyCompiledIR(compile_orc, &orc_handle, context->module, | |
314 | + handle->stack = compile_orc; | |
315 | + if (LLVMOrcAddEagerlyCompiledIR(compile_orc, &handle->orc_handle, context->module, | |
316 | llvm_resolve_symbol, NULL)) | |
317 | - { | |
318 | elog(ERROR, "failed to JIT module"); | |
319 | - } | |
320 | ||
321 | /* LLVMOrcAddEagerlyCompiledIR takes ownership of the module */ | |
322 | } | |
323 | @@ -589,20 +702,23 @@ llvm_compile_module(LLVMJitContext *context) | |
324 | LLVMSharedModuleRef smod; | |
325 | ||
326 | smod = LLVMOrcMakeSharedModule(context->module); | |
327 | - if (LLVMOrcAddEagerlyCompiledIR(compile_orc, &orc_handle, smod, | |
328 | + handle->stack = compile_orc; | |
329 | + if (LLVMOrcAddEagerlyCompiledIR(compile_orc, &handle->orc_handle, smod, | |
330 | llvm_resolve_symbol, NULL)) | |
331 | - { | |
332 | elog(ERROR, "failed to JIT module"); | |
333 | - } | |
334 | + | |
335 | LLVMOrcDisposeSharedModuleRef(smod); | |
336 | } | |
337 | #else /* LLVM 4.0 and 3.9 */ | |
338 | { | |
339 | - orc_handle = LLVMOrcAddEagerlyCompiledIR(compile_orc, context->module, | |
340 | - llvm_resolve_symbol, NULL); | |
341 | + handle->stack = compile_orc; | |
342 | + handle->orc_handle = LLVMOrcAddEagerlyCompiledIR(compile_orc, context->module, | |
343 | + llvm_resolve_symbol, NULL); | |
344 | + | |
345 | LLVMDisposeModule(context->module); | |
346 | } | |
347 | #endif | |
348 | + | |
349 | INSTR_TIME_SET_CURRENT(endtime); | |
350 | INSTR_TIME_ACCUM_DIFF(context->base.instr.emission_counter, | |
351 | endtime, starttime); | |
352 | @@ -612,15 +728,7 @@ llvm_compile_module(LLVMJitContext *context) | |
353 | ||
354 | /* remember emitted code for cleanup and lookups */ | |
355 | oldcontext = MemoryContextSwitchTo(TopMemoryContext); | |
356 | - { | |
357 | - LLVMJitHandle *handle; | |
358 | - | |
359 | - handle = (LLVMJitHandle *) palloc(sizeof(LLVMJitHandle)); | |
360 | - handle->stack = compile_orc; | |
361 | - handle->orc_handle = orc_handle; | |
362 | - | |
363 | - context->handles = lappend(context->handles, handle); | |
364 | - } | |
365 | + context->handles = lappend(context->handles, handle); | |
366 | MemoryContextSwitchTo(oldcontext); | |
367 | ||
368 | ereport(DEBUG1, | |
369 | @@ -642,6 +750,8 @@ llvm_session_initialize(void) | |
370 | char *error = NULL; | |
371 | char *cpu = NULL; | |
372 | char *features = NULL; | |
373 | + LLVMTargetMachineRef opt0_tm; | |
374 | + LLVMTargetMachineRef opt3_tm; | |
375 | ||
376 | if (llvm_session_initialized) | |
377 | return; | |
378 | @@ -674,12 +784,12 @@ llvm_session_initialize(void) | |
379 | elog(DEBUG2, "LLVMJIT detected CPU \"%s\", with features \"%s\"", | |
380 | cpu, features); | |
381 | ||
382 | - llvm_opt0_targetmachine = | |
383 | + opt0_tm = | |
384 | LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features, | |
385 | LLVMCodeGenLevelNone, | |
386 | LLVMRelocDefault, | |
387 | LLVMCodeModelJITDefault); | |
388 | - llvm_opt3_targetmachine = | |
389 | + opt3_tm = | |
390 | LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features, | |
391 | LLVMCodeGenLevelAggressive, | |
392 | LLVMRelocDefault, | |
393 | @@ -693,27 +803,41 @@ llvm_session_initialize(void) | |
394 | /* force symbols in main binary to be loaded */ | |
395 | LLVMLoadLibraryPermanently(NULL); | |
396 | ||
397 | - llvm_opt0_orc = LLVMOrcCreateInstance(llvm_opt0_targetmachine); | |
398 | - llvm_opt3_orc = LLVMOrcCreateInstance(llvm_opt3_targetmachine); | |
399 | - | |
400 | -#if defined(HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER) && HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER | |
401 | - if (jit_debugging_support) | |
402 | +#if LLVM_VERSION_MAJOR > 11 | |
403 | { | |
404 | - LLVMJITEventListenerRef l = LLVMCreateGDBRegistrationListener(); | |
405 | + llvm_ts_context = LLVMOrcCreateNewThreadSafeContext(); | |
406 | + | |
407 | + llvm_opt0_orc = llvm_create_jit_instance(opt0_tm); | |
408 | + opt0_tm = 0; | |
409 | ||
410 | - LLVMOrcRegisterJITEventListener(llvm_opt0_orc, l); | |
411 | - LLVMOrcRegisterJITEventListener(llvm_opt3_orc, l); | |
412 | + llvm_opt3_orc = llvm_create_jit_instance(opt3_tm); | |
413 | + opt3_tm = 0; | |
414 | } | |
415 | +#else /* LLVM_VERSION_MAJOR > 11 */ | |
416 | + { | |
417 | + llvm_opt0_orc = LLVMOrcCreateInstance(opt0_tm); | |
418 | + llvm_opt3_orc = LLVMOrcCreateInstance(opt3_tm); | |
419 | + | |
420 | +#if defined(HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER) && HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER | |
421 | + if (jit_debugging_support) | |
422 | + { | |
423 | + LLVMJITEventListenerRef l = LLVMCreateGDBRegistrationListener(); | |
424 | + | |
425 | + LLVMOrcRegisterJITEventListener(llvm_opt0_orc, l); | |
426 | + LLVMOrcRegisterJITEventListener(llvm_opt3_orc, l); | |
427 | + } | |
428 | #endif | |
429 | #if defined(HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER) && HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER | |
430 | - if (jit_profiling_support) | |
431 | - { | |
432 | - LLVMJITEventListenerRef l = LLVMCreatePerfJITEventListener(); | |
433 | + if (jit_profiling_support) | |
434 | + { | |
435 | + LLVMJITEventListenerRef l = LLVMCreatePerfJITEventListener(); | |
436 | ||
437 | - LLVMOrcRegisterJITEventListener(llvm_opt0_orc, l); | |
438 | - LLVMOrcRegisterJITEventListener(llvm_opt3_orc, l); | |
439 | - } | |
440 | + LLVMOrcRegisterJITEventListener(llvm_opt0_orc, l); | |
441 | + LLVMOrcRegisterJITEventListener(llvm_opt3_orc, l); | |
442 | + } | |
443 | #endif | |
444 | + } | |
445 | +#endif /* LLVM_VERSION_MAJOR > 11 */ | |
446 | ||
447 | before_shmem_exit(llvm_shutdown, 0); | |
448 | ||
449 | @@ -725,27 +849,49 @@ llvm_session_initialize(void) | |
450 | static void | |
451 | llvm_shutdown(int code, Datum arg) | |
452 | { | |
453 | - /* unregister profiling support, needs to be flushed to be useful */ | |
454 | - | |
455 | - if (llvm_opt3_orc) | |
456 | +#if LLVM_VERSION_MAJOR > 11 | |
457 | + { | |
458 | + if (llvm_opt3_orc) | |
459 | + { | |
460 | + LLVMOrcDisposeLLJIT(llvm_opt3_orc); | |
461 | + llvm_opt3_orc = NULL; | |
462 | + } | |
463 | + if (llvm_opt0_orc) | |
464 | + { | |
465 | + LLVMOrcDisposeLLJIT(llvm_opt0_orc); | |
466 | + llvm_opt0_orc = NULL; | |
467 | + } | |
468 | + if (llvm_ts_context) | |
469 | + { | |
470 | + LLVMOrcDisposeThreadSafeContext(llvm_ts_context); | |
471 | + llvm_ts_context = NULL; | |
472 | + } | |
473 | + } | |
474 | +#else /* LLVM_VERSION_MAJOR > 11 */ | |
475 | { | |
476 | + /* unregister profiling support, needs to be flushed to be useful */ | |
477 | + | |
478 | + if (llvm_opt3_orc) | |
479 | + { | |
480 | #if defined(HAVE_DECL_LLVMORCREGISTERPERF) && HAVE_DECL_LLVMORCREGISTERPERF | |
481 | - if (jit_profiling_support) | |
482 | - LLVMOrcUnregisterPerf(llvm_opt3_orc); | |
483 | + if (jit_profiling_support) | |
484 | + LLVMOrcUnregisterPerf(llvm_opt3_orc); | |
485 | #endif | |
486 | - LLVMOrcDisposeInstance(llvm_opt3_orc); | |
487 | - llvm_opt3_orc = NULL; | |
488 | - } | |
489 | + LLVMOrcDisposeInstance(llvm_opt3_orc); | |
490 | + llvm_opt3_orc = NULL; | |
491 | + } | |
492 | ||
493 | - if (llvm_opt0_orc) | |
494 | - { | |
495 | + if (llvm_opt0_orc) | |
496 | + { | |
497 | #if defined(HAVE_DECL_LLVMORCREGISTERPERF) && HAVE_DECL_LLVMORCREGISTERPERF | |
498 | - if (jit_profiling_support) | |
499 | - LLVMOrcUnregisterPerf(llvm_opt0_orc); | |
500 | + if (jit_profiling_support) | |
501 | + LLVMOrcUnregisterPerf(llvm_opt0_orc); | |
502 | #endif | |
503 | - LLVMOrcDisposeInstance(llvm_opt0_orc); | |
504 | - llvm_opt0_orc = NULL; | |
505 | + LLVMOrcDisposeInstance(llvm_opt0_orc); | |
506 | + llvm_opt0_orc = NULL; | |
507 | + } | |
508 | } | |
509 | +#endif /* LLVM_VERSION_MAJOR > 11 */ | |
510 | } | |
511 | ||
512 | /* helper for llvm_create_types, returning a global var's type */ | |
513 | @@ -941,3 +1087,145 @@ llvm_resolve_symbol(const char *symname, void *ctx) | |
514 | ||
515 | return (uint64_t) addr; | |
516 | } | |
517 | + | |
518 | +#if LLVM_VERSION_MAJOR > 11 | |
519 | + | |
520 | +static LLVMErrorRef | |
521 | +llvm_resolve_symbols(LLVMOrcDefinitionGeneratorRef GeneratorObj, void *Ctx, | |
522 | + LLVMOrcLookupStateRef *LookupState, LLVMOrcLookupKind Kind, | |
523 | + LLVMOrcJITDylibRef JD, LLVMOrcJITDylibLookupFlags JDLookupFlags, | |
524 | + LLVMOrcCLookupSet LookupSet, size_t LookupSetSize) | |
525 | +{ | |
526 | + LLVMOrcCSymbolMapPairs symbols = palloc0(sizeof(LLVMJITCSymbolMapPair) * LookupSetSize); | |
527 | + LLVMErrorRef error; | |
528 | + LLVMOrcMaterializationUnitRef mu; | |
529 | + | |
530 | + for (int i = 0; i < LookupSetSize; i++) | |
531 | + { | |
532 | + const char *name = LLVMOrcSymbolStringPoolEntryStr(LookupSet[i].Name); | |
533 | + | |
534 | + symbols[i].Name = LookupSet[i].Name; | |
535 | + symbols[i].Sym.Address = llvm_resolve_symbol(name, NULL); | |
536 | + symbols[i].Sym.Flags.GenericFlags = LLVMJITSymbolGenericFlagsExported; | |
537 | + } | |
538 | + | |
539 | + mu = LLVMOrcAbsoluteSymbols(symbols, LookupSetSize); | |
540 | + error = LLVMOrcJITDylibDefine(JD, mu); | |
541 | + if (error != LLVMErrorSuccess) | |
542 | + LLVMOrcDisposeMaterializationUnit(mu); | |
543 | + | |
544 | + pfree(symbols); | |
545 | + | |
546 | + return error; | |
547 | +} | |
548 | + | |
549 | +/* | |
550 | + * We cannot throw errors through LLVM (without causing a FATAL at least), so | |
551 | + * just use WARNING here. That's OK anyway, as the error is also reported at | |
552 | + * the top level action (with less detail) and there might be multiple | |
553 | + * invocations of errors with details. | |
554 | + * | |
555 | + * This doesn't really happen during normal operation, but in cases like | |
556 | + * symbol resolution breakage. So just using elog(WARNING) is fine. | |
557 | + */ | |
558 | +static void | |
559 | +llvm_log_jit_error(void *ctx, LLVMErrorRef error) | |
560 | +{ | |
561 | + elog(WARNING, "error during JITing: %s", | |
562 | + llvm_error_message(error)); | |
563 | +} | |
564 | + | |
565 | +/* | |
566 | + * Create our own object layer, so we can add event listeners. | |
567 | + */ | |
568 | +static LLVMOrcObjectLayerRef | |
569 | +llvm_create_object_layer(void *Ctx, LLVMOrcExecutionSessionRef ES, const char *Triple) | |
570 | +{ | |
571 | + LLVMOrcObjectLayerRef objlayer = | |
572 | + LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager(ES); | |
573 | + | |
574 | +#if defined(HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER) && HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER | |
575 | + if (jit_debugging_support) | |
576 | + { | |
577 | + LLVMJITEventListenerRef l = LLVMCreateGDBRegistrationListener(); | |
578 | + | |
579 | + LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(objlayer, l); | |
580 | + } | |
581 | +#endif | |
582 | + | |
583 | +#if defined(HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER) && HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER | |
584 | + if (jit_profiling_support) | |
585 | + { | |
586 | + LLVMJITEventListenerRef l = LLVMCreatePerfJITEventListener(); | |
587 | + | |
588 | + LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(objlayer, l); | |
589 | + } | |
590 | +#endif | |
591 | + | |
592 | + return objlayer; | |
593 | +} | |
594 | + | |
595 | +/* | |
596 | + * Create LLJIT instance, using the passed in target machine. Note that the | |
597 | + * target machine afterwards is owned by the LLJIT instance. | |
598 | + */ | |
599 | +static LLVMOrcLLJITRef | |
600 | +llvm_create_jit_instance(LLVMTargetMachineRef tm) | |
601 | +{ | |
602 | + LLVMOrcLLJITRef lljit; | |
603 | + LLVMOrcJITTargetMachineBuilderRef tm_builder; | |
604 | + LLVMOrcLLJITBuilderRef lljit_builder; | |
605 | + LLVMErrorRef error; | |
606 | + LLVMOrcDefinitionGeneratorRef main_gen; | |
607 | + LLVMOrcDefinitionGeneratorRef ref_gen; | |
608 | + | |
609 | + lljit_builder = LLVMOrcCreateLLJITBuilder(); | |
610 | + tm_builder = LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(tm); | |
611 | + LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(lljit_builder, tm_builder); | |
612 | + | |
613 | + LLVMOrcLLJITBuilderSetObjectLinkingLayerCreator(lljit_builder, | |
614 | + llvm_create_object_layer, | |
615 | + NULL); | |
616 | + | |
617 | + error = LLVMOrcCreateLLJIT(&lljit, lljit_builder); | |
618 | + if (error) | |
619 | + elog(ERROR, "failed to create lljit instance: %s", | |
620 | + llvm_error_message(error)); | |
621 | + | |
622 | + LLVMOrcExecutionSessionSetErrorReporter(LLVMOrcLLJITGetExecutionSession(lljit), | |
623 | + llvm_log_jit_error, NULL); | |
624 | + | |
625 | + /* | |
626 | + * Symbol resolution support for symbols in the postgres binary / | |
627 | + * libraries already loaded. | |
628 | + */ | |
629 | + error = LLVMOrcCreateDynamicLibrarySearchGeneratorForProcess(&main_gen, | |
630 | + LLVMOrcLLJITGetGlobalPrefix(lljit), | |
631 | + 0, NULL); | |
632 | + if (error) | |
633 | + elog(ERROR, "failed to create generator: %s", | |
634 | + llvm_error_message(error)); | |
635 | + LLVMOrcJITDylibAddGenerator(LLVMOrcLLJITGetMainJITDylib(lljit), main_gen); | |
636 | + | |
637 | + /* | |
638 | + * Symbol resolution support for "special" functions, e.g. a call into an | |
639 | + * SQL callable function. | |
640 | + */ | |
641 | + ref_gen = LLVMOrcCreateCustomCAPIDefinitionGenerator(llvm_resolve_symbols, NULL); | |
642 | + LLVMOrcJITDylibAddGenerator(LLVMOrcLLJITGetMainJITDylib(lljit), ref_gen); | |
643 | + | |
644 | + return lljit; | |
645 | +} | |
646 | + | |
647 | +static char * | |
648 | +llvm_error_message(LLVMErrorRef error) | |
649 | +{ | |
650 | + char *orig = LLVMGetErrorMessage(error); | |
651 | + char *msg = pstrdup(orig); | |
652 | + | |
653 | + LLVMDisposeErrorMessage(orig); | |
654 | + | |
655 | + return msg; | |
656 | +} | |
657 | + | |
658 | +#endif /* LLVM_VERSION_MAJOR > 11 */ | |
659 | diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list | |
660 | index bbe62ab90b..a49e779fcf 100644 | |
661 | --- a/src/tools/pgindent/typedefs.list | |
662 | +++ b/src/tools/pgindent/typedefs.list | |
663 | @@ -1133,6 +1133,7 @@ LLVMJitHandle | |
664 | LLVMMemoryBufferRef | |
665 | LLVMModuleRef | |
666 | LLVMOrcJITStackRef | |
667 | +LLVMOrcLookupStateRef | |
668 | LLVMOrcModuleHandle | |
669 | LLVMOrcTargetAddress | |
670 | LLVMPassManagerBuilderRef | |
671 | -- | |
672 | 2.29.2 | |
673 |