1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-04-29 19:30:36 +02:00
guile/module/system/il/glil.scm
Andy Wingo 9cc649b880 Add instructions for doing very late binding
Fixes the mutually-recursive toplevel definitions case. This could be
fixed by rewriting bodies as letrecs, as r6 does, but that's not really
repl-compatible.

* module/system/il/ghil.scm (ghil-lookup): Ok, if we can't locate a
  variable, mark it as unresolved.

* module/system/il/compile.scm (make-glil-var): Compile unresolved
  variables as <glil-late-bound> objects.

* module/system/il/glil.scm: Add <glil-late-bound> definition.

* module/system/vm/assemble.scm (codegen): And, finally, when we see a
  <vlate-bound> object, allocate a slot for it in the object vector,
  setting it to a symbol. Add a new pair of instructions to resolve that
  symbol to a variable at the last minute.

* src/vm_loader.c (load-number): Bugfix: the radix argument should be
  SCM_UNDEFINED in order to default to 10.
  (late-bind): Add an unresolved symbol to the object vector. Could be
  replaced with load-symbol I guess.

* src/vm_system.c (late-variable-ref, late-variable-set): New
  instructions to do late symbol binding.

* testsuite/Makefile.am (vm_test_files):
* testsuite/t-mutual-toplevel-defines.scm: New test, failing for some
  reason involving the core even? and odd? definitions.
2008-05-19 17:46:05 +02:00

211 lines
6 KiB
Scheme
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;;; Guile Low Intermediate Language
;; Copyright (C) 2001 Free Software Foundation, Inc.
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;;; Code:
(define-module (system il glil)
:use-syntax (system base syntax)
:export
(pprint-glil
<glil-vars> make-glil-vars
glil-vars-nargs glil-vars-nrest glil-vars-nlocs glil-vars-nexts
<glil-asm> make-glil-asm glil-asm?
glil-asm-vars glil-asm-body
<glil-bind> make-glil-bind glil-bind?
glil-bind-vars
<glil-unbind> make-glil-unbind glil-unbind?
<glil-source> make-glil-source glil-source?
glil-source-loc
<glil-void> make-glil-void glil-void?
<glil-const> make-glil-const glil-const?
glil-const-obj
<glil-argument> make-glil-argument glil-argument?
glil-argument-op glil-argument-index
<glil-local> make-glil-local glil-local?
glil-local-op glil-local-index
<glil-external> make-glil-external glil-external?
glil-external-op glil-external-depth glil-external-index
<glil-module> make-glil-module glil-module?
glil-module-op glil-module-module glil-module-index
<glil-late-bound> make-glil-late-bound glil-late-bound?
glil-late-bound-op glil-late-bound-name
<glil-label> make-glil-label glil-label?
glil-label-label
<glil-branch> make-glil-branch glil-branch?
glil-branch-int glil-branch-label
<glil-call> make-glil-call glil-call?
glil-call-int glil-call-nargs))
(define-record (<glil-vars> nargs nrest nlocs nexts))
(define-type <glil>
(|
;; Meta operations
(<glil-asm> vars body)
(<glil-bind> vars)
(<glil-unbind>)
(<glil-source> loc)
;; Objects
(<glil-void>)
(<glil-const> obj)
;; Variables
(<glil-argument> op index)
(<glil-local> op index)
(<glil-external> op depth index)
(<glil-module> op module name)
(<glil-late-bound> op name)
;; Controls
(<glil-label> label)
(<glil-branch> inst label)
(<glil-call> inst nargs)))
;;;
;;; Parser
;;;
;;; (define (parse-glil x)
;;; (match x
;;; (('@asm args . body)
;;; (let* ((env (make-new-env e))
;;; (args (parse-args args env)))
;;; (make-asm env args (map-parse body env))))
;;; (else
;;; (error "Invalid assembly code:" x))))
;;;
;;; (define (parse-args x e)
;;; (let ((args (cond ((symbol? x) (make-args (list (make-local-var x)) #t))
;;; ((list? x) (make-args (map make-local-var x) #f))
;;; (else (let loop ((l x) (v '()))
;;; (if (pair? l)
;;; (loop (cdr l) (cons (car l) v))
;;; (make-args (map make-local-var
;;; (reverse! (cons l v)))
;;; #t)))))))
;;; (for-each (lambda (v) (env-add! e v)) (args-vars args))
;;; args))
;;;
;;; (define (map-parse x e)
;;; (map (lambda (x) (parse x e)) x))
;;;
;;; (define (parse x e)
;;; (match x
;;; ;; (@asm ARGS BODY...)
;;; (('@asm args . body)
;;; (parse-asm x e))
;;; ;; (@bind VARS BODY...)
;;; ;; (@block VARS BODY...)
;;; (((or '@bind '@block) vars . body)
;;; (let* ((offset (env-nvars e))
;;; (vars (args-vars (parse-args vars e)))
;;; (block (make-block (car x) offset vars (map-parse body e))))
;;; (for-each (lambda (v) (env-remove! e)) vars)
;;; block))
;;; ;; (void)
;;; (('void)
;;; (make-void))
;;; ;; (const OBJ)
;;; (('const obj)
;;; (make-const obj))
;;; ;; (ref NAME)
;;; ;; (set NAME)
;;; (((or 'ref 'set) name)
;;; (make-access (car x) (env-ref e name)))
;;; ;; (label LABEL)
;;; (('label label)
;;; (make-label label))
;;; ;; (br-if LABEL)
;;; ;; (jump LABEL)
;;; (((or 'br-if 'jump) label)
;;; (make-instl (car x) label))
;;; ;; (call NARGS)
;;; ;; (tail-call NARGS)
;;; (((or 'call 'tail-call) n)
;;; (make-instn (car x) n))
;;; ;; (INST)
;;; ((inst)
;;; (if (instruction? inst)
;;; (make-inst inst)
;;; (error "Unknown instruction:" inst)))))
;;;
;;; Unparser
;;;
(define (unparse glil)
(record-case glil
;; meta
((<glil-asm> vars body)
`(@asm (,(glil-vars-nargs vars) ,(glil-vars-nrest vars)
,(glil-vars-nlocs vars) ,(glil-vars-nexts vars))
,@(map unparse body)))
((<glil-bind> vars) `(@bind ,@vars))
((<glil-unbind>) `(@unbind))
((<glil-source> loc) `(@source ,(car loc) ,(cdr loc)))
;; constants
((<glil-void>) `(void))
((<glil-const> obj) `(const ,obj))
;; variables
((<glil-argument> op index)
`(,(symbol-append 'argument- op) ,index))
((<glil-local> op index)
`(,(symbol-append 'local- op) ,index))
((<glil-external> op depth index)
`(,(symbol-append 'external- op) ,depth ,index))
((<glil-module> op module name)
`(,(symbol-append 'module- op) ,module ,name))
;; controls
((<glil-label> label) label)
((<glil-branch> inst label) `(,inst ,label))
((<glil-call> inst nargs) `(,inst ,nargs))))
;;;
;;; Printer
;;;
(define (pprint-glil glil . port)
(let ((port (if (pair? port) (car port) (current-output-port))))
(let print ((code (unparse glil)) (column 0))
(display (make-string column #\space) port)
(cond ((and (pair? code) (eq? (car code) '@asm))
(format port "(@asm ~A\n" (cadr code))
(let ((col (+ column 2)))
(let loop ((l (cddr code)))
(print (car l) col)
(if (null? (cdr l))
(display ")" port)
(begin (newline port) (loop (cdr l)))))))
(else (write code port))))
(newline port)))