33Opcodes operate on abstract values (Value) in a register machine. Each
44value has a type (RType). A value can hold various things, such as:
55
6- - local variables (Register)
6+ - local variables or temporaries (Register)
77- intermediate values of expressions (RegisterOp subclasses)
88- condition flags (true/false)
99- literals (integer literals, True, False, etc.)
10+
11+ NOTE: As a convention, we don't create subclasses of concrete Value/Op
12+ subclasses (e.g. you shouldn't define a subclass of Integer, which
13+ is a concrete class).
14+
15+ If you want to introduce a variant of an existing class, you'd
16+ typically add an attribute (e.g. a flag) to an existing concrete
17+ class to enable the new behavior. Sometimes adding a new abstract
18+ base class is also an option, or just creating a new subclass
19+ without any inheritance relationship (some duplication of code
20+ is preferred over introducing complex implementation inheritance).
21+
22+ This makes it possible to use isinstance(x, <concrete Value
23+ subclass>) checks without worrying about potential subclasses.
1024"""
1125
1226from __future__ import annotations
1327
1428from abc import abstractmethod
1529from collections .abc import Sequence
16- from typing import TYPE_CHECKING , Final , Generic , NamedTuple , TypeVar , Union
30+ from typing import TYPE_CHECKING , Final , Generic , NamedTuple , TypeVar , Union , final
1731
1832from mypy_extensions import trait
1933
4761T = TypeVar ("T" )
4862
4963
64+ @final
5065class BasicBlock :
5166 """IR basic block.
5267
@@ -142,6 +157,7 @@ def is_void(self) -> bool:
142157 return isinstance (self .type , RVoid )
143158
144159
160+ @final
145161class Register (Value ):
146162 """A Register holds a value of a specific type, and it can be read and mutated.
147163
@@ -168,6 +184,7 @@ def __repr__(self) -> str:
168184 return f"<Register { self .name !r} at { hex (id (self ))} >"
169185
170186
187+ @final
171188class Integer (Value ):
172189 """Short integer literal.
173190
@@ -198,6 +215,7 @@ def numeric_value(self) -> int:
198215 return self .value
199216
200217
218+ @final
201219class Float (Value ):
202220 """Float literal.
203221
@@ -257,13 +275,14 @@ def accept(self, visitor: OpVisitor[T]) -> T:
257275
258276
259277class BaseAssign (Op ):
260- """Base class for ops that assign to a register."""
278+ """Abstract base class for ops that assign to a register."""
261279
262280 def __init__ (self , dest : Register , line : int = - 1 ) -> None :
263281 super ().__init__ (line )
264282 self .dest = dest
265283
266284
285+ @final
267286class Assign (BaseAssign ):
268287 """Assign a value to a Register (dest = src)."""
269288
@@ -286,6 +305,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
286305 return visitor .visit_assign (self )
287306
288307
308+ @final
289309class AssignMulti (BaseAssign ):
290310 """Assign multiple values to a Register (dest = src1, src2, ...).
291311
@@ -320,7 +340,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
320340
321341
322342class ControlOp (Op ):
323- """Control flow operation ."""
343+ """Abstract base class for control flow operations ."""
324344
325345 def targets (self ) -> Sequence [BasicBlock ]:
326346 """Get all basic block targets of the control operation."""
@@ -331,6 +351,7 @@ def set_target(self, i: int, new: BasicBlock) -> None:
331351 raise AssertionError (f"Invalid set_target({ self } , { i } )" )
332352
333353
354+ @final
334355class Goto (ControlOp ):
335356 """Unconditional jump."""
336357
@@ -360,6 +381,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
360381 return visitor .visit_goto (self )
361382
362383
384+ @final
363385class Branch (ControlOp ):
364386 """Branch based on a value.
365387
@@ -426,6 +448,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
426448 return visitor .visit_branch (self )
427449
428450
451+ @final
429452class Return (ControlOp ):
430453 """Return a value from a function."""
431454
@@ -455,6 +478,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
455478 return visitor .visit_return (self )
456479
457480
481+ @final
458482class Unreachable (ControlOp ):
459483 """Mark the end of basic block as unreachable.
460484
@@ -511,6 +535,7 @@ def can_raise(self) -> bool:
511535 return self .error_kind != ERR_NEVER
512536
513537
538+ @final
514539class IncRef (RegisterOp ):
515540 """Increase reference count (inc_ref src)."""
516541
@@ -531,6 +556,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
531556 return visitor .visit_inc_ref (self )
532557
533558
559+ @final
534560class DecRef (RegisterOp ):
535561 """Decrease reference count and free object if zero (dec_ref src).
536562
@@ -559,6 +585,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
559585 return visitor .visit_dec_ref (self )
560586
561587
588+ @final
562589class Call (RegisterOp ):
563590 """Native call f(arg, ...).
564591
@@ -587,6 +614,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
587614 return visitor .visit_call (self )
588615
589616
617+ @final
590618class MethodCall (RegisterOp ):
591619 """Native method call obj.method(arg, ...)"""
592620
@@ -618,6 +646,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
618646 return visitor .visit_method_call (self )
619647
620648
649+ @final
621650class PrimitiveDescription :
622651 """Description of a primitive op.
623652
@@ -670,6 +699,7 @@ def __repr__(self) -> str:
670699 return f"<PrimitiveDescription { self .name !r} : { self .arg_types } >"
671700
672701
702+ @final
673703class PrimitiveOp (RegisterOp ):
674704 """A higher-level primitive operation.
675705
@@ -707,6 +737,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
707737 return visitor .visit_primitive_op (self )
708738
709739
740+ @final
710741class LoadErrorValue (RegisterOp ):
711742 """Load an error value.
712743
@@ -737,6 +768,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
737768 return visitor .visit_load_error_value (self )
738769
739770
771+ @final
740772class LoadLiteral (RegisterOp ):
741773 """Load a Python literal object (dest = 'foo' / b'foo' / ...).
742774
@@ -772,6 +804,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
772804 return visitor .visit_load_literal (self )
773805
774806
807+ @final
775808class GetAttr (RegisterOp ):
776809 """obj.attr (for a native object)"""
777810
@@ -804,6 +837,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
804837 return visitor .visit_get_attr (self )
805838
806839
840+ @final
807841class SetAttr (RegisterOp ):
808842 """obj.attr = src (for a native object)
809843
@@ -855,6 +889,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
855889NAMESPACE_TYPE_VAR : Final = "typevar"
856890
857891
892+ @final
858893class LoadStatic (RegisterOp ):
859894 """Load a static name (name :: static).
860895
@@ -895,6 +930,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
895930 return visitor .visit_load_static (self )
896931
897932
933+ @final
898934class InitStatic (RegisterOp ):
899935 """static = value :: static
900936
@@ -927,6 +963,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
927963 return visitor .visit_init_static (self )
928964
929965
966+ @final
930967class TupleSet (RegisterOp ):
931968 """dest = (reg, ...) (for fixed-length tuple)"""
932969
@@ -959,6 +996,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
959996 return visitor .visit_tuple_set (self )
960997
961998
999+ @final
9621000class TupleGet (RegisterOp ):
9631001 """Get item of a fixed-length tuple (src[index])."""
9641002
@@ -983,6 +1021,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
9831021 return visitor .visit_tuple_get (self )
9841022
9851023
1024+ @final
9861025class Cast (RegisterOp ):
9871026 """cast(type, src)
9881027
@@ -1014,6 +1053,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
10141053 return visitor .visit_cast (self )
10151054
10161055
1056+ @final
10171057class Box (RegisterOp ):
10181058 """box(type, src)
10191059
@@ -1048,6 +1088,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
10481088 return visitor .visit_box (self )
10491089
10501090
1091+ @final
10511092class Unbox (RegisterOp ):
10521093 """unbox(type, src)
10531094
@@ -1074,6 +1115,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
10741115 return visitor .visit_unbox (self )
10751116
10761117
1118+ @final
10771119class RaiseStandardError (RegisterOp ):
10781120 """Raise built-in exception with an optional error string.
10791121
@@ -1113,6 +1155,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
11131155StealsDescription = Union [bool , list [bool ]]
11141156
11151157
1158+ @final
11161159class CallC (RegisterOp ):
11171160 """result = function(arg0, arg1, ...)
11181161
@@ -1167,6 +1210,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
11671210 return visitor .visit_call_c (self )
11681211
11691212
1213+ @final
11701214class Truncate (RegisterOp ):
11711215 """result = truncate src from src_type to dst_type
11721216
@@ -1197,6 +1241,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
11971241 return visitor .visit_truncate (self )
11981242
11991243
1244+ @final
12001245class Extend (RegisterOp ):
12011246 """result = extend src from src_type to dst_type
12021247
@@ -1231,6 +1276,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
12311276 return visitor .visit_extend (self )
12321277
12331278
1279+ @final
12341280class LoadGlobal (RegisterOp ):
12351281 """Load a low-level global variable/pointer.
12361282
@@ -1258,6 +1304,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
12581304 return visitor .visit_load_global (self )
12591305
12601306
1307+ @final
12611308class IntOp (RegisterOp ):
12621309 """Binary arithmetic or bitwise op on integer operands (e.g., r1 = r2 + r3).
12631310
@@ -1322,6 +1369,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
13221369int_op_to_id : Final = {op : op_id for op_id , op in IntOp .op_str .items ()}
13231370
13241371
1372+ @final
13251373class ComparisonOp (RegisterOp ):
13261374 """Low-level comparison op for integers and pointers.
13271375
@@ -1383,6 +1431,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
13831431 return visitor .visit_comparison_op (self )
13841432
13851433
1434+ @final
13861435class FloatOp (RegisterOp ):
13871436 """Binary float arithmetic op (e.g., r1 = r2 + r3).
13881437
@@ -1424,6 +1473,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
14241473float_op_to_id : Final = {op : op_id for op_id , op in FloatOp .op_str .items ()}
14251474
14261475
1476+ @final
14271477class FloatNeg (RegisterOp ):
14281478 """Float negation op (r1 = -r2)."""
14291479
@@ -1444,6 +1494,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
14441494 return visitor .visit_float_neg (self )
14451495
14461496
1497+ @final
14471498class FloatComparisonOp (RegisterOp ):
14481499 """Low-level comparison op for floats."""
14491500
@@ -1480,6 +1531,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
14801531float_comparison_op_to_id : Final = {op : op_id for op_id , op in FloatComparisonOp .op_str .items ()}
14811532
14821533
1534+ @final
14831535class LoadMem (RegisterOp ):
14841536 """Read a memory location: result = *(type *)src.
14851537
@@ -1509,6 +1561,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
15091561 return visitor .visit_load_mem (self )
15101562
15111563
1564+ @final
15121565class SetMem (Op ):
15131566 """Write to a memory location: *(type *)dest = src
15141567
@@ -1540,6 +1593,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
15401593 return visitor .visit_set_mem (self )
15411594
15421595
1596+ @final
15431597class GetElementPtr (RegisterOp ):
15441598 """Get the address of a struct element.
15451599
@@ -1566,6 +1620,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
15661620 return visitor .visit_get_element_ptr (self )
15671621
15681622
1623+ @final
15691624class LoadAddress (RegisterOp ):
15701625 """Get the address of a value: result = (type)&src
15711626
@@ -1600,6 +1655,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
16001655 return visitor .visit_load_address (self )
16011656
16021657
1658+ @final
16031659class KeepAlive (RegisterOp ):
16041660 """A no-op operation that ensures source values aren't freed.
16051661
@@ -1647,6 +1703,7 @@ def accept(self, visitor: OpVisitor[T]) -> T:
16471703 return visitor .visit_keep_alive (self )
16481704
16491705
1706+ @final
16501707class Unborrow (RegisterOp ):
16511708 """A no-op op to create a regular reference from a borrowed one.
16521709
0 commit comments