ops.py 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579
  1. """Low-level opcodes for compiler intermediate representation (IR).
  2. Opcodes operate on abstract values (Value) in a register machine. Each
  3. value has a type (RType). A value can hold various things, such as:
  4. - local variables (Register)
  5. - intermediate values of expressions (RegisterOp subclasses)
  6. - condition flags (true/false)
  7. - literals (integer literals, True, False, etc.)
  8. """
  9. from __future__ import annotations
  10. from abc import abstractmethod
  11. from typing import TYPE_CHECKING, Final, Generic, List, NamedTuple, Sequence, TypeVar, Union
  12. from mypy_extensions import trait
  13. from mypyc.ir.rtypes import (
  14. RArray,
  15. RInstance,
  16. RTuple,
  17. RType,
  18. RVoid,
  19. bit_rprimitive,
  20. bool_rprimitive,
  21. float_rprimitive,
  22. int_rprimitive,
  23. is_bit_rprimitive,
  24. is_bool_rprimitive,
  25. is_int_rprimitive,
  26. is_none_rprimitive,
  27. is_pointer_rprimitive,
  28. is_short_int_rprimitive,
  29. object_rprimitive,
  30. pointer_rprimitive,
  31. short_int_rprimitive,
  32. void_rtype,
  33. )
  34. if TYPE_CHECKING:
  35. from mypyc.codegen.literals import LiteralValue
  36. from mypyc.ir.class_ir import ClassIR
  37. from mypyc.ir.func_ir import FuncDecl, FuncIR
  38. T = TypeVar("T")
  39. class BasicBlock:
  40. """IR basic block.
  41. Contains a sequence of Ops and ends with a ControlOp (Goto,
  42. Branch, Return or Unreachable). Only the last op can be a
  43. ControlOp.
  44. All generated Ops live in basic blocks. Basic blocks determine the
  45. order of evaluation and control flow within a function. A basic
  46. block is always associated with a single function/method (FuncIR).
  47. When building the IR, ops that raise exceptions can be included in
  48. the middle of a basic block, but the exceptions aren't checked.
  49. Afterwards we perform a transform that inserts explicit checks for
  50. all error conditions and splits basic blocks accordingly to preserve
  51. the invariant that a jump, branch or return can only ever appear
  52. as the final op in a block. Manually inserting error checking ops
  53. would be boring and error-prone.
  54. BasicBlocks have an error_handler attribute that determines where
  55. to jump if an error occurs. If none is specified, an error will
  56. propagate up out of the function. This is compiled away by the
  57. `exceptions` module.
  58. Block labels are used for pretty printing and emitting C code, and
  59. get filled in by those passes.
  60. Ops that may terminate the program aren't treated as exits.
  61. """
  62. def __init__(self, label: int = -1) -> None:
  63. self.label = label
  64. self.ops: list[Op] = []
  65. self.error_handler: BasicBlock | None = None
  66. self.referenced = False
  67. @property
  68. def terminated(self) -> bool:
  69. """Does the block end with a jump, branch or return?
  70. This should always be true after the basic block has been fully built, but
  71. this is false during construction.
  72. """
  73. return bool(self.ops) and isinstance(self.ops[-1], ControlOp)
  74. @property
  75. def terminator(self) -> ControlOp:
  76. """The terminator operation of the block."""
  77. assert bool(self.ops) and isinstance(self.ops[-1], ControlOp)
  78. return self.ops[-1]
  79. # Never generates an exception
  80. ERR_NEVER: Final = 0
  81. # Generates magic value (c_error_value) based on target RType on exception
  82. ERR_MAGIC: Final = 1
  83. # Generates false (bool) on exception
  84. ERR_FALSE: Final = 2
  85. # Always fails
  86. ERR_ALWAYS: Final = 3
  87. # Like ERR_MAGIC, but the magic return overlaps with a possible return value, and
  88. # an extra PyErr_Occurred() check is also required
  89. ERR_MAGIC_OVERLAPPING: Final = 4
  90. # Hack: using this line number for an op will suppress it in tracebacks
  91. NO_TRACEBACK_LINE_NO = -10000
  92. class Value:
  93. """Abstract base class for all IR values.
  94. These include references to registers, literals, and all
  95. operations (Ops), such as assignments, calls and branches.
  96. Values are often used as inputs of Ops. Register can be used as an
  97. assignment target.
  98. A Value is part of the IR being compiled if it's included in a BasicBlock
  99. that is reachable from a FuncIR (i.e., is part of a function).
  100. See also: Op is a subclass of Value that is the base class of all
  101. operations.
  102. """
  103. # Source line number (-1 for no/unknown line)
  104. line = -1
  105. # Type of the value or the result of the operation
  106. type: RType = void_rtype
  107. is_borrowed = False
  108. @property
  109. def is_void(self) -> bool:
  110. return isinstance(self.type, RVoid)
  111. class Register(Value):
  112. """A Register holds a value of a specific type, and it can be read and mutated.
  113. A Register is always local to a function. Each local variable maps
  114. to a Register, and they are also used for some (but not all)
  115. temporary values.
  116. Note that the term 'register' is overloaded and is sometimes used
  117. to refer to arbitrary Values (for example, in RegisterOp).
  118. """
  119. def __init__(self, type: RType, name: str = "", is_arg: bool = False, line: int = -1) -> None:
  120. self.type = type
  121. self.name = name
  122. self.is_arg = is_arg
  123. self.is_borrowed = is_arg
  124. self.line = line
  125. @property
  126. def is_void(self) -> bool:
  127. return False
  128. def __repr__(self) -> str:
  129. return f"<Register {self.name!r} at {hex(id(self))}>"
  130. class Integer(Value):
  131. """Short integer literal.
  132. Integer literals are treated as constant values and are generally
  133. not included in data flow analyses and such, unlike Register and
  134. Op subclasses.
  135. Integer can represent multiple types:
  136. * Short tagged integers (short_int_primitive type; the tag bit is clear)
  137. * Ordinary fixed-width integers (e.g., int32_rprimitive)
  138. * Values of other unboxed primitive types that are represented as integers
  139. (none_rprimitive, bool_rprimitive)
  140. * Null pointers (value 0) of various types, including object_rprimitive
  141. """
  142. def __init__(self, value: int, rtype: RType = short_int_rprimitive, line: int = -1) -> None:
  143. if is_short_int_rprimitive(rtype) or is_int_rprimitive(rtype):
  144. self.value = value * 2
  145. else:
  146. self.value = value
  147. self.type = rtype
  148. self.line = line
  149. def numeric_value(self) -> int:
  150. if is_short_int_rprimitive(self.type) or is_int_rprimitive(self.type):
  151. return self.value // 2
  152. return self.value
  153. class Float(Value):
  154. """Float literal.
  155. Floating point literals are treated as constant values and are generally
  156. not included in data flow analyses and such, unlike Register and
  157. Op subclasses.
  158. """
  159. def __init__(self, value: float, line: int = -1) -> None:
  160. self.value = value
  161. self.type = float_rprimitive
  162. self.line = line
  163. class Op(Value):
  164. """Abstract base class for all IR operations.
  165. Each operation must be stored in a BasicBlock (in 'ops') to be
  166. active in the IR. This is different from non-Op values, including
  167. Register and Integer, where a reference from an active Op is
  168. sufficient to be considered active.
  169. In well-formed IR an active Op has no references to inactive ops
  170. or ops used in another function.
  171. """
  172. def __init__(self, line: int) -> None:
  173. self.line = line
  174. def can_raise(self) -> bool:
  175. # Override this is if Op may raise an exception. Note that currently the fact that
  176. # only RegisterOps may raise an exception in hard coded in some places.
  177. return False
  178. @abstractmethod
  179. def sources(self) -> list[Value]:
  180. """All the values the op may read."""
  181. def stolen(self) -> list[Value]:
  182. """Return arguments that have a reference count stolen by this op"""
  183. return []
  184. def unique_sources(self) -> list[Value]:
  185. result: list[Value] = []
  186. for reg in self.sources():
  187. if reg not in result:
  188. result.append(reg)
  189. return result
  190. @abstractmethod
  191. def accept(self, visitor: OpVisitor[T]) -> T:
  192. pass
  193. class BaseAssign(Op):
  194. """Base class for ops that assign to a register."""
  195. def __init__(self, dest: Register, line: int = -1) -> None:
  196. super().__init__(line)
  197. self.dest = dest
  198. class Assign(BaseAssign):
  199. """Assign a value to a Register (dest = src)."""
  200. error_kind = ERR_NEVER
  201. def __init__(self, dest: Register, src: Value, line: int = -1) -> None:
  202. super().__init__(dest, line)
  203. self.src = src
  204. def sources(self) -> list[Value]:
  205. return [self.src]
  206. def stolen(self) -> list[Value]:
  207. return [self.src]
  208. def accept(self, visitor: OpVisitor[T]) -> T:
  209. return visitor.visit_assign(self)
  210. class AssignMulti(BaseAssign):
  211. """Assign multiple values to a Register (dest = src1, src2, ...).
  212. This is used to initialize RArray values. It's provided to avoid
  213. very verbose IR for common vectorcall operations.
  214. Note that this interacts atypically with reference counting. We
  215. assume that each RArray register is initialized exactly once
  216. with this op.
  217. """
  218. error_kind = ERR_NEVER
  219. def __init__(self, dest: Register, src: list[Value], line: int = -1) -> None:
  220. super().__init__(dest, line)
  221. assert src
  222. assert isinstance(dest.type, RArray)
  223. assert dest.type.length == len(src)
  224. self.src = src
  225. def sources(self) -> list[Value]:
  226. return self.src.copy()
  227. def stolen(self) -> list[Value]:
  228. return []
  229. def accept(self, visitor: OpVisitor[T]) -> T:
  230. return visitor.visit_assign_multi(self)
  231. class ControlOp(Op):
  232. """Control flow operation."""
  233. def targets(self) -> Sequence[BasicBlock]:
  234. """Get all basic block targets of the control operation."""
  235. return ()
  236. def set_target(self, i: int, new: BasicBlock) -> None:
  237. """Update a basic block target."""
  238. raise AssertionError(f"Invalid set_target({self}, {i})")
  239. class Goto(ControlOp):
  240. """Unconditional jump."""
  241. error_kind = ERR_NEVER
  242. def __init__(self, label: BasicBlock, line: int = -1) -> None:
  243. super().__init__(line)
  244. self.label = label
  245. def targets(self) -> Sequence[BasicBlock]:
  246. return (self.label,)
  247. def set_target(self, i: int, new: BasicBlock) -> None:
  248. assert i == 0
  249. self.label = new
  250. def __repr__(self) -> str:
  251. return "<Goto %s>" % self.label.label
  252. def sources(self) -> list[Value]:
  253. return []
  254. def accept(self, visitor: OpVisitor[T]) -> T:
  255. return visitor.visit_goto(self)
  256. class Branch(ControlOp):
  257. """Branch based on a value.
  258. If op is BOOL, branch based on a bit/bool value:
  259. if [not] r1 goto L1 else goto L2
  260. If op is IS_ERROR, branch based on whether there is an error value:
  261. if [not] is_error(r1) goto L1 else goto L2
  262. """
  263. # Branch ops never raise an exception.
  264. error_kind = ERR_NEVER
  265. BOOL: Final = 100
  266. IS_ERROR: Final = 101
  267. def __init__(
  268. self,
  269. value: Value,
  270. true_label: BasicBlock,
  271. false_label: BasicBlock,
  272. op: int,
  273. line: int = -1,
  274. *,
  275. rare: bool = False,
  276. ) -> None:
  277. super().__init__(line)
  278. # Target value being checked
  279. self.value = value
  280. # Branch here if the condition is true
  281. self.true = true_label
  282. # Branch here if the condition is false
  283. self.false = false_label
  284. # Branch.BOOL (boolean check) or Branch.IS_ERROR (error value check)
  285. self.op = op
  286. # If True, the condition is negated
  287. self.negated = False
  288. # If not None, the true label should generate a traceback entry (func name, line number)
  289. self.traceback_entry: tuple[str, int] | None = None
  290. # If True, we expect to usually take the false branch (for optimization purposes);
  291. # this is implicitly treated as true if there is a traceback entry
  292. self.rare = rare
  293. def targets(self) -> Sequence[BasicBlock]:
  294. return (self.true, self.false)
  295. def set_target(self, i: int, new: BasicBlock) -> None:
  296. assert i == 0 or i == 1
  297. if i == 0:
  298. self.true = new
  299. else:
  300. self.false = new
  301. def sources(self) -> list[Value]:
  302. return [self.value]
  303. def invert(self) -> None:
  304. self.negated = not self.negated
  305. def accept(self, visitor: OpVisitor[T]) -> T:
  306. return visitor.visit_branch(self)
  307. class Return(ControlOp):
  308. """Return a value from a function."""
  309. error_kind = ERR_NEVER
  310. def __init__(self, value: Value, line: int = -1) -> None:
  311. super().__init__(line)
  312. self.value = value
  313. def sources(self) -> list[Value]:
  314. return [self.value]
  315. def stolen(self) -> list[Value]:
  316. return [self.value]
  317. def accept(self, visitor: OpVisitor[T]) -> T:
  318. return visitor.visit_return(self)
  319. class Unreachable(ControlOp):
  320. """Mark the end of basic block as unreachable.
  321. This is sometimes necessary when the end of a basic block is never
  322. reached. This can also be explicitly added to the end of non-None
  323. returning functions (in None-returning function we can just return
  324. None).
  325. Mypy statically guarantees that the end of the function is not
  326. unreachable if there is not a return statement.
  327. This prevents the block formatter from being confused due to lack
  328. of a leave and also leaves a nifty note in the IR. It is not
  329. generally processed by visitors.
  330. """
  331. error_kind = ERR_NEVER
  332. def __init__(self, line: int = -1) -> None:
  333. super().__init__(line)
  334. def sources(self) -> list[Value]:
  335. return []
  336. def accept(self, visitor: OpVisitor[T]) -> T:
  337. return visitor.visit_unreachable(self)
  338. class RegisterOp(Op):
  339. """Abstract base class for operations that can be written as r1 = f(r2, ..., rn).
  340. Takes some values, performs an operation, and generates an output
  341. (unless the 'type' attribute is void_rtype, which is the default).
  342. Other ops can refer to the result of the Op by referring to the Op
  343. instance. This doesn't do any explicit control flow, but can raise an
  344. error.
  345. Note that the operands can be arbitrary Values, not just Register
  346. instances, even though the naming may suggest otherwise.
  347. """
  348. error_kind = -1 # Can this raise exception and how is it signalled; one of ERR_*
  349. _type: RType | None = None
  350. def __init__(self, line: int) -> None:
  351. super().__init__(line)
  352. assert self.error_kind != -1, "error_kind not defined"
  353. def can_raise(self) -> bool:
  354. return self.error_kind != ERR_NEVER
  355. class IncRef(RegisterOp):
  356. """Increase reference count (inc_ref src)."""
  357. error_kind = ERR_NEVER
  358. def __init__(self, src: Value, line: int = -1) -> None:
  359. assert src.type.is_refcounted
  360. super().__init__(line)
  361. self.src = src
  362. def sources(self) -> list[Value]:
  363. return [self.src]
  364. def accept(self, visitor: OpVisitor[T]) -> T:
  365. return visitor.visit_inc_ref(self)
  366. class DecRef(RegisterOp):
  367. """Decrease reference count and free object if zero (dec_ref src).
  368. The is_xdec flag says to use an XDECREF, which checks if the
  369. pointer is NULL first.
  370. """
  371. error_kind = ERR_NEVER
  372. def __init__(self, src: Value, is_xdec: bool = False, line: int = -1) -> None:
  373. assert src.type.is_refcounted
  374. super().__init__(line)
  375. self.src = src
  376. self.is_xdec = is_xdec
  377. def __repr__(self) -> str:
  378. return "<{}DecRef {!r}>".format("X" if self.is_xdec else "", self.src)
  379. def sources(self) -> list[Value]:
  380. return [self.src]
  381. def accept(self, visitor: OpVisitor[T]) -> T:
  382. return visitor.visit_dec_ref(self)
  383. class Call(RegisterOp):
  384. """Native call f(arg, ...).
  385. The call target can be a module-level function or a class.
  386. """
  387. def __init__(self, fn: FuncDecl, args: Sequence[Value], line: int) -> None:
  388. self.fn = fn
  389. self.args = list(args)
  390. assert len(self.args) == len(fn.sig.args)
  391. self.type = fn.sig.ret_type
  392. ret_type = fn.sig.ret_type
  393. if not ret_type.error_overlap:
  394. self.error_kind = ERR_MAGIC
  395. else:
  396. self.error_kind = ERR_MAGIC_OVERLAPPING
  397. super().__init__(line)
  398. def sources(self) -> list[Value]:
  399. return list(self.args.copy())
  400. def accept(self, visitor: OpVisitor[T]) -> T:
  401. return visitor.visit_call(self)
  402. class MethodCall(RegisterOp):
  403. """Native method call obj.method(arg, ...)"""
  404. def __init__(self, obj: Value, method: str, args: list[Value], line: int = -1) -> None:
  405. self.obj = obj
  406. self.method = method
  407. self.args = args
  408. assert isinstance(obj.type, RInstance), "Methods can only be called on instances"
  409. self.receiver_type = obj.type
  410. method_ir = self.receiver_type.class_ir.method_sig(method)
  411. assert method_ir is not None, "{} doesn't have method {}".format(
  412. self.receiver_type.name, method
  413. )
  414. ret_type = method_ir.ret_type
  415. self.type = ret_type
  416. if not ret_type.error_overlap:
  417. self.error_kind = ERR_MAGIC
  418. else:
  419. self.error_kind = ERR_MAGIC_OVERLAPPING
  420. super().__init__(line)
  421. def sources(self) -> list[Value]:
  422. return self.args.copy() + [self.obj]
  423. def accept(self, visitor: OpVisitor[T]) -> T:
  424. return visitor.visit_method_call(self)
  425. class LoadErrorValue(RegisterOp):
  426. """Load an error value.
  427. Each type has one reserved value that signals an error (exception). This
  428. loads the error value for a specific type.
  429. """
  430. error_kind = ERR_NEVER
  431. def __init__(
  432. self, rtype: RType, line: int = -1, is_borrowed: bool = False, undefines: bool = False
  433. ) -> None:
  434. super().__init__(line)
  435. self.type = rtype
  436. self.is_borrowed = is_borrowed
  437. # Undefines is true if this should viewed by the definedness
  438. # analysis pass as making the register it is assigned to
  439. # undefined (and thus checks should be added on uses).
  440. self.undefines = undefines
  441. def sources(self) -> list[Value]:
  442. return []
  443. def accept(self, visitor: OpVisitor[T]) -> T:
  444. return visitor.visit_load_error_value(self)
  445. class LoadLiteral(RegisterOp):
  446. """Load a Python literal object (dest = 'foo' / b'foo' / ...).
  447. This is used to load a static PyObject * value corresponding to
  448. a literal of one of the supported types.
  449. Tuple / frozenset literals must contain only valid literal values as items.
  450. NOTE: You can use this to load boxed (Python) int objects. Use
  451. Integer to load unboxed, tagged integers or fixed-width,
  452. low-level integers.
  453. For int literals, both int_rprimitive (CPyTagged) and
  454. object_primitive (PyObject *) are supported as rtype. However,
  455. when using int_rprimitive, the value must *not* be small enough
  456. to fit in an unboxed integer.
  457. """
  458. error_kind = ERR_NEVER
  459. is_borrowed = True
  460. def __init__(self, value: LiteralValue, rtype: RType) -> None:
  461. self.value = value
  462. self.type = rtype
  463. def sources(self) -> list[Value]:
  464. return []
  465. def accept(self, visitor: OpVisitor[T]) -> T:
  466. return visitor.visit_load_literal(self)
  467. class GetAttr(RegisterOp):
  468. """obj.attr (for a native object)"""
  469. error_kind = ERR_MAGIC
  470. def __init__(self, obj: Value, attr: str, line: int, *, borrow: bool = False) -> None:
  471. super().__init__(line)
  472. self.obj = obj
  473. self.attr = attr
  474. assert isinstance(obj.type, RInstance), "Attribute access not supported: %s" % obj.type
  475. self.class_type = obj.type
  476. attr_type = obj.type.attr_type(attr)
  477. self.type = attr_type
  478. if attr_type.error_overlap:
  479. self.error_kind = ERR_MAGIC_OVERLAPPING
  480. self.is_borrowed = borrow and attr_type.is_refcounted
  481. def sources(self) -> list[Value]:
  482. return [self.obj]
  483. def accept(self, visitor: OpVisitor[T]) -> T:
  484. return visitor.visit_get_attr(self)
  485. class SetAttr(RegisterOp):
  486. """obj.attr = src (for a native object)
  487. Steals the reference to src.
  488. """
  489. error_kind = ERR_FALSE
  490. def __init__(self, obj: Value, attr: str, src: Value, line: int) -> None:
  491. super().__init__(line)
  492. self.obj = obj
  493. self.attr = attr
  494. self.src = src
  495. assert isinstance(obj.type, RInstance), "Attribute access not supported: %s" % obj.type
  496. self.class_type = obj.type
  497. self.type = bool_rprimitive
  498. # If True, we can safely assume that the attribute is previously undefined
  499. # and we don't use a setter
  500. self.is_init = False
  501. def mark_as_initializer(self) -> None:
  502. self.is_init = True
  503. self.error_kind = ERR_NEVER
  504. self.type = void_rtype
  505. def sources(self) -> list[Value]:
  506. return [self.obj, self.src]
  507. def stolen(self) -> list[Value]:
  508. return [self.src]
  509. def accept(self, visitor: OpVisitor[T]) -> T:
  510. return visitor.visit_set_attr(self)
  511. # Default name space for statics, variables
  512. NAMESPACE_STATIC: Final = "static"
  513. # Static namespace for pointers to native type objects
  514. NAMESPACE_TYPE: Final = "type"
  515. # Namespace for modules
  516. NAMESPACE_MODULE: Final = "module"
  517. class LoadStatic(RegisterOp):
  518. """Load a static name (name :: static).
  519. Load a C static variable/pointer. The namespace for statics is shared
  520. for the entire compilation group. You can optionally provide a module
  521. name and a sub-namespace identifier for additional namespacing to avoid
  522. name conflicts. The static namespace does not overlap with other C names,
  523. since the final C name will get a prefix, so conflicts only must be
  524. avoided with other statics.
  525. """
  526. error_kind = ERR_NEVER
  527. is_borrowed = True
  528. def __init__(
  529. self,
  530. type: RType,
  531. identifier: str,
  532. module_name: str | None = None,
  533. namespace: str = NAMESPACE_STATIC,
  534. line: int = -1,
  535. ann: object = None,
  536. ) -> None:
  537. super().__init__(line)
  538. self.identifier = identifier
  539. self.module_name = module_name
  540. self.namespace = namespace
  541. self.type = type
  542. self.ann = ann # An object to pretty print with the load
  543. def sources(self) -> list[Value]:
  544. return []
  545. def accept(self, visitor: OpVisitor[T]) -> T:
  546. return visitor.visit_load_static(self)
  547. class InitStatic(RegisterOp):
  548. """static = value :: static
  549. Initialize a C static variable/pointer. See everything in LoadStatic.
  550. """
  551. error_kind = ERR_NEVER
  552. def __init__(
  553. self,
  554. value: Value,
  555. identifier: str,
  556. module_name: str | None = None,
  557. namespace: str = NAMESPACE_STATIC,
  558. line: int = -1,
  559. ) -> None:
  560. super().__init__(line)
  561. self.identifier = identifier
  562. self.module_name = module_name
  563. self.namespace = namespace
  564. self.value = value
  565. def sources(self) -> list[Value]:
  566. return [self.value]
  567. def accept(self, visitor: OpVisitor[T]) -> T:
  568. return visitor.visit_init_static(self)
  569. class TupleSet(RegisterOp):
  570. """dest = (reg, ...) (for fixed-length tuple)"""
  571. error_kind = ERR_NEVER
  572. def __init__(self, items: list[Value], line: int) -> None:
  573. super().__init__(line)
  574. self.items = items
  575. # Don't keep track of the fact that an int is short after it
  576. # is put into a tuple, since we don't properly implement
  577. # runtime subtyping for tuples.
  578. self.tuple_type = RTuple(
  579. [
  580. arg.type if not is_short_int_rprimitive(arg.type) else int_rprimitive
  581. for arg in items
  582. ]
  583. )
  584. self.type = self.tuple_type
  585. def sources(self) -> list[Value]:
  586. return self.items.copy()
  587. def accept(self, visitor: OpVisitor[T]) -> T:
  588. return visitor.visit_tuple_set(self)
  589. class TupleGet(RegisterOp):
  590. """Get item of a fixed-length tuple (src[index])."""
  591. error_kind = ERR_NEVER
  592. def __init__(self, src: Value, index: int, line: int = -1) -> None:
  593. super().__init__(line)
  594. self.src = src
  595. self.index = index
  596. assert isinstance(src.type, RTuple), "TupleGet only operates on tuples"
  597. assert index >= 0
  598. self.type = src.type.types[index]
  599. def sources(self) -> list[Value]:
  600. return [self.src]
  601. def accept(self, visitor: OpVisitor[T]) -> T:
  602. return visitor.visit_tuple_get(self)
  603. class Cast(RegisterOp):
  604. """cast(type, src)
  605. Perform a runtime type check (no representation or value conversion).
  606. DO NOT increment reference counts.
  607. """
  608. error_kind = ERR_MAGIC
  609. def __init__(self, src: Value, typ: RType, line: int, *, borrow: bool = False) -> None:
  610. super().__init__(line)
  611. self.src = src
  612. self.type = typ
  613. self.is_borrowed = borrow
  614. def sources(self) -> list[Value]:
  615. return [self.src]
  616. def stolen(self) -> list[Value]:
  617. if self.is_borrowed:
  618. return []
  619. return [self.src]
  620. def accept(self, visitor: OpVisitor[T]) -> T:
  621. return visitor.visit_cast(self)
  622. class Box(RegisterOp):
  623. """box(type, src)
  624. This converts from a potentially unboxed representation to a straight Python object.
  625. Only supported for types with an unboxed representation.
  626. """
  627. error_kind = ERR_NEVER
  628. def __init__(self, src: Value, line: int = -1) -> None:
  629. super().__init__(line)
  630. self.src = src
  631. self.type = object_rprimitive
  632. # When we box None and bool values, we produce a borrowed result
  633. if (
  634. is_none_rprimitive(self.src.type)
  635. or is_bool_rprimitive(self.src.type)
  636. or is_bit_rprimitive(self.src.type)
  637. ):
  638. self.is_borrowed = True
  639. def sources(self) -> list[Value]:
  640. return [self.src]
  641. def stolen(self) -> list[Value]:
  642. return [self.src]
  643. def accept(self, visitor: OpVisitor[T]) -> T:
  644. return visitor.visit_box(self)
  645. class Unbox(RegisterOp):
  646. """unbox(type, src)
  647. This is similar to a cast, but it also changes to a (potentially) unboxed runtime
  648. representation. Only supported for types with an unboxed representation.
  649. """
  650. def __init__(self, src: Value, typ: RType, line: int) -> None:
  651. self.src = src
  652. self.type = typ
  653. if not typ.error_overlap:
  654. self.error_kind = ERR_MAGIC
  655. else:
  656. self.error_kind = ERR_MAGIC_OVERLAPPING
  657. super().__init__(line)
  658. def sources(self) -> list[Value]:
  659. return [self.src]
  660. def accept(self, visitor: OpVisitor[T]) -> T:
  661. return visitor.visit_unbox(self)
  662. class RaiseStandardError(RegisterOp):
  663. """Raise built-in exception with an optional error string.
  664. We have a separate opcode for this for convenience and to
  665. generate smaller, more idiomatic C code.
  666. """
  667. # TODO: Make it more explicit at IR level that this always raises
  668. error_kind = ERR_FALSE
  669. VALUE_ERROR: Final = "ValueError"
  670. ASSERTION_ERROR: Final = "AssertionError"
  671. STOP_ITERATION: Final = "StopIteration"
  672. UNBOUND_LOCAL_ERROR: Final = "UnboundLocalError"
  673. RUNTIME_ERROR: Final = "RuntimeError"
  674. NAME_ERROR: Final = "NameError"
  675. ZERO_DIVISION_ERROR: Final = "ZeroDivisionError"
  676. def __init__(self, class_name: str, value: str | Value | None, line: int) -> None:
  677. super().__init__(line)
  678. self.class_name = class_name
  679. self.value = value
  680. self.type = bool_rprimitive
  681. def sources(self) -> list[Value]:
  682. return []
  683. def accept(self, visitor: OpVisitor[T]) -> T:
  684. return visitor.visit_raise_standard_error(self)
  685. # True steals all arguments, False steals none, a list steals those in matching positions
  686. StealsDescription = Union[bool, List[bool]]
  687. class CallC(RegisterOp):
  688. """result = function(arg0, arg1, ...)
  689. Call a C function that is not a compiled/native function (for
  690. example, a Python C API function). Use Call to call native
  691. functions.
  692. """
  693. def __init__(
  694. self,
  695. function_name: str,
  696. args: list[Value],
  697. ret_type: RType,
  698. steals: StealsDescription,
  699. is_borrowed: bool,
  700. error_kind: int,
  701. line: int,
  702. var_arg_idx: int = -1,
  703. ) -> None:
  704. self.error_kind = error_kind
  705. super().__init__(line)
  706. self.function_name = function_name
  707. self.args = args
  708. self.type = ret_type
  709. self.steals = steals
  710. self.is_borrowed = is_borrowed
  711. # The position of the first variable argument in args (if >= 0)
  712. self.var_arg_idx = var_arg_idx
  713. def sources(self) -> list[Value]:
  714. return self.args
  715. def stolen(self) -> list[Value]:
  716. if isinstance(self.steals, list):
  717. assert len(self.steals) == len(self.args)
  718. return [arg for arg, steal in zip(self.args, self.steals) if steal]
  719. else:
  720. return [] if not self.steals else self.sources()
  721. def accept(self, visitor: OpVisitor[T]) -> T:
  722. return visitor.visit_call_c(self)
  723. class Truncate(RegisterOp):
  724. """result = truncate src from src_type to dst_type
  725. Truncate a value from type with more bits to type with less bits.
  726. dst_type and src_type can be native integer types, bools or tagged
  727. integers. Tagged integers should have the tag bit unset.
  728. """
  729. error_kind = ERR_NEVER
  730. def __init__(self, src: Value, dst_type: RType, line: int = -1) -> None:
  731. super().__init__(line)
  732. self.src = src
  733. self.type = dst_type
  734. self.src_type = src.type
  735. def sources(self) -> list[Value]:
  736. return [self.src]
  737. def stolen(self) -> list[Value]:
  738. return []
  739. def accept(self, visitor: OpVisitor[T]) -> T:
  740. return visitor.visit_truncate(self)
  741. class Extend(RegisterOp):
  742. """result = extend src from src_type to dst_type
  743. Extend a value from a type with fewer bits to a type with more bits.
  744. dst_type and src_type can be native integer types, bools or tagged
  745. integers. Tagged integers should have the tag bit unset.
  746. If 'signed' is true, perform sign extension. Otherwise, the result will be
  747. zero extended.
  748. """
  749. error_kind = ERR_NEVER
  750. def __init__(self, src: Value, dst_type: RType, signed: bool, line: int = -1) -> None:
  751. super().__init__(line)
  752. self.src = src
  753. self.type = dst_type
  754. self.src_type = src.type
  755. self.signed = signed
  756. def sources(self) -> list[Value]:
  757. return [self.src]
  758. def stolen(self) -> list[Value]:
  759. return []
  760. def accept(self, visitor: OpVisitor[T]) -> T:
  761. return visitor.visit_extend(self)
  762. class LoadGlobal(RegisterOp):
  763. """Load a low-level global variable/pointer.
  764. Note that can't be used to directly load Python module-level
  765. global variable, since they are stored in a globals dictionary
  766. and accessed using dictionary operations.
  767. """
  768. error_kind = ERR_NEVER
  769. is_borrowed = True
  770. def __init__(self, type: RType, identifier: str, line: int = -1, ann: object = None) -> None:
  771. super().__init__(line)
  772. self.identifier = identifier
  773. self.type = type
  774. self.ann = ann # An object to pretty print with the load
  775. def sources(self) -> list[Value]:
  776. return []
  777. def accept(self, visitor: OpVisitor[T]) -> T:
  778. return visitor.visit_load_global(self)
  779. class IntOp(RegisterOp):
  780. """Binary arithmetic or bitwise op on integer operands (e.g., r1 = r2 + r3).
  781. These ops are low-level and are similar to the corresponding C
  782. operations.
  783. The left and right values must have low-level integer types with
  784. compatible representations. Fixed-width integers, short_int_rprimitive,
  785. bool_rprimitive and bit_rprimitive are supported.
  786. For tagged (arbitrary-precision) integer ops look at mypyc.primitives.int_ops.
  787. """
  788. error_kind = ERR_NEVER
  789. # Arithmetic ops
  790. ADD: Final = 0
  791. SUB: Final = 1
  792. MUL: Final = 2
  793. DIV: Final = 3
  794. MOD: Final = 4
  795. # Bitwise ops
  796. AND: Final = 200
  797. OR: Final = 201
  798. XOR: Final = 202
  799. LEFT_SHIFT: Final = 203
  800. RIGHT_SHIFT: Final = 204
  801. op_str: Final = {
  802. ADD: "+",
  803. SUB: "-",
  804. MUL: "*",
  805. DIV: "/",
  806. MOD: "%",
  807. AND: "&",
  808. OR: "|",
  809. XOR: "^",
  810. LEFT_SHIFT: "<<",
  811. RIGHT_SHIFT: ">>",
  812. }
  813. def __init__(self, type: RType, lhs: Value, rhs: Value, op: int, line: int = -1) -> None:
  814. super().__init__(line)
  815. self.type = type
  816. self.lhs = lhs
  817. self.rhs = rhs
  818. self.op = op
  819. def sources(self) -> list[Value]:
  820. return [self.lhs, self.rhs]
  821. def accept(self, visitor: OpVisitor[T]) -> T:
  822. return visitor.visit_int_op(self)
  823. # We can't have this in the IntOp class body, because of
  824. # https://github.com/mypyc/mypyc/issues/932.
  825. int_op_to_id: Final = {op: op_id for op_id, op in IntOp.op_str.items()}
  826. class ComparisonOp(RegisterOp):
  827. """Low-level comparison op for integers and pointers.
  828. Both unsigned and signed comparisons are supported. Supports
  829. comparisons between fixed-width integer types and pointer types.
  830. The operands should have matching sizes.
  831. The result is always a bit (representing a boolean).
  832. Python semantics, such as calling __eq__, are not supported.
  833. """
  834. # Must be ERR_NEVER or ERR_FALSE. ERR_FALSE means that a false result
  835. # indicates that an exception has been raised and should be propagated.
  836. error_kind = ERR_NEVER
  837. # S for signed and U for unsigned
  838. EQ: Final = 100
  839. NEQ: Final = 101
  840. SLT: Final = 102
  841. SGT: Final = 103
  842. SLE: Final = 104
  843. SGE: Final = 105
  844. ULT: Final = 106
  845. UGT: Final = 107
  846. ULE: Final = 108
  847. UGE: Final = 109
  848. op_str: Final = {
  849. EQ: "==",
  850. NEQ: "!=",
  851. SLT: "<",
  852. SGT: ">",
  853. SLE: "<=",
  854. SGE: ">=",
  855. ULT: "<",
  856. UGT: ">",
  857. ULE: "<=",
  858. UGE: ">=",
  859. }
  860. signed_ops: Final = {"==": EQ, "!=": NEQ, "<": SLT, ">": SGT, "<=": SLE, ">=": SGE}
  861. unsigned_ops: Final = {"==": EQ, "!=": NEQ, "<": ULT, ">": UGT, "<=": ULE, ">=": UGE}
  862. def __init__(self, lhs: Value, rhs: Value, op: int, line: int = -1) -> None:
  863. super().__init__(line)
  864. self.type = bit_rprimitive
  865. self.lhs = lhs
  866. self.rhs = rhs
  867. self.op = op
  868. def sources(self) -> list[Value]:
  869. return [self.lhs, self.rhs]
  870. def accept(self, visitor: OpVisitor[T]) -> T:
  871. return visitor.visit_comparison_op(self)
  872. class FloatOp(RegisterOp):
  873. """Binary float arithmetic op (e.g., r1 = r2 + r3).
  874. These ops are low-level and are similar to the corresponding C
  875. operations (and somewhat different from Python operations).
  876. The left and right values must be floats.
  877. """
  878. error_kind = ERR_NEVER
  879. ADD: Final = 0
  880. SUB: Final = 1
  881. MUL: Final = 2
  882. DIV: Final = 3
  883. MOD: Final = 4
  884. op_str: Final = {ADD: "+", SUB: "-", MUL: "*", DIV: "/", MOD: "%"}
  885. def __init__(self, lhs: Value, rhs: Value, op: int, line: int = -1) -> None:
  886. super().__init__(line)
  887. self.type = float_rprimitive
  888. self.lhs = lhs
  889. self.rhs = rhs
  890. self.op = op
  891. def sources(self) -> list[Value]:
  892. return [self.lhs, self.rhs]
  893. def accept(self, visitor: OpVisitor[T]) -> T:
  894. return visitor.visit_float_op(self)
  895. # We can't have this in the FloatOp class body, because of
  896. # https://github.com/mypyc/mypyc/issues/932.
  897. float_op_to_id: Final = {op: op_id for op_id, op in FloatOp.op_str.items()}
  898. class FloatNeg(RegisterOp):
  899. """Float negation op (r1 = -r2)."""
  900. error_kind = ERR_NEVER
  901. def __init__(self, src: Value, line: int = -1) -> None:
  902. super().__init__(line)
  903. self.type = float_rprimitive
  904. self.src = src
  905. def sources(self) -> list[Value]:
  906. return [self.src]
  907. def accept(self, visitor: OpVisitor[T]) -> T:
  908. return visitor.visit_float_neg(self)
  909. class FloatComparisonOp(RegisterOp):
  910. """Low-level comparison op for floats."""
  911. error_kind = ERR_NEVER
  912. EQ: Final = 200
  913. NEQ: Final = 201
  914. LT: Final = 202
  915. GT: Final = 203
  916. LE: Final = 204
  917. GE: Final = 205
  918. op_str: Final = {EQ: "==", NEQ: "!=", LT: "<", GT: ">", LE: "<=", GE: ">="}
  919. def __init__(self, lhs: Value, rhs: Value, op: int, line: int = -1) -> None:
  920. super().__init__(line)
  921. self.type = bit_rprimitive
  922. self.lhs = lhs
  923. self.rhs = rhs
  924. self.op = op
  925. def sources(self) -> list[Value]:
  926. return [self.lhs, self.rhs]
  927. def accept(self, visitor: OpVisitor[T]) -> T:
  928. return visitor.visit_float_comparison_op(self)
  929. # We can't have this in the FloatOp class body, because of
  930. # https://github.com/mypyc/mypyc/issues/932.
  931. float_comparison_op_to_id: Final = {op: op_id for op_id, op in FloatComparisonOp.op_str.items()}
  932. class LoadMem(RegisterOp):
  933. """Read a memory location: result = *(type *)src.
  934. Attributes:
  935. type: Type of the read value
  936. src: Pointer to memory to read
  937. """
  938. error_kind = ERR_NEVER
  939. def __init__(self, type: RType, src: Value, line: int = -1) -> None:
  940. super().__init__(line)
  941. self.type = type
  942. # TODO: for now we enforce that the src memory address should be Py_ssize_t
  943. # later we should also support same width unsigned int
  944. assert is_pointer_rprimitive(src.type)
  945. self.src = src
  946. self.is_borrowed = True
  947. def sources(self) -> list[Value]:
  948. return [self.src]
  949. def accept(self, visitor: OpVisitor[T]) -> T:
  950. return visitor.visit_load_mem(self)
  951. class SetMem(Op):
  952. """Write to a memory location: *(type *)dest = src
  953. Attributes:
  954. type: Type of the written value
  955. dest: Pointer to memory to write
  956. src: Source value
  957. """
  958. error_kind = ERR_NEVER
  959. def __init__(self, type: RType, dest: Value, src: Value, line: int = -1) -> None:
  960. super().__init__(line)
  961. self.type = void_rtype
  962. self.dest_type = type
  963. self.src = src
  964. self.dest = dest
  965. def sources(self) -> list[Value]:
  966. return [self.src, self.dest]
  967. def stolen(self) -> list[Value]:
  968. return [self.src]
  969. def accept(self, visitor: OpVisitor[T]) -> T:
  970. return visitor.visit_set_mem(self)
  971. class GetElementPtr(RegisterOp):
  972. """Get the address of a struct element.
  973. Note that you may need to use KeepAlive to avoid the struct
  974. being freed, if it's reference counted, such as PyObject *.
  975. """
  976. error_kind = ERR_NEVER
  977. def __init__(self, src: Value, src_type: RType, field: str, line: int = -1) -> None:
  978. super().__init__(line)
  979. self.type = pointer_rprimitive
  980. self.src = src
  981. self.src_type = src_type
  982. self.field = field
  983. def sources(self) -> list[Value]:
  984. return [self.src]
  985. def accept(self, visitor: OpVisitor[T]) -> T:
  986. return visitor.visit_get_element_ptr(self)
  987. class LoadAddress(RegisterOp):
  988. """Get the address of a value: result = (type)&src
  989. Attributes:
  990. type: Type of the loaded address(e.g. ptr/object_ptr)
  991. src: Source value (str for globals like 'PyList_Type',
  992. Register for temporary values or locals, LoadStatic
  993. for statics.)
  994. """
  995. error_kind = ERR_NEVER
  996. is_borrowed = True
  997. def __init__(self, type: RType, src: str | Register | LoadStatic, line: int = -1) -> None:
  998. super().__init__(line)
  999. self.type = type
  1000. self.src = src
  1001. def sources(self) -> list[Value]:
  1002. if isinstance(self.src, Register):
  1003. return [self.src]
  1004. else:
  1005. return []
  1006. def accept(self, visitor: OpVisitor[T]) -> T:
  1007. return visitor.visit_load_address(self)
  1008. class KeepAlive(RegisterOp):
  1009. """A no-op operation that ensures source values aren't freed.
  1010. This is sometimes useful to avoid decref when a reference is still
  1011. being held but not seen by the compiler.
  1012. A typical use case is like this (C-like pseudocode):
  1013. ptr = &x.item
  1014. r = *ptr
  1015. keep_alive x # x must not be freed here
  1016. # x may be freed here
  1017. If we didn't have "keep_alive x", x could be freed immediately
  1018. after taking the address of 'item', resulting in a read after free
  1019. on the second line.
  1020. """
  1021. error_kind = ERR_NEVER
  1022. def __init__(self, src: list[Value]) -> None:
  1023. assert src
  1024. self.src = src
  1025. def sources(self) -> list[Value]:
  1026. return self.src.copy()
  1027. def accept(self, visitor: OpVisitor[T]) -> T:
  1028. return visitor.visit_keep_alive(self)
  1029. @trait
  1030. class OpVisitor(Generic[T]):
  1031. """Generic visitor over ops (uses the visitor design pattern)."""
  1032. @abstractmethod
  1033. def visit_goto(self, op: Goto) -> T:
  1034. raise NotImplementedError
  1035. @abstractmethod
  1036. def visit_branch(self, op: Branch) -> T:
  1037. raise NotImplementedError
  1038. @abstractmethod
  1039. def visit_return(self, op: Return) -> T:
  1040. raise NotImplementedError
  1041. @abstractmethod
  1042. def visit_unreachable(self, op: Unreachable) -> T:
  1043. raise NotImplementedError
  1044. @abstractmethod
  1045. def visit_assign(self, op: Assign) -> T:
  1046. raise NotImplementedError
  1047. @abstractmethod
  1048. def visit_assign_multi(self, op: AssignMulti) -> T:
  1049. raise NotImplementedError
  1050. @abstractmethod
  1051. def visit_load_error_value(self, op: LoadErrorValue) -> T:
  1052. raise NotImplementedError
  1053. @abstractmethod
  1054. def visit_load_literal(self, op: LoadLiteral) -> T:
  1055. raise NotImplementedError
  1056. @abstractmethod
  1057. def visit_get_attr(self, op: GetAttr) -> T:
  1058. raise NotImplementedError
  1059. @abstractmethod
  1060. def visit_set_attr(self, op: SetAttr) -> T:
  1061. raise NotImplementedError
  1062. @abstractmethod
  1063. def visit_load_static(self, op: LoadStatic) -> T:
  1064. raise NotImplementedError
  1065. @abstractmethod
  1066. def visit_init_static(self, op: InitStatic) -> T:
  1067. raise NotImplementedError
  1068. @abstractmethod
  1069. def visit_tuple_get(self, op: TupleGet) -> T:
  1070. raise NotImplementedError
  1071. @abstractmethod
  1072. def visit_tuple_set(self, op: TupleSet) -> T:
  1073. raise NotImplementedError
  1074. def visit_inc_ref(self, op: IncRef) -> T:
  1075. raise NotImplementedError
  1076. def visit_dec_ref(self, op: DecRef) -> T:
  1077. raise NotImplementedError
  1078. @abstractmethod
  1079. def visit_call(self, op: Call) -> T:
  1080. raise NotImplementedError
  1081. @abstractmethod
  1082. def visit_method_call(self, op: MethodCall) -> T:
  1083. raise NotImplementedError
  1084. @abstractmethod
  1085. def visit_cast(self, op: Cast) -> T:
  1086. raise NotImplementedError
  1087. @abstractmethod
  1088. def visit_box(self, op: Box) -> T:
  1089. raise NotImplementedError
  1090. @abstractmethod
  1091. def visit_unbox(self, op: Unbox) -> T:
  1092. raise NotImplementedError
  1093. @abstractmethod
  1094. def visit_raise_standard_error(self, op: RaiseStandardError) -> T:
  1095. raise NotImplementedError
  1096. @abstractmethod
  1097. def visit_call_c(self, op: CallC) -> T:
  1098. raise NotImplementedError
  1099. @abstractmethod
  1100. def visit_truncate(self, op: Truncate) -> T:
  1101. raise NotImplementedError
  1102. @abstractmethod
  1103. def visit_extend(self, op: Extend) -> T:
  1104. raise NotImplementedError
  1105. @abstractmethod
  1106. def visit_load_global(self, op: LoadGlobal) -> T:
  1107. raise NotImplementedError
  1108. @abstractmethod
  1109. def visit_int_op(self, op: IntOp) -> T:
  1110. raise NotImplementedError
  1111. @abstractmethod
  1112. def visit_comparison_op(self, op: ComparisonOp) -> T:
  1113. raise NotImplementedError
  1114. @abstractmethod
  1115. def visit_float_op(self, op: FloatOp) -> T:
  1116. raise NotImplementedError
  1117. @abstractmethod
  1118. def visit_float_neg(self, op: FloatNeg) -> T:
  1119. raise NotImplementedError
  1120. @abstractmethod
  1121. def visit_float_comparison_op(self, op: FloatComparisonOp) -> T:
  1122. raise NotImplementedError
  1123. @abstractmethod
  1124. def visit_load_mem(self, op: LoadMem) -> T:
  1125. raise NotImplementedError
  1126. @abstractmethod
  1127. def visit_set_mem(self, op: SetMem) -> T:
  1128. raise NotImplementedError
  1129. @abstractmethod
  1130. def visit_get_element_ptr(self, op: GetElementPtr) -> T:
  1131. raise NotImplementedError
  1132. @abstractmethod
  1133. def visit_load_address(self, op: LoadAddress) -> T:
  1134. raise NotImplementedError
  1135. @abstractmethod
  1136. def visit_keep_alive(self, op: KeepAlive) -> T:
  1137. raise NotImplementedError
  1138. # TODO: Should the following definition live somewhere else?
  1139. # We do a three-pass deserialization scheme in order to resolve name
  1140. # references.
  1141. # 1. Create an empty ClassIR for each class in an SCC.
  1142. # 2. Deserialize all of the functions, which can contain references
  1143. # to ClassIRs in their types
  1144. # 3. Deserialize all of the classes, which contain lots of references
  1145. # to the functions they contain. (And to other classes.)
  1146. #
  1147. # Note that this approach differs from how we deserialize ASTs in mypy itself,
  1148. # where everything is deserialized in one pass then a second pass cleans up
  1149. # 'cross_refs'. We don't follow that approach here because it seems to be more
  1150. # code for not a lot of gain since it is easy in mypyc to identify all the objects
  1151. # we might need to reference.
  1152. #
  1153. # Because of these references, we need to maintain maps from class
  1154. # names to ClassIRs and func IDs to FuncIRs.
  1155. #
  1156. # These are tracked in a DeserMaps which is passed to every
  1157. # deserialization function.
  1158. #
  1159. # (Serialization and deserialization *will* be used for incremental
  1160. # compilation but so far it is not hooked up to anything.)
  1161. class DeserMaps(NamedTuple):
  1162. classes: dict[str, "ClassIR"]
  1163. functions: dict[str, "FuncIR"]