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

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

448 statements  

1import logging 

2from typing import Iterator, Optional 

3 

4from . import expr 

5from .const import IRConst 

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

7from .errors import PyVEXError 

8from .expr import Const, Get, IRExpr 

9from .native import ffi, pvc 

10 

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

12 

13 

14class IRStmt(VEXObject): 

15 """ 

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

17 """ 

18 

19 tag: Optional[str] = None 

20 tag_int = 0 # set automatically at bottom of file 

21 

22 __slots__ = [] 

23 

24 def pp(self): 

25 print(str(self)) 

26 

27 @property 

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

29 for k in self.__slots__: 

30 v = getattr(self, k) 

31 if isinstance(v, IRExpr): 

32 # return itself 

33 yield v 

34 # return all the child expressions 

35 yield from v.child_expressions 

36 

37 # ??? 

38 @property 

39 def expressions(self): 

40 return self.child_expressions 

41 

42 @property 

43 def constants(self): 

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

45 

46 @staticmethod 

47 def _from_c(c_stmt): 

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

49 return None 

50 

51 try: 

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

53 except KeyError: 

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

55 return stmt_class._from_c(c_stmt) 

56 

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

58 return True 

59 

60 def replace_expression(self, replacements): 

61 """ 

62 Replace child expressions in-place. 

63 

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

65 :return: None 

66 """ 

67 

68 for k in self.__slots__: 

69 v = getattr(self, k) 

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

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

72 elif isinstance(v, IRExpr): 

73 v.replace_expression(replacements) 

74 elif type(v) is tuple: 

75 # Rebuild the tuple 

76 _lst = [] 

77 replaced = False 

78 for expr_ in v: 

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

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

81 replaced = True 

82 else: 

83 _lst.append(expr_) 

84 if replaced: 

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

86 

87 def __str__(self): 

88 return self.pp_str(None, None, None) 

89 

90 def pp_str(self, reg_name=None, arch=None, tyenv=None) -> str: 

91 raise NotImplementedError() 

92 

93 

94class NoOp(IRStmt): 

95 """ 

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

97 """ 

98 

99 __slots__ = [] 

100 

101 tag = "Ist_NoOp" 

102 

103 def pp_str(self, reg_name=None, arch=None, tyenv=None): 

104 return "IR-NoOp" 

105 

106 @staticmethod 

107 def _from_c(c_stmt): 

108 return NoOp() 

109 

110 

111class IMark(IRStmt): 

112 """ 

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

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

115 instruction. 

116 """ 

117 

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

119 

120 tag = "Ist_IMark" 

121 

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

123 self.addr = addr 

124 self.len = length 

125 self.delta = delta 

126 

127 def pp_str(self, reg_name=None, arch=None, tyenv=None): 

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

129 

130 @staticmethod 

131 def _from_c(c_stmt): 

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

133 

134 

135class AbiHint(IRStmt): 

136 """ 

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

138 """ 

139 

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

141 

142 tag = "Ist_AbiHint" 

143 

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

145 self.base = base 

146 self.len = length 

147 self.nia = nia 

148 

149 def pp_str(self, reg_name=None, arch=None, tyenv=None): 

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

151 

152 @staticmethod 

153 def _from_c(c_stmt): 

154 return AbiHint( 

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

156 ) 

157 

158 

159class Put(IRStmt): 

160 """ 

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

162 """ 

163 

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

165 

166 tag = "Ist_Put" 

167 

168 def __init__(self, data: "IRExpr", offset): 

169 self.data = data 

170 self.offset = offset 

171 

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

173 def pp_str(self, reg_name=None, arch=None, tyenv=None): 

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

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

176 

177 if reg_name is not None: 

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

179 else: 

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

181 

182 @staticmethod 

183 def _from_c(c_stmt): 

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

185 

186 def typecheck(self, tyenv): 

187 return self.data.typecheck(tyenv) 

188 

189 

190class PutI(IRStmt): 

191 """ 

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

193 """ 

