Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pyvex/stmt.py: 66%

447 statements  

« prev     ^ index     » next       coverage.py v7.3.1, created at 2023-09-25 06:15 +0000

1import logging 

2from typing import Iterator, Optional 

3 

4from archinfo import RegisterOffset, TmpVar 

5 

6from . import expr 

7from .const import IRConst 

8from .enums import IRCallee, IRRegArray, VEXObject, get_enum_from_int, get_int_from_enum 

9from .errors import PyVEXError 

10from .expr import Const, Get, IRExpr 

11from .native import ffi, pvc 

12 

13log = logging.getLogger("pyvex.stmt") 

14 

15 

16class IRStmt(VEXObject): 

17 """ 

18 IR statements in VEX represents operations with side-effects. 

19 """ 

20 

21 tag: Optional[str] = None 

22 tag_int = 0 # set automatically at bottom of file 

23 

24 __slots__ = [] 

25 

26 def pp(self): 

27 print(self.__str__()) 

28 

29 @property 

30 def child_expressions(self) -> Iterator["IRExpr"]: 

31 for k in self.__slots__: 

32 v = getattr(self, k) 

33 if isinstance(v, IRExpr): 

34 # return itself 

35 yield v 

36 # return all the child expressions 

37 yield from v.child_expressions 

38 

39 # ??? 

40 @property 

41 def expressions(self): 

42 return self.child_expressions 

43 

44 @property 

45 def constants(self): 

46 return sum((e.constants for e in self.expressions), []) 

47 

48 @staticmethod 

49 def _from_c(c_stmt): 

50 if c_stmt[0] == ffi.NULL: 

51 return None 

52 

53 try: 

54 stmt_class = enum_to_stmt_class(c_stmt.tag)._from_c(c_stmt) 

55 except KeyError: 

56 raise PyVEXError("Unknown/unsupported IRStmtTag %s.\n" % get_enum_from_int(c_stmt.tag)) 

57 return stmt_class._from_c(c_stmt) 

58 

59 def typecheck(self, tyenv): # pylint: disable=unused-argument,no-self-use 

60 return True 

61 

62 def replace_expression(self, replacements): 

63 """ 

64 Replace child expressions in-place. 

65 

66 :param Dict[IRExpr, IRExpr] replacements: A mapping from expression-to-find to expression-to-replace-with 

67 :return: None 

68 """ 

69 

70 for k in self.__slots__: 

71 v = getattr(self, k) 

72 if isinstance(v, IRExpr) and v in replacements: 

73 setattr(self, k, replacements.get(v)) 

74 elif isinstance(v, IRExpr): 

75 v.replace_expression(replacements) 

76 elif type(v) is tuple: 

77 # Rebuild the tuple 

78 _lst = [] 

79 replaced = False 

80 for expr_ in v: 

81 if isinstance(expr_, IRExpr) and expr_ in replacements: 

82 _lst.append(replacements.get(expr_)) 

83 replaced = True 

84 else: 

85 _lst.append(expr_) 

86 if replaced: 

87 setattr(self, k, tuple(_lst)) 

88 

89 def __str__(self, reg_name=None, arch=None, tyenv=None): 

90 raise NotImplementedError() 

91 

92 

93class NoOp(IRStmt): 

94 """ 

95 A no-operation statement. It is usually the result of an IR optimization. 

96 """ 

97 

98 __slots__ = [] 

99 

100 tag = "Ist_NoOp" 

101 

102 def __str__(self, reg_name=None, arch=None, tyenv=None): 

103 return "IR-NoOp" 

104 

105 @staticmethod 

106 def _from_c(c_stmt): 

107 return NoOp() 

108 

109 

110class IMark(IRStmt): 

111 """ 

112 An instruction mark. It marks the start of the statements that represent a single machine instruction (the end of 

113 those statements is marked by the next IMark or the end of the IRSB). Contains the address and length of the 

114 instruction. 

115 """ 

116 

117 __slots__ = ["addr", "len", "delta"] 

118 

119 tag = "Ist_IMark" 

120 

121 def __init__(self, addr: int, length: int, delta: int): 

122 self.addr = addr 

123 self.len = length 

124 self.delta = delta 

125 

126 def __str__(self, reg_name=None, arch=None, tyenv=None): 

127 return "------ IMark(0x%x, %d, %d) ------" % (self.addr, self.len, self.delta) 

128 

129 @staticmethod 

130 def _from_c(c_stmt): 

131 return IMark(c_stmt.Ist.IMark.addr, c_stmt.Ist.IMark.len, c_stmt.Ist.IMark.delta) 

132 

133 

134class AbiHint(IRStmt): 

135 """ 

136 An ABI hint, provides specific information about this platform's ABI. 

137 """ 

138 

139 __slots__ = ["base", "len", "nia"] 

140 

141 tag = "Ist_AbiHint" 

142 

143 def __init__(self, base, length, nia): 

144 self.base = base 

145 self.len = length 

146 self.nia = nia 

147 

148 def __str__(self, reg_name=None, arch=None, tyenv=None): 

149 return "====== AbiHint(0x%s, %d, %s) ======" % (self.base, self.len, self.nia) 

150 

151 @staticmethod 

152 def _from_c(c_stmt): 

153 return AbiHint( 

154 IRExpr._from_c(c_stmt.Ist.AbiHint.base), c_stmt.Ist.AbiHint.len, IRExpr._from_c(c_stmt.Ist.AbiHint.nia) 

155 ) 

156 

157 

158class Put(IRStmt): 

159 """ 

160 Write to a guest register, at a fixed offset in the guest state. 

161 """ 

162 

163 __slots__ = ["data", "offset"] 

164 

165 tag = "Ist_Put" 

166 

167 def __init__(self, data: "IRExpr", offset: RegisterOffset): 

168 self.data = data 

169 self.offset = offset 

170 

171 ## TODO: Check if result_size and arch are available before looking of arch register name 

172 def __str__(self, reg_name=None, arch=None, tyenv=None): 

173 if arch is not None and tyenv is not None: 

