Skip to content

[Target] Enforce invariants through setters - #9250

Open
alexreinking wants to merge 6 commits into
alexreinking/target-gettersfrom
alexreinking/target-integrity
Open

[Target] Enforce invariants through setters#9250
alexreinking wants to merge 6 commits into
alexreinking/target-gettersfrom
alexreinking/target-integrity

Conversation

@alexreinking

@alexreinking alexreinking commented Jul 28, 2026

Copy link
Copy Markdown
Member

Strengthen the contract on setters to ensure that Target(t.to_string()) == t holds. Previously, t could be pushed into an invalid state that the Target() constructor would reject via its validation function.

Add a fuzz tester for target invariants.

Drive-by: Removes unused EGL feature.

Breaking changes

Downstreams that construct illegal target strings will now see exceptions upon construction, rather than upon use.

Checklist

  • Tests added or updated (not required for docs, CI config, or typo fixes)
  • Documentation updated (if public API changed)
  • Python bindings updated (if public API changed)
  • Benchmarks are included here if the change is intended to affect performance.
  • Commits include AI attribution where applicable (see Code of Conduct)

Stack created with GitHub Stacks CLIGive Feedback 💬

alexreinking and others added 5 commits July 28, 2026 15:47
Extend validate_features() with more checks for blatantly incoherent
targets, each enforced through the copy-validate-commit setters so they
cannot be bypassed:

- vector_bits requires a scalable-vector feature (SVE/SVE2/RVV/AVX10_1)
- large_buffers requires a 64-bit target
- profile and profile_by_timer are mutually exclusive
- simulator requires the iOS OS
- device sub-features require their parent (cuda capabilities require
  cuda, cl_* require opencl, vk_* require vulkan, hlsl_sm* require
  d3d12compute), via a shared sub_features_by_parent() table that
  subsumes the previous d3d12-specific check

set_bits/set_vector_bits now validate, and the constructor sets
vector_bits after features (its validity depends on them). All rules
permit OSUnknown / bits==0 so freestanding and device sub-targets still
construct.

Enforcing the sub-feature rule made JITModule's per-feature GPU
stripping throw (it cleared a parent while sub-features remained).
Replace it with Target::without_device_features(), which clears every
device-offload feature together with its sub-features.

Covered by test/fuzz/target_invariants.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
EGL was a vestige of the removed OpenGL Compute support: nothing reads
has_feature(EGL), so it had no codegen or runtime effect. Drop the
enumerator and its Target::Feature, name-map, and Python-binding entries.

Removing halide_target_feature_egl renumbers the subsequent
halide_target_feature_t values, matching how earlier feature removals
were handled (targets serialize by name, not by raw enum value).

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Add test/error coverage for the user_error/user_assert paths in
Target.cpp that lacked dedicated tests, most of them the newly-added
integrity checks:

- feature incompatible with arch (sve2 on x86)
- sub-feature without its parent (cuda_capability without cuda)
- processor tuning invalid for arch (tune_znver4 on arm)
- vector_bits without a scalable-vector feature
- large_buffers on a 32-bit target
- profile together with profile_by_timer
- simulator without iOS
- set_bits with an invalid width, set_vector_bits negative,
  set_feature with an out-of-range feature
- natural_vector_size on a hexagon target without hvx
- an unrecognized target-string token
- no_bounds_query in HL_JIT_TARGET (skipped on Windows, no setenv)

The has_unknowns bad_target_string path and natural_vector_size on an
unknown target are already covered by incomplete_target.cpp and
unknown_target.cpp. The remaining user_asserts are host CPUID probes
(no SSE2 / no AltiVec) and the JIT host-mismatch check, which depend on
the host/environment and aren't portably unit-testable.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
The new setter-enforced invariants surfaced three cases where existing
code produced a now-invalid Target:

- Dropping the last scalable-vector feature (e.g. deriving a non-SVE
  target from an SVE host, as warning/emulated_float16 does) left
  vector_bits orphaned. set_feature/set_features now clear it when no
  scalable-vector feature remains.
- tutorial/lesson_11 reused one Target across cross-compiles, so x86
  features lingered when the arch was switched to ARM. Start each
  cross-compile from a fresh Target.
- realize_larger_than_two_gigs set large_buffers unconditionally; it
  can't run faithfully on a 32-bit target, so it now [SKIP]s there.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@alexreinking
alexreinking marked this pull request as ready for review July 29, 2026 02:00
@codecov

codecov Bot commented Jul 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 68.45238% with 53 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.22%. Comparing base (0260779) to head (9886da2).

Files with missing lines Patch % Lines
src/Target.cpp 67.48% 44 Missing and 9 partials ⚠️
Additional details and impacted files
@@                       Coverage Diff                       @@
##           alexreinking/target-getters    #9250      +/-   ##
===============================================================
- Coverage                        70.31%   70.22%   -0.10%     
===============================================================
  Files                              255      255              
  Lines                            78916    79039     +123     
  Branches                         18866    18887      +21     
===============================================================
+ Hits                             55491    55503      +12     
- Misses                           17832    17888      +56     
- Partials                          5593     5648      +55     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant