1
1
from typing import override
2
2
3
3
import sleepy .tafka .representation as taf
4
- from sleepy .tafka . walker import TafkaWalker
4
+ from sleepy .tafka import Context , TafkaWalker , Usages
5
5
6
6
from .argument import Immediate , Integer , Unassigned
7
7
from .argument import PhysicalRegister as PhysReg
20
20
Orb ,
21
21
Remi ,
22
22
Slti ,
23
+ Stor ,
23
24
Xorb ,
24
25
mov ,
25
26
movi ,
@@ -42,17 +43,27 @@ def temporary(self) -> VirtReg:
42
43
return next (self .sequence )
43
44
44
45
45
- class AsmikEmitListener (TafkaWalker .Listener ):
46
+ class AsmikEmitListener (TafkaWalker .ContextedListener ):
46
47
def __init__ (self ) -> None :
48
+ super ().__init__ ()
49
+
47
50
self .memory = Memory ()
48
51
self .registers = VirtualRegisters ()
49
52
50
53
self .resolved : dict [str , int ] = {}
51
54
55
+ self .procedure : taf .Procedure
56
+ self .usages : Usages
57
+
52
58
@override
53
59
def enter_procedure (self , procedure : taf .Procedure ) -> None :
60
+ super ().enter_procedure (procedure )
61
+
62
+ self .usages = Usages .analyzed (procedure )
63
+ self .procedure = procedure
64
+
54
65
addr = self .memory .data_put (IntegerData (self .next_instr_addr ))
55
- self .resolved [repr ( procedure .const ) ] = addr
66
+ self .resolved [f"$ { procedure .const . name } " ] = addr
56
67
for i , param in enumerate (procedure .parameters ):
57
68
register = self .registers .binded_to (param )
58
69
self .emit (mov (register , PhysReg .arg (i + 1 )))
@@ -63,6 +74,7 @@ def exit_procedure(self, procedure: taf.Procedure) -> None:
63
74
64
75
@override
65
76
def enter_block (self , block : taf .Block ) -> None :
77
+ super ().enter_block (block )
66
78
self .resolved [repr (block .label )] = self .next_instr_addr
67
79
68
80
@override
@@ -71,7 +83,7 @@ def exit_block(self, block: taf.Block) -> None:
71
83
72
84
@override
73
85
def enter_statement (self , statement : taf .Statement ) -> None :
74
- pass
86
+ super (). enter_statement ( statement )
75
87
76
88
@override
77
89
def exit_statement (self , statement : taf .Statement ) -> None :
@@ -98,27 +110,48 @@ def on_conditional(self, conditional: taf.Conditional) -> None:
98
110
self .emit (movi (else_address , Unassigned (else_label )))
99
111
self .emit (Brn (condition , else_address ))
100
112
113
+ def push_context (self , variables : list [taf .Var ]) -> None :
114
+ def push (register : Reg ) -> None :
115
+ self .emit (Stor (Reg .sp (), register ))
116
+ self .emit (Addim (Reg .sp (), Reg .sp (), Integer (8 )))
117
+
118
+ for local in variables :
119
+ if self .is_alive (local ):
120
+ push (self .registers .binded_to (local ))
121
+ push (Reg .ra ())
122
+
123
+ def pop_context (self , variables : list [taf .Var ]) -> None :
124
+ def pop (register : Reg ) -> None :
125
+ self .emit (Addim (Reg .sp (), Reg .sp (), Integer (- 8 )))
126
+ self .emit (Load (register , Reg .sp ()))
127
+
128
+ pop (Reg .ra ())
129
+ for local in variables [::- 1 ]:
130
+ if self .is_alive (local ):
131
+ pop (self .registers .binded_to (local ))
132
+
101
133
@override
102
134
def on_invokation (
103
135
self ,
104
136
target : taf .Var ,
105
137
source : taf .Invokation ,
106
138
) -> None :
139
+ variables = list (self .procedure .locals )
140
+
141
+ self .push_context (variables )
142
+
107
143
for i , arg in enumerate (source .args ):
108
144
arg_reg = self .registers .binded_to (arg )
109
145
self .emit (mov (PhysReg .arg (i + 1 ), arg_reg ))
110
146
111
- prev_ra = self .registers .temporary ()
112
- self .emit (mov (prev_ra , Reg .ra ()))
113
-
114
147
proc_reg = self .registers .binded_to (source .closure )
115
148
self .emit (Addim (Reg .ra (), Reg .ip (), Integer (4 )))
116
149
self .emit (Brn (Reg .ze (), proc_reg ))
117
150
118
- res_reg = self .registers .binded_to (target )
119
- self .emit (mov (res_reg , Reg .a1 ()))
151
+ result = self .registers .binded_to (target )
152
+ self .emit (mov (result , Reg .a1 ()))
120
153
121
- self .emit ( mov ( Reg . ra (), prev_ra ) )
154
+ self .pop_context ( variables )
122
155
123
156
@override
124
157
def on_load (self , target : taf .Var , source : taf .Load ) -> None :
@@ -215,10 +248,20 @@ def addr_of(self, cnst: taf.Const) -> Immediate:
215
248
addr = self .memory .data_put (data )
216
249
return Integer (addr )
217
250
case taf .Signature ():
218
- return Unassigned (repr ( cnst ) )
251
+ return Unassigned (f"$ { cnst . name } " )
219
252
case _:
220
253
raise NotImplementedError
221
254
255
+ def is_alive (self , var : taf .Var ) -> bool :
256
+ read = self .usages .next_read (var , self .context )
257
+ write = self .usages .next_write (var , self .context )
258
+ init = self .usages .next_write (var , Context (- 1 , self .procedure .entry ))
259
+
260
+ assert init is not None # noqa: S101
261
+ if write is not None :
262
+ return read is not None and read <= write
263
+ return read is not None and init < self .position
264
+
222
265
@property
223
266
def next_instr_addr (self ) -> int :
224
267
return len (self .memory .instr ) * 4
0 commit comments