Answer 5.37
This commit is contained in:
144
ex-5_31-xx.scm
144
ex-5_31-xx.scm
@@ -74,14 +74,19 @@ ev-appl-did-operator-no-restore
|
||||
(display (car xs) port)
|
||||
(display "\n" port)
|
||||
(write-list-to-port (cdr xs) port))))
|
||||
(let* ((compile-result (compile code target linkage))
|
||||
(assembly-insts (statements compile-result))
|
||||
(port (open-output-file file-name)))
|
||||
(write-list-to-port assembly-insts port)
|
||||
(display "[")
|
||||
(display file-name)
|
||||
(display "]\n")
|
||||
(close-output-port port)))
|
||||
(if #f ; #t means write to file; #f means don't write to file
|
||||
(let* ((compile-result (compile code target linkage))
|
||||
(assembly-insts (statements compile-result))
|
||||
(port (open-output-file file-name)))
|
||||
(write-list-to-port assembly-insts port)
|
||||
(display "[")
|
||||
(display file-name)
|
||||
(display "]\n")
|
||||
(close-output-port port))
|
||||
(begin
|
||||
(display "[")
|
||||
(display file-name)
|
||||
(display "]\n"))))
|
||||
|
||||
; Uncomment the following lines to write the assembly code for the to methods
|
||||
; into files.
|
||||
@@ -320,31 +325,104 @@ ev-appl-did-operator-no-restore
|
||||
|
||||
(display "\nex-5.37 - preserving-mechanism-evaluation\n")
|
||||
|
||||
(display "CONTINUE HERE!\n")
|
||||
; Uncomment the following code to compile a version with optimized and
|
||||
; unoptimzed stack usage for a simple program.
|
||||
|
||||
(define (preserving regs seq1 seq2)
|
||||
(if (null? regs)
|
||||
(append-instruction-sequences seq1 seq2)
|
||||
(let ((first-reg (car regs)))
|
||||
(if (and (needs-register? seq2 first-reg)
|
||||
(modifies-register? seq1 first-reg))
|
||||
(preserving (cdr regs)
|
||||
(make-instruction-sequence
|
||||
(list-union (list first-reg)
|
||||
(registers-needed seq1))
|
||||
(list-difference (registers-modified seq1)
|
||||
(list first-reg))
|
||||
(append `((save ,first-reg))
|
||||
(statements seq1)
|
||||
`((restore ,first-reg))))
|
||||
seq2)
|
||||
(preserving (cdr regs) seq1 seq2)))))
|
||||
(compile-to-file
|
||||
'(+ 1 1)
|
||||
'val 'next "f-add.scm")
|
||||
|
||||
; Exercise 5.37. One way to understand the compiler's preserving mechanism for
|
||||
; optimizing stack usage is to see what extra operations would be generated if
|
||||
; we did not use this idea. Modify preserving so that it always generates the
|
||||
; save and restore operations. Compile some simple expressions and identify the
|
||||
; unnecessary stack operations that are generated. Compare the code to that
|
||||
; generated with the preserving mechanism intact.
|
||||
;(define (preserving regs seq1 seq2)
|
||||
; (if (null? regs)
|
||||
; (append-instruction-sequences seq1 seq2)
|
||||
; (let ((first-reg (car regs)))
|
||||
; (if #t ; preserve all registers no matter what
|
||||
; ; (and (needs-register? seq2 first-reg) (modifies-register? seq1 first-reg))
|
||||
; (preserving (cdr regs)
|
||||
; (make-instruction-sequence
|
||||
; (list-union (list first-reg)
|
||||
; (registers-needed seq1))
|
||||
; (list-difference (registers-modified seq1)
|
||||
; (list first-reg))
|
||||
; (append `((save ,first-reg))
|
||||
; (statements seq1)
|
||||
; `((restore ,first-reg))))
|
||||
; seq2)
|
||||
; (preserving (cdr regs) seq1 seq2)))))
|
||||
|
||||
(display "\nex-5.38\n")
|
||||
(compile-to-file
|
||||
'(+ 1 1)
|
||||
'val 'next "f-add-unoptimized-stack-usage.scm")
|
||||
|
||||
; $ diff f-add.scm f-add-unoptimized-stack-usage.scm
|
||||
; 0a1,3
|
||||
; > (save continue)
|
||||
; > (save env)
|
||||
; > (save continue)
|
||||
; 1a5,11
|
||||
; > (restore continue)
|
||||
; > (restore env)
|
||||
; > (restore continue)
|
||||
; > (save continue)
|
||||
; > (save proc)
|
||||
; > (save env)
|
||||
; > (save continue)
|
||||
; 2a13
|
||||
; > (restore continue)
|
||||
; 3a15,17
|
||||
; > (restore env)
|
||||
; > (save argl)
|
||||
; > (save continue)
|
||||
; 4a19,20
|
||||
; > (restore continue)
|
||||
; > (restore argl)
|
||||
; 5a22,23
|
||||
; > (restore proc)
|
||||
; > (restore continue)
|
||||
; 12a31
|
||||
; > (save continue)
|
||||
; 13a33
|
||||
; > (restore continue)
|
||||
|
||||
; Even for the simple program (+ 1 1) the stack-preserving-mechanism saves 20
|
||||
; stack operations. Pretty impressive.
|
||||
|
||||
(display "[answered]\n")
|
||||
|
||||
(display "\nex-5.38 - optimize-procedure-application\n")
|
||||
|
||||
; The expression (+ a 1) might be compiled into something as simple as:
|
||||
|
||||
; (assign val (op lookup-variable-value) (const a) (reg env))
|
||||
; (assign val (op +) (reg val) (const 1))
|
||||
|
||||
; a. The open-coded primitives, unlike the special forms, all need their
|
||||
; operands evaluated. Write a code generator spread-arguments for use by all
|
||||
; the open-coding code generators. Spread-arguments should take an operand list
|
||||
; and compile the given operands targeted to successive argument registers.
|
||||
; Note that an operand may contain a call to an open-coded primitive, so
|
||||
; argument registers will have to be preserved during operand evaluation.
|
||||
|
||||
(define (spread-arguments operand-codes)
|
||||
(assert (length operand-codes) 2)
|
||||
(make-instruction-sequence
|
||||
'()
|
||||
'()
|
||||
'((assign ))))
|
||||
|
||||
; b. For each of the primitive procedures =, *, -, and +, write a code
|
||||
; generator that takes a combination with that operator, together with a target
|
||||
; and a linkage descriptor, and produces code to spread the arguments into the
|
||||
; registers and then perform the operation targeted to the given target with
|
||||
; the given linkage. You need only handle expressions with two operands. Make
|
||||
; compile dispatch to these code generators.
|
||||
|
||||
; c. Try your new compiler on the factorial example. Compare the resulting
|
||||
; code with the result produced without open coding.
|
||||
|
||||
; d. Extend your code generators for + and * so that they can handle
|
||||
; expressions with arbitrary numbers of operands. An expression with more than
|
||||
; two operands will have to be compiled into a sequence of operations, each
|
||||
; with only two inputs.
|
||||
|
||||
(display "\nex-5.39\n")
|
||||
|
||||
Reference in New Issue
Block a user