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