PostgreSQL Source Code  git master
llvmjit_deform.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * llvmjit_deform.c
4  * Generate code for deforming a heap tuple.
5  *
6  * This gains performance benefits over unJITed deforming from compile-time
7  * knowledge of the tuple descriptor. Fixed column widths, NOT NULLness, etc
8  * can be taken advantage of.
9  *
10  * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
11  * Portions Copyright (c) 1994, Regents of the University of California
12  *
13  * IDENTIFICATION
14  * src/backend/jit/llvm/llvmjit_deform.c
15  *
16  *-------------------------------------------------------------------------
17  */
18 
19 #include "postgres.h"
20 
21 #include <llvm-c/Core.h>
22 
23 #include "access/htup_details.h"
24 #include "access/tupdesc_details.h"
25 #include "executor/tuptable.h"
26 #include "jit/llvmjit.h"
27 #include "jit/llvmjit_emit.h"
28 
29 
30 /*
31  * Create a function that deforms a tuple of type desc up to natts columns.
32  */
33 LLVMValueRef
34 slot_compile_deform(LLVMJitContext *context, TupleDesc desc,
35  const TupleTableSlotOps *ops, int natts)
36 {
37  char *funcname;
38 
39  LLVMModuleRef mod;
40  LLVMBuilderRef b;
41 
42  LLVMTypeRef deform_sig;
43  LLVMValueRef v_deform_fn;
44 
45  LLVMBasicBlockRef b_entry;
46  LLVMBasicBlockRef b_adjust_unavail_cols;
47  LLVMBasicBlockRef b_find_start;
48 
49  LLVMBasicBlockRef b_out;
50  LLVMBasicBlockRef b_dead;
51  LLVMBasicBlockRef *attcheckattnoblocks;
52  LLVMBasicBlockRef *attstartblocks;
53  LLVMBasicBlockRef *attisnullblocks;
54  LLVMBasicBlockRef *attcheckalignblocks;
55  LLVMBasicBlockRef *attalignblocks;
56  LLVMBasicBlockRef *attstoreblocks;
57 
58  LLVMValueRef v_offp;
59 
60  LLVMValueRef v_tupdata_base;
61  LLVMValueRef v_tts_values;
62  LLVMValueRef v_tts_nulls;
63  LLVMValueRef v_slotoffp;
64  LLVMValueRef v_flagsp;
65  LLVMValueRef v_nvalidp;
66  LLVMValueRef v_nvalid;
67  LLVMValueRef v_maxatt;
68 
69  LLVMValueRef v_slot;
70 
71  LLVMValueRef v_tupleheaderp;
72  LLVMValueRef v_tuplep;
73  LLVMValueRef v_infomask1;
74  LLVMValueRef v_infomask2;
75  LLVMValueRef v_bits;
76 
77  LLVMValueRef v_hoff;
78 
79  LLVMValueRef v_hasnulls;
80 
81  /* last column (0 indexed) guaranteed to exist */
82  int guaranteed_column_number = -1;
83 
84  /* current known alignment */
85  int known_alignment = 0;
86 
87  /* if true, known_alignment describes definite offset of column */
88  bool attguaranteedalign = true;
89 
90  int attnum;
91 
92  /* virtual tuples never need deforming, so don't generate code */
93  if (ops == &TTSOpsVirtual)
94  return NULL;
95 
96  /* decline to JIT for slot types we don't know to handle */
97  if (ops != &TTSOpsHeapTuple && ops != &TTSOpsBufferHeapTuple &&
98  ops != &TTSOpsMinimalTuple)
99  return NULL;
100 
101  mod = llvm_mutable_module(context);
102 
103  funcname = llvm_expand_funcname(context, "deform");
104 
105  /*
106  * Check which columns have to exist, so we don't have to check the row's
107  * natts unnecessarily.
108  */
109  for (attnum = 0; attnum < desc->natts; attnum++)
110  {
111  Form_pg_attribute att = TupleDescAttr(desc, attnum);
112 
113  /*
114  * If the column is declared NOT NULL then it must be present in every
115  * tuple, unless there's a "missing" entry that could provide a
116  * non-NULL value for it. That in turn guarantees that the NULL bitmap
117  * - if there are any NULLable columns - is at least long enough to
118  * cover columns up to attnum.
119  *
120  * Be paranoid and also check !attisdropped, even though the
121  * combination of attisdropped && attnotnull combination shouldn't
122  * exist.
123  */
124  if (att->attnotnull &&
125  !att->atthasmissing &&
126  !att->attisdropped)
127  guaranteed_column_number = attnum;
128  }
129 
130  /* Create the signature and function */
131  {
132  LLVMTypeRef param_types[1];
133 
134  param_types[0] = l_ptr(StructTupleTableSlot);
135 
136  deform_sig = LLVMFunctionType(LLVMVoidType(), param_types,
137  lengthof(param_types), 0);
138  }
139  v_deform_fn = LLVMAddFunction(mod, funcname, deform_sig);
140  LLVMSetLinkage(v_deform_fn, LLVMInternalLinkage);
141  LLVMSetParamAlignment(LLVMGetParam(v_deform_fn, 0), MAXIMUM_ALIGNOF);
143 
144  b_entry =
145  LLVMAppendBasicBlock(v_deform_fn, "entry");
146  b_adjust_unavail_cols =
147  LLVMAppendBasicBlock(v_deform_fn, "adjust_unavail_cols");
148  b_find_start =
149  LLVMAppendBasicBlock(v_deform_fn, "find_startblock");
150  b_out =
151  LLVMAppendBasicBlock(v_deform_fn, "outblock");
152  b_dead =
153  LLVMAppendBasicBlock(v_deform_fn, "deadblock");
154 
155  b = LLVMCreateBuilder();
156 
157  attcheckattnoblocks = palloc(sizeof(LLVMBasicBlockRef) * natts);
158  attstartblocks = palloc(sizeof(LLVMBasicBlockRef) * natts);
159  attisnullblocks = palloc(sizeof(LLVMBasicBlockRef) * natts);
160  attcheckalignblocks = palloc(sizeof(LLVMBasicBlockRef) * natts);
161  attalignblocks = palloc(sizeof(LLVMBasicBlockRef) * natts);
162  attstoreblocks = palloc(sizeof(LLVMBasicBlockRef) * natts);
163 
164  known_alignment = 0;
165 
166  LLVMPositionBuilderAtEnd(b, b_entry);
167 
168  /* perform allocas first, llvm only converts those to registers */
169  v_offp = LLVMBuildAlloca(b, TypeSizeT, "v_offp");
170 
171  v_slot = LLVMGetParam(v_deform_fn, 0);
172 
173  v_tts_values =
174  l_load_struct_gep(b, v_slot, FIELDNO_TUPLETABLESLOT_VALUES,
175  "tts_values");
176  v_tts_nulls =
177  l_load_struct_gep(b, v_slot, FIELDNO_TUPLETABLESLOT_ISNULL,
178  "tts_ISNULL");
179  v_flagsp = LLVMBuildStructGEP(b, v_slot, FIELDNO_TUPLETABLESLOT_FLAGS, "");
180  v_nvalidp = LLVMBuildStructGEP(b, v_slot, FIELDNO_TUPLETABLESLOT_NVALID, "");
181 
182  if (ops == &TTSOpsHeapTuple || ops == &TTSOpsBufferHeapTuple)
183  {
184  LLVMValueRef v_heapslot;
185 
186  v_heapslot =
187  LLVMBuildBitCast(b,
188  v_slot,
190  "heapslot");
191  v_slotoffp = LLVMBuildStructGEP(b, v_heapslot, FIELDNO_HEAPTUPLETABLESLOT_OFF, "");
192  v_tupleheaderp =
193  l_load_struct_gep(b, v_heapslot, FIELDNO_HEAPTUPLETABLESLOT_TUPLE,
194  "tupleheader");
195 
196  }
197  else if (ops == &TTSOpsMinimalTuple)
198  {
199  LLVMValueRef v_minimalslot;
200 
201  v_minimalslot =
202  LLVMBuildBitCast(b,
203  v_slot,
205  "minimalslot");
206  v_slotoffp = LLVMBuildStructGEP(b, v_minimalslot, FIELDNO_MINIMALTUPLETABLESLOT_OFF, "");
207  v_tupleheaderp =
208  l_load_struct_gep(b, v_minimalslot, FIELDNO_MINIMALTUPLETABLESLOT_TUPLE,
209  "tupleheader");
210  }
211  else
212  {
213  /* should've returned at the start of the function */
214  pg_unreachable();
215  }
216 
217  v_tuplep =
218  l_load_struct_gep(b, v_tupleheaderp, FIELDNO_HEAPTUPLEDATA_DATA,
219  "tuple");
220  v_bits =
221  LLVMBuildBitCast(b,
222  LLVMBuildStructGEP(b, v_tuplep,
224  ""),
225  l_ptr(LLVMInt8Type()),
226  "t_bits");
227  v_infomask1 =
228  l_load_struct_gep(b, v_tuplep,
230  "infomask1");
231  v_infomask2 =
232  l_load_struct_gep(b,
234  "infomask2");
235 
236  /* t_infomask & HEAP_HASNULL */
237  v_hasnulls =
238  LLVMBuildICmp(b, LLVMIntNE,
239  LLVMBuildAnd(b,
240  l_int16_const(HEAP_HASNULL),
241  v_infomask1, ""),
242  l_int16_const(0),
243  "hasnulls");
244 
245  /* t_infomask2 & HEAP_NATTS_MASK */
246  v_maxatt = LLVMBuildAnd(b,
247  l_int16_const(HEAP_NATTS_MASK),
248  v_infomask2,
249  "maxatt");
250 
251  /*
252  * Need to zext, as getelementptr otherwise treats hoff as a signed 8bit
253  * integer, which'd yield a negative offset for t_hoff > 127.
254  */
255  v_hoff =
256  LLVMBuildZExt(b,
257  l_load_struct_gep(b, v_tuplep,
259  ""),
260  LLVMInt32Type(), "t_hoff");
261 
262  v_tupdata_base =
263  LLVMBuildGEP(b,
264  LLVMBuildBitCast(b,
265  v_tuplep,
266  l_ptr(LLVMInt8Type()),
267  ""),
268  &v_hoff, 1,
269  "v_tupdata_base");
270 
271  /*
272  * Load tuple start offset from slot. Will be reset below in case there's
273  * no existing deformed columns in slot.
274  */
275  {
276  LLVMValueRef v_off_start;
277 
278  v_off_start = LLVMBuildLoad(b, v_slotoffp, "v_slot_off");
279  v_off_start = LLVMBuildZExt(b, v_off_start, TypeSizeT, "");
280  LLVMBuildStore(b, v_off_start, v_offp);
281  }
282 
283  /* build the basic block for each attribute, need them as jump target */
284  for (attnum = 0; attnum < natts; attnum++)
285  {
286  attcheckattnoblocks[attnum] =
287  l_bb_append_v(v_deform_fn, "block.attr.%d.attcheckattno", attnum);
288  attstartblocks[attnum] =
289  l_bb_append_v(v_deform_fn, "block.attr.%d.start", attnum);
290  attisnullblocks[attnum] =
291  l_bb_append_v(v_deform_fn, "block.attr.%d.attisnull", attnum);
292  attcheckalignblocks[attnum] =
293  l_bb_append_v(v_deform_fn, "block.attr.%d.attcheckalign", attnum);
294  attalignblocks[attnum] =
295  l_bb_append_v(v_deform_fn, "block.attr.%d.align", attnum);
296  attstoreblocks[attnum] =
297  l_bb_append_v(v_deform_fn, "block.attr.%d.store", attnum);
298  }
299 
300  /*
301  * Check if it is guaranteed that all the desired attributes are available
302  * in the tuple (but still possibly NULL), by dint of either the last
303  * to-be-deformed column being NOT NULL, or subsequent ones not accessed
304  * here being NOT NULL. If that's not guaranteed the tuple headers natt's
305  * has to be checked, and missing attributes potentially have to be
306  * fetched (using slot_getmissingattrs().
307  */
308  if ((natts - 1) <= guaranteed_column_number)
309  {
310  /* just skip through unnecessary blocks */
311  LLVMBuildBr(b, b_adjust_unavail_cols);
312  LLVMPositionBuilderAtEnd(b, b_adjust_unavail_cols);
313  LLVMBuildBr(b, b_find_start);
314  }
315  else
316  {
317  LLVMValueRef v_params[3];
318 
319  /* branch if not all columns available */
320  LLVMBuildCondBr(b,
321  LLVMBuildICmp(b, LLVMIntULT,
322  v_maxatt,
323  l_int16_const(natts),
324  ""),
325  b_adjust_unavail_cols,
326  b_find_start);
327 
328  /* if not, memset tts_isnull of relevant cols to true */
329  LLVMPositionBuilderAtEnd(b, b_adjust_unavail_cols);
330 
331  v_params[0] = v_slot;
332  v_params[1] = LLVMBuildZExt(b, v_maxatt, LLVMInt32Type(), "");
333  v_params[2] = l_int32_const(natts);
334  LLVMBuildCall(b, llvm_get_decl(mod, FuncSlotGetmissingattrs),
335  v_params, lengthof(v_params), "");
336  LLVMBuildBr(b, b_find_start);
337  }
338 
339  LLVMPositionBuilderAtEnd(b, b_find_start);
340 
341  v_nvalid = LLVMBuildLoad(b, v_nvalidp, "");
342 
343  /*
344  * Build switch to go from nvalid to the right startblock. Callers
345  * currently don't have the knowledge, but it'd be good for performance to
346  * avoid this check when it's known that the slot is empty (e.g. in scan
347  * nodes).
348  */
349  if (true)
350  {
351  LLVMValueRef v_switch = LLVMBuildSwitch(b, v_nvalid,
352  b_dead, natts);
353 
354  for (attnum = 0; attnum < natts; attnum++)
355  {
356  LLVMValueRef v_attno = l_int16_const(attnum);
357 
358  LLVMAddCase(v_switch, v_attno, attcheckattnoblocks[attnum]);
359  }
360 
361  }
362  else
363  {
364  /* jump from entry block to first block */
365  LLVMBuildBr(b, attcheckattnoblocks[0]);
366  }
367 
368  LLVMPositionBuilderAtEnd(b, b_dead);
369  LLVMBuildUnreachable(b);
370 
371  /*
372  * Iterate over each attribute that needs to be deformed, build code to
373  * deform it.
374  */
375  for (attnum = 0; attnum < natts; attnum++)
376  {
377  Form_pg_attribute att = TupleDescAttr(desc, attnum);
378  LLVMValueRef v_incby;
379  int alignto;
380  LLVMValueRef l_attno = l_int16_const(attnum);
381  LLVMValueRef v_attdatap;
382  LLVMValueRef v_resultp;
383 
384  /* build block checking whether we did all the necessary attributes */
385  LLVMPositionBuilderAtEnd(b, attcheckattnoblocks[attnum]);
386 
387  /*
388  * If this is the first attribute, slot->tts_nvalid was 0. Therefore
389  * also reset offset to 0, it may be from a previous execution.
390  */
391  if (attnum == 0)
392  {
393  LLVMBuildStore(b, l_sizet_const(0), v_offp);
394  }
395 
396  /*
397  * Build check whether column is available (i.e. whether the tuple has
398  * that many columns stored). We can avoid the branch if we know
399  * there's a subsequent NOT NULL column.
400  */
401  if (attnum <= guaranteed_column_number)
402  {
403  LLVMBuildBr(b, attstartblocks[attnum]);
404  }
405  else
406  {
407  LLVMValueRef v_islast;
408 
409  v_islast = LLVMBuildICmp(b, LLVMIntUGE,
410  l_attno,
411  v_maxatt,
412  "heap_natts");
413  LLVMBuildCondBr(b, v_islast, b_out, attstartblocks[attnum]);
414  }
415  LLVMPositionBuilderAtEnd(b, attstartblocks[attnum]);
416 
417  /*
418  * Check for nulls if necessary. No need to take missing attributes
419  * into account, because if they're present the heaptuple's natts
420  * would have indicated that a slot_getmissingattrs() is needed.
421  */
422  if (!att->attnotnull)
423  {
424  LLVMBasicBlockRef b_ifnotnull;
425  LLVMBasicBlockRef b_ifnull;
426  LLVMBasicBlockRef b_next;
427  LLVMValueRef v_attisnull;
428  LLVMValueRef v_nullbyteno;
429  LLVMValueRef v_nullbytemask;
430  LLVMValueRef v_nullbyte;
431  LLVMValueRef v_nullbit;
432 
433  b_ifnotnull = attcheckalignblocks[attnum];
434  b_ifnull = attisnullblocks[attnum];
435 
436  if (attnum + 1 == natts)
437  b_next = b_out;
438  else
439  b_next = attcheckattnoblocks[attnum + 1];
440 
441  v_nullbyteno = l_int32_const(attnum >> 3);
442  v_nullbytemask = l_int8_const(1 << ((attnum) & 0x07));
443  v_nullbyte = l_load_gep1(b, v_bits, v_nullbyteno, "attnullbyte");
444 
445  v_nullbit = LLVMBuildICmp(b,
446  LLVMIntEQ,
447  LLVMBuildAnd(b, v_nullbyte, v_nullbytemask, ""),
448  l_int8_const(0),
449  "attisnull");
450 
451  v_attisnull = LLVMBuildAnd(b, v_hasnulls, v_nullbit, "");
452 
453  LLVMBuildCondBr(b, v_attisnull, b_ifnull, b_ifnotnull);
454 
455  LLVMPositionBuilderAtEnd(b, b_ifnull);
456 
457  /* store null-byte */
458  LLVMBuildStore(b,
459  l_int8_const(1),
460  LLVMBuildGEP(b, v_tts_nulls, &l_attno, 1, ""));
461  /* store zero datum */
462  LLVMBuildStore(b,
463  l_sizet_const(0),
464  LLVMBuildGEP(b, v_tts_values, &l_attno, 1, ""));
465 
466  LLVMBuildBr(b, b_next);
467  attguaranteedalign = false;
468  }
469  else
470  {
471  /* nothing to do */
472  LLVMBuildBr(b, attcheckalignblocks[attnum]);
473  LLVMPositionBuilderAtEnd(b, attisnullblocks[attnum]);
474  LLVMBuildBr(b, attcheckalignblocks[attnum]);
475  }
476  LLVMPositionBuilderAtEnd(b, attcheckalignblocks[attnum]);
477 
478  /* determine required alignment */
479  if (att->attalign == 'i')
480  alignto = ALIGNOF_INT;
481  else if (att->attalign == 'c')
482  alignto = 1;
483  else if (att->attalign == 'd')
484  alignto = ALIGNOF_DOUBLE;
485  else if (att->attalign == 's')
486  alignto = ALIGNOF_SHORT;
487  else
488  {
489  elog(ERROR, "unknown alignment");
490  alignto = 0;
491  }
492 
493  /* ------
494  * Even if alignment is required, we can skip doing it if provably
495  * unnecessary:
496  * - first column is guaranteed to be aligned
497  * - columns following a NOT NULL fixed width datum have known
498  * alignment, can skip alignment computation if that known alignment
499  * is compatible with current column.
500  * ------
501  */
502  if (alignto > 1 &&
503  (known_alignment < 0 || known_alignment != TYPEALIGN(alignto, known_alignment)))
504  {
505  /*
506  * When accessing a varlena field, we have to "peek" to see if we
507  * are looking at a pad byte or the first byte of a 1-byte-header
508  * datum. A zero byte must be either a pad byte, or the first
509  * byte of a correctly aligned 4-byte length word; in either case,
510  * we can align safely. A non-zero byte must be either a 1-byte
511  * length word, or the first byte of a correctly aligned 4-byte
512  * length word; in either case, we need not align.
513  */
514  if (att->attlen == -1)
515  {
516  LLVMValueRef v_possible_padbyte;
517  LLVMValueRef v_ispad;
518  LLVMValueRef v_off;
519 
520  /* don't know if short varlena or not */
521  attguaranteedalign = false;
522 
523  v_off = LLVMBuildLoad(b, v_offp, "");
524 
525  v_possible_padbyte =
526  l_load_gep1(b, v_tupdata_base, v_off, "padbyte");
527  v_ispad =
528  LLVMBuildICmp(b, LLVMIntEQ,
529  v_possible_padbyte, l_int8_const(0),
530  "ispadbyte");
531  LLVMBuildCondBr(b, v_ispad,
532  attalignblocks[attnum],
533  attstoreblocks[attnum]);
534  }
535  else
536  {
537  LLVMBuildBr(b, attalignblocks[attnum]);
538  }
539 
540  LLVMPositionBuilderAtEnd(b, attalignblocks[attnum]);
541 
542  /* translation of alignment code (cf TYPEALIGN()) */
543  {
544  LLVMValueRef v_off_aligned;
545  LLVMValueRef v_off = LLVMBuildLoad(b, v_offp, "");
546 
547  /* ((ALIGNVAL) - 1) */
548  LLVMValueRef v_alignval = l_sizet_const(alignto - 1);
549 
550  /* ((uintptr_t) (LEN) + ((ALIGNVAL) - 1)) */
551  LLVMValueRef v_lh = LLVMBuildAdd(b, v_off, v_alignval, "");
552 
553  /* ~((uintptr_t) ((ALIGNVAL) - 1)) */
554  LLVMValueRef v_rh = l_sizet_const(~(alignto - 1));
555 
556  v_off_aligned = LLVMBuildAnd(b, v_lh, v_rh, "aligned_offset");
557 
558  LLVMBuildStore(b, v_off_aligned, v_offp);
559  }
560 
561  /*
562  * As alignment either was unnecessary or has been performed, we
563  * now know the current alignment. This is only safe because this
564  * value isn't used for varlena and nullable columns.
565  */
566  if (known_alignment >= 0)
567  {
568  Assert(known_alignment != 0);
569  known_alignment = TYPEALIGN(alignto, known_alignment);
570  }
571 
572  LLVMBuildBr(b, attstoreblocks[attnum]);
573  LLVMPositionBuilderAtEnd(b, attstoreblocks[attnum]);
574  }
575  else
576  {
577  LLVMPositionBuilderAtEnd(b, attcheckalignblocks[attnum]);
578  LLVMBuildBr(b, attalignblocks[attnum]);
579  LLVMPositionBuilderAtEnd(b, attalignblocks[attnum]);
580  LLVMBuildBr(b, attstoreblocks[attnum]);
581  }
582  LLVMPositionBuilderAtEnd(b, attstoreblocks[attnum]);
583 
584  /*
585  * Store the current offset if known to be constant. That allows LLVM
586  * to generate better code. Without that LLVM can't figure out that
587  * the offset might be constant due to the jumps for previously
588  * decoded columns.
589  */
590  if (attguaranteedalign)
591  {
592  Assert(known_alignment >= 0);
593  LLVMBuildStore(b, l_sizet_const(known_alignment), v_offp);
594  }
595 
596  /* compute what following columns are aligned to */
597  if (att->attlen < 0)
598  {
599  /* can't guarantee any alignment after variable length field */
600  known_alignment = -1;
601  attguaranteedalign = false;
602  }
603  else if (att->attnotnull && attguaranteedalign && known_alignment >= 0)
604  {
605  /*
606  * If the offset to the column was previously known, a NOT NULL &
607  * fixed-width column guarantees that alignment is just the
608  * previous alignment plus column width.
609  */
610  Assert(att->attlen > 0);
611  known_alignment += att->attlen;
612  }
613  else if (att->attnotnull && (att->attlen % alignto) == 0)
614  {
615  /*
616  * After a NOT NULL fixed-width column with a length that is a
617  * multiple of its alignment requirement, we know the following
618  * column is aligned to at least the current column's alignment.
619  */
620  Assert(att->attlen > 0);
621  known_alignment = alignto;
622  Assert(known_alignment > 0);
623  attguaranteedalign = false;
624  }
625  else
626  {
627  known_alignment = -1;
628  attguaranteedalign = false;
629  }
630 
631 
632  /* compute address to load data from */
633  {
634  LLVMValueRef v_off = LLVMBuildLoad(b, v_offp, "");
635 
636  v_attdatap =
637  LLVMBuildGEP(b, v_tupdata_base, &v_off, 1, "");
638  }
639 
640  /* compute address to store value at */
641  v_resultp = LLVMBuildGEP(b, v_tts_values, &l_attno, 1, "");
642 
643  /* store null-byte (false) */
644  LLVMBuildStore(b, l_int8_const(0),
645  LLVMBuildGEP(b, v_tts_nulls, &l_attno, 1, ""));
646 
647  /*
648  * Store datum. For byval: datums copy the value, extend to Datum's
649  * width, and store. For byref types: store pointer to data.
650  */
651  if (att->attbyval)
652  {
653  LLVMValueRef v_tmp_loaddata;
654  LLVMTypeRef vartypep =
655  LLVMPointerType(LLVMIntType(att->attlen * 8), 0);
656 
657  v_tmp_loaddata =
658  LLVMBuildPointerCast(b, v_attdatap, vartypep, "");
659  v_tmp_loaddata = LLVMBuildLoad(b, v_tmp_loaddata, "attr_byval");
660  v_tmp_loaddata = LLVMBuildZExt(b, v_tmp_loaddata, TypeSizeT, "");
661 
662  LLVMBuildStore(b, v_tmp_loaddata, v_resultp);
663  }
664  else
665  {
666  LLVMValueRef v_tmp_loaddata;
667 
668  /* store pointer */
669  v_tmp_loaddata =
670  LLVMBuildPtrToInt(b,
671  v_attdatap,
672  TypeSizeT,
673  "attr_ptr");
674  LLVMBuildStore(b, v_tmp_loaddata, v_resultp);
675  }
676 
677  /* increment data pointer */
678  if (att->attlen > 0)
679  {
680  v_incby = l_sizet_const(att->attlen);
681  }
682  else if (att->attlen == -1)
683  {
684  v_incby = LLVMBuildCall(b,
686  &v_attdatap, 1,
687  "varsize_any");
688  l_callsite_ro(v_incby);
689  l_callsite_alwaysinline(v_incby);
690  }
691  else if (att->attlen == -2)
692  {
693  v_incby = LLVMBuildCall(b,
695  &v_attdatap, 1, "strlen");
696 
697  l_callsite_ro(v_incby);
698 
699  /* add 1 for NUL byte */
700  v_incby = LLVMBuildAdd(b, v_incby, l_sizet_const(1), "");
701  }
702  else
703  {
704  Assert(false);
705  v_incby = NULL; /* silence compiler */
706  }
707 
708  if (attguaranteedalign)
709  {
710  Assert(known_alignment >= 0);
711  LLVMBuildStore(b, l_sizet_const(known_alignment), v_offp);
712  }
713  else
714  {
715  LLVMValueRef v_off = LLVMBuildLoad(b, v_offp, "");
716 
717  v_off = LLVMBuildAdd(b, v_off, v_incby, "increment_offset");
718  LLVMBuildStore(b, v_off, v_offp);
719  }
720 
721  /*
722  * jump to next block, unless last possible column, or all desired
723  * (available) attributes have been fetched.
724  */
725  if (attnum + 1 == natts)
726  {
727  /* jump out */
728  LLVMBuildBr(b, b_out);
729  }
730  else
731  {
732  LLVMBuildBr(b, attcheckattnoblocks[attnum + 1]);
733  }
734  }
735 
736 
737  /* build block that returns */
738  LLVMPositionBuilderAtEnd(b, b_out);
739 
740  {
741  LLVMValueRef v_off = LLVMBuildLoad(b, v_offp, "");
742  LLVMValueRef v_flags;
743 
744  LLVMBuildStore(b, l_int16_const(natts), v_nvalidp);
745  v_off = LLVMBuildTrunc(b, v_off, LLVMInt32Type(), "");
746  LLVMBuildStore(b, v_off, v_slotoffp);
747  v_flags = LLVMBuildLoad(b, v_flagsp, "tts_flags");
748  v_flags = LLVMBuildOr(b, v_flags, l_int16_const(TTS_FLAG_SLOW), "");
749  LLVMBuildStore(b, v_flags, v_flagsp);
750  LLVMBuildRetVoid(b);
751  }
752 
753  LLVMDisposeBuilder(b);
754 
755  return v_deform_fn;
756 }
LLVMValueRef slot_compile_deform(LLVMJitContext *context, TupleDesc desc, const TupleTableSlotOps *ops, int natts)
#define FIELDNO_HEAPTUPLEHEADERDATA_INFOMASK
Definition: htup_details.h:168
#define FIELDNO_MINIMALTUPLETABLESLOT_TUPLE
Definition: tuptable.h:282
#define pg_unreachable()
Definition: c.h:193
LLVMTypeRef TypeSizeT
Definition: llvmjit.c:52
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
const TupleTableSlotOps TTSOpsBufferHeapTuple
Definition: execTuples.c:87
LLVMValueRef FuncVarsizeAny
Definition: llvmjit.c:84
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:84
LLVMValueRef llvm_get_decl(LLVMModuleRef mod, LLVMValueRef v_src)
Definition: llvmjit.c:315
#define FIELDNO_TUPLETABLESLOT_ISNULL
Definition: tuptable.h:127
#define FIELDNO_HEAPTUPLETABLESLOT_OFF
Definition: tuptable.h:251
#define lengthof(array)
Definition: c.h:662
LLVMTypeRef StructHeapTupleTableSlot
Definition: llvmjit.c:69
#define HEAP_HASNULL
Definition: htup_details.h:189
#define ERROR
Definition: elog.h:43
#define FIELDNO_HEAPTUPLETABLESLOT_TUPLE
Definition: tuptable.h:249
char * llvm_expand_funcname(struct LLVMJitContext *context, const char *basename)
Definition: llvmjit.c:226
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
#define FIELDNO_TUPLETABLESLOT_NVALID
Definition: tuptable.h:120
#define FIELDNO_TUPLETABLESLOT_FLAGS
Definition: tuptable.h:118
LLVMValueRef FuncSlotGetmissingattrs
Definition: llvmjit.c:86
LLVMValueRef FuncStrlen
Definition: llvmjit.c:83
LLVMTypeRef StructMinimalTupleTableSlot
Definition: llvmjit.c:70
LLVMTypeRef StructTupleTableSlot
Definition: llvmjit.c:68
int16 attnum
Definition: pg_attribute.h:79
#define TYPEALIGN(ALIGNVAL, LEN)
Definition: c.h:678
LLVMModuleRef llvm_mutable_module(LLVMJitContext *context)
Definition: llvmjit.c:201
#define FIELDNO_MINIMALTUPLETABLESLOT_OFF
Definition: tuptable.h:286
#define FIELDNO_HEAPTUPLEHEADERDATA_HOFF
Definition: htup_details.h:171
#define HEAP_NATTS_MASK
Definition: htup_details.h:276
#define Assert(condition)
Definition: c.h:732
#define FIELDNO_HEAPTUPLEHEADERDATA_INFOMASK2
Definition: htup_details.h:165
void * palloc(Size size)
Definition: mcxt.c:949
#define FIELDNO_TUPLETABLESLOT_VALUES
Definition: tuptable.h:125
#define elog(elevel,...)
Definition: elog.h:226
const TupleTableSlotOps TTSOpsHeapTuple
Definition: execTuples.c:85
LLVMValueRef AttributeTemplate
Definition: llvmjit.c:82
void llvm_copy_attributes(LLVMValueRef v_from, LLVMValueRef v_to)
Definition: llvmjit.c:336
const TupleTableSlotOps TTSOpsMinimalTuple
Definition: execTuples.c:86
#define FIELDNO_HEAPTUPLEDATA_DATA
Definition: htup.h:67
#define FIELDNO_HEAPTUPLEHEADERDATA_BITS
Definition: htup_details.h:176
#define TTS_FLAG_SLOW
Definition: tuptable.h:104