revmc_backend/
pointer.rs

1use crate::Builder;
2
3/// A pointer to a value.
4#[derive(Clone, Copy, Debug)]
5pub struct Pointer<B: Builder> {
6    /// The type of the pointee.
7    pub ty: B::Type,
8    /// The base of the pointer. Either an address or a stack slot.
9    pub base: PointerBase<B>,
10}
11
12/// The base of a pointer. Either an address or a stack slot.
13#[derive(Clone, Copy, Debug)]
14pub enum PointerBase<B: Builder> {
15    /// An address.
16    Address(B::Value),
17    /// A stack slot.
18    StackSlot(B::StackSlot),
19}
20
21impl<B: Builder> Pointer<B> {
22    /// Creates a new stack-allocated pointer.
23    pub fn new_stack_slot(bcx: &mut B, ty: B::Type, name: &str) -> Self {
24        let slot = bcx.new_stack_slot_raw(ty, name);
25        Self { ty, base: PointerBase::StackSlot(slot) }
26    }
27
28    /// Creates a new address pointer.
29    pub fn new_address(ty: B::Type, value: B::Value) -> Self {
30        Self { ty, base: PointerBase::Address(value) }
31    }
32
33    /// Returns `true` if the pointer is an address.
34    pub fn is_address(&self) -> bool {
35        matches!(self.base, PointerBase::Address(_))
36    }
37
38    /// Returns `true` if the pointer is a stack slot.
39    pub fn is_stack_slot(&self) -> bool {
40        matches!(self.base, PointerBase::StackSlot(_))
41    }
42
43    /// Converts the pointer to an address.
44    pub fn into_address(self) -> Option<B::Value> {
45        match self.base {
46            PointerBase::Address(ptr) => Some(ptr),
47            PointerBase::StackSlot(_) => None,
48        }
49    }
50
51    /// Converts the pointer to a stack slot.
52    pub fn into_stack_slot(self) -> Option<B::StackSlot> {
53        match self.base {
54            PointerBase::Address(_) => None,
55            PointerBase::StackSlot(slot) => Some(slot),
56        }
57    }
58
59    /// Loads the value from the pointer.
60    pub fn load(&self, bcx: &mut B, name: &str) -> B::Value {
61        match self.base {
62            PointerBase::Address(ptr) => bcx.load(self.ty, ptr, name),
63            PointerBase::StackSlot(slot) => bcx.stack_load(self.ty, slot, name),
64        }
65    }
66
67    /// Stores the value to the pointer.
68    pub fn store(&self, bcx: &mut B, value: B::Value) {
69        match self.base {
70            PointerBase::Address(ptr) => bcx.store(value, ptr),
71            PointerBase::StackSlot(slot) => bcx.stack_store(value, slot),
72        }
73    }
74
75    /// Stores the value to the pointer.
76    pub fn store_imm(&self, bcx: &mut B, value: i64) {
77        let value = bcx.iconst(self.ty, value);
78        self.store(bcx, value)
79    }
80
81    /// Gets the address of the pointer.
82    pub fn addr(&self, bcx: &mut B) -> B::Value {
83        match self.base {
84            PointerBase::Address(ptr) => ptr,
85            PointerBase::StackSlot(slot) => bcx.stack_addr(self.ty, slot),
86        }
87    }
88}