Line data Source code
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 : */
27 : static inline LLVMValueRef
28 129976 : l_ptr_const(void *ptr, LLVMTypeRef type)
29 : {
30 129976 : LLVMValueRef c = LLVMConstInt(TypeSizeT, (uintptr_t) ptr, false);
31 :
32 129976 : return LLVMConstIntToPtr(c, type);
33 : }
34 :
35 : /*
36 : * Emit pointer.
37 : */
38 : static inline LLVMTypeRef
39 159874 : l_ptr(LLVMTypeRef t)
40 : {
41 159874 : return LLVMPointerType(t, 0);
42 : }
43 :
44 : /*
45 : * Emit constant integer.
46 : */
47 : static inline LLVMValueRef
48 45968 : l_int8_const(LLVMContextRef lc, int8 i)
49 : {
50 45968 : return LLVMConstInt(LLVMInt8TypeInContext(lc), i, false);
51 : }
52 :
53 : /*
54 : * Emit constant integer.
55 : */
56 : static inline LLVMValueRef
57 65542 : l_int16_const(LLVMContextRef lc, int16 i)
58 : {
59 65542 : return LLVMConstInt(LLVMInt16TypeInContext(lc), i, false);
60 : }
61 :
62 : /*
63 : * Emit constant integer.
64 : */
65 : static inline LLVMValueRef
66 44932 : l_int32_const(LLVMContextRef lc, int32 i)
67 : {
68 44932 : return LLVMConstInt(LLVMInt32TypeInContext(lc), i, false);
69 : }
70 :
71 : /*
72 : * Emit constant integer.
73 : */
74 : static inline LLVMValueRef
75 12748 : l_int64_const(LLVMContextRef lc, int64 i)
76 : {
77 12748 : return LLVMConstInt(LLVMInt64TypeInContext(lc), i, false);
78 : }
79 :
80 : /*
81 : * Emit constant integer.
82 : */
83 : static inline LLVMValueRef
84 30638 : l_sizet_const(size_t i)
85 : {
86 30638 : return LLVMConstInt(TypeSizeT, i, false);
87 : }
88 :
89 : /*
90 : * Emit constant integer.
91 : */
92 : static inline LLVMValueRef
93 26852 : l_datum_const(Datum i)
94 : {
95 26852 : return LLVMConstInt(TypeDatum, i, false);
96 : }
97 :
98 : /*
99 : * Emit constant boolean, as used for storage (e.g. global vars, structs).
100 : */
101 : static inline LLVMValueRef
102 32346 : l_sbool_const(bool i)
103 : {
104 32346 : return LLVMConstInt(TypeStorageBool, (int) i, false);
105 : }
106 :
107 : /*
108 : * Emit constant boolean, as used for parameters (e.g. function parameters).
109 : */
110 : static inline LLVMValueRef
111 : l_pbool_const(bool i)
112 : {
113 : return LLVMConstInt(TypeParamBool, (int) i, false);
114 : }
115 :
116 : static inline LLVMValueRef
117 328152 : l_struct_gep(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, int32 idx, const char *name)
118 : {
119 328152 : return LLVMBuildStructGEP2(b, t, v, idx, "");
120 : }
121 :
122 : static inline LLVMValueRef
123 127088 : l_gep(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, LLVMValueRef *indices, int32 nindices, const char *name)
124 : {
125 127088 : return LLVMBuildGEP2(b, t, v, indices, nindices, name);
126 : }
127 :
128 : static inline LLVMValueRef
129 388798 : l_load(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, const char *name)
130 : {
131 388798 : return LLVMBuildLoad2(b, t, v, name);
132 : }
133 :
134 : static inline LLVMValueRef
135 37626 : l_call(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef fn, LLVMValueRef *args, int32 nargs, const char *name)
136 : {
137 37626 : return LLVMBuildCall2(b, t, fn, args, nargs, name);
138 : }
139 :
140 : /*
141 : * Load a pointer member idx from a struct.
142 : */
143 : static inline LLVMValueRef
144 241208 : l_load_struct_gep(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, int32 idx, const char *name)
145 : {
146 241208 : return l_load(b,
147 : LLVMStructGetTypeAtIndex(t, idx),
148 : l_struct_gep(b, t, v, idx, ""),
149 : name);
150 : }
151 :
152 : /*
153 : * Load value of a pointer, after applying one index operation.
154 : */
155 : static inline LLVMValueRef
156 43014 : l_load_gep1(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, LLVMValueRef idx, const char *name)
157 : {
158 43014 : return l_load(b, t, l_gep(b, t, v, &idx, 1, ""), name);
159 : }
160 :
161 : /* separate, because pg_attribute_printf(2, 3) can't appear in definition */
162 : static inline LLVMBasicBlockRef l_bb_before_v(LLVMBasicBlockRef r, const char *fmt,...) pg_attribute_printf(2, 3);
163 :
164 : /*
165 : * Insert a new basic block, just before r, the name being determined by fmt
166 : * and arguments.
167 : */
168 : static inline LLVMBasicBlockRef
169 29410 : l_bb_before_v(LLVMBasicBlockRef r, const char *fmt,...)
170 : {
171 : char buf[512];
172 : va_list args;
173 : LLVMContextRef lc;
174 :
175 29410 : va_start(args, fmt);
176 29410 : vsnprintf(buf, sizeof(buf), fmt, args);
177 29410 : va_end(args);
178 :
179 29410 : lc = LLVMGetTypeContext(LLVMTypeOf(LLVMGetBasicBlockParent(r)));
180 :
181 29410 : return LLVMInsertBasicBlockInContext(lc, r, buf);
182 : }
183 :
184 : /* separate, because pg_attribute_printf(2, 3) can't appear in definition */
185 : static inline LLVMBasicBlockRef l_bb_append_v(LLVMValueRef f, const char *fmt,...) pg_attribute_printf(2, 3);
186 :
187 : /*
188 : * Insert a new basic block after previous basic blocks, the name being
189 : * determined by fmt and arguments.
190 : */
191 : static inline LLVMBasicBlockRef
192 123206 : l_bb_append_v(LLVMValueRef f, const char *fmt,...)
193 : {
194 : char buf[512];
195 : va_list args;
196 : LLVMContextRef lc;
197 :
198 123206 : va_start(args, fmt);
199 123206 : vsnprintf(buf, sizeof(buf), fmt, args);
200 123206 : va_end(args);
201 :
202 123206 : lc = LLVMGetTypeContext(LLVMTypeOf(f));
203 :
204 123206 : return LLVMAppendBasicBlockInContext(lc, f, buf);
205 : }
206 :
207 : /*
208 : * Mark a callsite as readonly.
209 : */
210 : static inline void
211 1164 : l_callsite_ro(LLVMValueRef f)
212 : {
213 1164 : const char argname[] = "readonly";
214 : LLVMAttributeRef ref;
215 :
216 1164 : ref = LLVMCreateStringAttribute(LLVMGetTypeContext(LLVMTypeOf(f)),
217 : argname,
218 : sizeof(argname) - 1,
219 : NULL, 0);
220 :
221 1164 : LLVMAddCallSiteAttribute(f, LLVMAttributeFunctionIndex, ref);
222 1164 : }
223 :
224 : /*
225 : * Mark a callsite as alwaysinline.
226 : */
227 : static inline void
228 1164 : l_callsite_alwaysinline(LLVMValueRef f)
229 : {
230 1164 : const char argname[] = "alwaysinline";
231 : int id;
232 : LLVMAttributeRef attr;
233 :
234 1164 : id = LLVMGetEnumAttributeKindForName(argname,
235 : sizeof(argname) - 1);
236 1164 : attr = LLVMCreateEnumAttribute(LLVMGetTypeContext(LLVMTypeOf(f)), id, 0);
237 1164 : LLVMAddCallSiteAttribute(f, LLVMAttributeFunctionIndex, attr);
238 1164 : }
239 :
240 : /*
241 : * Emit code to switch memory context.
242 : */
243 : static inline LLVMValueRef
244 2678 : l_mcxt_switch(LLVMModuleRef mod, LLVMBuilderRef b, LLVMValueRef nc)
245 : {
246 2678 : const char *cmc = "CurrentMemoryContext";
247 : LLVMValueRef cur;
248 : LLVMValueRef ret;
249 :
250 2678 : if (!(cur = LLVMGetNamedGlobal(mod, cmc)))
251 298 : cur = LLVMAddGlobal(mod, l_ptr(StructMemoryContextData), cmc);
252 2678 : ret = l_load(b, l_ptr(StructMemoryContextData), cur, cmc);
253 2678 : LLVMBuildStore(b, nc, cur);
254 :
255 2678 : return ret;
256 : }
257 :
258 : /*
259 : * Return pointer to the argno'th argument nullness.
260 : */
261 : static inline LLVMValueRef
262 9710 : l_funcnullp(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
263 : {
264 : LLVMValueRef v_args;
265 : LLVMValueRef v_argn;
266 :
267 9710 : v_args = l_struct_gep(b,
268 : StructFunctionCallInfoData,
269 : v_fcinfo,
270 : FIELDNO_FUNCTIONCALLINFODATA_ARGS,
271 : "");
272 9710 : v_argn = l_struct_gep(b,
273 : LLVMArrayType(StructNullableDatum, 0),
274 : v_args,
275 : argno,
276 : "");
277 9710 : return l_struct_gep(b,
278 : StructNullableDatum,
279 : v_argn,
280 : FIELDNO_NULLABLE_DATUM_ISNULL,
281 : "");
282 : }
283 :
284 : /*
285 : * Return pointer to the argno'th argument datum.
286 : */
287 : static inline LLVMValueRef
288 1390 : l_funcvaluep(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
289 : {
290 : LLVMValueRef v_args;
291 : LLVMValueRef v_argn;
292 :
293 1390 : v_args = l_struct_gep(b,
294 : StructFunctionCallInfoData,
295 : v_fcinfo,
296 : FIELDNO_FUNCTIONCALLINFODATA_ARGS,
297 : "");
298 1390 : v_argn = l_struct_gep(b,
299 : LLVMArrayType(StructNullableDatum, 0),
300 : v_args,
301 : argno,
302 : "");
303 1390 : return l_struct_gep(b,
304 : StructNullableDatum,
305 : v_argn,
306 : FIELDNO_NULLABLE_DATUM_DATUM,
307 : "");
308 : }
309 :
310 : /*
311 : * Return argno'th argument nullness.
312 : */
313 : static inline LLVMValueRef
314 8320 : l_funcnull(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
315 : {
316 8320 : return l_load(b, TypeStorageBool, l_funcnullp(b, v_fcinfo, argno), "");
317 : }
318 :
319 : /*
320 : * Return argno'th argument datum.
321 : */
322 : static inline LLVMValueRef
323 0 : l_funcvalue(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
324 : {
325 0 : return l_load(b, TypeDatum, l_funcvaluep(b, v_fcinfo, argno), "");
326 : }
327 :
328 : #endif /* USE_LLVM */
329 : #endif
|