PostgreSQL Source Code git master
llvmjit_emit.h
Go to the documentation of this file.
1/*
2 * llvmjit_emit.h
3 * Helpers to make emitting LLVM IR a bit more concise and pgindent proof.
4 *
5 * Copyright (c) 2018-2025, PostgreSQL Global Development Group
6 *
7 * src/include/jit/llvmjit_emit.h
8 */
9#ifndef LLVMJIT_EMIT_H
10#define LLVMJIT_EMIT_H
11
12/*
13 * To avoid breaking cpluspluscheck, allow including the file even when LLVM
14 * is not available.
15 */
16#ifdef USE_LLVM
17
18#include <llvm-c/Core.h>
19#include <llvm-c/Target.h>
20
21#include "jit/llvmjit.h"
22
23
24/*
25 * Emit a non-LLVM pointer as an LLVM constant.
26 */
27static inline LLVMValueRef
28l_ptr_const(void *ptr, LLVMTypeRef type)
29{
30 LLVMValueRef c = LLVMConstInt(TypeSizeT, (uintptr_t) ptr, false);
31
32 return LLVMConstIntToPtr(c, type);
33}
34
35/*
36 * Emit pointer.
37 */
38static inline LLVMTypeRef
39l_ptr(LLVMTypeRef t)
40{
41 return LLVMPointerType(t, 0);
42}
43
44/*
45 * Emit constant integer.
46 */
47static inline LLVMValueRef
48l_int8_const(LLVMContextRef lc, int8 i)
49{
50 return LLVMConstInt(LLVMInt8TypeInContext(lc), i, false);
51}
52
53/*
54 * Emit constant integer.
55 */
56static inline LLVMValueRef
57l_int16_const(LLVMContextRef lc, int16 i)
58{
59 return LLVMConstInt(LLVMInt16TypeInContext(lc), i, false);
60}
61
62/*
63 * Emit constant integer.
64 */
65static inline LLVMValueRef
66l_int32_const(LLVMContextRef lc, int32 i)
67{
68 return LLVMConstInt(LLVMInt32TypeInContext(lc), i, false);
69}
70
71/*
72 * Emit constant integer.
73 */
74static inline LLVMValueRef
75l_int64_const(LLVMContextRef lc, int64 i)
76{
77 return LLVMConstInt(LLVMInt64TypeInContext(lc), i, false);
78}
79
80/*
81 * Emit constant integer.
82 */
83static inline LLVMValueRef
84l_sizet_const(size_t i)
85{
86 return LLVMConstInt(TypeSizeT, i, false);
87}
88
89/*
90 * Emit constant boolean, as used for storage (e.g. global vars, structs).
91 */
92static inline LLVMValueRef
93l_sbool_const(bool i)
94{
95 return LLVMConstInt(TypeStorageBool, (int) i, false);
96}
97
98/*
99 * Emit constant boolean, as used for parameters (e.g. function parameters).
100 */
101static inline LLVMValueRef
102l_pbool_const(bool i)
103{
104 return LLVMConstInt(TypeParamBool, (int) i, false);
105}
106
107static inline LLVMValueRef
108l_struct_gep(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, int32 idx, const char *name)
109{
110 return LLVMBuildStructGEP2(b, t, v, idx, "");
111}
112
113static inline LLVMValueRef
114l_gep(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, LLVMValueRef *indices, int32 nindices, const char *name)
115{
116 return LLVMBuildGEP2(b, t, v, indices, nindices, name);
117}
118
119static inline LLVMValueRef
120l_load(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, const char *name)
121{
122 return LLVMBuildLoad2(b, t, v, name);
123}
124
125static inline LLVMValueRef
126l_call(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef fn, LLVMValueRef *args, int32 nargs, const char *name)
127{
128 return LLVMBuildCall2(b, t, fn, args, nargs, name);
129}
130
131/*
132 * Load a pointer member idx from a struct.
133 */
134static inline LLVMValueRef
135l_load_struct_gep(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, int32 idx, const char *name)
136{
137 return l_load(b,
138 LLVMStructGetTypeAtIndex(t, idx),
139 l_struct_gep(b, t, v, idx, ""),
140 name);
141}
142
143/*
144 * Load value of a pointer, after applying one index operation.
145 */
146static inline LLVMValueRef
147l_load_gep1(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, LLVMValueRef idx, const char *name)
148{
149 return l_load(b, t, l_gep(b, t, v, &idx, 1, ""), name);
150}
151
152/* separate, because pg_attribute_printf(2, 3) can't appear in definition */
153static inline LLVMBasicBlockRef l_bb_before_v(LLVMBasicBlockRef r, const char *fmt,...) pg_attribute_printf(2, 3);
154
155/*
156 * Insert a new basic block, just before r, the name being determined by fmt
157 * and arguments.
158 */
159static inline LLVMBasicBlockRef
160l_bb_before_v(LLVMBasicBlockRef r, const char *fmt,...)
161{
162 char buf[512];
163 va_list args;
164 LLVMContextRef lc;
165
166 va_start(args, fmt);
167 vsnprintf(buf, sizeof(buf), fmt, args);
168 va_end(args);
169
170 lc = LLVMGetTypeContext(LLVMTypeOf(LLVMGetBasicBlockParent(r)));
171
172 return LLVMInsertBasicBlockInContext(lc, r, buf);
173}
174
175/* separate, because pg_attribute_printf(2, 3) can't appear in definition */
176static inline LLVMBasicBlockRef l_bb_append_v(LLVMValueRef f, const char *fmt,...) pg_attribute_printf(2, 3);
177
178/*
179 * Insert a new basic block after previous basic blocks, the name being
180 * determined by fmt and arguments.
181 */
182static inline LLVMBasicBlockRef
183l_bb_append_v(LLVMValueRef f, const char *fmt,...)
184{
185 char buf[512];
186 va_list args;
187 LLVMContextRef lc;
188
189 va_start(args, fmt);
190 vsnprintf(buf, sizeof(buf), fmt, args);
191 va_end(args);
192
193 lc = LLVMGetTypeContext(LLVMTypeOf(f));
194
195 return LLVMAppendBasicBlockInContext(lc, f, buf);
196}
197
198/*
199 * Mark a callsite as readonly.
200 */
201static inline void
202l_callsite_ro(LLVMValueRef f)
203{
204 const char argname[] = "readonly";
205 LLVMAttributeRef ref;
206
207 ref = LLVMCreateStringAttribute(LLVMGetTypeContext(LLVMTypeOf(f)),
208 argname,
209 sizeof(argname) - 1,
210 NULL, 0);
211
212 LLVMAddCallSiteAttribute(f, LLVMAttributeFunctionIndex, ref);
213}
214
215/*
216 * Mark a callsite as alwaysinline.
217 */
218static inline void
219l_callsite_alwaysinline(LLVMValueRef f)
220{
221 const char argname[] = "alwaysinline";
222 int id;
223 LLVMAttributeRef attr;
224
225 id = LLVMGetEnumAttributeKindForName(argname,
226 sizeof(argname) - 1);
227 attr = LLVMCreateEnumAttribute(LLVMGetTypeContext(LLVMTypeOf(f)), id, 0);
228 LLVMAddCallSiteAttribute(f, LLVMAttributeFunctionIndex, attr);
229}
230
231/*
232 * Emit code to switch memory context.
233 */
234static inline LLVMValueRef
235l_mcxt_switch(LLVMModuleRef mod, LLVMBuilderRef b, LLVMValueRef nc)
236{
237 const char *cmc = "CurrentMemoryContext";
238 LLVMValueRef cur;
239 LLVMValueRef ret;
240
241 if (!(cur = LLVMGetNamedGlobal(mod, cmc)))
242 cur = LLVMAddGlobal(mod, l_ptr(StructMemoryContextData), cmc);
243 ret = l_load(b, l_ptr(StructMemoryContextData), cur, cmc);
244 LLVMBuildStore(b, nc, cur);
245
246 return ret;
247}
248
249/*
250 * Return pointer to the argno'th argument nullness.
251 */
252static inline LLVMValueRef
253l_funcnullp(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
254{
255 LLVMValueRef v_args;
256 LLVMValueRef v_argn;
257
258 v_args = l_struct_gep(b,
260 v_fcinfo,
262 "");
263 v_argn = l_struct_gep(b,
264 LLVMArrayType(StructNullableDatum, 0),
265 v_args,
266 argno,
267 "");
268 return l_struct_gep(b,
270 v_argn,
272 "");
273}
274
275/*
276 * Return pointer to the argno'th argument datum.
277 */
278static inline LLVMValueRef
279l_funcvaluep(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
280{
281 LLVMValueRef v_args;
282 LLVMValueRef v_argn;
283
284 v_args = l_struct_gep(b,
286 v_fcinfo,
288 "");
289 v_argn = l_struct_gep(b,
290 LLVMArrayType(StructNullableDatum, 0),
291 v_args,
292 argno,
293 "");
294 return l_struct_gep(b,
296 v_argn,
298 "");
299}
300
301/*
302 * Return argno'th argument nullness.
303 */
304static inline LLVMValueRef
305l_funcnull(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
306{
307 return l_load(b, TypeStorageBool, l_funcnullp(b, v_fcinfo, argno), "");
308}
309
310/*
311 * Return argno'th argument datum.
312 */
313static inline LLVMValueRef
314l_funcvalue(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
315{
316 return l_load(b, TypeSizeT, l_funcvaluep(b, v_fcinfo, argno), "");
317}
318
319#endif /* USE_LLVM */
320#endif
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:262
int64_t int64
Definition: c.h:499
#define pg_attribute_printf(f, a)
Definition: c.h:233
int16_t int16
Definition: c.h:497
int8_t int8
Definition: c.h:496
int32_t int32
Definition: c.h:498
struct cursor * cur
Definition: ecpg.c:29
#define FIELDNO_FUNCTIONCALLINFODATA_ARGS
Definition: fmgr.h:94
int b
Definition: isn.c:74
int i
Definition: isn.c:77
LLVMTypeRef StructFunctionCallInfoData
Definition: llvmjit.c:69
LLVMTypeRef TypeParamBool
Definition: llvmjit.c:57
LLVMTypeRef StructMemoryContextData
Definition: llvmjit.c:68
LLVMTypeRef TypeSizeT
Definition: llvmjit.c:56
LLVMTypeRef TypeStorageBool
Definition: llvmjit.c:58
LLVMTypeRef StructNullableDatum
Definition: llvmjit.c:60
static char * buf
Definition: pg_test_fsync.c:72
#define vsnprintf
Definition: port.h:238
#define FIELDNO_NULLABLE_DATUM_ISNULL
Definition: postgres.h:81
#define FIELDNO_NULLABLE_DATUM_DATUM
Definition: postgres.h:79
char * c
static void * fn(void *arg)
Definition: thread-alloc.c:119
const char * type
const char * name