Age Owner TLA 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-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
1844 andres 27 CBC 62678 : l_ptr_const(void *ptr, LLVMTypeRef type)
28 : {
29 62678 : LLVMValueRef c = LLVMConstInt(TypeSizeT, (uintptr_t) ptr, false);
30 :
31 62678 : return LLVMConstIntToPtr(c, type);
32 : }
33 :
34 : /*
35 : * Emit pointer.
36 : */
37 : static inline LLVMTypeRef
38 77036 : l_ptr(LLVMTypeRef t)
39 : {
40 77036 : return LLVMPointerType(t, 0);
41 : }
42 :
43 : /*
44 : * Emit constant integer.
45 : */
46 : static inline LLVMValueRef
47 25756 : l_int8_const(int8 i)
48 : {
49 25756 : return LLVMConstInt(LLVMInt8Type(), i, false);
50 : }
51 :
52 : /*
53 : * Emit constant integer.
54 : */
55 : static inline LLVMValueRef
56 36196 : l_int16_const(int16 i)
57 : {
58 36196 : return LLVMConstInt(LLVMInt16Type(), i, false);
59 : }
60 :
61 : /*
62 : * Emit constant integer.
63 : */
64 : static inline LLVMValueRef
65 22969 : l_int32_const(int32 i)
66 : {
67 22969 : return LLVMConstInt(LLVMInt32Type(), i, false);
68 : }
69 :
70 : /*
71 : * Emit constant integer.
72 : */
73 : static inline LLVMValueRef
74 5360 : l_int64_const(int64 i)
75 : {
76 5360 : return LLVMConstInt(LLVMInt64Type(), i, false);
77 : }
78 :
79 : /*
80 : * Emit constant integer.
81 : */
82 : static inline LLVMValueRef
83 28016 : l_sizet_const(size_t i)
84 : {
85 28016 : 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 14316 : l_sbool_const(bool i)
93 : {
94 14316 : 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 104906 : l_load_struct_gep(LLVMBuilderRef b, LLVMValueRef v, int32 idx, const char *name)
111 : {
112 104906 : LLVMValueRef v_ptr = LLVMBuildStructGEP(b, v, idx, "");
113 :
114 104906 : 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 21538 : l_load_gep1(LLVMBuilderRef b, LLVMValueRef v, LLVMValueRef idx, const char *name)
122 : {
123 21538 : LLVMValueRef v_ptr = LLVMBuildGEP(b, v, &idx, 1, "");
124 :
125 21538 : 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 13614 : l_bb_before_v(LLVMBasicBlockRef r, const char *fmt,...)
137 : {
138 : char buf[512];
139 : va_list args;
140 :
141 13614 : va_start(args, fmt);
142 13614 : vsnprintf(buf, sizeof(buf), fmt, args);
143 13614 : va_end(args);
144 :
145 13614 : 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 65573 : l_bb_append_v(LLVMValueRef f, const char *fmt,...)
157 : {
158 : char buf[512];
159 : va_list args;
160 :
161 65573 : va_start(args, fmt);
162 65573 : vsnprintf(buf, sizeof(buf), fmt, args);
163 65573 : va_end(args);
164 :
165 65573 : return LLVMAppendBasicBlock(f, buf);
166 : }
167 :
168 : /*
169 : * Mark a callsite as readonly.
170 : */
171 : static inline void
172 1024 : l_callsite_ro(LLVMValueRef f)
173 : {
174 1024 : const char argname[] = "readonly";
175 : LLVMAttributeRef ref;
176 :
177 1024 : ref = LLVMCreateStringAttribute(LLVMGetGlobalContext(),
178 : argname,
179 : sizeof(argname) - 1,
180 : NULL, 0);
181 :
182 1024 : LLVMAddCallSiteAttribute(f, LLVMAttributeFunctionIndex, ref);
183 1024 : }
184 :
185 : /*
186 : * Mark a callsite as alwaysinline.
187 : */
188 : static inline void
189 1024 : l_callsite_alwaysinline(LLVMValueRef f)
190 : {
191 1024 : const char argname[] = "alwaysinline";
192 : int id;
193 : LLVMAttributeRef attr;
194 :
195 1024 : id = LLVMGetEnumAttributeKindForName(argname,
196 : sizeof(argname) - 1);
197 1024 : attr = LLVMCreateEnumAttribute(LLVMGetGlobalContext(), id, 0);
198 1024 : LLVMAddCallSiteAttribute(f, LLVMAttributeFunctionIndex, attr);
199 1024 : }
200 :
201 : /*
202 : * Emit code to switch memory context.
203 : */
204 : static inline LLVMValueRef
205 1577 : l_mcxt_switch(LLVMModuleRef mod, LLVMBuilderRef b, LLVMValueRef nc)
206 : {
207 1577 : const char *cmc = "CurrentMemoryContext";
208 : LLVMValueRef cur;
209 : LLVMValueRef ret;
210 :
211 1577 : if (!(cur = LLVMGetNamedGlobal(mod, cmc)))
212 238 : cur = LLVMAddGlobal(mod, l_ptr(StructMemoryContextData), cmc);
213 1577 : ret = LLVMBuildLoad(b, cur, cmc);
214 1577 : LLVMBuildStore(b, nc, cur);
215 :
216 1577 : return ret;
217 : }
218 :
219 : /*
220 : * Return pointer to the argno'th argument nullness.
221 : */
222 : static inline LLVMValueRef
1534 223 4485 : l_funcnullp(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
224 : {
225 : LLVMValueRef v_args;
226 : LLVMValueRef v_argn;
227 :
228 4485 : v_args = LLVMBuildStructGEP(b,
229 : v_fcinfo,
230 : FIELDNO_FUNCTIONCALLINFODATA_ARGS,
231 : "");
232 4485 : v_argn = LLVMBuildStructGEP(b, v_args, argno, "");
233 :
234 4485 : 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 838 : l_funcvaluep(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
242 : {
243 : LLVMValueRef v_args;
244 : LLVMValueRef v_argn;
245 :
246 838 : v_args = LLVMBuildStructGEP(b,
247 : v_fcinfo,
248 : FIELDNO_FUNCTIONCALLINFODATA_ARGS,
249 : "");
250 838 : v_argn = LLVMBuildStructGEP(b, v_args, argno, "");
251 :
252 838 : return LLVMBuildStructGEP(b, v_argn, FIELDNO_NULLABLE_DATUM_DATUM, "");
253 : }
254 :
255 : /*
256 : * Return argno'th argument nullness.
257 : */
258 : static inline LLVMValueRef
259 3647 : l_funcnull(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
260 : {
261 3647 : return LLVMBuildLoad(b, l_funcnullp(b, v_fcinfo, argno), "");
262 : }
263 :
264 : /*
265 : * Return argno'th argument datum.
266 : */
267 : static inline LLVMValueRef
1534 andres 268 UBC 0 : l_funcvalue(LLVMBuilderRef b, LLVMValueRef v_fcinfo, size_t argno)
269 : {
270 0 : return LLVMBuildLoad(b, l_funcvaluep(b, v_fcinfo, argno), "");
271 : }
272 :
273 : #endif /* USE_LLVM */
274 : #endif
|