174 reg_name = arch.translate_register_name(self.offset, self.data.result_size(tyenv) // 8) 

175 

176 if reg_name is not None: 

177 return f"PUT({reg_name}) = {self.data}" 

178 else: 

179 return f"PUT(offset={self.offset}) = {self.data}" 

180 

181 @staticmethod 

182 def _from_c(c_stmt): 

183 return Put(IRExpr._from_c(c_stmt.Ist.Put.data), c_stmt.Ist.Put.offset) 

184 

185 def typecheck(self, tyenv): 

186 return self.data.typecheck(tyenv) 

187 

188 

189class PutI(IRStmt): 

190 """ 

191 Write to a guest register, at a non-fixed offset in the guest state. 

192 """ 

193 

194 __slots__ = ["descr", "ix", "data", "bias"] 

195 

196 tag = "Ist_PutI" 

197 

198 def __init__(self, descr, ix, data, bias): 

199 self.descr = descr 

200 self.ix = ix 

201 self.data = data 

202 self.bias = bias 

203 

204 def __str__(self, reg_name=None, arch=None, tyenv=None): 

205 return "PutI(%s)[%s,%d] = %s" % (self.descr, self.ix, self.bias, self.data) 

206 

207 @staticmethod 

208 def _from_c(c_stmt): 

209 return PutI( 

210 IRRegArray._from_c(c_stmt.Ist.PutI.details.descr), 

211 IRExpr._from_c(c_stmt.Ist.PutI.details.ix), 

212 IRExpr._from_c(c_stmt.Ist.PutI.details.data), 

213 c_stmt.Ist.PutI.details.bias, 

214 ) 

215 

216 def typecheck(self, tyenv): 

217 dataty = self.data.typecheck(tyenv) 

218 if dataty is None: 

219 return False 

220 if dataty != self.descr.elemTy: 

221 log.debug("Expression doesn't match RegArray type") 

222 return False 

223 return True 

224 

225 

226class WrTmp(IRStmt): 

227 """ 

228 Assign a value to a temporary. Note that SSA rules require each tmp is only assigned to once. IR sanity checking 

229 will reject any block containing a temporary which is not assigned to exactly once. 

230 """ 

231 

232 __slots__ = ["data", "tmp"] 

233 

234 tag = "Ist_WrTmp" 

235 

236 def __init__(self, tmp: TmpVar, data: "IRExpr"): 

237 self.tmp = tmp 

238 self.data = data 

239 

240 def __str__(self, reg_name=None, arch=None, tyenv=None): 

241 # Support for named register in string representation of expr.Get 

242 

243 if arch is not None and tyenv is not None and isinstance(self.data, Get): 

244 reg_name = arch.translate_register_name(self.data.offset, self.data.result_size(tyenv) // 8) 

245 

246 if reg_name is not None and isinstance(self.data, expr.Get): 

247 return "t%d = %s" % (self.tmp, self.data.__str__(reg_name=reg_name)) 

248 else: 

249 return "t%d = %s" % (self.tmp, self.data) 

250 

251 @staticmethod 

252 def _from_c(c_stmt): 

253 return WrTmp(c_stmt.Ist.WrTmp.tmp, IRExpr._from_c(c_stmt.Ist.WrTmp.data)) 

254 

255 def typecheck(self, tyenv): 

256 dataty = self.data.typecheck(tyenv) 

257 if dataty is None: 

258 return False 

259 if dataty != tyenv.lookup(self.tmp): 

260 log.debug("Expression doesn't match tmp type") 

261 return False 

262 return True 

263 

264 

265class Store(IRStmt): 

266 """ 

267 Write a value to memory.. 

268 """ 

269 

270 __slots__ = ["addr", "data", "end"] 

271 

272 tag = "Ist_Store" 

273 

274 def __init__(self, addr: "IRExpr", data: "IRExpr", end: str): 

275 self.addr = addr 

276 self.data = data 

277 self.end = end 

278 

279 @property 

280 def endness(self): 

281 return self.end 

282 

283 def __str__(self, reg_name=None, arch=None, tyenv=None): 

284 return f"ST{self.endness[-2:].lower()}({self.addr}) = {self.data}" 

285 

286 @staticmethod 

287 def _from_c(c_stmt): 

288 return Store( 

289 IRExpr._from_c(c_stmt.Ist.Store.addr), 

290 IRExpr._from_c(c_stmt.Ist.Store.data), 

291 get_enum_from_int(c_stmt.Ist.Store.end), 

292 ) 

293 

294 def typecheck(self, tyenv): 

295 dataty = self.data.typecheck(tyenv) 

296 if dataty is None: 

297 return False 

298 addrty = self.addr.typecheck(tyenv) 

299 if addrty is None: 

300 return False 

301 if addrty != tyenv.wordty: 

302 log.debug("addr must be full word for arch") 

303 return False 

304 if self.end not in ("Iend_LE", "Iend_BE"): 

305 log.debug("invalid endness enum") 

306 return False 

307 return True 

308 

309 

310class CAS(IRStmt): 

311 """ 

312 an atomic compare-and-swap operation. 

313 """ 

314 

315 __slots__ = ["addr", "dataLo", "dataHi", "expdLo", "expdHi", "oldLo", "oldHi", "end"] 

316 

317 tag = "Ist_CAS" 

318 

319 def __init__(self, addr, dataLo, dataHi, expdLo, expdHi, oldLo, oldHi, end): 

320 self.addr = addr 

321 self.dataLo = dataLo 

322 self.dataHi = dataHi 

323 self.expdLo = expdLo 

324 self.expdHi = expdHi 

325 self.oldLo = oldLo 

326 self.oldHi = oldHi 

327 self.end = end 

328 

329 @property 

330 def endness(self): 

331 return self.end 

332 

333 def __str__(self, reg_name=None, arch=None, tyenv=None): 

334 return "t({},{}) = CAS{}({} :: ({},{})->({},{}))".format( 

335 self.oldLo, self.oldHi, self.end[-2:].lower(), self.addr, self.expdLo, self.expdHi, self.dataLo, self.dataHi 

336 ) 

337 

338 @staticmethod 

339 def _from_c(c_stmt): 

340 return CAS( 

341 IRExpr._from_c(c_stmt.Ist.CAS.details.addr), 

342 IRExpr._from_c(c_stmt.Ist.CAS.details.dataLo), 

343 IRExpr._from_c(c_stmt.Ist.CAS.details.dataHi), 

344 IRExpr._from_c(c_stmt.Ist.CAS.details.expdLo), 

345 IRExpr._from_c(c_stmt.Ist.CAS.details.expdHi), 

346 c_stmt.Ist.CAS.details.oldLo, 

347 c_stmt.Ist.CAS.details.oldHi, 

348 get_enum_from_int(c_stmt.Ist.CAS.details.end), 

349 ) 

350 

351 def typecheck(self, tyenv): 

352 addrty = self.addr.typecheck(tyenv) 

353 if addrty is None: 

354 return False 

355 if addrty != tyenv.wordty: 

356 log.debug("addr must be full word for arch") 

357 return False 

358 if self.end not in ("Iend_LE", "Iend_BE"): 

359 log.debug("invalid endness enum") 

360 return False 

361 

362 if self.oldHi == 0xFFFFFFFF: 

363 # single-element case 

364 if self.expdHi is not None or self.dataHi is not None: 

365 log.debug("expdHi and dataHi must be None") 

366 return False 

367 expdLoTy = self.expdLo.typecheck(tyenv) 

368 dataLoTy = self.dataLo.typecheck(tyenv) 

369 if expdLoTy is None or dataLoTy is None: 

370 return False 

371 if tyenv.lookup(self.oldLo) != expdLoTy or expdLoTy != dataLoTy: 

372 log.debug("oldLo, expdL, dataLo must all have the same type") 

373 return False 

374 else: 

375 # double-element case 

376 expdLoTy = self.expdLo.typecheck(tyenv) 

377 dataLoTy = self.dataLo.typecheck(tyenv) 

378 expdHiTy = self.expdHi.typecheck(tyenv) 

379 dataHiTy = self.dataHi.typecheck(tyenv) 

380 if expdLoTy is None or dataLoTy is None or expdHiTy is None or dataHiTy is None: 

381 return False 

382 if ( 

383 tyenv.lookup(self.oldLo) != expdLoTy 

384 or expdLoTy != dataLoTy 

385 or tyenv.lookup(self.oldHi) != expdHiTy 

386 or expdHiTy != dataHiTy 

387 or expdLoTy != expdHiTy 

388 ): 

389 log.debug("oldLo, expdLo, dataLo, oldHi, expdHi, dataHi must all have the same type") 

390 return False 

391 

392 return True 

393 

394 

395class LLSC(IRStmt): 

396 """ 

397 Either Load-Linked or Store-Conditional, depending on STOREDATA. If STOREDATA is NULL then this is a Load-Linked, 

398 else it is a Store-Conditional. 

399 """ 

400 

401 __slots__ = ["addr", "storedata", "result", "end"] 

402 

403 tag = "Ist_LLSC" 

404 

405 def __init__(self, addr, storedata, result, end): 

406 self.addr = addr 

407 self.storedata = storedata 

408 self.result = result 

409 self.end = end 

410 

411 @property 

412 def endness(self): 

413 return self.end 

414 

415 def __str__(self, reg_name=None, arch=None, tyenv=None): 

416 if self.storedata is None: 

417 return "t%d = LD%s-Linked(%s)" % (self.result, self.end[-2:].lower(), self.addr) 

418 else: 

419 return "t%d = ( ST%s-Cond(%s) = %s )" % (self.result, self.end[-2:].lower(), self.addr, self.storedata) 

420 

421 @staticmethod 

422 def _from_c(c_stmt): 

423 return LLSC( 

424 IRExpr._from_c(c_stmt.Ist.LLSC.addr), 

425 IRExpr._from_c(c_stmt.Ist.LLSC.storedata), 

426 c_stmt.Ist.LLSC.result, 

427 get_enum_from_int(c_stmt.Ist.LLSC.end), 

428 ) 

429 

430 def typecheck(self, tyenv): 

431 addrty = self.addr.typecheck(tyenv) 

432 if addrty is None: 

433 return False 

434 if addrty != tyenv.wordty: 

435 log.debug("addr must be full word for arch") 

436 return False 

437 if self.end not in ("Iend_LE", "Iend_BE"): 

438 log.debug("invalid endness enum") 

439 return False 

440 

441 if self.storedata is not None: 

442 # load-linked 

443 storety = self.storedata.typecheck(tyenv) 

444 if storety is None: 

445 return False 

446 

447 if tyenv.lookup(self.result) != "Ity_I1": 

448 log.debug("result tmp must be Ity_I1") 

449 return False 

450 

451 return True 

452 

453 

454class MBE(IRStmt): 

455 __slots__ = ["event"] 

456 

457 tag = "Ist_MBE" 

458 

459 def __init__(self, event): 

460 self.event = event 

461 

462 def __str__(self, reg_name=None, arch=None, tyenv=None): 

463 return "MBusEvent-" + self.event 

464 

465 @staticmethod 

466 def _from_c(c_stmt): 

467 return MBE(get_enum_from_int(c_stmt.Ist.MBE.event)) 

468 

469 

470class Dirty(IRStmt): 

471 __slots__ = ["cee", "guard", "args", "tmp", "mFx", "mAddr", "mSize", "nFxState"] 

472 

473 tag = "Ist_Dirty" 

474 

475 def __init__(self, cee, guard, args, tmp, mFx, mAddr, mSize, nFxState): 

476 self.cee = cee 

477 self.guard = guard 

478 self.args = tuple(args) 

479 self.tmp = tmp 

480 self.mFx = mFx 

481 self.mAddr = mAddr 

482 self.mSize = mSize 

483 self.nFxState = nFxState 

484 

485 def __str__(self, reg_name=None, arch=None, tyenv=None): 

486 return "t{} = DIRTY {} {} ::: {}({})".format( 

487 self.tmp, self.guard, "TODO(effects)", self.cee, ",".join(str(a) for a in self.args) 

488 ) 

489 

490 @property 

491 def child_expressions(self): 

492 expressions = sum((a.child_expressions for a in self.args), []) 

493 expressions.extend(self.args) 

494 expressions.append(self.guard) 

495 expressions.extend(self.guard.child_expressions) 

496 return expressions 

497 

498 @staticmethod 

499 def _from_c(c_stmt): 

500 args = [] 

501 for i in range(20): 

502 a = c_stmt.Ist.Dirty.details.args[i] 

503 if a == ffi.NULL: 

504 break 

505 

506 args.append(IRExpr._from_c(a)) 

507 

508 return Dirty( 

509 IRCallee._from_c(c_stmt.Ist.Dirty.details.cee), 

510 IRExpr._from_c(c_stmt.Ist.Dirty.details.guard), 

511 tuple(args), 

512 c_stmt.Ist.Dirty.details.tmp, 

513 get_enum_from_int(c_stmt.Ist.Dirty.details.mFx), 

514 IRExpr._from_c(c_stmt.Ist.Dirty.details.mAddr), 

515 c_stmt.Ist.Dirty.details.mSize, 

516 c_stmt.Ist.Dirty.details.nFxState, 

517 ) 

518 

519 

520class Exit(IRStmt): 

521 """ 

522 A conditional exit from the middle of an IRSB. 

523 """ 

524 

525 __slots__ = ["guard", "dst", "offsIP", "jk"] 

526 

527 tag = "Ist_Exit" 

528 

529 def __init__(self, guard, dst, jk, offsIP): 

530 self.guard = guard 

531 self.dst = dst 

532 self.offsIP = offsIP 

533 self.jk = jk 

534 

535 @property 

536 def jumpkind(self): 

537 return self.jk 

538 

539 def __str__(self, reg_name=None, arch=None, tyenv=None): 

540 if arch is not None and tyenv is not None: 

541 reg_name = arch.translate_register_name(self.offsIP, arch.bits // 8) 

542 

543 if reg_name is None: 

544 return "if (%s) { PUT(offset=%d) = %#x; %s }" % (self.guard, self.offsIP, self.dst.value, self.jumpkind) 

545 else: 

546 return f"if ({self.guard}) {{ PUT({reg_name}) = {self.dst.value:#x}; {self.jumpkind} }}" 

547 

548 @property 

549 def child_expressions(self): 

550 return [self.guard] + self.guard.child_expressions + [Const(self.dst)] 

551 

552 @staticmethod 

553 def _from_c(c_stmt): 

554 return Exit( 

555 IRExpr._from_c(c_stmt.Ist.Exit.guard), 

556 IRConst._from_c(c_stmt.Ist.Exit.dst), 

557 get_enum_from_int(c_stmt.Ist.Exit.jk), 

558 c_stmt.Ist.Exit.offsIP, 

559 ) 

560 

561 def typecheck(self, tyenv): 

562 if not self.jk.startswith("Ijk_"): 

563 log.debug("Jumpkind is not a jumpkind enum") 

564 return False 

565 guardty = self.guard.typecheck(tyenv) 

566 if guardty is None: 

567 return False 

568 if guardty != "Ity_I1": 

569 log.debug("guard must be Ity_I1") 

570 return False 

571 return True 

572 

573 

574class LoadG(IRStmt): 

575 """ 

576 A guarded load. 

577 """ 

578 

579 __slots__ = ["addr", "alt", "guard", "dst", "cvt", "end", "cvt_types"] 

580 

581 tag = "Ist_LoadG" 

582 

583 def __init__(self, end, cvt, dst, addr, alt, guard): 

584 self.addr = addr 

585 self.alt = alt 

586 self.guard = guard 

587 self.dst = dst 

588 self.cvt = cvt 

589 self.end = end 

590 

591 type_in = ffi.new("IRType *") # TODO separate this from the pyvex C implementation 

592 type_out = ffi.new("IRType *") 

593 pvc.typeOfIRLoadGOp(get_int_from_enum(self.cvt), type_out, type_in) 

594 type_in = ffi.cast("int *", type_in)[0] 

595 type_out = ffi.cast("int *", type_out)[0] 

596 self.cvt_types = (get_enum_from_int(type_in), get_enum_from_int(type_out)) 

597 

598 @property 

599 def endness(self): 

600 return self.end 

601 

602 def __str__(self, reg_name=None, arch=None, tyenv=None): 

603 return "t%d = if (%s) %s(LD%s(%s)) else %s" % ( 

604 self.dst, 

605 self.guard, 

606 self.cvt, 

607 self.end[-2:].lower(), 

608 self.addr, 

609 self.alt, 

610 ) 

611 

612 @staticmethod 

613 def _from_c(c_stmt): 

614 return LoadG( 

615 get_enum_from_int(c_stmt.Ist.LoadG.details.end), 

616 get_enum_from_int(c_stmt.Ist.LoadG.details.cvt), 

617 c_stmt.Ist.LoadG.details.dst, 

618 IRExpr._from_c(c_stmt.Ist.LoadG.details.addr), 

619 IRExpr._from_c(c_stmt.Ist.LoadG.details.alt), 

620 IRExpr._from_c(c_stmt.Ist.LoadG.details.guard), 

621 ) 

622 

623 def typecheck(self, tyenv): 

624 addrty = self.addr.typecheck(tyenv) 

625 if addrty is None: 

626 return False 

627 if addrty != tyenv.wordty: 

628 log.debug("addr must be full word for arch") 

629 return False 

630 if self.end not in ("Iend_LE", "Iend_BE"): 

631 log.debug("invalid endness enum") 

632 return False 

633 

634 dstty = tyenv.lookup(self.dst) 

635 guardty = self.guard.typecheck(tyenv) 

636 altty = self.alt.typecheck(tyenv) 

637 

638 if guardty is None or altty is None: 

639 return False 

640 if dstty != "Ity_I32" or altty != "Ity_I32": 

641 log.debug("dst and alt must be Ity_I32") 

642 return False 

643 if guardty != "Ity_I1": 

644 log.debug("guard must be Ity_I1") 

645 return False 

646 if not self.cvt.startswith("ILGop_"): 

647 log.debug("Invalid cvt enum") 

648 return False 

649 return True 

650 

651 

652class StoreG(IRStmt): 

653 """ 

654 A guarded store. 

655 """ 

656 

657 __slots__ = ["addr", "data", "guard", "end"] 

658 

659 tag = "Ist_StoreG" 

660 

661 def __init__(self, end, addr, data, guard): 

662 self.addr = addr 

663 self.data = data 

664 self.guard = guard 

665 self.end = end 

666 

667 @property 

668 def endness(self): 

669 return self.end 

670 

671 def __str__(self, reg_name=None, arch=None, tyenv=None): 

672 return f"if ({self.guard}) ST{self.end[-2:].lower()}({self.addr}) = {self.data}" 

673 

674 @staticmethod 

675 def _from_c(c_stmt): 

676 return StoreG( 

677 get_enum_from_int(c_stmt.Ist.StoreG.details.end), 

678 IRExpr._from_c(c_stmt.Ist.StoreG.details.addr), 

679 IRExpr._from_c(c_stmt.Ist.StoreG.details.data), 

680 IRExpr._from_c(c_stmt.Ist.StoreG.details.guard), 

681 ) 

682 

683 def typecheck(self, tyenv): 

684 addrty = self.addr.typecheck(tyenv) 

685 if addrty is None: 

686 return False 

687 if addrty != tyenv.wordty: 

688 log.debug("addr must be full word for arch") 

689 return False 

690 if self.end not in ("Iend_LE", "Iend_BE"): 

691 log.debug("invalid endness enum") 

692 return False 

693 

694 guardty = self.guard.typecheck(tyenv) 

695 dataty = self.data.typecheck(tyenv) 

696 

697 if guardty is None or dataty is None: 

698 return False 

699 if guardty != "Ity_I1": 

700 log.debug("guard must be Ity_I1") 

701 return False 

702 return True 

703 

704 

705_globals = globals().copy() 

706# 

707# Mapping from tag strings/enums to IRStmt classes 

708# 

709tag_to_stmt_mapping = {} 

710enum_to_stmt_mapping = {} 

711tag_count = 0 

712cls = None 

713for cls in _globals.values(): 

714 if type(cls) is type and issubclass(cls, IRStmt) and cls is not IRStmt: 

715 tag_to_stmt_mapping[cls.tag] = cls 

716 enum_to_stmt_mapping[get_int_from_enum(cls.tag)] = cls 

717 cls.tag_int = tag_count 

718 tag_count += 1 

719del cls 

720 

721 

722def tag_to_stmt_class(tag): 

723 try: 

724 return tag_to_stmt_mapping[tag] 

725 except KeyError: 

726 raise KeyError("No statement class for tag %s." % tag) 

727 

728 

729def enum_to_stmt_class(tag_enum): 

730 try: 

731 return enum_to_stmt_mapping[tag_enum] 

732 except KeyError: 

733 raise KeyError("No statement class for tag %s." % get_enum_from_int(tag_enum))