blob: 4f4df7e913f8d01a4d0e90bb3cb25b450d80ec0a [file] [log] [blame]
Ben Olmsteadc0d77842019-07-31 17:34:05 -07001# 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 constraints.py."""
16
17import unittest
reventlov6731fc42019-10-03 15:23:13 -070018from compiler.front_end import attributes
19from compiler.front_end import constraints
20from compiler.front_end import glue
reventlov6731fc42019-10-03 15:23:13 -070021from compiler.util import error
Eric Rahm9b98d3f2024-07-08 11:43:14 -070022from compiler.util import ir_data_utils
reventlov6731fc42019-10-03 15:23:13 -070023from compiler.util import ir_util
Jason Graffius91910772023-05-18 12:43:52 -040024from compiler.util import test_util
Ben Olmsteadc0d77842019-07-31 17:34:05 -070025
26
27def _make_ir_from_emb(emb_text, name="m.emb"):
Dmitri Prime495d3f22024-09-06 16:56:59 -070028 ir, unused_debug_info, errors = glue.parse_emboss_file(
29 name,
30 test_util.dict_file_reader({name: emb_text}),
31 stop_before_step="check_constraints",
32 )
33 assert not errors, repr(errors)
34 return ir
Ben Olmsteadc0d77842019-07-31 17:34:05 -070035
36
37class ConstraintsTest(unittest.TestCase):
Dmitri Prime495d3f22024-09-06 16:56:59 -070038 """Tests constraints.check_constraints and helpers."""
Ben Olmsteadc0d77842019-07-31 17:34:05 -070039
Dmitri Prime495d3f22024-09-06 16:56:59 -070040 def test_error_on_missing_inner_array_size(self):
41 ir = _make_ir_from_emb("struct Foo:\n" " 0 [+1] UInt:8[][1] one_byte\n")
42 # There is a latent issue here where the source location reported in this
43 # error is using a default value of 0:0. An issue is filed at
44 # https://github.com/google/emboss/issues/153 for further investigation.
45 # In the meantime we use `ir_data_utils.reader` to mimic this legacy
46 # behavior.
47 error_array = ir_data_utils.reader(
48 ir.module[0].type[0].structure.field[0].type.array_type
49 )
50 self.assertEqual(
51 [
52 [
53 error.error(
54 "m.emb",
55 error_array.base_type.array_type.element_count.source_location,
56 "Array dimensions can only be omitted for the outermost dimension.",
57 )
58 ]
59 ],
60 error.filter_errors(constraints.check_constraints(ir)),
61 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -070062
Dmitri Prime495d3f22024-09-06 16:56:59 -070063 def test_no_error_on_ok_array_size(self):
64 ir = _make_ir_from_emb("struct Foo:\n" " 0 [+1] UInt:8[1][1] one_byte\n")
65 self.assertEqual([], constraints.check_constraints(ir))
Ben Olmsteadc0d77842019-07-31 17:34:05 -070066
Dmitri Prime495d3f22024-09-06 16:56:59 -070067 def test_no_error_on_ok_missing_outer_array_size(self):
68 ir = _make_ir_from_emb("struct Foo:\n" " 0 [+1] UInt:8[1][] one_byte\n")
69 self.assertEqual([], constraints.check_constraints(ir))
Ben Olmsteadc0d77842019-07-31 17:34:05 -070070
Dmitri Prime495d3f22024-09-06 16:56:59 -070071 def test_no_error_on_dynamically_sized_struct_in_dynamically_sized_field(self):
72 ir = _make_ir_from_emb(
73 "struct Foo:\n"
74 " 0 [+1] UInt size\n"
75 " 1 [+size] Bar bar\n"
76 "struct Bar:\n"
77 " 0 [+1] UInt size\n"
78 " 1 [+size] UInt:8[] payload\n"
79 )
80 self.assertEqual([], constraints.check_constraints(ir))
Ben Olmsteadc0d77842019-07-31 17:34:05 -070081
Dmitri Prime495d3f22024-09-06 16:56:59 -070082 def test_no_error_on_dynamically_sized_struct_in_statically_sized_field(self):
83 ir = _make_ir_from_emb(
84 "struct Foo:\n"
85 " 0 [+10] Bar bar\n"
86 "struct Bar:\n"
87 " 0 [+1] UInt size\n"
88 " 1 [+size] UInt:8[] payload\n"
89 )
90 self.assertEqual([], constraints.check_constraints(ir))
Ben Olmsteadc0d77842019-07-31 17:34:05 -070091
Dmitri Prime495d3f22024-09-06 16:56:59 -070092 def test_no_error_non_fixed_size_outer_array_dimension(self):
93 ir = _make_ir_from_emb(
94 "struct Foo:\n"
95 " 0 [+1] UInt size\n"
96 " 1 [+size] UInt:8[1][size-1] one_byte\n"
97 )
98 self.assertEqual([], constraints.check_constraints(ir))
Ben Olmsteadc0d77842019-07-31 17:34:05 -070099
Dmitri Prime495d3f22024-09-06 16:56:59 -0700100 def test_error_non_fixed_size_inner_array_dimension(self):
101 ir = _make_ir_from_emb(
102 "struct Foo:\n"
103 " 0 [+1] UInt size\n"
104 " 1 [+size] UInt:8[size-1][1] one_byte\n"
105 )
106 error_array = ir.module[0].type[0].structure.field[1].type.array_type
107 self.assertEqual(
108 [
109 [
110 error.error(
111 "m.emb",
112 error_array.base_type.array_type.element_count.source_location,
113 "Inner array dimensions must be constant.",
114 )
115 ]
116 ],
117 error.filter_errors(constraints.check_constraints(ir)),
118 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700119
Dmitri Prime495d3f22024-09-06 16:56:59 -0700120 def test_error_non_constant_inner_array_dimensions(self):
121 ir = _make_ir_from_emb(
122 "struct Foo:\n"
123 " 0 [+1] Bar[1] one_byte\n"
124 # There is no dynamically-sized byte-oriented type in
125 # the Prelude, so this test has to make its own.
126 "external Bar:\n"
127 " [is_integer: true]\n"
128 " [addressable_unit_size: 8]\n"
129 )
130 error_array = ir.module[0].type[0].structure.field[0].type.array_type
131 self.assertEqual(
132 [
133 [
134 error.error(
135 "m.emb",
136 error_array.base_type.atomic_type.source_location,
137 "Array elements must be fixed size.",
138 )
139 ]
140 ],
141 error.filter_errors(constraints.check_constraints(ir)),
142 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700143
Dmitri Prime495d3f22024-09-06 16:56:59 -0700144 def test_error_dynamically_sized_array_elements(self):
145 ir = _make_ir_from_emb(
146 '[$default byte_order: "LittleEndian"]\n'
147 "struct Foo:\n"
148 " 0 [+1] Bar[1] bar\n"
149 "struct Bar:\n"
150 " 0 [+1] UInt size\n"
151 " 1 [+size] UInt:8[] payload\n"
152 )
153 error_array = ir.module[0].type[0].structure.field[0].type.array_type
154 self.assertEqual(
155 [
156 [
157 error.error(
158 "m.emb",
159 error_array.base_type.atomic_type.source_location,
160 "Array elements must be fixed size.",
161 )
162 ]
163 ],
164 error.filter_errors(constraints.check_constraints(ir)),
165 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700166
Dmitri Prime495d3f22024-09-06 16:56:59 -0700167 def test_field_too_small_for_type(self):
168 ir = _make_ir_from_emb(
169 '[$default byte_order: "LittleEndian"]\n'
170 "struct Foo:\n"
171 " 0 [+1] Bar bar\n"
172 "struct Bar:\n"
173 " 0 [+2] UInt value\n"
174 )
175 error_type = ir.module[0].type[0].structure.field[0].type
176 self.assertEqual(
177 [
178 [
179 error.error(
180 "m.emb",
181 error_type.source_location,
182 "Fixed-size type 'Bar' cannot be placed in field of size 8 bits; "
183 "requires 16 bits.",
184 )
185 ]
186 ],
187 error.filter_errors(constraints.check_constraints(ir)),
188 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700189
Dmitri Prime495d3f22024-09-06 16:56:59 -0700190 def test_dynamically_sized_field_always_too_small_for_type(self):
191 ir = _make_ir_from_emb(
192 '[$default byte_order: "LittleEndian"]\n'
193 "struct Foo:\n"
194 " 0 [+1] bits:\n"
195 " 0 [+1] UInt x\n"
196 " 0 [+x] Bar bar\n"
197 "struct Bar:\n"
198 " 0 [+2] UInt value\n"
199 )
200 error_type = ir.module[0].type[0].structure.field[2].type
201 self.assertEqual(
202 [
203 [
204 error.error(
205 "m.emb",
206 error_type.source_location,
207 "Field of maximum size 8 bits cannot hold fixed-size type 'Bar', "
208 "which requires 16 bits.",
209 )
210 ]
211 ],
212 error.filter_errors(constraints.check_constraints(ir)),
213 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700214
Dmitri Prime495d3f22024-09-06 16:56:59 -0700215 def test_struct_field_too_big_for_type(self):
216 ir = _make_ir_from_emb(
217 "struct Foo:\n"
218 " 0 [+2] Byte double_byte\n"
219 "struct Byte:\n"
220 " 0 [+1] UInt b\n"
221 )
222 error_type = ir.module[0].type[0].structure.field[0].type
223 self.assertEqual(
224 [
225 [
226 error.error(
227 "m.emb",
228 error_type.source_location,
229 "Fixed-size type 'Byte' cannot be placed in field of size 16 bits; "
230 "requires 8 bits.",
231 )
232 ]
233 ],
234 error.filter_errors(constraints.check_constraints(ir)),
235 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700236
Dmitri Prime495d3f22024-09-06 16:56:59 -0700237 def test_bits_field_too_big_for_type(self):
238 ir = _make_ir_from_emb(
239 "struct Foo:\n"
240 " 0 [+9] UInt uint72\n"
241 ' [byte_order: "LittleEndian"]\n'
242 )
243 error_field = ir.module[0].type[0].structure.field[0]
244 uint_type = ir_util.find_object(error_field.type.atomic_type.reference, ir)
245 uint_requirements = ir_util.get_attribute(
246 uint_type.attribute, attributes.STATIC_REQUIREMENTS
247 )
248 self.assertEqual(
249 [
250 [
251 error.error(
252 "m.emb",
253 error_field.source_location,
254 "Requirements of UInt not met.",
255 ),
256 error.note(
257 "",
258 uint_requirements.source_location,
259 "Requirements specified here.",
260 ),
261 ]
262 ],
263 error.filter_errors(constraints.check_constraints(ir)),
264 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700265
Dmitri Prime495d3f22024-09-06 16:56:59 -0700266 def test_field_type_not_allowed_in_bits(self):
267 ir = _make_ir_from_emb(
268 '[$default byte_order: "LittleEndian"]\n'
269 "bits Foo:\n"
270 " 0 [+16] Bar bar\n"
271 "external Bar:\n"
272 " [addressable_unit_size: 8]\n"
273 )
274 error_type = ir.module[0].type[0].structure.field[0].type
275 self.assertEqual(
276 [
277 [
278 error.error(
279 "m.emb",
280 error_type.source_location,
281 "Byte-oriented type 'Bar' cannot be used in a bits field.",
282 )
283 ]
284 ],
285 error.filter_errors(constraints.check_constraints(ir)),
286 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700287
Dmitri Prime495d3f22024-09-06 16:56:59 -0700288 def test_arrays_allowed_in_bits(self):
289 ir = _make_ir_from_emb("bits Foo:\n" " 0 [+16] Flag[16] bar\n")
290 self.assertEqual([], constraints.check_constraints(ir))
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700291
Dmitri Prime495d3f22024-09-06 16:56:59 -0700292 def test_oversized_anonymous_bit_field(self):
293 ir = _make_ir_from_emb(
294 '[$default byte_order: "LittleEndian"]\n'
295 "struct Foo:\n"
296 " 0 [+4] bits:\n"
297 " 0 [+8] UInt field\n"
298 )
299 self.assertEqual([], constraints.check_constraints(ir))
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700300
Dmitri Prime495d3f22024-09-06 16:56:59 -0700301 def test_undersized_anonymous_bit_field(self):
302 ir = _make_ir_from_emb(
303 '[$default byte_order: "LittleEndian"]\n'
304 "struct Foo:\n"
305 " 0 [+1] bits:\n"
306 " 0 [+32] UInt field\n"
307 )
308 error_type = ir.module[0].type[0].structure.field[0].type
309 self.assertEqual(
310 [
311 [
312 error.error(
313 "m.emb",
314 error_type.source_location,
315 "Fixed-size anonymous type cannot be placed in field of size 8 "
316 "bits; requires 32 bits.",
317 )
318 ]
319 ],
320 error.filter_errors(constraints.check_constraints(ir)),
321 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700322
Dmitri Prime495d3f22024-09-06 16:56:59 -0700323 def test_reserved_field_name(self):
324 ir = _make_ir_from_emb(
325 '[$default byte_order: "LittleEndian"]\n'
326 "struct Foo:\n"
327 " 0 [+8] UInt restrict\n"
328 )
329 error_name = ir.module[0].type[0].structure.field[0].name.name
330 self.assertEqual(
331 [
332 [
333 error.error(
334 "m.emb",
335 error_name.source_location,
336 "C reserved word may not be used as a field name.",
337 )
338 ]
339 ],
340 error.filter_errors(constraints.check_constraints(ir)),
341 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700342
Dmitri Prime495d3f22024-09-06 16:56:59 -0700343 def test_reserved_type_name(self):
344 ir = _make_ir_from_emb("struct False:\n" " 0 [+1] UInt foo\n")
345 error_name = ir.module[0].type[0].name.name
346 self.assertEqual(
347 [
348 [
349 error.error(
350 "m.emb",
351 error_name.source_location,
352 "Python 3 reserved word may not be used as a type name.",
353 )
354 ]
355 ],
356 error.filter_errors(constraints.check_constraints(ir)),
357 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700358
Dmitri Prime495d3f22024-09-06 16:56:59 -0700359 def test_reserved_enum_name(self):
360 ir = _make_ir_from_emb("enum Foo:\n" " NULL = 1\n")
361 error_name = ir.module[0].type[0].enumeration.value[0].name.name
362 self.assertEqual(
363 [
364 [
365 error.error(
366 "m.emb",
367 error_name.source_location,
368 "C reserved word may not be used as an enum name.",
369 )
370 ]
371 ],
372 error.filter_errors(constraints.check_constraints(ir)),
373 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700374
Dmitri Prime495d3f22024-09-06 16:56:59 -0700375 def test_bits_type_in_struct_array(self):
376 ir = _make_ir_from_emb(
377 '[$default byte_order: "LittleEndian"]\n'
378 "struct Foo:\n"
379 " 0 [+10] UInt:8[10] array\n"
380 )
381 self.assertEqual([], constraints.check_constraints(ir))
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700382
Dmitri Prime495d3f22024-09-06 16:56:59 -0700383 def test_bits_type_in_bits_array(self):
384 ir = _make_ir_from_emb("bits Foo:\n" " 0 [+10] UInt:8[10] array\n")
385 self.assertEqual([], constraints.check_constraints(ir))
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700386
Dmitri Prime495d3f22024-09-06 16:56:59 -0700387 def test_explicit_size_too_small(self):
388 ir = _make_ir_from_emb("bits Foo:\n" " 0 [+0] UInt:0 zero_bit\n")
389 error_field = ir.module[0].type[0].structure.field[0]
390 uint_type = ir_util.find_object(error_field.type.atomic_type.reference, ir)
391 uint_requirements = ir_util.get_attribute(
392 uint_type.attribute, attributes.STATIC_REQUIREMENTS
393 )
394 self.assertEqual(
395 [
396 [
397 error.error(
398 "m.emb",
399 error_field.source_location,
400 "Requirements of UInt not met.",
401 ),
402 error.note(
403 "",
404 uint_requirements.source_location,
405 "Requirements specified here.",
406 ),
407 ]
408 ],
409 error.filter_errors(constraints.check_constraints(ir)),
410 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700411
Dmitri Prime495d3f22024-09-06 16:56:59 -0700412 def test_explicit_enumeration_size_too_small(self):
413 ir = _make_ir_from_emb(
414 '[$default byte_order: "BigEndian"]\n'
415 "bits Foo:\n"
416 " 0 [+0] Bar:0 zero_bit\n"
417 "enum Bar:\n"
418 " BAZ = 0\n"
419 )
420 error_type = ir.module[0].type[0].structure.field[0].type
421 self.assertEqual(
422 [
423 [
424 error.error(
425 "m.emb",
426 error_type.source_location,
427 "Enumeration type 'Bar' cannot be 0 bits; type 'Bar' "
428 "must be between 1 and 64 bits, inclusive.",
429 ),
430 ]
431 ],
432 error.filter_errors(constraints.check_constraints(ir)),
433 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700434
Dmitri Prime495d3f22024-09-06 16:56:59 -0700435 def test_explicit_size_too_big_for_field(self):
436 ir = _make_ir_from_emb("bits Foo:\n" " 0 [+8] UInt:32 thirty_two_bit\n")
437 error_type = ir.module[0].type[0].structure.field[0].type
438 self.assertEqual(
439 [
440 [
441 error.error(
442 "m.emb",
443 error_type.source_location,
444 "Fixed-size type 'UInt:32' cannot be placed in field of size 8 "
445 "bits; requires 32 bits.",
446 )
447 ]
448 ],
449 error.filter_errors(constraints.check_constraints(ir)),
450 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700451
Dmitri Prime495d3f22024-09-06 16:56:59 -0700452 def test_explicit_size_too_small_for_field(self):
453 ir = _make_ir_from_emb("bits Foo:\n" " 0 [+64] UInt:32 thirty_two_bit\n")
454 error_type = ir.module[0].type[0].structure.field[0].type
455 self.assertEqual(
456 [
457 [
458 error.error(
459 "m.emb",
460 error_type.source_location,
461 "Fixed-size type 'UInt:32' cannot be placed in field of "
462 "size 64 bits; requires 32 bits.",
463 )
464 ]
465 ],
466 error.filter_errors(constraints.check_constraints(ir)),
467 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700468
Dmitri Prime495d3f22024-09-06 16:56:59 -0700469 def test_explicit_size_too_big(self):
470 ir = _make_ir_from_emb(
471 "struct Foo:\n"
472 " 0 [+16] UInt:128 one_twenty_eight_bit\n"
473 ' [byte_order: "LittleEndian"]\n'
474 )
475 error_field = ir.module[0].type[0].structure.field[0]
476 uint_type = ir_util.find_object(error_field.type.atomic_type.reference, ir)
477 uint_requirements = ir_util.get_attribute(
478 uint_type.attribute, attributes.STATIC_REQUIREMENTS
479 )
480 self.assertEqual(
481 [
482 [
483 error.error(
484 "m.emb",
485 error_field.source_location,
486 "Requirements of UInt not met.",
487 ),
488 error.note(
489 "",
490 uint_requirements.source_location,
491 "Requirements specified here.",
492 ),
493 ]
494 ],
495 error.filter_errors(constraints.check_constraints(ir)),
496 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700497
Dmitri Prime495d3f22024-09-06 16:56:59 -0700498 def test_explicit_enumeration_size_too_big(self):
499 ir = _make_ir_from_emb(
500 '[$default byte_order: "BigEndian"]\n'
501 "struct Foo:\n"
502 " 0 [+9] Bar seventy_two_bit\n"
503 "enum Bar:\n"
504 " BAZ = 0\n"
505 )
506 error_type = ir.module[0].type[0].structure.field[0].type
507 self.assertEqual(
508 [
509 [
510 error.error(
511 "m.emb",
512 error_type.source_location,
513 "Enumeration type 'Bar' cannot be 72 bits; type 'Bar' "
514 + "must be between 1 and 64 bits, inclusive.",
515 ),
516 ]
517 ],
518 error.filter_errors(constraints.check_constraints(ir)),
519 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700520
Dmitri Prime495d3f22024-09-06 16:56:59 -0700521 def test_explicit_enumeration_size_too_big_for_small_enum(self):
522 ir = _make_ir_from_emb(
523 '[$default byte_order: "BigEndian"]\n'
524 "struct Foo:\n"
525 " 0 [+8] Bar sixty_four_bit\n"
526 "enum Bar:\n"
527 " [maximum_bits: 63]\n"
528 " BAZ = 0\n"
529 )
530 error_type = ir.module[0].type[0].structure.field[0].type
531 self.assertEqual(
532 [
533 [
534 error.error(
535 "m.emb",
536 error_type.source_location,
537 "Enumeration type 'Bar' cannot be 64 bits; type 'Bar' "
538 + "must be between 1 and 63 bits, inclusive.",
539 ),
540 ]
541 ],
542 error.filter_errors(constraints.check_constraints(ir)),
543 )
reventlovc50913d2022-04-18 15:28:36 -0700544
Dmitri Prime495d3f22024-09-06 16:56:59 -0700545 def test_explicit_size_on_fixed_size_type(self):
546 ir = _make_ir_from_emb(
547 "struct Foo:\n"
548 " 0 [+1] Byte:8 one_byte\n"
549 "struct Byte:\n"
550 " 0 [+1] UInt b\n"
551 )
552 self.assertEqual([], constraints.check_constraints(ir))
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700553
Dmitri Prime495d3f22024-09-06 16:56:59 -0700554 def test_explicit_size_too_small_on_fixed_size_type(self):
555 ir = _make_ir_from_emb(
556 "struct Foo:\n"
557 " 0 [+0] Byte:0 null_byte\n"
558 "struct Byte:\n"
559 " 0 [+1] UInt b\n"
560 )
561 error_type = ir.module[0].type[0].structure.field[0].type
562 self.assertEqual(
563 [
564 [
565 error.error(
566 "m.emb",
567 error_type.size_in_bits.source_location,
568 "Explicit size of 0 bits does not match fixed size (8 bits) of "
569 "type 'Byte'.",
570 ),
571 error.note(
572 "m.emb",
573 ir.module[0].type[1].source_location,
574 "Size specified here.",
575 ),
576 ]
577 ],
578 error.filter_errors(constraints.check_constraints(ir)),
579 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700580
Dmitri Prime495d3f22024-09-06 16:56:59 -0700581 def test_explicit_size_too_big_on_fixed_size_type(self):
582 ir = _make_ir_from_emb(
583 "struct Foo:\n"
584 " 0 [+2] Byte:16 double_byte\n"
585 "struct Byte:\n"
586 " 0 [+1] UInt b\n"
587 )
588 error_type = ir.module[0].type[0].structure.field[0].type
589 self.assertEqual(
590 [
591 [
592 error.error(
593 "m.emb",
594 error_type.size_in_bits.source_location,
595 "Explicit size of 16 bits does not match fixed size (8 bits) of "
596 "type 'Byte'.",
597 ),
598 error.note(
599 "m.emb",
600 ir.module[0].type[1].source_location,
601 "Size specified here.",
602 ),
603 ]
604 ],
605 error.filter_errors(constraints.check_constraints(ir)),
606 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700607
Dmitri Prime495d3f22024-09-06 16:56:59 -0700608 def test_explicit_size_ignored_on_variable_size_type(self):
609 ir = _make_ir_from_emb(
610 '[$default byte_order: "LittleEndian"]\n'
611 "struct Foo:\n"
612 " 0 [+1] UInt n\n"
613 " 1 [+n] UInt:8[] d\n"
614 "struct Bar:\n"
615 " 0 [+10] Foo:80 foo\n"
616 )
617 self.assertEqual([], constraints.check_constraints(ir))
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700618
Dmitri Prime495d3f22024-09-06 16:56:59 -0700619 def test_fixed_size_type_in_dynamically_sized_field(self):
620 ir = _make_ir_from_emb(
621 "struct Foo:\n"
622 " 0 [+1] UInt bar\n"
623 " 0 [+bar] Byte one_byte\n"
624 "struct Byte:\n"
625 " 0 [+1] UInt b\n"
626 )
627 self.assertEqual([], constraints.check_constraints(ir))
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700628
Dmitri Prime495d3f22024-09-06 16:56:59 -0700629 def test_enum_in_dynamically_sized_field(self):
630 ir = _make_ir_from_emb(
631 '[$default byte_order: "BigEndian"]\n'
632 "struct Foo:\n"
633 " 0 [+1] UInt bar\n"
634 " 0 [+bar] Baz baz\n"
635 "enum Baz:\n"
636 " QUX = 0\n"
637 )
638 error_type = ir.module[0].type[0].structure.field[1].type
639 self.assertEqual(
640 [
641 [
642 error.error(
643 "m.emb",
644 error_type.source_location,
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700645 "Enumeration type 'Baz' cannot be placed in a "
Dmitri Prime495d3f22024-09-06 16:56:59 -0700646 "dynamically-sized field.",
647 )
648 ]
649 ],
650 error.filter_errors(constraints.check_constraints(ir)),
651 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700652
Dmitri Prime495d3f22024-09-06 16:56:59 -0700653 def test_enum_value_too_high(self):
654 ir = _make_ir_from_emb(
655 '[$default byte_order: "LittleEndian"]\n'
656 "enum Foo:\n"
657 " HIGH = 0x1_0000_0000_0000_0000\n"
658 )
659 error_value = ir.module[0].type[0].enumeration.value[0].value
660 self.assertEqual(
661 [
662 [
663 error.error(
664 "m.emb",
665 error_value.source_location,
666 # TODO(bolms): Try to print numbers like 2**64 in hex? (I.e., if a
667 # number is a round number in hex, but not in decimal, print in
668 # hex?)
669 "Value 18446744073709551616 is out of range for 64-bit unsigned "
670 + "enumeration.",
671 )
672 ]
673 ],
674 constraints.check_constraints(ir),
675 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700676
Dmitri Prime495d3f22024-09-06 16:56:59 -0700677 def test_enum_value_too_low(self):
678 ir = _make_ir_from_emb(
679 '[$default byte_order: "LittleEndian"]\n'
680 "enum Foo:\n"
681 " LOW = -0x8000_0000_0000_0001\n"
682 )
683 error_value = ir.module[0].type[0].enumeration.value[0].value
684 self.assertEqual(
685 [
686 [
687 error.error(
688 "m.emb",
689 error_value.source_location,
690 "Value -9223372036854775809 is out of range for 64-bit signed "
691 + "enumeration.",
692 )
693 ]
694 ],
695 constraints.check_constraints(ir),
696 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700697
Dmitri Prime495d3f22024-09-06 16:56:59 -0700698 def test_enum_value_too_wide(self):
699 ir = _make_ir_from_emb(
700 '[$default byte_order: "LittleEndian"]\n'
701 "enum Foo:\n"
702 " LOW = -1\n"
703 " HIGH = 0x8000_0000_0000_0000\n"
704 )
705 error_value = ir.module[0].type[0].enumeration.value[1].value
706 self.assertEqual(
707 [
708 [
709 error.error(
710 "m.emb",
711 error_value.source_location,
712 "Value 9223372036854775808 is out of range for 64-bit signed "
713 + "enumeration.",
714 )
715 ]
716 ],
717 error.filter_errors(constraints.check_constraints(ir)),
718 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700719
Dmitri Prime495d3f22024-09-06 16:56:59 -0700720 def test_enum_value_too_wide_unsigned_error_message(self):
721 ir = _make_ir_from_emb(
722 '[$default byte_order: "LittleEndian"]\n'
723 "enum Foo:\n"
724 " LOW = -2\n"
725 " LOW2 = -1\n"
726 " HIGH = 0x8000_0000_0000_0000\n"
727 )
728 error_value = ir.module[0].type[0].enumeration.value[2].value
729 self.assertEqual(
730 [
731 [
732 error.error(
733 "m.emb",
734 error_value.source_location,
735 "Value 9223372036854775808 is out of range for 64-bit signed "
736 + "enumeration.",
737 )
738 ]
739 ],
740 error.filter_errors(constraints.check_constraints(ir)),
741 )
reventlovc50913d2022-04-18 15:28:36 -0700742
Dmitri Prime495d3f22024-09-06 16:56:59 -0700743 def test_enum_value_too_wide_small_size_error_message(self):
744 ir = _make_ir_from_emb(
745 '[$default byte_order: "LittleEndian"]\n'
746 "enum Foo:\n"
747 " [maximum_bits: 8]\n"
748 " HIGH = 0x100\n"
749 )
750 error_value = ir.module[0].type[0].enumeration.value[0].value
751 self.assertEqual(
752 [
753 [
754 error.error(
755 "m.emb",
756 error_value.source_location,
757 "Value 256 is out of range for 8-bit unsigned enumeration.",
758 )
759 ]
760 ],
761 error.filter_errors(constraints.check_constraints(ir)),
762 )
reventlovc50913d2022-04-18 15:28:36 -0700763
Dmitri Prime495d3f22024-09-06 16:56:59 -0700764 def test_enum_value_too_wide_small_size_signed_error_message(self):
765 ir = _make_ir_from_emb(
766 '[$default byte_order: "LittleEndian"]\n'
767 "enum Foo:\n"
768 " [maximum_bits: 8]\n"
769 " [is_signed: true]\n"
770 " HIGH = 0x80\n"
771 )
772 error_value = ir.module[0].type[0].enumeration.value[0].value
773 self.assertEqual(
774 [
775 [
776 error.error(
777 "m.emb",
778 error_value.source_location,
779 "Value 128 is out of range for 8-bit signed enumeration.",
780 )
781 ]
782 ],
783 error.filter_errors(constraints.check_constraints(ir)),
784 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700785
Dmitri Prime495d3f22024-09-06 16:56:59 -0700786 def test_enum_value_too_wide_multiple(self):
787 ir = _make_ir_from_emb(
788 '[$default byte_order: "LittleEndian"]\n'
789 "enum Foo:\n"
790 " LOW = -2\n"
791 " LOW2 = -1\n"
792 " HIGH = 0x8000_0000_0000_0000\n"
793 " HIGH2 = 0x8000_0000_0000_0001\n"
794 )
795 error_value = ir.module[0].type[0].enumeration.value[2].value
796 error_value2 = ir.module[0].type[0].enumeration.value[3].value
797 self.assertEqual(
798 [
799 [
800 error.error(
801 "m.emb",
802 error_value.source_location,
803 "Value 9223372036854775808 is out of range for 64-bit signed "
804 + "enumeration.",
805 )
806 ],
807 [
808 error.error(
809 "m.emb",
810 error_value2.source_location,
811 "Value 9223372036854775809 is out of range for 64-bit signed "
812 + "enumeration.",
813 )
814 ],
815 ],
816 error.filter_errors(constraints.check_constraints(ir)),
817 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700818
Dmitri Prime495d3f22024-09-06 16:56:59 -0700819 def test_enum_value_too_wide_multiple_signed_error_message(self):
820 ir = _make_ir_from_emb(
821 '[$default byte_order: "LittleEndian"]\n'
822 "enum Foo:\n"
823 " LOW = -3\n"
824 " LOW2 = -2\n"
825 " LOW3 = -1\n"
826 " HIGH = 0x8000_0000_0000_0000\n"
827 " HIGH2 = 0x8000_0000_0000_0001\n"
828 )
829 error_value = ir.module[0].type[0].enumeration.value[3].value
830 error_value2 = ir.module[0].type[0].enumeration.value[4].value
831 self.assertEqual(
832 [
833 [
834 error.error(
835 "m.emb",
836 error_value.source_location,
837 "Value 9223372036854775808 is out of range for 64-bit signed "
838 "enumeration.",
839 )
840 ],
841 [
842 error.error(
843 "m.emb",
844 error_value2.source_location,
845 "Value 9223372036854775809 is out of range for 64-bit signed "
846 "enumeration.",
847 )
848 ],
849 ],
850 error.filter_errors(constraints.check_constraints(ir)),
851 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700852
Dmitri Prime495d3f22024-09-06 16:56:59 -0700853 def test_enum_value_mixed_error_message(self):
854 ir = _make_ir_from_emb(
855 '[$default byte_order: "LittleEndian"]\n'
856 "enum Foo:\n"
857 " LOW = -1\n"
858 " HIGH = 0x8000_0000_0000_0000\n"
859 " HIGH2 = 0x1_0000_0000_0000_0000\n"
860 )
861 error_value1 = ir.module[0].type[0].enumeration.value[1].value
862 error_value2 = ir.module[0].type[0].enumeration.value[2].value
863 self.assertEqual(
864 [
865 [
866 error.error(
867 "m.emb",
868 error_value1.source_location,
869 "Value 9223372036854775808 is out of range for 64-bit signed "
870 + "enumeration.",
871 )
872 ],
873 [
874 error.error(
875 "m.emb",
876 error_value2.source_location,
877 "Value 18446744073709551616 is out of range for 64-bit signed "
878 + "enumeration.",
879 )
880 ],
881 ],
882 error.filter_errors(constraints.check_constraints(ir)),
883 )
reventlovc50913d2022-04-18 15:28:36 -0700884
Dmitri Prime495d3f22024-09-06 16:56:59 -0700885 def test_enum_value_explicitly_signed_error_message(self):
886 ir = _make_ir_from_emb(
887 '[$default byte_order: "LittleEndian"]\n'
888 "enum Foo:\n"
889 " [is_signed: true]\n"
890 " HIGH = 0x8000_0000_0000_0000\n"
891 " HIGH2 = 0x1_0000_0000_0000_0000\n"
892 )
893 error_value0 = ir.module[0].type[0].enumeration.value[0].value
894 error_value1 = ir.module[0].type[0].enumeration.value[1].value
895 self.assertEqual(
896 [
897 [
898 error.error(
899 "m.emb",
900 error_value0.source_location,
901 "Value 9223372036854775808 is out of range for 64-bit signed "
902 + "enumeration.",
903 )
904 ],
905 [
906 error.error(
907 "m.emb",
908 error_value1.source_location,
909 "Value 18446744073709551616 is out of range for 64-bit signed "
910 + "enumeration.",
911 )
912 ],
913 ],
914 error.filter_errors(constraints.check_constraints(ir)),
915 )
reventlovc50913d2022-04-18 15:28:36 -0700916
Dmitri Prime495d3f22024-09-06 16:56:59 -0700917 def test_enum_value_explicitly_unsigned_error_message(self):
918 ir = _make_ir_from_emb(
919 '[$default byte_order: "LittleEndian"]\n'
920 "enum Foo:\n"
921 " [is_signed: false]\n"
922 " LOW = -1\n"
923 " HIGH = 0x8000_0000_0000_0000\n"
924 " HIGH2 = 0x1_0000_0000_0000_0000\n"
925 )
926 error_value0 = ir.module[0].type[0].enumeration.value[0].value
927 error_value2 = ir.module[0].type[0].enumeration.value[2].value
928 self.assertEqual(
929 [
930 [
931 error.error(
932 "m.emb",
933 error_value0.source_location,
934 "Value -1 is out of range for 64-bit unsigned enumeration.",
935 )
936 ],
937 [
938 error.error(
939 "m.emb",
940 error_value2.source_location,
941 "Value 18446744073709551616 is out of range for 64-bit unsigned "
942 + "enumeration.",
943 )
944 ],
945 ],
946 error.filter_errors(constraints.check_constraints(ir)),
947 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700948
Dmitri Prime495d3f22024-09-06 16:56:59 -0700949 def test_explicit_non_byte_size_array_element(self):
950 ir = _make_ir_from_emb(
951 '[$default byte_order: "LittleEndian"]\n'
952 "struct Foo:\n"
953 " 0 [+2] UInt:4[4] nibbles\n"
954 )
955 error_type = ir.module[0].type[0].structure.field[0].type.array_type
956 self.assertEqual(
957 [
958 [
959 error.error(
960 "m.emb",
961 error_type.base_type.source_location,
962 "Array elements in structs must have sizes which are a multiple of "
963 "8 bits.",
964 )
965 ]
966 ],
967 error.filter_errors(constraints.check_constraints(ir)),
968 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700969
Dmitri Prime495d3f22024-09-06 16:56:59 -0700970 def test_implicit_non_byte_size_array_element(self):
971 ir = _make_ir_from_emb(
972 '[$default byte_order: "LittleEndian"]\n'
973 "bits Nibble:\n"
974 " 0 [+4] UInt nibble\n"
975 "struct Foo:\n"
976 " 0 [+2] Nibble[4] nibbles\n"
977 )
978 error_type = ir.module[0].type[1].structure.field[0].type.array_type
979 self.assertEqual(
980 [
981 [
982 error.error(
983 "m.emb",
984 error_type.base_type.source_location,
985 "Array elements in structs must have sizes which are a multiple of "
986 "8 bits.",
987 )
988 ]
989 ],
990 error.filter_errors(constraints.check_constraints(ir)),
991 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -0700992
Dmitri Prime495d3f22024-09-06 16:56:59 -0700993 def test_bits_must_be_fixed_size(self):
994 ir = _make_ir_from_emb(
995 "bits Dynamic:\n"
996 " 0 [+3] UInt x\n"
997 " 3 [+3 * x] UInt:3[x] a\n"
998 )
999 error_type = ir.module[0].type[0]
1000 self.assertEqual(
1001 [
1002 [
1003 error.error(
1004 "m.emb",
1005 error_type.source_location,
1006 "`bits` types must be fixed size.",
1007 )
1008 ]
1009 ],
1010 error.filter_errors(constraints.check_constraints(ir)),
1011 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -07001012
Dmitri Prime495d3f22024-09-06 16:56:59 -07001013 def test_bits_must_be_small(self):
1014 ir = _make_ir_from_emb(
1015 "bits Big:\n" " 0 [+64] UInt x\n" " 64 [+1] UInt y\n"
1016 )
1017 error_type = ir.module[0].type[0]
1018 self.assertEqual(
1019 [
1020 [
1021 error.error(
1022 "m.emb",
1023 error_type.source_location,
1024 "`bits` types must be 64 bits or smaller.",
1025 )
1026 ]
1027 ],
1028 error.filter_errors(constraints.check_constraints(ir)),
1029 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -07001030
Dmitri Prime495d3f22024-09-06 16:56:59 -07001031 def test_constant_expressions_must_be_small(self):
1032 ir = _make_ir_from_emb(
1033 '[$default byte_order: "LittleEndian"]\n'
1034 "struct Foo:\n"
1035 " 0 [+8] UInt x\n"
1036 " if x < 0x1_0000_0000_0000_0000:\n"
1037 " 8 [+1] UInt y\n"
1038 )
1039 condition = ir.module[0].type[0].structure.field[1].existence_condition
1040 error_location = condition.function.args[1].source_location
1041 self.assertEqual(
1042 [
1043 [
1044 error.error(
1045 "m.emb",
1046 error_location,
1047 "Constant value {} of expression cannot fit in a 64-bit signed or "
1048 "unsigned integer.".format(2**64),
1049 )
1050 ]
1051 ],
1052 error.filter_errors(constraints.check_constraints(ir)),
1053 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -07001054
Dmitri Prime495d3f22024-09-06 16:56:59 -07001055 def test_variable_expression_out_of_range_for_uint64(self):
1056 ir = _make_ir_from_emb(
1057 '[$default byte_order: "LittleEndian"]\n'
1058 "struct Foo:\n"
1059 " 0 [+8] UInt x\n"
1060 " if x + 1 < 0xffff_ffff_ffff_ffff:\n"
1061 " 8 [+1] UInt y\n"
1062 )
1063 condition = ir.module[0].type[0].structure.field[1].existence_condition
1064 error_location = condition.function.args[0].source_location
1065 self.assertEqual(
1066 [
1067 [
1068 error.error(
1069 "m.emb",
1070 error_location,
1071 "Potential range of expression is {} to {}, which cannot fit in a "
1072 "64-bit signed or unsigned integer.".format(1, 2**64),
1073 )
1074 ]
1075 ],
1076 error.filter_errors(constraints.check_constraints(ir)),
1077 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -07001078
Dmitri Prime495d3f22024-09-06 16:56:59 -07001079 def test_variable_expression_out_of_range_for_int64(self):
1080 ir = _make_ir_from_emb(
1081 '[$default byte_order: "LittleEndian"]\n'
1082 "struct Foo:\n"
1083 " 0 [+8] UInt x\n"
1084 " if x - 0x8000_0000_0000_0001 < 0:\n"
1085 " 8 [+1] UInt y\n"
1086 )
1087 condition = ir.module[0].type[0].structure.field[1].existence_condition
1088 error_location = condition.function.args[0].source_location
1089 self.assertEqual(
1090 [
1091 [
1092 error.error(
1093 "m.emb",
1094 error_location,
1095 "Potential range of expression is {} to {}, which cannot fit in a "
1096 "64-bit signed or unsigned integer.".format(
1097 -(2**63) - 1, 2**63 - 2
1098 ),
1099 )
1100 ]
1101 ],
1102 error.filter_errors(constraints.check_constraints(ir)),
1103 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -07001104
Dmitri Prime495d3f22024-09-06 16:56:59 -07001105 def test_requires_expression_out_of_range_for_uint64(self):
1106 ir = _make_ir_from_emb(
1107 '[$default byte_order: "LittleEndian"]\n'
1108 "struct Foo:\n"
1109 " 0 [+8] UInt x\n"
1110 " [requires: this * 2 < 0x1_0000]\n"
1111 )
1112 attribute_list = ir.module[0].type[0].structure.field[0].attribute
1113 error_arg = attribute_list[0].value.expression.function.args[0]
1114 error_location = error_arg.source_location
1115 self.assertEqual(
1116 [
1117 [
1118 error.error(
1119 "m.emb",
1120 error_location,
1121 "Potential range of expression is {} to {}, which cannot fit "
1122 "in a 64-bit signed or unsigned integer.".format(0, 2**65 - 2),
1123 )
1124 ]
1125 ],
1126 error.filter_errors(constraints.check_constraints(ir)),
1127 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -07001128
Dmitri Prime495d3f22024-09-06 16:56:59 -07001129 def test_arguments_require_different_signedness_64_bits(self):
1130 ir = _make_ir_from_emb(
1131 '[$default byte_order: "LittleEndian"]\n'
1132 "struct Foo:\n"
1133 " 0 [+1] UInt x\n"
1134 # Left side requires uint64, right side requires int64.
1135 " if (x + 0x8000_0000_0000_0000) + (x - 0x7fff_ffff_ffff_ffff) < 10:\n"
1136 " 1 [+1] UInt y\n"
1137 )
1138 condition = ir.module[0].type[0].structure.field[1].existence_condition
1139 error_expression = condition.function.args[0]
1140 error_location = error_expression.source_location
1141 arg0_location = error_expression.function.args[0].source_location
1142 arg1_location = error_expression.function.args[1].source_location
1143 self.assertEqual(
1144 [
1145 [
1146 error.error(
1147 "m.emb",
1148 error_location,
1149 "Either all arguments to '+' and its result must fit in a 64-bit "
1150 "unsigned integer, or all must fit in a 64-bit signed integer.",
1151 ),
1152 error.note(
1153 "m.emb", arg0_location, "Requires unsigned 64-bit integer."
1154 ),
1155 error.note(
1156 "m.emb", arg1_location, "Requires signed 64-bit integer."
1157 ),
1158 ]
1159 ],
1160 error.filter_errors(constraints.check_constraints(ir)),
1161 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -07001162
Dmitri Prime495d3f22024-09-06 16:56:59 -07001163 def test_return_value_requires_different_signedness_from_arguments(self):
1164 ir = _make_ir_from_emb(
1165 '[$default byte_order: "LittleEndian"]\n'
1166 "struct Foo:\n"
1167 " 0 [+1] UInt x\n"
1168 # Both arguments require uint64; result fits in int64.
1169 " if (x + 0x7fff_ffff_ffff_ffff) - 0x8000_0000_0000_0000 < 10:\n"
1170 " 1 [+1] UInt y\n"
1171 )
1172 condition = ir.module[0].type[0].structure.field[1].existence_condition
1173 error_expression = condition.function.args[0]
1174 error_location = error_expression.source_location
1175 arg0_location = error_expression.function.args[0].source_location
1176 arg1_location = error_expression.function.args[1].source_location
1177 self.assertEqual(
1178 [
1179 [
1180 error.error(
1181 "m.emb",
1182 error_location,
1183 "Either all arguments to '-' and its result must fit in a 64-bit "
1184 "unsigned integer, or all must fit in a 64-bit signed integer.",
1185 ),
1186 error.note(
1187 "m.emb", arg0_location, "Requires unsigned 64-bit integer."
1188 ),
1189 error.note(
1190 "m.emb", arg1_location, "Requires unsigned 64-bit integer."
1191 ),
1192 error.note(
1193 "m.emb", error_location, "Requires signed 64-bit integer."
1194 ),
1195 ]
1196 ],
1197 error.filter_errors(constraints.check_constraints(ir)),
1198 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -07001199
Dmitri Prime495d3f22024-09-06 16:56:59 -07001200 def test_return_value_requires_different_signedness_from_one_argument(self):
1201 ir = _make_ir_from_emb(
1202 '[$default byte_order: "LittleEndian"]\n'
1203 "struct Foo:\n"
1204 " 0 [+1] UInt x\n"
1205 # One argument requires uint64; result fits in int64.
1206 " if (x + 0x7fff_ffff_ffff_fff0) - 0x7fff_ffff_ffff_ffff < 10:\n"
1207 " 1 [+1] UInt y\n"
1208 )
1209 condition = ir.module[0].type[0].structure.field[1].existence_condition
1210 error_expression = condition.function.args[0]
1211 error_location = error_expression.source_location
1212 arg0_location = error_expression.function.args[0].source_location
1213 self.assertEqual(
1214 [
1215 [
1216 error.error(
1217 "m.emb",
1218 error_location,
1219 "Either all arguments to '-' and its result must fit in a 64-bit "
1220 "unsigned integer, or all must fit in a 64-bit signed integer.",
1221 ),
1222 error.note(
1223 "m.emb", arg0_location, "Requires unsigned 64-bit integer."
1224 ),
1225 error.note(
1226 "m.emb", error_location, "Requires signed 64-bit integer."
1227 ),
1228 ]
1229 ],
1230 error.filter_errors(constraints.check_constraints(ir)),
1231 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -07001232
Dmitri Prime495d3f22024-09-06 16:56:59 -07001233 def test_checks_constancy_of_constant_references(self):
1234 ir = _make_ir_from_emb(
1235 "struct Foo:\n" " 0 [+1] UInt x\n" " let y = x\n" " let z = Foo.y\n"
1236 )
1237 error_expression = ir.module[0].type[0].structure.field[2].read_transform
1238 error_location = error_expression.source_location
1239 note_field = ir.module[0].type[0].structure.field[1]
1240 note_location = note_field.source_location
1241 self.assertEqual(
1242 [
1243 [
1244 error.error(
1245 "m.emb",
1246 error_location,
1247 "Static references must refer to constants.",
1248 ),
1249 error.note("m.emb", note_location, "y is not constant."),
1250 ]
1251 ],
1252 error.filter_errors(constraints.check_constraints(ir)),
1253 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -07001254
Dmitri Prime495d3f22024-09-06 16:56:59 -07001255 def test_checks_for_explicit_size_on_parameters(self):
1256 ir = _make_ir_from_emb("struct Foo(y: UInt):\n" " 0 [+1] UInt x\n")
1257 error_parameter = ir.module[0].type[0].runtime_parameter[0]
1258 error_location = error_parameter.physical_type_alias.source_location
1259 self.assertEqual(
1260 [
1261 [
1262 error.error(
1263 "m.emb",
1264 error_location,
1265 "Integer range of parameter must not be unbounded; it "
1266 "must fit in a 64-bit signed or unsigned integer.",
1267 )
1268 ]
1269 ],
1270 error.filter_errors(constraints.check_constraints(ir)),
1271 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -07001272
Dmitri Prime495d3f22024-09-06 16:56:59 -07001273 def test_checks_for_correct_explicit_size_on_parameters(self):
1274 ir = _make_ir_from_emb("struct Foo(y: UInt:300):\n" " 0 [+1] UInt x\n")
1275 error_parameter = ir.module[0].type[0].runtime_parameter[0]
1276 error_location = error_parameter.physical_type_alias.source_location
1277 self.assertEqual(
1278 [
1279 [
1280 error.error(
1281 "m.emb",
1282 error_location,
1283 "Potential range of parameter is 0 to {}, which cannot "
1284 "fit in a 64-bit signed or unsigned integer.".format(
1285 2**300 - 1
1286 ),
1287 )
1288 ]
1289 ],
1290 error.filter_errors(constraints.check_constraints(ir)),
1291 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -07001292
Dmitri Prime495d3f22024-09-06 16:56:59 -07001293 def test_checks_for_explicit_enum_size_on_parameters(self):
1294 ir = _make_ir_from_emb(
1295 "struct Foo(y: Bar:8):\n" " 0 [+1] UInt x\n" "enum Bar:\n" " QUX = 1\n"
1296 )
1297 error_parameter = ir.module[0].type[0].runtime_parameter[0]
1298 error_size = error_parameter.physical_type_alias.size_in_bits
1299 error_location = error_size.source_location
1300 self.assertEqual(
1301 [
1302 [
1303 error.error(
1304 "m.emb",
1305 error_location,
1306 "Parameters with enum type may not have explicit size.",
1307 )
1308 ]
1309 ],
1310 error.filter_errors(constraints.check_constraints(ir)),
1311 )
Ben Olmsteadc0d77842019-07-31 17:34:05 -07001312
1313
1314if __name__ == "__main__":
Dmitri Prime495d3f22024-09-06 16:56:59 -07001315 unittest.main()