;;; -*- Mode:Lisp; Package:NC; Readtable:CL; Base:10 -*- ;;; Copyright (c) 1985 Yale University ;;; Authors: N Adams, R Kelsey, D Kranz, J Philbin, J Rees. ;;; This material was developed by the T Project at the Yale University Computer ;;; Science Department. Permission to copy this software, to redistribute it, ;;; and to use it for any purpose is granted, subject to the following restric- ;;; tions and understandings. ;;; 1. Any copy made of this software must include this copyright notice in full. ;;; 2. Users of this software agree to make their best efforts (a) to return ;;; to the T Project at Yale any improvements or extensions that they make, ;;; so that these may be included in future releases; and (b) to inform ;;; the T Project of noteworthy uses of this software. ;;; 3. All materials developed as a consequence of the use of this software ;;; shall duly acknowledge such use, in accordance with the usual standards ;;; of acknowledging credit in academic research. ;;; 4. Yale has made no warrantee or representation that the operation of ;;; this software will be error-free, and Yale is under no obligation to ;;; provide any services, by way of maintenance, update, or otherwise. ;;; 5. In conjunction with products arising from the use of this material, ;;; there shall be no use of the name of the Yale University nor of any ;;; adaptation thereof in any advertising, promotional, or sales literature ;;; without prior written consent from Yale in each case. ;;; (defvar *primop-field-table* (make-table '*primop-field-table*)) (eval-when (compile eval) (defparameter *primop-fields-extra-defs* nil) (defmacro primop-field (name args &body body) (let* ((title (concatenate-symbol 'primop. name)) (field (concatenate-symbol 'xprimop- name)) (keyname (intern name 'keyword)) (primop (car args))) (push `(progn (setf (table-entry *primop-field-table* ',keyname) ',keyname) (defun ,title ,args (funcall (,field ,primop) . ,(cdr args)))) *primop-fields-extra-defs*) `(function (lambda ,(cdr args) . ,(if body body `((bug "~S has no method for ~S" ',primop ',title))))))) (defmacro def-primop-fields () `(progn ,@*primop-fields-extra-defs*)) ) (defstruct (xprimop (:print-function (lambda (struct stream depth) depth (format stream "#{Primop ~s ~o}" (xprimop-name struct) (object-hash struct))))) name bitv arglist ;; Simplification (simplify (primop-field simplify (primop node) nil)) (presimplify (primop-field presimplify (primop node) nil)) ; (integrate? (primop-field integrate? (primop node) ; (and (eq (node-role node) call-proc) ; (primop-type-check primop (node-parent node))))) ;; Code generation (generate (primop-field generate (primop node))) (type (primop-field type (primop node) 'top?)) source handler (arg-specs (primop-field arg-specs (primop) nil)) (rep-wants (primop-field rep-wants (primop) nil)) ) (def-primop-fields) (zl:deff primop? 'xprimop-p) ;;; System internal fields (zl:defsubst primop.name (primop) (xprimop-name primop)) (zl:defsubst primop.arglist (primop) (xprimop-arglist primop)) (zl:defsubst primop.source (primop) (xprimop-source primop)) (defvar *primop-predicate-table* (make-table '*primop-predicate-table*)) (eval-when (compile eval) (defparameter *next-primop-predicate-index* 0)) (defmacro define-primop-predicate (name) (let ((name (concatenate-symbol 'primop. name)) (keyname (intern name 'keyword))) (prog1 `(progn (setf (table-entry *primop-predicate-table* ',keyname) ,*next-primop-predicate-index*) (zl:defsubst ,name (primop) (logbitp ,*next-primop-predicate-index* (xprimop-bitv primop)))) (incf *next-primop-predicate-index*)))) (define-primop-predicate constructed?) (define-primop-predicate support?) (define-primop-predicate location?) (define-primop-predicate side-effects?) (define-primop-predicate handler?) (define-primop-predicate settable?) (define-primop-predicate uses-L-value?) (define-primop-predicate special?) (define-primop-predicate defines-support?) (define-primop-predicate type-predicate?) (define-primop-predicate conditional?) ;;; Non generic, specific to certain types of primops (defvar *primop-operation-table* (make-table '*primop-operation-table*)) (defmacro define-primop-operation (name args &rest default) (let* ((title (concatenate-symbol 'primop. name)) (field (concatenate-symbol 'xprimop- name)) (keyname (intern name 'keyword)) (primop (car args))) `(progn (setf (table-entry *primop-operation-table* ',keyname) ',field) (defun ,title ,args (let ((.method. (table-entry (xprimop-handler ,primop) ',field))) (if .method. (funcall .method. . ,args) . ,(if default default `((error "~S has no method for ~S" ,primop ',title))))))))) ;;; Parameterized primops (define-primop-operation constructor (primop)) (define-primop-operation variant-id (primop) (primop.name primop)) ;;; Creating support (define-primop-operation support-variant (primop)) ;;; Locations (define-primop-operation location-specs (primop) nil) (define-primop-operation simplify-setter (self call) nil) (defvar *constructed-bit* (table-entry *primop-predicate-table* 'primop.constructed?)) ;;; BUG: Parameterized primops cannot produce parameterized primops ;;; BUG: Parameterized primops cannot be N-ary (defun primop-code (name arglist new? clauses) (multiple-value-bind (bitv fields methods) (parse-primop-clauses clauses) `(make-xprimop :name ',name :bitv ,bitv :arglist ',arglist :source ',(if new? clauses nil) :handler (let ((handler-table (make-table))) ,@(mapc #'(lambda (meth) `(setf (table-entry handler-table ',(car meth)) ,(cdr meth))) methods) handler-table) . ,fields))) (defmacro set-bit (index word) `(dpb 1 (byte 1 ,index) ,word)) (defun parse-primop-clauses (clauses) (do ((to-do clauses (cdr to-do)) (fields '()) (methods '()) (bitv 0)) ((null to-do) (values bitv fields methods)) (let* ((clause (car to-do)) (name (car clause)) (bit (table-entry *primop-predicate-table* name))) (if (and bit (cadr clause)) (setq bitv (set-bit bit bitv)) (let ((args (cadr clause)) (body (cddr clause)) (field (table-entry *primop-field-table* name))) (if field ;; Could do args checking (setq fields (list* field `(function (lambda ,args . ,body)) fields)) (let ((operation (table-entry *primop-operation-table* name))) (if operation (push `(,operation . (function (lambda ,args . ,body))) methods) (bug "unkown primop operation ~S in ~S" name (car to-do)))))))))) #|||||||| (define (make-primop-constructor name formals clauses) (receive (c-bitv c-fields c-methods) (parse-primop-clauses clauses) (let ((bitv (set-bit *constructed-bit* c-bitv))) `(lambda ,formals (sub-primop-constructor ',name ,bitv (object nil ((xprimop-arglist %%handler self) (list . ,formals)) . ,c-methods) . ,c-fields))))) (define (sub-primop-constructor name bitv handler . fields) (lambda (parent) (let ((p (copy-structure parent))) (set (xprimop-id p) name) (set (xprimop-bitv p) (fixnum-logior bitv (xprimop-bitv parent))) (set (xprimop-handler p) (join handler (xprimop-handler parent))) (iterate loop ((fields fields)) (cond (fields (set ((car fields) p) (cadr fields)) (loop (cddr fields))))) p))) (define *constructed-primops* (create-%table '*constructed-primops* 0 t list? (lambda (l) (fixnum-abs (fx+ (descriptor-hash (car l)) (fx* (tree-hash (cdr l)) 2)))) alikev?)) (define (construct-primop base args) (let ((key (cons base args))) (cond ((table-entry *constructed-primops* key) => identity) (else (let ((new ((apply (primop.constructor base) args) base))) (set (table-entry *constructed-primops* key) new) new))))) |||||# (defvar *primop-table* (make-table)) (defmacro define-primop (name arglist &body clauses) (let ((vname (intern (format nil "PRIMOP/~s" name)))) `(progn (defun ,vname () ,(primop-code name arglist t clauses)) (defconstant ,vname (,vname)) (setf (table-entry *primop-table* ',name) ,vname) ;; for C-Sh-A (setf (get ',name 'si:arglist) ',arglist))))