node.scm 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. ;;; Ported from Scheme 48 1.9. See file COPYING for notices and license.
  2. ;;;
  3. ;;; Port Author: Andrew Whatson
  4. ;;;
  5. ;;; Original Authors: Richard Kelsey
  6. ;;;
  7. ;;; scheme48-1.9.2/ps-compiler/node/node.scm
  8. ;;;
  9. ;;; This file contains the definitions of the node tree data structure.
  10. (define-module (ps-compiler node node)
  11. #:use-module (prescheme scheme48)
  12. #:use-module (prescheme s48-defrecord)
  13. #:use-module (prescheme record-discloser)
  14. #:use-module (prescheme syntax-utils)
  15. #:use-module (ps-compiler node primop)
  16. #:use-module (ps-compiler node variable)
  17. #:use-module (ps-compiler util syntax)
  18. #:use-module (ps-compiler util util)
  19. #:export (node? node-variant
  20. node-parent set-node-parent!
  21. node-index set-node-index!
  22. node-simplified? set-node-simplified?!
  23. node-flag set-node-flag!
  24. empty empty? proclaim-empty
  25. erase
  26. detach detach-body
  27. attach attach-body
  28. move move-body
  29. insert-body
  30. replace replace-body
  31. connect-sequence
  32. mark-changed
  33. leaf-node?
  34. literal-node? make-literal-node
  35. literal-value set-literal-value!
  36. literal-type set-literal-type!
  37. copy-literal-node
  38. reference-node? make-reference-node
  39. reference-variable set-reference-variable!
  40. call-node? make-call-node
  41. call-primop set-call-primop!
  42. call-args set-call-args!
  43. call-exits set-call-exits!
  44. call-source set-call-source!
  45. call-arg call-arg-count
  46. lambda-node? make-lambda-node
  47. lambda-body set-lambda-body!
  48. lambda-variables set-lambda-variables!
  49. lambda-name set-lambda-name!
  50. lambda-id
  51. lambda-type
  52. lambda-block set-lambda-block!
  53. lambda-env set-lambda-env!
  54. lambda-protocol set-lambda-protocol!
  55. lambda-source set-lambda-source!
  56. lambda-variable-count
  57. calls-known? set-calls-known?!
  58. proc-lambda?
  59. initialize-lambdas add-lambda add-lambdas
  60. change-lambda-type
  61. walk-lambdas make-lambda-list))
  62. ;;----------------------------------------------------------------------------
  63. ;; The main record for the node tree
  64. (define-record-type node
  65. ((variant) ;; One of LAMBDA, CALL, REFERENCE, LITERAL
  66. )
  67. ((parent empty) ;; Parent node
  68. (index '<free>) ;; Index of this node in parent
  69. (simplified? #f) ;; True if it has already been simplified.
  70. (flag #f) ;; Useful flag, all users must leave this is #F
  71. stuff-0 ;; Variant components - each type of node has a different
  72. stuff-1 ;; use for these fields
  73. stuff-2
  74. stuff-3
  75. ))
  76. (define-record-discloser type/node
  77. (lambda (node)
  78. `(node ,(node-variant node)
  79. . ,(case (node-variant node)
  80. ((lambda)
  81. (node-hash node)
  82. (list (lambda-name node) (lambda-id node)))
  83. ((call)
  84. (list (primop-id (call-primop node))))
  85. ((reference)
  86. (let ((var (reference-variable node)))
  87. (list (variable-name var) (variable-id var))))
  88. ((literal)
  89. (list (literal-value node)))
  90. (else
  91. '())))))
  92. (define make-node node-maker)
  93. ;;--------------------------------------------------------------------------
  94. ;; EMPTY is used to mark empty parent and child slots in nodes.
  95. (define empty
  96. (list 'empty))
  97. (define (empty? obj) (eq? obj empty))
  98. (define (proclaim-empty probe)
  99. (cond ((not (empty? probe))
  100. (bug "not empty - ~S" probe))))
  101. ;;----------------------------------------------------------------------------
  102. ;; This walks the tree rooted at NODE and removes all pointers that point into
  103. ;; this tree from outside.
  104. (define (erase node)
  105. (let label ((node node))
  106. (cond ((empty? node)
  107. #f)
  108. (else
  109. (case (node-variant node)
  110. ((lambda)
  111. (label (lambda-body node)))
  112. ((call)
  113. (walk-vector label (call-args node))))
  114. (really-erase node)))))
  115. ;; This does the following:
  116. ;; Checks that this node has not already been removed from the tree.
  117. ;;
  118. ;; Reference nodes are removed from the refs list of the variable they reference.
  119. ;;
  120. ;; For lambda nodes, the variables are erased, non-CONT lambdas are removed from
  121. ;; the *LAMBDAS* list (CONT lambdas are never on the list).
  122. ;;
  123. ;; Literal nodes whose values have reference lists are removed from those
  124. ;; reference lists.
  125. (define (really-erase node)
  126. (cond ((empty? node)
  127. #f)
  128. (else
  129. (cond ((eq? (node-index node) '<erased>)
  130. (bug "node erased twice ~S" node))
  131. ((reference-node? node)
  132. (let ((var (reference-variable node)))
  133. (set-variable-refs! var
  134. (delq! node (variable-refs var)))))
  135. ((lambda-node? node)
  136. (for-each (lambda (v)
  137. (if v (erase-variable v)))
  138. (lambda-variables node))
  139. (if (neq? (lambda-type node) 'cont)
  140. (delete-lambda node))
  141. (set-lambda-variables! node '())) ;; safety
  142. ((literal-node? node)
  143. (let ((refs (literal-refs node)))
  144. (if refs
  145. (set-literal-reference-list!
  146. refs
  147. (delq! node (literal-reference-list refs)))))))
  148. ;; (erase-type (node-type node))
  149. (set-node-index! node '<erased>))))
  150. ;;---------------------------------------------------------------------------
  151. ;; CONNECTING AND DISCONNECTING NODES
  152. ;;
  153. ;; There are two versions of each of these routines, one for value nodes
  154. ;; (LAMBDA, REFERENCE, or LITERAL), and one for call nodes.
  155. ;; Detach a node from the tree.
  156. (define (detach node)
  157. (vector-set! (call-args (node-parent node))
  158. (node-index node)
  159. empty)
  160. (set-node-index! node #f)
  161. (set-node-parent! node empty)
  162. node)
  163. (define (detach-body node)
  164. (set-lambda-body! (node-parent node) empty)
  165. (set-node-index! node #f)
  166. (set-node-parent! node empty)
  167. node)
  168. ;; Attach a node to the tree.
  169. (define (attach parent index child)
  170. (proclaim-empty (node-parent child))
  171. (proclaim-empty (vector-ref (call-args parent) index))
  172. (vector-set! (call-args parent) index child)
  173. (set-node-parent! child parent)
  174. (set-node-index! child index)
  175. (values))
  176. (define (attach-body parent call)
  177. (proclaim-empty (node-parent call))
  178. (proclaim-empty (lambda-body parent))
  179. (set-lambda-body! parent call)
  180. (set-node-parent! call parent)
  181. (set-node-index! call '-1)
  182. (values))
  183. ;; NODES is an alternating series ... lambda, call, lambda, call, ...
  184. ;; that is connected into a sequence. Each call becomes the body of the
  185. ;; previous lambda and each lambda becomes the (single) exit of the previous
  186. ;; call.
  187. (define (connect-sequence . all-nodes)
  188. (if (not (null? all-nodes))
  189. (let loop ((last (car all-nodes)) (nodes (cdr all-nodes)))
  190. (if (not (null? nodes))
  191. (let ((next (car nodes)))
  192. (cond ((and (lambda-node? last)
  193. (call-node? next))
  194. (attach-body last next))
  195. ((and (call-node? last)
  196. (lambda-node? next)
  197. (= 1 (call-exits last)))
  198. (attach last 0 next))
  199. (else
  200. (bug "bad node sequence ~S" all-nodes)))
  201. (loop next (cdr nodes)))))))
  202. ;; Replace node in tree with value of applying proc to node.
  203. ;; Note the fact that a change has been made at this point in the tree.
  204. (define (move node proc)
  205. (let ((parent (node-parent node))
  206. (index (node-index node)))
  207. (detach node)
  208. (let ((new (proc node)))
  209. (attach parent index new)
  210. (mark-changed new))))
  211. (define (move-body node proc)
  212. (let ((parent (node-parent node)))
  213. (detach-body node)
  214. (let ((new (proc node)))
  215. (attach-body parent new)
  216. (mark-changed new))))
  217. ;; Put CALL into the tree as the body of lambda-node PARENT, making the current
  218. ;; body of PARENT the body of lambda-node CONT.
  219. (define (insert-body call cont parent)
  220. (move-body (lambda-body parent)
  221. (lambda (old-call)
  222. (attach-body cont old-call)
  223. call)))
  224. ;; Replace old-node with new-node, noting that a change has been made at this
  225. ;; point in the tree.
  226. (define (replace old-node new-node)
  227. (let ((index (node-index old-node))
  228. (parent (node-parent old-node)))
  229. (mark-changed old-node)
  230. (erase (detach old-node))
  231. (attach parent index new-node)
  232. (set-node-simplified?! new-node #f)
  233. (values)))
  234. (define (replace-body old-node new-node)
  235. (let ((parent (node-parent old-node)))
  236. (mark-changed old-node)
  237. (erase (detach-body old-node))
  238. (attach-body parent new-node)
  239. (set-node-simplified?! new-node #f)
  240. (values)))
  241. ;; Starting with the parent of NODE, set the SIMPLIFIED? flags of the
  242. ;; ancestors of NODE to be #F.
  243. (define (mark-changed node)
  244. (do ((p (node-parent node) (node-parent p)))
  245. ((or (empty? p)
  246. (not (node-simplified? p))))
  247. (set-node-simplified?! p #f)))
  248. ;;-------------------------------------------------------------------------
  249. ;; Syntax for defining the different types of nodes.
  250. (define-syntax define-node-type
  251. (lambda (x)
  252. (syntax-case x ()
  253. ((_ id slots ...)
  254. (let* ((pred (syntax-conc #'id '-node?))
  255. (slots #'(slots ...))
  256. (indexes (iota (length slots))))
  257. #`(begin
  258. (define (#,pred x)
  259. (eq? 'id (node-variant x)))
  260. #,@(map (lambda (slot i)
  261. (let* ((getter (syntax-conc #'id '- slot))
  262. (number (string->symbol (number->string i)))
  263. (field (datum->syntax slot (symbol-append 'node-stuff- number))))
  264. #`(define-node-field #,getter #,pred #,field)))
  265. slots indexes)))))))
  266. ;; These are used to rename the NODE-STUFF fields of particular node variants.
  267. (define-syntax define-node-field
  268. (lambda (x)
  269. (syntax-case x ()
  270. ((_ getter pred field)
  271. (with-syntax ((setter (syntax-conc 'set- #'getter '!))
  272. (set-field (syntax-conc 'set- #'field '!)))
  273. #'(begin
  274. (define (getter node)
  275. (field (enforce pred node)))
  276. (define (setter node val)
  277. (set-field (enforce pred node) val))))))))
  278. ;;-------------------------------------------------------------------------
  279. ;; literals
  280. (define-node-type literal
  281. value ;; the value
  282. type ;; the type of the value
  283. refs ;; either #F or a literal-reference record; only a few types of literal
  284. ) ;; literal values require reference lists
  285. (define-record-type literal-reference
  286. ()
  287. ((list '()) ;; list of literal nodes that refer to a particular value
  288. ))
  289. (define make-literal-reference-list literal-reference-maker)
  290. (define (make-literal-node value type)
  291. (let ((node (make-node 'literal)))
  292. (set-literal-value! node value)
  293. (set-literal-type! node type)
  294. (set-literal-refs! node #f)
  295. node))
  296. (define (copy-literal-node node)
  297. (let ((new (make-node 'literal))
  298. (refs (literal-refs node)))
  299. (set-literal-value! new (literal-value node))
  300. (set-literal-type! new (literal-type node))
  301. (set-literal-refs! new refs)
  302. (if refs (set-literal-reference-list!
  303. refs
  304. (cons new (literal-reference-list refs))))
  305. new))
  306. (define (make-marked-literal value refs)
  307. (let ((node (make-node 'literal)))
  308. (set-literal-value! node value)
  309. (set-literal-refs! node refs)
  310. (set-literal-reference-list! refs
  311. (cons node (literal-reference-list refs)))
  312. node))
  313. ;;-------------------------------------------------------------------------
  314. ;; These just contain an identifier.
  315. (define-node-type reference
  316. variable
  317. )
  318. (define (make-reference-node variable)
  319. (let ((node (make-node 'reference)))
  320. (set-reference-variable! node variable)
  321. (set-variable-refs! variable (cons node (variable-refs variable)))
  322. node))
  323. ;; Literal and reference nodes are leaf nodes as they do not contain any other
  324. ;; nodes.
  325. (define (leaf-node? n)
  326. (or (literal-node? n)
  327. (reference-node? n)))
  328. ;;--------------------------------------------------------------------------
  329. ;; Call nodes
  330. (define-node-type call
  331. primop ;; the primitive being called
  332. args ;; vector of child nodes
  333. exits ;; the number of arguments that are continuations
  334. source ;; source info
  335. )
  336. ;; Create a call node with primop P, N children and EXITS exits.
  337. (define (make-call-node primop n exits)
  338. (let ((node (make-node 'call)))
  339. (set-call-primop! node primop)
  340. (set-call-args! node (make-vector n empty))
  341. (set-call-exits! node exits)
  342. (set-call-source! node #f)
  343. node))
  344. (define (call-arg call index)
  345. (vector-ref (call-args call) index))
  346. (define (call-arg-count call)
  347. (vector-length (call-args call)))
  348. ;;----------------------------------------------------------------------------
  349. ;; LAMBDA NODES
  350. (define-node-type lambda
  351. body ;; the call-node that is the body of the lambda
  352. variables ;; a list of variable records with #Fs for ignored positions
  353. source ;; source code for the lambda (if any)
  354. data ;; a LAMBDA-DATA record (lambdas have more associated data than
  355. ) ;; the other node types.)
  356. (define-subrecord lambda lambda-data lambda-data
  357. ((name) ;; symbol (for debugging only)
  358. id ;; unique integer (for debugging only)
  359. (type)) ;; PROC, KNOWN-PROC, CONT, or JUMP (maybe ESCAPE at some point)
  360. ((block #f) ;; either a basic-block (for flow analysis) or a code-block
  361. ;; (for code generation).
  362. (env #f) ;; a record containing lexical environment data
  363. (protocol #f) ;; calling protocol from the source language
  364. (prev #f) ;; previous node on *LAMBDAS* list
  365. (next #f) ;; next node on *LAMBDAS* list
  366. ))
  367. ;; Doubly linked list of all non-CONT lambdas
  368. (define *lambdas* #f)
  369. (define (initialize-lambdas)
  370. (set! *lambdas* (make-lambda-node '*lambdas* 'cont '()))
  371. (link-lambdas *lambdas* *lambdas*))
  372. (define (link-lambdas node1 node2)
  373. (set-lambda-prev! node2 node1)
  374. (set-lambda-next! node1 node2))
  375. (define (add-lambda node)
  376. (let ((next (lambda-next *lambdas*)))
  377. (link-lambdas *lambdas* node)
  378. (link-lambdas node next)))
  379. (define (delete-lambda node)
  380. (link-lambdas (lambda-prev node) (lambda-next node))
  381. (set-lambda-prev! node #f)
  382. (set-lambda-next! node #f))
  383. (define (walk-lambdas proc)
  384. (do ((n (lambda-next *lambdas*) (lambda-next n)))
  385. ((eq? n *lambdas*))
  386. (proc n))
  387. (values))
  388. (define (make-lambda-list)
  389. (do ((n (lambda-next *lambdas*) (lambda-next n))
  390. (l '() (cons n l)))
  391. ((eq? n *lambdas*)
  392. l)))
  393. (define (add-lambdas nodes)
  394. (for-each add-lambda nodes))
  395. ;; Create a lambda node. NAME is used as the name of the lambda node's
  396. ;; self variable. VARS is a list of variables. The VARIABLE-BINDER slot
  397. ;; of each variable is set to be the new lambda node.
  398. (define (make-lambda-node name type vars)
  399. (let ((node (make-node 'lambda))
  400. (data (lambda-data-maker name (new-variable-id) type)))
  401. (set-lambda-body! node empty)
  402. (set-lambda-variables! node vars)
  403. (set-lambda-data! node data)
  404. (set-lambda-source! node #f)
  405. (for-each (lambda (var)
  406. (if var (set-variable-binder! var node)))
  407. vars)
  408. (if (neq? type 'cont)
  409. (add-lambda node))
  410. node))
  411. ;; Change the type of lambda-node NODE to be TYPE. This may require adding or
  412. ;; deleting NODE from the list *LAMBDAS*.
  413. (define (change-lambda-type node type)
  414. (let ((has (lambda-type node)))
  415. (cond ((neq? type (lambda-type node))
  416. (set-lambda-type! node type)
  417. (cond ((eq? type 'cont)
  418. (delete-lambda node))
  419. ((eq? has 'cont)
  420. (add-lambda node)))))
  421. (values)))
  422. (define (lambda-variable-count node)
  423. (length (lambda-variables node)))
  424. (define (calls-known? node)
  425. (neq? (lambda-type node) 'proc))
  426. (define (set-calls-known?! node)
  427. (set-lambda-type! node 'known-proc))
  428. (define (proc-lambda? node)
  429. (or (eq? 'proc (lambda-type node))
  430. (eq? 'known-proc (lambda-type node))))