this repo has no description
1# Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2class Opcode:
3 CMP_OP = (
4 "<",
5 "<=",
6 "==",
7 "!=",
8 ">",
9 ">=",
10 "in",
11 "not in",
12 "is",
13 "is not",
14 "exception match",
15 "BAD",
16 )
17 HAVE_ARGUMENT = 90 # Opcodes from here have an argument:
18 EXTENDED_ARG = 144
19 CODEUNIT_SIZE = 2
20
21 def __init__(self) -> None:
22 self.hasconst: set[int] = set()
23 self.hasname: set[int] = set()
24 self.hasjrel: set[int] = set()
25 self.hasjabs: set[int] = set()
26 self.haslocal: set[int] = set()
27 self.hascompare: set[int] = set()
28 self.hasfree: set[int] = set()
29 self.shadowop: set[int] = set()
30
31 self.opmap: dict[str, int] = {}
32 self.opname: list[str] = ["<%r>" % (op,) for op in range(256)]
33 self.stack_effects: dict[str, object] = {}
34
35 def stack_effect(self, opcode: int, oparg, jump: int) -> int: # pyre-ignore[2]
36 oparg_int = 0
37 if opcode >= self.HAVE_ARGUMENT:
38 if oparg is None:
39 raise ValueError(
40 "stack_effect: opcode requires oparg but oparg was not specified"
41 )
42 oparg_int = int(oparg)
43 elif oparg is not None:
44 raise ValueError(
45 "stack_effect: opcode does not permit oparg but oparg was specified"
46 )
47 jump_int = {None: -1, True: 1, False: 0}.get(jump) # pyre-ignore[6]
48 if jump_int is None:
49 raise ValueError("stack_effect: jump must be False, True or None")
50 opname = self.opname[opcode]
51 return self.stack_effect_raw(opname, oparg_int, jump_int)
52
53 def stack_effect_raw(self, opname: str, oparg, jump: int) -> int: # pyre-ignore[2]
54 effect = self.stack_effects.get(opname)
55 if effect is None:
56 raise ValueError(
57 f"Error, opcode {opname} was not found, please update opcode.stack_effects"
58 )
59 if isinstance(effect, int):
60 return effect
61 else:
62 return effect(oparg, jump) # pyre-ignore[29]
63
64 def def_op(self, name: str, op: int) -> None:
65 self.opname[op] = name
66 self.opmap[name] = op
67 setattr(self, name, op)
68
69 def name_op(self, name: str, op: int) -> None:
70 self.def_op(name, op)
71 self.hasname.add(op)
72
73 def jrel_op(self, name: str, op: int) -> None:
74 self.def_op(name, op)
75 self.hasjrel.add(op)
76
77 def jabs_op(self, name: str, op: int) -> None:
78 self.def_op(name, op)
79 self.hasjabs.add(op)
80
81 def has_jump(self, op: int) -> bool:
82 return op in self.hasjrel or op in self.hasjabs
83
84 def shadow_op(self, name: str, op: int) -> None:
85 self.def_op(name, op)
86 self.shadowop.add(op)
87
88 def remove_op(self, opname: str) -> None:
89 op = self.opmap[opname]
90 self.hasconst.discard(op)
91 self.hasname.discard(op)
92 self.hasjrel.discard(op)
93 self.hasjabs.discard(op)
94 self.haslocal.discard(op)
95 self.hascompare.discard(op)
96 self.hasfree.discard(op)
97 self.shadowop.discard(op)
98 self.opmap.pop(opname)
99 self.opname[op] = None # pyre-ignore[6]
100 self.stack_effects.pop(opname)
101 delattr(self, opname)
102
103 def copy(self) -> "Opcode":
104 result = Opcode()
105 result.hasconst = self.hasconst.copy()
106 result.hasname = self.hasname.copy()
107 result.hasjrel = self.hasjrel.copy()
108 result.hasjabs = self.hasjabs.copy()
109 result.haslocal = self.haslocal.copy()
110 result.hascompare = self.hascompare.copy()
111 result.hasfree = self.hasfree.copy()
112 result.shadowop = self.shadowop.copy()
113 result.opmap = self.opmap.copy()
114 result.opname = self.opname.copy()
115 result.stack_effects = self.stack_effects.copy()
116 for name, op in self.opmap.items():
117 setattr(result, name, op)
118 return result