194 

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

196 

197 tag = "Ist_PutI" 

198 

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

200 self.descr = descr 

201 self.ix = ix 

202 self.data = data 

203 self.bias = bias 

204 

205 def pp_str(self, reg_name=None, arch=None, tyenv=None): 

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

207 

208 @staticmethod 

209 def _from_c(c_stmt): 

210 return PutI( 

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

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

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

214 c_stmt.Ist.PutI.details.bias, 

215 ) 

216 

217 def typecheck(self, tyenv): 

218 dataty = self.data.typecheck(tyenv) 

219 if dataty is None: 

220 return False 

221 if dataty != self.descr.elemTy: 

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

223 return False 

224 return True 

225 

226 

227class WrTmp(IRStmt): 

228 """ 

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

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

231 """ 

232 

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

234 

235 tag = "Ist_WrTmp" 

236 

237 def __init__(self, tmp, data: "IRExpr"): 

238 self.tmp = tmp 

239 self.data = data 

240 

241 def pp_str(self, reg_name=None, arch=None, tyenv=None): 

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

243 

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

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

246 

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

248 return "t%d = %s" % (self.tmp, self.data.pp_str_with_name(reg_name)) 

249 else: 

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

251 

252 @staticmethod 

253 def _from_c(c_stmt): 

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

255 

256 def typecheck(self, tyenv): 

257 dataty = self.data.typecheck(tyenv) 

258 if dataty is None: 

259 return False 

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

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

262 return False 

263 return True 

264 

265 

266class Store(IRStmt): 

267 """ 

268 Write a value to memory.. 

269 """ 

270 

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

272 

273 tag = "Ist_Store" 

274 

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

276 self.addr = addr 

277 self.data = data 

278 self.end = end 

279 

280 @property 

281 def endness(self): 

282 return self.end 

283 

284 def pp_str(self, reg_name=None, arch=None, tyenv=None): 

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

286 

287 @staticmethod 

288 def _from_c(c_stmt): 

289 return Store( 

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

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

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

293 ) 

294 

295 def typecheck(self, tyenv): 

296 dataty = self.data.typecheck(tyenv) 

297 if dataty is None: 

298 return False 

299 addrty = self.addr.typecheck(tyenv) 

300 if addrty is None: 

301 return False 

302 if addrty != tyenv.wordty: 

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

304 return False 

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

306 log.debug("invalid endness enum") 

307 return False 

308 return True 

309 

310 

311class CAS(IRStmt): 

312 """ 

313 an atomic compare-and-swap operation. 

314 """ 

315 

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

317 

318 tag = "Ist_CAS" 

319 

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

321 self.addr = addr 

322 self.dataLo = dataLo 

323 self.dataHi = dataHi 

324 self.expdLo = expdLo 

325 self.expdHi = expdHi 

326 self.oldLo = oldLo 

327 self.oldHi = oldHi 

328 self.end = end 

329 

330 @property 

331 def endness(self): 

332 return self.end 

333 

334 def pp_str(self, reg_name=None, arch=None, tyenv=None): 

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

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

337 ) 

338 

339 @staticmethod 

340 def _from_c(c_stmt): 

341 return CAS( 

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

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

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

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

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

347 c_stmt.Ist.CAS.details.oldLo, 

348 c_stmt.Ist.CAS.details.oldHi, 

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

350 ) 

351 

352 def typecheck(self, tyenv): 

353 addrty = self.addr.typecheck(tyenv) 

354 if addrty is None: 

355 return False 

356 if addrty != tyenv.wordty: 

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

358 return False 

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

360 log.debug("invalid endness enum") 

361 return False 

362 

363 if self.oldHi == 0xFFFFFFFF: 

364 # single-element case 

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

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

367 return False 

368 expdLoTy = self.expdLo.typecheck(tyenv) 

369 dataLoTy = self.dataLo.typecheck(tyenv) 

370 if expdLoTy is None or dataLoTy is None: 

371 return False 

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

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

