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
10 #define LLVMJIT_EMIT_H
13 * To avoid breaking cpluspluscheck, allow including the file even when 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
);
38 static inline LLVMTypeRef
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
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
, "");
113 return LLVMBuildStructGEP2(b
, t
, v
, idx
, "");
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
);
123 return LLVMBuildGEP2(b
, t
, v
, indices
, nindices
, name
);
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
);
133 return LLVMBuildLoad2(b
, t
, v
, name
);
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
);
143 return LLVMBuildCall2(b
, t
, fn
, args
, nargs
, name
);
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
)
154 LLVMStructGetTypeAtIndex(t
, idx
),
155 l_struct_gep(b
, t
, v
, idx
, ""),
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
175 static inline LLVMBasicBlockRef
176 l_bb_before_v(LLVMBasicBlockRef r
, const char *fmt
,...)
183 vsnprintf(buf
, sizeof(buf
), fmt
, 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
,...)
206 vsnprintf(buf
, sizeof(buf
), fmt
, args
);
209 lc
= LLVMGetTypeContext(LLVMTypeOf(f
));
211 return LLVMAppendBasicBlockInContext(lc
, f
, buf
);
215 * Mark a callsite as readonly.
218 l_callsite_ro(LLVMValueRef f
)
220 const char argname
[] = "readonly";
221 LLVMAttributeRef ref
;
223 ref
= LLVMCreateStringAttribute(LLVMGetTypeContext(LLVMTypeOf(f
)),
228 LLVMAddCallSiteAttribute(f
, LLVMAttributeFunctionIndex
, ref
);
232 * Mark a callsite as alwaysinline.
235 l_callsite_alwaysinline(LLVMValueRef f
)
237 const char argname
[] = "alwaysinline";
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";
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
);
266 * Return pointer to the argno'th argument nullness.
268 static inline LLVMValueRef
269 l_funcnullp(LLVMBuilderRef b
, LLVMValueRef v_fcinfo
, size_t argno
)
274 v_args
= l_struct_gep(b
,
275 StructFunctionCallInfoData
,
277 FIELDNO_FUNCTIONCALLINFODATA_ARGS
,
279 v_argn
= l_struct_gep(b
,
280 LLVMArrayType(StructNullableDatum
, 0),
284 return l_struct_gep(b
,
287 FIELDNO_NULLABLE_DATUM_ISNULL
,
292 * Return pointer to the argno'th argument datum.
294 static inline LLVMValueRef
295 l_funcvaluep(LLVMBuilderRef b
, LLVMValueRef v_fcinfo
, size_t argno
)
300 v_args
= l_struct_gep(b
,
301 StructFunctionCallInfoData
,
303 FIELDNO_FUNCTIONCALLINFODATA_ARGS
,
305 v_argn
= l_struct_gep(b
,
306 LLVMArrayType(StructNullableDatum
, 0),
310 return l_struct_gep(b
,
313 FIELDNO_NULLABLE_DATUM_DATUM
,
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 */