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-2023, 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 
20 #include "jit/llvmjit.h"
21 
22 
23 /*
24  * Emit a non-LLVM pointer as an LLVM constant.
25  */
26 static inline LLVMValueRef
27 l_ptr_const(void *ptr, LLVMTypeRef type)
28 {
29  LLVMValueRef c = LLVMConstInt(TypeSizeT, (uintptr_t) ptr, false);
30 
31  return LLVMConstIntToPtr(c, type);
32 }
33 
34 /*
35  * Emit pointer.
36  */
37 static inline LLVMTypeRef
38 l_ptr(LLVMTypeRef t)
39 {
40  return LLVMPointerType(t, 0);
41 }
42 
43 /*
44  * Emit constant integer.
45  */
46 static inline LLVMValueRef
47 l_int8_const(int8 i)
48 {
49  return LLVMConstInt(LLVMInt8Type(), i, false);
50 }
51 
52 /*
53  * Emit constant integer.
54  */
55 static inline LLVMValueRef
56 l_int16_const(int16 i)
57 {
58  return LLVMConstInt(LLVMInt16Type(), i, false);
59 }
60 
61 /*
62  * Emit constant integer.
63  */
64 static inline LLVMValueRef
65 l_int32_const(int32 i)
66 {
67  return LLVMConstInt(LLVMInt32Type(), i, false);
68 }
69 
70 /*
71  * Emit constant integer.
72  */
73 static inline LLVMValueRef
74 l_int64_const(int64 i)
75 {
76  return LLVMConstInt(LLVMInt64Type(), i, false);
77 }
78 
79 /*
80  * Emit constant integer.
81  */
82 static inline LLVMValueRef
83 l_sizet_const(size_t i)
84 {
85  return LLVMConstInt(TypeSizeT, i, false);
86 }
87 
88 /*
89  * Emit constant boolean, as used for storage (e.g. global vars, structs).
90  */
91 static inline LLVMValueRef
92 l_sbool_const(bool i)
93 {
94  return LLVMConstInt(TypeStorageBool, (int) i, false);
95 }
96 
97 /*
98  * Emit constant boolean, as used for parameters (e.g. function parameters).
99  */
100 static inline LLVMValueRef
101 l_pbool_const(bool i)
102 {
103  return LLVMConstInt(TypeParamBool, (int) i, false);
104 }
105 
106 /*
107  * Load a pointer member idx from a struct.
108  */
109 static inline LLVMValueRef
110 l_load_struct_gep(LLVMBuilderRef b, LLVMValueRef v, int32 idx, const char *name)
111 {
112  LLVMValueRef v_ptr = LLVMBuildStructGEP(b, v, idx, "");
113 
114  return LLVMBuildLoad(b, v_ptr, name);
115 }
116 
117 /*
118  * Load value of a pointer, after applying one index operation.
119  */
120 static inline LLVMValueRef
121 l_load_gep1(LLVMBuilderRef b, LLVMValueRef v, LLVMValueRef idx, const char *name)
122 {
123  LLVMValueRef v_ptr = LLVMBuildGEP(b, v, &idx, 1, "");
124 
125  return LLVMBuildLoad(b, v_ptr, name);
126 }
127 
128 /* separate, because pg_attribute_printf(2, 3) can't appear in definition */
129 static inline LLVMBasicBlockRef l_bb_before_v(LLVMBasicBlockRef r, const char *fmt,...) pg_attribute_printf(2, 3);
130 
131 /*
132  * Insert a new basic block, just before r, the name being determined by fmt
133  * and arguments.
134  */
135 static inline LLVMBasicBlockRef
136 l_bb_before_v(LLVMBasicBlockRef r, const char *fmt,...)
137 {
138  char buf[512];
139  va_list args;
140 
141  va_start(args, fmt);
142  vsnprintf(buf, sizeof(buf), fmt, args);
143  va_end(args);
144 
145  return LLVMInsertBasicBlock(r, buf);
146 }
147 
148 /* separate, because pg_attribute_printf(2, 3) can't appear in definition */
149 static inline LLVMBasicBlockRef l_bb_append_v(LLVMValueRef f, const char *fmt,...) pg_attribute_printf(2, 3);
150 
151 /*
152  * Insert a new basic block after previous basic blocks, the name being
153  * determined by fmt and arguments.
154  */
155 static inline LLVMBasicBlockRef
156 l_bb_append_v(LLVMValueRef f, const char *fmt,...)
157 {
158  char buf[512];
159  va_list args;
160 
161  va_start(args, fmt);
162  vsnprintf(buf, sizeof(buf), fmt, args);
163  va_end(args);
164 
165  return LLVMAppendBasicBlock(f, buf);
166 }
167 
168 /*
169  * Mark a callsite as readonly.
170  */
171 static inline void
172 l_callsite_ro(LLVMValueRef f)
173 {
174  const char argname[] = "readonly";
175  LLVMAttributeRef ref;
176 
177  ref = LLVMCreateStringAttribute(LLVMGetGlobalContext(),
178  argname,
179  sizeof(argname) - 1,
180  NULL, 0);
181 
182  LLVMAddCallSiteAttribute(f, LLVMAttributeFunctionIndex, ref);
183 }
184 
185 /*
186  * Mark a callsite as alwaysinline.
187  */
188 static inline void
189 l_callsite_alwaysinline(LLVMValueRef f)
190 {
191  const char argname[] = "alwaysinline";
192  int id;
193  LLVMAttributeRef attr;
194 
195  id = LLVMGetEnumAttributeKindForName(argname,
196  sizeof(argname) - 1);
197  attr = LLVMCreateEnumAttribute(LLVMGetGlobalContext(), id, 0);
198  LLVMAddCallSiteAttribute(f, LLVMAttributeFunctionIndex, attr);
199 }
200 
201 /*
202  * Emit code to switch memory context.
203  */
204 static inline LLVMValueRef
205 l_mcxt_switch(LLVMModuleRef mod, LLVMBuilderRef b, LLVMValueRef nc)
206 {
207  const char *cmc = "CurrentMemoryContext";
208  LLVMValueRef cur;
209  LLVMValueRef ret;
210 
211  if (!(cur = LLVMGetNamedGlobal(mod, cmc)))
212  cur = LLVMAddGlobal(mod, l_ptr(StructMemoryContextData), cmc);
213  ret = LLVMBuildLoad(b, cur, cmc);
214  LLVMBuildStore(b, nc, cur);
215 
216  return ret;
217 }
218 
219 /*
220  * Return pointer to the argno'th argument nullness.
221  */
222 static inline LLVMValueRef
223 l_funcnullp(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
224 {
225  LLVMValueRef v_args;
226  LLVMValueRef v_argn;
227 
228  v_args = LLVMBuildStructGEP(b,
229  v_fcinfo,
231  "");
232  v_argn = LLVMBuildStructGEP(b, v_args, argno, "");
233 
234  return LLVMBuildStructGEP(b, v_argn, FIELDNO_NULLABLE_DATUM_ISNULL, "");
235 }
236 
237 /*
238  * Return pointer to the argno'th argument datum.
239  */
240 static inline LLVMValueRef
241 l_funcvaluep(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
242 {
243  LLVMValueRef v_args;
244  LLVMValueRef v_argn;
245 
246  v_args = LLVMBuildStructGEP(b,
247  v_fcinfo,
249  "");
250  v_argn = LLVMBuildStructGEP(b, v_args, argno, "");
251 
252  return LLVMBuildStructGEP(b, v_argn, FIELDNO_NULLABLE_DATUM_DATUM, "");
253 }
254 
255 /*
256  * Return argno'th argument nullness.
257  */
258 static inline LLVMValueRef
259 l_funcnull(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
260 {
261  return LLVMBuildLoad(b, l_funcnullp(b, v_fcinfo, argno), "");
262 }
263 
264 /*
265  * Return argno'th argument datum.
266  */
267 static inline LLVMValueRef
268 l_funcvalue(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
269 {
270  return LLVMBuildLoad(b, l_funcvaluep(b, v_fcinfo, argno), "");
271 }
272 
273 #endif /* USE_LLVM */
274 #endif
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:259
signed char int8
Definition: c.h:476
signed short int16
Definition: c.h:477
signed int int32
Definition: c.h:478
#define pg_attribute_printf(f, a)
Definition: c.h:175
struct cursor * cur
Definition: ecpg.c:28
const char * name
Definition: encode.c:571
#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 TypeParamBool
Definition: llvmjit.c:60
LLVMTypeRef StructMemoryContextData
Definition: llvmjit.c:78
LLVMTypeRef TypeSizeT
Definition: llvmjit.c:59
LLVMTypeRef TypeStorageBool
Definition: llvmjit.c:61
static char * buf
Definition: pg_test_fsync.c:67
#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