PreviousUpNext

15.4.228  src/lib/compiler/back/low/code/registerkinds-junk.pkg

## registerkinds-junk.pkg -- derived from  ~/src/sml/nj/smlnj-110.58/new/new/src/MLRISC/instructions/cells-basis.sig 
#

# Compiled by:
#     src/lib/compiler/back/low/lib/lowhalf.lib



###             "At Group L, Stoffel oversees six first-rate programmers,
###              a managerial challenge roughly comparable to herding cats."
###
###                                -- Washington Post Magazine, 1985



# Support for handling registers, register colors and register sets.

stipulate
    package lem =  lowhalf_error_message;                               # lowhalf_error_message is from   src/lib/compiler/back/low/control/lowhalf-error-message.pkg
    package nt  =  note;                                                # note                  is from   src/lib/src/note.pkg
    package rwv =  rw_vector;                                           # rw_vector             is from   src/lib/std/src/rw-vector.pkg
herein

    package   registerkinds_junk
    : (weak)  Registerkinds_Junk                                        # Registerkinds_Junk    is from   src/lib/compiler/back/low/code/registerkinds-junk.api
    {
        Registerkind_Names
            =
            REGISTERKIND_NAMES
              {
                name:      String,
                nickname:  String
              };

        Register_Size_In_Bits = Int;                    # Width in bits.
        Universal_Register_Id = Int;                    # Small-int unique across all      'registers' of all kinds, including condition code bits etc.
        Interkind_Register_Id = Int;                    # Small-int unique across all plain registers. These are our register 'colors' for register allocation purposes.
        Intrakind_Register_Id = Int;                    # Small-int unique across all plain registers  of one kind -- e.g. all float registers or all int registers.

        Registerkind                                    # This is an equality type.
          #
          =   INT_REGISTER                              # General purpose register 
          | FLOAT_REGISTER                              # Floating point register 
          |   RAM_BYTE                                  
          #
          | FLAGS_REGISTER                              # We treat each condition-codes register bit as a separate 1-bit register.
          | CONTROL_DEPENDENCY                          # Simplifies our code to treat control dependencies like register dependencies.
          | OTHER_REGISTER Ref( Registerkind_Names )    # Architecture-specific registers.
          ;

        Registerkind_Info
            =
            REGISTERKIND_INFO
              {
                kind:                   Registerkind,                                           # See comment in   src/lib/compiler/back/low/code/registerkinds-junk.api
                codetemps_made_count:   Ref( Int ),                                             # See comment in   src/lib/compiler/back/low/code/registerkinds-junk.api

                global_codetemps_created_so_far:        Ref( Int ),                             # See comment in   src/lib/compiler/back/low/code/registerkinds-junk.api

                min_register_id:        Int,                                                    # See comment in   src/lib/compiler/back/low/code/registerkinds-junk.api
                max_register_id:        Int,                                                    # See comment in   src/lib/compiler/back/low/code/registerkinds-junk.api

                to_string:              Interkind_Register_Id -> String,
                sized_to_string:        (Interkind_Register_Id, Register_Size_In_Bits) -> String,

                hardware_registers:     Ref( rwv::Rw_Vector(Codetemp_Info) ),                   # See comment in   src/lib/compiler/back/low/code/registerkinds-junk.api

                always_zero_register:   Null_Or( Interkind_Register_Id )
              }

        also
        Codetemp_Info
            =
            CODETEMP_INFO
                      { id:     Universal_Register_Id,
                        color:  Ref( Codetemp_Color ),
                        kind:   Registerkind_Info,
                        notes:  Ref( nt::Notes )
                      }

        also
        Codetemp_Color
          = MACHINE  Interkind_Register_Id
          | CODETEMP
          | ALIASED  Codetemp_Info
          | SPILLED
          ;

        array0
            =
            rwv::from_fn (0, \\ _ = raise exception MATCH): rwv::Rw_Vector( Codetemp_Info );

        fun error msg
            =
            lem::error ("registerkinds-junk", msg);

        fun name_of_registerkind INT_REGISTER           => "REGISTER";
            name_of_registerkind FLOAT_REGISTER         => "FLOAT_REGISTER";
            name_of_registerkind FLAGS_REGISTER         => "FLAGS_REGISTER";
            name_of_registerkind RAM_BYTE               => "RAM_BYTE";
            name_of_registerkind CONTROL_DEPENDENCY     => "CONTROL_DEPENDENCY";
            #
            name_of_registerkind (OTHER_REGISTER (REF (REGISTERKIND_NAMES r ))) => r.name;
        end;

        fun nickname_of_registerkind INT_REGISTER       => "r";                                         # Apparently invoked only in   src/lib/compiler/back/low/treecode/treecode-hashing-equality-and-display-g.pkg
            nickname_of_registerkind FLOAT_REGISTER     => "f";
            nickname_of_registerkind FLAGS_REGISTER     => "cc";
            nickname_of_registerkind RAM_BYTE           => "m";                                         # "m" for "main memory".
            nickname_of_registerkind CONTROL_DEPENDENCY => "ctrl";
            #
            nickname_of_registerkind (OTHER_REGISTER (REF (REGISTERKIND_NAMES r ))) => r.nickname;
        end;

        fun make_registerkind { name=>"INT_REGISTER",        ... } =>  INT_REGISTER;                    # Invoked in  src/lib/compiler/back/low/intel32/code/registerkinds-intel32.codemade.pkg
            make_registerkind { name=>"FLOAT_REGISTER",      ... } =>  FLOAT_REGISTER;                  # also    in  src/lib/compiler/back/low/pwrpc32/code/registerkinds-pwrpc32.codemade.pkg
            make_registerkind { name=>"FLAGS_REGISTER",      ... } =>  FLAGS_REGISTER;                  # also    in  src/lib/compiler/back/low/sparc32/code/registerkinds-sparc32.codemade.pkg
            make_registerkind { name=>"RAM_BYTE",            ... } =>  RAM_BYTE;
            make_registerkind { name=>"CONTROL_DEPENDENCY",  ... } =>  CONTROL_DEPENDENCY;
            make_registerkind { name, nickname                   } =>  OTHER_REGISTER (REF (REGISTERKIND_NAMES { name, nickname } ));   # This is the only case exercised by existing code.
        end;

        fun follow_register_alias_chain (CODETEMP_INFO { color => REF (ALIASED c), ... } ) =>  follow_register_alias_chain(c);
            follow_register_alias_chain c => c;
        end;

        fun universal_register_id_of (CODETEMP_INFO r)
            =
            r.id;

        fun interkind_register_id_of (CODETEMP_INFO { color=>REF (ALIASED c),  ... } ) =>  interkind_register_id_of c;
            interkind_register_id_of (CODETEMP_INFO { color=>REF (MACHINE r),  ... } ) =>  r;
            interkind_register_id_of (CODETEMP_INFO { color=>REF SPILLED,      ... } ) =>  -1;
            interkind_register_id_of (CODETEMP_INFO { color=>REF CODETEMP, id, ... } ) =>  id;                                                          # Note that CODETEMPs have idential interkind- and intra-kind IDs.
        end;  

        fun intrakind_register_id_of (CODETEMP_INFO { color=>REF (ALIASED c),                              ... } ) =>  intrakind_register_id_of  c;
            intrakind_register_id_of (CODETEMP_INFO { color=>REF (MACHINE r), kind => REGISTERKIND_INFO k, ... } ) =>  r - k.min_register_id;
            intrakind_register_id_of (CODETEMP_INFO { color=>REF SPILLED,                                  ... } ) =>  -1;
            intrakind_register_id_of (CODETEMP_INFO { color=>REF CODETEMP, id,                             ... } ) =>  id;
        end;


        fun hardware_register_id_of (CODETEMP_INFO { color=>REF (ALIASED c), ... } )
                => 
                hardware_register_id_of  c;

            hardware_register_id_of (CODETEMP_INFO { color =>  REF (MACHINE r), 
                                                kind  =>  REGISTERKIND_INFO d,
                                                ...
                                               }
                                    )
                =>
                r - d.min_register_id;

            hardware_register_id_of (CODETEMP_INFO { color=>REF SPILLED, id, ... } )
                => 
                error("hardware_register_id_of: SPILLED: " + int::to_string id);

            hardware_register_id_of (CODETEMP_INFO { color=>REF CODETEMP, id, ... } )
                => 
                error("hardware_register_id_of: CODETEMP: " + int::to_string id);
        end;



        fun register_to_hashcode (CODETEMP_INFO { id, ... } )
            =
            unt::from_int id;


        fun hash_color c
            =
            unt::from_int (interkind_register_id_of  c);


        fun same_id                    (r1, r2) =   universal_register_id_of r1  ==  universal_register_id_of  r2;
        fun codetemps_are_same_color   (r1, r2) =   interkind_register_id_of r1  ==  interkind_register_id_of  r2;

        fun compare_registers_by_color (r1, r2)
            =
            int::compare ( interkind_register_id_of  r1,
                           interkind_register_id_of  r2
                         );

        fun registerkind_of (CODETEMP_INFO { kind => REGISTERKIND_INFO { kind, ... }, ... } )
            =
            kind;




        # Register prettyprinting:
        # 
        fun register_to_string (CODETEMP_INFO { color=>REF (ALIASED c), ... } )
                =>
                register_to_string c;

            register_to_string (c as CODETEMP_INFO { kind => REGISTERKIND_INFO { to_string, ... }, ... } )
                =>
                to_string (intrakind_register_id_of c);
        end;
        #
        fun register_to_string'                                                         # Apparently called only once, in   src/lib/compiler/back/low/intel32/emit/translate-machcode-to-asmcode-intel32-g.codemade.pkg
              {
                my_register  =>  c as CODETEMP_INFO { kind => REGISTERKIND_INFO { sized_to_string, ... }, ... },
                size_in_bits =>  size
              }
            = 
            sized_to_string (intrakind_register_id_of c, size); 

        fun cnv (r, low, high)
            =
            if (low <= r and r <= high)   r - low;
            else                          r;
            fi;


        # See 'api Colorset' comments in
        #
        #     src/lib/compiler/back/low/code/registerkinds-junk.api
        #
        package cos {                                                                   # Exported to client packages.   "cos" == "colorset".
            #
            Codetemp_Info = Codetemp_Info;                                              # Included for purely technical reasons -- Colorset api declaration won't work without it.
            Colorset = List( Codetemp_Info );

            empty_colorset = [];

            size =   list::length; 

            fun add_codetemp_to_colorset (codetemp, colorset)
                =
                f colorset
                where 
                    c =   interkind_register_id_of codetemp;

                    fun f (l as (h ! t))
                            => 
                            {   ch =   interkind_register_id_of h;
                                #
                                if   (c < ch)  codetemp ! l;
                                elif (c > ch)  h ! f t;
                                else l;
                                fi;
                            };

                        f [] =>   [codetemp];
                    end;
                end;

            fun drop_codetemp_from_colorset (register, l)
                =
                f l
                where
                    c =   interkind_register_id_of register;

                    fun f (l as (h ! t))
                            => 
                            {   ch =   interkind_register_id_of h;

                                if   (c == ch)   t; 
                                elif (c < ch)    l;
                                else             h ! f l;
                                fi;
                            };

                        f [] => [];
                    end;
                end;


            fun make_colorset  registers
                =
                list::fold_forward
                    add_codetemp_to_colorset
                    []
                    (map  follow_register_alias_chain  registers);


            fun difference_of_colorsets ([], _) =>   [];
                difference_of_colorsets (l, []) =>   l;

                difference_of_colorsets
                      (
                        l1 as x ! xs,
                        l2 as y ! ys
                      )
                    => 
                    {   cx =   interkind_register_id_of  x;
                        cy =   interkind_register_id_of  y;

                        if   (cx == cy)        difference_of_colorsets (xs, ys);
                        elif (cx <  cy)    x ! difference_of_colorsets (xs, l2);
                        else                   difference_of_colorsets (l1, ys);
                        fi;
                    };
            end;

            fun union_of_colorsets (a, []) =>   a;
                union_of_colorsets ([], a) =>   a;

                union_of_colorsets (l1 as x ! xs, l2 as y ! ys)
                     => 
                     {   cx =   interkind_register_id_of  x;
                         cy =   interkind_register_id_of  y;

                         if   (cx == cy)   x ! union_of_colorsets (xs, ys);
                         elif (cx <  cy)   x ! union_of_colorsets (xs, l2);
                         else              y ! union_of_colorsets (l1, ys);
                         fi;
                     };
            end;


            fun intersection_of_colorsets (a, []) =>   [];
                intersection_of_colorsets ([], a)  =>   [];

                intersection_of_colorsets
                      (
                        l1 as x ! xs,
                        l2 as y ! ys
                      )
                    => 
                    {   cx =   interkind_register_id_of  x;
                        cy =   interkind_register_id_of  y;

                        if   (cx == cy)  x ! intersection_of_colorsets (xs, ys);
                        elif (cx <  cy)      intersection_of_colorsets (xs, l2);
                        else                 intersection_of_colorsets (l1, ys);
                        fi;
                    };
            end;


            fun not_same_colorset ([], []) => FALSE;
                not_same_colorset([], l)  => TRUE;
                not_same_colorset(_, [])  => TRUE;

                not_same_colorset (x ! l1, y ! l2)
                     =>
                     interkind_register_id_of x  !=  interkind_register_id_of y
                     or
                     not_same_colorset (l1, l2);
            end;

            fun same_colorset ([], [])
                    =>
                    TRUE;

                same_colorset (x ! l1, y ! l2)
                    =>
                    interkind_register_id_of x == interkind_register_id_of y
                    or
                    same_colorset (l1, l2);

                same_colorset (_, _)
                    =>
                    FALSE;
            end;

            fun get_codetemps_in_colorset  cs
                =
                cs;

            fun colorset_is_empty [] =>  TRUE;
                colorset_is_empty _  =>  FALSE;
            end;

            fun colorsets_intersection_is_empty (_, []) =>  TRUE;
                colorsets_intersection_is_empty ([], _) =>  TRUE;

                colorsets_intersection_is_empty (l1 as x ! xs, l2 as y ! ys)
                    => 
                    {   cx = interkind_register_id_of x;
                        cy = interkind_register_id_of y;

                        if (cx == cy)
                            #
                            FALSE;
                        else
                            if (cx < cy)   colorsets_intersection_is_empty (xs, l2);
                            else           colorsets_intersection_is_empty (l1, ys);
                            fi;
                        fi;
                    };
            end;

#           fun is_in_colorset (x, l)                                                   # Commented out because never used -- 2011-06-25 CrT 
#               = 
#               {   x =   interkind_register_id_of x;
#
#                   list::exists
#                       (\\ y = interkind_register_id_of y == x)
#                       l;
#               };

        };

        # A common idiom -- sort a codetemps list
        # by color and drop duplicated colors:
        #
        sortuniq_colored_codetemps
            =
            cos::get_codetemps_in_colorset
            o
            cos::make_colorset;


        package id_indexed_hashtable
            = 
            typelocked_hashtable_g (                                    # typelocked_hashtable_g        is from   src/lib/src/typelocked-hashtable-g.pkg
                Hash_Key = Codetemp_Info;
                hash_value = register_to_hashcode; 
                same_key = same_id;
            );
        package iih =  id_indexed_hashtable;                            # Abbreviation.



        package color_indexed_hashtable
            = 
            typelocked_hashtable_g (
                #
                Hash_Key   =  Codetemp_Info;
                hash_value =  hash_color; 
                same_key   =  codetemps_are_same_color;
            );
        package cih =  color_indexed_hashtable;                         # Abbreviation.



        ##################################################              # This package should have its own file. XXX SUCKO FIXME.
        # Lists of codetemps segregated by kind -- in
        # practice, floats vs ints.  This is a workhorse
        # datastructure used to track which codetemps are
        # live, dead, spilled, etc:
        #
        package cls {                                                   # Exports to client packages.  "cls" == "codetemplists".
            #
            Codetemp_Info = Codetemp_Info;                              # These two included only to make Registerkind api declaration work.
            Registerkind_Info = Registerkind_Info;

            Codetemplists
                =
                List( (Registerkind_Info, List(Codetemp_Info)) ); 

            empty_codetemplists =   [];


            stipulate
                fun kind_of (CODETEMP_INFO r)
                    =
                    r.kind; 

                fun same_kind
                      ( REGISTERKIND_INFO { codetemps_made_count=>x, ... },
                        REGISTERKIND_INFO { codetemps_made_count=>y, ... }
                      )
                    =
                    x == y;                                                     # We're comparing the refcells themselves -- not their contents!
            herein

                fun add_codetemp_to_appropriate_kindlist
                      (
                        codetemp,
                        codetemplists: Codetemplists
                      )
                    =
                    loop codetemplists
                    where
                        kind =   kind_of codetemp;

                        fun loop ((x as (kind', s)) ! codetemplists)
                                => 
                                if (same_kind (kind, kind'))   (kind', codetemp ! s) !      codetemplists; 
                                else                               x ! loop codetemplists;
                                fi;

                            loop [] =>   [ (kind, [codetemp]) ];
                        end;
                    end;


                fun drop_codetemp_from_codetemplists (r, codetemplists: Codetemplists)
                    =
                    loop codetemplists
                    where
                        kind =   kind_of r;
                        c =   interkind_register_id_of r;

                        fun filter (r ! rs)
                                 =>
                                 if (interkind_register_id_of r == c)     filter rs; 
                                 else                                 r ! filter rs;
                                 fi;

                            filter [] =>   [];
                        end;

                        fun loop((x as (kind', s)) ! codetemplists)
                                => 
                                if (same_kind (kind, kind'))   (kind', filter s) ! codetemplists;
                                else                     x ! loop codetemplists;
                                fi;

                            loop [] =>   [];
                        end;
                    end;


                fun get_codetemps_for_kindinfo (k:  Registerkind_Info)
                    =
                    loop
                    where
                        fun loop ((k', s) ! codetemplists)
                                =>
                                if (same_kind (k, k'))   s;
                                else                     loop codetemplists;
                                fi;

                            loop ([] : Codetemplists) =>   [];
                        end;
                    end;


                fun replace_codetemps_for_kindinfo
                        #
                        (k:  Registerkind_Info)
                        #
                        (codetemplists: Codetemplists,  codetemps)
                    =
                    loop codetemplists
                    where
                        fun loop ((x as (k', _)) ! codetemplists)
                                =>
                                if (same_kind (k, k'))   (k', codetemps) ! codetemplists;
                                else                     x !  loop codetemplists;
                                fi;

                            loop [] =>   [ (k, codetemps) ];
                        end;
                    end;


                fun replace_this_by_that_in_codetemplists { this, that } (codetemplists: Codetemplists) # No-op if 'this' and 'that' are different kinds.
                    =
                    loop codetemplists
                    where
                        this ->   CODETEMP_INFO { kind => this_kind, ... };

                        this_id =   interkind_register_id_of  this;

                        fun replace_this_by_that' r
                            =
                            if (interkind_register_id_of r == this_id)   that;
                            else                                         r;
                            fi;

                        # Find the codetemps list for this_kind
                        # and do the substitute in it:
                        #
                        fun loop ((x as (kind', codetemps)) ! codetemplists)
                                => 
                                if (same_kind (this_kind, kind'))   (kind', list::map replace_this_by_that' codetemps) ! codetemplists; 
                                else                                x ! loop codetemplists;
                                fi;

                            loop [] =>  [];
                        end;
                    end;
            end;


            get_all_codetemps_from_codetemplists
                =
                list::fold_backward
                    (\\ ((_, s), s') =  s @ s')
                    []
                :
                Codetemplists -> List(Codetemp_Info)
                ;


            # Prettyprint codetemplists:
            #
            fun print_set (f, set, s)
                =
                "{ "  !  loop (set, s)
                where
                    fun loop ([],  s) =>   "}" ! s;
                        loop ([x], s) =>   f (follow_register_alias_chain x) ! "}" ! s;

                        loop (x ! xs, s)
                             =>
                             f (follow_register_alias_chain x) ! " " ! loop (xs, s);
                    end;
                end;

            fun to_string' codetemplists
                =
                pr codetemplists
                where
                    fun pr codetemplists
                        = 
                        string::cat (loop (codetemplists, []))
                        where
                            fun loop ((REGISTERKIND_INFO { kind, ... }, s) ! rest, sss)
                                    =>
                                    case s
                                        #
                                        [] => loop (rest, sss);

                                        _  => name_of_registerkind  kind
                                              !
                                              "="
                                              !
                                              print_set (
                                                  register_to_string, s, " "
                                                  !
                                                  loop (rest, sss)
                                              );
                                    esac;

                                loop ([], sss) =>   sss;
                            end;
                        end;
                end;

            codetemplists_to_string =  to_string';

        };                                                                                              # package codetemplists 


        # These annotations specify
        # definitions and uses for
        # a codetemp:
        #
        exception DEF_USE   { registerkind: Registerkind,
                              defs:     List(Codetemp_Info),
                              uses:     List(Codetemp_Info)
                            };

        def_use =   nt::make_notekind'
                      {
                        x_to_note => DEF_USE,
                        #
                        get       => \\ DEF_USE x =>  x;
                                        other     =>  raise exception other;
                                     end,

                        to_string => \\ { registerkind, defs, uses }
                                         =
                                         "def_use" + name_of_registerkind registerkind
                      };

        # Hack for generating memory aliasing registers 
        #
        ram_registerkind_info
            =  
            REGISTERKIND_INFO
              {
                kind                 =>  RAM_BYTE,
                codetemps_made_count =>  REF 0,

                min_register_id      =>   0,
                max_register_id      =>  -1,

                to_string            =>  \\ m      =  "m" + int::to_string m,
                sized_to_string      =>  \\ (m, _) =  "m" + int::to_string m,

                hardware_registers   =>  REF array0,
                always_zero_register =>  NULL,

                global_codetemps_created_so_far     =>  REF 0           # See comment in src/lib/compiler/back/low/code/registerkinds-junk.api
              };




        #######################################################################################################################
        # These three are for INTERNAL USE ONLY,
        # for alias analysis:
        #
        fun show (REGISTERKIND_INFO { to_string, min_register_id, max_register_id, ... } ) r
            =
            to_string (cnv (r, min_register_id, max_register_id));

        fun show_with_size (REGISTERKIND_INFO { sized_to_string, min_register_id, max_register_id, ... } ) (r, size)
            = 
            sized_to_string (cnv (r, min_register_id, max_register_id), size);

        fun make_ram_register  id
            =
            CODETEMP_INFO
              {
                id,
                notes =>  REF [],
                kind  =>  ram_registerkind_info,
                color =>  REF( MACHINE id )
              };

        zero_length_rw_vector
            =
            rwv::from_fn (0, \\ _ = raise exception MATCH):   rwv::Rw_Vector(Codetemp_Info);


        #######################################################################################################################
        # The rest of this stuff is never referenced, so I've commented it out.
        # I have no idea which parts are past mistakes that were being phased out,
        # and which parts were future mistakes being phased in. -- 2011-03-13 CrT
        #

    #   fun same_kind_of_register (c1, c2)          =   same_kind (kind_of c1, kind_of c2);                     # Commented out because unused -- 2011-03-12 CrT

    #   fun same_register_up_to_aliasing (c1, c2)   =   same_id ( follow_register_alias_chain c1,                       # Commented out because unused -- 2011-03-12 CrT
    #                                                               follow_register_alias_chain c2
    #                                                                  );
    #   fun notes_of_register (CODETEMP_INFO { notes, ... } ) =   notes;                                                                # Commented out because unused -- 2011-03-12 CrT

    #    fun set_color_alias_of_from_pseudoregister { from, to }                                                                # Commented out because unused -- 2011-03-12 CrT
    #   #
    #   # Set the color of the 'from' register to be the same as
    #   # the 'to' register.  The 'from' register MUST be a pseudo register,
    #   # and cannot be of kind CONST.
    #   = 
    #   {   (follow_register_alias_chain from) ->         CODETEMP_INFO { color => color_from, id, kind=>REGISTERKIND_INFO { kind, ... }, ... };
    #       (follow_register_alias_chain to  ) ->   to as CODETEMP_INFO { color => color_to, ... };
    #          
    #
    #       if (color_from != color_to)
    #                   #  prevent self-loops 
    #           if (id < 0)
    #               #
    #               error "set_color_aliase_of_from_pseudoregister: constant";
    #           else
    #               case (*color_from, kind) 
    #                   #
    #                   (CODETEMP, _) =>  color_from := ALIASED to;
    #                   _             =>  error "setAlias: non-pseudo";
    #               esac;
    #       fi;  fi;
    #   };

    #    fun register_is_constant (CODETEMP_INFO { id, ... } )                                  # Commented out because unused -- 2011-03-12 CrT
    #   =
    #   id < 0; 

    };
end;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext