Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/pyvex/lifting/util/syntax_wrapper.py: 74%

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

223 statements  

1import functools 

2from typing import Union 

3 

4from pyvex.const import get_type_size 

5from pyvex.expr import Const, IRExpr, RdTmp 

6 

7from .vex_helper import IRSBCustomizer, Type 

8 

9 

10def checkparams(rhstype=None): 

11 def decorator(fn): 

12 @functools.wraps(fn) 

13 def inner_decorator(self, *args, **kwargs): 

14 irsb_cs = {a.irsb_c for a in list(args) + [self] if isinstance(a, VexValue)} # pylint: disable=no-member 

15 assert len(irsb_cs) == 1, "All VexValues must belong to the same irsb_c" 

16 args = list(args) 

17 for idx, arg in enumerate(args): 

18 if isinstance(arg, int): 

19 thetype = rhstype if rhstype else self.ty 

20 args[idx] = VexValue.Constant(self.irsb_c, arg, thetype) 

21 elif not isinstance(arg, VexValue): 

22 raise Exception("Cannot convert param %s" % str(arg)) 

23 args = tuple(args) 

24 return fn(self, *args, **kwargs) 

25 

26 return inner_decorator 

27 

28 return decorator 

29 

30 

31def vvifyresults(f): 

32 @functools.wraps(f) 

33 def decor(self, *args, **kwargs): 

34 returned = f(self, *args, **kwargs) 

35 assert isinstance(returned, RdTmp) or isinstance(returned, Const) 

36 return VexValue(self.irsb_c, returned) 

37 

38 return decor 

39 

40 

41class VexValue: 

42 def __init__(self, irsb_c: "IRSBCustomizer", rdt: "Union[RdTmp, Const]", signed=False): 

43 self.irsb_c = irsb_c 

44 self.ty = self.irsb_c.get_type(rdt) 

45 self.rdt = rdt 

46 self.width = get_type_size(self.ty) 

47 self._is_signed = signed 

48 

49 @property 

50 def value(self): 

51 if isinstance(self.rdt, Const): 

52 return self.rdt.con.value 

53 else: 

54 raise ValueError("Non-constant VexValue has no value property") 

55 

56 @property 

57 def signed(self): 

58 return VexValue(self.irsb_c, self.rdt, True) 

59 

60 @vvifyresults 

61 def widen_unsigned(self, ty): 

62 return self.irsb_c.op_widen_int_unsigned(self.rdt, ty) 

63 

64 @vvifyresults 

65 def cast_to(self, ty, signed=False, high=False): 

66 return self.irsb_c.cast_to(self.rdt, ty, signed=signed, high=high) 

67 

68 @vvifyresults 

69 def widen_signed(self, ty): 

70 return self.irsb_c.op_widen_int_signed(self.rdt, ty) 

71 

72 @vvifyresults 

73 def narrow_high(self, ty): 

74 return self.irsb_c.op_narrow_int(self.rdt, ty, high_half=True) 

75 

76 @vvifyresults 

77 def narrow_low(self, ty): 

78 return self.irsb_c.op_narrow_int(self.rdt, ty, high_half=False) 

79 

80 # TODO at some point extend this to Vex nonconstants 

81 def __getitem__(self, idx): 

82 def getb(i): 

83 return VexValue(self.irsb_c, self.irsb_c.get_bit(self.rdt, i)) 

84 

85 def makeconstant(x): 

86 return VexValue.Constant(self.irsb_c, x, Type.int_8).rdt 

87 

88 if not isinstance(idx, slice): 

89 actualindex = slice(idx).indices(self.width)[1] 

90 return getb(makeconstant(actualindex)) 

91 else: 

92 return [getb(makeconstant(i)) for i in range(*idx.indices(self.width))] 

93 

94 def __setitem__(self, idx, bval): 

95 setted = self.set_bit(idx, bval) 

96 self.__init__(setted.irsb_c, setted.rdt) 

97 

98 @checkparams() 

99 @vvifyresults 

100 def set_bit(self, idx, bval): 

101 return self.irsb_c.set_bit(self.rdt, idx.rdt, bval.rdt) 

102 

103 @checkparams() 

104 @vvifyresults 

105 def set_bits(self, idxsandvals): 

106 return self.irsb_c.set_bits(self.rdt, [(i.cast_to(Type.int_8).rdt, b.rdt) for i, b in idxsandvals]) 

107 

108 @checkparams() 

109 @vvifyresults 

110 def ite(self, iftrue, iffalse): 

111 onebitcond = self.cast_to(Type.int_1) 

112 return self.irsb_c.ite(onebitcond.rdt, iftrue.rdt, iffalse.rdt) 

113 

114 @checkparams() 

115 @vvifyresults 

116 def sar(self, right): 

117 """ 

118 `v.sar(r)` should do arithmetic shift right of `v` by `r` 

119 

120 :param right:VexValue value to shift by 

121 :return: VexValue - result of a shift 

122 """ 

123 return self.irsb_c.op_sar(self.rdt, right.rdt) 

124 

125 @checkparams() 

126 @vvifyresults 

127 def __add__(self, right): 

128 return self.irsb_c.op_add(self.rdt, right.rdt) 

129 

130 @checkparams() 

131 def __radd__(self, left): 

132 return self + left 

133 

134 @checkparams() 

135 @vvifyresults 

136 def __sub__(self, right): 

137 return self.irsb_c.op_sub(self.rdt, right.rdt) 

138 

139 @checkparams() 

140 def __rsub__(self, left): 

141 return left - self 

142 

143 @checkparams() 

144 @vvifyresults 

