This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

RFC: additions to the machine-definition language


Hi!

I was looking for some bugs in a machine definition & associated files
and  it occured to me that a lot of the #define gobbledygook needed to
described a processor could be moved to the .md file and be made
smaller and cleaner in the process. 

So I did a proof-of-concept implementation of this in emacs-lisp. 
(Why? Because it's really easy to do, and everybody 
has emacs, and I was bored... :) 

The implemented features are: 

(define-register "REGNAME")
(define-register-class (REGISTER_LIST))
(define-pic-offset-table-reg "REGNAME")
(define-arg-pointer-reg "REGNAME")
(define-frame-pointer-reg "REGNAME")
(define-fixed-registers "REGNAME")
(define-call-used-registers "REGNAME")
(define-reg-alloc-order REGISTER_LIST OR REG_CLASS_LIST)
(define-leaf-reg-alloc-order REGISTER_LIST OR REG_CLASS_LIST)

The current implementation will output the following: 

#define REGISTER_NAMES ...
#define FIRST_PSEUDO_REGISTER ... 
#define FRAME_POINTER_REGNUM ...
#define ARG_POINTER_REGNUM ... 
#define PIC_OFFSET_TABLE_REGNUM ... 
enum regclass ... 
#define N_REG_CLASSES ... 
#define REG_CLASS_NAMES ... 
#define REG_CLASS_CONTENTS ... 
#define FIXED_REGISTERS ... 
#define CALL_USED_REGISTERS ... 
#define REG_ALLOC_ORDER  ...
#define REG_LEAF_ALLOC_ORDER ...

The main advantage is that it's a lot easier and less error prone to
define these things in the .md file that to

To try it, save the attachments as def-reg.el (the actual
implementation) and sparc.el (shows how to use it for the SPARC
processor)

and in emacs do:

M-x load-file RET def-reg.el RET
M-x load-file RET sparc.el RET

Create an empty buffer and do:

M-x dr-output RET

