1# Copyright 2019 Google LLC 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# https://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15"""Tests for expression_bounds.""" 16 17import unittest 18from compiler.front_end import expression_bounds 19from compiler.front_end import glue 20from compiler.util import test_util 21 22 23class ComputeConstantsTest(unittest.TestCase): 24 25 def _make_ir(self, emb_text): 26 ir, unused_debug_info, errors = glue.parse_emboss_file( 27 "m.emb", 28 test_util.dict_file_reader({"m.emb": emb_text}), 29 stop_before_step="compute_constants") 30 assert not errors, errors 31 return ir 32 33 def test_constant_integer(self): 34 ir = self._make_ir("struct Foo:\n" 35 " 10 [+1] UInt x\n") 36 self.assertEqual([], expression_bounds.compute_constants(ir)) 37 start = ir.module[0].type[0].structure.field[0].location.start 38 self.assertEqual("10", start.type.integer.minimum_value) 39 self.assertEqual("10", start.type.integer.maximum_value) 40 self.assertEqual("10", start.type.integer.modular_value) 41 self.assertEqual("infinity", start.type.integer.modulus) 42 43 def test_boolean_constant(self): 44 ir = self._make_ir("struct Foo:\n" 45 " if true:\n" 46 " 0 [+1] UInt x\n") 47 self.assertEqual([], expression_bounds.compute_constants(ir)) 48 expression = ir.module[0].type[0].structure.field[0].existence_condition 49 self.assertTrue(expression.type.boolean.HasField("value")) 50 self.assertTrue(expression.type.boolean.value) 51 52 def test_constant_equality(self): 53 ir = self._make_ir("struct Foo:\n" 54 " if 5 == 5:\n" 55 " 0 [+1] UInt x\n" 56 " if 5 == 6:\n" 57 " 0 [+1] UInt y\n") 58 self.assertEqual([], expression_bounds.compute_constants(ir)) 59 structure = ir.module[0].type[0].structure 60 true_condition = structure.field[0].existence_condition 61 false_condition = structure.field[1].existence_condition 62 self.assertTrue(true_condition.type.boolean.HasField("value")) 63 self.assertTrue(true_condition.type.boolean.value) 64 self.assertTrue(false_condition.type.boolean.HasField("value")) 65 self.assertFalse(false_condition.type.boolean.value) 66 67 def test_constant_inequality(self): 68 ir = self._make_ir("struct Foo:\n" 69 " if 5 != 5:\n" 70 " 0 [+1] UInt x\n" 71 " if 5 != 6:\n" 72 " 0 [+1] UInt y\n") 73 self.assertEqual([], expression_bounds.compute_constants(ir)) 74 structure = ir.module[0].type[0].structure 75 false_condition = structure.field[0].existence_condition 76 true_condition = structure.field[1].existence_condition 77 self.assertTrue(false_condition.type.boolean.HasField("value")) 78 self.assertFalse(false_condition.type.boolean.value) 79 self.assertTrue(true_condition.type.boolean.HasField("value")) 80 self.assertTrue(true_condition.type.boolean.value) 81 82 def test_constant_less_than(self): 83 ir = self._make_ir("struct Foo:\n" 84 " if 5 < 4:\n" 85 " 0 [+1] UInt x\n" 86 " if 5 < 5:\n" 87 " 0 [+1] UInt y\n" 88 " if 5 < 6:\n" 89 " 0 [+1] UInt z\n") 90 self.assertEqual([], expression_bounds.compute_constants(ir)) 91 structure = ir.module[0].type[0].structure 92 greater_than_condition = structure.field[0].existence_condition 93 equal_condition = structure.field[1].existence_condition 94 less_than_condition = structure.field[2].existence_condition 95 self.assertTrue(greater_than_condition.type.boolean.HasField("value")) 96 self.assertFalse(greater_than_condition.type.boolean.value) 97 self.assertTrue(equal_condition.type.boolean.HasField("value")) 98 self.assertFalse(equal_condition.type.boolean.value) 99 self.assertTrue(less_than_condition.type.boolean.HasField("value")) 100 self.assertTrue(less_than_condition.type.boolean.value) 101 102 def test_constant_less_than_or_equal(self): 103 ir = self._make_ir("struct Foo:\n" 104 " if 5 <= 4:\n" 105 " 0 [+1] UInt x\n" 106 " if 5 <= 5:\n" 107 " 0 [+1] UInt y\n" 108 " if 5 <= 6:\n" 109 " 0 [+1] UInt z\n") 110 self.assertEqual([], expression_bounds.compute_constants(ir)) 111 structure = ir.module[0].type[0].structure 112 greater_than_condition = structure.field[0].existence_condition 113 equal_condition = structure.field[1].existence_condition 114 less_than_condition = structure.field[2].existence_condition 115 self.assertTrue(greater_than_condition.type.boolean.HasField("value")) 116 self.assertFalse(greater_than_condition.type.boolean.value) 117 self.assertTrue(equal_condition.type.boolean.HasField("value")) 118 self.assertTrue(equal_condition.type.boolean.value) 119 self.assertTrue(less_than_condition.type.boolean.HasField("value")) 120 self.assertTrue(less_than_condition.type.boolean.value) 121 122 def test_constant_greater_than(self): 123 ir = self._make_ir("struct Foo:\n" 124 " if 5 > 4:\n" 125 " 0 [+1] UInt x\n" 126 " if 5 > 5:\n" 127 " 0 [+1] UInt y\n" 128 " if 5 > 6:\n" 129 " 0 [+1] UInt z\n") 130 self.assertEqual([], expression_bounds.compute_constants(ir)) 131 structure = ir.module[0].type[0].structure 132 greater_than_condition = structure.field[0].existence_condition 133 equal_condition = structure.field[1].existence_condition 134 less_than_condition = structure.field[2].existence_condition 135 self.assertTrue(greater_than_condition.type.boolean.HasField("value")) 136 self.assertTrue(greater_than_condition.type.boolean.value) 137 self.assertTrue(equal_condition.type.boolean.HasField("value")) 138 self.assertFalse(equal_condition.type.boolean.value) 139 self.assertTrue(less_than_condition.type.boolean.HasField("value")) 140 self.assertFalse(less_than_condition.type.boolean.value) 141 142 def test_constant_greater_than_or_equal(self): 143 ir = self._make_ir("struct Foo:\n" 144 " if 5 >= 4:\n" 145 " 0 [+1] UInt x\n" 146 " if 5 >= 5:\n" 147 " 0 [+1] UInt y\n" 148 " if 5 >= 6:\n" 149 " 0 [+1] UInt z\n") 150 self.assertEqual([], expression_bounds.compute_constants(ir)) 151 structure = ir.module[0].type[0].structure 152 greater_than_condition = structure.field[0].existence_condition 153 equal_condition = structure.field[1].existence_condition 154 less_than_condition = structure.field[2].existence_condition 155 self.assertTrue(greater_than_condition.type.boolean.HasField("value")) 156 self.assertTrue(greater_than_condition.type.boolean.value) 157 self.assertTrue(equal_condition.type.boolean.HasField("value")) 158 self.assertTrue(equal_condition.type.boolean.value) 159 self.assertTrue(less_than_condition.type.boolean.HasField("value")) 160 self.assertFalse(less_than_condition.type.boolean.value) 161 162 def test_constant_and(self): 163 ir = self._make_ir("struct Foo:\n" 164 " if false && false:\n" 165 " 0 [+1] UInt x\n" 166 " if true && false:\n" 167 " 0 [+1] UInt y\n" 168 " if false && true:\n" 169 " 0 [+1] UInt z\n" 170 " if true && true:\n" 171 " 0 [+1] UInt w\n") 172 self.assertEqual([], expression_bounds.compute_constants(ir)) 173 structure = ir.module[0].type[0].structure 174 false_false_condition = structure.field[0].existence_condition 175 true_false_condition = structure.field[1].existence_condition 176 false_true_condition = structure.field[2].existence_condition 177 true_true_condition = structure.field[3].existence_condition 178 self.assertTrue(false_false_condition.type.boolean.HasField("value")) 179 self.assertFalse(false_false_condition.type.boolean.value) 180 self.assertTrue(true_false_condition.type.boolean.HasField("value")) 181 self.assertFalse(true_false_condition.type.boolean.value) 182 self.assertTrue(false_true_condition.type.boolean.HasField("value")) 183 self.assertFalse(false_true_condition.type.boolean.value) 184 self.assertTrue(true_true_condition.type.boolean.HasField("value")) 185 self.assertTrue(true_true_condition.type.boolean.value) 186 187 def test_constant_or(self): 188 ir = self._make_ir("struct Foo:\n" 189 " if false || false:\n" 190 " 0 [+1] UInt x\n" 191 " if true || false:\n" 192 " 0 [+1] UInt y\n" 193 " if false || true:\n" 194 " 0 [+1] UInt z\n" 195 " if true || true:\n" 196 " 0 [+1] UInt w\n") 197 self.assertEqual([], expression_bounds.compute_constants(ir)) 198 structure = ir.module[0].type[0].structure 199 false_false_condition = structure.field[0].existence_condition 200 true_false_condition = structure.field[1].existence_condition 201 false_true_condition = structure.field[2].existence_condition 202 true_true_condition = structure.field[3].existence_condition 203 self.assertTrue(false_false_condition.type.boolean.HasField("value")) 204 self.assertFalse(false_false_condition.type.boolean.value) 205 self.assertTrue(true_false_condition.type.boolean.HasField("value")) 206 self.assertTrue(true_false_condition.type.boolean.value) 207 self.assertTrue(false_true_condition.type.boolean.HasField("value")) 208 self.assertTrue(false_true_condition.type.boolean.value) 209 self.assertTrue(true_true_condition.type.boolean.HasField("value")) 210 self.assertTrue(true_true_condition.type.boolean.value) 211 212 def test_enum_constant(self): 213 ir = self._make_ir("struct Foo:\n" 214 " if Bar.QUX == Bar.QUX:\n" 215 " 0 [+1] Bar x\n" 216 "enum Bar:\n" 217 " QUX = 12\n") 218 self.assertEqual([], expression_bounds.compute_constants(ir)) 219 condition = ir.module[0].type[0].structure.field[0].existence_condition 220 left = condition.function.args[0] 221 self.assertEqual("12", left.type.enumeration.value) 222 223 def test_non_constant_field_reference(self): 224 ir = self._make_ir("struct Foo:\n" 225 " y [+1] UInt x\n" 226 " 0 [+1] UInt y\n") 227 self.assertEqual([], expression_bounds.compute_constants(ir)) 228 start = ir.module[0].type[0].structure.field[0].location.start 229 self.assertEqual("0", start.type.integer.minimum_value) 230 self.assertEqual("255", start.type.integer.maximum_value) 231 self.assertEqual("0", start.type.integer.modular_value) 232 self.assertEqual("1", start.type.integer.modulus) 233 234 def test_field_reference_bounds_are_uncomputable(self): 235 # Variable-sized UInt/Int/Bcd should not cause an error here: they are 236 # handled in the constraints pass. 237 ir = self._make_ir("struct Foo:\n" 238 " 0 [+1] UInt x\n" 239 " 0 [+x] UInt y\n" 240 " y [+1] UInt z\n") 241 self.assertEqual([], expression_bounds.compute_constants(ir)) 242 243 def test_field_references_references_bounds_are_uncomputable(self): 244 ir = self._make_ir("struct Foo:\n" 245 " 0 [+1] UInt x\n" 246 " 0 [+x] UInt y\n" 247 " 0 [+y] UInt z\n" 248 " z [+1] UInt q\n") 249 self.assertEqual([], expression_bounds.compute_constants(ir)) 250 251 def test_non_constant_equality(self): 252 ir = self._make_ir("struct Foo:\n" 253 " if 5 == y:\n" 254 " 0 [+1] UInt x\n" 255 " 0 [+1] UInt y\n") 256 self.assertEqual([], expression_bounds.compute_constants(ir)) 257 structure = ir.module[0].type[0].structure 258 condition = structure.field[0].existence_condition 259 self.assertFalse(condition.type.boolean.HasField("value")) 260 261 def test_constant_addition(self): 262 ir = self._make_ir("struct Foo:\n" 263 " 7+5 [+1] UInt x\n") 264 self.assertEqual([], expression_bounds.compute_constants(ir)) 265 start = ir.module[0].type[0].structure.field[0].location.start 266 self.assertEqual("12", start.type.integer.minimum_value) 267 self.assertEqual("12", start.type.integer.maximum_value) 268 self.assertEqual("12", start.type.integer.modular_value) 269 self.assertEqual("infinity", start.type.integer.modulus) 270 self.assertEqual("7", start.function.args[0].type.integer.minimum_value) 271 self.assertEqual("7", start.function.args[0].type.integer.maximum_value) 272 self.assertEqual("7", start.function.args[0].type.integer.modular_value) 273 self.assertEqual("infinity", start.type.integer.modulus) 274 self.assertEqual("5", start.function.args[1].type.integer.minimum_value) 275 self.assertEqual("5", start.function.args[1].type.integer.maximum_value) 276 self.assertEqual("5", start.function.args[1].type.integer.modular_value) 277 self.assertEqual("infinity", start.type.integer.modulus) 278 279 def test_constant_subtraction(self): 280 ir = self._make_ir("struct Foo:\n" 281 " 7-5 [+1] UInt x\n") 282 self.assertEqual([], expression_bounds.compute_constants(ir)) 283 start = ir.module[0].type[0].structure.field[0].location.start 284 self.assertEqual("2", start.type.integer.minimum_value) 285 self.assertEqual("2", start.type.integer.maximum_value) 286 self.assertEqual("2", start.type.integer.modular_value) 287 self.assertEqual("infinity", start.type.integer.modulus) 288 self.assertEqual("7", start.function.args[0].type.integer.minimum_value) 289 self.assertEqual("7", start.function.args[0].type.integer.maximum_value) 290 self.assertEqual("7", start.function.args[0].type.integer.modular_value) 291 self.assertEqual("infinity", start.type.integer.modulus) 292 self.assertEqual("5", start.function.args[1].type.integer.minimum_value) 293 self.assertEqual("5", start.function.args[1].type.integer.maximum_value) 294 self.assertEqual("5", start.function.args[1].type.integer.modular_value) 295 self.assertEqual("infinity", start.type.integer.modulus) 296 297 def test_constant_multiplication(self): 298 ir = self._make_ir("struct Foo:\n" 299 " 7*5 [+1] UInt x\n") 300 self.assertEqual([], expression_bounds.compute_constants(ir)) 301 start = ir.module[0].type[0].structure.field[0].location.start 302 self.assertEqual("35", start.type.integer.minimum_value) 303 self.assertEqual("35", start.type.integer.maximum_value) 304 self.assertEqual("35", start.type.integer.modular_value) 305 self.assertEqual("infinity", start.type.integer.modulus) 306 self.assertEqual("7", start.function.args[0].type.integer.minimum_value) 307 self.assertEqual("7", start.function.args[0].type.integer.maximum_value) 308 self.assertEqual("7", start.function.args[0].type.integer.modular_value) 309 self.assertEqual("infinity", start.type.integer.modulus) 310 self.assertEqual("5", start.function.args[1].type.integer.minimum_value) 311 self.assertEqual("5", start.function.args[1].type.integer.maximum_value) 312 self.assertEqual("5", start.function.args[1].type.integer.modular_value) 313 self.assertEqual("infinity", start.type.integer.modulus) 314 315 def test_nested_constant_expression(self): 316 ir = self._make_ir("struct Foo:\n" 317 " if 7*(3+1) == 28:\n" 318 " 0 [+1] UInt x\n") 319 self.assertEqual([], expression_bounds.compute_constants(ir)) 320 condition = ir.module[0].type[0].structure.field[0].existence_condition 321 self.assertTrue(condition.type.boolean.value) 322 condition_left = condition.function.args[0] 323 self.assertEqual("28", condition_left.type.integer.minimum_value) 324 self.assertEqual("28", condition_left.type.integer.maximum_value) 325 self.assertEqual("28", condition_left.type.integer.modular_value) 326 self.assertEqual("infinity", condition_left.type.integer.modulus) 327 condition_left_left = condition_left.function.args[0] 328 self.assertEqual("7", condition_left_left.type.integer.minimum_value) 329 self.assertEqual("7", condition_left_left.type.integer.maximum_value) 330 self.assertEqual("7", condition_left_left.type.integer.modular_value) 331 self.assertEqual("infinity", condition_left_left.type.integer.modulus) 332 condition_left_right = condition_left.function.args[1] 333 self.assertEqual("4", condition_left_right.type.integer.minimum_value) 334 self.assertEqual("4", condition_left_right.type.integer.maximum_value) 335 self.assertEqual("4", condition_left_right.type.integer.modular_value) 336 self.assertEqual("infinity", condition_left_right.type.integer.modulus) 337 condition_left_right_left = condition_left_right.function.args[0] 338 self.assertEqual("3", condition_left_right_left.type.integer.minimum_value) 339 self.assertEqual("3", condition_left_right_left.type.integer.maximum_value) 340 self.assertEqual("3", condition_left_right_left.type.integer.modular_value) 341 self.assertEqual("infinity", condition_left_right_left.type.integer.modulus) 342 condition_left_right_right = condition_left_right.function.args[1] 343 self.assertEqual("1", condition_left_right_right.type.integer.minimum_value) 344 self.assertEqual("1", condition_left_right_right.type.integer.maximum_value) 345 self.assertEqual("1", condition_left_right_right.type.integer.modular_value) 346 self.assertEqual("infinity", 347 condition_left_right_right.type.integer.modulus) 348 349 def test_constant_plus_non_constant(self): 350 ir = self._make_ir("struct Foo:\n" 351 " 0 [+1] UInt x\n" 352 " 5+(4*x) [+1] UInt y\n") 353 self.assertEqual([], expression_bounds.compute_constants(ir)) 354 y_start = ir.module[0].type[0].structure.field[1].location.start 355 self.assertEqual("4", y_start.type.integer.modulus) 356 self.assertEqual("1", y_start.type.integer.modular_value) 357 self.assertEqual("5", y_start.type.integer.minimum_value) 358 self.assertEqual("1025", y_start.type.integer.maximum_value) 359 360 def test_constant_minus_non_constant(self): 361 ir = self._make_ir("struct Foo:\n" 362 " 0 [+1] UInt x\n" 363 " 5-(4*x) [+1] UInt y\n") 364 self.assertEqual([], expression_bounds.compute_constants(ir)) 365 y_start = ir.module[0].type[0].structure.field[1].location.start 366 self.assertEqual("4", y_start.type.integer.modulus) 367 self.assertEqual("1", y_start.type.integer.modular_value) 368 self.assertEqual("-1015", y_start.type.integer.minimum_value) 369 self.assertEqual("5", y_start.type.integer.maximum_value) 370 371 def test_non_constant_minus_constant(self): 372 ir = self._make_ir("struct Foo:\n" 373 " 0 [+1] UInt x\n" 374 " (4*x)-5 [+1] UInt y\n") 375 self.assertEqual([], expression_bounds.compute_constants(ir)) 376 y_start = ir.module[0].type[0].structure.field[1].location.start 377 self.assertEqual(str((4 * 0) - 5), y_start.type.integer.minimum_value) 378 self.assertEqual(str((4 * 255) - 5), y_start.type.integer.maximum_value) 379 self.assertEqual("4", y_start.type.integer.modulus) 380 self.assertEqual("3", y_start.type.integer.modular_value) 381 382 def test_non_constant_plus_non_constant(self): 383 ir = self._make_ir("struct Foo:\n" 384 " 0 [+1] UInt x\n" 385 " 1 [+1] UInt y\n" 386 " (4*x)+(6*y+3) [+1] UInt z\n") 387 self.assertEqual([], expression_bounds.compute_constants(ir)) 388 z_start = ir.module[0].type[0].structure.field[2].location.start 389 self.assertEqual("3", z_start.type.integer.minimum_value) 390 self.assertEqual(str(4 * 255 + 6 * 255 + 3), 391 z_start.type.integer.maximum_value) 392 self.assertEqual("2", z_start.type.integer.modulus) 393 self.assertEqual("1", z_start.type.integer.modular_value) 394 395 def test_non_constant_minus_non_constant(self): 396 ir = self._make_ir("struct Foo:\n" 397 " 0 [+1] UInt x\n" 398 " 1 [+1] UInt y\n" 399 " (x*3)-(y*3) [+1] UInt z\n") 400 self.assertEqual([], expression_bounds.compute_constants(ir)) 401 z_start = ir.module[0].type[0].structure.field[2].location.start 402 self.assertEqual("3", z_start.type.integer.modulus) 403 self.assertEqual("0", z_start.type.integer.modular_value) 404 self.assertEqual(str(-3 * 255), z_start.type.integer.minimum_value) 405 self.assertEqual(str(3 * 255), z_start.type.integer.maximum_value) 406 407 def test_non_constant_times_constant(self): 408 ir = self._make_ir("struct Foo:\n" 409 " 0 [+1] UInt x\n" 410 " (4*x+1)*5 [+1] UInt y\n") 411 self.assertEqual([], expression_bounds.compute_constants(ir)) 412 y_start = ir.module[0].type[0].structure.field[1].location.start 413 self.assertEqual("20", y_start.type.integer.modulus) 414 self.assertEqual("5", y_start.type.integer.modular_value) 415 self.assertEqual("5", y_start.type.integer.minimum_value) 416 self.assertEqual(str((4 * 255 + 1) * 5), y_start.type.integer.maximum_value) 417 418 def test_non_constant_times_negative_constant(self): 419 ir = self._make_ir("struct Foo:\n" 420 " 0 [+1] UInt x\n" 421 " (4*x+1)*-5 [+1] UInt y\n") 422 self.assertEqual([], expression_bounds.compute_constants(ir)) 423 y_start = ir.module[0].type[0].structure.field[1].location.start 424 self.assertEqual("20", y_start.type.integer.modulus) 425 self.assertEqual("15", y_start.type.integer.modular_value) 426 self.assertEqual(str((4 * 255 + 1) * -5), 427 y_start.type.integer.minimum_value) 428 self.assertEqual("-5", y_start.type.integer.maximum_value) 429 430 def test_non_constant_times_zero(self): 431 ir = self._make_ir("struct Foo:\n" 432 " 0 [+1] UInt x\n" 433 " (4*x+1)*0 [+1] UInt y\n") 434 self.assertEqual([], expression_bounds.compute_constants(ir)) 435 y_start = ir.module[0].type[0].structure.field[1].location.start 436 self.assertEqual("infinity", y_start.type.integer.modulus) 437 self.assertEqual("0", y_start.type.integer.modular_value) 438 self.assertEqual("0", y_start.type.integer.minimum_value) 439 self.assertEqual("0", y_start.type.integer.maximum_value) 440 441 def test_non_constant_times_non_constant_shared_modulus(self): 442 ir = self._make_ir("struct Foo:\n" 443 " 0 [+1] UInt x\n" 444 " 1 [+1] UInt y\n" 445 " (4*x+3)*(4*y+3) [+1] UInt z\n") 446 self.assertEqual([], expression_bounds.compute_constants(ir)) 447 z_start = ir.module[0].type[0].structure.field[2].location.start 448 self.assertEqual("4", z_start.type.integer.modulus) 449 self.assertEqual("1", z_start.type.integer.modular_value) 450 self.assertEqual("9", z_start.type.integer.minimum_value) 451 self.assertEqual(str((4 * 255 + 3)**2), z_start.type.integer.maximum_value) 452 453 def test_non_constant_times_non_constant_congruent_to_zero(self): 454 ir = self._make_ir("struct Foo:\n" 455 " 0 [+1] UInt x\n" 456 " 1 [+1] UInt y\n" 457 " (4*x)*(4*y) [+1] UInt z\n") 458 self.assertEqual([], expression_bounds.compute_constants(ir)) 459 z_start = ir.module[0].type[0].structure.field[2].location.start 460 self.assertEqual("16", z_start.type.integer.modulus) 461 self.assertEqual("0", z_start.type.integer.modular_value) 462 self.assertEqual("0", z_start.type.integer.minimum_value) 463 self.assertEqual(str((4 * 255)**2), z_start.type.integer.maximum_value) 464 465 def test_non_constant_times_non_constant_partially_shared_modulus(self): 466 ir = self._make_ir("struct Foo:\n" 467 " 0 [+1] UInt x\n" 468 " 1 [+1] UInt y\n" 469 " (4*x+3)*(8*y+3) [+1] UInt z\n") 470 self.assertEqual([], expression_bounds.compute_constants(ir)) 471 z_start = ir.module[0].type[0].structure.field[2].location.start 472 self.assertEqual("4", z_start.type.integer.modulus) 473 self.assertEqual("1", z_start.type.integer.modular_value) 474 self.assertEqual("9", z_start.type.integer.minimum_value) 475 self.assertEqual(str((4 * 255 + 3) * (8 * 255 + 3)), 476 z_start.type.integer.maximum_value) 477 478 def test_non_constant_times_non_constant_full_complexity(self): 479 ir = self._make_ir("struct Foo:\n" 480 " 0 [+1] UInt x\n" 481 " 1 [+1] UInt y\n" 482 " (12*x+9)*(40*y+15) [+1] UInt z\n") 483 self.assertEqual([], expression_bounds.compute_constants(ir)) 484 z_start = ir.module[0].type[0].structure.field[2].location.start 485 self.assertEqual("60", z_start.type.integer.modulus) 486 self.assertEqual("15", z_start.type.integer.modular_value) 487 self.assertEqual(str(9 * 15), z_start.type.integer.minimum_value) 488 self.assertEqual(str((12 * 255 + 9) * (40 * 255 + 15)), 489 z_start.type.integer.maximum_value) 490 491 def test_signed_non_constant_times_signed_non_constant_full_complexity(self): 492 ir = self._make_ir("struct Foo:\n" 493 " 0 [+1] Int x\n" 494 " 1 [+1] Int y\n" 495 " (12*x+9)*(40*y+15) [+1] Int z\n") 496 self.assertEqual([], expression_bounds.compute_constants(ir)) 497 z_start = ir.module[0].type[0].structure.field[2].location.start 498 self.assertEqual("60", z_start.type.integer.modulus) 499 self.assertEqual("15", z_start.type.integer.modular_value) 500 # Max x/min y is slightly lower than min x/max y (-7825965 vs -7780065). 501 self.assertEqual(str((12 * 127 + 9) * (40 * -128 + 15)), 502 z_start.type.integer.minimum_value) 503 # Max x/max y is slightly higher than min x/min y (7810635 vs 7795335). 504 self.assertEqual(str((12 * 127 + 9) * (40 * 127 + 15)), 505 z_start.type.integer.maximum_value) 506 507 def test_non_constant_times_non_constant_flipped_min_max(self): 508 ir = self._make_ir("struct Foo:\n" 509 " 0 [+1] UInt x\n" 510 " 1 [+1] UInt y\n" 511 " (-x*3)*(y*3) [+1] UInt z\n") 512 self.assertEqual([], expression_bounds.compute_constants(ir)) 513 z_start = ir.module[0].type[0].structure.field[2].location.start 514 self.assertEqual("9", z_start.type.integer.modulus) 515 self.assertEqual("0", z_start.type.integer.modular_value) 516 self.assertEqual(str(-((3 * 255)**2)), z_start.type.integer.minimum_value) 517 self.assertEqual("0", z_start.type.integer.maximum_value) 518 519 # Currently, only `$static_size_in_bits` has an infinite bound, so all of the 520 # examples below use `$static_size_in_bits`. Unfortunately, this also means 521 # that these tests rely on the fact that Emboss doesn't try to do any term 522 # rewriting or smart correlation between the arguments of various operators: 523 # for example, several tests rely on `$static_size_in_bits - 524 # $static_size_in_bits` having the range `-infinity` to `infinity`, when a 525 # trivial term rewrite would turn that expression into `0`. 526 # 527 # Unbounded expressions are only allowed at compile-time anyway, so these 528 # tests cover some fairly unlikely uses of the Emboss expression language. 529 def test_unbounded_plus_constant(self): 530 ir = self._make_ir("external Foo:\n" 531 " [requires: $static_size_in_bits + 2 > 0]\n") 532 self.assertEqual([], expression_bounds.compute_constants(ir)) 533 expr = ir.module[0].type[0].attribute[0].value.expression.function.args[0] 534 self.assertEqual("1", expr.type.integer.modulus) 535 self.assertEqual("0", expr.type.integer.modular_value) 536 self.assertEqual("2", expr.type.integer.minimum_value) 537 self.assertEqual("infinity", expr.type.integer.maximum_value) 538 539 def test_negative_unbounded_plus_constant(self): 540 ir = self._make_ir("external Foo:\n" 541 " [requires: -$static_size_in_bits + 2 > 0]\n") 542 self.assertEqual([], expression_bounds.compute_constants(ir)) 543 expr = ir.module[0].type[0].attribute[0].value.expression.function.args[0] 544 self.assertEqual("1", expr.type.integer.modulus) 545 self.assertEqual("0", expr.type.integer.modular_value) 546 self.assertEqual("-infinity", expr.type.integer.minimum_value) 547 self.assertEqual("2", expr.type.integer.maximum_value) 548 549 def test_negative_unbounded_plus_unbounded(self): 550 ir = self._make_ir( 551 "external Foo:\n" 552 " [requires: -$static_size_in_bits + $static_size_in_bits > 0]\n") 553 self.assertEqual([], expression_bounds.compute_constants(ir)) 554 expr = ir.module[0].type[0].attribute[0].value.expression.function.args[0] 555 self.assertEqual("1", expr.type.integer.modulus) 556 self.assertEqual("0", expr.type.integer.modular_value) 557 self.assertEqual("-infinity", expr.type.integer.minimum_value) 558 self.assertEqual("infinity", expr.type.integer.maximum_value) 559 560 def test_unbounded_minus_unbounded(self): 561 ir = self._make_ir( 562 "external Foo:\n" 563 " [requires: $static_size_in_bits - $static_size_in_bits > 0]\n") 564 self.assertEqual([], expression_bounds.compute_constants(ir)) 565 expr = ir.module[0].type[0].attribute[0].value.expression.function.args[0] 566 self.assertEqual("1", expr.type.integer.modulus) 567 self.assertEqual("0", expr.type.integer.modular_value) 568 self.assertEqual("-infinity", expr.type.integer.minimum_value) 569 self.assertEqual("infinity", expr.type.integer.maximum_value) 570 571 def test_unbounded_minus_negative_unbounded(self): 572 ir = self._make_ir( 573 "external Foo:\n" 574 " [requires: $static_size_in_bits - -$static_size_in_bits > 0]\n") 575 self.assertEqual([], expression_bounds.compute_constants(ir)) 576 expr = ir.module[0].type[0].attribute[0].value.expression.function.args[0] 577 self.assertEqual("1", expr.type.integer.modulus) 578 self.assertEqual("0", expr.type.integer.modular_value) 579 self.assertEqual("0", expr.type.integer.minimum_value) 580 self.assertEqual("infinity", expr.type.integer.maximum_value) 581 582 def test_unbounded_times_constant(self): 583 ir = self._make_ir("external Foo:\n" 584 " [requires: ($static_size_in_bits + 1) * 2 > 0]\n") 585 self.assertEqual([], expression_bounds.compute_constants(ir)) 586 expr = ir.module[0].type[0].attribute[0].value.expression.function.args[0] 587 self.assertEqual("2", expr.type.integer.modulus) 588 self.assertEqual("0", expr.type.integer.modular_value) 589 self.assertEqual("2", expr.type.integer.minimum_value) 590 self.assertEqual("infinity", expr.type.integer.maximum_value) 591 592 def test_unbounded_times_negative_constant(self): 593 ir = self._make_ir("external Foo:\n" 594 " [requires: ($static_size_in_bits + 1) * -2 > 0]\n") 595 self.assertEqual([], expression_bounds.compute_constants(ir)) 596 expr = ir.module[0].type[0].attribute[0].value.expression.function.args[0] 597 self.assertEqual("2", expr.type.integer.modulus) 598 self.assertEqual("0", expr.type.integer.modular_value) 599 self.assertEqual("-infinity", expr.type.integer.minimum_value) 600 self.assertEqual("-2", expr.type.integer.maximum_value) 601 602 def test_unbounded_times_negative_zero(self): 603 ir = self._make_ir("external Foo:\n" 604 " [requires: ($static_size_in_bits + 1) * 0 > 0]\n") 605 self.assertEqual([], expression_bounds.compute_constants(ir)) 606 expr = ir.module[0].type[0].attribute[0].value.expression.function.args[0] 607 self.assertEqual("infinity", expr.type.integer.modulus) 608 self.assertEqual("0", expr.type.integer.modular_value) 609 self.assertEqual("0", expr.type.integer.minimum_value) 610 self.assertEqual("0", expr.type.integer.maximum_value) 611 612 def test_negative_unbounded_times_constant(self): 613 ir = self._make_ir("external Foo:\n" 614 " [requires: (-$static_size_in_bits + 1) * 2 > 0]\n") 615 self.assertEqual([], expression_bounds.compute_constants(ir)) 616 expr = ir.module[0].type[0].attribute[0].value.expression.function.args[0] 617 self.assertEqual("2", expr.type.integer.modulus) 618 self.assertEqual("0", expr.type.integer.modular_value) 619 self.assertEqual("-infinity", expr.type.integer.minimum_value) 620 self.assertEqual("2", expr.type.integer.maximum_value) 621 622 def test_double_unbounded_minus_unbounded(self): 623 ir = self._make_ir( 624 "external Foo:\n" 625 " [requires: 2 * $static_size_in_bits - $static_size_in_bits > 0]\n") 626 self.assertEqual([], expression_bounds.compute_constants(ir)) 627 expr = ir.module[0].type[0].attribute[0].value.expression.function.args[0] 628 self.assertEqual("1", expr.type.integer.modulus) 629 self.assertEqual("0", expr.type.integer.modular_value) 630 self.assertEqual("-infinity", expr.type.integer.minimum_value) 631 self.assertEqual("infinity", expr.type.integer.maximum_value) 632 633 def test_double_unbounded_times_negative_unbounded(self): 634 ir = self._make_ir( 635 "external Foo:\n" 636 " [requires: 2 * $static_size_in_bits * -$static_size_in_bits > 0]\n") 637 self.assertEqual([], expression_bounds.compute_constants(ir)) 638 expr = ir.module[0].type[0].attribute[0].value.expression.function.args[0] 639 self.assertEqual("2", expr.type.integer.modulus) 640 self.assertEqual("0", expr.type.integer.modular_value) 641 self.assertEqual("-infinity", expr.type.integer.minimum_value) 642 self.assertEqual("0", expr.type.integer.maximum_value) 643 644 def test_upper_bound_of_field(self): 645 ir = self._make_ir("struct Foo:\n" 646 " 0 [+1] Int x\n" 647 " let u = $upper_bound(x)\n") 648 self.assertEqual([], expression_bounds.compute_constants(ir)) 649 u_type = ir.module[0].type[0].structure.field[1].read_transform.type 650 self.assertEqual("infinity", u_type.integer.modulus) 651 self.assertEqual("127", u_type.integer.maximum_value) 652 self.assertEqual("127", u_type.integer.minimum_value) 653 self.assertEqual("127", u_type.integer.modular_value) 654 655 def test_lower_bound_of_field(self): 656 ir = self._make_ir("struct Foo:\n" 657 " 0 [+1] Int x\n" 658 " let l = $lower_bound(x)\n") 659 self.assertEqual([], expression_bounds.compute_constants(ir)) 660 l_type = ir.module[0].type[0].structure.field[1].read_transform.type 661 self.assertEqual("infinity", l_type.integer.modulus) 662 self.assertEqual("-128", l_type.integer.maximum_value) 663 self.assertEqual("-128", l_type.integer.minimum_value) 664 self.assertEqual("-128", l_type.integer.modular_value) 665 666 def test_upper_bound_of_max(self): 667 ir = self._make_ir("struct Foo:\n" 668 " 0 [+1] Int x\n" 669 " 1 [+1] UInt y\n" 670 " let u = $upper_bound($max(x, y))\n") 671 self.assertEqual([], expression_bounds.compute_constants(ir)) 672 u_type = ir.module[0].type[0].structure.field[2].read_transform.type 673 self.assertEqual("infinity", u_type.integer.modulus) 674 self.assertEqual("255", u_type.integer.maximum_value) 675 self.assertEqual("255", u_type.integer.minimum_value) 676 self.assertEqual("255", u_type.integer.modular_value) 677 678 def test_lower_bound_of_max(self): 679 ir = self._make_ir("struct Foo:\n" 680 " 0 [+1] Int x\n" 681 " 1 [+1] UInt y\n" 682 " let l = $lower_bound($max(x, y))\n") 683 self.assertEqual([], expression_bounds.compute_constants(ir)) 684 l_type = ir.module[0].type[0].structure.field[2].read_transform.type 685 self.assertEqual("infinity", l_type.integer.modulus) 686 self.assertEqual("0", l_type.integer.maximum_value) 687 self.assertEqual("0", l_type.integer.minimum_value) 688 self.assertEqual("0", l_type.integer.modular_value) 689 690 def test_double_unbounded_both_ends_times_negative_unbounded(self): 691 ir = self._make_ir( 692 "external Foo:\n" 693 " [requires: (2 * ($static_size_in_bits - $static_size_in_bits) + 1) " 694 " * -$static_size_in_bits > 0]\n") 695 self.assertEqual([], expression_bounds.compute_constants(ir)) 696 expr = ir.module[0].type[0].attribute[0].value.expression.function.args[0] 697 self.assertEqual("1", expr.type.integer.modulus) 698 self.assertEqual("0", expr.type.integer.modular_value) 699 self.assertEqual("-infinity", expr.type.integer.minimum_value) 700 self.assertEqual("infinity", expr.type.integer.maximum_value) 701 702 def test_choice_two_non_constant_integers(self): 703 cases = [ 704 # t % 12 == 7 and f % 20 == 15 ==> r % 4 == 3 705 (12, 7, 20, 15, 4, 3, -128 * 20 + 15, 127 * 20 + 15), 706 # t % 24 == 15 and f % 12 == 7 ==> r % 4 == 3 707 (24, 15, 12, 7, 4, 3, -128 * 24 + 15, 127 * 24 + 15), 708 # t % 20 == 15 and f % 20 == 10 ==> r % 5 == 0 709 (20, 15, 20, 10, 5, 0, -128 * 20 + 10, 127 * 20 + 15), 710 # t % 20 == 16 and f % 20 == 11 ==> r % 5 == 1 711 (20, 16, 20, 11, 5, 1, -128 * 20 + 11, 127 * 20 + 16), 712 ] 713 for (t_mod, t_val, f_mod, f_val, r_mod, r_val, r_min, r_max) in cases: 714 ir = self._make_ir("struct Foo:\n" 715 " 0 [+1] UInt x\n" 716 " 1 [+1] Int y\n" 717 " if (x == 0 ? y * {} + {} : y * {} + {}) == 0:\n" 718 " 1 [+1] UInt z\n".format( 719 t_mod, t_val, f_mod, f_val)) 720 self.assertEqual([], expression_bounds.compute_constants(ir)) 721 field = ir.module[0].type[0].structure.field[2] 722 expr = field.existence_condition.function.args[0] 723 self.assertEqual(str(r_mod), expr.type.integer.modulus) 724 self.assertEqual(str(r_val), expr.type.integer.modular_value) 725 self.assertEqual(str(r_min), expr.type.integer.minimum_value) 726 self.assertEqual(str(r_max), expr.type.integer.maximum_value) 727 728 def test_choice_one_non_constant_integer(self): 729 cases = [ 730 # t == 35 and f % 20 == 15 ==> res % 20 == 15 731 (35, 20, 15, 20, 15, -128 * 20 + 15, 127 * 20 + 15), 732 # t == 200035 and f % 20 == 15 ==> res % 20 == 15 733 (200035, 20, 15, 20, 15, -128 * 20 + 15, 200035), 734 # t == 21 and f % 20 == 16 ==> res % 5 == 1 735 (21, 20, 16, 5, 1, -128 * 20 + 16, 127 * 20 + 16), 736 ] 737 for (t_val, f_mod, f_val, r_mod, r_val, r_min, r_max) in cases: 738 ir = self._make_ir("struct Foo:\n" 739 " 0 [+1] UInt x\n" 740 " 1 [+1] Int y\n" 741 " if (x == 0 ? {0} : y * {1} + {2}) == 0:\n" 742 " 1 [+1] UInt z\n" 743 " if (x == 0 ? y * {1} + {2} : {0}) == 0:\n" 744 " 1 [+1] UInt q\n".format(t_val, f_mod, f_val)) 745 self.assertEqual([], expression_bounds.compute_constants(ir)) 746 field_constant_true = ir.module[0].type[0].structure.field[2] 747 constant_true = field_constant_true.existence_condition.function.args[0] 748 field_constant_false = ir.module[0].type[0].structure.field[3] 749 constant_false = field_constant_false.existence_condition.function.args[0] 750 self.assertEqual(str(r_mod), constant_true.type.integer.modulus) 751 self.assertEqual(str(r_val), constant_true.type.integer.modular_value) 752 self.assertEqual(str(r_min), constant_true.type.integer.minimum_value) 753 self.assertEqual(str(r_max), constant_true.type.integer.maximum_value) 754 self.assertEqual(str(r_mod), constant_false.type.integer.modulus) 755 self.assertEqual(str(r_val), constant_false.type.integer.modular_value) 756 self.assertEqual(str(r_min), constant_false.type.integer.minimum_value) 757 self.assertEqual(str(r_max), constant_false.type.integer.maximum_value) 758 759 def test_choice_two_constant_integers(self): 760 cases = [ 761 # t == 10 and f == 7 ==> res % 3 == 1 762 (10, 7, 3, 1, 7, 10), 763 # t == 4 and f == 4 ==> res == 4 764 (4, 4, "infinity", 4, 4, 4), 765 ] 766 for (t_val, f_val, r_mod, r_val, r_min, r_max) in cases: 767 ir = self._make_ir("struct Foo:\n" 768 " 0 [+1] UInt x\n" 769 " 1 [+1] Int y\n" 770 " if (x == 0 ? {} : {}) == 0:\n" 771 " 1 [+1] UInt z\n".format(t_val, f_val)) 772 self.assertEqual([], expression_bounds.compute_constants(ir)) 773 field_constant_true = ir.module[0].type[0].structure.field[2] 774 constant_true = field_constant_true.existence_condition.function.args[0] 775 self.assertEqual(str(r_mod), constant_true.type.integer.modulus) 776 self.assertEqual(str(r_val), constant_true.type.integer.modular_value) 777 self.assertEqual(str(r_min), constant_true.type.integer.minimum_value) 778 self.assertEqual(str(r_max), constant_true.type.integer.maximum_value) 779 780 def test_constant_true_has(self): 781 ir = self._make_ir("struct Foo:\n" 782 " if $present(x):\n" 783 " 1 [+1] UInt q\n" 784 " 0 [+1] UInt x\n" 785 " if x > 10:\n" 786 " 1 [+1] Int y\n" 787 " if false:\n" 788 " 2 [+1] Int z\n") 789 self.assertEqual([], expression_bounds.compute_constants(ir)) 790 field = ir.module[0].type[0].structure.field[0] 791 has_func = field.existence_condition 792 self.assertTrue(has_func.type.boolean.value) 793 794 def test_constant_false_has(self): 795 ir = self._make_ir("struct Foo:\n" 796 " if $present(z):\n" 797 " 1 [+1] UInt q\n" 798 " 0 [+1] UInt x\n" 799 " if x > 10:\n" 800 " 1 [+1] Int y\n" 801 " if false:\n" 802 " 2 [+1] Int z\n") 803 self.assertEqual([], expression_bounds.compute_constants(ir)) 804 field = ir.module[0].type[0].structure.field[0] 805 has_func = field.existence_condition 806 self.assertTrue(has_func.type.boolean.HasField("value")) 807 self.assertFalse(has_func.type.boolean.value) 808 809 def test_variable_has(self): 810 ir = self._make_ir("struct Foo:\n" 811 " if $present(y):\n" 812 " 1 [+1] UInt q\n" 813 " 0 [+1] UInt x\n" 814 " if x > 10:\n" 815 " 1 [+1] Int y\n" 816 " if false:\n" 817 " 2 [+1] Int z\n") 818 self.assertEqual([], expression_bounds.compute_constants(ir)) 819 field = ir.module[0].type[0].structure.field[0] 820 has_func = field.existence_condition 821 self.assertFalse(has_func.type.boolean.HasField("value")) 822 823 def test_max_of_constants(self): 824 ir = self._make_ir("struct Foo:\n" 825 " 0 [+1] UInt x\n" 826 " 1 [+1] Int y\n" 827 " if $max(0, 1, 2) == 0:\n" 828 " 1 [+1] UInt z\n") 829 self.assertEqual([], expression_bounds.compute_constants(ir)) 830 field = ir.module[0].type[0].structure.field[2] 831 max_func = field.existence_condition.function.args[0] 832 self.assertEqual("infinity", max_func.type.integer.modulus) 833 self.assertEqual("2", max_func.type.integer.modular_value) 834 self.assertEqual("2", max_func.type.integer.minimum_value) 835 self.assertEqual("2", max_func.type.integer.maximum_value) 836 837 def test_max_dominated_by_constant(self): 838 ir = self._make_ir("struct Foo:\n" 839 " 0 [+1] UInt x\n" 840 " 1 [+1] Int y\n" 841 " if $max(x, y, 255) == 0:\n" 842 " 1 [+1] UInt z\n") 843 self.assertEqual([], expression_bounds.compute_constants(ir)) 844 field = ir.module[0].type[0].structure.field[2] 845 max_func = field.existence_condition.function.args[0] 846 self.assertEqual("infinity", max_func.type.integer.modulus) 847 self.assertEqual("255", max_func.type.integer.modular_value) 848 self.assertEqual("255", max_func.type.integer.minimum_value) 849 self.assertEqual("255", max_func.type.integer.maximum_value) 850 851 def test_max_of_variables(self): 852 ir = self._make_ir("struct Foo:\n" 853 " 0 [+1] UInt x\n" 854 " 1 [+1] Int y\n" 855 " if $max(x, y) == 0:\n" 856 " 1 [+1] UInt z\n") 857 self.assertEqual([], expression_bounds.compute_constants(ir)) 858 field = ir.module[0].type[0].structure.field[2] 859 max_func = field.existence_condition.function.args[0] 860 self.assertEqual("1", max_func.type.integer.modulus) 861 self.assertEqual("0", max_func.type.integer.modular_value) 862 self.assertEqual("0", max_func.type.integer.minimum_value) 863 self.assertEqual("255", max_func.type.integer.maximum_value) 864 865 def test_max_of_variables_with_shared_modulus(self): 866 ir = self._make_ir("struct Foo:\n" 867 " 0 [+1] UInt x\n" 868 " 1 [+1] Int y\n" 869 " if $max(x * 8 + 5, y * 4 + 3) == 0:\n" 870 " 1 [+1] UInt z\n") 871 self.assertEqual([], expression_bounds.compute_constants(ir)) 872 field = ir.module[0].type[0].structure.field[2] 873 max_func = field.existence_condition.function.args[0] 874 self.assertEqual("2", max_func.type.integer.modulus) 875 self.assertEqual("1", max_func.type.integer.modular_value) 876 self.assertEqual("5", max_func.type.integer.minimum_value) 877 self.assertEqual("2045", max_func.type.integer.maximum_value) 878 879 def test_max_of_three_variables(self): 880 ir = self._make_ir("struct Foo:\n" 881 " 0 [+1] UInt x\n" 882 " 1 [+1] Int y\n" 883 " 2 [+2] Int z\n" 884 " if $max(x, y, z) == 0:\n" 885 " 1 [+1] UInt q\n") 886 self.assertEqual([], expression_bounds.compute_constants(ir)) 887 field = ir.module[0].type[0].structure.field[3] 888 max_func = field.existence_condition.function.args[0] 889 self.assertEqual("1", max_func.type.integer.modulus) 890 self.assertEqual("0", max_func.type.integer.modular_value) 891 self.assertEqual("0", max_func.type.integer.minimum_value) 892 self.assertEqual("32767", max_func.type.integer.maximum_value) 893 894 def test_max_of_one_variable(self): 895 ir = self._make_ir("struct Foo:\n" 896 " 0 [+1] UInt x\n" 897 " 1 [+1] Int y\n" 898 " 2 [+2] Int z\n" 899 " if $max(x * 2 + 3) == 0:\n" 900 " 1 [+1] UInt q\n") 901 self.assertEqual([], expression_bounds.compute_constants(ir)) 902 field = ir.module[0].type[0].structure.field[3] 903 max_func = field.existence_condition.function.args[0] 904 self.assertEqual("2", max_func.type.integer.modulus) 905 self.assertEqual("1", max_func.type.integer.modular_value) 906 self.assertEqual("3", max_func.type.integer.minimum_value) 907 self.assertEqual("513", max_func.type.integer.maximum_value) 908 909 def test_max_of_one_variable_and_one_constant(self): 910 ir = self._make_ir("struct Foo:\n" 911 " 0 [+1] UInt x\n" 912 " 1 [+1] Int y\n" 913 " 2 [+2] Int z\n" 914 " if $max(x * 2 + 3, 311) == 0:\n" 915 " 1 [+1] UInt q\n") 916 self.assertEqual([], expression_bounds.compute_constants(ir)) 917 field = ir.module[0].type[0].structure.field[3] 918 max_func = field.existence_condition.function.args[0] 919 self.assertEqual("2", max_func.type.integer.modulus) 920 self.assertEqual("1", max_func.type.integer.modular_value) 921 self.assertEqual("311", max_func.type.integer.minimum_value) 922 self.assertEqual("513", max_func.type.integer.maximum_value) 923 924 def test_choice_non_integer_arguments(self): 925 ir = self._make_ir("struct Foo:\n" 926 " 0 [+1] UInt x\n" 927 " if x == 0 ? false : true:\n" 928 " 1 [+1] UInt y\n") 929 self.assertEqual([], expression_bounds.compute_constants(ir)) 930 expr = ir.module[0].type[0].structure.field[1].existence_condition 931 self.assertEqual("boolean", expr.type.WhichOneof("type")) 932 self.assertFalse(expr.type.boolean.HasField("value")) 933 934 def test_uint_value_range_for_explicit_size(self): 935 ir = self._make_ir("struct Foo:\n" 936 " 0 [+1] UInt x\n" 937 " 1 [+x] UInt:16 y\n" 938 " y [+1] UInt z\n") 939 self.assertEqual([], expression_bounds.compute_constants(ir)) 940 z_start = ir.module[0].type[0].structure.field[2].location.start 941 self.assertEqual("1", z_start.type.integer.modulus) 942 self.assertEqual("0", z_start.type.integer.modular_value) 943 self.assertEqual("0", z_start.type.integer.minimum_value) 944 self.assertEqual("65535", z_start.type.integer.maximum_value) 945 946 def test_uint_value_ranges(self): 947 cases = [ 948 (1, 1), 949 (2, 3), 950 (3, 7), 951 (4, 15), 952 (8, 255), 953 (12, 4095), 954 (15, 32767), 955 (16, 65535), 956 (32, 4294967295), 957 (48, 281474976710655), 958 (64, 18446744073709551615), 959 ] 960 for bits, upper in cases: 961 ir = self._make_ir("struct Foo:\n" 962 " 0 [+8] bits:\n" 963 " 0 [+{}] UInt x\n" 964 " x [+1] UInt z\n".format(bits)) 965 self.assertEqual([], expression_bounds.compute_constants(ir)) 966 z_start = ir.module[0].type[0].structure.field[2].location.start 967 self.assertEqual("1", z_start.type.integer.modulus) 968 self.assertEqual("0", z_start.type.integer.modular_value) 969 self.assertEqual("0", z_start.type.integer.minimum_value) 970 self.assertEqual(str(upper), z_start.type.integer.maximum_value) 971 972 def test_int_value_ranges(self): 973 cases = [ 974 (1, -1, 0), 975 (2, -2, 1), 976 (3, -4, 3), 977 (4, -8, 7), 978 (8, -128, 127), 979 (12, -2048, 2047), 980 (15, -16384, 16383), 981 (16, -32768, 32767), 982 (32, -2147483648, 2147483647), 983 (48, -140737488355328, 140737488355327), 984 (64, -9223372036854775808, 9223372036854775807), 985 ] 986 for bits, lower, upper in cases: 987 ir = self._make_ir("struct Foo:\n" 988 " 0 [+8] bits:\n" 989 " 0 [+{}] Int x\n" 990 " x [+1] UInt z\n".format(bits)) 991 self.assertEqual([], expression_bounds.compute_constants(ir)) 992 z_start = ir.module[0].type[0].structure.field[2].location.start 993 self.assertEqual("1", z_start.type.integer.modulus) 994 self.assertEqual("0", z_start.type.integer.modular_value) 995 self.assertEqual(str(lower), z_start.type.integer.minimum_value) 996 self.assertEqual(str(upper), z_start.type.integer.maximum_value) 997 998 def test_bcd_value_ranges(self): 999 cases = [ 1000 (1, 1), 1001 (2, 3), 1002 (3, 7), 1003 (4, 9), 1004 (8, 99), 1005 (12, 999), 1006 (15, 7999), 1007 (16, 9999), 1008 (32, 99999999), 1009 (48, 999999999999), 1010 (64, 9999999999999999), 1011 ] 1012 for bits, upper in cases: 1013 ir = self._make_ir("struct Foo:\n" 1014 " 0 [+8] bits:\n" 1015 " 0 [+{}] Bcd x\n" 1016 " x [+1] UInt z\n".format(bits)) 1017 self.assertEqual([], expression_bounds.compute_constants(ir)) 1018 z_start = ir.module[0].type[0].structure.field[2].location.start 1019 self.assertEqual("1", z_start.type.integer.modulus) 1020 self.assertEqual("0", z_start.type.integer.modular_value) 1021 self.assertEqual("0", z_start.type.integer.minimum_value) 1022 self.assertEqual(str(upper), z_start.type.integer.maximum_value) 1023 1024 def test_virtual_field_bounds(self): 1025 ir = self._make_ir("struct Foo:\n" 1026 " 0 [+1] UInt x\n" 1027 " let y = x + 10\n") 1028 self.assertEqual([], expression_bounds.compute_constants(ir)) 1029 field_y = ir.module[0].type[0].structure.field[1] 1030 self.assertEqual("1", field_y.read_transform.type.integer.modulus) 1031 self.assertEqual("0", field_y.read_transform.type.integer.modular_value) 1032 self.assertEqual("10", field_y.read_transform.type.integer.minimum_value) 1033 self.assertEqual("265", field_y.read_transform.type.integer.maximum_value) 1034 1035 def test_virtual_field_bounds_copied(self): 1036 ir = self._make_ir("struct Foo:\n" 1037 " let z = y + 100\n" 1038 " let y = x + 10\n" 1039 " 0 [+1] UInt x\n") 1040 self.assertEqual([], expression_bounds.compute_constants(ir)) 1041 field_z = ir.module[0].type[0].structure.field[0] 1042 self.assertEqual("1", field_z.read_transform.type.integer.modulus) 1043 self.assertEqual("0", field_z.read_transform.type.integer.modular_value) 1044 self.assertEqual("110", field_z.read_transform.type.integer.minimum_value) 1045 self.assertEqual("365", field_z.read_transform.type.integer.maximum_value) 1046 y_reference = field_z.read_transform.function.args[0] 1047 self.assertEqual("1", y_reference.type.integer.modulus) 1048 self.assertEqual("0", y_reference.type.integer.modular_value) 1049 self.assertEqual("10", y_reference.type.integer.minimum_value) 1050 self.assertEqual("265", y_reference.type.integer.maximum_value) 1051 1052 def test_constant_reference_to_virtual_bounds_copied(self): 1053 ir = self._make_ir("struct Foo:\n" 1054 " let ten = Bar.ten\n" 1055 " let truth = Bar.truth\n" 1056 "struct Bar:\n" 1057 " let ten = 10\n" 1058 " let truth = true\n") 1059 self.assertEqual([], expression_bounds.compute_constants(ir)) 1060 field_ten = ir.module[0].type[0].structure.field[0] 1061 self.assertEqual("infinity", field_ten.read_transform.type.integer.modulus) 1062 self.assertEqual("10", field_ten.read_transform.type.integer.modular_value) 1063 self.assertEqual("10", field_ten.read_transform.type.integer.minimum_value) 1064 self.assertEqual("10", field_ten.read_transform.type.integer.maximum_value) 1065 field_truth = ir.module[0].type[0].structure.field[1] 1066 self.assertTrue(field_truth.read_transform.type.boolean.value) 1067 1068 def test_forward_reference_to_reference_to_enum_correctly_calculated(self): 1069 ir = self._make_ir("struct Foo:\n" 1070 " let ten = Bar.TEN\n" 1071 "enum Bar:\n" 1072 " TEN = TEN2\n" 1073 " TEN2 = 5 + 5\n") 1074 self.assertEqual([], expression_bounds.compute_constants(ir)) 1075 field_ten = ir.module[0].type[0].structure.field[0] 1076 self.assertEqual("10", field_ten.read_transform.type.enumeration.value) 1077 1078 1079class InfinityAugmentedArithmeticTest(unittest.TestCase): 1080 1081 # TODO(bolms): Will there ever be any situations where all elements of the arg 1082 # to _min would be "infinity"? 1083 def test_min_of_infinities(self): 1084 self.assertEqual("infinity", 1085 expression_bounds._min(["infinity", "infinity"])) 1086 1087 # TODO(bolms): Will there ever be any situations where all elements of the arg 1088 # to _max would be "-infinity"? 1089 def test_max_of_negative_infinities(self): 1090 self.assertEqual("-infinity", 1091 expression_bounds._max(["-infinity", "-infinity"])) 1092 1093 def test_shared_modular_value_of_identical_modulus_and_value(self): 1094 self.assertEqual((10, 8), 1095 expression_bounds._shared_modular_value((10, 8), (10, 8))) 1096 1097 def test_shared_modular_value_of_identical_modulus(self): 1098 self.assertEqual((5, 3), 1099 expression_bounds._shared_modular_value((10, 8), (10, 3))) 1100 1101 def test_shared_modular_value_of_identical_value(self): 1102 self.assertEqual((6, 2), 1103 expression_bounds._shared_modular_value((18, 2), (12, 2))) 1104 1105 def test_shared_modular_value_of_different_arguments(self): 1106 self.assertEqual((7, 4), 1107 expression_bounds._shared_modular_value((21, 11), (14, 4))) 1108 1109 def test_shared_modular_value_of_infinity_and_non(self): 1110 self.assertEqual((7, 4), 1111 expression_bounds._shared_modular_value(("infinity", 25), 1112 (14, 4))) 1113 1114 def test_shared_modular_value_of_infinity_and_infinity(self): 1115 self.assertEqual((14, 5), 1116 expression_bounds._shared_modular_value(("infinity", 19), 1117 ("infinity", 5))) 1118 1119 def test_shared_modular_value_of_infinity_and_identical_value(self): 1120 self.assertEqual(("infinity", 5), 1121 expression_bounds._shared_modular_value(("infinity", 5), 1122 ("infinity", 5))) 1123 1124 1125if __name__ == "__main__": 1126 unittest.main() 1127