LCOV - differential code coverage report
Current view: top level - src/backend/jit/llvm - llvmjit_deform.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 94.2 % 225 212 13 212
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 1 1 1
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (240..) days: 94.2 % 225 212 13 212
Legend: Lines: hit not hit Function coverage date bins:
(240..) days: 100.0 % 1 1 1

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

Generated by: LCOV version v1.16-55-g56c0a2a