Skip to content

Commit

Permalink
feat: implement local variables
Browse files Browse the repository at this point in the history
This commit introduces a new data type to represent local variable
declarations. These are not currently attached to anything, but are used
downstream during code generation. The local identifiers are also used
in the in-crate representation of Miden Assembly, coming in a follow-on
commit.
  • Loading branch information
bitwalker committed Sep 7, 2023
1 parent 62598b1 commit 840eacd
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 0 deletions.
2 changes: 2 additions & 0 deletions hir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ mod immediates;
mod insert;
mod instruction;
mod layout;
mod locals;
mod module;
mod program;
#[cfg(test)]
Expand All @@ -40,6 +41,7 @@ pub use self::immediates::Immediate;
pub use self::insert::{Insert, InsertionPoint};
pub use self::instruction::*;
pub use self::layout::{ArenaMap, LayoutAdapter, LayoutNode, OrderedArenaMap};
pub use self::locals::{Local, LocalId};
pub use self::module::*;
pub use self::program::{Linker, LinkerError, Program};
pub use self::value::{Value, ValueData, ValueList, ValueListPool};
Expand Down
86 changes: 86 additions & 0 deletions hir/src/locals.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use std::{alloc::Layout, fmt};

use super::Type;

/// A strongly typed identifier for referencing locals associated with a function
#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct LocalId(u8);
impl LocalId {
/// Create a new instance from a `u32`.
#[inline]
pub fn from_u8(x: u8) -> Self {
debug_assert!(x < u8::MAX, "invalid raw local id");
Self(x)
}

/// Return the underlying index value as a `usize`.
#[inline]
pub fn as_usize(self) -> usize {
self.0 as usize
}
}
impl cranelift_entity::EntityRef for LocalId {
#[inline]
fn new(index: usize) -> Self {
debug_assert!(index < (u8::MAX as usize));
Self(index as u8)
}

#[inline]
fn index(self) -> usize {
self.0 as usize
}
}
impl cranelift_entity::packed_option::ReservedValue for LocalId {
#[inline]
fn reserved_value() -> LocalId {
Self(u8::MAX)
}

#[inline]
fn is_reserved_value(&self) -> bool {
self.0 == u8::MAX
}
}
impl fmt::Display for LocalId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "local{}", self.0)
}
}
impl fmt::Debug for LocalId {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
}
}

/// Represents a local allocated on the heap statically
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Local {
/// The unique identifier associated with this local
///
/// It also represents the offset in the set of locals of a function
/// where this local will be allocated.
///
/// NOTE: If a local's size is larger than a word, multiple consecutive
/// local allocations may be made to ensure there is enough memory starting
/// at the offset represented by `id` to hold the entire value
pub id: LocalId,
/// The type of the value stored in this local
pub ty: Type,
}
impl Local {
/// Returns the [Layout] for this local in memory
pub fn layout(&self) -> Layout {
self.ty.layout()
}

/// Returns the size in bytes for this local, including necessary alignment padding
pub fn size_in_bytes(&self) -> usize {
self.ty.size_in_bytes()
}

/// Returns the size in words for this local, including necessary alignment padding
pub fn size_in_words(&self) -> usize {
self.ty.size_in_words()
}
}

0 comments on commit 840eacd

Please sign in to comment.