! Copyright (C) 2004, 2006 Slava Pestov. ! See http://factorcode.org/license.txt for BSD license. IN: compiler USING: arrays assembler errors generic hashtables inference kernel kernel-internals lists math namespaces queues sequences words ; GENERIC: stack-reserve* M: object stack-reserve* drop 0 ; : stack-reserve ( node -- n ) 0 swap [ stack-reserve* max ] each-node ; : intrinsic ( #call -- quot ) node-param "intrinsic" word-prop ; : if-intrinsic ( #call -- quot ) node-param "if-intrinsic" word-prop ; DEFER: #terminal? PREDICATE: #merge #terminal-merge node-successor #terminal? ; PREDICATE: #call #terminal-call dup node-successor #if? over node-successor node-successor #terminal? and swap if-intrinsic and ; UNION: #terminal POSTPONE: f #return #values #terminal-merge ; : tail-call? ( -- ? ) node-stack get [ dup #terminal-call? swap node-successor #terminal? or ] all? ; : generate-code ( word node quot -- length | quot: node -- ) compiled-offset >r compile-aligned rot save-xt over stack-reserve %prologue call compile-aligned compiled-offset r> - ; : generate-reloc ( -- length ) relocation-table get dup [ assemble-cell ] each length cells ; SYMBOL: previous-offset : begin-generating ( -- code-len-fixup reloc-len-fixup ) compiled-offset previous-offset set V{ } clone relocation-table set init-templates begin-assembly swap ; : generate-1 ( word node quot -- | quot: node -- ) #! If generation fails, reset compiled offset. [ begin-generating >r >r generate-code generate-reloc r> set-compiled-cell r> set-compiled-cell ] [ previous-offset get set-compiled-offset rethrow ] recover ; SYMBOL: generate-queue : generate-loop ( -- ) generate-queue get dup queue-empty? [ drop ] [ deque first3 generate-1 generate-loop ] if ; : generate-block ( word node quot -- | quot: node -- ) 3array generate-queue get enque ; GENERIC: generate-node ( node -- ) : generate-nodes ( node -- ) [ node@ generate-node ] iterate-nodes end-basic-block ; : generate-word ( node -- ) [ [ generate-nodes ] with-node-iterator ] generate-block ; : generate ( word node -- ) [ generate-queue set generate-word generate-loop ] with-scope ; ! node M: node generate-node ( node -- next ) drop iterate-next ; ! #label : generate-call ( label -- next ) end-basic-block tail-call? [ %jump f ] [ %call iterate-next ] if ; M: #label generate-node ( node -- next ) #! We remap the IR node's label to a new label object here, #! to avoid problems with two IR #label nodes having the #! same label in different lexical scopes. dup node-param dup generate-call >r swap node-child generate-word r> ; ! #if : end-false-branch ( label -- ) tail-call? [ %return drop ] [ %jump-label ] if ; : generate-if ( node label -- next )