PreviousUpNext

15.4.410  src/lib/compiler/back/low/tools/arch/architecture-description.pkg

## architecture-description.pkg -- derived from ~/src/sml/nj/smlnj-110.60/MLRISC/Tools/ADL/mdl-compile.sml
#
# See overview comments in
#     src/lib/compiler/back/low/tools/arch/architecture-description.api

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



###               "I visualize a time when we
###                will be to robots what
###                dogs are to humans, and I'm
###                rooting for the machines."
###
###                       -- Claude Shannon


stipulate
    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 htb =  hashtable;                                                   # hashtable                                             is from   src/lib/src/hashtable.pkg
#   package spp =  simple_prettyprinter;                                        # simple_prettyprinter                                  is from   src/lib/prettyprint/simple/simple-prettyprinter.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 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 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 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 rsp =  adl_raw_syntax_predicates;                                   # adl_raw_syntax_predicates                             is from   src/lib/compiler/back/low/tools/arch/adl-raw-syntax-predicates.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 mtj =  adl_type_junk;                                               # adl_type_junk                                         is from   src/lib/compiler/back/low/tools/arch/adl-type-junk.pkg
herein

    # This package is referenced in:
    #
    #     src/lib/compiler/back/low/tools/arch/make-sourcecode-for-backend-packages.pkg
    #
    package   architecture_description
    : (weak)  Architecture_Description                  # Architecture_Description      is from   src/lib/compiler/back/low/tools/arch/architecture-description.api
    {
        Filename = String;

        infix my ++ ;

        ++ = mst::(++);

        Slot(X) = EMPTY String                                                  # One slot holds one architecture-description-file declaration.
                | SLOT (String, X)
                ; 

        # architecture description: 
        #
        Architecture_Description
            =
            ARCHITECTURE_DESCRIPTION
              { symboltable:                    Ref( mst::Symboltable ),
                architecture_description_file:  Filename,                                                               # Something like "src/lib/compiler/back/low/intel32/one_word_int.architecture-description".
                #
                debug:                          Ref( List( String ) ),
                registersets:                   Ref( List( raw::Register_Set ) ),
                special_registers:              Ref( List( raw::Special_Register ) ),
                instruction_formats:            Ref( List( (Null_Or(Int), raw::Instruction_Format) )),
                #
                base_ops:               Ref( Slot( List( raw::Constructor ) ) ),
                endian:                         Ref( Slot( raw::Endian ) ),                                             # LITTLE for intel32, BIG for pwrpc32 and sparc32.
                #
                asm_case:                       Ref( Slot( raw::Assemblycase ) ),                                       # Should generated assembly code be UPPERCASE, LOWERCASE or VERBATIM?
                architecture_name:              Ref( Slot(  String ) ),                                                 # Architecture name ("intel32"|"sparc32"|"pwrpc32") -- 'foo' from the 'architecture foo = ' line
                #
                cpus:                           Ref( Slot( List( raw::Cpu     ) ) ),
                pipelines:                      Ref( Slot( List( raw::Pipeline) ) ),
                resources:                      Ref( Slot( List( raw::Id      ) ) ),
                latencies:                      Ref( Slot( List( raw::Latency ) ) )
              };

        fun get_slot (REF (EMPTY name)) =>  err::fail (name + " has not been declared"); 
            get_slot (REF (SLOT(_, x))) =>  x;
        end;

        fun get_slot' (REF (EMPTY _))    =>  [];
            get_slot' (REF (SLOT(_, x))) =>  x;
        end;

        fun set_slot (s as REF (EMPTY name),     x) =>    s := SLOT (name, x);
            set_slot (s as REF (SLOT (name, _)), x) =>    err::error("duplicate declaration of " + name);
        end;

        fun set_slot' (s as REF (EMPTY name),     x) =>   s := SLOT (name, x);
            set_slot' (s as REF (SLOT (name, _)), x) =>   s := SLOT (name, x);
        end;

        # Fetch slots from architecture description record:
        #
        fun endian_of                           (ARCHITECTURE_DESCRIPTION r )   =  get_slot  r.endian;                          # LITTLE for INTEL32 (x86), BIG for SPARC32 and PWRPC32.
        fun asm_case_of                         (ARCHITECTURE_DESCRIPTION r )   =  get_slot  r.asm_case;
        fun architecture_name_of                (ARCHITECTURE_DESCRIPTION r )   =  get_slot  r.architecture_name;               # "INTEL32"|"SPARC32"|"PWRPC32" -- 'foo' from 'architecture foo = ' line
        fun architecture_description_file_of    (ARCHITECTURE_DESCRIPTION r )   =            r.architecture_description_file;   # Something like "src/lib/compiler/back/low/intel32/one_word_int.architecture-description".
        fun symboltable_of                      (ARCHITECTURE_DESCRIPTION r )   =           *r.symboltable;
        fun registersets_of                     (ARCHITECTURE_DESCRIPTION r )   =           *r.registersets;
        fun special_registers_of                (ARCHITECTURE_DESCRIPTION r )   =           *r.special_registers;
        fun instruction_formats_of              (ARCHITECTURE_DESCRIPTION r )   =           *r.instruction_formats;
        fun base_ops_of         (ARCHITECTURE_DESCRIPTION r )   =  get_slot  r.base_ops;
        fun resources_of                        (ARCHITECTURE_DESCRIPTION r )   =  get_slot' r.resources;
        fun latencies_of                        (ARCHITECTURE_DESCRIPTION r )   =  get_slot' r.latencies;
        fun cpus_of                             (ARCHITECTURE_DESCRIPTION r )   =  get_slot' r.cpus;
        fun pipelines_of                        (ARCHITECTURE_DESCRIPTION r )   =  get_slot' r.pipelines;
        #
        fun debugging                           (ARCHITECTURE_DESCRIPTION r ) x =  list::exists (\\ x' =  x == x')  *r.debug;


#       fun registersets (ARCHITECTURE_DESCRIPTION { registersets, ... } )
#           =
#           list_mergesort::sort
#               #
#               (\\ ( REGISTER_SET { from=>f1, ... },
#                     REGISTER_SET { from=>f2, ... }
#                   )
#                   =   *f1 > *f2
#               )
#               #
#               (list::filter
#                   #
#                   \\  REGISTER_SET { registerset=>TRUE, alias=>NULL, ... } =>  TRUE;
#                       REGISTER_SET _                                       =>  FALSE;
#                   end
#                   #
#                   *registersets
#                );
#
#       fun registersets_aliases (ARCHITECTURE_DESCRIPTION { registersets, ... } )
#           = 
#           list_mergesort::sort
#               #
#               (\\ ( REGISTER_SET { from=>f1, ... },
#                     REGISTER_SET { from=>f2, ... }
#                   )
#                   =
#                   *f1 > *f2
#               )
#               #
#               (list::filter
#                   #
#                   \\  REGISTER_SET { registerset=>TRUE, ... } =>  TRUE;
#                       REGISTER_SET { alias=THE _,       ... } =>  TRUE;
#                       _                                       =>  FALSE;
#                   end
#                   #
#                   *registersets
#               );


        # Find register-set named k by
        # looping over ARCHITECTURE_DESCRIPTION.registersets:
        #
        fun find_registerset_by_name (ARCHITECTURE_DESCRIPTION { registersets, ... } ) name
            = 
            loop  *registersets
            where
                fun loop ((c as raw::REGISTER_SET r) ! cs)
                        =>
                        if (r.name == name or r.nickname == name)   c;
                        else                                        loop cs;
                        fi;

                    loop [] =>   err::fail ("registerkind " + name + " not found");
                end;
            end;


        fun find_instruction_sumtype   (ARCHITECTURE_DESCRIPTION { symboltable, ... } )   name                  # This is called (only) from   src/lib/compiler/back/low/tools/arch/adl-rtl-comp-g.pkg
            = 
            # For query string "binaryOp" return sumtype named "binaryOp"
            # from package Instruction in architecture description:
            #
            loop sumtypes
            where
                instruction_dict =   mst::find_package  *symboltable  (raw::IDENT([], "Instruction"));
                #
                sumtypes =   mst::sumtype_definitions  instruction_dict;

                fun loop ((sumtype as raw::SUMTYPE r) ! sumtypes)
                        =>
                        if (r.name == name)   sumtype;
                        else                  loop sumtypes;
                        fi;

                    loop [] =>   err::fail ("Instruction sumtype " + name + " not found");
                    loop _  =>   err::fail "Bug: Unsupported case in find_instruction_sumtype";
                end;
            end;


        fun has_copy_impl  architecture_description                                                             # TRUE iff architecture description has an instruction named "COPY" whose type is a record with a field named "impl".
            =
            list::exists
                #
                \\ raw::CONSTRUCTOR { name => "COPY",  type => THE (raw::RECORDTY fields),  ...  }
                        =>
                        list::exists   (\\ (id, _) =  id == "impl")   fields;

                    _ => FALSE;
                end
                #
                (base_ops_of  architecture_description);



        # Extract info from the symboltable:
        #
        my decl_of:                                             Architecture_Description -> String -> raw::Declaration          # Body of package.
            =
            mst::decl_of        o symboltable_of;
        #
        my generic_arg_of:                                      Architecture_Description -> String -> raw::Declaration          # Generic argument.
            =
            mst::generic_arg_of o symboltable_of;
        #
        my type_of:                                             Architecture_Description -> String -> raw::Declaration          # Type definitions.
            =
            mst::type_of        o symboltable_of;



        # Require that contents of 'values' and 'types' lists
        # be defined in given architecture description:
        #
        fun require  architecture_description  symboltable_name  { values, types }
            =
            {   decls =  decl_of  architecture_description  symboltable_name;
                #
                hash  =  hash_string::hash_string;

                exception NOT_DEFINED;

                value_table =  htb::make_hashtable  (hash, (==))  { size_hint => 32, not_found_exception => NOT_DEFINED };
                type_table  =  htb::make_hashtable  (hash, (==))  { size_hint => 32, not_found_exception => NOT_DEFINED };

                fun enter_sumtype (raw::SUMTYPE       { name, ... } ) =>  htb::set type_table (name, ());
                    enter_sumtype (raw::SUMTYPE_ALIAS { name, ... } ) =>  htb::set type_table (name, ());
                end;

                fun enter_type (raw::TYPE_ALIAS (id, _, _)) =   htb::set  type_table  (id, ());
                fun enter_fun  (raw::FUN        (id, _)   ) =   htb::set value_table  (id, ());


                fun rewrite_declaration_node _ (d as raw::SUMTYPE_DECL (dts, ts)) =>  { apply enter_sumtype dts;  apply enter_type ts; d; };
                    rewrite_declaration_node _ (d as raw::FUN_DECL fbs)            =>  { apply enter_fun      fbs;                       d; };
                    rewrite_declaration_node _  d                                  =>  {                                                 d; };
                end;


                fns.rewrite_declaration_parsetree  decls        # We abuse 'rewrite' as 'apply'.
                where
                    fns =  rrs::make_raw_syntax_parsetree_rewriters [ rrs::REWRITE_DECLARATION_NODE rewrite_declaration_node ];
                end;

                fun check  kind  table  id
                    = 
                    htb::look_up  table  id
                    except
                        _ =  err::warning ("missing " + kind + " " + symboltable_name + "." + id);

                apply (check "function" value_table)  values;
                apply (check "type"      type_table)  types ;
            };


        # Compile an architecture-description parsetree into internal form:
        #
        # We get called from make_sourcecode_for_backend_packages () in:
        #     src/lib/compiler/back/low/tools/arch/make-sourcecode-for-backend-packages-g.pkg
        #
        fun translate_raw_syntax_to_architecture_description
              (
                architecture_description_file:  String,                                                         # Something like "src/lib/compiler/back/low/intel32/one_word_int.architecture-description".
                declarations:                   List( raw::Declaration )                                        # 'declarations' is the parsetree from the above architecture description file.
              )
            = 
            {   err::init ();
                #
                digest_declarations  declarations;
                #
                architecture_description;
            }
            where
                endian                  = REF (EMPTY "endian"                   );
                asm_case                = REF (EMPTY "assembly case"            );
                architecture_name       = REF (EMPTY "architecture name"        );                              # This will be "pwrpc32" or "sparc32" or "intel32", from "architecture intel32 = ... " line
                base_ops                = REF (EMPTY "base instructions"        );
                pipelines               = REF (EMPTY "pipelines"                );
                resources               = REF (EMPTY "resources"                );
                latencies               = REF (EMPTY "latencies"                );
                cpus                    = REF (EMPTY "cpus"                     );

                symboltable             = REF mst::empty;

                registersets            = REF [];
                special_registers       = REF [];
                debug                   = REF [];
                instruction_formats     = REF [];

                architecture_description
                    =
                    ARCHITECTURE_DESCRIPTION
                      { symboltable,
                        endian,
                        asm_case,
                        architecture_name,
                        architecture_description_file,
                        registersets,
                        special_registers,
                        instruction_formats,
                        base_ops,
                        debug,
                        cpus,
                        resources,
                        pipelines,
                        latencies
                      };

                fun note_declaration declaration                                                                # Add given declaration to *symboltable.
                    =
                    symboltable :=   mst::note_declaration  *symboltable  declaration;

                fun digest_declarations []       =>  ();
                    #
                    digest_declarations (d ! ds) =>  {   digest_declaration  d;
                                                         digest_declarations ds;
                                                     };
                end

                also    
                fun digest_declaration  d
                    =
                    case d
                        #
                        # Standard SML constructions:
                        #
                        raw::SUMTYPE_DECL _   =>  note_declaration d;
                        raw::FUN_DECL _        =>  note_declaration d;
                        raw::VAL_DECL _        =>  note_declaration d;
                        raw::VALUE_API_DECL _  =>  note_declaration d;
                        raw::TYPE_API_DECL _   =>  note_declaration d;
                        raw::LOCAL_DECL _      =>  note_declaration d;
                        raw::PACKAGE_DECL _    =>  note_declaration d;
                        raw::INFIX_DECL _      =>  note_declaration d;
                        raw::INFIXR_DECL _     =>  note_declaration d;
                        raw::NONFIX_DECL _     =>  note_declaration d;
                        raw::OPEN_DECL _       =>  note_declaration d;
                        #
                        raw::SEQ_DECL ds       =>  digest_declarations ds;
                        raw::VERBATIM_CODE _   =>  ();

                        raw::SOURCE_CODE_REGION_FOR_DECLARATION (l, d)
                            =>
                            {   err::set_loc l;
                                #
                                digest_declaration  d;
                            };

                        # Constructions special to architecture-description-language:
                        # 
                        raw::INSTRUCTION_FORMATS_DECL (bits, f) =>   instruction_formats :=  *instruction_formats   @   map  (\\ f = (bits, f))  f;
                        raw::REGISTERS_DECL d                   =>          registersets :=         *registersets   @   d;
                        raw::SPECIAL_REGISTERS_DECL d           =>     special_registers :=    *special_registers   @   d;
                        #
                        raw::BASE_OP_DECL c                     => { set_slot (base_ops, c);    note_declaration d;  };
                        raw::ARCHITECTURE_DECL (n, ds)          => { set_slot (architecture_name, n);   digest_declarations ds; };
                        #
                        raw::BITS_ORDERING_DECL _               =>   err::error "bitsordering";
                        #
                        raw::BIG_VS_LITTLE_ENDIAN_DECL e        =>   set_slot  (endian, e);
                        raw::ARCHITECTURE_NAME_DECL n           =>   set_slot' (architecture_name, n);
                        raw::ASSEMBLY_CASE_DECL c               =>   set_slot  (asm_case, c);
                        raw::PIPELINE_DECL p                    =>   set_slot  (pipelines, p);
                        raw::CPU_DECL c                         =>   set_slot  (cpus,     c);
                        raw::RESOURCE_DECL r                    =>   set_slot  (resources, r);
                        raw::LATENCY_DECL l                     =>   set_slot  (latencies, l);
                        #
                        raw::DEBUG_DECL id                      =>   debug :=  id  !  *debug;

                        _ =>  err::error "compile";
                    esac;
            end;



    };                                                                          # package   architecture_description
end;                                                                            # stipulate


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext