22
33from abc import abstractmethod
44
5- from typing import Dict , Tuple , List , Set , TypeVar , Iterator , Generic , Optional
5+ from typing import Dict , Tuple , List , Set , TypeVar , Iterator , Generic , Optional , Iterable
66
77from mypyc .ops import (
8+ Value , Register ,
89 BasicBlock , OpVisitor , Assign , LoadInt , LoadErrorValue , RegisterOp , Goto ,
910 Branch , Return , Call , Environment , Box , Unbox , Cast , Op , Unreachable ,
10- TupleGet , TupleSet , GetAttr , SetAttr , PyCall , LoadStatic , PyGetAttr , Label , Register ,
11+ TupleGet , TupleSet , GetAttr , SetAttr , PyCall , LoadStatic , PyGetAttr , Label ,
1112 PyMethodCall , PrimitiveOp , MethodCall ,
1213)
1314
@@ -75,7 +76,7 @@ def __init__(self, before: AnalysisDict[T], after: AnalysisDict[T]) -> None:
7576 def __str__ (self ) -> str :
7677 return 'before: %s\n after: %s\n ' % (self .before , self .after )
7778
78- GenAndKill = Tuple [Set [Register ], Set [Register ]]
79+ GenAndKill = Tuple [Set [Value ], Set [Value ]]
7980
8081
8182class BaseAnalysisVisitor (OpVisitor [GenAndKill ]):
@@ -86,6 +87,10 @@ def visit_goto(self, op: Goto) -> GenAndKill:
8687 def visit_register_op (self , op : RegisterOp ) -> GenAndKill :
8788 raise NotImplementedError
8889
90+ @abstractmethod
91+ def visit_assign (self , op : Assign ) -> GenAndKill :
92+ raise NotImplementedError
93+
8994 def visit_call (self , op : Call ) -> GenAndKill :
9095 return self .visit_register_op (op )
9196
@@ -101,9 +106,6 @@ def visit_py_method_call(self, op: PyMethodCall) -> GenAndKill:
101106 def visit_primitive_op (self , op : PrimitiveOp ) -> GenAndKill :
102107 return self .visit_register_op (op )
103108
104- def visit_assign (self , op : Assign ) -> GenAndKill :
105- return self .visit_register_op (op )
106-
107109 def visit_load_int (self , op : LoadInt ) -> GenAndKill :
108110 return self .visit_register_op (op )
109111
@@ -149,15 +151,18 @@ def visit_unreachable(self, op: Unreachable) -> GenAndKill:
149151 return set (), set ()
150152
151153 def visit_register_op (self , op : RegisterOp ) -> GenAndKill :
152- if op . dest is not None :
153- return {op . dest }, set ()
154+ if not op . is_void :
155+ return {op }, set ()
154156 else :
155157 return set (), set ()
156158
159+ def visit_assign (self , op : Assign ) -> GenAndKill :
160+ return {op .dest }, set ()
161+
157162
158163def analyze_maybe_defined_regs (blocks : List [BasicBlock ],
159164 cfg : CFG ,
160- initial_defined : Set [Register ]) -> AnalysisResult [Register ]:
165+ initial_defined : Set [Value ]) -> AnalysisResult [Value ]:
161166 """Calculate potentially defined registers at each CFG location.
162167
163168 A register is defined if it has a value along some path from the initial location.
@@ -183,17 +188,20 @@ def visit_unreachable(self, op: Unreachable) -> GenAndKill:
183188 return set (), set ()
184189
185190 def visit_register_op (self , op : RegisterOp ) -> GenAndKill :
186- if op . dest is not None :
187- return {op . dest }, set ()
191+ if not op . is_void :
192+ return {op }, set ()
188193 else :
189194 return set (), set ()
190195
196+ def visit_assign (self , op : Assign ) -> GenAndKill :
197+ return {op .dest }, set ()
198+
191199
192200def analyze_must_defined_regs (
193201 blocks : List [BasicBlock ],
194202 cfg : CFG ,
195- initial_defined : Set [Register ],
196- num_regs : int ) -> AnalysisResult [Register ]:
203+ initial_defined : Set [Value ],
204+ regs : Iterable [ Value ] ) -> AnalysisResult [Value ]:
197205 """Calculate always defined registers at each CFG location.
198206
199207 A register is defined if it has a value along all paths from the initial location.
@@ -204,11 +212,11 @@ def analyze_must_defined_regs(
204212 initial = initial_defined ,
205213 backward = False ,
206214 kind = MUST_ANALYSIS ,
207- universe = set ([ Register ( r ) for r in range ( num_regs )] ))
215+ universe = set (regs ))
208216
209217
210218class BorrowedArgumentsVisitor (BaseAnalysisVisitor ):
211- def __init__ (self , args : Set [Register ]) -> None :
219+ def __init__ (self , args : Set [Value ]) -> None :
212220 self .args = args
213221
214222 def visit_branch (self , op : Branch ) -> GenAndKill :
@@ -221,15 +229,17 @@ def visit_unreachable(self, op: Unreachable) -> GenAndKill:
221229 return set (), set ()
222230
223231 def visit_register_op (self , op : RegisterOp ) -> GenAndKill :
232+ return set (), set ()
233+
234+ def visit_assign (self , op : Assign ) -> GenAndKill :
224235 if op .dest in self .args :
225236 return set (), {op .dest }
226237 return set (), set ()
227238
228-
229239def analyze_borrowed_arguments (
230240 blocks : List [BasicBlock ],
231241 cfg : CFG ,
232- args : Set [Register ]) -> AnalysisResult [Register ]:
242+ args : Set [Value ]) -> AnalysisResult [Value ]:
233243 """Calculate arguments that can use references borrowed from the caller.
234244
235245 When assigning to an argument, it no longer is borrowed.
@@ -254,21 +264,21 @@ def visit_unreachable(self, op: Unreachable) -> GenAndKill:
254264 return set (), set ()
255265
256266 def visit_register_op (self , op : RegisterOp ) -> GenAndKill :
257- return set (), {op . dest } if op . dest is not None else set ()
267+ return set (), {op } if not op . is_void else set ()
258268
269+ def visit_assign (self , op : Assign ) -> GenAndKill :
270+ return set (), {op .dest }
259271
260272def analyze_undefined_regs (blocks : List [BasicBlock ],
261273 cfg : CFG ,
262274 env : Environment ,
263- initial_defined : Set [Register ]) -> AnalysisResult [Register ]:
275+ initial_defined : Set [Value ]) -> AnalysisResult [Value ]:
264276 """Calculate potentially undefined registers at each CFG location.
265277
266278 A register is undefined if there is some path from initial block
267279 where it has an undefined value.
268280 """
269- initial_undefined = {Register (reg )
270- for reg in range (len (env .names ))
271- if Register (reg ) not in initial_defined }
281+ initial_undefined = set (env .regs ()) - initial_defined
272282 return run_analysis (blocks = blocks ,
273283 cfg = cfg ,
274284 gen_and_kill = UndefinedVisitor (),
@@ -289,14 +299,17 @@ def visit_unreachable(self, op: Unreachable) -> GenAndKill:
289299
290300 def visit_register_op (self , op : RegisterOp ) -> GenAndKill :
291301 gen = set (op .sources ())
292- if op . dest is not None :
293- return gen , {op . dest }
302+ if not op . is_void :
303+ return gen , {op }
294304 else :
295305 return gen , set ()
296306
307+ def visit_assign (self , op : Assign ) -> GenAndKill :
308+ return set (op .sources ()), {op .dest }
309+
297310
298311def analyze_live_regs (blocks : List [BasicBlock ],
299- cfg : CFG ) -> AnalysisResult [Register ]:
312+ cfg : CFG ) -> AnalysisResult [Value ]:
300313 """Calculate live registers at each CFG location.
301314
302315 A register is live at a location if it can be read along some CFG path starting
0 commit comments