Rework lwlocknames.txt to become lwlocklist.h
[pgsql.git] / src / include / jit / llvmjit_emit.h
blob4f35f3dca139fad1e51e4bd3af294d6d3ec5ea45
1 /*
2 * llvmjit_emit.h
3 * Helpers to make emitting LLVM IR a bit more concise and pgindent proof.
5 * Copyright (c) 2018-2024, PostgreSQL Global Development Group
7 * src/include/jit/llvmjit_emit.h
8 */
9 #ifndef LLVMJIT_EMIT_H
10 #define LLVMJIT_EMIT_H
13 * To avoid breaking cpluspluscheck, allow including the file even when LLVM
14 * is not available.
16 #ifdef USE_LLVM
18 #include <llvm-c/Core.h>
19 #include <llvm-c/Target.h>
21 #include "jit/llvmjit.h"
25 * Emit a non-LLVM pointer as an LLVM constant.
27 static inline LLVMValueRef
28 l_ptr_const(void *ptr, LLVMTypeRef type)
30 LLVMValueRef c = LLVMConstInt(TypeSizeT, (uintptr_t) ptr, false);
32 return LLVMConstIntToPtr(c, type);
36 * Emit pointer.
38 static inline LLVMTypeRef
39 l_ptr(LLVMTypeRef t)
41 return LLVMPointerType(t, 0);
45 * Emit constant integer.
47 static inline LLVMValueRef
48 l_int8_const(LLVMContextRef lc, int8 i)
50 return LLVMConstInt(LLVMInt8TypeInContext(lc), i, false);
54 * Emit constant integer.
56 static inline LLVMValueRef
57 l_int16_const(LLVMContextRef lc, int16 i)
59 return LLVMConstInt(LLVMInt16TypeInContext(lc), i, false);
63 * Emit constant integer.
65 static inline LLVMValueRef
66 l_int32_const(LLVMContextRef lc, int32 i)
68 return LLVMConstInt(LLVMInt32TypeInContext(lc), i, false);
72 * Emit constant integer.
74 static inline LLVMValueRef
75 l_int64_const(LLVMContextRef lc, int64 i)
77 return LLVMConstInt(LLVMInt64TypeInContext(lc), i, false);
81 * Emit constant integer.
83 static inline LLVMValueRef
84 l_sizet_const(size_t i)
86 return LLVMConstInt(TypeSizeT, i, false);
90 * Emit constant boolean, as used for storage (e.g. global vars, structs).
92 static inline LLVMValueRef
93 l_sbool_const(bool i)
95 return LLVMConstInt(TypeStorageBool, (int) i, false);
99 * Emit constant boolean, as used for parameters (e.g. function parameters).
101 static inline LLVMValueRef
102 l_pbool_const(bool i)
104 return LLVMConstInt(TypeParamBool, (int) i, false);
107 static inline LLVMValueRef
108 l_struct_gep(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, int32 idx, const char *name)
110 #if LLVM_VERSION_MAJOR < 16
111 return LLVMBuildStructGEP(b, v, idx, "");
112 #else
113 return LLVMBuildStructGEP2(b, t, v, idx, "");
114 #endif
117 static inline LLVMValueRef
118 l_gep(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, LLVMValueRef *indices, int32 nindices, const char *name)
120 #if LLVM_VERSION_MAJOR < 16
121 return LLVMBuildGEP(b, v, indices, nindices, name);
122 #else
123 return LLVMBuildGEP2(b, t, v, indices, nindices, name);
124 #endif
127 static inline LLVMValueRef
128 l_load(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, const char *name)
130 #if LLVM_VERSION_MAJOR < 16
131 return LLVMBuildLoad(b, v, name);
132 #else
133 return LLVMBuildLoad2(b, t, v, name);
134 #endif
137 static inline LLVMValueRef
138 l_call(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef fn, LLVMValueRef *args, int32 nargs, const char *name)
140 #if LLVM_VERSION_MAJOR < 16
141 return LLVMBuildCall(b, fn, args, nargs, name);
142 #else
143 return LLVMBuildCall2(b, t, fn, args, nargs, name);
144 #endif
148 * Load a pointer member idx from a struct.
150 static inline LLVMValueRef
151 l_load_struct_gep(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, int32 idx, const char *name)
153 return l_load(b,
154 LLVMStructGetTypeAtIndex(t, idx),
155 l_struct_gep(b, t, v, idx, ""),
156 name);
160 * Load value of a pointer, after applying one index operation.
162 static inline LLVMValueRef
163 l_load_gep1(LLVMBuilderRef b, LLVMTypeRef t, LLVMValueRef v, LLVMValueRef idx, const char *name)
165 return l_load(b, t, l_gep(b, t, v, &idx, 1, ""), name);
168 /* separate, because pg_attribute_printf(2, 3) can't appear in definition */
169 static inline LLVMBasicBlockRef l_bb_before_v(LLVMBasicBlockRef r, const char *fmt,...) pg_attribute_printf(2, 3);
172 * Insert a new basic block, just before r, the name being determined by fmt
173 * and arguments.
175 static inline LLVMBasicBlockRef
176 l_bb_before_v(LLVMBasicBlockRef r, const char *fmt,...)
178 char buf[512];
179 va_list args;
180 LLVMContextRef lc;
182 va_start(args, fmt);
183 vsnprintf(buf, sizeof(buf), fmt, args);
184 va_end(args);
186 lc = LLVMGetTypeContext(LLVMTypeOf(LLVMGetBasicBlockParent(r)));
188 return LLVMInsertBasicBlockInContext(lc, r, buf);
191 /* separate, because pg_attribute_printf(2, 3) can't appear in definition */
192 static inline LLVMBasicBlockRef l_bb_append_v(LLVMValueRef f, const char *fmt,...) pg_attribute_printf(2, 3);
195 * Insert a new basic block after previous basic blocks, the name being
196 * determined by fmt and arguments.
198 static inline LLVMBasicBlockRef
199 l_bb_append_v(LLVMValueRef f, const char *fmt,...)
201 char buf[512];
202 va_list args;
203 LLVMContextRef lc;
205 va_start(args, fmt);
206 vsnprintf(buf, sizeof(buf), fmt, args);
207 va_end(args);
209 lc = LLVMGetTypeContext(LLVMTypeOf(f));
211 return LLVMAppendBasicBlockInContext(lc, f, buf);
215 * Mark a callsite as readonly.
217 static inline void
218 l_callsite_ro(LLVMValueRef f)
220 const char argname[] = "readonly";
221 LLVMAttributeRef ref;
223 ref = LLVMCreateStringAttribute(LLVMGetTypeContext(LLVMTypeOf(f)),
224 argname,
225 sizeof(argname) - 1,
226 NULL, 0);
228 LLVMAddCallSiteAttribute(f, LLVMAttributeFunctionIndex, ref);
232 * Mark a callsite as alwaysinline.
234 static inline void
235 l_callsite_alwaysinline(LLVMValueRef f)
237 const char argname[] = "alwaysinline";
238 int id;
239 LLVMAttributeRef attr;
241 id = LLVMGetEnumAttributeKindForName(argname,
242 sizeof(argname) - 1);
243 attr = LLVMCreateEnumAttribute(LLVMGetTypeContext(LLVMTypeOf(f)), id, 0);
244 LLVMAddCallSiteAttribute(f, LLVMAttributeFunctionIndex, attr);
248 * Emit code to switch memory context.
250 static inline LLVMValueRef
251 l_mcxt_switch(LLVMModuleRef mod, LLVMBuilderRef b, LLVMValueRef nc)
253 const char *cmc = "CurrentMemoryContext";
254 LLVMValueRef cur;
255 LLVMValueRef ret;
257 if (!(cur = LLVMGetNamedGlobal(mod, cmc)))
258 cur = LLVMAddGlobal(mod, l_ptr(StructMemoryContextData), cmc);
259 ret = l_load(b, l_ptr(StructMemoryContextData), cur, cmc);
260 LLVMBuildStore(b, nc, cur);
262 return ret;
266 * Return pointer to the argno'th argument nullness.
268 static inline LLVMValueRef
269 l_funcnullp(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
271 LLVMValueRef v_args;
272 LLVMValueRef v_argn;
274 v_args = l_struct_gep(b,
275 StructFunctionCallInfoData,
276 v_fcinfo,
277 FIELDNO_FUNCTIONCALLINFODATA_ARGS,
278 "");
279 v_argn = l_struct_gep(b,
280 LLVMArrayType(StructNullableDatum, 0),
281 v_args,
282 argno,
283 "");
284 return l_struct_gep(b,
285 StructNullableDatum,
286 v_argn,
287 FIELDNO_NULLABLE_DATUM_ISNULL,
288 "");
292 * Return pointer to the argno'th argument datum.
294 static inline LLVMValueRef
295 l_funcvaluep(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
297 LLVMValueRef v_args;
298 LLVMValueRef v_argn;
300 v_args = l_struct_gep(b,
301 StructFunctionCallInfoData,
302 v_fcinfo,
303 FIELDNO_FUNCTIONCALLINFODATA_ARGS,
304 "");
305 v_argn = l_struct_gep(b,
306 LLVMArrayType(StructNullableDatum, 0),
307 v_args,
308 argno,
309 "");
310 return l_struct_gep(b,
311 StructNullableDatum,
312 v_argn,
313 FIELDNO_NULLABLE_DATUM_DATUM,
314 "");
318 * Return argno'th argument nullness.
320 static inline LLVMValueRef
321 l_funcnull(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
323 return l_load(b, TypeStorageBool, l_funcnullp(b, v_fcinfo, argno), "");
327 * Return argno'th argument datum.
329 static inline LLVMValueRef
330 l_funcvalue(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
332 return l_load(b, TypeSizeT, l_funcvaluep(b, v_fcinfo, argno), "");
335 #endif /* USE_LLVM */
336 #endif