|
8 | 8 | icmp ugt vs sgt, lshr vs ashr, and the trunc/zext pair that wraps u32 * u32. |
9 | 9 | """ |
10 | 10 |
|
| 11 | +import importlib.util |
11 | 12 | import re |
12 | 13 | from pathlib import Path |
13 | 14 |
|
14 | 15 | import pytest |
15 | 16 |
|
16 | 17 | from tests.framework.compiler import run_ir_generation |
17 | 18 |
|
18 | | -SIGNEDNESS_DIR = Path(__file__).parent / "passing_tests" / "signedness" |
| 19 | +PASSING_DIR = Path(__file__).parent / "passing_tests" |
| 20 | +HAVE_VMLINUX = importlib.util.find_spec("vmlinux") is not None |
19 | 21 |
|
20 | | -# file -> (patterns that must appear, patterns that must not) |
| 22 | +# path under passing_tests -> (patterns that must appear, patterns that must not) |
21 | 23 | CASES = { |
22 | | - "widen_unsigned.py": ( |
| 24 | + "signedness/widen_unsigned.py": ( |
23 | 25 | [r"zext i32 .* to i64"], |
24 | 26 | [r"sext i32 .* to i64"], |
25 | 27 | ), |
26 | | - "widen_signed.py": ( |
| 28 | + "signedness/widen_signed.py": ( |
27 | 29 | [r"sext i32 .* to i64"], |
28 | 30 | [r"zext i32 .* to i64"], |
29 | 31 | ), |
30 | | - "mixed_division.py": ( |
| 32 | + "signedness/mixed_division.py": ( |
31 | 33 | [r"\budiv i64", r"\burem i64", r"\bsdiv i64"], |
32 | 34 | [r"\bsrem i64"], |
33 | 35 | ), |
34 | | - "unsigned_compare.py": ( |
| 36 | + "signedness/unsigned_compare.py": ( |
35 | 37 | [r"icmp ugt i64", r"icmp sgt i64"], |
36 | 38 | [], |
37 | 39 | ), |
38 | | - "narrow_wrap.py": ( |
| 40 | + "signedness/narrow_wrap.py": ( |
39 | 41 | # the product is computed at 64 bits, cut to 32, then zero-extended |
40 | 42 | [r"\bmul i64", r"trunc i64 .* to i32", r"zext i32 .* to i64"], |
41 | 43 | [r"sext i32 .* to i64"], |
42 | 44 | ), |
43 | | - "right_shift.py": ( |
| 45 | + "signedness/right_shift.py": ( |
44 | 46 | [r"\blshr i64 .*, 4", r"\bashr i64 .*, 4"], |
45 | 47 | [], |
46 | 48 | ), |
47 | | - "literal_rank.py": ( |
| 49 | + "signedness/literal_rank.py": ( |
48 | 50 | [r"\budiv i64 .*, 4294967294"], |
49 | 51 | [r"\bsdiv i64"], |
50 | 52 | ), |
| 53 | + # An enum constant is a C `int`, so `XDP_PASS - k` with k a c_uint32 is a |
| 54 | + # u32 operation: the result is cut to 32 bits and zero-extended. Ranked |
| 55 | + # as i64 it would be a signed 64-bit subtraction with no trunc at all. |
| 56 | + "vmlinux/enum_rank.py": ( |
| 57 | + [r"trunc i64 .* to i32", r"zext i32 .* to i64"], |
| 58 | + [r"sext i32 .* to i64"], |
| 59 | + ), |
| 60 | + # `return p` on a map lookup dereferences through a null check and returns |
| 61 | + # the i64, never the pointer. |
| 62 | + "return/map_value.py": ( |
| 63 | + [r"deref_0_not_null", r"ret i64 %"], |
| 64 | + [r"ret i64\*"], |
| 65 | + ), |
51 | 66 | } |
52 | 67 |
|
53 | 68 |
|
54 | 69 | @pytest.mark.parametrize("name", list(CASES)) |
55 | 70 | def test_signedness_ir_shape(name, tmp_path): |
56 | | - ll_path = tmp_path / name.replace(".py", ".ll") |
57 | | - run_ir_generation(SIGNEDNESS_DIR / name, ll_path) |
| 71 | + if name.startswith("vmlinux/") and not HAVE_VMLINUX: |
| 72 | + pytest.skip("vmlinux.py not importable") |
| 73 | + ll_path = tmp_path / Path(name).name.replace(".py", ".ll") |
| 74 | + run_ir_generation(PASSING_DIR / name, ll_path) |
58 | 75 | ir_text = ll_path.read_text() |
59 | 76 |
|
60 | 77 | expected, forbidden = CASES[name] |
|
0 commit comments