21 #include <llvm-c/Core.h>
43 LLVMTypeRef deform_sig;
44 LLVMValueRef v_deform_fn;
46 LLVMBasicBlockRef b_entry;
47 LLVMBasicBlockRef b_adjust_unavail_cols;
48 LLVMBasicBlockRef b_find_start;
50 LLVMBasicBlockRef b_out;
51 LLVMBasicBlockRef b_dead;
52 LLVMBasicBlockRef *attcheckattnoblocks;
53 LLVMBasicBlockRef *attstartblocks;
54 LLVMBasicBlockRef *attisnullblocks;
55 LLVMBasicBlockRef *attcheckalignblocks;
56 LLVMBasicBlockRef *attalignblocks;
57 LLVMBasicBlockRef *attstoreblocks;
61 LLVMValueRef v_tupdata_base;
62 LLVMValueRef v_tts_values;
63 LLVMValueRef v_tts_nulls;
64 LLVMValueRef v_slotoffp;
65 LLVMValueRef v_flagsp;
66 LLVMValueRef v_nvalidp;
67 LLVMValueRef v_nvalid;
68 LLVMValueRef v_maxatt;
72 LLVMValueRef v_tupleheaderp;
73 LLVMValueRef v_tuplep;
74 LLVMValueRef v_infomask1;
75 LLVMValueRef v_infomask2;
80 LLVMValueRef v_hasnulls;
83 int guaranteed_column_number = -1;
86 int known_alignment = 0;
89 bool attguaranteedalign =
true;
103 lc = LLVMGetModuleContext(mod);
126 if (att->attnotnull &&
127 !att->atthasmissing &&
129 guaranteed_column_number =
attnum;
134 LLVMTypeRef param_types[1];
138 deform_sig = LLVMFunctionType(LLVMVoidTypeInContext(lc),
139 param_types,
lengthof(param_types), 0);
141 v_deform_fn = LLVMAddFunction(mod,
funcname, deform_sig);
142 LLVMSetLinkage(v_deform_fn, LLVMInternalLinkage);
143 LLVMSetParamAlignment(LLVMGetParam(v_deform_fn, 0), MAXIMUM_ALIGNOF);
147 LLVMAppendBasicBlockInContext(lc, v_deform_fn,
"entry");
148 b_adjust_unavail_cols =
149 LLVMAppendBasicBlockInContext(lc, v_deform_fn,
"adjust_unavail_cols");
151 LLVMAppendBasicBlockInContext(lc, v_deform_fn,
"find_startblock");
153 LLVMAppendBasicBlockInContext(lc, v_deform_fn,
"outblock");
155 LLVMAppendBasicBlockInContext(lc, v_deform_fn,
"deadblock");
157 b = LLVMCreateBuilderInContext(lc);
159 attcheckattnoblocks =
palloc(
sizeof(LLVMBasicBlockRef) * natts);
160 attstartblocks =
palloc(
sizeof(LLVMBasicBlockRef) * natts);
161 attisnullblocks =
palloc(
sizeof(LLVMBasicBlockRef) * natts);
162 attcheckalignblocks =
palloc(
sizeof(LLVMBasicBlockRef) * natts);
163 attalignblocks =
palloc(
sizeof(LLVMBasicBlockRef) * natts);
164 attstoreblocks =
palloc(
sizeof(LLVMBasicBlockRef) * natts);
168 LLVMPositionBuilderAtEnd(
b, b_entry);
171 v_offp = LLVMBuildAlloca(
b,
TypeSizeT,
"v_offp");
173 v_slot = LLVMGetParam(v_deform_fn, 0);
186 LLVMValueRef v_heapslot;
200 LLVMValueRef v_minimalslot;
207 v_slotoffp = l_struct_gep(
b,
237 l_ptr(LLVMInt8TypeInContext(lc)),
253 LLVMBuildICmp(
b, LLVMIntNE,
257 l_int16_const(lc, 0),
261 v_maxatt = LLVMBuildAnd(
b,
277 LLVMInt32TypeInContext(lc),
"t_hoff");
279 v_tupdata_base = l_gep(
b,
280 LLVMInt8TypeInContext(lc),
283 l_ptr(LLVMInt8TypeInContext(lc)),
293 LLVMValueRef v_off_start;
295 v_off_start = l_load(
b, LLVMInt32TypeInContext(lc), v_slotoffp,
"v_slot_off");
296 v_off_start = LLVMBuildZExt(
b, v_off_start,
TypeSizeT,
"");
297 LLVMBuildStore(
b, v_off_start, v_offp);
303 attcheckattnoblocks[
attnum] =
304 l_bb_append_v(v_deform_fn,
"block.attr.%d.attcheckattno",
attnum);
306 l_bb_append_v(v_deform_fn,
"block.attr.%d.start",
attnum);
308 l_bb_append_v(v_deform_fn,
"block.attr.%d.attisnull",
attnum);
309 attcheckalignblocks[
attnum] =
310 l_bb_append_v(v_deform_fn,
"block.attr.%d.attcheckalign",
attnum);
312 l_bb_append_v(v_deform_fn,
"block.attr.%d.align",
attnum);
314 l_bb_append_v(v_deform_fn,
"block.attr.%d.store",
attnum);
325 if ((natts - 1) <= guaranteed_column_number)
328 LLVMBuildBr(
b, b_adjust_unavail_cols);
329 LLVMPositionBuilderAtEnd(
b, b_adjust_unavail_cols);
330 LLVMBuildBr(
b, b_find_start);
334 LLVMValueRef v_params[3];
339 LLVMBuildICmp(
b, LLVMIntULT,
341 l_int16_const(lc, natts),
343 b_adjust_unavail_cols,
347 LLVMPositionBuilderAtEnd(
b, b_adjust_unavail_cols);
349 v_params[0] = v_slot;
350 v_params[1] = LLVMBuildZExt(
b, v_maxatt, LLVMInt32TypeInContext(lc),
"");
351 v_params[2] = l_int32_const(lc, natts);
356 LLVMBuildBr(
b, b_find_start);
359 LLVMPositionBuilderAtEnd(
b, b_find_start);
361 v_nvalid = l_load(
b, LLVMInt16TypeInContext(lc), v_nvalidp,
"");
371 LLVMValueRef v_switch = LLVMBuildSwitch(
b, v_nvalid,
376 LLVMValueRef v_attno = l_int16_const(lc,
attnum);
378 LLVMAddCase(v_switch, v_attno, attcheckattnoblocks[
attnum]);
384 LLVMBuildBr(
b, attcheckattnoblocks[0]);
387 LLVMPositionBuilderAtEnd(
b, b_dead);
388 LLVMBuildUnreachable(
b);
397 LLVMValueRef v_incby;
399 LLVMValueRef l_attno = l_int16_const(lc,
attnum);
400 LLVMValueRef v_attdatap;
401 LLVMValueRef v_resultp;
404 LLVMPositionBuilderAtEnd(
b, attcheckattnoblocks[
attnum]);
412 LLVMBuildStore(
b, l_sizet_const(0), v_offp);
420 if (
attnum <= guaranteed_column_number)
422 LLVMBuildBr(
b, attstartblocks[
attnum]);
426 LLVMValueRef v_islast;
428 v_islast = LLVMBuildICmp(
b, LLVMIntUGE,
432 LLVMBuildCondBr(
b, v_islast, b_out, attstartblocks[
attnum]);
434 LLVMPositionBuilderAtEnd(
b, attstartblocks[
attnum]);
441 if (!att->attnotnull)
443 LLVMBasicBlockRef b_ifnotnull;
444 LLVMBasicBlockRef b_ifnull;
445 LLVMBasicBlockRef b_next;
446 LLVMValueRef v_attisnull;
447 LLVMValueRef v_nullbyteno;
448 LLVMValueRef v_nullbytemask;
449 LLVMValueRef v_nullbyte;
450 LLVMValueRef v_nullbit;
452 b_ifnotnull = attcheckalignblocks[
attnum];
453 b_ifnull = attisnullblocks[
attnum];
458 b_next = attcheckattnoblocks[
attnum + 1];
460 v_nullbyteno = l_int32_const(lc,
attnum >> 3);
461 v_nullbytemask = l_int8_const(lc, 1 << ((
attnum) & 0x07));
462 v_nullbyte = l_load_gep1(
b, LLVMInt8TypeInContext(lc), v_bits, v_nullbyteno,
"attnullbyte");
464 v_nullbit = LLVMBuildICmp(
b,
466 LLVMBuildAnd(
b, v_nullbyte, v_nullbytemask,
""),
470 v_attisnull = LLVMBuildAnd(
b, v_hasnulls, v_nullbit,
"");
472 LLVMBuildCondBr(
b, v_attisnull, b_ifnull, b_ifnotnull);
474 LLVMPositionBuilderAtEnd(
b, b_ifnull);
479 l_gep(
b, LLVMInt8TypeInContext(lc), v_tts_nulls, &l_attno, 1,
""));
483 l_gep(
b,
TypeSizeT, v_tts_values, &l_attno, 1,
""));
485 LLVMBuildBr(
b, b_next);
486 attguaranteedalign =
false;
491 LLVMBuildBr(
b, attcheckalignblocks[
attnum]);
492 LLVMPositionBuilderAtEnd(
b, attisnullblocks[
attnum]);
493 LLVMBuildBr(
b, attcheckalignblocks[
attnum]);
495 LLVMPositionBuilderAtEnd(
b, attcheckalignblocks[
attnum]);
498 if (att->attalign == TYPALIGN_INT)
499 alignto = ALIGNOF_INT;
500 else if (att->attalign == TYPALIGN_CHAR)
502 else if (att->attalign == TYPALIGN_DOUBLE)
503 alignto = ALIGNOF_DOUBLE;
504 else if (att->attalign == TYPALIGN_SHORT)
505 alignto = ALIGNOF_SHORT;
522 (known_alignment < 0 || known_alignment !=
TYPEALIGN(alignto, known_alignment)))
533 if (att->attlen == -1)
535 LLVMValueRef v_possible_padbyte;
536 LLVMValueRef v_ispad;
540 attguaranteedalign =
false;
545 l_load_gep1(
b, LLVMInt8TypeInContext(lc), v_tupdata_base, v_off,
"padbyte");
547 LLVMBuildICmp(
b, LLVMIntEQ,
548 v_possible_padbyte, l_int8_const(lc, 0),
550 LLVMBuildCondBr(
b, v_ispad,
556 LLVMBuildBr(
b, attalignblocks[
attnum]);
559 LLVMPositionBuilderAtEnd(
b, attalignblocks[
attnum]);
563 LLVMValueRef v_off_aligned;
564 LLVMValueRef v_off = l_load(
b,
TypeSizeT, v_offp,
"");
567 LLVMValueRef v_alignval = l_sizet_const(alignto - 1);
570 LLVMValueRef v_lh = LLVMBuildAdd(
b, v_off, v_alignval,
"");
573 LLVMValueRef v_rh = l_sizet_const(~(alignto - 1));
575 v_off_aligned = LLVMBuildAnd(
b, v_lh, v_rh,
"aligned_offset");
577 LLVMBuildStore(
b, v_off_aligned, v_offp);
585 if (known_alignment >= 0)
587 Assert(known_alignment != 0);
588 known_alignment =
TYPEALIGN(alignto, known_alignment);
591 LLVMBuildBr(
b, attstoreblocks[
attnum]);
592 LLVMPositionBuilderAtEnd(
b, attstoreblocks[
attnum]);
596 LLVMPositionBuilderAtEnd(
b, attcheckalignblocks[
attnum]);
597 LLVMBuildBr(
b, attalignblocks[
attnum]);
598 LLVMPositionBuilderAtEnd(
b, attalignblocks[
attnum]);
599 LLVMBuildBr(
b, attstoreblocks[
attnum]);
601 LLVMPositionBuilderAtEnd(
b, attstoreblocks[
attnum]);
609 if (attguaranteedalign)
611 Assert(known_alignment >= 0);
612 LLVMBuildStore(
b, l_sizet_const(known_alignment), v_offp);
619 known_alignment = -1;
620 attguaranteedalign =
false;
622 else if (att->attnotnull && attguaranteedalign && known_alignment >= 0)
630 known_alignment += att->attlen;
632 else if (att->attnotnull && (att->attlen % alignto) == 0)
640 known_alignment = alignto;
641 Assert(known_alignment > 0);
642 attguaranteedalign =
false;
646 known_alignment = -1;
647 attguaranteedalign =
false;
653 LLVMValueRef v_off = l_load(
b,
TypeSizeT, v_offp,
"");
656 l_gep(
b, LLVMInt8TypeInContext(lc), v_tupdata_base, &v_off, 1,
"");
660 v_resultp = l_gep(
b,
TypeSizeT, v_tts_values, &l_attno, 1,
"");
663 LLVMBuildStore(
b, l_int8_const(lc, 0),
672 LLVMValueRef v_tmp_loaddata;
673 LLVMTypeRef vartype = LLVMIntTypeInContext(lc, att->attlen * 8);
674 LLVMTypeRef vartypep = LLVMPointerType(vartype, 0);
677 LLVMBuildPointerCast(
b, v_attdatap, vartypep,
"");
678 v_tmp_loaddata = l_load(
b, vartype, v_tmp_loaddata,
"attr_byval");
679 v_tmp_loaddata = LLVMBuildZExt(
b, v_tmp_loaddata,
TypeSizeT,
"");
681 LLVMBuildStore(
b, v_tmp_loaddata, v_resultp);
685 LLVMValueRef v_tmp_loaddata;
693 LLVMBuildStore(
b, v_tmp_loaddata, v_resultp);
699 v_incby = l_sizet_const(att->attlen);
701 else if (att->attlen == -1)
708 l_callsite_ro(v_incby);
709 l_callsite_alwaysinline(v_incby);
711 else if (att->attlen == -2)
716 &v_attdatap, 1,
"strlen");
718 l_callsite_ro(v_incby);
721 v_incby = LLVMBuildAdd(
b, v_incby, l_sizet_const(1),
"");
729 if (attguaranteedalign)
731 Assert(known_alignment >= 0);
732 LLVMBuildStore(
b, l_sizet_const(known_alignment), v_offp);
736 LLVMValueRef v_off = l_load(
b,
TypeSizeT, v_offp,
"");
738 v_off = LLVMBuildAdd(
b, v_off, v_incby,
"increment_offset");
739 LLVMBuildStore(
b, v_off, v_offp);
749 LLVMBuildBr(
b, b_out);
753 LLVMBuildBr(
b, attcheckattnoblocks[
attnum + 1]);
759 LLVMPositionBuilderAtEnd(
b, b_out);
762 LLVMValueRef v_off = l_load(
b,
TypeSizeT, v_offp,
"");
763 LLVMValueRef v_flags;
765 LLVMBuildStore(
b, l_int16_const(lc, natts), v_nvalidp);
766 v_off = LLVMBuildTrunc(
b, v_off, LLVMInt32TypeInContext(lc),
"");
767 LLVMBuildStore(
b, v_off, v_slotoffp);
768 v_flags = l_load(
b, LLVMInt16TypeInContext(lc), v_flagsp,
"tts_flags");
769 v_flags = LLVMBuildOr(
b, v_flags, l_int16_const(lc,
TTS_FLAG_SLOW),
"");
770 LLVMBuildStore(
b, v_flags, v_flagsp);
774 LLVMDisposeBuilder(
b);
#define TYPEALIGN(ALIGNVAL, LEN)
#define Assert(condition)
const TupleTableSlotOps TTSOpsVirtual
const TupleTableSlotOps TTSOpsBufferHeapTuple
const TupleTableSlotOps TTSOpsHeapTuple
const TupleTableSlotOps TTSOpsMinimalTuple
#define FIELDNO_HEAPTUPLEDATA_DATA
#define FIELDNO_HEAPTUPLEHEADERDATA_INFOMASK
#define FIELDNO_HEAPTUPLEHEADERDATA_HOFF
#define FIELDNO_HEAPTUPLEHEADERDATA_BITS
#define FIELDNO_HEAPTUPLEHEADERDATA_INFOMASK2
LLVMTypeRef StructMinimalTupleTableSlot
LLVMValueRef llvm_pg_func(LLVMModuleRef mod, const char *funcname)
char * llvm_expand_funcname(struct LLVMJitContext *context, const char *basename)
LLVMTypeRef llvm_pg_var_func_type(const char *varname)
LLVMTypeRef StructTupleTableSlot
LLVMTypeRef TypeStorageBool
LLVMTypeRef StructHeapTupleTableSlot
LLVMModuleRef llvm_mutable_module(LLVMJitContext *context)
LLVMValueRef AttributeTemplate
LLVMTypeRef StructHeapTupleHeaderData
LLVMTypeRef StructHeapTupleData
void llvm_copy_attributes(LLVMValueRef v_from, LLVMValueRef v_to)
LLVMTypeRef LLVMGetFunctionType(LLVMValueRef r)
FormData_pg_attribute * Form_pg_attribute
#define TupleDescAttr(tupdesc, i)
#define FIELDNO_HEAPTUPLETABLESLOT_OFF
#define FIELDNO_HEAPTUPLETABLESLOT_TUPLE
#define FIELDNO_TUPLETABLESLOT_ISNULL
#define FIELDNO_MINIMALTUPLETABLESLOT_TUPLE
#define FIELDNO_MINIMALTUPLETABLESLOT_OFF
#define FIELDNO_TUPLETABLESLOT_VALUES
#define FIELDNO_TUPLETABLESLOT_FLAGS
#define FIELDNO_TUPLETABLESLOT_NVALID