@@ -471,6 +471,7 @@ llvm_compile_expr(ExprState *state)
471471 }
472472
473473 case EEOP_ASSIGN_TMP :
474+ case EEOP_ASSIGN_TMP_MAKE_RO :
474475 {
475476 LLVMValueRef v_value ,
476477 v_isnull ;
@@ -490,59 +491,40 @@ llvm_compile_expr(ExprState *state)
490491 v_risnullp =
491492 LLVMBuildGEP (b , v_resultnulls , & v_resultnum , 1 , "" );
492493
493- /* and store */
494- LLVMBuildStore (b , v_value , v_rvaluep );
494+ /* store nullness */
495495 LLVMBuildStore (b , v_isnull , v_risnullp );
496496
497- LLVMBuildBr (b , opblocks [opno + 1 ]);
498- break ;
499- }
500-
501- case EEOP_ASSIGN_TMP_MAKE_RO :
502- {
503- LLVMBasicBlockRef b_notnull ;
504- LLVMValueRef v_params [1 ];
505- LLVMValueRef v_ret ;
506- LLVMValueRef v_value ,
507- v_isnull ;
508- LLVMValueRef v_rvaluep ,
509- v_risnullp ;
510- LLVMValueRef v_resultnum ;
511- size_t resultnum = op -> d .assign_tmp .resultnum ;
512-
513- b_notnull = l_bb_before_v (opblocks [opno + 1 ],
514- "op.%d.assign_tmp.notnull" , opno );
515-
516- /* load data */
517- v_value = LLVMBuildLoad (b , v_tmpvaluep , "" );
518- v_isnull = LLVMBuildLoad (b , v_tmpisnullp , "" );
519-
520- /* compute addresses of targets */
521- v_resultnum = l_int32_const (resultnum );
522- v_rvaluep = LLVMBuildGEP (b , v_resultvalues ,
523- & v_resultnum , 1 , "" );
524- v_risnullp = LLVMBuildGEP (b , v_resultnulls ,
525- & v_resultnum , 1 , "" );
497+ /* make value readonly if necessary */
498+ if (opcode == EEOP_ASSIGN_TMP_MAKE_RO )
499+ {
500+ LLVMBasicBlockRef b_notnull ;
501+ LLVMValueRef v_params [1 ];
526502
527- /* store nullness */
528- LLVMBuildStore ( b , v_isnull , v_risnullp );
503+ b_notnull = l_bb_before_v ( opblocks [ opno + 1 ],
504+ "op.%d.assign_tmp.notnull" , opno );
529505
530- /* check if value is NULL */
531- LLVMBuildCondBr (b ,
532- LLVMBuildICmp (b , LLVMIntEQ , v_isnull ,
533- l_sbool_const (0 ), "" ),
534- b_notnull , opblocks [opno + 1 ]);
506+ /* check if value is NULL */
507+ LLVMBuildCondBr (b ,
508+ LLVMBuildICmp (b , LLVMIntEQ , v_isnull ,
509+ l_sbool_const (0 ), "" ),
510+ b_notnull , opblocks [opno + 1 ]);
511+
512+ /* if value is not null, convert to RO datum */
513+ LLVMPositionBuilderAtEnd (b , b_notnull );
514+ v_params [0 ] = v_value ;
515+ v_value =
516+ LLVMBuildCall (b ,
517+ llvm_get_decl (mod , FuncMakeExpandedObjectReadOnlyInternal ),
518+ v_params , lengthof (v_params ), "" );
535519
536- /* if value is not null, convert to RO datum */
537- LLVMPositionBuilderAtEnd (b , b_notnull );
538- v_params [0 ] = v_value ;
539- v_ret =
540- LLVMBuildCall (b ,
541- llvm_get_decl (mod , FuncMakeExpandedObjectReadOnlyInternal ),
542- v_params , lengthof (v_params ), "" );
520+ /*
521+ * Falling out of the if () with builder in b_notnull,
522+ * which is fine - the null is already stored above.
523+ */
524+ }
543525
544- /* store value */
545- LLVMBuildStore (b , v_ret , v_rvaluep );
526+ /* and finally store result */
527+ LLVMBuildStore (b , v_value , v_rvaluep );
546528
547529 LLVMBuildBr (b , opblocks [opno + 1 ]);
548530 break ;
@@ -563,78 +545,81 @@ llvm_compile_expr(ExprState *state)
563545 break ;
564546 }
565547
548+ case EEOP_FUNCEXPR :
566549 case EEOP_FUNCEXPR_STRICT :
567550 {
568551 FunctionCallInfo fcinfo = op -> d .func .fcinfo_data ;
569- LLVMBasicBlockRef b_nonull ;
570- LLVMValueRef v_fcinfo ;
571- LLVMBasicBlockRef * b_checkargnulls ;
572-
573- /*
574- * Block for the actual function call, if args are
575- * non-NULL.
576- */
577- b_nonull = l_bb_before_v (opblocks [opno + 1 ],
578- "b.%d.no-null-args" , opno );
552+ LLVMValueRef v_fcinfo_isnull ;
553+ LLVMValueRef v_retval ;
579554
580- /* should make sure they're optimized beforehand */
581- if (op -> d .func .nargs == 0 )
582- elog (ERROR , "argumentless strict functions are pointless" );
555+ if (opcode == EEOP_FUNCEXPR_STRICT )
556+ {
557+ LLVMBasicBlockRef b_nonull ;
558+ LLVMBasicBlockRef * b_checkargnulls ;
559+ LLVMValueRef v_fcinfo ;
583560
584- v_fcinfo =
585- l_ptr_const (fcinfo , l_ptr (StructFunctionCallInfoData ));
561+ /*
562+ * Block for the actual function call, if args are
563+ * non-NULL.
564+ */
565+ b_nonull = l_bb_before_v (opblocks [opno + 1 ],
566+ "b.%d.no-null-args" , opno );
586567
587- /*
588- * set resnull to true, if the function is actually
589- * called, it'll be reset
590- */
591- LLVMBuildStore (b , l_sbool_const (1 ), v_resnullp );
568+ /* should make sure they're optimized beforehand */
569+ if (op -> d .func .nargs == 0 )
570+ elog (ERROR , "argumentless strict functions are pointless" );
592571
593- /* create blocks for checking args, one for each */
594- b_checkargnulls =
595- palloc (sizeof (LLVMBasicBlockRef * ) * op -> d .func .nargs );
596- for (int argno = 0 ; argno < op -> d .func .nargs ; argno ++ )
597- b_checkargnulls [argno ] =
598- l_bb_before_v (b_nonull , "b.%d.isnull.%d" , opno , argno );
572+ v_fcinfo =
573+ l_ptr_const (fcinfo , l_ptr (StructFunctionCallInfoData ));
599574
600- /* jump to check of first argument */
601- LLVMBuildBr (b , b_checkargnulls [0 ]);
575+ /*
576+ * set resnull to true, if the function is actually
577+ * called, it'll be reset
578+ */
579+ LLVMBuildStore (b , l_sbool_const (1 ), v_resnullp );
602580
603- /* check each arg for NULLness */
604- for (int argno = 0 ; argno < op -> d .func .nargs ; argno ++ )
605- {
606- LLVMValueRef v_argisnull ;
607- LLVMBasicBlockRef b_argnotnull ;
581+ /* create blocks for checking args, one for each */
582+ b_checkargnulls =
583+ palloc (sizeof (LLVMBasicBlockRef * ) * op -> d .func .nargs );
584+ for (int argno = 0 ; argno < op -> d .func .nargs ; argno ++ )
585+ b_checkargnulls [argno ] =
586+ l_bb_before_v (b_nonull , "b.%d.isnull.%d" , opno ,
587+ argno );
608588
609- LLVMPositionBuilderAtEnd (b , b_checkargnulls [argno ]);
589+ /* jump to check of first argument */
590+ LLVMBuildBr (b , b_checkargnulls [0 ]);
610591
611- /* compute block to jump to if argument is not null */
612- if (argno + 1 == op -> d .func .nargs )
613- b_argnotnull = b_nonull ;
614- else
615- b_argnotnull = b_checkargnulls [argno + 1 ];
592+ /* check each arg for NULLness */
593+ for (int argno = 0 ; argno < op -> d .func .nargs ; argno ++ )
594+ {
595+ LLVMValueRef v_argisnull ;
596+ LLVMBasicBlockRef b_argnotnull ;
597+
598+ LLVMPositionBuilderAtEnd (b , b_checkargnulls [argno ]);
599+
600+ /*
601+ * Compute block to jump to if argument is not
602+ * null.
603+ */
604+ if (argno + 1 == op -> d .func .nargs )
605+ b_argnotnull = b_nonull ;
606+ else
607+ b_argnotnull = b_checkargnulls [argno + 1 ];
608+
609+ /* and finally load & check NULLness of arg */
610+ v_argisnull = l_funcnull (b , v_fcinfo , argno );
611+ LLVMBuildCondBr (b ,
612+ LLVMBuildICmp (b , LLVMIntEQ ,
613+ v_argisnull ,
614+ l_sbool_const (1 ),
615+ "" ),
616+ opblocks [opno + 1 ],
617+ b_argnotnull );
618+ }
616619
617- /* and finally load & check NULLness of arg */
618- v_argisnull = l_funcnull (b , v_fcinfo , argno );
619- LLVMBuildCondBr (b ,
620- LLVMBuildICmp (b , LLVMIntEQ ,
621- v_argisnull ,
622- l_sbool_const (1 ),
623- "" ),
624- opblocks [opno + 1 ],
625- b_argnotnull );
620+ LLVMPositionBuilderAtEnd (b , b_nonull );
626621 }
627622
628- LLVMPositionBuilderAtEnd (b , b_nonull );
629- }
630- /* FALLTHROUGH */
631-
632- case EEOP_FUNCEXPR :
633- {
634- FunctionCallInfo fcinfo = op -> d .func .fcinfo_data ;
635- LLVMValueRef v_fcinfo_isnull ;
636- LLVMValueRef v_retval ;
637-
638623 v_retval = BuildV1Call (context , b , mod , fcinfo ,
639624 & v_fcinfo_isnull );
640625 LLVMBuildStore (b , v_retval , v_resvaluep );
@@ -657,24 +642,14 @@ llvm_compile_expr(ExprState *state)
657642 LLVMBuildBr (b , opblocks [opno + 1 ]);
658643 break ;
659644
660- case EEOP_BOOL_AND_STEP_FIRST :
661- {
662- LLVMValueRef v_boolanynullp ;
663-
664- v_boolanynullp = l_ptr_const (op -> d .boolexpr .anynull ,
665- l_ptr (TypeStorageBool ));
666- LLVMBuildStore (b , l_sbool_const (0 ), v_boolanynullp );
667-
668- }
669- /* FALLTHROUGH */
670-
671645 /*
672646 * Treat them the same for now, optimizer can remove
673647 * redundancy. Could be worthwhile to optimize during emission
674648 * though.
675649 */
676- case EEOP_BOOL_AND_STEP_LAST :
650+ case EEOP_BOOL_AND_STEP_FIRST :
677651 case EEOP_BOOL_AND_STEP :
652+ case EEOP_BOOL_AND_STEP_LAST :
678653 {
679654 LLVMValueRef v_boolvalue ;
680655 LLVMValueRef v_boolnull ;
@@ -700,6 +675,9 @@ llvm_compile_expr(ExprState *state)
700675 v_boolanynullp = l_ptr_const (op -> d .boolexpr .anynull ,
701676 l_ptr (TypeStorageBool ));
702677
678+ if (opcode == EEOP_BOOL_AND_STEP_FIRST )
679+ LLVMBuildStore (b , l_sbool_const (0 ), v_boolanynullp );
680+
703681 v_boolnull = LLVMBuildLoad (b , v_resnullp , "" );
704682 v_boolvalue = LLVMBuildLoad (b , v_resvaluep , "" );
705683
@@ -759,23 +737,15 @@ llvm_compile_expr(ExprState *state)
759737 LLVMBuildBr (b , opblocks [opno + 1 ]);
760738 break ;
761739 }
762- case EEOP_BOOL_OR_STEP_FIRST :
763- {
764- LLVMValueRef v_boolanynullp ;
765-
766- v_boolanynullp = l_ptr_const (op -> d .boolexpr .anynull ,
767- l_ptr (TypeStorageBool ));
768- LLVMBuildStore (b , l_sbool_const (0 ), v_boolanynullp );
769- }
770- /* FALLTHROUGH */
771740
772741 /*
773742 * Treat them the same for now, optimizer can remove
774743 * redundancy. Could be worthwhile to optimize during emission
775744 * though.
776745 */
777- case EEOP_BOOL_OR_STEP_LAST :
746+ case EEOP_BOOL_OR_STEP_FIRST :
778747 case EEOP_BOOL_OR_STEP :
748+ case EEOP_BOOL_OR_STEP_LAST :
779749 {
780750 LLVMValueRef v_boolvalue ;
781751 LLVMValueRef v_boolnull ;
@@ -802,6 +772,8 @@ llvm_compile_expr(ExprState *state)
802772 v_boolanynullp = l_ptr_const (op -> d .boolexpr .anynull ,
803773 l_ptr (TypeStorageBool ));
804774
775+ if (opcode == EEOP_BOOL_OR_STEP_FIRST )
776+ LLVMBuildStore (b , l_sbool_const (0 ), v_boolanynullp );
805777 v_boolnull = LLVMBuildLoad (b , v_resnullp , "" );
806778 v_boolvalue = LLVMBuildLoad (b , v_resvaluep , "" );
807779
@@ -1958,41 +1930,40 @@ llvm_compile_expr(ExprState *state)
19581930 break ;
19591931
19601932 case EEOP_AGG_STRICT_DESERIALIZE :
1961- {
1962- FunctionCallInfo fcinfo = op -> d .agg_deserialize .fcinfo_data ;
1963- LLVMValueRef v_fcinfo ;
1964- LLVMValueRef v_argnull0 ;
1965- LLVMBasicBlockRef b_deserialize ;
1966-
1967- b_deserialize = l_bb_before_v (opblocks [opno + 1 ],
1968- "op.%d.deserialize" , opno );
1969-
1970- v_fcinfo = l_ptr_const (fcinfo ,
1971- l_ptr (StructFunctionCallInfoData ));
1972- v_argnull0 = l_funcnull (b , v_fcinfo , 0 );
1973-
1974- LLVMBuildCondBr (b ,
1975- LLVMBuildICmp (b ,
1976- LLVMIntEQ ,
1977- v_argnull0 ,
1978- l_sbool_const (1 ),
1979- "" ),
1980- opblocks [op -> d .agg_deserialize .jumpnull ],
1981- b_deserialize );
1982- LLVMPositionBuilderAtEnd (b , b_deserialize );
1983- }
1984- /* FALLTHROUGH */
1985-
19861933 case EEOP_AGG_DESERIALIZE :
19871934 {
19881935 AggState * aggstate ;
1989- FunctionCallInfo fcinfo ;
1936+ FunctionCallInfo fcinfo = op -> d . agg_deserialize . fcinfo_data ;
19901937
19911938 LLVMValueRef v_retval ;
19921939 LLVMValueRef v_fcinfo_isnull ;
19931940 LLVMValueRef v_tmpcontext ;
19941941 LLVMValueRef v_oldcontext ;
19951942
1943+ if (opcode == EEOP_AGG_STRICT_DESERIALIZE )
1944+ {
1945+ LLVMValueRef v_fcinfo ;
1946+ LLVMValueRef v_argnull0 ;
1947+ LLVMBasicBlockRef b_deserialize ;
1948+
1949+ b_deserialize = l_bb_before_v (opblocks [opno + 1 ],
1950+ "op.%d.deserialize" , opno );
1951+
1952+ v_fcinfo = l_ptr_const (fcinfo ,
1953+ l_ptr (StructFunctionCallInfoData ));
1954+ v_argnull0 = l_funcnull (b , v_fcinfo , 0 );
1955+
1956+ LLVMBuildCondBr (b ,
1957+ LLVMBuildICmp (b ,
1958+ LLVMIntEQ ,
1959+ v_argnull0 ,
1960+ l_sbool_const (1 ),
1961+ "" ),
1962+ opblocks [op -> d .agg_deserialize .jumpnull ],
1963+ b_deserialize );
1964+ LLVMPositionBuilderAtEnd (b , b_deserialize );
1965+ }
1966+
19961967 aggstate = castNode (AggState , state -> parent );
19971968 fcinfo = op -> d .agg_deserialize .fcinfo_data ;
19981969
0 commit comments