PreviousUpNext

15.4.401  src/lib/compiler/back/low/tools/arch/adl-rtl-comp-g.pkg

## adl-rtl-comp-g.pkg -- derived from  ~/src/sml/nj/smlnj-110.60/MLRISC/Tools/ADL/mdl-rtl-comp.sml
#
# Process rtl descriptions

# Compiled by:
#     src/lib/compiler/back/low/tools/arch/make-sourcecode-for-backend-packages.lib



###               "It is the business of the future to be dangerous;
###                and it is among the merits of science that
###                it equips the future for its duties."
###
###                                 -- Alfred North Whitehead 



stipulate
    package ard =  architecture_description;                            # architecture_description                              is from   src/lib/compiler/back/low/tools/arch/architecture-description.pkg
    package cst =  adl_raw_syntax_constants;                            # adl_raw_syntax_constants                              is from   src/lib/compiler/back/low/tools/adl-syntax/adl-raw-syntax-constants.pkg
    package err =  adl_error;                                           # adl_error                                             is from   src/lib/compiler/back/low/tools/line-number-db/adl-error.pkg
    package lms =  list_mergesort;                                      # list_mergesort                                        is from   src/lib/src/list-mergesort.pkg
    package mst =  adl_symboltable;                                     # adl_symboltable                                       is from   src/lib/compiler/back/low/tools/arch/adl-symboltable.pkg
    package mt  =  adl_typing;                                          # adl_typing                                            is from   src/lib/compiler/back/low/tools/arch/adl-typing.pkg
    package raw =  adl_raw_syntax_form;                                 # adl_raw_syntax_form                                   is from   src/lib/compiler/back/low/tools/adl-syntax/adl-raw-syntax-form.pkg
    package rkj =  registerkinds_junk;                                  # registerkinds_junk                                    is from   src/lib/compiler/back/low/code/registerkinds-junk.pkg
    package rrs =  adl_rewrite_raw_syntax_parsetree;                    # adl_rewrite_raw_syntax_parsetree                      is from   src/lib/compiler/back/low/tools/adl-syntax/adl-rewrite-raw-syntax-parsetree.pkg
    package rsj =  adl_raw_syntax_junk;                                 # adl_raw_syntax_junk                                   is from   src/lib/compiler/back/low/tools/adl-syntax/adl-raw-syntax-junk.pkg
    package rst =  adl_raw_syntax_translation;                          # adl_raw_syntax_translation                            is from   src/lib/compiler/back/low/tools/adl-syntax/adl-raw-syntax-translation.pkg
    package rsu =  adl_raw_syntax_unparser;                             # adl_raw_syntax_unparser                               is from   src/lib/compiler/back/low/tools/adl-syntax/adl-raw-syntax-unparser.pkg
    package smj =  sourcecode_making_junk;                              # sourcecode_making_junk                                is from   src/lib/compiler/back/low/tools/arch/sourcecode-making-junk.pkg
    package spp =  simple_prettyprinter;                                # simple_prettyprinter                                  is from   src/lib/prettyprint/simple/simple-prettyprinter.pkg
    package tcp =  treecode_pith;                                       # treecode_pith                                         is from   src/lib/compiler/back/low/treecode/treecode-pith.pkg
