PreviousUpNext

15.4.310  src/lib/compiler/back/low/main/pwrpc32/backend-lowhalf-pwrpc32.pkg

## backend-lowhalf-pwrpc32.pkg
#
# PowerPC-specific backend

# Compiled by:
#     src/lib/compiler/mythryl-compiler-support-for-pwrpc32.lib

stipulate
    package irc =  iterated_register_coalescing;                                # iterated_register_coalescing                  is from   src/lib/compiler/back/low/regor/iterated-register-coalescing.pkg
    package lem =  lowhalf_error_message;                                       # lowhalf_error_message                         is from   src/lib/compiler/back/low/control/lowhalf-error-message.pkg
    package cig =  codetemp_interference_graph;                                 # codetemp_interference_graph                   is from   src/lib/compiler/back/low/regor/codetemp-interference-graph.pkg
    package sma =  supported_architectures;                                     # supported_architectures                       is from   src/lib/compiler/front/basics/main/supported-architectures.pkg

    package treecode_form_pwrpc32
         =  treecode_form_g (                                                   # treecode_form_g                               is from   src/lib/compiler/back/low/treecode/treecode-form-g.pkg
                #
                package lac =  late_constant;                                   # late_constant                                 is from   src/lib/compiler/back/low/main/nextcode/late-constant.pkg
                package rgn =  nextcode_ramregions;                             # nextcode_ramregions                           is from   src/lib/compiler/back/low/main/nextcode/nextcode-ramregions.pkg
                package trx =  treecode_extension_mythryl;                      # treecode_extension_mythryl                    is from   src/lib/compiler/back/low/main/nextcode/treecode-extension-mythryl.pkg
            );

    package treecode_eval_pwrpc32
          = treecode_eval_g (                                                   # treecode_eval_g                               is from   src/lib/compiler/back/low/treecode/treecode-eval-g.pkg
                #
                package tcf =  treecode_form_pwrpc32;
                #
                fun eq _ _ =  FALSE;
                #
                eq_rext = eq;
                eq_fext = eq;
                eq_ccext = eq;
                eq_sext = eq;
            );

    package treecode_hash_pwrpc32
          = treecode_hash_g (                                                   # treecode_hash_g                               is from   src/lib/compiler/back/low/treecode/treecode-hash-g.pkg
                #
                package tcf =  treecode_form_pwrpc32;
                #
                fun h _ _ = 0u0;
                #
                hash_rext = h;  hash_fext = h;
                hash_ccext = h;       hash_sext = h;
            );

    package gas_pseudo_ops_pwrpc32
          = gas_pseudo_ops_pwrpc32_g (
                #
                package tcf =  treecode_form_pwrpc32;
                package tce =  treecode_eval_pwrpc32;
            );

    package client_pseudo_ops_pwrpc32
          = client_pseudo_ops_mythryl_g (                                       # client_pseudo_ops_mythryl_g                   is from   src/lib/compiler/back/low/main/nextcode/client-pseudo-ops-mythryl-g.pkg
                #
                package bpo = gas_pseudo_ops_pwrpc32;                           # "bpo" == "base_pseudo_ops".
            );

    package pseudo_ops_pwrpc32
          = pseudo_op_g (                                                       # pseudo_op_g                                   is from   src/lib/compiler/back/low/mcg/pseudo-op-g.pkg
                #
                package cpo =  client_pseudo_ops_pwrpc32;                       # "cpo" == "client_pseudo_ops".
            );

    package code_buffer_pwrpc32
          = codebuffer_g (                                                      # codebuffer_g                                  is from   src/lib/compiler/back/low/code/codebuffer-g.pkg
                #
                pseudo_ops_pwrpc32
            );

    package treecode_buffer_pwrpc32
          = treecode_codebuffer_g (                                                     # treecode_codebuffer_g                         is from   src/lib/compiler/back/low/treecode/treecode-codebuffer-g.pkg
                #
                package tcf =  treecode_form_pwrpc32;
                package cst =  code_buffer_pwrpc32;
            );

    # Machcode (abstract machine code) for powerpc architecture:
    #
    package machcode_pwrpc32
          = machcode_pwrpc32_g (                                                        # machcode_pwrpc32_g                            is from   src/lib/compiler/back/low/pwrpc32/code/machcode-pwrpc32-g.codemade.pkg
                #
                treecode_form_pwrpc32
            );

    package machcode_universals_pwrpc32
          = machcode_universals_pwrpc32_g (                                     # machcode_universals_pwrpc32_g                 is from   src/lib/compiler/back/low/pwrpc32/code/machcode-universals-pwrpc32-g.pkg
                #
                package mcf =  machcode_pwrpc32;
                package tce =  treecode_eval_pwrpc32;
                package tch =  treecode_hash_pwrpc32;
            );

    package compile_register_moves_pwrpc32
          = compile_register_moves_pwrpc32_g (                                  # compile_register_moves_pwrpc32_g              is from   src/lib/compiler/back/low/pwrpc32/code/compile-register-moves-pwrpc32-g.pkg
                machcode_pwrpc32
            );


    package translate_machcode_to_asmcode_pwrpc32
          = translate_machcode_to_asmcode_pwrpc32_g (                           # translate_machcode_to_asmcode_pwrpc32_g       is from   src/lib/compiler/back/low/pwrpc32/emit/translate-machcode-to-asmcode-pwrpc32-g.codemade.pkg
                #
                package mcf =  machcode_pwrpc32;
                package cst =  code_buffer_pwrpc32;
                package tce =  treecode_eval_pwrpc32;
                package crm =  compile_register_moves_pwrpc32;
            );

    package translate_machcode_to_execode_pwrpc32
          = translate_machcode_to_execode_pwrpc32_g (                           # translate_machcode_to_execode_pwrpc32_g       is from   src/lib/compiler/back/low/pwrpc32/emit/translate-machcode-to-execode-pwrpc32-g.codemade.pkg
                #
                package mcf =  machcode_pwrpc32;
                package pop =  pseudo_ops_pwrpc32;
                package cst =  code_buffer_pwrpc32;
                package tce =  treecode_eval_pwrpc32;
                package csb =  code_segment_buffer;                             # code_segment_buffer                           is from   src/lib/compiler/execution/code-segments/code-segment-buffer.pkg
            );

    #  Flowgraph data package specialized to pwrpc32 instructions 
    #
    package machcode_controlflow_graph_pwrpc32
          = machcode_controlflow_graph_g (                                      # machcode_controlflow_graph_g                  is from   src/lib/compiler/back/low/mcg/machcode-controlflow-graph-g.pkg
                #
                package mcf =  machcode_pwrpc32;
#               package pop =  pseudo_ops_pwrpc32;
                package meg =  digraph_by_adjacency_list;                       # digraph_by_adjacency_list                     is from   src/lib/graph/digraph-by-adjacency-list.pkg
                package mu  =  machcode_universals_pwrpc32;
                package ae  =  translate_machcode_to_asmcode_pwrpc32;
            );


    stipulate
        package rkj =  registerkinds_junk;                                      # registerkinds_junk                            is from   src/lib/compiler/back/low/code/registerkinds-junk.pkg
    herein

        package   platform_register_info_pwrpw32
        : (weak)  Platform_Register_Info                                        # Platform_Register_Info                        is from   src/lib/compiler/back/low/main/nextcode/platform-register-info.api
        {
            # Exported tor client packages:
            #
            package tcf =  treecode_form_pwrpc32;
            package rgk =  registerkinds_pwrpc32;                               # registerkinds_pwrpc32                         is from   src/lib/compiler/back/low/pwrpc32/code/registerkinds-pwrpc32.codemade.pkg


            fun upto (from, to)
                =
                if (from > to)   [];
                else             from ! (upto (from+1, to));
                fi;

            infix my  upto ;

            gp = registerkinds_pwrpc32::get_ith_int_hardware_register;
            fp = registerkinds_pwrpc32::get_ith_float_hardware_register;
            cc = registerkinds_pwrpc32::get_ith_hardware_register_of_kind   rkj::FLAGS_REGISTER;

            fun reg  r =  tcf::CODETEMP_INFO  (32, gp r); 
            fun freg f =  tcf::CODETEMP_INFO_FLOAT (64, fp f);

            heap_is_exhausted__test
                =
                THE (tcf::CC (tcf::GTU, cc 0));                                         # A platform-specific test for  (heap_allocation_pointer > heap_allocation_limit)  ;
                                                                                        # this will be used in   src/lib/compiler/back/low/main/nextcode/emit-treecode-heapcleaner-calls-g.pkg
                                                                                        # In this version we are only checking status bits set by a comparison done separately
                                                                                        # by code generated in   src/lib/compiler/back/low/main/main/translate-nextcode-to-treecode-g.pkg

            virtual_framepointer  = registerkinds_pwrpc32::make_int_codetemp_info ();
                #
                # This appears to violate the statement in                                              XXX BUGGO FIXME
                #     http://www.smlnj.org//compiler-notes/omit-vfp.ps
                # that "the virtual frame pointer cannot be allocated using [rgk::make_int_codetemp_info ()]..."
                #      "the virtual frame pointer must   be allocated using [rgk::make_global_codetemp()]..."
                #
                # Note that    src/lib/compiler/back/low/main/intel32/backend-lowhalf-intel32-g.pkg
                # -- which is presumably much better tested -- does in fact use rgk::make_global_codetemp().
                #
                # If there's some architectural difference at work here, it should be commented.

            vfptr                  = tcf::CODETEMP_INFO (32, virtual_framepointer);

            stackptr                            = reg  1;                               # We use the stack lightly, mainly for calling C functions.
            heap_allocation_pointer             = reg 14;                               # We allot ram just by advancing this pointer.  We use this very heavily -- every 10 instructions or so.

            fun heap_allocation_limit _         = reg 15;                               # heap_allocation_pointer may not advance beyond this point.

            fun heap_changelog_pointer _        = reg 16;                               # Every (pointer) update to the heap gets logged to this cons-cell list.
                                                                                        # (The heapcleaner scans this list to detect intergenerational pointers.)

            fun stdlink _                       = reg 17;

            fun stdclos _                       = reg 18;
            fun stdarg _                        = reg 19;
            fun stdfate _                       = reg 20;

            fun exception_handler_register _    = reg 21;
            fun current_thread_ptr _            = reg 22;
            fun base_pointer _                  = reg 23;

            fun heapcleaner_link _              = tcf::CODETEMP_INFO (32, registerkinds_pwrpc32::lr); 
            fun framepointer _                  = stackptr;                             # Holds current C stackframe, which holds pointers to runtime resources like the heapcleaner ("garbage collector"), which is written in C.

            miscregs    = map reg ([24, 25, 26, 27, 29, 30, 31] @ (3 upto 13)); 
            calleesave  = rw_vector::from_list (miscregs);
            floatregs   = map freg (1 upto 31);
            savedfpregs = [];

            available_int_registers
                =
                map un_reg
                    ([stdlink FALSE, stdclos FALSE, stdarg FALSE,
                               stdfate FALSE] @ miscregs)
                where 
                    fun un_reg (tcf::CODETEMP_INFO (_, r))
                            =>
                            r;

                        un_reg _
                            =>
                            lem::error ("pwrpc32-nextcode-registers", "availR");
                    end;
                end;

            stipulate
                package cos =  rkj::cos;                                                        # "cos" == "colorset".
                #
                my --- = cos::difference_of_colorsets;
                #
                infix my  --- ;
            herein

                all_regs    =  map gp (0 upto 31);

                global_int_registers =  cos::get_codetemps_in_colorset
                                            #
                                            (   cos::make_colorset  all_regs
                                                ---
                                                cos::make_colorset  available_int_registers
                                            );
            end;

            available_float_registers =  map fp (1 upto 31);

            global_float_registers = [fp 0];

            use_signed_heaplimit_check =  FALSE;

            address_width =  32;

            #  FIXME 
            ccall_caller_save_r = [];           #  no ccalls implemented yet 
            ccall_caller_save_f = [];           #  ... 

        };
    end;
