home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / t3_1 / risc_src.lha / risc_sources / comp / top / primop.t < prev    next >
Encoding:
Text File  |  1989-06-30  |  12.9 KB  |  373 lines

  1. (herald (orbit_top oprimops))
  2.  
  3. ;;; Copyright (c) 1985 Yale University
  4. ;;;     Authors: N Adams, R Kelsey, D Kranz, J Philbin, J Rees.
  5. ;;; This material was developed by the T Project at the Yale University Computer 
  6. ;;; Science Department.  Permission to copy this software, to redistribute it, 
  7. ;;; and to use it for any purpose is granted, subject to the following restric-
  8. ;;; tions and understandings.
  9. ;;; 1. Any copy made of this software must include this copyright notice in full.
  10. ;;; 2. Users of this software agree to make their best efforts (a) to return
  11. ;;;    to the T Project at Yale any improvements or extensions that they make,
  12. ;;;    so that these may be included in future releases; and (b) to inform
  13. ;;;    the T Project of noteworthy uses of this software.
  14. ;;; 3. All materials developed as a consequence of the use of this software
  15. ;;;    shall duly acknowledge such use, in accordance with the usual standards
  16. ;;;    of acknowledging credit in academic research.
  17. ;;; 4. Yale has made no warrantee or representation that the operation of
  18. ;;;    this software will be error-free, and Yale is under no obligation to
  19. ;;;    provide any services, by way of maintenance, update, or otherwise.
  20. ;;; 5. In conjunction with products arising from the use of this material,
  21. ;;;    there shall be no use of the name of the Yale University nor of any
  22. ;;;    adaptation thereof in any advertising, promotional, or sales literature
  23. ;;;    without prior written consent from Yale in each case.
  24. ;;;
  25.  
  26. ;;;
  27. ;;;    PRIMITIVE OPERATIONS
  28. ;;;
  29. ;;; The operations on primops are all of the form PRIMOP.<name>
  30. ;;;
  31.  
  32. (define primop-table (make-table 'primop-table))
  33.  
  34. ;;; %PRIMOP
  35. ;;;   The information about a primitive operation.
  36.  
  37. (define-structure-type %primop
  38.  
  39. ;;; Data fields for the primop implemetation
  40.   handler        ; A handler for this specific primop
  41.   bitv           ; Bit set for coding primop predicates
  42.   id             ; Symbol identifying this primop
  43.   formals        ; Formal arguments to this primop if it has parameters
  44.   source         ; Source code for the primop
  45.  
  46. ;;; Methods that most primops have
  47.   simplify       ; Simplify method
  48.   integrate?     ; When to integrate this primop
  49.   type           ; The type of this primop as a procedure
  50.   generate       ; Code generation routine
  51.   arg-specs      ; Code generation data
  52.   rep-wants      ; Code generation data
  53.  
  54.   (((identification self) (%primop-id self))
  55.     ((print self stream) (format stream "#{Primop~_~S~_~S}"
  56.                          (object-hash self) (%primop-id self)))))
  57.  
  58. (define primop? %primop?)
  59.  
  60. (set (%primop-source (stype-master %primop-stype)) nil)
  61.  
  62. ;;; System internal fields
  63.  
  64. (define primop.id          %primop-id)
  65. (define primop.formals     %primop-formals)
  66. (define primop.source      %primop-source)
  67.  
  68. (define (any-primop-id primop)
  69.   (cond ((primop.variant-id primop)
  70.          => identity)
  71.         ((primop.id primop)
  72.          => identity)
  73.         (else
  74.          'anonymous)))
  75.  
  76. ;;;
  77. ;;;   Primop Predicates
  78. ;;;
  79. ;;; These are coded into the %PRIMOP-BITV field of %PRIMOP.  Every predicate
  80. ;;; has an associated index into primops bitvs that indicates the value of the
  81. ;;; predicate on the particular primop.
  82.  
  83. (define primop-predicate-table
  84.   (make-table 'primop-predicate-table))
  85.  
  86. (lset *next-primop-predicate-index* 0)
  87.  
  88. (define-local-syntax (define-primop-predicate name)
  89.   (let ((name (concatenate-symbol 'primop. name)))
  90.     `(let ((mask (set-bit-field 0 *next-primop-predicate-index* 1 1)))
  91.        (increment *next-primop-predicate-index*)
  92.        (set (table-entry primop-predicate-table ',name) mask)
  93.        (define ,name (primop-predicate mask)))))
  94.  
  95. (define (primop-predicate mask)
  96.   (lambda (primop)
  97.     (fxn= 0 (fixnum-logand mask (%primop-bitv primop)))))
  98.  
  99. (define-primop-predicate constructed?)
  100. (define-primop-predicate side-effects?)
  101. (define-primop-predicate settable?)
  102. (define-primop-predicate uses-L-value?)
  103. (define-primop-predicate definition?)
  104. (define-primop-predicate special?)
  105. (define-primop-predicate type-predicate?)
  106. (define-primop-predicate conditional?)
  107. (define-primop-predicate location?)
  108. (define-primop-predicate recursive?)
  109.  
  110. ;;;
  111. ;;;   Primop Fields
  112. ;;;
  113. ;;;  These are the operations that many but not all primops handle.
  114.  
  115. (define primop-field-table
  116.   (make-table 'primop-field-table))
  117.  
  118. (define-local-syntax (define-primop-field name args . default)
  119.   (let* ((title (concatenate-symbol 'primop. name))
  120.          (field (concatenate-symbol '%primop- name))
  121.          (primop (car args))
  122.          (method (if default 
  123.                      default
  124.                      `(bug "~S has no method for ~S" ',primop ',title))))
  125.     `(block (set (,field (stype-master %primop-stype))
  126.                  (lambda ,args (ignorable . ,args) . ,method))
  127.             (set (table-entry primop-field-table ',title) ',field)
  128.             (define (,title . ,args)
  129.               ((,field ,primop) . ,args)))))
  130.  
  131. ;;; Simplification
  132. (define-primop-field simplify    (primop node) nil)
  133. (define-primop-field integrate?  (primop node)
  134.   (and (eq? (node-role node) call-proc)
  135.        (primop-type-check primop (node-parent node))))
  136.  
  137. ;;; Code generation
  138. (define-primop-field generate  (primop node))
  139. (define-primop-field type      (primop node) type/top)
  140. (define-primop-field arg-specs (primop) nil)
  141. (define-primop-field rep-wants (primop) nil)
  142.  
  143. ;;;
  144. ;;;   Primop Operations
  145. ;;;
  146. ;;; Non generic operations, specific to certain types of primops 
  147.  
  148. (define primop-operation-table
  149.   (make-table 'primop-operation-table))
  150.  
  151. (define-local-syntax (define-primop-operation name args . default)
  152.   (let* ((title (concatenate-symbol 'primop. name))
  153.          (field (concatenate-symbol '%primop- name))
  154.          (primop (car args))
  155.          (method (if default 
  156.                      default
  157.                      `(error "~S has no method for ~S" ',primop ',title))))
  158.     `(block (define-operation (,field %%handler . ,args) . ,default)
  159.             (set (table-entry primop-operation-table ',title) ',field)
  160.             (define (,title . ,args)
  161.               (,field (%primop-handler ,primop) . ,args)))))
  162.  
  163. ;;; Alphatize
  164. (define-primop-operation make-closed (primop) (make-closed-primop primop))
  165.  
  166. ;;; Simplification
  167. (define-primop-operation presimplify (primop node) nil)
  168.  
  169. ;;; Parameterized primops
  170. (define-primop-operation constructor (primop))
  171. (define-primop-operation arglist     (primop) '())
  172. (define-primop-operation variant-id  (primop) nil)
  173.  
  174. ;;; Creating support
  175. (define-primop-operation definition-variant (primop))
  176.  
  177. ;;; Flow of control
  178. (define-primop-operation test-code    (primop node arg) nil)
  179. (define-primop-operation compare-code (primop node arg) nil)
  180.  
  181. ;;; Code Generation
  182. (define-primop-operation values-returned (primop)
  183.   (if (primop.side-effects? primop) 0 1))
  184.  
  185. ;;; Locations
  186. (define-primop-operation location-specs (primop) nil)
  187. (define-primop-operation simplify-setter (self call) nil)
  188. (define-primop-operation contents-type (self) type/top)
  189. (define-primop-operation set-type (self) type/top)
  190.  
  191. ;;; Conditionals and Predicates
  192. (define-primop-operation conditional-type (primop node))
  193. (define-primop-operation predicate-type (primop node))
  194. (define-primop-operation primop.simplify-jump? (primop index) nil)
  195. (define-primop-operation primop.known-values? (primop call)
  196.   (return nil nil nil))
  197.  
  198. ;;; Type Predicates
  199. (define-primop-operation jump-on-equal? (primop) nil)
  200.  
  201. ;;;
  202. ;;;   Parameterized Primops
  203. ;;;
  204. ;;; These are primops that produce new primops when called.
  205.  
  206. ;;; BUG: Parameterized primops cannot produce parameterized primops
  207. ;;; BUG: Parameterized primops cannot be N-ary
  208.  
  209. (define (hash-primop-list l)
  210.   (iterate loop ((l l) (hash 4324277))
  211.     (if (null? l)
  212.         (fixnum-logand hash *max-fixnum*)
  213.         (loop (cdr l)
  214.               (fixnum-add (fixnum-ashl hash 1)
  215.                           (descriptor->fixnum (car l)))))))
  216.  
  217. (define constructed-primops 
  218.   (create-%table 'constructed-primops
  219.                  0
  220.                  t
  221.                  list?
  222.                  hash-primop-list
  223.                  alikev?))
  224.  
  225. (define (construct-primop base args)
  226.   (let ((key (cons base args)))
  227.     (cond ((table-entry constructed-primops key)
  228.            => identity)
  229.           (else
  230.            (let ((new ((apply (primop.constructor base) args) base)))
  231.              (set (table-entry constructed-primops key) new)         
  232.              new)))))
  233.  
  234. ;;;
  235. ;;;   Creating Primops
  236. ;;;
  237. ;;; The syntax for primops is (PRIMOP <id> <formals list> . <method-clauses>).
  238. ;;; They could be easily implemented as objects.  The implementation in this
  239. ;;; file is (supposedly) faster.
  240. ;;;
  241.  
  242. (define primop-syntax-table
  243.   (make-syntax-table (env-syntax-table t-implementation-env)
  244.                      'primop-syntax-table))
  245.  
  246. (set (env-for-syntax-definition primop-syntax-table) orbit-env)
  247.  
  248. (define (primop->executable primop)
  249.   (primop-code (primop.id primop)
  250.                (primop.formals primop)
  251.                (primop.source primop)))
  252.  
  253. (define (primops->source-code primops)
  254.   (map (lambda (p)
  255.          `(set (table-entry primop-table
  256.                             ',(primop.id p))
  257.                ,(primop->executable p)))
  258.        primops))
  259.  
  260. (define (primop-executables->source-code names sources)
  261.   (map (lambda (name source)
  262.          `(set (table-entry primop-table ',name) ,source))
  263.        names
  264.        sources))
  265.  
  266. (define (orbit-primop-compile source env)
  267.   (bind ((*noise-flag* nil)
  268.          (*debug-flag* nil)
  269.          (*noise+error*    (error-output))
  270.          (*noise+terminal* null-port)
  271.          (*noise-stream*   null-port))
  272.     (receive (comex supex)
  273.              (compile `(,syntax/lambda () . ,source)
  274.                       standard-early-binding-env
  275.                       (env-syntax-table env)
  276.                       (->filename 'primop)
  277.                       '(primop))
  278.       (ignore supex)
  279.       comex)))
  280.  
  281. ;;; Useful mask
  282.  
  283. (define constructed-mask
  284.   (table-entry primop-predicate-table 'primop.constructed?))
  285.  
  286. (define (primop-code name formals clauses)
  287.   (receive (bitv fields methods)
  288.            (parse-primop-clauses (if formals (car clauses) clauses))
  289.     `(make-primop ',name
  290.                   ,bitv
  291.                   ',formals
  292.                   (object '#f
  293.                     ,@(if formals
  294.                           `(((%primop-constructor %%handler self) 
  295.                              ,(make-primop-constructor formals
  296.                                                        (cdr clauses))))
  297.                           '())
  298.                     . ,methods)
  299.                   . ,fields)))
  300.  
  301. (define (make-primop name bitv formals handler . fields)
  302.   (let ((p (make-%primop)))
  303.     (set (%primop-id          p) name)
  304.     (set (%primop-bitv        p) bitv)
  305.     (set (%primop-formals     p) formals)
  306.     (set (%primop-handler     p) handler)
  307.     (iterate loop ((fields fields))
  308.       (cond (fields
  309.              (set ((car fields) p) (cadr fields))
  310.              (loop (cddr fields)))))
  311.     p))
  312.  
  313. (define (parse-primop-clauses clauses)
  314.   (iterate loop ((to-do clauses) (fields '()) (methods '()) (bitv 0))
  315.     (destructure ((((name . args) . body) (car to-do)))
  316.       (cond ((null? to-do)
  317.              (return bitv fields methods))
  318.             ((table-entry primop-predicate-table name)
  319.              => (lambda (mask)
  320.                   (loop (cdr to-do) fields methods (fixnum-logior bitv mask))))
  321.             ((table-entry primop-field-table name)
  322.              => (lambda (field)
  323.                   (loop (cdr to-do)          ;; Could do args checking
  324.                         `(,field
  325.                           (lambda ,args ,(make-ignorable args) . ,body)
  326.                           . ,fields)
  327.                         methods
  328.                         bitv)))
  329.             ((table-entry primop-operation-table name)
  330.              => (lambda (operation)
  331.                   (loop (cdr to-do)
  332.                         fields
  333.                         `(((,operation %%handler . ,args)
  334.                            ,(make-ignorable args) . ,body) . ,methods)
  335.                         bitv)))
  336.             (else
  337.              (bug "unknown primop operation in ~S" (car to-do)))))))
  338.  
  339. (define (make-ignorable vars)
  340.   (iterate loop ((vars vars) (res '()))
  341.     (cond ((null? vars)
  342.            `(ignorable . ,res))
  343.           ((atom? vars)
  344.            `(ignorable ,vars . ,res))
  345.           (else
  346.            (loop (cdr vars) (cons (car vars) res))))))
  347.  
  348. (define (make-primop-constructor formals clauses)
  349.   (receive (c-bitv c-fields c-methods)
  350.            (parse-primop-clauses clauses)
  351.     (let ((bitv (fixnum-logior c-bitv constructed-mask)))
  352.       `(lambda ,formals
  353.          (sub-primop-constructor ,bitv 
  354.                                  (object '#f
  355.                                    ((%primop-arglist %%handler self)
  356.                                     (list . ,formals))
  357.                                    . ,c-methods)
  358.                                  . ,c-fields)))))
  359.  
  360. (define (sub-primop-constructor bitv handler . fields)
  361.   (lambda (parent)
  362.     (let ((p (copy-structure parent)))
  363.       (set (%primop-bitv    p) (fixnum-logior bitv (%primop-bitv parent)))
  364.       (set (%primop-handler p) (join handler (%primop-handler parent)))
  365.       (iterate loop ((fields fields))
  366.         (cond (fields
  367.                (set ((car fields) p) (cadr fields))
  368.                (loop (cddr fields)))))
  369.       p)))
  370.  
  371.  
  372.  
  373.