node.scm 17 KB

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