145 def __div__(self, right): 

146 if self._is_signed: 

147 return self.irsb_c.op_sdiv(self.rdt, right.rdt) 

148 else: 

149 return self.irsb_c.op_udiv(self.rdt, right.rdt) 

150 

151 @checkparams() 

152 def __rdiv__(self, left): 

153 return left // self 

154 

155 @checkparams() 

156 def __floordiv__(self, right): # Note: nonprimitive 

157 return self.__div__(right) 

158 

159 @checkparams() 

160 def __rfloordiv__(self, left): 

161 return left // self 

162 

163 @checkparams() 

164 def __truediv__(self, right): # Note: nonprimitive 

165 return self / right 

166 

167 @checkparams() 

168 def __rtruediv__(self, left): 

169 return left.__truediv__(self) 

170 

171 @checkparams() 

172 @vvifyresults 

173 def __and__(self, right): 

174 return self.irsb_c.op_and(self.rdt, right.rdt) 

175 

176 @checkparams() 

177 def __rand__(self, left): 

178 return left & self 

179 

180 @checkparams() 

181 @vvifyresults 

182 def __eq__(self, right): 

183 return self.irsb_c.op_cmp_eq(self.rdt, right.rdt) 

184 

185 @checkparams() 

186 @vvifyresults 

187 def __ne__(self, other): 

188 return self.irsb_c.op_cmp_ne(self.rdt, other.rdt) 

189 

190 @checkparams() 

191 @vvifyresults 

192 def __invert__(self): 

193 return self.irsb_c.op_not(self.rdt) 

194 

195 @checkparams() 

196 @vvifyresults 

197 def __le__(self, right): 

198 if self._is_signed: 

199 return self.irsb_c.op_cmp_sle(self.rdt, right.rdt) 

200 else: 

201 return self.irsb_c.op_cmp_ule(self.rdt, right.rdt) 

202 

203 @checkparams() 

204 @vvifyresults 

205 def __gt__(self, other): 

206 if self._is_signed: 

207 return self.irsb_c.op_cmp_sgt(self.rdt, other.rdt) 

208 else: 

209 return self.irsb_c.op_cmp_ugt(self.rdt, other.rdt) 

210 

211 @checkparams() 

212 @vvifyresults 

213 def __ge__(self, right): 

214 if self._is_signed: 

215 return self.irsb_c.op_cmp_sge(self.rdt, right.rdt) 

216 else: 

217 return self.irsb_c.op_cmp_uge(self.rdt, right.rdt) 

218 

219 @checkparams(rhstype=Type.int_8) 

220 @vvifyresults 

221 def __lshift__(self, right): # TODO put better type inference in irsb_c so we can have rlshift 

222 """ 

223 logical shift left 

224 """ 

225 return self.irsb_c.op_shl(self.rdt, right.rdt) 

226 

227 @checkparams() 

228 @vvifyresults 

229 def __lt__(self, right): 

230 if self._is_signed: 

231 return self.irsb_c.op_cmp_slt(self.rdt, right.rdt) 

232 else: 

233 return self.irsb_c.op_cmp_ult(self.rdt, right.rdt) 

234 

235 @checkparams() 

236 @vvifyresults 

237 def __mod__(self, right): # Note: nonprimitive 

238 return self.irsb_c.op_mod(self.rdt, right.rdt) 

239 

240 @checkparams() 

241 def __rmod__(self, left): 

242 return left % self 

243 

244 @checkparams() 

245 @vvifyresults 

246 def __mul__(self, right): 

247 if self._is_signed: 

248 return self.irsb_c.op_smul(self.rdt, right.rdt) 

249 else: 

250 return self.irsb_c.op_umul(self.rdt, right.rdt) 

251 

252 @checkparams() 

253 def __rmul__(self, left): 

254 return left * self 

255 

256 @checkparams() 

257 @vvifyresults 

258 def __neg__(self): # Note: nonprimitive 

259 if not self._is_signed: 

260 raise Exception("Number is unsigned, cannot change sign!") 

261 else: 

262 return self.rdt * -1 

263 

264 @checkparams() 

265 @vvifyresults 

266 def __or__(self, right): 

267 return self.irsb_c.op_or(self.rdt, right.rdt) 

268 

269 def __ror__(self, left): 

270 return self | left 

271 

272 @checkparams() 

273 @vvifyresults 

274 def __pos__(self): 

275 return self 

276 

277 @checkparams(rhstype=Type.int_8) 

278 @vvifyresults 

279 def __rshift__(self, right): 

280 """ 

281 logical shift right 

282 """ 

283 return self.irsb_c.op_shr(self.rdt, right.rdt) 

284 

285 @checkparams() 

286 def __rlshift__(self, left): 

287 return left << self 

288 

289 @checkparams() 

290 def __rrshift__(self, left): 

291 return left >> self 

292 

293 @checkparams() 

294 @vvifyresults 

295 def __xor__(self, right): 

296 return self.irsb_c.op_xor(self.rdt, right.rdt) 

297 

298 def __rxor__(self, left): 

299 return self ^ left 

300 

301 @classmethod 

302 def Constant(cls, irsb_c, val, ty): 

303 """ 

304 Creates a constant as a VexValue 

305 :param irsb_c: The IRSBCustomizer to use 

306 :param val: The value, as an integer 

307 :param ty: The type of the resulting VexValue 

308 :return: a VexValue 

309 """ 

310 assert not (isinstance(val, VexValue) or isinstance(val, IRExpr)) 

311 rdt = irsb_c.mkconst(val, ty) 

312 return cls(irsb_c, rdt)