What do you think?  
Please ignore that the syntax is not always orthogonal, this was done
having minimum effort as a priorty (besides it's easily fixable). The
current elisp code is intended as a fast prototyping tool and as a
proof-of-concept to have all the warts figured out before actually
doing a C implementation. 

Is this worthwile pursuing?  Comments, ideas are always welcome. 

--dan 


;;; Package for prototyping enhancements for GCC's .md files
;;; Author: Dan Nicolaescu <dann@ics.uci.edu>
;;;  
;;; The goal of this is to get rid of a lot of preprocessor
;;; gobbledygook from the machine definition header files and put
;;; something more intelligible in the .md files, where it belongs.
;;; 
;;;
;;; Implemented features: (see sparc.el for usage examples)
;;;   define-register
;;;   define-register-class
;;;   define-pic-offset-table-reg
;;;   define-arg-pointer-reg
;;;   define-frame-pointer-reg
;;;   define-fixed-registers
;;;   define-call-used-registers
;;;   define-reg-alloc-order
;;;   define-leaf-reg-alloc-order
;;; TODO:
;;;  eazy:
;;;   - allow conditionals in `define-fixed-registers' and 
;;;      `define-call-used-registers' to be able to generate 
;;;       "CONDITIONAL_REGISTER_USAGE" 
;;;   - make `define-register-class' also take register classes as
;;;     parameters, not only registers
;;;   - define data the type sizes 
;;;  harder:
;;;   - there should be a way to define addressing modes
;;;   - translate the whole thing to C? -- bleah
;;;   - other suggestions and help are welcome
 
(require 'cl)

;; Emacsen befor 21.x don't have mapc
(unless (fboundp 'mapc) (fset 'mapc 'mapcar))

(defvar dr-regset nil)
(defvar dr-regset-const-name nil)
(defvar dr-regnum 0)
(defvar dr-regclassset nil)
(defvar dr-fixed-registers nil)
(defvar dr-call-used-registers nil)
(defvar dr-reg-alloc-order nil)
(defvar dr-leaf-reg-alloc-order nil)
(defvar dr-frame-pointer-reg nil)
(defvar dr-arg-pointer-reg nil)
(defvar dr-pic-offset-table-reg nil)

(defun define-register (regname &optional const-name)
  (setq dr-regset (push (cons regname dr-regnum) dr-regset))
  (when const-name
    (setq dr-regset-const-name 
	  (push (cons const-name dr-regnum) dr-regset-const-name)))
  (setq dr-regnum (1+ dr-regnum)))

(defmacro define-registers (rlist)
  `(mapc 'define-register  (list ,@rlist)))

(defmacro define-register-class (classname letter reglist)
  `(setq dr-regclassset 
	 (push 
	  (list ,classname ,letter 
		(list ,@reglist)) 
	  dr-regclassset)))


(defmacro dr-add-to-list (lst &rest reg-or-class-lst)
  `(mapc 
    (lambda (elem) 
      (if (listp elem)
	  ;; it's a regclass
	  (setq ,lst
		(append 
		 (reverse
		  (mapcar (lambda (cls-lst-elem)
			    (cdr (assoc cls-lst-elem dr-regset)))
			  (caddr (assoc (cadr elem) dr-regclassset)))) 
		 ,lst))
	;; it's a register
	(setq ,lst
	      (push (cdr (assoc elem dr-regset)) 
		    ,lst))))
    (list ,@reg-or-class-lst)))


(defmacro define-fixed-registers (&rest reg-or-class-list)
  `(dr-add-to-list dr-fixed-registers ,@reg-or-class-list))
  
(defmacro define-call-used-registers (&rest reg-or-class-list)
  `(dr-add-to-list dr-call-used-registers ,@reg-or-class-list))

(defmacro define-reg-alloc-order (&rest reg-or-class-list)
  `(dr-add-to-list dr-reg-alloc-order ,@reg-or-class-list))

(defmacro define-leaf-reg-alloc-order (&rest reg-or-class-list)
  `(dr-add-to-list dr-leaf-reg-alloc-order ,@reg-or-class-list))
  

(defmacro define-frame-pointer-reg (regname)
  (setq dr-frame-pointer-reg regname))

(defmacro define-arg-pointer-reg (regname)
  (setq dr-arg-pointer-reg regname))

(defmacro define-pic-offset-table-reg (regname)
  (setq dr-pic-offset-table-reg regname))



(defun dr-reset-internal-vars ()
  (interactive)
  (setq dr-regclassset nil)
  (setq dr-regset-const-name nil)
  (setq dr-regset nil)
  (setq dr-regnum 0)
  (setq dr-fixed-registers nil)
  (setq dr-call-used-registers nil)
  (setq dr-leaf-reg-alloc-order nil)
  (setq dr-reg-alloc-order nil)
  (setq dr-frame-pointer-reg nil)
  (setq dr-arg-pointer-reg nil)
  (setq dr-pic-offset-table-reg nil))



(defun dr-output ()
  (interactive)
  (dr-output-regset-const-name (current-buffer))
  (dr-output-reg-names (current-buffer))
  (dr-output-first-pseudo (current-buffer))

  (dr-output-frame-pointer-reg (current-buffer))
  (dr-output-arg-pointer-reg (current-buffer))
  (dr-output-pic-offset-table-reg (current-buffer))

  (dr-output-regclass-enum (current-buffer))
  (dr-output-n-regclasses (current-buffer))
  (dr-output-regclass-names (current-buffer))
  (dr-output-regclass-contents (current-buffer))
  (dr-output-fixed-registers (current-buffer))
  (dr-output-call-used-registers (current-buffer))
  (dr-output-reg-alloc-order (current-buffer))
  (dr-output-leaf-reg-alloc-order (current-buffer)))

(defun dr-output-regset-const-name (buff)
  (with-current-buffer buff
    (insert "\n")
    (mapc (lambda (elem) (insert 
			  (format "#define %s %d\n" 
				  (car elem) (cdr elem)))) 
	  (reverse dr-regset-const-name))
    (insert "\n")))

(defun dr-output-reg-names (buff)
  (with-current-buffer buff
    (insert "#define REGISTER_NAMES \\\n{")
    (mapc (lambda (elem) (insert (format "\"%s\", " (car elem))))
	    (reverse dr-regset))
    ;; delete the last space and comma
    (delete-backward-char 2) 
    (insert "}\n")))

(defun dr-output-regclass-enum (buff)
  (with-current-buffer buff
    (insert "\nenum regclass { NO_REGS, ")
    (mapc (lambda (elem) (insert (format "%s, " (car elem))))
	    (reverse dr-regclassset))
    (insert "ALL_REGS };\n")))

(defun dr-output-regclass-names (buff)
  (with-current-buffer buff
    (insert "\n#define REG_CLASS_NAMES  { \"NO_REGS\", \\\n")
    (mapc (lambda (elem) (insert (format "\"%s\", " (car elem))))
	    (reverse dr-regclassset))
    (insert "\\\n\"ALL_REGS\" }\n")))

(defun dr-output-n-regclasses (buff)
  (with-current-buffer buff
    (insert (format "\n#define N_REG_CLASSES  %d\n" 
		    (+ 2 (length dr-regclassset))))))

(defun dr-output-first-pseudo (buff)
  (with-current-buffer buff
    (insert (format "\n#define FIRST_PSEUDO_REGISTER  %d\n" 
		    dr-regnum))))

(defmacro dr-output-1-if-in-list (lst)
  `(dotimes (cnt dr-regnum)
	   (if (member cnt ,lst)
	       (insert "1, ")
	     (insert "0, "))))

(defun dr-output-fixed-registers (buff)
  (with-current-buffer buff
    (insert "\n#define FIXED_REGISTERS  \\\n{")
    (dr-output-1-if-in-list dr-fixed-registers)
    ;; delete the last space and comma
    (delete-backward-char 2) 
    (insert "}\n")))

(defun dr-output-call-used-registers (buff)
  (with-current-buffer buff
    (insert "\n#define CALL_USED_REGISTERS  \\\n{")
    (dr-output-1-if-in-list dr-call-used-registers)
    ;; delete the last space and comma
    (delete-backward-char 2) 
    (insert "}\n")))

(defun dr-output-reg-alloc-order (buff)
  (with-current-buffer buff
    (insert "\n#define REG_ALLOC_ORDER  \\\n{")
    (mapc (lambda (elem) 
	    (insert (format "%d, " elem))) 
	  (reverse dr-reg-alloc-order))
    ;; delete the last space and comma
    (delete-backward-char 2) 
    (insert "}\n")))

(defun dr-output-leaf-reg-alloc-order (buff)
  (with-current-buffer buff
    (insert "\n#define REG_LEAF_ALLOC_ORDER  \\\n{")
    (mapc (lambda (elem) 
	    (insert (format "%d, " elem))) 
	  (reverse dr-leaf-reg-alloc-order))
    ;; delete the last space and comma
    (delete-backward-char 2) 
    (insert "}\n")))

(defun dr-output-one-regclass (regclasslist)
  (insert (format "{/*%s*/ " (car regclasslist)))
  (let ((num 0)
	;; construct the register list as numbers
	(rlist (mapcar (lambda (elem)
			 (cdr (assoc elem dr-regset)))
		       (caddr regclasslist))))
    (dotimes (i words)
      ;; emacs' integers are 28 bits, so we go 16 bits at a time
      (setq num 0)
      (insert "0x")
      (dotimes (j 16) 
	(when (member (+ (* i 32) j 16) rlist)
	  (setq num (logior num (lsh 1 j)))))
      (insert (format "%x" num))
      (setq num 0)
      (dotimes (j 16) 
	(when (member (+ (* i 32) j) rlist)
	  (setq num (logior num (lsh 1 j)))))
      (insert (format "%x" num))
      (insert ", ")))
    (delete-backward-char 2)
    (insert "}, \\\n"))

(defun dr-output-regclass-contents (buff)
  (with-current-buffer buff
    (insert "\n#define REG_CLASS_CONTENTS  {\\\n")
    ;; we need words words for the representation
    (let ((words (1+ (/ dr-regnum 32))))
      (dr-output-one-regclass (list "NOREGS" "N" '()))
      (mapc 'dr-output-one-regclass 
	     (reverse dr-regclassset))
      (dr-output-one-regclass (list "ALL_REGS" "A" 
				    (reverse (mapcar 'car dr-regset)))))
    (delete-backward-char 4)
    (insert "}\n")))
  
(defun dr-output-frame-pointer-reg (buff)
  (with-current-buffer buff
    (insert (format "\n#define FRAME_POINTER_REGNUM %d\n" 
		    (cdr (assoc dr-frame-pointer-reg dr-regset))))))

(defun dr-output-arg-pointer-reg (buff)
  (with-current-buffer buff
    (insert (format "\n#define ARG_POINTER_REGNUM %d\n" 
		    (cdr (assoc dr-arg-pointer-reg dr-regset))))))

(defun dr-output-pic-offset-table-reg (buff)
  (with-current-buffer buff
    (insert (format "\n#define PIC_OFFSET_TABLE_REGNUM %d\n" 
		    (cdr (assoc dr-pic-offset-table-reg dr-regset))))))

(provide 'def-reg)
(require 'def-reg)
(dr-reset-internal-vars)

(define-registers ("%g0" "%g1" "%g2" "%g3" "%g4" "%g5" "%g6" "%g7"))
(define-registers ("%o0" "%o1" "%o2" "%o3" "%o4" "%o5"))
(define-register "%sp" "STACK_POINTER") ;; this one also generates a
					;; #define STACK_POINTER
					;; register_number
(define-register "%o7")
(define-registers ("%l0" "%l1" "%l2" "%l3" "%l4" "%l5" "%l6" "%l7"))
(define-registers ("%i0" "%i1" "%i2" "%i3" "%i4" "%i5"))
(define-register "%fp" "FRAME_POINTER")
(define-register "%i7")
(define-registers ("%f0" "%f1" "%f2" "%f3" "%f4" "%f5" "%f6" "%f7"))
(define-registers ("%f8" "%f9" "%f10" "%f11" "%f12" "%f13" "%f14" "%f15"))
(define-registers ("%f16" "%f17" "%f18" "%f19" "%f20" "%f21" "%f22" "%f23"))
(define-registers ("%f24" "%f25" "%f26" "%f27" "%f28" "%f29" "%f30" "%f31"))
(define-registers ("%f32" "%f33" "%f34" "%f35" "%f36" "%f37" "%f38" "%f39"))
(define-registers ("%f40" "%f41" "%f42" "%f43" "%f44" "%f45" "%f46" "%f47"))
(define-registers ("%f48" "%f49" "%f50" "%f51" "%f52" "%f53" "%f54" "%f55"))
(define-registers ("%f56" "%f57" "%f58" "%f59" "%f60" "%f61" "%f62" "%f63"))
(define-registers ("%fcc0" "%fcc1" "%fcc2" "%fcc3"))
(define-register "%icc")

(define-pic-offset-table-reg "%l7")
(define-arg-pointer-reg "%fp")
(define-frame-pointer-reg "%fp")

(define-register-class "FPCC_REGS" "c" ("%fcc0" "%fcc1" "%fcc2" "%fcc3"))

(define-register-class  "I64_REGS" "h" 
  ("%l0" "%l1" "%l2" "%l3" "%l4" "%l5" "%l6" "%l7"
   "%i0" "%i1" "%i2" "%i3" "%i4" "%i5" "%fp" "%i7"))

(define-register-class  "GENERAL_REGS" "r"
  ("%g0" "%g1" "%g2" "%g3" "%g4" "%g5" "%g6" "%g7"
   "%o0" "%o1" "%o2" "%o3" "%o4" "%o5" "%sp" "%o7"
   "%l0" "%l1" "%l2" "%l3" "%l4" "%l5" "%l6" "%l7"
   "%i0" "%i1" "%i2" "%i3" "%i4" "%i5" "%fp" "%i7"))

(define-register-class  "FP_REGS" "f"
  ("%f0" "%f1" "%f2" "%f3" "%f4" "%f5" "%f6" "%f7"
   "%f8" "%f9" "%f10" "%f11" "%f12" "%f13" "%f14" "%f15"
   "%f16" "%f17" "%f18" "%f19" "%f20" "%f21" "%f22" "%f23"
   "%f24" "%f25" "%f26" "%f27" "%f28" "%f29" "%f30" "%f31"))

(define-register-class  "EXTRA_FP_REGS" "e"
  ("%f0" "%f1" "%f2" "%f3" "%f4" "%f5" "%f6" "%f7"
   "%f8" "%f9" "%f10" "%f11" "%f12" "%f13" "%f14" "%f15"
   "%f16" "%f17" "%f18" "%f19" "%f20" "%f21" "%f22" "%f23"
   "%f24" "%f25" "%f26" "%f27" "%f28" "%f29" "%f30" "%f31"
   "%f32" "%f33" "%f34" "%f35" "%f36" "%f37" "%f38" "%f39"
   "%f40" "%f41" "%f42" "%f43" "%f44" "%f45" "%f46" "%f47"
   "%f48" "%f49" "%f50" "%f51" "%f52" "%f53" "%f54" "%f55"
   "%f56" "%f57" "%f58" "%f59" "%f60" "%f61" "%f62" "%f63"))

;; the letter  is wrong
(define-register-class  "GENERAL_OR_FP_REGS" "g"
  ("%g0" "%g1" "%g2" "%g3" "%g4" "%g5" "%g6" "%g7"
   "%o0" "%o1" "%o2" "%o3" "%o4" "%o5" "%sp" "%o7"
   "%l0" "%l1" "%l2" "%l3" "%l4" "%l5" "%l6" "%l7"
   "%i0" "%i1" "%i2" "%i3" "%i4" "%i5" "%fp" "%i7"
   "%f0" "%f1" "%f2" "%f3" "%f4" "%f5" "%f6" "%f7"
   "%f8" "%f9" "%f10" "%f11" "%f12" "%f13" "%f14" "%f15"
   "%f16" "%f17" "%f18" "%f19" "%f20" "%f21" "%f22" "%f23"
   "%f24" "%f25" "%f26" "%f27" "%f28" "%f29" "%f30" "%f31"))

;; the letter  is wrong
(define-register-class  "GENERAL_OR_EXTRA_FP_REGS" "b"
  ("%g0" "%g1" "%g2" "%g3" "%g4" "%g5" "%g6" "%g7"
   "%o0" "%o1" "%o2" "%o3" "%o4" "%o5" "%sp" "%o7"
   "%l0" "%l1" "%l2" "%l3" "%l4" "%l5" "%l6" "%l7"
   "%i0" "%i1" "%i2" "%i3" "%i4" "%i5" "%fp" "%i7"
   "%f0" "%f1" "%f2" "%f3" "%f4" "%f5" "%f6" "%f7"
   "%f8" "%f9" "%f10" "%f11" "%f12" "%f13" "%f14" "%f15"
   "%f16" "%f17" "%f18" "%f19" "%f20" "%f21" "%f22" "%f23"
   "%f24" "%f25" "%f26" "%f27" "%f28" "%f29" "%f30" "%f31"
   "%f32" "%f33" "%f34" "%f35" "%f36" "%f37" "%f38" "%f39"
   "%f40" "%f41" "%f42" "%f43" "%f44" "%f45" "%f46" "%f47"
   "%f48" "%f49" "%f50" "%f51" "%f52" "%f53" "%f54" "%f55"
   "%f56" "%f57" "%f58" "%f59" "%f60" "%f61" "%f62" "%f63"))

(define-fixed-registers "%g0" "%g2" "%g3" "%g4" "%g5" "%g6" "%g7")
  
(define-call-used-registers 
  "%g0" "%g1" "%g2" "%g3" "%g4" "%g5" "%g6" "%g7"
  "%o0" "%o1" "%o2" "%o3" "%o4" "%o5" "%sp" "%o7"
  "%fp" "%i7"
  '(regclass "EXTRA_FP_REGS")
  '(regclass "FPCC_REGS")
  "%icc")

(define-reg-alloc-order 
  "%o0" "%o1" "%o2" "%o3" "%o4" "%o5" "%g2" "%g3"
  '(regclass "I64_REGS")
  "%f2" "%f3" "%f4" "%f5" "%f6" "%f7"
  "%f8" "%f9" "%f10" "%f11" "%f12" "%f13" "%f14" "%f15"
  "%f16" "%f17" "%f18" "%f19" "%f20" "%f21" "%f22" "%f23"
  "%f24" "%f25" "%f26" "%f27" "%f28" "%f29" "%f30" "%f31"
  "%f32" "%f33" "%f34" "%f35" "%f36" "%f37" "%f38" "%f39"
  "%f40" "%f41" "%f42" "%f43" "%f44" "%f45" "%f46" "%f47"
  "%f48" "%f49" "%f50" "%f51" "%f52" "%f53" "%f54" "%f55"
  "%f56" "%f57" "%f58" "%f59" "%f60" "%f61" "%f62" "%f63"
  "%f0" "%f1"
  '(regclass "FPCC_REGS")
  "%icc"
  "%g1" "%g4" "%g5" "%g6" "%g7" "%g0" "%sp" "%fp")

(define-leaf-reg-alloc-order 
  "%g2" "%g3" "%i0" "%i1" "%i2" "%i3" "%i4" "%i5"
  "%g4" "%g5" "%g6" "%g7" "%g1"
  "%o7" "%o0" "%o1" "%o2" "%o3" "%o4" "%o5" 
  "%l0" "%l1" "%l2" "%l3" "%l4" "%l5" "%l6" "%l7"
  "%f2" "%f3" "%f4" "%f5" "%f6" "%f7"
  "%f8" "%f9" "%f10" "%f11" "%f12" "%f13" "%f14" "%f15"
  "%f16" "%f17" "%f18" "%f19" "%f20" "%f21" "%f22" "%f23"
  "%f24" "%f25" "%f26" "%f27" "%f28" "%f29" "%f30" "%f31"
  "%f32" "%f33" "%f34" "%f35" "%f36" "%f37" "%f38" "%f39"
  "%f40" "%f41" "%f42" "%f43" "%f44" "%f45" "%f46" "%f47"
  "%f48" "%f49" "%f50" "%f51" "%f52" "%f53" "%f54" "%f55"
  "%f56" "%f57" "%f58" "%f59" "%f60" "%f61" "%f62" "%f63"
  "%f0" "%f1"
  '(regclass "FPCC_REGS")
  "%icc"
  "%g0" "%sp" "%fp" "%i7")


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]