herein

    # This generic is invoked (only) in:
    #
    #     src/lib/compiler/back/low/tools/arch/adl-rtl-comp.pkg
    #
    generic package   adl_rtl_comp_g   (
        #             ==============
        #
        package art:  Adl_Rtl_Tools;
        package lct:  Lowhalf_Types;

        sharing lct::rtl
             == art::rtl
             ;
    )
    : (weak)   Adl_Rtl_Comp                                             # Adl_Rtl_Comp                                          is from   src/lib/compiler/back/low/tools/arch/adl-rtl-comp.api
    {
        # Export to client packages:
        #
        package rtl =  art::rtl;
        package lct =  lct;

        stipulate
            package ht  =  hashtable;
            package tcf =  rtl::tcf;
            #
            include package   rsj;
            include package   err;
        herein

            t2s  =  spp::prettyprint_expression_to_string o rsu::type;
            e2s  =  spp::prettyprint_expression_to_string o rsu::expression;
            p2s  =  spp::prettyprint_expression_to_string o rsu::pattern;
            d2s  =  spp::prettyprint_expression_to_string o rsu::decl;
            re2s =  rtl::tcj::int_expression_to_string;

            i2s = int::to_string;

            fun tuplepat [p] =>  p;
                tuplepat ps  =>  raw::TUPLEPAT ps;
            end;

            fun tupleexp [e] =>  e;
                tupleexp es  =>  raw::TUPLE_IN_EXPRESSION es;
            end;

            exception NO_RTL;

            Rtl_Def
                = 
                RTLDEF
                  { id:    raw::Id, 
                    args:  List( raw::Id ), 
                    rtl:   rtl::Rtl
                  };


            Compiled_Rtls
                =
                COMPILED_RTLS
                  { architecture_description:                   ard::Architecture_Description,
                    symboltable:        mst::Symboltable,
                    #
                    rtls:               List( Rtl_Def ),
                    new_ops:            List( tcp::Misc_Op ),
                    rtl_table:          ht::Hashtable( String, Rtl_Def )
                  };

            current_rtls =  REF []:   Ref( List(Rtl_Def) );

            make_rtl_def =  raw::ID_IN_EXPRESSION (raw::IDENT (["adl_rtl_comp"], "RTLDEF"));

            fun architecture_description_of (COMPILED_RTLS { architecture_description, ... } )
                =
                architecture_description;

            fun rtls (COMPILED_RTLS { rtls, ... } )
                =
                rtls;

            fun no_error ()
                =
                *error_count == 0;


            ##########################################################################
            #
            # Perform type interference and arity raising
            #
            fun type_inference (architecture_description, rtl_decls)
                = 
                (semantics, symboltable)
                where
                    # Do typechecking + arity raising:
                    #
                    my (semantics, symboltable)
                        =
                        {   print "Typechecking...\n";
                            mt::type_check architecture_description rtl_decls;
                        };

                    # Make sure that there are 
                    # no unresolved type applications after
                    # arity raising.
                    #
                    fun check_semantics semantics
                        =
                        {   fun check_unresolved_type_applications (d, loc)
                                =
                                {   poly = REF FALSE;

                                    fun rewrite_expression_node ===> (e as raw::TYPE_IN_EXPRESSION type)
                                            =>
                                            {   if (mt::is_typeagnostic type)   poly := TRUE;   fi;
                                                e;
                                            };

                                        rewrite_expression_node ===> e
                                            =>
                                            e;

                                    end;

                                    fns.rewrite_declaration_parsetree  d
                                    where
                                        fns = rrs::make_raw_syntax_parsetree_rewriters [ rrs::REWRITE_EXPRESSION_NODE rewrite_expression_node ];
                                    end;

                                    if *poly   error_pos (loc, "unresolved polytype application in:\n" + d2s d);   fi;
                                };

                            fun rewrite_declaration_node ===> d
                                =
                                {   case d
                                        #
                                        raw::SOURCE_CODE_REGION_FOR_DECLARATION (l, d as raw::VAL_DECL _) =>  check_unresolved_type_applications (d, l);
                                        raw::RTL_DECL(_, _, loc)                =>  check_unresolved_type_applications (d, loc);
                                        _                                      =>  ();
                                    esac;

                                    d;
                                };

                            fns.rewrite_declaration_parsetree  semantics
                            where
                                fns = rrs::make_raw_syntax_parsetree_rewriters [ rrs::REWRITE_DECLARATION_NODE rewrite_declaration_node ];
                            end;

                            ();
                        };

                    if (no_error ())    check_semantics semantics;   fi;
                end;


            ##########################################################################
            #
            # Translate the rtl declarations into an executable form.
            #
            fun coder (architecture_description, symboltable, rtl_decls)
                = 
                ( all_decls,
                  reverse *all_rtls
                )
                where
                    fun register_of k
                        =
                        {   (ard::find_registerset_by_name  architecture_description  k)
                                ->
                                raw::REGISTER_SET { name, bits, ... };

                            raw::TUPLE_IN_EXPRESSION [ raw::ID_IN_EXPRESSION (raw::IDENT (["C"], name)), integer_constant_in_expression bits ];
                        };

                    fun rewrite_expression_node _ (raw::REGISTER_IN_EXPRESSION (m, e, NULL ))    =>  raw::APPLY_EXPRESSION (app("@@@", register_of m), e);
                        rewrite_expression_node _ (raw::REGISTER_IN_EXPRESSION (m, e, THE r))    =>  raw::APPLY_EXPRESSION (app("Mem", register_of m), raw::TUPLE_IN_EXPRESSION [e, id r]);
                        #
                        rewrite_expression_node _ (raw::IF_EXPRESSION (a, b, c)) =>  app ("If", raw::TUPLE_IN_EXPRESSION [a, b, c] );
                        #
                        rewrite_expression_node _ (raw::TUPLE_IN_EXPRESSION [])                  =>  id "Nop";
                        rewrite_expression_node _ (raw::ID_IN_EXPRESSION (raw::IDENT([], "=")))  =>  id "==";
                        rewrite_expression_node _ (raw::TYPED_EXPRESSION (e, _))                 =>  e;
                        #
                        rewrite_expression_node _ (raw::APPLY_EXPRESSION (raw::BITFIELD_IN_EXPRESSION (e, r), t))
                            => 
                            raw::APPLY_EXPRESSION
                              ( raw::APPLY_EXPRESSION
                                  ( app ("BitSlice", t),
                                    raw::LIST_IN_EXPRESSION
                                      ( map  (\\ (a, b) = raw::TUPLE_IN_EXPRESSION [integer_constant_in_expression a, integer_constant_in_expression b])  r,
                                        NULL
                                      )
                                  ),
                                e
                              );
                        #
                        rewrite_expression_node _ (raw::LITERAL_IN_EXPRESSION (raw::BOOL_LIT FALSE))    =>  id "False";
                        rewrite_expression_node _ (raw::LITERAL_IN_EXPRESSION (raw::BOOL_LIT TRUE ))    =>  id "True";
                        #
                        rewrite_expression_node _ (raw::ID_IN_EXPRESSION (raw::IDENT([], "not" ))) =>  id "Not";
                        rewrite_expression_node _ (raw::ID_IN_EXPRESSION (raw::IDENT([], "and" ))) =>  id "And";
                        rewrite_expression_node _ (raw::ID_IN_EXPRESSION (raw::IDENT([], "cond"))) =>  id "Cond";
                        rewrite_expression_node _ (raw::ID_IN_EXPRESSION (raw::IDENT([], "or"  ))) =>  id "Or";
                        rewrite_expression_node _ (raw::ID_IN_EXPRESSION (raw::IDENT([], "||"  ))) =>  id "Par";
                        #
                        rewrite_expression_node _ e                           =>  e;
                    end;

                    all_rtls = REF [];                                                                  # All rtl definitions.

                    fun add_rtls (p, loc)
                        =
                        fns.rewrite_pattern_parsetree  p
                        where

                            fun process_naming x
                                =
                                {   my (_, t) =  mst::find_value symboltable (raw::IDENT([], x));

                                    # Duplicate 't' by doing a no-op rewrite of it:
                                    #
                                    t = fns.rewrite_type_parsetree  t
                                        where
                                            fns =  rrs::make_raw_syntax_parsetree_rewriters [ ];
                                        end;

                                    if (mt::is_typeagnostic t)
                                        #
                                        error_pos (loc, "rtl " + x + " has typeagnostic type " + t2s t);
                                    else 
                                        case t
                                            #
                                            raw::FUNTY (raw::RECORDTY lts, _) =>  all_rtls :=  (x, lts, loc) ! *all_rtls;
                                            t                       =>  error_pos (loc, "rtl " + x + " has a non-function type " + t2s t);
                                        esac;
                                    fi;
                                };

                            fun rewrite_pattern_node _ (p as raw::IDPAT x) =>  { process_naming x;  p; };
                                rewrite_pattern_node _ p              =>  {                    p; };
                            end;

                            fns =  rrs::make_raw_syntax_parsetree_rewriters [  rrs::REWRITE_PATTERN_NODE rewrite_pattern_node ];
                        end;

                    fun rewrite_declaration_node _ (raw::SUMTYPE_DECL   _) =>  raw::SEQ_DECL [];
                        rewrite_declaration_node _ (raw::TYPE_API_DECL  _) =>  raw::SEQ_DECL [];
                        rewrite_declaration_node _ (raw::VALUE_API_DECL _) =>  raw::SEQ_DECL [];
                        #
                        rewrite_declaration_node _ (raw::VAL_DECL [ raw::NAMED_VARIABLE (raw::LISTPAT (pats, NULL),
                                    raw::APPLY_EXPRESSION(
                                       raw::APPLY_EXPRESSION (raw::APPLY_EXPRESSION (raw::ID_IN_EXPRESSION (raw::IDENT([], "map")), _), f),
                                           raw::LIST_IN_EXPRESSION (es, NULL)))]
                                  )
                            =>
                            raw::VAL_DECL
                                (paired_lists::map
                                    (\\ (p, e) = raw::NAMED_VARIABLE (p, raw::APPLY_EXPRESSION (f, e)))
                                    (pats, es)
                                );

                        rewrite_declaration_node _ (raw::VAL_DECL [ raw::NAMED_VARIABLE (raw::LISTPAT (pats, NULL), raw::LIST_IN_EXPRESSION (es, NULL)) ])
                            =>
                            raw::VAL_DECL (paired_lists::map raw::NAMED_VARIABLE (pats, es));

                        rewrite_declaration_node map_decl_parsetree (raw::RTL_DECL (pattern, expression, loc))
                            => 
                            {   add_rtls (pattern, loc);
                                map_decl_parsetree (raw::VAL_DECL [raw::NAMED_VARIABLE (pattern, expression)] );
                            };

                        rewrite_declaration_node _ (raw::SOURCE_CODE_REGION_FOR_DECLARATION (_, raw::SEQ_DECL []))
                            =>
                            raw::SEQ_DECL [];

                        rewrite_declaration_node _ d
                            =>
                            d;
                    end;

                    # Define the registerkinds in a substructure C 
                    #
                    registerkind_decls
                        =
                        raw::VAL_DECL
                            (map
                                (\\ raw::REGISTER_SET { name, nickname, ... }
                                    =
                                    raw::NAMED_VARIABLE
                                      ( raw::IDPAT name, 
                                        raw::APPLY_EXPRESSION
                                          ( raw::ID_IN_EXPRESSION (raw::IDENT (["C"], "newRegisterKind")),
                                            raw::RECORD_IN_EXPRESSION
                                              [ ("name",     string_constant_in_expression     name),
                                                ("nickname", string_constant_in_expression nickname)
                                              ]
                                          )
                                      )
                                )
                                (ard::registersets_of architecture_description)
                            );

                    user_rtl_decls
                        = 
                        fns.rewrite_declaration_parsetree  rtl_decls
                        where
                            fns =   rrs::make_raw_syntax_parsetree_rewriters
                                      [
                                        rrs::REWRITE_EXPRESSION_NODE rewrite_expression_node,
                                        rrs::REWRITE_DECLARATION_NODE       rewrite_declaration_node
                                      ];
                        end;

                    all_decls
                        =
                        raw::SEQ_DECL
                          [ raw::PACKAGE_DECL ("C", [], NULL,  raw::DECLSEXP [registerkind_decls]), 
                            user_rtl_decls
                          ];
                end;                                                                    # fun coder



            ##########################################################################
            #
            # Rewrite the program to fill in all syntactic shorthands
            #
            fun expand_syntactic_sugar (architecture_description, rtl_decls)
                =
                rtl_decls
                where 
                    # Function to define a new operator:
                    #
                    fun new_rtl_op  arg_type  f
                        =
                        raw::LOCAL_DECL
                          ( [ my_fn ("newOper",      app ("newOp", string_constant_in_expression f)) ],
                            [ fun_fn (f, formals, app ("newOper", actuals)) ]
                          )
                        where
                            fun new_vars (i, n)
                                =
                                if (i < n)   ("x" + i2s i) ! new_vars (i+1, n);
                                else         [];
                                fi;

                            fun arity (raw::TUPLETY x) =>  length x;
                                arity _                =>  1;
                            end;

                            names   =  new_vars (0, arity arg_type);

                            formals =  raw::TUPLEPAT (map raw::IDPAT names);
                            actuals =  raw::LIST_IN_EXPRESSION  (map id names, NULL);
                        end;

                    #  Rewrite the program first to fill in all syntactic shorthands:
                    #
                    fun rewrite_expression_node _ (e as raw::LITERAL_IN_EXPRESSION (raw::INT_LIT   _)) =>  app ("intConst",  e);
                        rewrite_expression_node _ (e as raw::LITERAL_IN_EXPRESSION (raw::UNT1_LIT _)) =>  app ("wordConst", e);
                        rewrite_expression_node _ (e as raw::LITERAL_IN_EXPRESSION (raw::UNT_LIT   _)) =>  app ("wordConst", e);
                        rewrite_expression_node _  e                                                   =>  e;
                    end;

                    fun rewrite_declaration_node _ (raw::RTL_SIG_DECL (fs, raw::FUNTY (arg_type, _))) =>   raw::SEQ_DECL (map (new_rtl_op arg_type) fs);
                        rewrite_declaration_node _ (d as raw::RTL_SIG_DECL (fs, type))                =>   { error("bad type in " + d2s d); d; };
                        rewrite_declaration_node _ d                                                  =>   d;
                    end;

                    rtl_decls
                        = 
                        fns.rewrite_declaration_parsetree  rtl_decls
                        where
                            fns =  rrs::make_raw_syntax_parsetree_rewriters [ rrs::REWRITE_EXPRESSION_NODE rewrite_expression_node, rrs::REWRITE_DECLARATION_NODE rewrite_declaration_node ];
                        end;
                end;


            ##########################################################################
            #
            # Compile a file.
            # Turn off pattern matching warnings.
            #
            fun compile_file  filename
                =
                {   warn     = global_controls::mc::warn_on_nonexhaustive_bind ;
                    previous = *warn;

                    fun reset ()
                        =
                        warn := previous ;

                    warn := FALSE;

                    {   mythryl_compiler::rpl::read_eval_print_from_file  filename;
                        #
                        reset ();
                    }
                    except
                        e = {   reset ();
                                raise exception e;
                            };
                };


            ##########################################################################
            #
            # Process the rtl description 
            #
            fun compile architecture_description
                =
                COMPILED_RTLS
                  { architecture_description,
                    symboltable,
                    rtls     => all_rtls,
                    new_ops,
                    rtl_table
                  }
                where
                    semantics =  ard::decl_of  architecture_description  "RTL";                         # The semantics symboltable.

                    semantics =  expand_syntactic_sugar (architecture_description, semantics);          # Expand Syntactic sugar.

                    (type_inference (architecture_description, semantics))
                        ->
                        (semantics, symboltable);                                       # Perform typechecking.

                    (coder (architecture_description, symboltable, semantics))                          # Generate the rtl functions defined by the user.
                        ->
                        (user_rtl_decls, all_rtls);

                    # Generate the rtl table:
                    #
                    rtl_table
                        = 
                        if (*error_count == 0)
                            #
                            raw::VAL_DECL [raw::NAMED_VARIABLE (raw::IDPAT "rtls", raw::LIST_IN_EXPRESSION (map mk_entry all_rtls, NULL))]
                            where
                                fun mk_entry (name, args, loc)
                                    =
                                    {   fun mk_arg (arg, type)
                                            =
                                            {   my (size, kind)
                                                    =
                                                    lct::representation_of (name, arg, loc, type);

                                                ( arg,
                                                  #     
                                                  app
                                                    ( "Arg",
                                                      raw::TUPLE_IN_EXPRESSION
                                                        [ integer_constant_in_expression    size,
                                                          string_constant_in_expression kind,
                                                          string_constant_in_expression arg
                                                        ]
                                                    )
                                                );
                                            };

                                        raw::APPLY_EXPRESSION
                                          ( make_rtl_def,
                                            raw::RECORD_IN_EXPRESSION
                                              [ ("id", string_constant_in_expression name),
                                                ("args",
                                                  raw::LIST_IN_EXPRESSION ( map  (\\ (x, _) =  string_constant_in_expression x) args,
                                                            NULL
                                                          )
                                                ),
                                                ("rtl", app (name, raw::RECORD_IN_EXPRESSION (map mk_arg args)))
                                              ]
                                          );
                                    };
                            end;
                        else
                            raw::VERBATIM_CODE [];
                        fi;

                    strname =  smj::make_package_name  architecture_description  "RTL";

                    #  Now generate the code that MDGen uses 
                    code =
                        raw::LOCAL_DECL
                          (
                            [ raw::PACKAGE_DECL
                                ( strname,
                                  [ raw::VERBATIM_CODE ["Build:  Rtl_Build" ] ],
                                  NULL,
                                  raw::DECLSEXP
                                    [ raw::LOCAL_DECL
                                        ( [ raw::OPEN_DECL [raw::IDENT([], "Build")],
                                            raw::VERBATIM_CODE ["package rkj = registerkinds_junk;"]
                                          ],
                                          [user_rtl_decls])
                                    ]
                                ),

                              raw::PACKAGE_DECL
                                ( strname,
                                  [],
                                  NULL,
                                  raw::APPSEXP ( raw::IDSEXP (raw::IDENT ([], strname)),
                                            raw::IDSEXP (raw::IDENT ([], "adl_rtl_builder"))
                                          )
                                ),

                              raw::LOCAL_DECL
                                ( [ raw::OPEN_DECL
                                     [ raw::IDENT ([], "adl_rtl_builder"),
                                       raw::IDENT ([], strname)
                                     ]
                                  ],
                                  [rtl_table]
                                )
                            ],

                            [ raw::VERBATIM_CODE [ "adl_rtl_comp::current_rtls := rtls;" ] ]
                          );

                    # Compile RTL into internal form:
                    #
                    fun typecheck_rtl  code
                        = 
                        if (*error_count == 0)
                            #
                            {   current_rtls := [] ;

                                make_filename
                                    =
                                    \\ architecture_name                                        # Architecture name can be "pwrpc32"|"sparc32"|"intel32". 
                                        =
                                        sprintf "CompileRTL-%s.pkg" architecture_name;

                                print "Generating ML code for computing RTLs...\n";

                                smj::write_sourcecode_file
                                  {
                                    architecture_description,
                                    created_by_package => "src/lib/compiler/back/low/tools/arch/adl-rtl-comp-g.pkg",
                                    #
                                    subdir        => "",                                                                                # Relative to file containing architecture description.
                                    make_filename,
                                    code          => [rsu::decl code]
                                  };

                                filename =  smj::make_sourcecode_filename  { architecture_description, subdir => "", make_filename };

                                print "Calling the ML compiler to build the rtls ...\n";
                                print "This may take a while...\n";

                                compile_file  filename;
                            };
                        fi;


                    # Execute the code:
                    # 
                    typecheck_rtl  code;
                    new_ops = adl_rtl_builder::get_new_ops ();
                    adl_rtl_builder::clear_new_ops ();

                    # Build a table of rtls:
                    #
                    rtl_table
                        =
                        ht::make_hashtable
                            (hash_string::hash_string, (==))
                            { size_hint => 32, not_found_exception => NO_RTL };

                    all_rtls  = *current_rtls;

                    apply
                        (\\ def as RTLDEF { id, ... }
                            =
                            ht::set  rtl_table (id, def)
                        )
                        all_rtls;
                end;


            ##########################################################################
            #
            # Prettyprint RTL code. 
            #
            fun dump_log (COMPILED_RTLS { architecture_description, rtls, new_ops, ... } )
                = 
                err::write_to_log (string::cat text)
                where
                    fun pr_new_op { name, hash, attributes }
                        = 
                        "New abstract operator " + name + "\n";

                    fun pr_rtl (def as RTLDEF { id=>f, args, rtl, ... } )
                        =
                        {   fun listify es
                                =
                                fold_backward  f  ""  es
                                where
                                    fun f (x, "") =>  x;
                                        f (x, y ) =>  x + ", " + y;
                                    end;
                                end;

                            fun prs es
                                =
                                listify (map rtl::exp_to_string es);

                            fun prs' es
                                =
                                listify  (map  (\\ (e, r) = rtl::exp_to_string e + "=" + i2s r)  es);

                            pretty = string::translate
                                        #
                                        \\ '\n' => "\n\t";
                                           ';'  => " ||";
                                            c   => char::to_string c;
                                        end;

                            (rtl::def_use  rtl) ->   (d, u);

                            (rtl::naming_constraints (d, u))
                                ->
                                { fixed_defs, fixed_uses, two_address };

                            rtl_text = pretty (rtl::rtl_to_string  rtl);

                            rtl = art::simplify rtl;

                            fun line (title, ""  ) =>  "";
                                line (title, text) =>  "\t" + title + ":\t" + text + "\n";
                            end;

                            "rtl "
                            + f
                            + "{ "
                            + list::fold_backward
                                  \\  (x, "") =>  x;
                                      (x, y ) =>  x + ", " + y;
                                  end
                                  ""
                                  args
                            + " } =\n\t" + rtl_text + "\n"
                            + line ("Define", prs d)
                            + line ("Use",    prs u)
                            + line ("Pinned definitions", prs' fixed_defs)
                            + line ("Pinned uses", prs' fixed_uses)
                            + line ("Two address operand", prs two_address)
                            + line ("Constructor", spp::prettyprint_expression_to_string (rsu::decl    (art::rtl_to_fun (f, args, rtl))))
                            + line ("Destructor",  spp::prettyprint_expression_to_string (rsu::pattern (art::rtl_to_pattern  rtl)))
                            + "\n";
                        };

                    # Sort them alphabetically:
                    #
                    rtls =  lms::sort_list
                                #
                                (\\ ( RTLDEF { id => f, ... },
                                      RTLDEF { id => g, ... }
                                    )
                                    =
                                    string::(>) (f, g)
                                )
                                #
                                rtls;

                    n_rtls    =  length rtls;
                    n_new_ops =  length new_ops;

                    text = 
                        "There are a total of " ! i2s n_rtls    ! " rtl templates defined.\n"  !
                        "There are a total of " ! i2s n_new_ops ! " new abstract operators.\n" !
                        "RTL information follows:\n\n" !
                        map pr_new_op new_ops
                        @ ["\n\n"]
                        @ map pr_rtl rtls
                        ;
                end;


            ##########################################################################
            #
            # Gnerate code the ArchRTL generic 
            #
            fun gen_arch_generic (COMPILED_RTLS { architecture_description, rtls, new_ops, ... } )
                = 
                {   strname = smj::make_package_name  architecture_description  "RTL";          # The ArchRTL generic.

                    # The main body is just the RTL constructor functions:
                    #
                    decls = 
                        raw::VERBATIM_CODE ["package t = RTL::T"]
                        !
                        raw::PACKAGE_DECL
                          ( "P",
                            [],
                            NULL,
                            raw::DECLSEXP
                              (map  art::create_new_op new_ops)
                          )
                        !
                        map (\\ RTLDEF { id, args, rtl }
                                =
                                art::rtl_to_fun  (id, args, rtl)
                            )
                            rtls
                        ;

                    arch_rtl
                        = 
                        raw::PACKAGE_DECL
                          (
                            strname,
                            [ raw::VERBATIM_CODE [ "package rtl:  Treecode_Rtl",
                                    "package c:    " +  smj::make_api_name  architecture_description  "registers"
                                  ]
                            ],
                            NULL,
                            raw::DECLSEXP decls
                          );

                    # Write the generic to a file:
                    #
                    smj::write_sourcecode_file
                      {
                        architecture_description,
                        created_by_package =>  "src/lib/compiler/back/low/tools/arch/adl-rtl-comp-g.pkg",
                        #
                        subdir        =>  "treecode",                                                           # Relative to file containing architecture description.
                        make_filename =>  \\ architecture_name = sprintf "RTL-%s.pkg" architecture_name,        # architecture_name can be "pwrpc32"|"sparc32"|"intel32".
                        code          =>  [ rsu::decl arch_rtl ]
                      };

                    ();
                };



            ##########################################################################
            #
            # Generic routine for generating query functions from rtl definitions.
            #
            fun make_query' warning (COMPILED_RTLS { rtls, architecture_description, rtl_table, ... } )
                =
                mk_query_fun
                where   
                    instructions =  ard::base_ops_of  architecture_description;                 # The instructions.

                    Rtlpat
                        = LIT  String 
                        | TYPE (String, raw::Sumtype)
                        ;

                    # Look up rtl:
                    #
                    fun look_up_rtl name
                        =
                        ht::look_up  rtl_table  name
                        except
                            e = {   warning ("Can't find definition for rtl " + name);
                                    raise exception e;
                                };

                    # Error handler:
                    #
                    error_handler               = app ("undefined", raw::TUPLE_IN_EXPRESSION []);
                    error_handling_clause       = raw::CLAUSE ([raw::WILDCARD_PATTERN], NULL, error_handler);

                    fun mk_query_fun { named_arguments, name, args, body, case_args, decls }
                        =
                        {
                            extra_case_args
                                =
                                map id case_args;

                            # Generate constants:
                            #
                            const_table =  cst::new_const_table ();
                            mk_const    =  cst::const const_table;

                            # Enumerate all rtl patterns and generate a case expression
                            # that branch to different cases.
                            #
                            fun foreach_rtl_pattern  gen_code  rtlpats
                                =
                                raw::CASE_EXPRESSION (tupleexp (exps @ extra_case_args), clauses)
                                where
                                    fun an_enum ([], pats, name)
                                            =>
                                            [ (pats, name) ];

                                        an_enum (LIT s ! rest, pats, name)
                                            =>
                                            an_enum (rest, pats, s + name);

                                        an_enum (TYPE (_, raw::SUMTYPE { cbs, ... } ) ! rest, pats, name)
                                            =>
                                            list::cat  names
                                            where
                                                names
                                                    =
                                                    map (\\ cb as raw::CONSTRUCTOR { name => constructor_name, ... }
                                                            =
                                                            {   pattern
                                                                    = 
                                                                    rst::map_cons_to_pattern
                                                                        { prefix => ["I"],
                                                                          id     => \\ { new_name, ... } =  raw::IDPAT new_name
                                                                        }
                                                                        cb;

                                                                an_enum (rest, pattern ! pats, constructor_name + name);
                                                            }
                                                        )
                                                        cbs;
                                            end;

                                        an_enum _ =>   raise exception DIE "Bug: Unsupported case in  make_query'/mk_query_fun/foreach_rtl_pattern/an_enum.";
                                    end;                                                                                        # fun an_enum

                                    fun case_exps []                   =>  [];
                                        case_exps (LIT _       ! rest) =>  case_exps rest;
                                        case_exps (TYPE (x, _) ! rest) =>  id x ! case_exps rest;
                                    end;

                                    exps    =  case_exps rtlpats;
                                    cases   =  an_enum (reverse rtlpats, [], "");
                                    clauses =  map gen_code cases;
                                end

                            # Enumerate each instruction:
                            # 
                            also
                            fun do_instr (raw::CONSTRUCTOR { rtl=>NULL, ... } )
                                    =>
                                    raise exception NO_RTL;

                                do_instr (instruction as raw::CONSTRUCTOR { rtl=>THE rtl_def, loc, ... } )
                                    =>
                                    {   fns = rrs::make_raw_syntax_parsetree_rewriters [ rrs::REWRITE_EXPRESSION_NODE rewrite_expression_node ];
                                        #
                                        fns.rewrite_expression_parsetree  rtl_def;
                                    }
                                    where
                                        set_loc  loc;

                                        e''' =  rst::cons_namings instruction;                          # Namings for the instruction.

                                        # Translate rtl definition:
                                        #
                                        fun trans (raw::TEXTASM s)
                                                =>
                                                LIT s;

                                            trans (raw::EXPASM (raw::ID_IN_EXPRESSION (raw::IDENT([], x))))
                                                => 
                                                TYPE (x, db)
                                                where
                                                    my (_, type) =   e''' x    except _ = fail("unknown identifier " + x + " in rtl expression: " + e2s rtl_def);

                                                    db =    case type
                                                                #
                                                                raw::IDTY (raw::IDENT ([], name)) =>  ard::find_instruction_sumtype  architecture_description  name;
                                                                t                                 =>  fail("illegal type " + t2s t);
                                                            esac;
                                                end;

                                            trans (raw::EXPASM e)
                                                =>
                                                fail("illegal rtl expression " + e2s e);
                                        end;

                                        fun rewrite_expression_node _ (e as raw::RTL_IN_EXPRESSION [raw::COMPOSITERTL _]) =>  e;
                                            rewrite_expression_node _ (     raw::ASM_IN_EXPRESSION (raw::ASMASM rtl)    ) =>  foreach_rtl_pattern  (gen_code (instruction, e'''))  (map trans rtl);
                                            rewrite_expression_node _ _                                                   =>  raise exception DIE "Bug:  Unsupported case in rewrite_expression_node";
                                        end;
                                    end;                                                                                                                # where
                            end                                                                                                                         # fun do_instr

                            # Call the user defined callback and generate code:
                            #
                            also
                            fun gen_code (instruction, e''') (pats, rtl_name)
                                =
                                raw::CLAUSE ([tuplepat (pats @ case_pats)], NULL, expression)
                                where
                                    my rtl as RTLDEF { args, ... }
                                        =
                                        look_up_rtl  rtl_name;

                                    my { case_pats, expression }
                                        = 
                                        body { const=>mk_const, rtl, instruction };

                                    fun simp_list  ps
                                        = 
                                        {   fun loop []
                                                    =>
                                                    [];

                                                loop (raw::WILDCARD_PATTERN ! ps)
                                                    =>
                                                    case (loop ps)
                                                        #
                                                        [] =>  [];
                                                        ps =>  raw::WILDCARD_PATTERN ! ps;
                                                    esac;

                                                loop (p ! ps)
                                                    =>
                                                    p ! loop ps;
                                            end;

                                            case (loop ps)
                                                #
                                                [] =>  raw::WILDCARD_PATTERN;
                                                ps =>  raw::LISTPAT (ps, THE raw::WILDCARD_PATTERN);
                                            esac;
                                        };

                                    fun simplify_pattern (raw::LISTPAT (ps, NULL)                ) =>  simp_list ps;
                                        simplify_pattern (raw::LISTPAT (ps, THE raw::WILDCARD_PATTERN)) =>  simp_list ps;
                                        simplify_pattern (raw::TUPLEPAT [p]                      ) =>  simplify_pattern p;
                                        #
                                        simplify_pattern  pattern =>   pattern;
                                    end;

                                    case_pats =  map  simplify_pattern  case_pats;
                                end
                                except _ = error_handling_clause;


                            Err = OK | BAD;

                            # Process all instructions:
                            # 
                            fun foreach_instr ([], OK ) =>  [];
                                foreach_instr ([], BAD) =>  [ error_handling_clause ];

                                foreach_instr (instruction ! instrs, err)
                                    =>
                                    {   rst::map_cons_to_clause
                                          {
                                            prefix     =>  ["I"],
                                            pattern    =>  \\ pattern = pattern,
                                            expression =>  do_instr instruction
                                          }
                                          instruction
                                          !
                                          foreach_instr (instrs, err);
                                    }
                                    except _ = foreach_instr (instrs, BAD);
                            end;

                            clauses = foreach_instr (instructions, OK);

                            query_fun = raw::FUN_DECL [raw::FUN ("query", clauses) ];

                            # How to make an argument:
                            # If the argument has more than one
                            # name we'll first pack them into a record pattern. 
                            #
                           fun mk_arg [x]
                                    =>
                                    raw::IDPAT x;

                               mk_arg xs
                                    =>
                                    if named_arguments   raw::RECORD_PATTERN   (map (\\ x = (x, raw::IDPAT x)) xs,   FALSE);
                                    else                 raw::TUPLEPAT (map raw::IDPAT xs);
                                    fi;
                            end;

                            wrapper
                                =
                                [ raw::FUN_DECL
                                    [ raw::FUN
                                        ( name, 
                                          [ raw::CLAUSE
                                              ( map mk_arg args,  
                                                NULL,
                                                raw::LET_EXPRESSION
                                                  ( decls @ [query_fun], 
                                                    [ app ("query", id "instruction") ]
                                                  )
                                              )
                                          ]
                                        )
                                    ]
                                ];

                            constants =  cst::gen_consts  const_table;

                            rst::simplify_declaration
                                #
                                case constants
                                    #
                                    [] =>  raw::SEQ_DECL wrapper;
                                     _ =>  raw::LOCAL_DECL (constants, wrapper);
                                esac;
                        };

                end;

            make_query =  make_query' (\\ _ = ());



            ##########################################################################
            #
            # Generic routine that enumerates all arguments in an 
            # instruction constructor.
            #
            fun forall_args { instruction, rtl=>RTLDEF { rtl, ... }, rtl_arg, non_rtl_arg } unit
                =
                rst::fold_cons every unit instruction
                where   
                    look_up_arg =  rtl::arg_of  rtl;

                    fun every ( { orig_name, new_name, type }, x)
                        =
                        {   (look_up_arg new_name) ->   (expression, pos);
                            #
                            rtl_arg (new_name, type, expression, pos, x);
                        }
                        except rtl::NOT_AN_ARGUMENT = non_rtl_arg (new_name, type, x);
                end;


            ##########################################################################
            #
            # Generic routine for generating a query function on the operand type 
            #
            fun mk_operand_query  compiled_rtls
                = 
                {   architecture_description =  architecture_description_of  compiled_rtls;
                    ();
                };


            ##########################################################################
            #
            # Generic routine that maps an instruction
            #
            fun map_instr { instruction, rtl=>RTLDEF { rtl, ... }, rtl_arg, non_rtl_arg }
                =
                if *changed    expression;
                else           id "instruction";
                fi
                where
                    look_up_arg =  rtl::arg_of  rtl;

                    changed =  REF FALSE;

                    fun map_arg { orig_name, new_name, type }
                        =
                        {   (look_up_arg  new_name) ->   (expression, pos);
                            #
                            case (rtl_arg (new_name, type, expression, pos))
                                #
                                THE e =>  {   changed := TRUE;   e;  };
                                NULL  =>  id new_name;
                            esac;
                        }
                        except
                            rtl::NOT_AN_ARGUMENT
                                =
                                case (non_rtl_arg (new_name, type))
                                    #
                                    THE e =>  {   changed := TRUE;   e;   };
                                    NULL  =>  id new_name;
                                esac;

                    expression
                        =
                        rst::map_cons_to_expression
                          {
                            prefix =>  ["I"],
                            id     =>  map_arg
                          }
                          instruction;
                end;


            ##########################################################################
            #
            # Generate RTL code for def/use like queries
            #
            fun make_def_use_query  compiled_rtls   { name, decls, def, use, named_arguments, args }
                = 
                if *trivial   fun_fn (name, raw::WILDCARD_PATTERN, raw::TUPLE_IN_EXPRESSION [nil, nil] );
                else          decl;
                fi
                where
                    architecture_description =  architecture_description_of  compiled_rtls;

                    trivial = REF TRUE;

                    nil = raw::LIST_IN_EXPRESSION ([], NULL);

                    fun def_use_body { instruction, rtl=>RTLDEF { rtl, ... }, const }
                        = 
                        { expression => raw::TUPLE_IN_EXPRESSION [d, u],
                          case_pats  => []
                        }
                        where
                            namings =   rst::fold_cons
                                            (\\( { new_name, type, ... }, l''') =  (new_name, type) ! l''')
                                            []
                                            instruction;

                            fun look_up id
                                =
                                list::find   (\\ (x, _) =  x==id)  namings;

                            fun add (f, x, e, y)
                                =
                                case (f (x, e, y))
                                    #
                                    THE e =>  e;
                                    NULL  =>  y;
                                esac;

                            fun fold f (e as tcf::ARG(_, _, x),                  expression) =>  add (f, id x, e, expression);
                                fold f (e as tcf::ATATAT(_, _, tcf::ARG(_, _, x)), expression) =>  add (f, id x, e, expression);

                                fold f (e as tcf::ATATAT(_, k, tcf::LITERAL i), expression)
                                    =>
                                    add (f, const register, e, expression)
                                    where
                                        (ard::find_registerset_by_name  architecture_description  (rkj::name_of_registerkind  k))
                                            ->
                                            raw::REGISTER_SET { name, ... };

                                        register
                                            = 
                                            raw::APPLY_EXPRESSION
                                              ( raw::APPLY_EXPRESSION
                                                  ( raw::ID_IN_EXPRESSION (raw::IDENT (["C"], "Reg")),
                                                    raw::ID_IN_EXPRESSION (raw::IDENT (["C"], name ))
                                                  ),
                                                integer_constant_in_expression (multiword_int::to_int i)
                                              );
                                    end;

                                fold f (_, expression)
                                    =>
                                    expression;
                            end;

                            (rtl::def_use rtl) ->   (d, u);

                            d =  list::fold_backward  (fold def)  nil  d;
                            u =  list::fold_backward  (fold use)  nil  u;

                            case (d, u)
                                #
                                ( raw::LIST_IN_EXPRESSION ([], NULL),
                                  raw::LIST_IN_EXPRESSION ([], NULL)
                                )                      =>   ();
                                #
                                _                      =>   trivial := FALSE;
                            esac;
                        end;                                                            # fun def_use_body

                    decl =   make_query
                                 compiled_rtls
                                 { name, named_arguments, args, decls, case_args=> [], body=>def_use_body };
                end;

            ##########################################################################
            #
            # Make a simple error handler
            #
            fun simple_error_handler  name
                =
                raw::VERBATIM_CODE ["fun undefined () = error \"" + name + "\""];


            ##########################################################################
            #
            # Make a complex error handler
            #
            fun complex_error_handler  name
                =
                raw::VERBATIM_CODE ["fun undefined () = bug(\"" + name + "\", instruction)"];


            ##########################################################################
            #
            # Make a complex error handler
            #
            fun complex_error_handler_def ()
                =
                raw::VERBATIM_CODE [ "fun bug (msg, instruction) =",
                      "stipulate my Asm::S.STREAM { emit, ... } = Asm::make_stream []",
                      "herein  emit instruction; error msg end"
                    ];

            ##########################################################################
            #
            # Do consistency checking on the RTL and instruction representation.
            # Call mkQuery to test the entire process.  
            #
            fun consistency_check  compiled_rtls
                =
                {   architecture_description =  architecture_description_of  compiled_rtls;

                    # Check one instruction:
                    #
                    fun check
                          { instruction as raw::CONSTRUCTOR { name=>instruction_name, ... },
                            rtl => RTLDEF { id=>f, args, rtl, ... },
                            const
                          }
                        = 
                        { case_pats  =>  [],
                          expression =>  raw::TUPLE_IN_EXPRESSION []
                        } 
                        where
                            # Find all arguments in the instruction constructor:
                            #
                            namings
                                =
                                rst::fold_cons
                                    #
                                    (\\( { new_name, type, ... }, l''')
                                        = 
                                        (new_name, REF FALSE, type) ! l'''
                                    )
                                    #
                                    []
                                    instruction;

                            fun look_up id
                                =
                                list::find
                                    (\\ (x, _, _) =   x==id)
                                    namings;

                            look_up_rtl_arg =  rtl::arg_of  rtl;

                            fun check_it (x, expression, pos, type)
                                =
                                {   fun err  why
                                        =
                                        {   error("in instruction " + instruction_name + " (rtl " + f + "):");

                                            if (why != "")  write_to_log_and_stderr  why;    fi;

                                            write_to_log_and_stderr ("rtl argument " + re2s expression + " cannot be represented as " + t2s type);
                                        };

                                    lct::insert_rep_coercion (expression, type);

                                    case (expression, type)
                                        #
                                        (tcf::ATATAT(_, k, tcf::ARG _), raw::REGISTER_TYPE registerkind)
                                            => 
                                            {   (ard::find_registerset_by_name  architecture_description  registerkind)
                                                    ->
                                                    raw::REGISTER_SET { name, ... };

                                                if (rkj::name_of_registerkind k  !=  name)
                                                    #
                                                    err "registerkind mismatched";
                                                fi;
                                            };

                                        (expression, raw::REGISTER_TYPE _)
                                            =>
                                            err "rtl is not a register reference";

                                        (tcf::ATATAT(_, _, tcf::ARG _), type)
                                            =>
                                            err "";

                                        (tcf::ARG (type, REF (tcf::REPX k), _), raw::IDTY (raw::IDENT(_, name_of_type)))
                                            => 
                                            if (k != name_of_type)   err "representation mismatch";  fi;

                                        (_, _)
                                            =>
                                            err "";
                                    esac;
                                }
                                except _ = ();

                            # Check one argument in rtl:
                            #
                            fun check_rtl_arg  x
                                =
                                {   (look_up_rtl_arg  x) ->   (expression, pos);

                                    case (look_up x)
                                        #       
                                        THE (_, found, type)
                                            =>
                                            {   found := TRUE;
                                                check_it (x, expression, pos, type);
                                            };

                                        NULL =>  error("'" + x + "' of rtl " + f + " is missing from instruction " + instruction_name);
                                    esac;
                                };

                            # Check one argument in instruction:
                            #
                            fun check_instr_arg (name, REF TRUE, type)
                                    =>
                                    ();

                                check_instr_arg (name, REF FALSE, type)
                                    =>
                                    if (lct::is_special_rep_type type)
                                        #
                                        warning ("In instruction " + instruction_name + " (rtl " + f + "): '"
                                                + name + "' has type "
                                                + t2s type + " but its meaning is unspecified in the rtl"
                                                );
                                    fi;
                            end;

                            apply check_rtl_arg    args;
                            apply check_instr_arg  namings;
                        end;                                                                            # fun check

                    print "Consistency checking...\n";

                    make_query'
                        warning
                        compiled_rtls 
                        { name            =>  "check",
                          named_arguments =>  FALSE,
                          args            =>  [],
                          decls           =>  [],
                          case_args       =>  [],
                          body            =>  check
                        };

                    ();
                };

            ##########################################################################
            #
            # Generate RTL code and write the log
            #
            fun gen compiled_rtls
                =
                {   gen_arch_generic   compiled_rtls;
                    consistency_check  compiled_rtls;
                };
        end;                                                                                            # stipulate
    };                                                                                                  # generic package   adl_rtl_comp_g
end;                                                                                                    # stipulate





Comments and suggestions to: bugs@mythryl.org

PreviousUpNext