herein

    package backend_lowhalf_pwrpc32
        = 
        backend_lowhalf_g (                                                                     # backend_lowhalf_g                     is from   src/lib/compiler/back/low/main/main/backend-lowhalf-g.pkg
            #
            package mp = machine_properties_pwrpc32;                                            # machine_properties_pwrpc32            is from   src/lib/compiler/back/low/main/pwrpc32/machine-properties-pwrpc32.pkg

            abi_variant      = NULL;

            package t   =  treecode_form_pwrpc32;
            #
            package cpo =  client_pseudo_ops_pwrpc32;
            package pop =  pseudo_ops_pwrpc32;
            package trx =  treecode_extension_mythryl;                                          # treecode_extension_mythryl            is from   src/lib/compiler/back/low/main/nextcode/treecode-extension-mythryl.pkg

            package pri =  platform_register_info_pwrpw32;
            package mu  =  machcode_universals_pwrpc32;
            package ae  =  translate_machcode_to_asmcode_pwrpc32;

            package crm =  compile_register_moves_pwrpc32;

            package cal                                                                         # "cal" == "ccalls" (native C calls).
                  = ccalls_pwrpc32_mac_osx_g (                                                  # ccalls_pwrpc32_mac_osx_g              is from   src/lib/compiler/back/low/pwrpc32/ccalls/ccalls-pwrpc32-mac-osx-g.pkg
                        #
                        package tcf =  treecode_form_pwrpc32;
                    );

            package fuf {                                                                       # "fuf" == "free_up_framepointer".
                #
                package mcg =  machcode_controlflow_graph_pwrpc32;
                package mcf =  machcode_pwrpc32;
                #
                virtual_framepointer = platform_register_info_pwrpw32::virtual_framepointer;
                #  no rewriting necessary, backend does not change sp 
                fun replace_framepointer_uses_with_stackpointer_in_machcode_controlflow_graph _ = ();
            };

            package t2m                                                                         # "t2m" == "translate_treecode_to_machcode".
                =
                translate_treecode_to_machcode_pwrpc32_g (                              # translate_treecode_to_machcode_pwrpc32_g      is from   src/lib/compiler/back/low/pwrpc32/treecode/translate-treecode-to-machcode-pwrpc32-g.pkg
                    #
                    package mcf =  machcode_pwrpc32;

#                   package treecode_form_pwrpc32
#                          = treecode_form_pwrpc32;

                    package pop
                        =
                        pseudo_instructions_pwrpc32_g (                                 # pseudo_instructions_pwrpc32_g                 is from   src/lib/compiler/back/low/main/pwrpc32/pseudo-instructions-pwrpc32-g.pkg
                                #
                                package mcf = machcode_pwrpc32;
                            );

                    package txc
                        =
                        treecode_extension_compiler_mythryl_g (                         # treecode_extension_compiler_mythryl_g         is from   src/lib/compiler/back/low/main/nextcode/treecode-extension-compiler-mythryl-g.pkg
                            #
                            package mcg =  machcode_controlflow_graph_pwrpc32;
                            package tcs =  treecode_buffer_pwrpc32;
                        );

                    bit64mode = FALSE;                                                  # 64-bit issue
                    mult_cost=REF 6;     # An estimate 
                );

            package jumps_pwrpc32
                =
                jump_size_ranges_pwrpc32_g (                                            # jump_size_ranges_pwrpc32_g            is from   src/lib/compiler/back/low/pwrpc32/jmp/jump-size-ranges-pwrpc32-g.pkg
                    #
                    package mcf =  machcode_pwrpc32;
                    package tce =  treecode_eval_pwrpc32;
                    package crm =  compile_register_moves_pwrpc32;
                );

            package sja                                                                         # "sja" == "squash_jumps_and...".
            = # squash_jumps_and_make_machinecode_bytevector_pwrpc32_g  is from   src/lib/compiler/back/low/jmp/squash-jumps-and-write-code-to-code-segment-buffer-pwrpc32-g.pkg
                squash_jumps_and_make_machinecode_bytevector_pwrpc32_g (
                    #
                    package mcg =  machcode_controlflow_graph_pwrpc32;
                    package jmp =  jumps_pwrpc32;
                    package mu  =  machcode_universals_pwrpc32;
                    package xe  =  translate_machcode_to_execode_pwrpc32;
                );

            package ra                                                                          # "ra"  == "register_allocator".
                = 
                regor_risc_g (                                                                  # regor_risc_g                                  is from   src/lib/compiler/back/low/regor/regor-risc-g.pkg
                    #
                    package mcf =  machcode_pwrpc32;
                    package mcg =  machcode_controlflow_graph_pwrpc32;
                    package mu  =  mu;                                                          # "mu"  == "machcode_universals".

                    package rmi                                                                 # "rmi" == "rewrite_machine_instructions".
                        =
                        instructions_rewrite_pwrpc32_g (                                        # instructions_rewrite_pwrpc32_g                is from   src/lib/compiler/back/low/pwrpc32/regor/instructions-rewrite-pwrpc32-g.pkg
                            machcode_pwrpc32
                        ); 

                    package asi                                                                 # "asi" == "architecture-specific spill instructions".
                        =
                        spill_instructions_pwrpc32_g (                                          # spill_instructions_pwrpc32_g                  is from   src/lib/compiler/back/low/pwrpc32/regor/spill-instructions-pwrpc32-g.pkg
                            #
                            package mcf =  machcode_pwrpc32;
                        );

                    package ae  =  translate_machcode_to_asmcode_pwrpc32;

                    package rsp = register_spilling_per_chaitin_heuristic;                      # register_spilling_per_chaitin_heuristic       is from   src/lib/compiler/back/low/regor/register-spilling-per-chaitin-heuristic.pkg
                                                                                                # "rsp" == "register_spilling_per_xxx_heuristic".

                    package spl                                                                 # "spl" == "spill".
                        =
                        register_spilling_g (                                                   # register_spilling_g                           is from   src/lib/compiler/back/low/regor/register-spilling-g.pkg
                            #
                            package mu =  mu;                                                   # "mu"  == "machcode_universals".
                            package ae =  translate_machcode_to_asmcode_pwrpc32;                # "ae"  == "asmcode_emitter".
                        );

                    package spill_table                                                         # Not an actual generic parameter.
                        =
                        spill_table_g (                                                         # spill_table_g                                 is from   src/lib/compiler/back/low/main/main/spill-table-g.pkg
                            #
                            machine_properties_pwrpc32                                          # machine_properties_pwrpc32                    is from   src/lib/compiler/back/low/main/pwrpc32/machine-properties-pwrpc32.pkg
                        );

                    machine_architecture                                                        # PWRPC32/SPARC32/INTEL32.
                        =
                        machine_properties_pwrpc32::machine_architecture;

                    Spill_Operand_Kind = SPILL_LOC | CONST_VAL;

                    Spill_Info = Void;

                    fun before_ra _
                        =
                        spill_table::spill_init();

                    sp = mcf::rgk::stackptr_r;

                    spill = nextcode_ramregions::spill;

                    fun pure _
                        =
                        FALSE;

#                   package nextcode_registers= platform_register_info_pwrpw32;                 # Not an actual generic parameter.

                    package rap {                                                               # "rap" == "register allocation parameters".
                        #
                        locally_allocated_hardware_registers =  platform_register_info_pwrpw32::available_int_registers;
                        globally_allocated_hardware_registers =  platform_register_info_pwrpw32::global_int_registers;

                        fun make_disp loc
                            =
                            t::LITERAL (t::mi::from_int (32, spill_table::get_reg_loc loc));


                        fun spill_loc { info, an, register, id }
                            = 
                            { operand =>  mcf::DISPLACE { base      =>  sp,
                                                          disp      =>  make_disp (cig::SPILL_TO_FRESH_FRAME_SLOT id),
                                                          ramregion =>  spill
                                                        },
                              kind    =>  SPILL_LOC
                            };

                        mode = irc::no_optimization;
                    };

                    package fap {                                                               # "fap" == "floating point register allocation parameters".
                        #
                        locally_allocated_hardware_registers =  platform_register_info_pwrpw32::available_float_registers;
                        globally_allocated_hardware_registers = platform_register_info_pwrpw32::global_float_registers;

                        fun make_disp loc
                            =
                            t::LITERAL (t::mi::from_int (32, spill_table::get_freg_loc loc));

                        fun spill_loc (s, an, loc)
                            = 
                            mcf::DISPLACE { base      =>  sp,
                                            disp      =>  make_disp (cig::SPILL_TO_FRESH_FRAME_SLOT loc),
                                            ramregion =>  spill
                                          };

                        mode = irc::no_optimization;
                    };
            );
      );
end;

##  COPYRIGHT (c) 1999 Lucent Technologies, Bell Labs. 
## Subsequent changes by Jeff Prothero Copyright (c) 2010-2015,
## released per terms of SMLNJ-COPYRIGHT.


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext