PreviousUpNext

15.4.422  src/lib/compiler/back/low/tools/arch/make-sourcecode-for-translate-machcode-to-asmcode-xxx-g-package.pkg

## make-sourcecode-for-translate-machcode-to-asmcode-xxx-g-package.pkg -- derived from ~/src/sml/nj/smlnj-110.60/MLRISC/Tools/ADL/mdl-gen-asm.sml
#
# This module generates the assembler of an architecture 
# given an architecture description.
#
# This currently generates
#     src/lib/compiler/back/low/intel32/emit/translate-machcode-to-asmcode-intel32-g.codemade.pkg
#     src/lib/compiler/back/low/pwrpc32/emit/translate-machcode-to-asmcode-pwrpc32-g.codemade.pkg
#     src/lib/compiler/back/low/sparc32/emit/translate-machcode-to-asmcode-sparc32-g.codemade.pkg

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



###                      "Why should I be worried about dying?
###                       It's not going to happen in my lifetime!"
###
###                                        -- Raymond Smullyan 



stipulate
    package ard =  architecture_description;                            # architecture_description                              is from   src/lib/compiler/back/low/tools/arch/architecture-description.pkg
herein

    api Make_Sourcecode_For_Translate_Machcode_To_Asmcode_Xxx_G_Package {
        #
        make_sourcecode_for_translate_machcode_to_asmcode_xxx_g_package
            :
            ard::Architecture_Description -> Void;
    };
end;

# We are run-time invoked in:
#     src/lib/compiler/back/low/tools/arch/make-sourcecode-for-backend-packages-g.pkg

# We are compile-time invoked in:
#     src/lib/compiler/back/low/tools/arch/make-sourcecode-for-backend-packages.pkg

stipulate
    package ard =  architecture_description;                            # architecture_description                              is from   src/lib/compiler/back/low/tools/arch/architecture-description.pkg
    package err =  adl_error;                                           # adl_error                                             is from   src/lib/compiler/back/low/tools/line-number-db/adl-error.pkg
    package smj =  sourcecode_making_junk;                              # sourcecode_making_junk                                is from   src/lib/compiler/back/low/tools/arch/sourcecode-making-junk.pkg
    package mst =  adl_symboltable;                                     # adl_symboltable                                       is from   src/lib/compiler/back/low/tools/arch/adl-symboltable.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 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 spp =  simple_prettyprinter;                                # simple_prettyprinter                                  is from   src/lib/prettyprint/simple/simple-prettyprinter.pkg
    #
    ++     =  spp::CONS;    infix my ++ ;
    alpha  =  spp::ALPHABETIC;
    iblock =  spp::INDENTED_BLOCK;
    indent =  spp::INDENT;
    nl     =  spp::NEWLINE;
    punct  =  spp::PUNCTUATION;
herein

    package   make_sourcecode_for_translate_machcode_to_asmcode_xxx_g_package
    : (weak)  Make_Sourcecode_For_Translate_Machcode_To_Asmcode_Xxx_G_Package
    {


        fun make_sourcecode_for_translate_machcode_to_asmcode_xxx_g_package   architecture_description
            =
            smj::write_sourcecode_file
              {
                architecture_description,
                created_by_package =>  "src/lib/compiler/back/low/tools/arch/make-sourcecode-for-translate-machcode-to-asmcode-xxx-g-package.pkg",
                #
                subdir        =>  "emit",                                                                                                                       # Relative to file containing architecture description.
                make_filename =>  fn architecture_name = sprintf "translate-machcode-to-asmcode-%s-g.codemade.pkg"  architecture_name,                          # architecture_name can be "pwrpc32" | "sparc32" | "intel32".
                code          =>  [ pkg_code ]
              }
            where
                architecture_name =  ard::architecture_name_of  architecture_description;               # "intel32"/"sparc32"/"pwrpc32"
                archl = string::to_lower architecture_name;
                archm = string::to_mixed architecture_name;

                # Name of the generic and api:
                #
#               pkg_name =  smj::make_package_name architecture_description "asm_emitter";
                api_name =  "Machcode_Codebuffer";

                # Arguments of the generic:
                # 
                args =  [
                          "package cst: Codebuffer;\t\t\t\t\t\t\t# Codebuffer\t\t\tis from   src/lib/compiler/back/low/code/codebuffer.api",
                          "",
                  sprintf "package mcf: Machcode_%s\t\t\t\t\t\t\t# Machcode_%s\t\tis from   src/lib/compiler/back/low/%s/code/machcode-%s.codemade.api" archm archm archl archl,
                          "             where",
                          "                 tcf == cst::pop::tcf;\t\t\t\t# \"tcf\" == \"treecode_form\".",
                          "",
                  sprintf "package crm: Compile_Register_Moves_%s\t\t\t\t\t# Compile_Register_Moves_%s\tis from   src/lib/compiler/back/low/%s/code/compile-register-moves-%s.api" archm archm archl archl,
                          "             where",
                          "                 mcf == mcf;",
                          "",
                          "package tce: Treecode_Eval\t\t\t\t\t\t\t# Treecode_Eval\t\t\tis from   src/lib/compiler/back/low/treecode/treecode-eval.api",
                          "             where",
                          "                 tcf == mcf::tcf;\t\t\t\t\t# \"tcf\" == \"treecode_form\".",
                          ""
                        ];

                # Append to above the argument to the generic package 'Assembly'
                # in our architecture description file, which will
                # currently be one of
                #       
                #     src/lib/compiler/back/low/pwrpc32/pwrpc32.architecture-description
                #     src/lib/compiler/back/low/sparc32/sparc32.architecture-description
                #     src/lib/compiler/back/low/intel32/intel32.architecture-description
                #
                # For intel32.architecture-description the appended part looks in SML syntax like
                #
                #     structure mem_regs: Machcode_Address_Of_Ramreg_Intel32 where mcf = machcode_form
                #         val mem_reg_base: rkj.Register option
                #
                # which when translated into Mythryl syntax looks like:
                #
                #     package mem_regs:    Machcode_Address_Of_Ramreg_Intel32 where mcf == machcode_form;
                #     mem_reg_base:  Null_Or( rkj::Codetemp_Info );
                #
                args = raw::SEQ_DECL
                        [ raw::VERBATIM_CODE args,
                          ard::generic_arg_of  architecture_description  "Assembly"
                        ];


                registerkinds =  ard::registersets_of  architecture_description;                            # Registerkinds declared by the user.

                asm_case =  ard::asm_case_of  architecture_description;                             # Assembly case.

                # How to make a string expression:
                #
                fun make_string s
                    =
                    rsj::string_constant_in_expression
                        #       
                        case asm_case
                            #
                            raw::VERBATIM  =>  s;
                            raw::LOWERCASE =>  string::map  char::to_lower  s;
                            raw::UPPERCASE =>  string::map  char::to_upper  s;
                        esac;

                # The Instruction package:
                #
                symboltable = mst::find_package
                                 (ard::symboltable_of  architecture_description)
                                 (raw::IDENT ([], "Instruction"));

                # All datatype definitions in this package:
                # 
                datatype_definitions
                    =
                    mst::datatype_definitions  symboltable;


                # There are three assembly modes:
                #   EMIT: directly emit to stream
                #   ASM:  convert to string
                #   NOTHING: do nothing
                #
                Mode = EMIT | ASM | NOTHING;


                # Find out which assembly mode a datatype should use:
                #
                fun mode_of (raw::DATATYPE { cbs, asm, ... } )          # "cbs" is "CONS bindings"
                        =>
                        loop (cbs, mode)
                        where
                            mode =  if asm    ASM;
                                    else      NOTHING;
                                    fi;

                            # Where raw::CONSTRUCTOR.asm -> THE (raw::ASMASM a),
                            # search list a for raw::EXPASM.
                            # Return EMIT if found, else the given mode:
                            #
                            fun loop2 ([],                m) =>  m;
                                loop2 (raw::EXPASM _ ! _, _) =>  EMIT;
                                loop2 (_             ! a, m) =>  loop2 (a, m);
                            end;

                            # Search a raw::DATATYPE.cbs list;
                            # if any raw::CONSTRUCTOR.asm -> THE(raw::STRINGASM)
                            # or     raw::CONSTRUCTOR.asm -> THE(raw::ASMASM a)
                            # then return ASM, except that a raw::EXPASM in 'a' means
                            # to   return EMIT:
                            #
                            fun loop ([], m   ) =>  m;
                                loop (_,  EMIT) =>  EMIT;
                                #
                                loop (raw::CONSTRUCTOR { asm => NULL,                   ... } ! cbs, m) =>   loop (cbs, m);
                                loop (raw::CONSTRUCTOR { asm => THE (raw::STRINGASM _), ... } ! cbs, _) =>   loop (cbs, ASM);
                                loop (raw::CONSTRUCTOR { asm => THE (raw::ASMASM a),    ... } ! cbs, m) =>   loop (cbs, loop2 (a, ASM));
                            end;
                        end;

                    mode_of _ =>   raise exception FAIL "Bug: Unsupported case in mode_of";
                end;


                # How to emit special types:
                #
                fun put_type (id, raw::IDTY (raw::IDENT (prefix, t)), e)
                        =>
                        case (prefix, t)
                            #
                            ([],                "int"             ) =>  rsj::app ("put_" + t, e);
                            ([],                "string"          ) =>  rsj::app ("emit", e);
                            (["Constant"],      "const"           ) =>  rsj::app ("put_" + t, e);
                            (["Label"],         "label"           ) =>  rsj::app ("put_" + t, e);
                            (["treecode_form"], "label_expression") =>  rsj::app ("put_" + t, e);
                            (["Region"],        "ramregion"       ) =>  rsj::app ("put_" + t, e);
                            #
                            _ =>
                                {   fun f (db as raw::DATATYPE { name=>id', ... })  =>  t == id' and mode_of db != NOTHING;
                                        f _                                         =>  raise exception FAIL "Bug: Unsupported case in put_type/f.";
                                    end;

                                    if (list::exists f datatype_definitions)    rsj::app ("put_" + t,  e);
                                    else                                        rsj::app ("put_" + id, e);
                                    fi;
                                };
                        esac;

                    put_type (_, raw::REGISTER_TYPE "registerset",  e) =>   rsj::app ("put_registerset",        e);
                    put_type (_, raw::REGISTER_TYPE k,              e) =>   rsj::app ("put_register",           e);
                    put_type (id, _,                                e) =>   rsj::app ("put_" + id,              e);
                end;

                # Here we are driven by the contents of package "Instruction" in our
                # architecture description file, which currently means one of 
                #
                #     src/lib/compiler/back/low/intel32/intel32.architecture-description
                #     src/lib/compiler/back/low/pwrpc32/pwrpc32.architecture-description
                #     src/lib/compiler/back/low/sparc32/sparc32.architecture-description
                #
                # For each datatype "foo" defined in the package Instruction that
                # has prettyprinting annotations attached we generate an assembly
                # function "asm_foo" and an emit function "put_foo".
                #
                # Example such functions on intel32 include:
                #
                #         fun asm_cond (mcf::EQ) => "e";
                #             asm_cond (mcf::NE) => "ne";
                #             asm_cond (mcf::LT) => "l";
                #             asm_cond (mcf::LE) => "le";
                #             asm_cond (mcf::GT) => "g";
                #             asm_cond (mcf::GE) => "ge";
                #             asm_cond (mcf::BB) => "b";
                #             asm_cond (mcf::BE) => "be";
                #             asm_cond (mcf::AA) => "a";
                #             asm_cond (mcf::AE) => "ae";
                #             asm_cond (mcf::CC) => "c";
                #             asm_cond (mcf::NC) => "nc";
                #             asm_cond (mcf::PP) => "p";
                #             asm_cond (mcf::NP) => "np";
                #             asm_cond (mcf::OO) => "o";
                #             asm_cond (mcf::NO) => "no";
                #         end 
                #
                #         also
                #         fun put_cond x = emit (asm_cond x)
                #
                fun make_asms ((db as raw::DATATYPE { name, cbs, ... } ) ! dbs, fbs)                                    # "dbs" == "datatype bindings", "cbs" == "constructor bindings".
                        =>
                        case (mode_of db)
                            #
                            NOTHING =>  make_asms (dbs,                                                                            fbs);
                            EMIT    =>  make_asms (dbs,                      raw::FUN ("put_" + name, make_asm_fun (EMIT, cbs)) ! fbs);
                            ASM     =>  make_asms (dbs, make_emit_fun name ! raw::FUN ("asm_"  + name, make_asm_fun (ASM,  cbs)) ! fbs);
                        esac;

                    make_asms ([], fbs)                                                                                 # "fbs" == "function bindings".
                        =>
                        reverse fbs;

                    make_asms _ =>   raise exception FAIL "Bug: Unsupported case in make_asms";             
                end

                # Here we're synthesizing raw syntax for
                #
                #     fun put_foo x =  emit (asm_foo x)
                #
                also
                fun make_emit_fun id
                    = 
                    raw::FUN ( "put_" + id,
                              [ raw::CLAUSE ( [raw::IDPAT "x"],
                                         NULL,
                                         rsj::app ("emit", rsj::app ("asm_" + id, rsj::id "x"))
                                       )
                              ]
                            ) 

                # Here we're synthesizing raw syntax for
                # something like
                #
                #         fun asm_cond (mcf::EQ) => "e";
                #             asm_cond (mcf::NE) => "ne";
                #             asm_cond (mcf::LT) => "l";
                #             asm_cond (mcf::LE) => "le";
                #             asm_cond (mcf::GT) => "g";
                #             asm_cond (mcf::GE) => "ge";
                #             asm_cond (mcf::BB) => "b";
                #             asm_cond (mcf::BE) => "be";
                #             asm_cond (mcf::AA) => "a";
                #             asm_cond (mcf::AE) => "ae";
                #             asm_cond (mcf::CC) => "c";
                #             asm_cond (mcf::NC) => "nc";
                #             asm_cond (mcf::PP) => "p";
                #             asm_cond (mcf::NP) => "np";
                #             asm_cond (mcf::OO) => "o";
                #             asm_cond (mcf::NO) => "no";
                #         end
                #
                # given something like the
                #     src/lib/compiler/back/low/intel32/intel32.architecture-description
                # declaration
                #
                #       datatype cond! =
                #           EQ "e" 0w4 | NE 0w5 | LT "l" 0w12 | LE 0w14 | GT "g" 0w15 | GE 0w13
                #         | BB  0w2 | BE 0w6 | AA 0w7 | AE 0w3
                #         | CC  0w2 | NC 0w3 | PP 0wxa | NP 0wxb
                #         | OO  0w0 | NO 0w1
                # 
                # parsed into raw-syntax form.
                # Here:
                #     a simple string like   "e"                 shows up as raw::CONSTRUCTOR.asm -> THE (raw::STRINGASM "e")
                #     a qualifier     like   asm: <expression>   shows up as raw::CONSTRUCTOR.asm -> THE (raw::ASMASM [raw::EXPASM expression])
                #     a qualifier     like   ``this and <that>'' shows up as raw::CONSTRUCTOR.asm -> THE (raw::ASMASM [asms])
                #                                                where each asm is one of
                #                                                    raw::EXPASM expression      produced by   <that>   surface syntax where the brokets are literal sourcetext, not metanotation.
                #                                                    raw::TEXTASM asmtext_t      produced by running text inside the ``...'' but not inside any <...>.
                #                                                A raw::TEXTASM is a string constant;
                #                                                a raw::EXPASM  is a string-valued expression to be evaluated at asmcode generation time.
                also
                fun make_asm_fun (mode, cbs)                    # "cbs" is "cons bindings"
                    = 
                    map  make_clause  cbs
                    where
                        fun put_it e
                            =
                            if (mode == EMIT)    rsj::app ("emit", e);
                            else                 e;
                            fi;

                        fun asm_to_expression e (raw::TEXTASM s)
                                =>
                                put_it (make_string s);

                            asm_to_expression e (raw::EXPASM (raw::ID_IN_EXPRESSION (raw::IDENT([], x))))
                                =>
                                {   (e x) ->   (e, type);
                                    #
                                    put_type (x, type, e);
                                }
                                except e = err::fail ("unknown assembly field <" + x + ">");


                            asm_to_expression e''' (raw::EXPASM e)
                                =>
                                fns.rewrite_expression_parsetree  e
                                where
                                    fun rewrite_expression_node _ (raw::ASM_IN_EXPRESSION (raw::STRINGASM s)) =>  put_it (make_string s);
                                        rewrite_expression_node _ (raw::ASM_IN_EXPRESSION (raw::ASMASM    a)) =>  raw::SEQUENTIAL_EXPRESSIONS (map (asm_to_expression e''') a);
                                        rewrite_expression_node _ e                                           =>  e;
                                    end;

                                    fns = rrs::make_raw_syntax_parsetree_rewriters [ rrs::REWRITE_EXPRESSION_NODE rewrite_expression_node ];
                                end;
                        end;

                        # In terms of the above example, here we're 
                        # generating raw-syntax clauses like
                        #
                        #     (mcf::EQ) => "e";
                        #
                        # for the fun asm_cond.
                        #
                        # In the general case the lefthand-side of the clause
                        # can carry values (i.e., instruction fields) and the
                        # right-hand-side can compute arbitrary functions of them.
                        #
                        fun make_clause (cb as raw::CONSTRUCTOR { name, asm, ... } )                    # "cb" == "constructor binding".
                            = 
                            {   expression
                                    = 
                                    case asm
                                        #
                                        NULL                   =>    put_it (make_string name);
                                        THE (raw::STRINGASM s) =>    put_it (make_string s);
                                        THE (raw::ASMASM    a) =>    {   cons_dict = rst::cons_namings cb;
                                                                         raw::SEQUENTIAL_EXPRESSIONS (map (asm_to_expression cons_dict) a);
                                                                     };
                                    esac;

                                rst::map_cons_to_clause
                                  {
                                    prefix  =>  ["mcf"],                # Generates the "mcf::" prefixes on "mcf::EQ" etc in the above example.
                                    pattern =>  fn p = p,               # rst::map_cons_to_pattern does everything we need, so we supply a no-op fn here.
                                    expression
                                  }
                                  cb;
                            };

                    end;

                # Make asm_*/put_* fun pairs from datatypes in
                #
                #     foo.adl: package Instruction
                #
                # -- see comment on function 'make_asms':
                #
                asm_funs =  raw::FUN_DECL (make_asms (datatype_definitions, []));

                # Main function for emitting an instruction:
                #
                put_instr_fun
                    = 
                    {   instructions =  ard::base_ops_of  architecture_description;
                        #
                        rsj::fun_fn
                          ( "put_op'",
                            raw::IDPAT "instruction", 
                            raw::CASE_EXPRESSION   (rsj::id "instruction",   make_asm_fun (EMIT, instructions))
                          );
                    };

                body =
                    [ raw::VERBATIM_CODE
                        [
                          "\t\t\t\t\t\t\t\t\t# Machcode_Codebuffer\t\tis from   src/lib/compiler/back/low/emit/machcode-codebuffer.api",
                          "",
                          "# Export to client packages:",
                          "#",
                          "package cst =  cst;\t\t\t\t\t\t\t# \"cst\"  == \"codestream\".",
                          "package mcf =  mcf;\t\t\t\t\t\t\t# \"mcf\" == \"machcode_form\" (abstract machine code).",
                          "",
                          "stipulate",
                          "    package rgk =  mcf::rgk;\t\t# \"rgk\" == \"registerkinds\".",
                          "    package tcf =  mcf::tcf;\t\t# \"tcf\" == \"treecode_form\".",
                          "    package pop =  cst::pop;\t\t\t\t\t\t# \"pop\" == \"pseudo_op\".",
                          "    package lac =  mcf::lac;\t\t\t\t\t\t# \"lac\" == \"late_constant\".",
                          "herein",
                          "",
                          "include asm_flags;\t\t\t\t\t\t\t# asm_flags\t\tis from   src/lib/compiler/back/low/emit/asm-flags.pkg",
                          ""
                        ],

                      smj::error_handler  architecture_description  (fn architecture_name = sprintf "translate_machcode_to_asmcode_%s_g" architecture_name),

                      raw::VERBATIM_CODE
                        [
                          "",
                          "fun make_codebuffer format_annotations",
                          "    =",
                          "    {   stream = *asm_stream::asm_out_stream;\t\t\t\t# asm_stream\t\tis from   src/lib/compiler/back/low/emit/asm-stream.pkg",
                          "",
                          "        fun emit' s",
                          "            =",
                          "            file__premicrothread::write (stream, s);",
                          "",
                          "        newline = REF TRUE;",
                          "        tabs    = REF 0;",
                          "",
                          "        fun tabbing 0 => ();",
                          "            tabbing n => { emit' \"\\t\"; tabbing (n - 1); } ;",
                          "        end;",
                          "",
                          "        fun emit s",
                          "            =",
                          "            {   tabbing *tabs;",
                          "                tabs := 0;",
                          "                newline := FALSE;",
                          "                emit' s;",
                          "            };",
                          "",
                          "        fun nl     ()",
                          "            =",
                          "            {   tabs := 0;",
                          "                if (not *newline)",
                          "                    #",
                          "                    newline := TRUE;",
                          "                    emit' \"\\n\";",
                          "                fi;",
                          "            };",
                          "",   
                          "        fun comma  () =  emit \", \";",
                          "        fun tab    () =  tabs := 1;",
                          "        fun indent () =  tabs := 2;",
                          "",
                          "        fun ms n",
                          "            =",
                          "            {   s = int::to_string n;",
                          "",
                          "                if (n < 0)   \"-\" + string::substring (s, 1, size s - 1);",
                          "                else         s;",
                          "                fi;",
                          "            };",
                          "",
                          "        fun put_label lab           = emit (pop::cpo::bpo::label_expression_to_string (tcf::LABEL lab));",
                          "        fun put_label_expression le = emit (pop::cpo::bpo::label_expression_to_string (tcf::LABEL_EXPRESSION le));",
                          "",
                          "        fun put_const lateconst",
                          "            =",
                          "            emit (lac::late_constant_to_string  lateconst);",
                          "",
                          "        fun put_int i",
                          "            =",
                          "            emit (ms i);",
                          "",
                          "        fun paren f",
                          "            =",
                          "            {   emit \"(\";",
                          "                f ();",
                          "                emit \")\";",
                          "            };",
                          "",   
                          "        fun put_private_label  label",
                          "            =",
                          "            emit (pop::cpo::bpo::define_private_label label  +  \"\\n\");",
                          "",
                          "        fun put_public_label  label",
                          "            =",
                          "            put_private_label  label;",
                          "",   
                          "        fun put_comment  msg",
                          "            =",
                          "            {   tab ();",
                          "                emit (\"/* \" + msg + \" */\");",
                          "                nl ();",
                          "            };",
                          "",
                          "        fun put_bblock_note a",
                          "            =",
                          "            put_comment (note::to_string a);",
                          "",
                          "        fun get_notes () =  error \"get_notes\";",
                          "        fun do_nothing _ =  ();",
                          "        fun fail _       =  raise exception FAIL \"asmcode-emitter\";",
                          "",
                          "        fun put_ramregion  ramregion",
                          "            =",
                          "            put_comment (mcf::rgn::ramregion_to_string  ramregion);",
                          "",   
                          "        put_ramregion",
                          "            =",
                          "            if *show_region    put_ramregion;",
                          "            else               do_nothing;",
                          "            fi;",
                          "", 
                          "        fun put_pseudo_op  pseudo_op",
                          "            =",
                          "            {   emit (pop::pseudo_op_to_string  pseudo_op);",
                          "                emit \"\\n\";",
                          "            };",
                          "",   
                          "        fun init  size",
                          "            =",
                          "            {   put_comment (\"Code Size = \" + ms size);",
                          "                nl ();",
                          "            };",
                          "",
                          "        put_register_info = asm_formatting_utilities::reginfo",
                          "                                 (emit, format_annotations);",
                          "",   
                          "        fun put_register r",
                          "            =",
                          "            {   emit (rkj::register_to_string r);",
                          "                put_register_info r;",
                          "            };",
                          "",
                          "        fun put_registerset (title, registerset)",
                          "            =",
                          "            {   nl ();",
                          "                put_comment  (title  +  rkj::cls::codetemplists_to_string  registerset);",
                          "            };",
                          "",
                          "        put_registerset",
                          "            =",
                          "            if *show_registerset   put_registerset;",
                          "            else                   do_nothing;",
                          "            fi;",
                          "",
                          "        fun put_defs  registerset =  put_registerset (\"defs: \", registerset);",
                          "        fun put_uses  registerset =  put_registerset (\"uses: \", registerset);",
                          "",
                          "        put_cuts_to",
                          "            =",
                          "            *show_cuts_to   ??   asm_formatting_utilities::put_cuts_to  emit",
                          "                            ::   do_nothing;",
                          "",
                          "        fun emitter instruction",
                          "            =",
                          "            {",
                          "                # NB: The following incorrect-indentation problem is nontrivial to fix",
                          "                #     so I'm just living with it for the moment.  -- 2011-05-14 CrT"
                        ],

                      asm_funs,

                      ard::decl_of architecture_description "Assembly",

                      put_instr_fun,

                      raw::VERBATIM_CODE
                        [ "                tab ();",
                          "                put_op' instruction;",
                          "                nl ();",
                          "            }\t\t\t\t\t\t# fun emitter",
                          "",
                          "        also",
                          "        fun put_indented_instruction  instruction",
                          "            =",
                          "            {   indent ();",
                          "                put_op instruction;",
                          "                nl ();",
                          "            }",
                          "",
                          "        also",
                          "        fun put_instructions instructions",
                          "            =",
                          "            apply if *indent_copies   put_indented_instruction;",
                          "                  else put_op;",
                          "                  fi",
                          "                  instructions",
                          "",
                          "        also",
                          "        fun put_op (mcf::NOTE { op, note } )",
                          "                =>",
                          "                {   put_comment (note::to_string note);",
                          "                    nl ();",
                          "                    put_op op;",
                          "                };",
                          "",
                          "            put_op (mcf::LIVE { regs, spilled } )",
                          "                =>",
                          "                put_comment(\"live= \" + rkj::cls::codetemplists_to_string regs +",
                          "                    \"spilled= \" + rkj::cls::codetemplists_to_string spilled);",
                          "",
                          "            put_op (mcf::DEAD { regs, spilled } )",
                          "                =>",
                          "                put_comment(\"dead= \" + rkj::cls::codetemplists_to_string regs +\t\t\t# 'dead' here was 'killed' -- is there a critical difference?",
                          "                    \"spilled= \" + rkj::cls::codetemplists_to_string spilled);",
                          "",
                          "            put_op (mcf::BASE_OP i)",
                          "                =>",
                          "                emitter i;",  
                          "",
                          "            put_op (mcf::COPY { kind=>rkj::INT_REGISTER, size_in_bits, src, dst, tmp } )",
                          "                =>",
                          "                put_instructions (crm::compile_int_register_moves { tmp, src, dst } );",
                          "",
                          "            put_op (mcf::COPY { kind=>rkj::FLOAT_REGISTER, size_in_bits, src, dst, tmp } )",
                          "                =>",
                          "                put_instructions (crm::compile_float_register_moves { tmp, src, dst } );",
                          "",
                          "            put_op _",
                          "                =>",
                          "                error \"put_op\";",
                          "        end;",
                          "", 
                          "        ",
                          "        {",
                          "          start_new_cccomponent => init,",
                          "          put_pseudo_op,",
                          "          put_op,",
                          "          get_completed_cccomponent => fail,",
                          "          put_private_label,",
                          "          put_public_label,",
                          "          put_comment,",
                          "          put_fn_liveout_info => do_nothing,",
                          "          put_bblock_note,",
                          "          get_notes",
                          "        };",
                          "    };\t\t\t\t\t\t\t\t\t\t# fun make_codebuffer",
                          "end;\t\t\t\t\t\t\t\t\t\t# stipulate"
                       ]
                    ];

            pkg_code
                =
                spp::CAT [
                    punct "# We are invoked by:", nl,
                    punct "#", nl,
                    punct (sprintf "#     src/lib/compiler/back/low/main/%s/backend-lowhalf-%s%s.pkg" archl archl (archl=="intel32" ?? "-g" :: "")), nl,
                    punct "#", nl,
                    alpha "stipulate",                                                                 nl,
                    iblock(indent++alpha "package lem =  lowhalf_error_message;\t\t\t\t\t\t# lowhalf_error_message\t\tis from   src/lib/compiler/back/low/control/lowhalf-error-message.pkg"), nl,
                    iblock(indent++alpha "package rkj =  registerkinds_junk;\t\t\t\t\t\t# registerkinds_junk\t\tis from   src/lib/compiler/back/low/code/registerkinds-junk.pkg"), nl,
                    alpha "herein", nl, nl,
                    iblock (indent ++ smj::make_generic'
                                         architecture_description
                                         (fn architecture_name =  sprintf "translate_machcode_to_asmcode_%s_g"  architecture_name)
                                         args
                                         smj::WEAK_SEAL
                                         api_name
                                         body
                           ),
                    alpha "end;", nl, nl
                ]
                where
                  architecture_name =  ard::architecture_name_of  architecture_description;             # "intel32"/"sparc32"/"pwrpc32"
                  archl = string::to_lower architecture_name;
                  archm = string::to_mixed architecture_name;
                end;


            end;                                                                # fun gen
    };                                                                          # package   make_sourcecode_for_translate_machcode_to_asmcode_xxx_g_package
end;                                                                            # stipulate


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext