node.scm 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  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. ;;;
  11. ;;;---------------------------------------------------------------------------
  12. ;;; Records to represent variables.
  13. (define-module (ps-compiler node node)
  14. #:use-module (prescheme scheme48)
  15. #:use-module (prescheme s48-defrecord)
  16. #:use-module (prescheme record-discloser)
  17. #:use-module (prescheme syntax-utils)
  18. #:use-module (ps-compiler node primop)
  19. #:use-module (ps-compiler util syntax)
  20. #:use-module (ps-compiler util util)
  21. #:replace (make-variable)
  22. #:export (variable?
  23. global-variable? make-global-variable
  24. variable-name set-variable-name!
  25. variable-id
  26. variable-type set-variable-type!
  27. variable-binder set-variable-binder!
  28. variable-refs set-variable-refs!
  29. variable-flag set-variable-flag!
  30. variable-flags set-variable-flags!
  31. variable-generate set-variable-generate!
  32. erase-variable
  33. variable-index copy-variable used? unused?
  34. variable-flag-accessor variable-flag-setter variable-flag-remover
  35. variable-known-value
  36. add-variable-known-value!
  37. remove-variable-known-value!
  38. variable-simplifier
  39. add-variable-simplifier!
  40. remove-variable-simplifier!
  41. note-known-global-lambda!
  42. variable-known-lambda
  43. reset-node-id node-hash node-unhash
  44. node? node-variant
  45. node-parent set-node-parent!
  46. node-index set-node-index!
  47. node-simplified? set-node-simplified?!
  48. node-flag set-node-flag!
  49. empty empty? proclaim-empty
  50. erase
  51. detach detach-body
  52. attach attach-body
  53. move move-body
  54. insert-body
  55. replace replace-body
  56. connect-sequence
  57. mark-changed
  58. leaf-node?
  59. literal-node? make-literal-node
  60. literal-value set-literal-value!
  61. literal-type set-literal-type!
  62. copy-literal-node
  63. reference-node? make-reference-node
  64. reference-variable set-reference-variable!
  65. call-node? make-call-node
  66. call-primop set-call-primop!
  67. call-args set-call-args!
  68. call-exits set-call-exits!
  69. call-source set-call-source!
  70. call-arg call-arg-count
  71. lambda-node? make-lambda-node
  72. lambda-body set-lambda-body!
  73. lambda-variables set-lambda-variables!
  74. lambda-name set-lambda-name!
  75. lambda-id
  76. lambda-type
  77. lambda-block set-lambda-block!
  78. lambda-env set-lambda-env!
  79. lambda-protocol set-lambda-protocol!
  80. lambda-source set-lambda-source!
  81. lambda-variable-count
  82. calls-known? set-calls-known?!
  83. proc-lambda?
  84. initialize-lambdas add-lambda add-lambdas
  85. change-lambda-type
  86. walk-lambdas make-lambda-list))
  87. (define-record-type variable
  88. ((name) ;; Source code name for variable (used for debugging only)
  89. (id) ;; Unique numeric identifier (used for debugging only)
  90. (type) ;; Type for variable's value
  91. )
  92. (binder ;; LAMBDA node which binds this variable
  93. (refs '()) ;; List of leaf nodes n for which (REFERENCE-VARIABLE n) = var.
  94. (flag #f) ;; Useful slot, used by shapes, COPY-NODE, NODE->VECTOR, etc.
  95. ;; all users must leave this is #F
  96. (flags '()) ;; For various annotations, e.g. IGNORABLE
  97. (generate #f) ;; For whatever code generation wants
  98. ))
  99. (define-record-discloser type/variable
  100. (lambda (var)
  101. (node-hash var)
  102. (list 'variable (variable-name var) (variable-id var))))
  103. (define (make-variable name type)
  104. (variable-maker name (new-id) type))
  105. (define (make-global-variable name type)
  106. (let ((var (make-variable name type)))
  107. (set-variable-binder! var #f)
  108. var))
  109. (define (global-variable? var)
  110. (not (variable-binder var)))
  111. ;; Every variable has a unique numeric identifier that is used for printing.
  112. (define *variable-id* 0)
  113. (define (new-id)
  114. (let ((id *variable-id*))
  115. (set! *variable-id* (+ 1 *variable-id*))
  116. id))
  117. (define (erase-variable var)
  118. (cond ((eq? (variable-id var) '<erased>)
  119. (bug "variable ~S already erased" var))
  120. (else
  121. (set-variable-id! var '<erased>))))
  122. (define *node-hash-table* #f)
  123. (define (reset-node-id)
  124. (set! *variable-id* 0)
  125. (set! *node-hash-table* (make-table)))
  126. (define (node-hash var-or-lambda)
  127. (let ((id (if (variable? var-or-lambda)
  128. (variable-id var-or-lambda)
  129. (lambda-id var-or-lambda))))
  130. (table-set! *node-hash-table* id var-or-lambda)))
  131. (define (node-unhash n)
  132. (table-ref *node-hash-table* n))
  133. ;; The index of VAR in the variables bound by its binder.
  134. (define (variable-index var)
  135. (let ((binder (variable-binder var)))
  136. (if (not binder)
  137. (bug "VARIABLE-INDEX called on global variable ~S" var)
  138. (do ((i 0 (+ i 1))
  139. (vs (lambda-variables binder) (cdr vs)))
  140. ((eq? (car vs) var)
  141. i)))))
  142. ;; Copy an old variable.
  143. (define (copy-variable old)
  144. (let ((var (make-variable (variable-name old) (variable-type old))))
  145. (set-variable-flags! var (variable-flags old))
  146. var))
  147. ;; An unused variable is either #F or a variable with no references.
  148. (define (used? var)
  149. (and var
  150. (not (null? (variable-refs var)))))
  151. (define (unused? var)
  152. (not (used? var)))
  153. ;; known values for top-level variables
  154. (define (variable-flag-accessor flag)
  155. (lambda (var)
  156. (let ((p (flag-assq flag (variable-flags var))))
  157. (if p (cdr p) #f))))
  158. (define (variable-flag-setter flag)
  159. (lambda (var value)
  160. (set-variable-flags! var
  161. (cons (cons flag value)
  162. (variable-flags var)))))
  163. (define (variable-flag-remover flag)
  164. (lambda (var)
  165. (set-variable-flags! var (filter (lambda (x)
  166. (or (not (pair? x))
  167. (not (eq? (car x) flag))))
  168. (variable-flags var)))))
  169. (define variable-known-value (variable-flag-accessor 'known-value))
  170. (define add-variable-known-value! (variable-flag-setter 'known-value))
  171. (define remove-variable-known-value! (variable-flag-remover 'known-value))
  172. (define variable-simplifier (variable-flag-accessor 'simplifier))
  173. (define add-variable-simplifier! (variable-flag-setter 'simplifier))
  174. (define remove-variable-simplifier! (variable-flag-remover 'simplifier))
  175. (define variable-known-lambda (variable-flag-accessor 'known-lambda))
  176. (define note-known-global-lambda! (variable-flag-setter 'known-lambda))
  177. ;;----------------------------------------------------------------------------
  178. ;; The main record for the node tree
  179. (define-record-type node
  180. ((variant) ;; One of LAMBDA, CALL, REFERENCE, LITERAL
  181. )
  182. ((parent empty) ;; Parent node
  183. (index '<free>) ;; Index of this node in parent
  184. (simplified? #f) ;; True if it has already been simplified.
  185. (flag #f) ;; Useful flag, all users must leave this is #F
  186. stuff-0 ;; Variant components - each type of node has a different
  187. stuff-1 ;; use for these fields
  188. stuff-2
  189. stuff-3
  190. ))
  191. (define-record-discloser type/node
  192. (lambda (node)
  193. `(node ,(node-variant node)
  194. . ,(case (node-variant node)
  195. ((lambda)
  196. (node-hash node)
  197. (list (lambda-name node) (lambda-id node)))
  198. ((call)
  199. (list (primop-id (call-primop node))))
  200. ((reference)
  201. (let ((var (reference-variable node)))
  202. (list (variable-name var) (variable-id var))))
  203. ((literal)
  204. (list (literal-value node)))
  205. (else
  206. '())))))
  207. (define make-node node-maker)
  208. ;;--------------------------------------------------------------------------
  209. ;; EMPTY is used to mark empty parent and child slots in nodes.
  210. (define empty
  211. (list 'empty))
  212. (define (empty? obj) (eq? obj empty))
  213. (define (proclaim-empty probe)
  214. (cond ((not (empty? probe))
  215. (bug "not empty - ~S" probe))))
  216. ;;----------------------------------------------------------------------------
  217. ;; This walks the tree rooted at NODE and removes all pointers that point into
  218. ;; this tree from outside.
  219. (define (erase node)
  220. (let label ((node node))
  221. (cond ((empty? node)
  222. #f)
  223. (else
  224. (case (node-variant node)
  225. ((lambda)
  226. (label (lambda-body node)))
  227. ((call)
  228. (walk-vector label (call-args node))))
  229. (really-erase node)))))
  230. ;; This does the following:
  231. ;; Checks that this node has not already been removed from the tree.
  232. ;;
  233. ;; Reference nodes are removed from the refs list of the variable they reference.
  234. ;;
  235. ;; For lambda nodes, the variables are erased, non-CONT lambdas are removed from
  236. ;; the *LAMBDAS* list (CONT lambdas are never on the list).
  237. ;;
  238. ;; Literal nodes whose values have reference lists are removed from those
  239. ;; reference lists.
  240. (define (really-erase node)
  241. (cond ((empty? node)
  242. #f)
  243. (else
  244. (cond ((eq? (node-index node) '<erased>)
  245. (bug "node erased twice ~S" node))
  246. ((reference-node? node)
  247. (let ((var (reference-variable node)))
  248. (set-variable-refs! var
  249. (delq! node (variable-refs var)))))
  250. ((lambda-node? node)
  251. (for-each (lambda (v)
  252. (if v (erase-variable v)))
  253. (lambda-variables node))
  254. (if (neq? (lambda-type node) 'cont)
  255. (delete-lambda node))
  256. (set-lambda-variables! node '())) ;; safety
  257. ((literal-node? node)
  258. (let ((refs (literal-refs node)))
  259. (if refs
  260. (set-literal-reference-list!
  261. refs
  262. (delq! node (literal-reference-list refs)))))))
  263. ;; (erase-type (node-type node))
  264. (set-node-index! node '<erased>))))
  265. ;;---------------------------------------------------------------------------
  266. ;; CONNECTING AND DISCONNECTING NODES
  267. ;;
  268. ;; There are two versions of each of these routines, one for value nodes
  269. ;; (LAMBDA, REFERENCE, or LITERAL), and one for call nodes.
  270. ;; Detach a node from the tree.
  271. (define (detach node)
  272. (vector-set! (call-args (node-parent node))
  273. (node-index node)
  274. empty)
  275. (set-node-index! node #f)
  276. (set-node-parent! node empty)
  277. node)
  278. (define (detach-body node)
  279. (set-lambda-body! (node-parent node) empty)
  280. (set-node-index! node #f)
  281. (set-node-parent! node empty)
  282. node)
  283. ;; Attach a node to the tree.
  284. (define (attach parent index child)
  285. (proclaim-empty (node-parent child))
  286. (proclaim-empty (vector-ref (call-args parent) index))
  287. (vector-set! (call-args parent) index child)
  288. (set-node-parent! child parent)
  289. (set-node-index! child index)
  290. (values))
  291. (define (attach-body parent call)
  292. (proclaim-empty (node-parent call))
  293. (proclaim-empty (lambda-body parent))
  294. (set-lambda-body! parent call)
  295. (set-node-parent! call parent)
  296. (set-node-index! call '-1)
  297. (values))
  298. ;; NODES is an alternating series ... lambda, call, lambda, call, ...
  299. ;; that is connected into a sequence. Each call becomes the body of the
  300. ;; previous lambda and each lambda becomes the (single) exit of the previous
  301. ;; call.
  302. (define (connect-sequence . all-nodes)
  303. (if (not (null? all-nodes))
  304. (let loop ((last (car all-nodes)) (nodes (cdr all-nodes)))
  305. (if (not (null? nodes))
  306. (let ((next (car nodes)))
  307. (cond ((and (lambda-node? last)
  308. (call-node? next))
  309. (attach-body last next))
  310. ((and (call-node? last)
  311. (lambda-node? next)
  312. (= 1 (call-exits last)))
  313. (attach last 0 next))
  314. (else
  315. (bug "bad node sequence ~S" all-nodes)))
  316. (loop next (cdr nodes)))))))
  317. ;; Replace node in tree with value of applying proc to node.
  318. ;; Note the fact that a change has been made at this point in the tree.
  319. (define (move node proc)
  320. (let ((parent (node-parent node))
  321. (index (node-index node)))
  322. (detach node)
  323. (let ((new (proc node)))
  324. (attach parent index new)
  325. (mark-changed new))))
  326. (define (move-body node proc)
  327. (let ((parent (node-parent node)))
  328. (detach-body node)
  329. (let ((new (proc node)))
  330. (attach-body parent new)
  331. (mark-changed new))))
  332. ;; Put CALL into the tree as the body of lambda-node PARENT, making the current
  333. ;; body of PARENT the body of lambda-node CONT.
  334. (define (insert-body call cont parent)
  335. (move-body (lambda-body parent)
  336. (lambda (old-call)
  337. (attach-body cont old-call)
  338. call)))
  339. ;; Replace old-node with new-node, noting that a change has been made at this
  340. ;; point in the tree.
  341. (define (replace old-node new-node)
  342. (let ((index (node-index old-node))
  343. (parent (node-parent old-node)))
  344. (mark-changed old-node)
  345. (erase (detach old-node))
  346. (attach parent index new-node)
  347. (set-node-simplified?! new-node #f)
  348. (values)))
  349. (define (replace-body old-node new-node)
  350. (let ((parent (node-parent old-node)))
  351. (mark-changed old-node)
  352. (erase (detach-body old-node))
  353. (attach-body parent new-node)
  354. (set-node-simplified?! new-node #f)
  355. (values)))
  356. ;; Starting with the parent of NODE, set the SIMPLIFIED? flags of the
  357. ;; ancestors of NODE to be #F.
  358. (define (mark-changed node)
  359. (do ((p (node-parent node) (node-parent p)))
  360. ((or (empty? p)
  361. (not (node-simplified? p))))
  362. (set-node-simplified?! p #f)))
  363. ;;-------------------------------------------------------------------------
  364. ;; Syntax for defining the different types of nodes.
  365. (define-syntax define-node-type
  366. (lambda (x)
  367. (syntax-case x ()
  368. ((_ id slots ...)
  369. (let* ((pred (syntax-conc #'id '-node?))
  370. (slots #'(slots ...))
  371. (indexes (iota (length slots))))
  372. #`(begin
  373. (define (#,pred x)
  374. (eq? 'id (node-variant x)))
  375. #,@(map (lambda (slot i)
  376. (let* ((getter (syntax-conc #'id '- slot))
  377. (number (string->symbol (number->string i)))
  378. (field (datum->syntax slot (symbol-append 'node-stuff- number))))
  379. #`(define-node-field #,getter #,pred #,field)))
  380. slots indexes)))))))
  381. ;; These are used to rename the NODE-STUFF fields of particular node variants.
  382. (define-syntax define-node-field
  383. (lambda (x)
  384. (syntax-case x ()
  385. ((_ getter pred field)
  386. (with-syntax ((setter (syntax-conc 'set- #'getter '!))
  387. (set-field (syntax-conc 'set- #'field '!)))
  388. #'(begin
  389. (define (getter node)
  390. (field (enforce pred node)))
  391. (define (setter node val)
  392. (set-field (enforce pred node) val))))))))
  393. ;;-------------------------------------------------------------------------
  394. ;; literals
  395. (define-node-type literal
  396. value ;; the value
  397. type ;; the type of the value
  398. refs ;; either #F or a literal-reference record; only a few types of literal
  399. ) ;; literal values require reference lists
  400. (define-record-type literal-reference
  401. ()
  402. ((list '()) ;; list of literal nodes that refer to a particular value
  403. ))
  404. (define make-literal-reference-list literal-reference-maker)
  405. (define (make-literal-node value type)
  406. (let ((node (make-node 'literal)))
  407. (set-literal-value! node value)
  408. (set-literal-type! node type)
  409. (set-literal-refs! node #f)
  410. node))
  411. (define (copy-literal-node node)
  412. (let ((new (make-node 'literal))
  413. (refs (literal-refs node)))
  414. (set-literal-value! new (literal-value node))
  415. (set-literal-type! new (literal-type node))
  416. (set-literal-refs! new refs)
  417. (if refs (set-literal-reference-list!
  418. refs
  419. (cons new (literal-reference-list refs))))
  420. new))
  421. (define (make-marked-literal value refs)
  422. (let ((node (make-node 'literal)))
  423. (set-literal-value! node value)
  424. (set-literal-refs! node refs)
  425. (set-literal-reference-list! refs
  426. (cons node (literal-reference-list refs)))
  427. node))
  428. ;;-------------------------------------------------------------------------
  429. ;; These just contain an identifier.
  430. (define-node-type reference
  431. variable
  432. )
  433. (define (make-reference-node variable)
  434. (let ((node (make-node 'reference)))
  435. (set-reference-variable! node variable)
  436. (set-variable-refs! variable (cons node (variable-refs variable)))
  437. node))
  438. ;; Literal and reference nodes are leaf nodes as they do not contain any other
  439. ;; nodes.
  440. (define (leaf-node? n)
  441. (or (literal-node? n)
  442. (reference-node? n)))
  443. ;;--------------------------------------------------------------------------
  444. ;; Call nodes
  445. (define-node-type call
  446. primop ;; the primitive being called
  447. args ;; vector of child nodes
  448. exits ;; the number of arguments that are continuations
  449. source ;; source info
  450. )
  451. ;; Create a call node with primop P, N children and EXITS exits.
  452. (define (make-call-node primop n exits)
  453. (let ((node (make-node 'call)))
  454. (set-call-primop! node primop)
  455. (set-call-args! node (make-vector n empty))
  456. (set-call-exits! node exits)
  457. (set-call-source! node #f)
  458. node))
  459. (define (call-arg call index)
  460. (vector-ref (call-args call) index))
  461. (define (call-arg-count call)
  462. (vector-length (call-args call)))
  463. ;;----------------------------------------------------------------------------
  464. ;; LAMBDA NODES
  465. (define-node-type lambda
  466. body ;; the call-node that is the body of the lambda
  467. variables ;; a list of variable records with #Fs for ignored positions
  468. source ;; source code for the lambda (if any)
  469. data ;; a LAMBDA-DATA record (lambdas have more associated data than
  470. ) ;; the other node types.)
  471. (define-subrecord lambda lambda-data lambda-data
  472. ((name) ;; symbol (for debugging only)
  473. id ;; unique integer (for debugging only)
  474. (type)) ;; PROC, KNOWN-PROC, CONT, or JUMP (maybe ESCAPE at some point)
  475. ((block #f) ;; either a basic-block (for flow analysis) or a code-block
  476. ;; (for code generation).
  477. (env #f) ;; a record containing lexical environment data
  478. (protocol #f) ;; calling protocol from the source language
  479. (prev #f) ;; previous node on *LAMBDAS* list
  480. (next #f) ;; next node on *LAMBDAS* list
  481. ))
  482. ;; Doubly linked list of all non-CONT lambdas
  483. (define *lambdas* #f)
  484. (define (initialize-lambdas)
  485. (set! *lambdas* (make-lambda-node '*lambdas* 'cont '()))
  486. (link-lambdas *lambdas* *lambdas*))
  487. (define (link-lambdas node1 node2)
  488. (set-lambda-prev! node2 node1)
  489. (set-lambda-next! node1 node2))
  490. (define (add-lambda node)
  491. (let ((next (lambda-next *lambdas*)))
  492. (link-lambdas *lambdas* node)
  493. (link-lambdas node next)))
  494. (define (delete-lambda node)
  495. (link-lambdas (lambda-prev node) (lambda-next node))
  496. (set-lambda-prev! node #f)
  497. (set-lambda-next! node #f))
  498. (define (walk-lambdas proc)
  499. (do ((n (lambda-next *lambdas*) (lambda-next n)))
  500. ((eq? n *lambdas*))
  501. (proc n))
  502. (values))
  503. (define (make-lambda-list)
  504. (do ((n (lambda-next *lambdas*) (lambda-next n))
  505. (l '() (cons n l)))
  506. ((eq? n *lambdas*)
  507. l)))
  508. (define (add-lambdas nodes)
  509. (for-each add-lambda nodes))
  510. ;; Create a lambda node. NAME is used as the name of the lambda node's
  511. ;; self variable. VARS is a list of variables. The VARIABLE-BINDER slot
  512. ;; of each variable is set to be the new lambda node.
  513. (define (make-lambda-node name type vars)
  514. (let ((node (make-node 'lambda))
  515. (data (lambda-data-maker name (new-id) type)))
  516. (set-lambda-body! node empty)
  517. (set-lambda-variables! node vars)
  518. (set-lambda-data! node data)
  519. (set-lambda-source! node #f)
  520. (for-each (lambda (var)
  521. (if var (set-variable-binder! var node)))
  522. vars)
  523. (if (neq? type 'cont)
  524. (add-lambda node))
  525. node))
  526. ;; Change the type of lambda-node NODE to be TYPE. This may require adding or
  527. ;; deleting NODE from the list *LAMBDAS*.
  528. (define (change-lambda-type node type)
  529. (let ((has (lambda-type node)))
  530. (cond ((neq? type (lambda-type node))
  531. (set-lambda-type! node type)
  532. (cond ((eq? type 'cont)
  533. (delete-lambda node))
  534. ((eq? has 'cont)
  535. (add-lambda node)))))
  536. (values)))
  537. (define (lambda-variable-count node)
  538. (length (lambda-variables node)))
  539. (define (calls-known? node)
  540. (neq? (lambda-type node) 'proc))
  541. (define (set-calls-known?! node)
  542. (set-lambda-type! node 'known-proc))
  543. (define (proc-lambda? node)
  544. (or (eq? 'proc (lambda-type node))
  545. (eq? 'known-proc (lambda-type node))))