Emacs: Please use -*- Text -*- mode. Thank you.
-$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/compiler/documentation/porting.guide,v 1.12 1991/02/27 23:34:02 jinx Exp $
+$Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/compiler/documentation/porting.guide,v 1.13 1991/02/28 18:07:29 jinx Exp $
Copyright (c) 1991 Massachusetts Institute of Technology
when pressed for machine registers, and reloads the values when
necessary.
-Thus the resultint LAP program is the collection of the code issued by
+Thus the resulting LAP program is the collection of the code issued by
the rules that translate RTL into LAP, the instructions issued behind
the scenes by the register allocator, and the instructions used to
linearize the control flow graph.
\f
5.3 Writing statement rules.
-*** Here ***
-
-- Use of LAP, INST, and INST-EA.
-
-- delete-dead-registers! must be invoked before allocating an alias
-for a target pseudo-register. Define a utility that does the common
-case.
-- all source registers aliases need to be need-register!d, before
-allocating the target register. This is done by the usual utilities.
-- describe the common utilities for reusing and 2/3 operand opcodes.
-
*** Get CPH to examine this carefully.
-- Closures, multi closures, uuo-link calls, and block-linking. Other
+Statement rules provide the translation between RTL instructions and
+fragments of assembly language. Most RTL instructions are
+assignments, where an RTL register is written with the contents of a
+virtual location or the result of some operation.
+
+ 5.3.1 Outupt of the statement rules
+
+The output of the statement rules is a fragment of assembly language
+written in the syntax expected by the LAP assembler. The fragments,
+containing any number of machine instructions, are constructed by
+using the LAP macro, built on top of Scheme's QUASIQUOTE (back-quote).
+Within a LAP form, you can use UNQUOTE (comma) and UNQUOTE-SPLICING
+(comma atsign) to tag subexpressions that should be evaluated and
+appended. For example,
+ (LAP (MOV L ,r1 ,r2)
+ (ADD L ,r3 ,r2))
+constructs a fragment with two instructions in it where the values of
+r1, r2, and r3 are substituted in the instructions.
+The code
+ (LAP (MOV L ,r1 ,r2)
+ ,@(generate-test r2))
+constructs a fragment whose first instruction is a MOV instruction,
+and the rest is the fragment returned by generate-test.
+
+The INST macro is similar to LAP but constructs a single instruction.
+It should not be used unless necessary (ie. in
+LAP:MAKE-LABEL-STATEMENT), since you may find yourself later wanting
+to change a single instruction into a fragment in a utility procedure,
+and having to find every use of the procedure.
+
+==> We should change the linearizer to expect LAP:MAKE-LABEL-STATEMENT
+to return a fragment, and do away with INST.
+
+An additional macro, INST-EA, is provided to construct a piece of
+assembly language representing an addressing mode. For example,
+INST-EA is used by the following procedure in the Vax back-end:
+ (define (non-pointer->ea type datum)
+ (if (and (zero? type)
+ (<= 0 datum 63))
+ (INST-EA (S ,datum))
+ (INST-EA (&U ,(make-non-pointer-literal type datum)))))
+where non-pointer->ea may be used in
+ (LAP (MOV L ,(non-pointer->ea <type> <datum>)
+ ,(any-register-reference target)))
+INST-EA is superfluous on machines without general addressing modes
+(ie. load-store architectures).
+
+Each port provides a procedure, named REGISTER-REFERENCE, that maps
+between RTL machine registers and the assembly language syntax used to
+refer to the registers. It uses INST-EA to build such references.
+
+The macros LAP, INST, and INST-EA, besides providing the functionality
+of QUASIQUOTE, also provide a hook for the compiler pre-processing
+time assembly of the code generated by the rules.
+\f
+ 5.3.2 Hardware register allocation
+
+Hardware register allocation occurs during the RTL->LAP translation.
+The rules, besides generating assembly language, invoke utilities
+provided by the register allocator to manipulate machine registers and
+aliases for pseudo-registers and temporaries.
+
+The register allocator maintains the mapping between pseudo-registers
+and hardware registers, and inserts additional assembly language
+instructions between the fragments generated by the rules to shuffle
+data.
+
+The register allocator manipulates RTL registers, but there are also
+wrappers for the common cases that return and manipulate register
+references. If you have carefully chosen your RTL register numbers
+for machine registers to match the hardware numbering, and your
+assembly language does not distinguish between references to a
+register and other fields, you can ignore register references and use
+the RTL register numbers directly. This is a common situation with
+load-store architectures.
+
+The interface to the register allocator is defined in
+compiler/back/lapgn2.scm. Not all ports use all of the procedures
+defined there. Often a smaller subset is sufficient depending on
+whether there are general addressing modes, etc. A list of
+the most frequently used follows:
+
+* LOAD-ALIAS-REGISTER! expects an RTL register and a register type and
+returns a machine register of the specified type that is an alias for
+the RTL register and contains the current value of the RTL register.
+This procedure should only be used for source RTL registers.
+REFERENCE-ALIAS-REGISTER! performs the same action but returns a
+register reference instead of an RTL register number.
+
+* ALLOCATE-ALIAS-REGISTER! expects and RTL register and a register
+type, and returns a machine register of the specified type that is the
+only alias for the RTL register and should be written with the new
+contents of the RTL register. ALLOCATE-ALIAS-REGISTER! is used to
+generate aliases for target RTL registers. REFERENCE-TARGET-ALIAS!
+performs the same action but returns a register reference instead of
+an RTL register number.
+
+* STANDARD-REGISTER-REFERENCE expects an RTL register, a register
+type, and a boolean. It will return a reference for an alias of the
+specified register containing the current value of the RTL register.
+This reference will be of the specified type if the boolean is false,
+or sometimes of other types if the boolean is true. In other words,
+the boolean argument determined whether other types are acceptable,
+although not desirable. The register type may be false, specifying
+that there really is no preference for the type, and any reference is
+valid. Note that STANDARD-REGISTER-REFERENCE should be used only for
+source pseudo-registers (ie. those that already contain data), and may
+return a memory reference for those machines with general addressing
+modes if there is no preferred type or alternates are acceptable.
+
+* MOVE-TO-ALIAS-REGISTER! expects a source RTL register, a register
+type, and a target RTL register. It returns a new alias for the
+target of the specified type containing a copy of the current contents
+of the source. Often this is accomplished by choosing an alias of the
+source that already contains the correct data and making it the only
+alias for target.
+
+* MOVE-TO-TEMPORARY-REGISTER! expects a source RTL register and a
+register type and returns an appropriate register containing a copy of
+the source. The register is intended for temporary use, and
+MOVE-TO-TEMPORARY-REGISTER! attempts to reuse an existing alias for
+the source RTL register.
+\f
+* REUSE-PSEUDO-REGISTER-ALIAS! expects an RTL register, a register
+type, and two continuations. It attempts to find a reusable alias for
+the RTL register of the specified type, and invokes the first
+continuation passing it the alias if it succeeds, or the second
+continuation with no arguments if it fails. MOVE-TO-ALIAS-REGISTER!
+and MOVE-TO-TEMPORARY-REGISTER! are written in terms of
+REUSE-PSEUDO-REGISTER-ALIAS! but occasionally neither meets the
+requirements.
+
+* NEED-REGISTER! expects and RTL machine register and informs the
+register allocator that the rule being expanded requires the use of
+that register so it should not be available for subsequent requests.
+The procedures described above that allocate and assign aliases call
+NEED-REGISTER! behind the scenes, but you may occasionally need to
+invoke it explicitly.
+
+* LOAD-MACHINE-REGISTER! expects an RTL register and an RTL machine
+register and generates code that copies the current value of the RTL
+register to the machine register. It is used to pass arguments on
+registers to out-of-line code, typically in the compiled code runtime
+library.
+
+* CLEAR-REGISTERS! expects any number of RTL registers and clears them
+from the register map, pushing their current contents to memory if
+needed. It returns the code that will perform the required motion at
+runtime. It should be used before invoking LOAD-MACHINE-REGISTER! to
+ensure that the potentially valid previous contents of the machine
+register have been saved if necessary.
+
+* CLEAR-MAP! deletes all aliases from the register map, pushing the
+contents held in aliases into the memory homes if needed.
+This procedure returns an assembly language code fragment, and is
+typically used before invoking out-of-line code.
+
+* DELETE-DEAD-REGISTERS! informs the register allocator that RTL
+pseudo registers whose contens will not be needed after the RTL rule
+being translated can be eliminated from the register map and their
+aliases reused for other purposes.
+
+Most of the rules are actually written in terms of port-specific
+procedures that invoke the procedures listed above in particular fixed
+patterns. For example, on a machine with general addresing modes and
+memory operands, we might define
+ (define (standard-source rtl-reg)
+ (standard-register-reference rtl-reg 'GENERAL true))
+ (define (standard-target rtl-reg)
+ (delete-dead-registers!)
+ (reference-target-alias! rtl-reg 'GENERAL))
+while on a load-store architecture we might define
+ (define (standard-source rtl-reg)
+ (load-alias-register! rtl-reg 'GENERAL))
+ (define (standard-target rtl-reg)
+ (delete-dead-registers!)
+ (allocate-alias-register! rtl-reg 'GENERAL))
+
+This example brings up the most important rule to be followed when
+writing RTL assignment rules: Any rule that writes an RTL
+pseudo-register MUST invoke DELETE-DEAD-REGISTERS! after allocating
+aliases for the necessary sources but before allocating an alias for
+the target. MOVE-TO-ALIAS-REGISTER! already invokes it since it
+simultaneously allocates an alias for a source and for a target.
+Thus rules frequently expand into the following pattern:
+ (let* ((r1 (standard-source source1))
+ (r2 (standard-source source2))
+ (rt (standard-target target)))
+ (LAP ...))
+\f
+ 5.3.3 Invocation rules, etc.
+
+*** MISSING: Closures, multi closures, uuo-link calls, and block-linking. Other
hairy stuff in rules3. Rules4 and part of rules3 should go away, they
are fossils. On the other hand, they are easy to take care of because
of the portable runtime library.
-- You need multiplication by 4 rules in order to get variable-offset
-vector-ref and vector-set! to work, even if there are no other
-multiplication rules.
-- How to interface to the runtime library. How to write
-special-purpose optimized entries.
+\f
+ 5.3.4 Fixnum rules.
+
+*** MISSING: You need multiplication by 4 rules in order to get
+variable-offset vector-ref and vector-set! to work, even if there are
+no other multiplication rules.
+
+ 5.3.5 Rules to invoke the runtime library
+
+*** MISSING:
\f
5.4 Writing predicate rules.
(load "make")
(disk-save "<lib directory pathname>/runtime+sf.com"))
at the Scheme prompt.
-
+\f
You also need to have a working version of cref. This can be done by
invoking scheme with the options ``-band runtime+sf.com'', and then
typing
(begin
(cd "<runtime directory pathname>")
(load "runtim.sf"))
-\f
+
6.2 Building an interpreted compiler
Once you have a new microcode, compatible runtime system, and ready