374 return False 

375 else: 

376 # double-element case 

377 expdLoTy = self.expdLo.typecheck(tyenv) 

378 dataLoTy = self.dataLo.typecheck(tyenv) 

379 expdHiTy = self.expdHi.typecheck(tyenv) 

380 dataHiTy = self.dataHi.typecheck(tyenv) 

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

382 return False 

383 if ( 

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

385 or expdLoTy != dataLoTy 

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

387 or expdHiTy != dataHiTy 

388 or expdLoTy != expdHiTy 

389 ): 

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

391 return False 

392 

393 return True 

394 

395 

396class LLSC(IRStmt): 

397 """ 

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

399 else it is a Store-Conditional. 

400 """ 

401 

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

403 

404 tag = "Ist_LLSC" 

405 

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

407 self.addr = addr 

408 self.storedata = storedata 

409 self.result = result 

410 self.end = end 

411 

412 @property 

413 def endness(self): 

414 return self.end 

415 

416 def pp_str(self, reg_name=None, arch=None, tyenv=None): 

417 if self.storedata is None: 

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

419 else: 

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

421 

422 @staticmethod 

423 def _from_c(c_stmt): 

424 return LLSC( 

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

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

427 c_stmt.Ist.LLSC.result, 

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

429 ) 

430 

431 def typecheck(self, tyenv): 

432 addrty = self.addr.typecheck(tyenv) 

433 if addrty is None: 

434 return False 

435 if addrty != tyenv.wordty: 

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

437 return False 

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

439 log.debug("invalid endness enum") 

440 return False 

441 

442 if self.storedata is not None: 

443 # load-linked 

444 storety = self.storedata.typecheck(tyenv) 

445 if storety is None: 

446 return False 

447 

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

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

450 return False 

451 

452 return True 

453 

454 

455class MBE(IRStmt): 

456 __slots__ = ["event"] 

457 

458 tag = "Ist_MBE" 

459 

460 def __init__(self, event): 

461 self.event = event 

462 

463 def pp_str(self, reg_name=None, arch=None, tyenv=None): 

464 return "MBusEvent-" + self.event 

465 

466 @staticmethod 

467 def _from_c(c_stmt): 

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

469 

470 

471class Dirty(IRStmt): 

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

473 

474 tag = "Ist_Dirty" 

475 

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

477 self.cee = cee 

478 self.guard = guard 

479 self.args = tuple(args) 

480 self.tmp = tmp 

481 self.mFx = mFx 

482 self.mAddr = mAddr 

483 self.mSize = mSize 

484 self.nFxState = nFxState 

485 

486 def pp_str(self, reg_name=None, arch=None, tyenv=None): 

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

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

489 ) 

490 

491 @property 

492 def child_expressions(self): 

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

494 expressions.extend(self.args) 

495 expressions.append(self.guard) 

496 expressions.extend(self.guard.child_expressions) 

497 return expressions 

498 

499 @staticmethod 

500 def _from_c(c_stmt): 

501 args = [] 

502 for i in range(20): 

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

504 if a == ffi.NULL: 

505 break 

506 

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

508 

509 return Dirty( 

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

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

512 tuple(args), 

513 c_stmt.Ist.Dirty.details.tmp, 

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

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

516 c_stmt.Ist.Dirty.details.mSize, 

517 c_stmt.Ist.Dirty.details.nFxState, 

518 ) 

519 

520 

521class Exit(IRStmt): 

522 """ 

523 A conditional exit from the middle of an IRSB. 

524 """ 

525 

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

527 

528 tag = "Ist_Exit" 

529 

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

531 self.guard = guard 

532 self.dst = dst 

533 self.offsIP = offsIP 

534 self.jk = jk 

535 

536 @property 

537 def jumpkind(self): 

538 return self.jk 

539 

540 def pp_str(self, reg_name=None, arch=None, tyenv=None): 

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

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

543 

544 if reg_name is None: 

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

546 else: 

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

548 

549 @property 

