sway_ir/
variable.rs

1//! A value representing a function-local variable.
2
3use crate::{
4    context::Context,
5    irtype::{Type, TypeContent},
6    pretty::DebugWithContext,
7    Constant,
8};
9
10/// A wrapper around an [ECS](https://github.com/orlp/slotmap) handle into the
11/// [`Context`].
12#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, DebugWithContext)]
13pub struct LocalVar(#[in_context(local_vars)] pub slotmap::DefaultKey);
14
15#[doc(hidden)]
16#[derive(Clone, DebugWithContext)]
17pub struct LocalVarContent {
18    pub ptr_ty: Type,
19    pub initializer: Option<Constant>,
20    pub mutable: bool,
21}
22
23impl LocalVar {
24    /// Return a new local of a specific type with an optional [`Constant`] initializer.  If a
25    /// local is marked as mutable then it is guaranteed to be on the stack rather than in
26    /// read-only memory.
27    pub fn new(
28        context: &mut Context,
29        ty: Type,
30        initializer: Option<Constant>,
31        mutable: bool,
32    ) -> Self {
33        let ptr_ty = Type::new_ptr(context, ty);
34        let content = LocalVarContent {
35            ptr_ty,
36            initializer,
37            mutable,
38        };
39        LocalVar(context.local_vars.insert(content))
40    }
41
42    /// Return the type of this local variable, which is always a pointer.
43    pub fn get_type(&self, context: &Context) -> Type {
44        context.local_vars[self.0].ptr_ty
45    }
46
47    /// Return the inner (pointed to) type.
48    pub fn get_inner_type(&self, context: &Context) -> Type {
49        let TypeContent::Pointer(inner_ty) = self.get_type(context).get_content(context) else {
50            unreachable!("Local var type is always a pointer.")
51        };
52        *inner_ty
53    }
54
55    /// Return the initializer for this local variable.
56    pub fn get_initializer<'a>(&self, context: &'a Context) -> Option<&'a Constant> {
57        context.local_vars[self.0].initializer.as_ref()
58    }
59
60    /// Return whether this local variable is mutable.
61    pub fn is_mutable(&self, context: &Context) -> bool {
62        context.local_vars[self.0].mutable
63    }
64
65    /// Change this local variable's mutability.
66    pub fn set_mutable(&self, context: &mut Context, mutable: bool) {
67        context.local_vars[self.0].mutable = mutable;
68    }
69}
70
71/// A wrapper around an [ECS](https://github.com/orlp/slotmap) handle into the
72/// [`Context`].
73#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, DebugWithContext)]
74pub struct GlobalVar(#[in_context(global_vars)] pub slotmap::DefaultKey);
75
76#[doc(hidden)]
77#[derive(Clone, DebugWithContext)]
78pub struct GlobalVarContent {
79    pub ptr_ty: Type,
80    pub initializer: Option<Constant>,
81    pub mutable: bool,
82}
83
84impl GlobalVar {
85    /// Return a new Global of a specific type with an optional [`Constant`] initializer.  If a
86    /// Global is marked as mutable then it is guaranteed to be on the stack rather than in
87    /// read-only memory.
88    pub fn new(
89        context: &mut Context,
90        ty: Type,
91        initializer: Option<Constant>,
92        mutable: bool,
93    ) -> Self {
94        let ptr_ty = Type::new_ptr(context, ty);
95        let content = GlobalVarContent {
96            ptr_ty,
97            initializer,
98            mutable,
99        };
100        GlobalVar(context.global_vars.insert(content))
101    }
102
103    /// Return the type of this Global variable, which is always a pointer.
104    pub fn get_type(&self, context: &Context) -> Type {
105        context.global_vars[self.0].ptr_ty
106    }
107
108    /// Return the inner (pointed to) type.
109    pub fn get_inner_type(&self, context: &Context) -> Type {
110        let TypeContent::Pointer(inner_ty) = self.get_type(context).get_content(context) else {
111            unreachable!("Global var type is always a pointer.")
112        };
113        *inner_ty
114    }
115
116    /// Return the initializer for this Global variable.
117    pub fn get_initializer<'a>(&self, context: &'a Context) -> Option<&'a Constant> {
118        context.global_vars[self.0].initializer.as_ref()
119    }
120
121    /// Return whether this Global variable is mutable.
122    pub fn is_mutable(&self, context: &Context) -> bool {
123        context.global_vars[self.0].mutable
124    }
125
126    /// Change this Global variable's mutability.
127    pub fn set_mutable(&self, context: &mut Context, mutable: bool) {
128        context.global_vars[self.0].mutable = mutable;
129    }
130}