Freeing registers before using them is simpler.

https://todo.sr.ht/~sforman/thun-der/3
This commit is contained in:
Simon Forman 2020-01-31 08:26:10 -08:00
parent 400cc7dcde
commit 3d1c9bab95
1 changed files with 42 additions and 14 deletions

View File

@ -24,8 +24,22 @@
You should have received a copy of the GNU General Public License
along with Thun. If not see <http://www.gnu.org/licenses/>.
(Big fonts are from Figlet "ANSI Shadow" http://www.patorjk.com/software/taag/#p=display&f=ANSI%20Shadow&t=formatter
and "Small".)
(Big fonts are from Figlet ANSI Shadow http://www.patorjk.com/software/taag/#p=display&f=ANSI%20Shadow&t=formatter )
Table of Contents
Parser & Grammar
Semantics
Functions
Combinators
Definitions
Compiler
to Prolog
to Machine Code
Meta-Programming
Expand/Contract Definitions
Formatter
Partial Reducer
*/
@ -171,7 +185,9 @@ thun(symbol(A), C, B, G) :- combo(A, B, F, C, [D|E]), thun(D, E, F, G).
% expression and we don't want to process combo/5 twice just to
% notice that, eh? Swap the rules and add green cuts after combo/5
% and that should make it more efficient.
%
% Ach! THe "green" cuts would mess up multi-rule combinators! D'oh!
% Neither functions nor definitions can affect the expression so we
% don't need to do similar gardening to those rules. The unification
% of the head clauses will distinguish the cases for them.
@ -788,17 +804,13 @@ non_alloc(rolldown).
% Functions delegate to a per-function compilation relation.
func_compile(+, E, [A, B|S], So, FP0, FP) --> !,
% If either register A or B is only used once we can reuse it.
( {reg_used_once(B, FP0)} -> [add(B, A, B)], free_reg(A, FP0, FP4), {Si=[B|S]}
; {reg_used_once(A, FP0)} -> [add(A, A, B)], free_reg(B, FP0, FP4), {Si=[A|S]}
; get_reg(R, FP0, FP1), [add(R, A, B)],
assoc_reg(R, int(_), FP1, FP2),
free_reg(A, FP2, FP3),
free_reg(B, FP3, FP4),
{Si=[R|S]} % Can all this be simplified by freeing first?
),
free_reg(A, FP0, FP1),
free_reg(B, FP1, FP2),
get_reg(R, FP2, FP3),
assoc_reg(R, int(_), FP3, FP4),
[add(R, A, B)],
% Update value in the context?
thun_compile(E, Si, So, FP4, FP).
thun_compile(E, [R|S], So, FP4, FP).
func_compile(dup, E, [A|S], So, FP0, FP) --> !,
add_ref(A, FP0, FP1),
@ -810,10 +822,11 @@ func_compile(pop, E, [A|S], So, FP0, FP) --> !,
func_compile(cons, E, [List, Item|S], So, FP0, FP) --> !,
% allocate a cons cell
% https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book-Z-H-33.html#%_sec_5.3
thun_compile(E, S, So, FP0, FP).
func_compile(Func, E, Si, So, FP0, FP) -->
{ non_alloc(Func), !, func(Func, Si, S) },
func_compile(Func, E, Si, So, FP0, FP) --> { non_alloc(Func), !,
func(Func, Si, S) },
thun_compile(E, S, So, FP0, FP).
func_compile(_Func, E, Si, So, FP0, FP) -->
@ -933,6 +946,21 @@ add(r1, r2, r1).
Fun!
- - - -
Test that returning registers before asking for new ones
does reuse registers that are unused and preserve registers
that are still in use.
?- show_compiler(`1 dup 2 + swap 3 +`, StackIn, StackOut).
mov_imm(r0, int(1)).
mov_imm(r1, int(2)).
add(r1, r1, r0).
mov_imm(r2, int(3)).
add(r0, r2, r0).
[r0-int(_), r1-int(_)].
StackOut = [r0, r1|StackIn] .