550 def child_expressions(self): 

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

552 

553 @staticmethod 

554 def _from_c(c_stmt): 

555 return Exit( 

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

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

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

559 c_stmt.Ist.Exit.offsIP, 

560 ) 

561 

562 def typecheck(self, tyenv): 

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

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

565 return False 

566 guardty = self.guard.typecheck(tyenv) 

567 if guardty is None: 

568 return False 

569 if guardty != "Ity_I1": 

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

571 return False 

572 return True 

573 

574 

575class LoadG(IRStmt): 

576 """ 

577 A guarded load. 

578 """ 

579 

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

581 

582 tag = "Ist_LoadG" 

583 

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

585 self.addr = addr 

586 self.alt = alt 

587 self.guard = guard 

588 self.dst = dst 

589 self.cvt = cvt 

590 self.end = end 

591 

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

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

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

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

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

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

598 

599 @property 

600 def endness(self): 

601 return self.end 

602 

603 def pp_str(self, reg_name=None, arch=None, tyenv=None): 

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

605 self.dst, 

606 self.guard, 

607 self.cvt, 

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

609 self.addr, 

610 self.alt, 

611 ) 

612 

613 @staticmethod 

614 def _from_c(c_stmt): 

615 return LoadG( 

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

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

618 c_stmt.Ist.LoadG.details.dst, 

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

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

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

622 ) 

623 

624 def typecheck(self, tyenv): 

625 addrty = self.addr.typecheck(tyenv) 

626 if addrty is None: 

627 return False 

628 if addrty != tyenv.wordty: 

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

630 return False 

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

632 log.debug("invalid endness enum") 

633 return False 

634 

635 dstty = tyenv.lookup(self.dst) 

636 guardty = self.guard.typecheck(tyenv) 

637 altty = self.alt.typecheck(tyenv) 

638 

639 if guardty is None or altty is None: 

640 return False 

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

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

643 return False 

644 if guardty != "Ity_I1": 

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

646 return False 

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

648 log.debug("Invalid cvt enum") 

649 return False 

650 return True 

651 

652 

653class StoreG(IRStmt): 

654 """ 

655 A guarded store. 

656 """ 

657 

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

659 

660 tag = "Ist_StoreG" 

661 

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

663 self.addr = addr 

664 self.data = data 

665 self.guard = guard 

666 self.end = end 

667 

668 @property 

669 def endness(self): 

670 return self.end 

671 

672 def pp_str(self, reg_name=None, arch=None, tyenv=None): 

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

674 

675 @staticmethod 

676 def _from_c(c_stmt): 

677 return StoreG( 

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

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

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

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

682 ) 

683 

684 def typecheck(self, tyenv): 

685 addrty = self.addr.typecheck(tyenv) 

686 if addrty is None: 

687 return False 

688 if addrty != tyenv.wordty: 

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

690 return False 

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

692 log.debug("invalid endness enum") 

693 return False 

694 

695 guardty = self.guard.typecheck(tyenv) 

696 dataty = self.data.typecheck(tyenv) 

697 

698 if guardty is None or dataty is None: 

699 return False 

700 if guardty != "Ity_I1": 

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

702 return False 

703 return True 

704 

705 

706_globals = globals().copy() 

707# 

708# Mapping from tag strings/enums to IRStmt classes 

709# 

710tag_to_stmt_mapping = {} 

711enum_to_stmt_mapping = {} 

712tag_count = 0 

713cls = None 

714for cls in _globals.values(): 

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

716 tag_to_stmt_mapping[cls.tag] = cls 

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

718 cls.tag_int = tag_count 

719 tag_count += 1 

720del cls 

721 

722 

723def tag_to_stmt_class(tag): 

724 try: 

725 return tag_to_stmt_mapping[tag] 

726 except KeyError: 

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

728 

729 

730def enum_to_stmt_class(tag_enum): 

731 try: 

732 return enum_to_stmt_mapping[tag_enum] 

733 except KeyError: 

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