Skip to content

Rust: Refactor Architecture trait to enforce method implementations for associated types at compile-time#7942

Open
mkrasnitski wants to merge 3 commits intoVector35:devfrom
mkrasnitski:architecture-methods
Open

Rust: Refactor Architecture trait to enforce method implementations for associated types at compile-time#7942
mkrasnitski wants to merge 3 commits intoVector35:devfrom
mkrasnitski:architecture-methods

Conversation

@mkrasnitski
Copy link
Contributor

@mkrasnitski mkrasnitski commented Feb 5, 2026

Currently, the Architecture trait has lots of methods which are documented as required only if a specific feature is supported by the architecture. For example, if an architecture does not use flags, then Architecture::Flag can be set to UnusedFlag. Otherwise, you need to provide a custom type which implements Flag, and you must also override the default implementations of Architecture::flags and Architecture::flag_from_id. This is a brittle approach because it's not enforced by the compiler. What this PR does is create corresponding required methods on the Flag trait which are then simply wrapped by the methods on Architecture.

In total, the following traits are refactored in this way:

  • Flag
  • FlagWrite
  • FlagClass
  • FlagGroup
  • Intrinsic
  • Register
  • RegisterStack

All the methods return some variant of Self, Option<Self>, or Vec<Self>, and are therefore associated methods which do not take &self as an argument. However, in order for the various Core* structs (like CoreFlag, CoreRegister, etc.) to implement these new methods, I had to add an arch: &CoreArchitecture parameter through which the raw handle could be accessed when performing raw API calls into the core. Most custom architectures will not use this parameter so it's slightly less ergonomic this way, but I wasn't able to find a workaround. Maybe generics could help here?

Other miscellaneous things of note:

  • I added UnusedFlagClass and UnusedFlagGroup structs which reduce boilerplate for custom architectures with simple flag implementations.
  • I changed Register::registers_full_width to no longer be required by having it call Register::registers_all by default, and added a doc-comment that it should be overridden if the architecture has any non-fullwidth registers.

* Add `UnusedFlagClass` and `UnusedFlagGroup` structs
* Move the following methods from the `Architecture` trait into the
  various flag traits and pruned their list of super traits:
  * `Architecture::{flags, flag_from_id}` moved into `Flag`
  * `Architecture::{flag_write_types, flag_write_from_id}` moved into `FlagWrite`
  * `Architecture::{flag_classes, flag_class_from_id}` moved into `FlagClass`
  * `Architecture::{flag_groups, flag_group_from_id}` moved into `FlagGroup`
Move `Architecture::{intrinsics, intrinsic_from_id}` into the
`Intrinsic` trait.
Move `Architecture::{register_stacks, register_stack_from_id}` into the
`RegisterStack` trait. Plus, move the following into the `Register` trait:
  * `Architecture::registers_all`
  * `Architecture::registers_full_width`
  * `Architecture::registers_global`
  * `Architecture::registers_system`
  * `Architecture::stack_pointer_reg`
  * `Architecture::link_reg`
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