miden_assembly/id.rs
1use crate::ast::ProcedureIndex;
2
3/// Uniquely identifies a procedure in a set of [crate::ast::Module]
4///
5/// A [GlobalProcedureIndex] is assigned to a procedure when it is added to the linker's module
6/// graph. The index uniquely identifies that procedure in the graph, and provides a unique,
7/// copyable, machine-word sized handle that can be trivially stored, passed around, and later used
8/// to perform constant-complexity operations against that procedure.
9///
10/// <div class="warning">
11/// As a result of this being just an index into a specific instance of a [super::ModuleGraph],
12/// it does not provide any guarantees about uniqueness or stability when the same module is stored
13/// in multiple graphs - each graph may assign it a unique index. You must ensure that you do not
14/// store these indices and attempt to use them with just any module graph - it is only valid with
15/// the one it was assigned from.
16/// </div>
17///
18/// In addition to the linker's module graph, these indices are also used with an instance of a
19/// `MastForestBuilder`. This is because the linker and `MastForestBuilder` instances
20/// are paired, i.e. the linker stores the syntax trees and call graph analysis for a program, while
21/// the `MastForestBuilder` caches the compiled [crate::Procedure]s for the same program, as
22/// derived from the corresponding graph.
23///
24/// This is intended for use when we are doing global inter-procedural analysis on a (possibly
25/// growable) set of modules. It is expected that the index of a module in the set, as well as the
26/// index of a procedure in a module, are stable once allocated in the graph. The set of modules and
27/// functions can grow, as long as growing the set only allocates unused identifiers.
28///
29/// NOTE: This struct is the same size as a u32
30#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
31pub struct GlobalProcedureIndex {
32 /// The index of the containing module in the global set of modules
33 pub module: ModuleIndex,
34 /// The local index of the procedure in the module
35 pub index: ProcedureIndex,
36}
37
38/// A strongly-typed index into a set of [crate::ast::Module]
39#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
40#[repr(transparent)]
41pub struct ModuleIndex(u16);
42impl ModuleIndex {
43 pub fn new(index: usize) -> Self {
44 Self(index.try_into().expect("invalid module index: too many modules"))
45 }
46
47 #[cfg(test)]
48 pub const fn const_new(index: u16) -> Self {
49 Self(index)
50 }
51
52 #[inline(always)]
53 pub const fn as_usize(&self) -> usize {
54 self.0 as usize
55 }
56}
57
58impl core::ops::Add<ProcedureIndex> for ModuleIndex {
59 type Output = GlobalProcedureIndex;
60
61 fn add(self, rhs: ProcedureIndex) -> Self::Output {
62 GlobalProcedureIndex { module: self, index: rhs }
63 }
64}
65
66impl core::fmt::Display for ModuleIndex {
67 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
68 write!(f, "{}", &self.as_usize())
69 }
70}