cairo_lang_sierra/extensions/modules/
mem.rs

1use super::uninitialized::UninitializedType;
2use super::utils::reinterpret_cast_signature;
3use crate::define_libfunc_hierarchy;
4use crate::extensions::lib_func::{
5    LibfuncSignature, OutputVarInfo, ParamSignature, SierraApChange,
6    SignatureAndTypeGenericLibfunc, SignatureOnlyGenericLibfunc, SignatureSpecializationContext,
7    WrapSignatureAndTypeGenericLibfunc,
8};
9use crate::extensions::{
10    NamedType, NoGenericArgsGenericLibfunc, OutputVarReferenceInfo, SpecializationError,
11    args_as_single_type,
12};
13use crate::ids::ConcreteTypeId;
14use crate::program::GenericArg;
15
16define_libfunc_hierarchy! {
17    pub enum MemLibfunc {
18        StoreTemp(StoreTempLibfunc),
19        StoreLocal(StoreLocalLibfunc),
20        FinalizeLocals(FinalizeLocalsLibfunc),
21        AllocLocal(AllocLocalLibfunc),
22        Rename(RenameLibfunc),
23    }, MemConcreteLibfunc
24}
25
26/// Libfunc for storing a value into temporary memory.
27#[derive(Default)]
28pub struct StoreTempLibfuncWrapped {}
29impl SignatureAndTypeGenericLibfunc for StoreTempLibfuncWrapped {
30    const STR_ID: &'static str = "store_temp";
31
32    fn specialize_signature(
33        &self,
34        context: &dyn SignatureSpecializationContext,
35        ty: ConcreteTypeId,
36    ) -> Result<LibfuncSignature, SpecializationError> {
37        let type_info = context.as_type_specialization_context().get_type_info(ty.clone())?;
38        if !type_info.storable {
39            return Err(SpecializationError::UnsupportedGenericArg);
40        }
41        Ok(LibfuncSignature::new_non_branch_ex(
42            vec![ParamSignature {
43                ty: ty.clone(),
44                allow_deferred: true,
45                allow_add_const: true,
46                allow_const: true,
47            }],
48            vec![OutputVarInfo {
49                ty,
50                ref_info: if type_info.zero_sized {
51                    OutputVarReferenceInfo::ZeroSized
52                } else {
53                    OutputVarReferenceInfo::NewTempVar { idx: 0 }
54                },
55            }],
56            SierraApChange::Known { new_vars_only: true },
57        ))
58    }
59}
60pub type StoreTempLibfunc = WrapSignatureAndTypeGenericLibfunc<StoreTempLibfuncWrapped>;
61
62/// Libfunc for storing a value into local memory.
63#[derive(Default)]
64pub struct StoreLocalLibfuncWrapped {}
65impl SignatureAndTypeGenericLibfunc for StoreLocalLibfuncWrapped {
66    const STR_ID: &'static str = "store_local";
67
68    fn specialize_signature(
69        &self,
70        context: &dyn SignatureSpecializationContext,
71        ty: ConcreteTypeId,
72    ) -> Result<LibfuncSignature, SpecializationError> {
73        let uninitialized_type =
74            context.get_wrapped_concrete_type(UninitializedType::id(), ty.clone())?;
75        let type_info = context.as_type_specialization_context().get_type_info(ty.clone())?;
76        if !type_info.storable {
77            return Err(SpecializationError::UnsupportedGenericArg);
78        }
79        Ok(LibfuncSignature::new_non_branch_ex(
80            vec![
81                ParamSignature::new(uninitialized_type),
82                ParamSignature {
83                    ty: ty.clone(),
84                    allow_deferred: true,
85                    allow_add_const: true,
86                    allow_const: true,
87                },
88            ],
89            vec![OutputVarInfo {
90                ty,
91                ref_info: if type_info.zero_sized {
92                    OutputVarReferenceInfo::ZeroSized
93                } else {
94                    OutputVarReferenceInfo::NewLocalVar
95                },
96            }],
97            SierraApChange::Known { new_vars_only: true },
98        ))
99    }
100}
101pub type StoreLocalLibfunc = WrapSignatureAndTypeGenericLibfunc<StoreLocalLibfuncWrapped>;
102
103/// Libfunc for finalizing the locals for current function.
104#[derive(Default)]
105pub struct FinalizeLocalsLibfunc {}
106impl NoGenericArgsGenericLibfunc for FinalizeLocalsLibfunc {
107    const STR_ID: &'static str = "finalize_locals";
108
109    fn specialize_signature(
110        &self,
111        _context: &dyn SignatureSpecializationContext,
112    ) -> Result<LibfuncSignature, SpecializationError> {
113        Ok(LibfuncSignature::new_non_branch(
114            vec![],
115            vec![],
116            SierraApChange::Known { new_vars_only: false },
117        ))
118    }
119}
120
121/// Libfunc for allocating locals for later stores.
122#[derive(Default)]
123pub struct AllocLocalLibfuncWrapped {}
124impl SignatureAndTypeGenericLibfunc for AllocLocalLibfuncWrapped {
125    const STR_ID: &'static str = "alloc_local";
126
127    fn specialize_signature(
128        &self,
129        context: &dyn SignatureSpecializationContext,
130        ty: ConcreteTypeId,
131    ) -> Result<LibfuncSignature, SpecializationError> {
132        let type_info = context.as_type_specialization_context().get_type_info(ty.clone())?;
133        Ok(LibfuncSignature::new_non_branch(
134            vec![],
135            vec![OutputVarInfo {
136                ty: context.get_wrapped_concrete_type(UninitializedType::id(), ty)?,
137                ref_info: if type_info.zero_sized {
138                    OutputVarReferenceInfo::ZeroSized
139                } else {
140                    OutputVarReferenceInfo::NewLocalVar
141                },
142            }],
143            SierraApChange::Known { new_vars_only: true },
144        ))
145    }
146}
147pub type AllocLocalLibfunc = WrapSignatureAndTypeGenericLibfunc<AllocLocalLibfuncWrapped>;
148
149/// Libfunc for renaming an identifier - used to align identities for flow control merge.
150#[derive(Default)]
151pub struct RenameLibfunc {}
152impl SignatureOnlyGenericLibfunc for RenameLibfunc {
153    const STR_ID: &'static str = "rename";
154
155    fn specialize_signature(
156        &self,
157        _context: &dyn SignatureSpecializationContext,
158        args: &[GenericArg],
159    ) -> Result<LibfuncSignature, SpecializationError> {
160        let ty = args_as_single_type(args)?;
161        Ok(reinterpret_cast_signature(ty.clone(), ty))
162    }
163}