PreviousUpNext

15.4.294  src/lib/compiler/back/low/main/nextcode/convert-nextcode-fun-args-to-treecode-g.pkg

## convert-nextcode-fun-args-to-treecode-g.pkg --- parameter passing convention for standard    and known functions.

# Compiled by:
#     src/lib/compiler/core.sublib


###               "Thomas Godfrey, a self-taught mathematician,
###                great in his way . . .  knew little out of
###                his way, and was not a pleasing companion;
###                as, like most great mathematicians I have met with,
###                he expected universal precision in everything said,
###                or was forever denying or distinguishing upon trifles,
###                to the disturbance of all conversation."
###
###                        -- Benjamin Franklin (1706-1790), Autobiography

# We are invoked from:
#
#     src/lib/compiler/back/low/main/main/translate-nextcode-to-treecode-g.pkg

                                                                                # Machine_Properties                    is from   src/lib/compiler/back/low/main/main/machine-properties.api
stipulate
    package err =  error_message;                                               # error_message                         is from   src/lib/compiler/front/basics/errormsg/error-message.pkg
    package ncf =  nextcode_form;                                               # nextcode_form                         is from   src/lib/compiler/back/top/nextcode/nextcode-form.pkg
herein

    # This generic is invoked (only) in:
    #
    #     src/lib/compiler/back/low/main/main/translate-nextcode-to-treecode-g.pkg
    #
    generic package   convert_nextcode_fun_args_to_treecode_g   (
        #             =======================================
        #
        package pri:    Platform_Register_Info;                                 # Platform_Register_Info                is from   src/lib/compiler/back/low/main/nextcode/platform-register-info.api
                                                                                # platform_register_info_intel32        is from   src/lib/compiler/back/low/main/intel32/backend-lowhalf-intel32-g.pkg
                                                                                # platform_register_info_pwrpw32        is from   src/lib/compiler/back/low/main/pwrpc32/backend-lowhalf-pwrpc32.pkg
                                                                                # platform_register_info_sparc32        is from   src/lib/compiler/back/low/main/sparc32/backend-lowhalf-sparc32.pkg

                                                                                # machine_properties_intel32            is from   src/lib/compiler/back/low/main/intel32/machine-properties-intel32.pkg
        package mp:     Machine_Properties;                                     # Machine_Properties                    is from   src/lib/compiler/back/low/main/main/machine-properties.api
    )
    : (weak) Convert_Nextcode_Fun_Args_To_Treecode                              # Convert_Nextcode_Fun_Args_To_Treecode is from   src/lib/compiler/back/low/main/nextcode/convert-nextcode-fun-args-to-treecode.api
    {
        # Export to client packages:
        #
        package tcf = pri::tcf;                                                 # "tcf" == "treecode_form".

        stipulate
            fun error msg
                =
                err::impossible ("ArgPassing." + msg);

            fun stdlink use_virtual_framepointer =    tcf::INT_EXPRESSION (pri::stdlink  use_virtual_framepointer);
            fun stdclos use_virtual_framepointer =    tcf::INT_EXPRESSION (pri::stdclos  use_virtual_framepointer);
            fun stdarg  use_virtual_framepointer =    tcf::INT_EXPRESSION (pri::stdarg   use_virtual_framepointer);
            fun stdfate use_virtual_framepointer =    tcf::INT_EXPRESSION (pri::stdfate  use_virtual_framepointer);

            fun gpregs  use_virtual_framepointer
                #
                = stdlink  use_virtual_framepointer                             # vreg 0  on  Intel32.
                ! stdclos  use_virtual_framepointer                             # vreg 1  on  Intel32.
                ! stdarg   use_virtual_framepointer                             # epb     on  Intel32.
                ! stdfate  use_virtual_framepointer                             # esi     on  Intel32.
                ! map tcf::INT_EXPRESSION pri::miscregs                         # On Intel32, miscregs = { ebx, ecx, edx, r10, r11, ... r31 } 
                ;

            fpregs
               =
               map   tcf::FLOAT_EXPRESSION   (pri::savedfpregs @ pri::floatregs);

            fun fromto (i, j, regs)                                             #   fromto(i,j,[x0,x1,...xn])  returns [xi,...,xj] (or [xi,...xn] if n<j).
                =
                to (i, from (i, regs))
                where
                    fun from (0,     xs) =>   xs;                               #   from(i,list)   drops first 'i' elements from list and returns the rest -- error if not enough elements to do so.
                        from (n, x ! xs) =>   from (n - 1, xs);
                        from (n, []    ) =>   error "fromto";
                    end;

                    fun to (k, r ! rs) =>   if (k <= j)   r ! to (k+1, rs);     #   to(k,list)     returns first j-k elements from list, or as many as possible
                                            else          [];
                                            fi;
                        to (k, []    ) =>   [];
                    end;
                end;

            fun gprfromto (i, j, use_virtual_framepointer) =   fromto (i, j, gpregs  use_virtual_framepointer);
            fun fprfromto (i, j, use_virtual_framepointer) =   fromto (i, j, fpregs);

            fun calleesaveregs  use_virtual_framepointer
                =
                gprfromto (4,   mp::num_callee_saves       + 3,   use_virtual_framepointer)   @
                fprfromto (0,   mp::num_float_callee_saves - 1,   use_virtual_framepointer);


            fun drop_first_n_from_list (n, l)                                   # This looks identical to from() above, up to error text.
                = 
                if (n == 0)
                    #   
                    l;
                else
                    case l
                        #
                        a ! r =>   drop_first_n_from_list (n - 1, r);
                        _     =>   error "coder cuthead 444";
                    esac;
                fi;


            stipulate
                fun is_float  ncf::typ::FLOAT64 =>   TRUE;
                    is_float  _                 =>   FALSE;
                end;
            herein

                fun scan (t ! z, gp, fp)
                        =>
                        if (is_float t)   (head fp) ! (scan (z, gp, tail fp)); 
                        else              (head gp) ! (scan (z, tail gp, fp));
                        fi;

                    scan ([], _, _)
                        =>
                        [];
                end;
            end;

            fun standard_escape (use_virtual_framepointer, args)                                                                                        # Used whenever ncftype_for_fun != ncf::typ::FATE
                =
                {   rest =   drop_first_n_from_list (mp::num_callee_saves + mp::num_float_callee_saves + 3, args);
                    len  =   length args;

                    gpr  =   stdarg use_virtual_framepointer
                         !   gprfromto (mp::num_callee_saves+4, len, use_virtual_framepointer)
                         ;

                    fpr  =   fprfromto (mp::num_float_callee_saves, len, use_virtual_framepointer);

                      stdlink         use_virtual_framepointer
                    ! stdclos         use_virtual_framepointer
                    ! stdfate         use_virtual_framepointer
                    ! calleesaveregs  use_virtual_framepointer
                    @ scan (rest, gpr, fpr)
                    ;
                };


            fun standard_cont (use_virtual_framepointer, args)                                                                                          # Used (only) when ncftype_for_fun == ncf::typ::FATE
                =
                {   rest =   if (mp::num_callee_saves > 0)   drop_first_n_from_list (mp::num_callee_saves + mp::num_float_callee_saves + 1, args);
                             else                            drop_first_n_from_list (                                                    2, args);
                             fi;

                    len  =   length args;
                    gpr  =   stdarg  use_virtual_framepointer   !   gprfromto (mp::num_callee_saves+4, 1+len, use_virtual_framepointer);
                    fpr  =   fprfromto (mp::num_float_callee_saves, len, use_virtual_framepointer);

                    if (mp::num_callee_saves > 0)  stdfate  use_virtual_framepointer ! (calleesaveregs  use_virtual_framepointer @ scan (rest, gpr, fpr));
                    else                           stdlink  use_virtual_framepointer ! (stdfate         use_virtual_framepointer ! scan (rest, gpr, fpr));
                    fi;
                };


        herein

            # This fun is called (only) from:
            #
            #     src/lib/compiler/back/low/main/main/translate-nextcode-to-treecode-g.pkg
            #
            fun convert_nextcode_public_fun_args_to_treecode { use_virtual_framepointer, ncftypes_for_args, ncftype_for_fun => ncf::typ::FATE }         # This is one of our two external entrypoints.
                    =>
                    standard_cont   (use_virtual_framepointer, ncftypes_for_args);

                convert_nextcode_public_fun_args_to_treecode { use_virtual_framepointer, ncftypes_for_args, ... }                                       # Empirically, ncftype_for_fun is either FUN or (POINTER VPT) here.
                    =>
                    standard_escape (use_virtual_framepointer, ncftypes_for_args);
            end;


            # Use an arbitrary but fixed set of registers.
            #
            # This fun is called (only) from:
            #
            #     src/lib/compiler/back/low/main/main/translate-nextcode-to-treecode-g.pkg
            #
            fun convert_fixed_nextcode_fun_args_to_treecode { use_virtual_framepointer, ncftypes_for_args }                                             # This is the other of our two external entrypoints.
                =
                iter (ncftypes_for_args, gpregs use_virtual_framepointer, fpregs)
                where 
                    fun iter (ncf::typ::FLOAT64 ! rest, regs, f ! fregs)
                            =>
                            f ! iter (rest, regs, fregs);

                        iter (_ ! rest, r ! regs, fregs)
                             =>
                             r ! iter (rest, regs, fregs);

                        iter ([], _, _)
                            =>
                            [];

                        iter _
                            =>
                            error "fixed: out of registers";
                    end;
                end;
        end;                                                                                            # stipulate
    };                                                                                                  # generic package   convert_nextcode_fun_args_to_treecode_g
end;                                                                                                    # stipulate


## COPYRIGHT (c) 1996 AT&T Bell Laboratories.
## Subsequent changes by Jeff Prothero Copyright (c) 2010-2015,
## released per terms of SMLNJ-COPYRIGHT.


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext