Next: , Previous: , Up: compiler   [Index]


17.22 Rewriting references to free variables

This compiler pass rewrites references to free variables in closure objects to forms actually accessing the values from the run–time closure object.

We know that a Scheme closure object (satisfiying the predicate procedure?) has memory layout:

                0   1   2   3   4   5
 |------------|---|---|---|---|---|---| closure object
       ^
       |      |.......................|
  pointer to     one slot for every
  binary code    free variable

the purpose of this compiler pass is to replace references to free variables with primopcall structs representing the use of the primitive operation $cpref.

In addition, it transforms every closure-maker not appearing as right-hand side expression of a fix into:

(fix ((tmp ?closure-maker))
  tmp)

this is an independent task that must be performed somewhere, and we do it here.

The following bindings are exported by the library (vicare compiler).

Function: pass-rewrite-freevar-references input

Perform code transformation traversing the whole hierarchy in input, which must be a codes struct representing recordised code; build and return a new codes struct.

Introduce primitive calls to the primitive operation $cpref to access free variables in closure objects.

As example, the core language expression:

(let ((a ((primitive read))))
  (lambda () a))

is transformed into:

(codes
  ((lambda (label: asmlabel:anonymous:clambda) (cp_0)
     (primopcall $cpref cp_0 (constant 0))))
  (bind ((a_0 (funcall (primref read))))
    (fix ((tmp_0 (closure-maker
                    (code-loc asmlabel:anonymous:clambda)
                    (freevars: a_0))))
      tmp_0)))

and the following core language expression, defining an assigned free variable:

(let ((a ((primitive read))))
  (lambda ()
    (begin
      (set! a '1)
      a)))

is transformed into:

(codes
 ((lambda (label: asmlabel:anonymous:clambda) (cp_0)
     (seq
       (primopcall $vector-set!
                  (primopcall $cpref cp_0 (constant 0))
                  (constant 0)
                  (constant 1))
       (primopcall $vector-ref
                  (primopcall $cpref cp_0 (constant 0))
                  (constant 0)))))
 (bind ((a_0 (funcall (primref read))))
   (bind ((a_1 (primopcall vector a_0)))
     (fix ((tmp_0 (closure-maker
                     (code-loc asmlabel:anonymous:clambda)
                     (freevars: a_1))))
       tmp_0))))

Next: , Previous: , Up: compiler   [Index]