Dust off portable fasdumper.
authorTaylor R Campbell <campbell@mumble.net>
Sat, 8 Dec 2018 15:16:58 +0000 (15:16 +0000)
committerTaylor R Campbell <campbell@mumble.net>
Sat, 8 Dec 2018 15:16:58 +0000 (15:16 +0000)
Write some trivial tests.  Missing a few still.

src/compiler/base/fasdump.scm
tests/check.scm
tests/compiler/test-fasdump.scm [new file with mode: 0644]

index 16694d588f734c2029b56b88a626381e667b45d0..ccf09cf9695851f81b3123a2653f8286d89e7027 100644 (file)
@@ -1,6 +1,6 @@
 #| -*-Scheme-*-
 
-Copyright (C) 2013 Taylor R Campbell
+Copyright (C) 2013, 2018 Taylor R Campbell
 
 This file is part of MIT/GNU Scheme.
 
@@ -40,6 +40,7 @@ USA.
   (bits-per-byte #f read-only #t)
   (bytes-per-word #f read-only #t)
   (words-per-float #f read-only #t)
+  (float-align-words #f read-only #t)
   (bits-per-bignum-digit #f read-only #t)
   (words-per-bignum-digit #f read-only #t)
   (greatest-fixnum #f read-only #t)
@@ -62,6 +63,7 @@ USA.
    'BITS-PER-BYTE       8
    'BYTES-PER-WORD      bytes-per-word
    'WORDS-PER-FLOAT     (/ 8 bytes-per-word)
+   'FLOAT-ALIGN-WORDS   (/ 8 bytes-per-word) ;XXX may want stricter
    'BITS-PER-BIGNUM-DIGIT       (- (* 8 bytes-per-word) 2)
    'WORDS-PER-BIGNUM-DIGIT      1
    'GREATEST-FIXNUM     (bit-mask (* bytes-per-word 8) 0)
@@ -76,28 +78,28 @@ USA.
                            write-std32be-word
                            write-std32be-untagged-word
                            write-std32be-bignum-digit
-                           write-ieee754-double-be))
+                           write-ieee754-binary64-be))
 
 (define (make-std32le-fasdump-format architecture)
   (make-std-fasdump-format architecture 4
                            write-std32le-word
                            write-std32le-untagged-word
                            write-std32le-bignum-digit
-                           write-ieee754-double-le))
+                           write-ieee754-binary64-le))
 
 (define (make-std64be-fasdump-format architecture)
   (make-std-fasdump-format architecture 8
                            write-std64be-word
                            write-std64be-untagged-word
                            write-std64be-bignum-digit
-                           write-ieee754-double-be))
+                           write-ieee754-binary64-be))
 
 (define (make-std64le-fasdump-format architecture)
   (make-std-fasdump-format architecture 8
                            write-std64le-word
                            write-std64le-untagged-word
                            write-std64le-bignum-digit
-                           write-ieee754-double-le))
+                           write-ieee754-binary64-le))
 \f
 ;;;; Bits
 
@@ -154,7 +156,7 @@ USA.
 (define (write-std64le-bignum-digit digit output-port)
   (write-64 write-le-halves digit output-port))
 
-(define (write-std32le-bignum-digit digit output-port)
+(define (write-std64be-bignum-digit digit output-port)
   (write-64 write-be-halves digit output-port))
 \f
 (define (write-halves* write-halves write-half bits n output-port)
@@ -186,18 +188,17 @@ USA.
   (write-octet n output-port))
 
 (define (write-octet octet output-port)
-  ;; XXX
-  (write-char (integer->char octet) output-port))
+  (write-u8 octet output-port))
 
-(define (write-ieee754-double-be x output-port)
-  (write-ieee754-double write-be-halves x output-port))
+(define (write-ieee754-binary64-be x output-port)
+  (write-ieee754-binary64 write-be-halves x output-port))
 
-(define (write-ieee754-double-le x output-port)
-  (write-ieee754-double write-le-halves x output-port))
+(define (write-ieee754-binary64-le x output-port)
+  (write-ieee754-binary64 write-le-halves x output-port))
 
