11
11
import sys
12
12
13
13
import parser
14
- from parser import InstDef
14
+ from parser import InstDef # TODO: Use parser.InstDef
15
15
16
16
arg_parser = argparse .ArgumentParser ()
17
17
arg_parser .add_argument ("-i" , "--input" , type = str , default = "Python/bytecodes.c" )
@@ -29,19 +29,24 @@ def eopen(filename: str, mode: str = "r"):
29
29
return open (filename , mode )
30
30
31
31
32
- def parse_cases (src : str , filename : str | None = None ) -> tuple [list [InstDef ], list [parser .Family ]]:
32
+ def parse_cases (
33
+ src : str , filename : str | None = None
34
+ ) -> tuple [list [InstDef ], list [parser .Super ], list [parser .Family ]]:
33
35
psr = parser .Parser (src , filename = filename )
34
36
instrs : list [InstDef ] = []
37
+ supers : list [parser .Super ] = []
35
38
families : list [parser .Family ] = []
36
39
while not psr .eof ():
37
40
if inst := psr .inst_def ():
38
41
assert inst .block
39
- instrs .append (InstDef (inst .name , inst .inputs , inst .outputs , inst .block ))
42
+ instrs .append (inst )
43
+ elif sup := psr .super_def ():
44
+ supers .append (sup )
40
45
elif fam := psr .family_def ():
41
46
families .append (fam )
42
47
else :
43
48
raise psr .make_syntax_error (f"Unexpected token" )
44
- return instrs , families
49
+ return instrs , supers , families
45
50
46
51
47
52
def always_exits (block : parser .Block ) -> bool :
@@ -62,16 +67,18 @@ def always_exits(block: parser.Block) -> bool:
62
67
return line .startswith (("goto " , "return " , "DISPATCH" , "GO_TO_" , "Py_UNREACHABLE()" ))
63
68
64
69
65
- def write_cases (f : io .TextIOBase , instrs : list [InstDef ]):
70
+ def write_cases (f : io .TextIOBase , instrs : list [InstDef ], supers : list [ parser . Super ] ):
66
71
predictions = set ()
67
72
for inst in instrs :
68
73
for target in re .findall (r"(?:PREDICT|GO_TO_INSTRUCTION)\((\w+)\)" , inst .block .text ):
69
74
predictions .add (target )
70
75
indent = " "
71
76
f .write (f"// This file is generated by { os .path .relpath (__file__ )} \n " )
72
77
f .write ("// Do not edit!\n " )
78
+ instr_index : dict [str , InstDef ] = {}
73
79
for instr in instrs :
74
80
assert isinstance (instr , InstDef )
81
+ instr_index [instr .name ] = instr
75
82
f .write (f"\n { indent } TARGET({ instr .name } ) {{\n " )
76
83
if instr .name in predictions :
77
84
f .write (f"{ indent } PREDICTED({ instr .name } );\n " )
@@ -102,6 +109,22 @@ def write_cases(f: io.TextIOBase, instrs: list[InstDef]):
102
109
# Write trailing '}'
103
110
f .write (f"{ indent } }}\n " )
104
111
112
+ for sup in supers :
113
+ assert isinstance (sup , parser .Super )
114
+ components = [instr_index [name ] for name in sup .ops ]
115
+ f .write (f"\n { indent } TARGET({ sup .name } ) {{\n " )
116
+ for i , instr in enumerate (components ):
117
+ if i > 0 :
118
+ f .write (f"{ indent } NEXTOPARG();\n " )
119
+ f .write (f"{ indent } next_instr++;\n " )
120
+ text = instr .block .to_text (- 4 )
121
+ textlines = text .splitlines (True )
122
+ textlines = [line for line in textlines if not line .strip ().startswith ("PREDICTED(" )]
123
+ text = "" .join (textlines )
124
+ f .write (f"{ indent } { text .strip ()} \n " )
125
+ f .write (f"{ indent } DISPATCH();\n " )
126
+ f .write (f"{ indent } }}\n " )
127
+
105
128
106
129
def main ():
107
130
args = arg_parser .parse_args ()
@@ -110,21 +133,22 @@ def main():
110
133
begin = srclines .index ("// BEGIN BYTECODES //" )
111
134
end = srclines .index ("// END BYTECODES //" )
112
135
src = "\n " .join (srclines [begin + 1 : end ])
113
- instrs , families = parse_cases (src , filename = args .input )
114
- ninstrs = nfamilies = 0
136
+ instrs , supers , families = parse_cases (src , filename = args .input )
137
+ ninstrs = nsupers = nfamilies = 0
115
138
if not args .quiet :
116
139
ninstrs = len (instrs )
140
+ nsupers = len (supers )
117
141
nfamilies = len (families )
118
142
print (
119
- f"Read { ninstrs } instructions "
143
+ f"Read { ninstrs } instructions, { nsupers } supers, "
120
144
f"and { nfamilies } families from { args .input } " ,
121
145
file = sys .stderr ,
122
146
)
123
147
with eopen (args .output , "w" ) as f :
124
- write_cases (f , instrs )
148
+ write_cases (f , instrs , supers )
125
149
if not args .quiet :
126
150
print (
127
- f"Wrote { ninstrs } instructions to { args .output } " ,
151
+ f"Wrote { ninstrs + nsupers } instructions to { args .output } " ,
128
152
file = sys .stderr ,
129
153
)
130
154
0 commit comments