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-2024, 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 l_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  */
38 static inline LLVMTypeRef
39 l_ptr(LLVMTypeRef t)
40 {
41  return LLVMPointerType(t, 0);
42 }
43 
44 /*
45  * Emit constant integer.
46  */
47 static inline LLVMValueRef
48 l_int8_const(LLVMContextRef lc, int8 i)
49 {
50  return LLVMConstInt(LLVMInt8TypeInContext(lc), i, false);
51 }
52 
53 /*
54  * Emit constant integer.
55  */
56 static inline LLVMValueRef
57 l_int16_const(LLVMContextRef lc, int16 i)
58 {
59  return LLVMConstInt(LLVMInt16TypeInContext(lc), i, false);
60 }
61 
62 /*
63  * Emit constant integer.
64  */
65 static inline LLVMValueRef
66 l_int32_const(LLVMContextRef lc, int32 i)
67 {
68  return LLVMConstInt(LLVMInt32TypeInContext(lc), i, false);
69 }
70 
71 /*
72  * Emit constant integer.
73  */
74 static inline LLVMValueRef
75 l_int64_const(LLVMContextRef lc, int64 i)
76 {
77  return LLVMConstInt(LLVMInt64TypeInContext(lc), i, false);
78 }
79 
80 /*
81  * Emit constant integer.
82  */
83 static inline LLVMValueRef
84 l_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  */
92 static inline LLVMValueRef
93 l_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  */
101 static inline LLVMValueRef
102 l_pbool_const(bool i)
103 {
104  return LLVMConstInt(TypeParamBool, (int) i, false);
105 }
106 
107 static inline LLVMValueRef
108 l_struct_gep(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, int32 idx, const char *name)
109 {
110  return LLVMBuildStructGEP2(b, t, v, idx, "");
111 }
112 
113 static inline LLVMValueRef
114 l_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 
119 static inline LLVMValueRef
120 l_load(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, const char *name)
121 {
122  return LLVMBuildLoad2(b, t, v, name);
123 }
124 
125 static inline LLVMValueRef
126 l_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  */
134 static inline LLVMValueRef
135 l_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  */
146 static inline LLVMValueRef
147 l_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 */
153 static 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  */
159 static inline LLVMBasicBlockRef
160 l_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 */
176 static 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  */
182 static inline LLVMBasicBlockRef
183 l_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  */
201 static inline void
202 l_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  */
218 static inline void
219 l_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  */
234 static inline LLVMValueRef
235 l_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  */
252 static inline LLVMValueRef
253 l_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  */
278 static inline LLVMValueRef
279 l_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  */
304 static inline LLVMValueRef
305 l_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  */
313 static inline LLVMValueRef
314 l_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:259
signed char int8
Definition: c.h:494
signed short int16
Definition: c.h:495
signed int int32
Definition: c.h:496
#define pg_attribute_printf(f, a)
Definition: c.h:194
struct cursor * cur
Definition: ecpg.c:28
#define FIELDNO_FUNCTIONCALLINFODATA_ARGS
Definition: fmgr.h:94
int b
Definition: isn.c:70
int i
Definition: isn.c:73
static void const char * fmt
va_end(args)
va_start(args, fmt)
LLVMTypeRef StructFunctionCallInfoData
Definition: llvmjit.c:68
LLVMTypeRef TypeParamBool
Definition: llvmjit.c:56
LLVMTypeRef StructMemoryContextData
Definition: llvmjit.c:67
LLVMTypeRef TypeSizeT
Definition: llvmjit.c:55
LLVMTypeRef TypeStorageBool
Definition: llvmjit.c:57
LLVMTypeRef StructNullableDatum
Definition: llvmjit.c:59
static char * buf
Definition: pg_test_fsync.c:73
#define vsnprintf
Definition: port.h:237
#define FIELDNO_NULLABLE_DATUM_ISNULL
Definition: postgres.h:76
#define FIELDNO_NULLABLE_DATUM_DATUM
Definition: postgres.h:74
char * c
static void * fn(void *arg)
Definition: thread-alloc.c:119
const char * type
const char * name