-(define (write-ieee754-double write-halves x output-port)
+(define (write-ieee754-binary64 write-halves x output-port)
   (receive (sign biased-exponent trailing-significand)
-           (decompose-ieee754-double x)
+           (decompose-ieee754-binary64 x)
     (let ((low  (shiftout trailing-significand #x00000000ffffffff))
           (high (shiftout trailing-significand #x000fffff00000000)))
       (let* ((sign&exponent
@@ -229,6 +230,7 @@ USA.
    'BITS-PER-BYTE       36
    'BYTES-PER-WORD      1
    'WORDS-PER-FLOAT     42              ;XXX
+   'FLOAT-ALIGN-WORDS   ???
    'BITS-PER-BIGNUM-DIGIT       18      ;XXX
    'WORDS-PER-BIGNUM-DIGIT      1/2     ;XXX
    'GREATEST-FIXNUM     #x1fffffff
@@ -271,13 +273,15 @@ USA.
        (lambda ()
          (if done? (error "Re-entry into fasdump not allowed!"))))
      (lambda ()
-       (call-with-output-file temporary
+       (call-with-binary-output-file temporary
          (lambda (output-port)
            (let ((state (make-state format output-port)))
              (set-port-position! output-port
                                  (* fasl-header-n-words
                                     (format.bytes-per-word format)))
+             (assert (fasdump-at-address? state 0))
              (fasdump-object state object)
+             (assert (fasdump-at-address? state (format.bytes-per-word format)))
              (do () ((queue-empty? (state.queue state)))
                (let ((object.n-words (dequeue! (state.queue state))))
                  (let ((object (car object.n-words))
@@ -299,12 +303,12 @@ USA.
 (define (fasdump-primitive-table-entry state primitive)
   (let ((name (car primitive))
         (arity (cdr primitive)))
-    (let ((n-words (fasdump-string-n-words (state.format state) name)))
+    (let ((n-words (fasdump-legacy-string-n-words (state.format state) name)))
       (fasdump-word state tc:fixnum (fixnum->datum (state.format state) arity))
       ;; One word for number of bytes, one word for content.
       (fasdump-word state tc:manifest-nm-vector (+ 1 n-words))
       (fasdump-word state 0 (string-length name))
-      (fasdump-string state name))))
+      (fasdump-legacy-string state name))))
 
 (define (count-primitive-table-entries state)
   (length (state.primitives-reversed state)))
@@ -313,7 +317,7 @@ USA.
   (define (count-words entry)
     ;; One word for arity, one word for manifest-nm-vector, one word
     ;; for number of bytes.
-    (+ 3 (fasdump-string-n-words (state.format state) (car entry))))
+    (+ 3 (fasdump-legacy-string-n-words (state.format state) (car entry))))
   (reduce + 0 (map count-words (state.primitives-reversed state))))
 
 (define (fixnum->datum format fixnum)
@@ -340,7 +344,7 @@ USA.
     (tagged tc:broken-heart             ;1 heap size in words
             (state.n-words state))
     (tagged tc:broken-heart 0)          ;2 heap start address
-    (tagged tc:null 0)                  ;3 dumped object address
+    (tagged tc:false 0)                 ;3 dumped object address
     (tagged tc:broken-heart 0)          ;4 constant size in words
     (tagged tc:broken-heart 0)          ;5 constant start address
     (tagged 1                           ;6 fasl format version/architecture
@@ -353,8 +357,8 @@ USA.
             (count-primitive-table-entries state))
     (tagged tc:broken-heart             ;9 no. of words in primitive table
             (count-primitive-table-words state))
-    (tagged tc:null 0)                  ;10 compiled interface version (0, 0)
-    (tagged tc:null 0)                  ;11 compiled utilities address (#f)
+    (tagged tc:false 0)                 ;10 compiled interface version (0, 0)
+    (tagged tc:false 0)                 ;11 compiled utilities address (#f)
     (untagged 0)                        ;12 header and data checksum (not yet?)
     (tagged tc:broken-heart 0)          ;13 no. of entries in C code table
     (tagged tc:broken-heart 0)          ;14 no. of words in C code table
@@ -397,31 +401,90 @@ USA.
     (with-fasdump-words state n-words
       (lambda ()
         (do ((i 0 (+ i 1))) ((>= i n-words))
-          (fasdump-word state tc:null 0))))))
+          (fasdump-word state tc:false 0))))))
 
 (define (fasdump-float state value)
   (let ((format (state.format state)))
     ((format.write-float format) value (state.output-port state))))
 
-(define (fasdump-string-n-words format string)
-  ;; Add a terminating null byte.
-  (quotient (+ 1 (string-length string) (- (format.bytes-per-word format) 1))
-            (format.bytes-per-word format)))
-
-(define (fasdump-string state string)
+(define (fasdump-legacy-string-n-words format string)
+  (let ((n-cps (string-length string)))
+    (do ((i 0 (+ i 1)))
+        ((>= i n-cps))
+      (if (not (<= 0 (char->integer (string-ref string i)) 255))
+          (error "Non-byte string:" string)))
+    (let ((n-bytes n-cps))
+      ;; Add a terminating null byte.
+      (quotient (+ 1 n-bytes (- (format.bytes-per-word format) 1))
+                (format.bytes-per-word format)))))
+
+(define (fasdump-legacy-string state string)
   (let ((format (state.format state))
         (output-port (state.output-port state)))
     (let ((bytes (string-length string))
-          (n-words (fasdump-string-n-words format string))
+          (n-words (fasdump-legacy-string-n-words format string))
+          (bytes-per-word (format.bytes-per-word format)))
+      (with-fasdump-words state n-words
+        (lambda ()
+          (let ((n-zeros (- (* n-words bytes-per-word) bytes)))
+            (do ((i 0 (+ i 1)))
+                ((>= i (string-length string)))
+              (let ((cp (char->integer (string-ref string i))))
+                (assert (<= 0 cp 255))
+                (write-octet cp output-port)))
+            (do ((i 0 (+ i 1))) ((>= i n-zeros))
+              ;; XXX fasdump-byte, not write-octet
+              (write-octet 0 output-port)))))
+      (assert (zero? (modulo (port-position output-port) bytes-per-word))))))
+\f
+(define (fasdump-bytevector-n-words format bytevector)
+  (let ((n-bytes (bytevector-length bytevector)))
+    (quotient (+ n-bytes (- (format.bytes-per-word format) 1))
+              (format.bytes-per-word format))))
+
+(define (fasdump-bytevector state bytevector)
+  (let ((format (state.format state))
+        (output-port (state.output-port state)))
+    (let ((bytes (bytevector-length bytevector))
+          (n-words (fasdump-bytevector-n-words format bytevector))
           (bytes-per-word (format.bytes-per-word format)))
       (with-fasdump-words state n-words
         (lambda ()
           (let ((n-zeros (- (* n-words bytes-per-word) bytes)))
-            (write-string string output-port)
+            (do ((i 0 (+ i 1)))
+                ((>= i (bytevector-length bytevector)))
+              (write-octet (bytevector-u8-ref bytevector i) output-port))
             (do ((i 0 (+ i 1))) ((>= i n-zeros))
               ;; XXX fasdump-byte, not write-octet
               (write-octet 0 output-port)))))
       (assert (zero? (modulo (port-position output-port) bytes-per-word))))))
+
+(define (fasdump-ustring-n-words format string)
+  (let ((n-cps (string-length string))
+        (bpc (max-bytes-per-cp string)))
+    (let ((n-bytes (* n-cps bpc)))
+      ;; Add a terminating null byte.
+      (quotient (+ 1 n-bytes (- (format.bytes-per-word format) 1))
+                (format.bytes-per-word format)))))
+
+(define (fasdump-ustring-flags format string)
+  format string
+  1)
+
+(define (max-bytes-per-cp string)
+  (define (cp-bytes cp)
+    (let ((bytes (quotient (+ (integer-length cp) 7) 8)))
+      (assert (<= 0 bytes 3))
+      bytes))
+  (do ((i 0 (+ i 1))
+       (bpc 1 (max bpc (cp-bytes (char->integer (string-ref string i))))))
+      ((>= i (string-length string))
+       bpc)))
+
+(define (fasdump-ustring state string)
+  ;; XXX cop-out
+  (assert (= 1 (max-bytes-per-cp string)))
+  (fasdump-legacy-string state string))
 \f
 (define (fasdump-bit-string-n-words format bit-string)
   (let ((bits-per-byte (format.bits-per-byte format))
@@ -509,8 +572,8 @@ USA.
 
 (define (get-primitive-number state name arity)
   (let* ((primitive-name->number (state.primitive-name->number state))
-         (n (hash-table/count primitive-name->number)))
-    (hash-table/intern! primitive-name->number name
+         (n (hash-table-size primitive-name->number)))
+    (hash-table-intern! primitive-name->number name
       (lambda ()
         (set-state.primitives-reversed!
          state
@@ -518,7 +581,7 @@ USA.
         n))))
 
 (define (get-object-address state object n-words overhead alignment)
-  (hash-table/intern! (state.addresses state) object
+  (hash-table-intern! (state.addresses state) object
     (lambda ()
       (let* ((unaligned-address (state.n-words state))
              (aligned-address
@@ -528,7 +591,7 @@ USA.
         (set-state.n-words! state (+ aligned-address n-words))
         (do ((i 0 (+ i 1))) ((>= i n-padding-words))
           (enqueue! (state.queue state) (cons #f 1)))
-        (enqueue! (state.queue state) (cons object n-words))
+        (enqueue! (state.queue state) (cons object (+ overhead n-words)))
         (* (- aligned-address overhead)
            (format.bytes-per-word (state.format state)))))))
 
@@ -549,9 +612,13 @@ USA.
           ((vector? object)
            (if-pointer tc:vector (+ 1 (vector-length object))))
           ((string? object)
-           (if-pointer tc:character-string
-                       ;; One for the real length, one for the manifest.
-                       (+ 2 (fasdump-string-n-words format object))))
+           (if-pointer tc:unicode-string
+                       ;; manifest, length/flags
+                       (+ 1 1 (fasdump-ustring-n-words format object))))
+          ((bytevector? object)
+           (if-pointer tc:bytevector
+                       ;; manifest, length
+                       (+ 1 1 (fasdump-bytevector-n-words format object))))
           ((bit-string? object)
            (if-pointer tc:bit-string
                        ;; One for the real length, one for the manifest.
@@ -579,7 +646,7 @@ USA.
           ((scode? object)
            (fasdump-classify/scode state object if-pointer if-non-pointer))
           ((char? object) (if-non-pointer tc:character (char->integer object)))
-          ((eqv? object #f) (if-non-pointer tc:null null:false))
+          ((eqv? object #f) (if-non-pointer tc:false false:false))
           ((eqv? object #t) (if-non-pointer tc:constant constant:true))
           ((eqv? object (aux-object))
            (if-non-pointer tc:constant constant:aux))
@@ -613,11 +680,12 @@ USA.
                            (+ 1 (fasdump-bignum-n-words format object)))))
           ((exact-rational? object) (if-pointer tc:ratnum 2))
           ((inexact-real? object)
-           (let ((words-per-float (format.words-per-float format)))
+           (let ((words-per-float (format.words-per-float format))
+                 (float-align-words (format.float-align-words format)))
              (if-aligned-pointer tc:big-flonum
                                  words-per-float
                                  1
-                                 words-per-float)))
+                                 float-align-words)))
           ((complex? object) (if-pointer tc:complex 2))
           (else
            (fasdump-error state "Invalid number for fasdump:" object)))))
@@ -625,22 +693,23 @@ USA.
 ;;;;;; Scode classification
 
 (define (fasdump-classify/scode state scode if-pointer if-non-pointer)
-  (cond ((access? scode) (if-pointer tc:access 2))
-        ((assignment? scode) (if-pointer tc:assignment 2))
-        ((combination? scode)
+  (cond ((scode-access? scode) (if-pointer tc:access 2))
+        ((scode-assignment? scode) (if-pointer tc:assignment 2))
+        ((scode-combination? scode)
          (if-pointer tc:combination
                      ;; One for the manifest; one for the operator.
-                     (+ 2 (length (combination-operands scode)))))
-        ((comment? scode) (if-pointer tc:comment 2))
-        ((conditional? scode) (if-pointer tc:conditional 3))
-        ((definition? scode) (if-pointer tc:definition 2))
-        ((delay? scode) (if-pointer tc:delay 1))
-        ((disjunction? scode) (if-pointer tc:disjunction 2))
-        ((lambda? scode) (fasdump-classify/lambda state scode if-pointer))
-        ((quotation? scode) (if-pointer tc:scode-quote 1))
-        ((sequence? scode) (if-pointer tc:sequence 2))
-        ((the-environment? scode) (if-non-pointer tc:the-environment 0))
-        ((variable? scode) (if-pointer tc:variable 3))
+                     (+ 2 (length (scode-combination-operands scode)))))
+        ((scode-comment? scode) (if-pointer tc:comment 2))
+        ((scode-conditional? scode) (if-pointer tc:conditional 3))
+        ((scode-definition? scode) (if-pointer tc:definition 2))
+        ((scode-delay? scode) (if-pointer tc:delay 1))
+        ((scode-disjunction? scode) (if-pointer tc:disjunction 2))
+        ((scode-lambda? scode)
+         (fasdump-classify/lambda state scode if-pointer))
+        ((scode-quotation? scode) (if-pointer tc:scode-quote 1))
+        ((scode-sequence? scode) (if-pointer tc:sequence 2))
+        ((scode-the-environment? scode) (if-non-pointer tc:the-environment 0))
+        ((scode-variable? scode) (if-pointer tc:variable 3))
         (else (error "This is not scode!" scode))))
 
 (define (fasdump-classify/lambda state scode if-pointer)
@@ -659,11 +728,12 @@ USA.
 
 (define (fasdump-storage state object)
   (assert (let ((address
-                 (or (hash-table/get (state.addresses state) object #f)
+                 (or (hash-table-ref/default (state.addresses state) object #f)
                      (error "Unallocated queued object:" object))))
             (fasdump-at-address? state address))
     `(object ,object)
-    `(object address ,(hash-table/get (state.addresses state) object #f))
+    `(object address
+             ,(hash-table-ref/default (state.addresses state) object #f))
     `(current address ,(fasdump-address state)))
   (let ((format (state.format state)))
     (cond ((pair? object)
@@ -679,13 +749,21 @@ USA.
                          (lambda () (vector-ref object i)))))
                    (fasdump-object state element))))))
           ((string? object)
-           (let ((n-words (fasdump-string-n-words format object)))
+           (let ((n-words (fasdump-ustring-n-words format object))
+                 (flags (fasdump-ustring-flags format object)))
              ;; One word for number of bytes, one word for content.
              (fasdump-word state tc:manifest-nm-vector (+ 1 n-words))
              (with-fasdump-words state (+ 1 n-words)
                (lambda ()
-                 (fasdump-word state 0 (string-length object))
-                 (fasdump-string state object)))))
+                 (fasdump-word state flags (string-length object))
+                 (fasdump-ustring state object)))))
+          ((bytevector? object)
+           (let ((n-words (fasdump-bytevector-n-words format object)))
+             (fasdump-word state tc:manifest-nm-vector (+ 1 n-words))
+             (with-fasdump-words state (+ 1 n-words)
+               (lambda ()
+                 (fasdump-word state 0 (bytevector-length object))
+                 (fasdump-bytevector state object)))))
           ((bit-string? object)
            (let ((n-words (fasdump-bit-string-n-words format object)))
              ;; One word for number of bits, one word for content.
@@ -697,10 +775,11 @@ USA.
           ((symbol? object)
            (with-fasdump-words state 2
              (lambda ()
-               (fasdump-object state (symbol->string object))
+               (fasdump-object state (string->utf8 (symbol->string object)))
                (if (uninterned-symbol? object)
                    (fasdump-word state tc:reference-trap trap:unbound)
-                   ;; XXX Hysterical raisins...
+                   ;; Fasloader uses this to distinguish interned
+                   ;; symbols from uninterned ones.
                    (fasdump-word state tc:broken-heart 0)))))
           ((reference-trap? object)
            (assert (> (reference-trap-kind object) trap-max-immediate))
@@ -713,7 +792,7 @@ USA.
           ((scode? object)
            (fasdump-storage/scode state object))
           ((eqv? object #f)             ;XXX Alignment kludge...
-           (fasdump-word state tc:null 0))
+           (fasdump-word state tc:false 0))
           (else
            (error "Fasdump bug -- object should have been rejected:"
                   object)))))
@@ -752,82 +831,84 @@ USA.
 ;;;;; Fasdumping an scode pointer's storage
 
 (define (fasdump-storage/scode state scode)
-  (cond ((access? scode)
+  (cond ((scode-access? scode)
          (with-fasdump-words state 2
            (lambda ()
-             (fasdump-object state (access-environment scode))
-             (fasdump-object state (access-name scode)))))
-        ((assignment? scode)
+             (fasdump-object state (scode-access-environment scode))
+             (fasdump-object state (scode-access-name scode)))))
+        ((scode-assignment? scode)
          (with-fasdump-words state 2
            (lambda ()
-             (fasdump-object state (assignment-variable scode))
-             (fasdump-object state (assignment-value scode)))))
-        ((combination? scode)
-         (let* ((operands (combination-operands scode))
+             (fasdump-object state
+                             (make-scode-variable
+                              (scode-assignment-name scode)))
+             (fasdump-object state (scode-assignment-value scode)))))
+        ((scode-combination? scode)
+         (let* ((operands (scode-combination-operands scode))
                 (n-words (+ 1 (length operands))))
            (fasdump-word state tc:manifest-vector n-words)
            (with-fasdump-words state n-words
              (lambda ()
-               (fasdump-object state (combination-operator scode))
+               (fasdump-object state (scode-combination-operator scode))
                (for-each (lambda (operand)
                            (fasdump-object state operand))
                          operands)))))
-        ((comment? scode)
+        ((scode-comment? scode)
          (with-fasdump-words state 2
            (lambda ()
-             (fasdump-object state (comment-expression scode))
-             (fasdump-object state (comment-text scode)))))
-        ((conditional? scode)
+             (fasdump-object state (scode-comment-expression scode))
+             (fasdump-object state (scode-comment-text scode)))))
+        ((scode-conditional? scode)
          (with-fasdump-words state 3
            (lambda ()
-             (fasdump-object state (conditional-predicate scode))
-             (fasdump-object state (conditional-consequent scode))
-             (fasdump-object state (conditional-alternative scode)))))
-        ((definition? scode)
+             (fasdump-object state (scode-conditional-predicate scode))
+             (fasdump-object state (scode-conditional-consequent scode))
+             (fasdump-object state (scode-conditional-alternative scode)))))
+        ((scode-definition? scode)
          (with-fasdump-words state 2
            (lambda ()
-             (fasdump-object state (definition-name scode))
-             (fasdump-object state (definition-value scode)))))
-        ((delay? scode)
+             (fasdump-object state (scode-definition-name scode))
+             (fasdump-object state (scode-definition-value scode)))))
+        ((scode-delay? scode)
          (with-fasdump-words state 1
            (lambda ()
-             (fasdump-object state (delay-expression scode)))))
-        ((disjunction? scode)
+             (fasdump-object state (scode-delay-expression scode)))))
+        ((scode-disjunction? scode)
          (with-fasdump-words state 2
            (lambda ()
-             (fasdump-object state (disjunction-predicate scode))
-             (fasdump-object state (disjunction-alternative scode)))))
-        ((lambda? scode)
-         (lambda-components scode
+             (fasdump-object state (scode-disjunction-predicate scode))
+             (fasdump-object state (scode-disjunction-alternative scode)))))
+        ((scode-lambda? scode)
+         (scode-lambda-components scode
            (lambda (name required optional rest aux decls body)
              (let* ((body
                      (if (pair? decls)
-                         (make-sequence
-                          (list (make-block-declaration decls)
+                         (make-scode-sequence
+                          (list (make-scode-block-declaration decls)
                                 body))
                          body))
                     (body (make-auxiliary-lambda aux body)))
                (if (or (pair? optional) rest)
                    (fasdump-xlambda state name required optional rest body)
                    (fasdump-lambda state name required body))))))
-        ((quotation? scode)
+        ((scode-quotation? scode)
          (with-fasdump-words state 1
            (lambda ()
-             (fasdump-object state (quotation-expression scode)))))
-        ((sequence? scode)
+             (fasdump-object state (scode-quotation-expression scode)))))
+        ((scode-sequence? scode)
          (with-fasdump-words state 2
            (lambda ()
-             (let ((actions (sequence-actions scode)))
+             (let ((actions (scode-sequence-actions scode)))
                (assert (not (length<=? actions 1)))
                (fasdump-object state (car actions))
                (fasdump-object state
                                (if (length<=? actions 2)
                                    (cadr actions)
-                                   (make-sequence (cdr actions))))))))
-        ((variable? scode)
+                                   (make-scode-sequence (cdr actions))))))))
+        ((scode-variable? scode)
          (with-fasdump-words state 3
            (lambda ()
-             (fasdump-object state (variable-name scode))
+             (fasdump-object state (scode-variable-name scode))
              ;; XXX Hysterical raisins...
              (fasdump-object state #t)
              (fasdump-object state '()))))
@@ -868,7 +949,7 @@ USA.
 (define (make-auxiliary-lambda auxiliaries body)
   (if (not (pair? auxiliaries))
       body
-      (make-combination
+      (make-scode-combination
        ;; NOTE: The list of auxiliaries must be empty here to avoid
        ;; infinite recursion!
        (let ((name lambda-tag:internal-lambda)
@@ -878,7 +959,7 @@ USA.
              (aux '())
              (decls '())
              (body body))
-         (make-lambda name required optional rest aux decls body))
+         (make-scode-lambda name required optional rest aux decls body))
        (map (lambda (auxiliary)
               auxiliary                 ;ignore
               (make-unassigned-reference-trap))
@@ -892,6 +973,7 @@ USA.
 (define tc:big-flonum #x06)
 (define tc:bit-string #x2f)
 (define tc:broken-heart #x22)
+(define tc:bytevector #x33)
 (define tc:character #x02)
 (define tc:character-string #x1e)
 (define tc:combination #x26)
@@ -903,12 +985,12 @@ USA.
 (define tc:delay #x11)
 (define tc:disjunction #x35)
 (define tc:extended-lambda #x14)
+(define tc:false #x00)
 (define tc:fixnum #x1a)
 (define tc:interned-symbol #x1d)
 (define tc:lambda #x17)
 (define tc:list #x01)                   ;pair
 (define tc:manifest-nm-vector #x27)
-(define tc:null #x00)
 (define tc:primitive #x18)
 (define tc:ratnum #x3a)
 (define tc:reference-trap #x32)
@@ -916,13 +998,14 @@ USA.
 (define tc:scode-quote #x03)
 (define tc:sequence #x19)
 (define tc:the-environment #x2d)
+(define tc:unicode-string #x1b)
 (define tc:uninterned-symbol #x05)
 (define tc:variable #x2c)
 (define tc:vector #x0a)
 
-(define tc:manifest-vector tc:null)
+(define tc:manifest-vector tc:false)
 
-(define null:false 0)
+(define false:false 0)
 
 (define constant:true 0)
 (define constant:unspecific 1)
@@ -935,23 +1018,30 @@ USA.
 (define constant:null 9)
 
 (define trap:unbound 2)
+(define trap-max-immediate 9)
+
+(define (reference-trap-kind trap)
+  (error 'reference-trap-kind trap))
+
+(define (reference-trap-extra trap)
+  (error 'reference-trap-extra trap))
 \f
 ;;;; Utilities
 
 (define (scode? object)
-  (or (access? object)
-      (assignment? object)
-      (combination? object)
-      (comment? object)
-      (conditional? object)
-      (definition? object)
-      (delay? object)
-      (disjunction? object)
-      (lambda? object)
-      (quotation? object)
-      (sequence? object)
-      (the-environment? object)
-      (variable? object)))
+  (or (scode-access? object)
+      (scode-assignment? object)
+      (scode-combination? object)
+      (scode-comment? object)
+      (scode-conditional? object)
+      (scode-definition? object)
+      (scode-delay? object)
+      (scode-disjunction? object)
+      (scode-lambda? object)
+      (scode-quotation? object)
+      (scode-sequence? object)
+      (scode-the-environment? object)
+      (scode-variable? object)))
 
 (define (shiftout n mask)
   (shift-right (bitwise-and n mask) (first-set-bit mask)))
@@ -1001,143 +1091,11 @@ USA.
 (define (optional-object) #!optional)
 (define (rest-object) #!rest)
 (define (unspecific-object) #!unspecific)
-\f
-;;;; IEEE 754 utilities
-
-(define (decompose-ieee754-double x)
-  (decompose-ieee754-binary x 11 53))
-
-(define (decompose-ieee754-binary x exponent-bits precision)
-  (receive (base emin emax bias exp-subnormal exp-inf/nan)
-           (ieee754-binary-parameters exponent-bits precision)
-    (decompose-ieee754 x base emax precision
-      (lambda (sign)                    ;if-zero
-        (values sign 0 0))
-      (lambda (sign scaled-significand) ;if-subnormal
-        (assert (= 0 (shift-right scaled-significand precision)))
-        (values sign exp-subnormal scaled-significand))
-      (lambda (sign exponent scaled-significand) ;if-normal
-        (assert (<= emin exponent emax))
-        ;; The integer part is always 1.  Strip it for the binary
-        ;; interchange format.
-        (assert (= 1 (shift-right scaled-significand (- precision 1))))
-        (values sign
-                (+ exponent bias)
-                (extract-bit-field (- precision 1) 0 scaled-significand)))
-      (lambda (sign)                    ;if-infinite
-        (values sign exp-inf/nan 0))
-      (lambda (sign quiet payload)      ;if-nan
-        (assert (not (and (zero? quiet) (zero? payload))))
-        (values sign
-                exp-inf/nan
-                (replace-bit-field (- precision 1) 1 payload quiet))))))
-
-(define (ieee754-sign x)
-  (cond ((< 0 x) 0)
-        ((< x 0) 1)
-        ;; Zero -- can't use < directly to detect sign.  Elicit a
-        ;; computational difference.
-        ((negative? (atan x -1)) 1)
-        (else 0)))
-
-(define (decompose-ieee754 x base emax precision
-          if-zero if-subnormal if-normal if-infinite if-nan)
-  (cond ((not (= x x))
-         ;; There are, of course, b^p different NaNs.  There is no
-         ;; obvious way to computationally detect the sign of a NaN,
-         ;; and no portable way to get at the quiet bit or the payload
-         ;; bits, so we'll just assume every NaN is a trivial positive
-         ;; signalling NaN and hope the caller has a good story...
-         (if-nan 0 0 1))
-        ((and (< 1. (abs x)) (= x (/ x 2)))
-         (if-infinite (if (< 0. x) 0 1)))
-        (else
-         (let ((sign (ieee754-sign x)) (x (abs x)) (emin (- 1 emax)))
-           (define (significand x)
-             (truncate->exact (* x (expt base (- precision 1)))))
-           (cond ((<= 1 x)              ;Nonnegative exponent (normal)
-                  (let loop ((exponent 0) (x x))
-                    (cond ((< emax exponent) (if-infinite sign))
-                          ((<= base x) (loop (+ exponent 1) (/ x base)))
-                          (else (if-normal sign exponent (significand x))))))
-                 ((< (expt base emin) x) ;Negative exponent, normal
-                  (let loop ((exponent 0) (x x))
-                    (assert (<= emin exponent))
-                    (if (<= 1 x)
-                        (if-normal sign exponent (significand x))
-                        (loop (- exponent 1) (* x base)))))
-                 ((< 0 x)               ;Negative exponent, subnormal
-                  (if (<= x (- (expt base emin) (expt base (- 0 precision))))
-                      (if-zero sign)
-                      (if-subnormal
-                       sign
-                       (significand (/ x (expt base emin))))))
-                 (else
-                  (if-zero sign)))))))
-\f
-(define (compose-ieee754-double sign biased-exponent trailing-significand)
-  (compose-ieee754-binary sign biased-exponent trailing-significand 11 53))
-
-(define (compose-ieee754-binary sign biased-exponent trailing-significand
-                                exponent-bits precision)
-  (receive (base emin emax bias exp-subnormal exp-inf/nan)
-           (ieee754-binary-parameters exponent-bits precision)
-    (let ((exponent (- biased-exponent bias)))
-      (cond ((= exponent exp-subnormal)
-             (if (zero? trailing-significand)
-                 (compose-ieee754-zero sign base emax precision)
-                 (compose-ieee754-subnormal sign trailing-significand
-                                            base emax precision)))
-            ((= exponent exp-inf/nan)
-             (if (zero? trailing-significand)
-                 (compose-ieee754-infinity sign base emax precision)
-                 (let ((p-1 (- precision 1))
-                       (T trailing-significand))
-                   (let ((quiet   (extract-bit-field 1 p-1 T))
-                         (payload (extract-bit-field p-1 0 T)))
-                     (compose-ieee754-nan sign quiet payload
-                                          base emax precision)))))
-            (else
-             (assert (<= emin exponent emax))
-             (let ((scaled-significand
-                    ;; Add the implied integer part of 1.
-                    (replace-bit-field 1 (- precision 1) trailing-significand
-                                       1)))
-               (compose-ieee754-normal sign exponent scaled-significand
-                                       base emax precision)))))))
-
-(define (compose-ieee754-zero sign base emax precision)
-  base emax precision                   ;ignore
-  (* (expt -1 sign) 0))
-
-(define (compose-ieee754-subnormal sign significand base emax precision)
-  (* (expt -1 sign)
-     (* significand (expt base (- precision emax)))))
-
-(define (compose-ieee754-normal sign exponent significand base emax precision)
-  (assert (<= (- 1 emax) exponent emax))
-  (* (expt -1 sign)
-     (expt base exponent)
-     (/ significand (expt base (- precision 1)))))
-
-(define (compose-ieee754-infinity sign)
-  (error "Can't compose an IEEE754 infinity!" sign))
-
-(define (compose-ieee754-nan sign quiet payload)
-  (error "Can't compose an IEEE754 NaN!" sign quiet payload))
-
-(define (ieee754-binary-parameters exponent-bits precision)
-  (assert (zero? (modulo (+ exponent-bits precision) 32)))
-  (let* ((base 2)
-         (emax (- (expt base (- exponent-bits 1)) 1)))
-    (let ((bias emax)
-          (emin (- 1 emax)))
-      (let ((exp-subnormal (- emin 1))
-            (exp-inf/nan (+ emax 1)))
-        (values base emin emax bias exp-subnormal exp-inf/nan)))))
-
-(define (ieee754-double-recomposable? x)
-  (= x
-     (receive (sign biased-exponent trailing-significand)
-              (decompose-ieee754-double x)
-       (compose-ieee754-double sign biased-exponent trailing-significand))))
+
+(define (port-position port)
+  ((access binary-port-position (->environment '(runtime binary-port))) port))
+
+(define (set-port-position! port position)
+  ((access set-binary-port-position! (->environment '(runtime binary-port)))
+   port
+   position))
\ No newline at end of file
index f843c729de1c2dbb85a29ef942c413387895cd75..a0dd7b452fddb8c121d17105e463674134d14a8f 100644 (file)
@@ -40,6 +40,7 @@ USA.
 
 (define known-tests
   '(
+    ("compiler/test-fasdump" (compiler portable-fasdump))
     "compiler/test-fgopt-conect"
     "compiler/test-toplev"
     "compiler/test-varname"
diff --git a/tests/compiler/test-fasdump.scm b/tests/compiler/test-fasdump.scm
new file mode 100644 (file)
index 0000000..ceda794
--- /dev/null
@@ -0,0 +1,287 @@
+#| -*-Scheme-*-
+
+Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
+    1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+    2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016,
+    2017, 2018 Massachusetts Institute of Technology
+
+This file is part of MIT/GNU Scheme.
+
+MIT/GNU Scheme 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 of the License, or (at
+your option) any later version.
+
+MIT/GNU Scheme 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 MIT/GNU Scheme; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
+USA.
+
+|#
+
+;;;; Tests for fasdumper
+
+(declare (usual-integrations))
+\f
+(define (define-enumerated-test name cases procedure)
+  (define-test name
+    (map (lambda (arguments)
+           (lambda ()
+             (apply procedure arguments)))
+         cases)))
+
+(define (equal-nan-scode? x y)
+  (let loop ((x x) (y y))
+    (cond ((and (flo:flonum? x) (flo:nan? x))
+           (and (flo:flonum? y)
+                (flo:nan? y)
+                (eqv? (flo:sign-negative? x) (flo:sign-negative? y))
+                (eqv? (flo:nan-quiet? x) (flo:nan-quiet? y))
+                (eqv? (flo:nan-payload x) (flo:nan-payload y))))
+          ((scode-access? x)
+           (and (scode-access? y)
+                (loop (scode-access-environment x)
+                      (scode-access-environment y))
+                (loop (scode-access-name x)
+                      (scode-access-name y))))
+          ((scode-assignment? x)
+           (and (scode-assignment? y)
+                (loop (scode-assignment-name x)
+                      (scode-assignment-name y))
+                (loop (scode-assignment-value x)
+                      (scode-assignment-value y))))
+          ((scode-assignment? x)
+           (and (scode-assignment? y)
+                (loop (scode-assignment-name x)
+                      (scode-assignment-name y))
+                (loop (scode-assignment-value x)
+                      (scode-assignment-value y))))
+          ((scode-combination? x)
+           (and (scode-combination? y)
+                (loop (scode-combination-operator x)
+                      (scode-combination-operator y))
+                (every loop
+                       (scode-combination-operands x)
+                       (scode-combination-operands y))))
+          ((scode-comment? x)
+           (and (scode-comment? y)
+                (loop (scode-comment-text x)
+                      (scode-comment-text y))
+                (loop (scode-comment-expression x)
+                      (scode-comment-expression y))))
+          ((scode-conditional? x)
+           (and (scode-conditional? y)
+                (loop (scode-conditional-predicate x)
+                      (scode-conditional-predicate y))
+                (loop (scode-conditional-consequent x)
+                      (scode-conditional-consequent y))
+                (loop (scode-conditional-alternative x)
+                      (scode-conditional-alternative y))))
+          ((scode-definition? x)
+           (and (scode-definition? y)
+                (loop (scode-definition-name x)
+                      (scode-definition-name y))
+                (loop (scode-definition-value x)
+                      (scode-definition-value y))))
+          ((scode-delay? x)
+           (and (scode-delay? y)
+                (loop (scode-delay-expression x)
+                      (scode-delay-expression y))))
+          ((scode-disjunction? x)
+           (and (scode-disjunction? y)
+                (loop (scode-disjunction-predicate x)
+                      (scode-disjunction-predicate y))
+                (loop (scode-disjunction-alternative x)
+                      (scode-disjunction-alternative y))))
+          ((scode-lambda? x)
+           (and (scode-lambda? y)
+                (scode-lambda-components x
+                  (lambda (xname xreq xopt xrest xaux xdecl xbody)
+                    (scode-lambda-components y
+                      (lambda (yname yreq yopt yrest yaux ydecl ybody)
+                        (and (loop xname yname)
+                             (every loop xreq yreq)
+                             (every loop xopt yopt)
+                             (loop xrest yrest)
+                             (every loop xaux yaux)
+                             (every loop xdecl ydecl)
+                             (loop xbody ybody))))))))
+          ((scode-quotation? x)
+           (and (scode-quotation? y)
+                (loop (scode-quotation-expression x)
+                      (scode-quotation-expression y))))
+          ((scode-sequence? x)
+           (and (scode-sequence? y)
+                (every loop
+                       (scode-sequence-actions x)
+                       (scode-sequence-actions y))))
+          ((scode-the-environment? x)
+           (scode-the-environment? y))
+          ((scode-variable? x)
+           (and (scode-variable? y)
+                (loop (scode-variable-name x)
+                      (scode-variable-name y))))
+          (else
+           (equal? x y)))))
+
+(define-comparator equal-nan-scode? 'equal-nan-scode?)
+
+(define assert-equal-nan-scode
+  (simple-binary-assertion equal-nan-scode? #f))
+
+(define-enumerated-test 'fasdump-invariance
+  `(((1 . 2))
+    (#())
+    (#(0))
+    (#(0 1))
+    (#(0 1 2))
+    (#(0 1 2 3))
+    (#(0 1 2 3 4))
+    (#(0 1 2 3 4 5))
+    (#(0 1 2 3 4 5 6))
+    (#(0 1 2 3 4 5 6 7))
+    (#(0 1 2 3 4 5 6 7 8))
+    (#(0 1 2 3 4 5 6 7 8 9))
+    (#(0 1 2 3 4 5 6 7 8 9 10))
+    (#(0 1 2 3 4 5 6 7 8 9 10 11))
+    (#(0 1 2 3 4 5 6 7 8 9 10 11 12))
+    (#(0 1 2 3 4 5 6 7 8 9 10 11 12 13))
+    (#(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14))
+    (#(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))
+    (#(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16))
+    (#(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17))
+    ("")
+    ("a")
+    ("ab")
+    ("abc")
+    ("abcd")
+    ("abcde")
+    ("abcdef")
+    ("abcdefg")
+    ("abcdefgh")
+    ("abcdefghi")
+    ("abcdefghij")
+    ("abcdefghijk")
+    ("abcdefghijkl")
+    ("abcdefghijklm")
+    ("abcdefghijklmn")
+    ("abcdefghijklmno")
+    ("abcdefghijklmnop")
+    ("abcdefghijklmnopq")
+    ("abcdefghijklmnopqr")
+    ("abcdefghijklmnopqrs")
+    ("abcdefghijklmnopqrst")
+    ("abcdefghijklmnopqrstu")
+    ("abcdefghijklmnopqrstuv")
+    ("abcdefghijklmnopqrstuvw")
+    ("abcdefghijklmnopqrstuvwx")
+    ("abcdefghijklmnopqrstuvwxy")
+    ("abcdefghijklmnopqrstuvwxyz")
+    ("\x0;abcdefghijklmnopqrstuvwxyz")
+    (#u8())
+    (#u8(1))
+    (#u8(1 2))
+    (#u8(1 2 3))
+    (#u8(1 2 3 4))
+    (#u8(1 2 3 4 5))
+    (#u8(1 2 3 4 5 6))
+    (#u8(1 2 3 4 5 6 7))
+    (#u8(1 2 3 4 5 6 7 8))
+    (#u8(1 2 3 4 5 6 7 8 9))
+    (#u8(1 2 3 4 5 6 7 8 9 10))
+    (#u8(1 2 3 4 5 6 7 8 9 10 11))
+    (#u8(1 2 3 4 5 6 7 8 9 10 11 12))
+    (#u8(1 2 3 4 5 6 7 8 9 10 11 12 13))
+    (#u8(1 2 3 4 5 6 7 8 9 10 11 12 13 14))
+    (#u8(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))
+    (#u8(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16))
+    (#u8(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17))
+    (#*)
+    (#*0)
+    (#*10)
+    (#*010)
+    (#*1010)
+    (#*01010)
+    (#*101010)
+    (#*0101010)
+    (#*10101010)
+    (#*010101010)
+    ;; XXX go up to 65
+    (||)
+    (x)
+    (xyz)
+    ;; XXX uninterned symbols
+    (,(make-primitive-procedure 'quagga 42))
+    ;; XXX reference trap
+    ;; XXX interpreter return address, wtf?
+    (#\U+0)
+    (#\0)
+    (#\U+1000)
+    (,(expt 2 100))
+    (-inf.0)
+    (-123.)
+    (,(flo:negate flo:smallest-positive-subnormal))
+    (-0.)
+    (0.)
+    (,flo:smallest-positive-subnormal)
+    (123.)
+    (+inf.0)
+    (,(flo:make-nan #f #t 0))
+    (,(flo:make-nan #t #t 0))
+    (,(flo:make-nan #f #t 1))
+    (,(flo:make-nan #t #t 1))
+    (,(flo:make-nan #f #f 1))
+    (,(flo:make-nan #t #f 1))
+    (1+2i)
+    (1.+2.i)
+    (#t)
+    (#f)
+    (())
+    (#!key)
+    (#!optional)
+    (#!rest)
+    (,(eof-object))
+    (#!unspecific)
+    (,(make-scode-access #f 'foo))
+    (,(make-scode-assignment 'foo (make-scode-variable 'bar)))
+    (,(make-scode-combination (make-scode-variable 'foo)
+                              (list (make-scode-variable 'bar))))
+    (,(make-scode-conditional (make-scode-variable 'p)
+                              (make-scode-variable 'c)
+                              (make-scode-variable 'a)))
+    (,(make-scode-definition 'foo (make-scode-variable 'bar)))
+    (,(make-scode-delay (make-scode-variable 'foo)))
+    (,(make-scode-disjunction (make-scode-variable 'a)
+                              (make-scode-variable 'b)))
+    (,(syntax '(lambda (x y #!optional z #!rest w)
+                 (declare (no-type-checks))
+                 (define (foo) x)
+                 (define (bar) z)
+                 (list (foo) (bar) x y z w))
+              (->environment '())))
+    (,(make-scode-quotation '(fnord #(blarf 1.23 #u8(87)))))
+    (,(make-scode-sequence
+       (list (make-scode-assignment 'foo 8)
+             (make-scode-assignment 'bar 'baz))))
+    (,(make-scode-the-environment))
+    (,(make-scode-variable 'foo)))
+  (lambda (object)
+    (with-test-properties
+        (lambda ()
+          (call-with-temporary-file-pathname
+            (lambda (pathname)
+              (let ((format fasdump-format:amd64))
+                (portable-fasdump object pathname format))
+              (let ((object* (fasload pathname)))
+                (if (not (equal-nan-scode? object object*))
+                    (begin
+                      (pp 'fail)
+                      (pp object)
+                      (pp object*)))
+                (assert-equal-nan-scode (fasload pathname) object)))))
+      'SEED object)))
\ No newline at end of file