#!/bin/sh # vim: ts=4 sw=4 et ft=sh # If you change max_spec_explicit_arg, you should consider changing # the value of the max_specialized_do_call_closure option in # compiler/options.m. max_spec_explicit_arg=5 max_spec_hidden_arg=5 variants="" spec_explicit_arg=-1 while test $spec_explicit_arg -le $max_spec_explicit_arg do if test $spec_explicit_arg -lt 0 then variant="compact" else variant="$spec_explicit_arg" fi echo "MR_define_entry(mercury__do_call_closure_$variant);" echo "{" echo " MR_Closure *closure;" echo " int num_explicit_args;" echo " int num_hidden_rf_args;" echo " int num_hidden_r_args;" echo "#ifdef MR_BOXED_FLOAT" echo " int num_explicit_f_args = 0;" echo " int num_hidden_f_args;" echo "#endif" echo " int i;" i=1; while test $i -le $spec_explicit_arg do echo " MR_Word arg$i;" i=`expr $i + 1` done echo echo " closure = (MR_Closure *) MR_r1;" echo " num_hidden_rf_args = closure->MR_closure_num_hidden_args_rf;" echo " num_hidden_r_args = MR_closure_num_hidden_r_args(closure);" echo "#ifdef MR_BOXED_FLOAT" echo " num_hidden_f_args = MR_closure_num_hidden_f_args(closure);" echo "#endif" if test $spec_explicit_arg -lt 0 then echo "#ifdef MR_BOXED_FLOAT" echo " num_explicit_args = (MR_r2 & 0xffff);" echo " num_explicit_f_args = (MR_r2 >> 16);" echo "#else" echo " num_explicit_args = MR_r2;" echo "#endif" num_explicit_args="num_explicit_args" else i=1; while test $i -le $spec_explicit_arg do j=`expr $i + 1` echo " arg$i = MR_r$j;" i=`expr $i + 1` done num_explicit_args="$spec_explicit_arg" fi echo echo " MR_maybe_record_closure_histogram($num_explicit_args, num_hidden_r_args);" echo if test $max_spec_hidden_arg -ge 0 -a $spec_explicit_arg -ge 0 then echo " switch (num_hidden_rf_args) {" spec_hidden_arg=0 while test $spec_hidden_arg -le $max_spec_hidden_arg do echo " case $spec_hidden_arg:" i=1; while test $i -le $spec_hidden_arg do echo " MR_r$i = closure->MR_closure_hidden_args($i);" i=`expr $i + 1` done j=1 while test $j -le $spec_explicit_arg do echo " MR_r$i = arg$j;" i=`expr $i + 1` j=`expr $j + 1` done echo " MR_tailcall(closure->MR_closure_code, MR_prof_ho_caller_proc);" echo " break;" echo spec_hidden_arg=`expr $spec_hidden_arg + 1` done echo " default:" echo " // Fall through to the general case below." echo " break;" echo " }" echo fi echo " MR_save_registers();" if test $spec_explicit_arg -lt 0 then echo " if (num_hidden_r_args < MR_HO_CALL_INPUTS_COMPACT) {" echo " // Copy the explicit args to the left, from the left." echo " for (i = 1; i <= num_explicit_args; i++) {" echo " MR_virtual_reg_assign(i + num_hidden_r_args," echo " MR_virtual_reg_value(i + MR_HO_CALL_INPUTS_COMPACT));" echo " }" echo " } else if (num_hidden_r_args > MR_HO_CALL_INPUTS_COMPACT) {" echo " // Copy the explicit args to the right, from the right." echo " for (i = num_explicit_args; i > 0 ; i--) {" echo " MR_virtual_reg_assign(i + num_hidden_r_args," echo " MR_virtual_reg_value(i + MR_HO_CALL_INPUTS_COMPACT));" echo " }" echo " } // else The explicit args are in the right place." else i=1 while test $i -le $spec_explicit_arg do echo " MR_virtual_reg_assign(num_hidden_r_args + $i, arg$i);" i=`expr $i + 1` done fi echo echo " for (i = 1; i <= num_hidden_r_args; i++) {" echo " MR_virtual_reg_assign(i, closure->MR_closure_hidden_args(i));" echo " }" echo " MR_restore_registers();" echo echo "#ifdef MR_BOXED_FLOAT" echo " if (num_hidden_f_args > 0) {" echo " // Copy the explicit args to the right, from the right." echo " for (i = num_explicit_f_args; i > 0 ; i--) {" echo " MR_f(i + num_hidden_f_args) = MR_f(i);" echo " }" echo " for (i = 1; i <= num_hidden_f_args; i++) {" echo " MR_f(i) = MR_word_to_float(" echo " closure->MR_closure_hidden_args(" echo " num_hidden_r_args + i));" echo " }" echo " }" echo "#endif" echo echo " MR_tailcall(closure->MR_closure_code, MR_prof_ho_caller_proc);" echo "}" echo variants="$variants $variant" # On some systems, e.g. FreeBSD, expr will treat a leading argument # beginning with a minus sign as an option to the program rather than # as a negative number. Since the value of $spec_explicit_arg may be # negative we arrange the arguments in the following so that first # argument position is occupied by a positive number. # spec_explicit_arg=`expr 1 + $spec_explicit_arg` done # Create these files atomically. { for variant in $variants do echo "MR_define_extern_entry(mercury__do_call_closure_$variant);" done } > mercury_ho_call_declares.i { for variant in $variants do echo " MR_init_entry_an(mercury__do_call_closure_$variant);" done } > mercury_ho_call_inits.i