2121#include <llvm-c/Core.h>
2222
2323#include "access/htup_details.h"
24+ #include "access/tupdesc_details.h"
2425#include "executor/tuptable.h"
2526#include "jit/llvmjit.h"
2627#include "jit/llvmjit_emit.h"
2728
2829
29- static LLVMValueRef get_memset (LLVMModuleRef mod );
30-
31-
3230/*
3331 * Create a function that deforms a tuple of type desc up to natts columns.
3432 */
@@ -100,10 +98,23 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts)
10098 */
10199 for (attnum = 0 ; attnum < desc -> natts ; attnum ++ )
102100 {
103- if (TupleDescAttr (desc , attnum )-> attnotnull )
104- {
101+ Form_pg_attribute att = TupleDescAttr (desc , attnum );
102+
103+ /*
104+ * If the column is possibly missing, we can't rely on its (or
105+ * subsequent) NOT NULL constraints to indicate minimum attributes in
106+ * the tuple, so stop here.
107+ */
108+ if (att -> atthasmissing )
109+ break ;
110+
111+ /*
112+ * Column is NOT NULL and there've been no preceding missing columns,
113+ * it's guaranteed that all columns up to here exist at least in the
114+ * NULL bitmap.
115+ */
116+ if (att -> attnotnull )
105117 guaranteed_column_number = attnum ;
106- }
107118 }
108119
109120 /* Create the signature and function */
@@ -242,9 +253,8 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts)
242253
243254 /*
244255 * Check if's guaranteed the all the desired attributes are available in
245- * tuple. If so, we can start deforming. If not, need to make sure
246- * tts_values/isnull is set appropriately for columns not available in the
247- * tuple.
256+ * tuple. If so, we can start deforming. If not, need to make sure to
257+ * fetch the missing columns.
248258 */
249259 if ((natts - 1 ) <= guaranteed_column_number )
250260 {
@@ -255,9 +265,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts)
255265 }
256266 else
257267 {
258- LLVMValueRef v_set ;
259- LLVMValueRef v_startset ;
260- LLVMValueRef v_params [5 ];
268+ LLVMValueRef v_params [3 ];
261269
262270 /* branch if not all columns available */
263271 LLVMBuildCondBr (b ,
@@ -271,19 +279,10 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts)
271279 /* if not, memset tts_isnull of relevant cols to true */
272280 LLVMPositionBuilderAtEnd (b , b_adjust_unavail_cols );
273281
274- v_set = LLVMBuildSub (b ,
275- l_int16_const (attnum ),
276- v_maxatt , "" );
277-
278- v_startset = LLVMBuildGEP (b , v_tts_nulls , & v_maxatt , 1 , "" );
279-
280- v_params [0 ] = v_startset ;
281- v_params [1 ] = l_int8_const (1 );
282- v_params [2 ] = LLVMBuildZExt (b , v_set , LLVMInt32Type (), "" );
283- v_params [3 ] = l_int32_const (1 );
284- v_params [4 ] = LLVMConstInt (LLVMInt1Type (), 0 , false);
285-
286- LLVMBuildCall (b , get_memset (mod ),
282+ v_params [0 ] = v_slot ;
283+ v_params [1 ] = LLVMBuildZExt (b , v_maxatt , LLVMInt32Type (), "" );
284+ v_params [2 ] = l_int32_const (natts );
285+ LLVMBuildCall (b , llvm_get_decl (mod , FuncSlotGetmissingattrs ),
287286 v_params , lengthof (v_params ), "" );
288287 LLVMBuildBr (b , b_find_start );
289288 }
@@ -358,15 +357,19 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts)
358357 {
359358 LLVMValueRef v_islast ;
360359
361- v_islast = LLVMBuildICmp (b , LLVMIntEQ ,
360+ v_islast = LLVMBuildICmp (b , LLVMIntUGE ,
362361 l_attno ,
363362 v_maxatt ,
364363 "heap_natts" );
365364 LLVMBuildCondBr (b , v_islast , b_out , attstartblocks [attnum ]);
366365 }
367366 LLVMPositionBuilderAtEnd (b , attstartblocks [attnum ]);
368367
369- /* check for nulls if necessary */
368+ /*
369+ * Check for nulls if necessary. No need to take missing attributes
370+ * into account, because in case they're present the heaptuple's natts
371+ * would have indicated that a slot_getmissingattrs() is needed.
372+ */
370373 if (!att -> attnotnull )
371374 {
372375 LLVMBasicBlockRef b_ifnotnull ;
@@ -699,31 +702,3 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts)
699702
700703 return v_deform_fn ;
701704}
702-
703- static LLVMValueRef
704- get_memset (LLVMModuleRef mod )
705- {
706- LLVMTypeRef sig ;
707- LLVMValueRef v_fn ;
708- LLVMTypeRef param_types [5 ];
709- const char * nm = "llvm.memset.p0i8.i32" ;
710-
711- v_fn = LLVMGetNamedFunction (mod , nm );
712- if (v_fn )
713- return v_fn ;
714-
715- param_types [0 ] = LLVMPointerType (LLVMInt8Type (), 0 ); /* addr */
716- param_types [1 ] = LLVMInt8Type (); /* val */
717- param_types [2 ] = LLVMInt32Type (); /* len */
718- param_types [3 ] = LLVMInt32Type (); /* align */
719- param_types [4 ] = LLVMInt1Type (); /* volatile */
720-
721- sig = LLVMFunctionType (LLVMVoidType (), param_types , lengthof (param_types ), 0 );
722- v_fn = LLVMAddFunction (mod , nm , sig );
723-
724- LLVMSetFunctionCallConv (v_fn , LLVMCCallConv );
725-
726- Assert (LLVMGetIntrinsicID (v_fn ));
727-
728- return v_fn ;
729- }
0 commit comments