Attempt to analyze `goto`. Looks like it'll need some rewriting.
Chris Pressey
6 years ago
255 | 255 |
context.set_unmeaningful(REG_A, FLAG_Z, FLAG_N)
|
256 | 256 |
elif opcode == 'with-sei':
|
257 | 257 |
analyze_block(instr.block, context, routines)
|
|
258 |
elif opcode == 'goto':
|
|
259 |
location = instr.location
|
|
260 |
type = location.type
|
|
261 |
|
|
262 |
if not isinstance(type, ExecutableType):
|
|
263 |
raise TypeMismatchError(location)
|
|
264 |
|
|
265 |
# assert that the dest routine's inputs are all initialized
|
|
266 |
for ref in type.inputs:
|
|
267 |
context.assert_meaningful(ref)
|
|
268 |
|
|
269 |
# and that the called routine's output constraints are a
|
|
270 |
# superset of this routine's
|
|
271 |
current_type = self.current_routine.type
|
|
272 |
if not (current_type.outputs <= type.outputs):
|
|
273 |
raise IncompatibleConstraintsError(current_type.outputs - type.outputs)
|
|
274 |
if not (current_type.trashes <= type.trashes):
|
|
275 |
raise IncompatibleConstraintsError(current_type.trashes - type.trashes)
|
258 | 276 |
else:
|
259 | 277 |
raise NotImplementedError(opcode)
|
1147 | 1147 |
| call foo
|
1148 | 1148 |
| }
|
1149 | 1149 |
? UninitializedOutputError: x
|
|
1150 |
|
|
1151 |
`goto`, if present, must be the final instruction in a routine.
|
|
1152 |
|
|
1153 |
| routine bar trashes x, z, n {
|
|
1154 |
| ld x, 200
|
|
1155 |
| }
|
|
1156 |
|
|
|
1157 |
| routine main trashes x, z, n {
|
|
1158 |
| ld x, 0
|
|
1159 |
| goto bar
|
|
1160 |
| }
|
|
1161 |
= ok
|
|
1162 |
|
|
1163 |
| routine bar trashes x, z, n {
|
|
1164 |
| ld x, 200
|
|
1165 |
| }
|
|
1166 |
|
|
|
1167 |
| routine main trashes x, z, n {
|
|
1168 |
| goto bar
|
|
1169 |
| ld x, 0
|
|
1170 |
| }
|
|
1171 |
? IllegalJumpError
|
|
1172 |
|
|
1173 |
| routine bar trashes x, z, n {
|
|
1174 |
| ld x, 200
|
|
1175 |
| }
|
|
1176 |
|
|
|
1177 |
| routine main trashes x, z, n {
|
|
1178 |
| ld x, 0
|
|
1179 |
| if z {
|
|
1180 |
| ld x, 1
|
|
1181 |
| goto bar
|
|
1182 |
| }
|
|
1183 |
| }
|
|
1184 |
? IllegalJumpError
|
|
1185 |
|
|
1186 |
Can't `goto` a routine that outputs or trashes more than the current routine.
|
|
1187 |
|
|
1188 |
| routine bar trashes x, y, z, n {
|
|
1189 |
| ld x, 200
|
|
1190 |
| ld y, 200
|
|
1191 |
| }
|
|
1192 |
|
|
|
1193 |
| routine main trashes x, z, n {
|
|
1194 |
| ld x, 0
|
|
1195 |
| goto bar
|
|
1196 |
| }
|
|
1197 |
? IllegalWriteError: y
|
|
1198 |
|
|
1199 |
| routine bar outputs y trashes z, n {
|
|
1200 |
| ld y, 200
|
|
1201 |
| }
|
|
1202 |
|
|
|
1203 |
| routine main trashes x, z, n {
|
|
1204 |
| ld x, 0
|
|
1205 |
| goto bar
|
|
1206 |
| }
|
|
1207 |
? IllegalWriteError: y
|