cairo_lang_sierra_generator/
db.rs1use std::sync::Arc;
2
3use cairo_lang_diagnostics::Maybe;
4use cairo_lang_filesystem::ids::CrateId;
5use cairo_lang_lowering::db::LoweringGroup;
6use cairo_lang_lowering::panic::PanicSignatureInfo;
7use cairo_lang_sierra::extensions::lib_func::SierraApChange;
8use cairo_lang_sierra::extensions::{ConcreteType, GenericTypeEx};
9use cairo_lang_sierra::ids::ConcreteTypeId;
10use cairo_lang_utils::{LookupIntern, Upcast};
11use lowering::ids::ConcreteFunctionWithBodyId;
12use semantic::items::imp::ImplLookupContext;
13use {cairo_lang_lowering as lowering, cairo_lang_semantic as semantic};
14
15use crate::program_generator::{self, SierraProgramWithDebug};
16use crate::replace_ids::SierraIdReplacer;
17use crate::specialization_context::SierraSignatureSpecializationContext;
18use crate::{ap_change, function_generator, pre_sierra, replace_ids};
19
20#[derive(Clone, Debug, PartialEq, Eq, Hash)]
23pub enum SierraGeneratorTypeLongId {
24 Regular(Arc<cairo_lang_sierra::program::ConcreteTypeLongId>),
26 CycleBreaker(semantic::TypeId),
28 Phantom(semantic::TypeId),
31}
32
33#[salsa::query_group(SierraGenDatabase)]
34pub trait SierraGenGroup: LoweringGroup + Upcast<dyn LoweringGroup> {
35 #[salsa::interned]
36 fn intern_label_id(&self, id: pre_sierra::LabelLongId) -> pre_sierra::LabelId;
37
38 #[salsa::interned]
39 fn intern_concrete_lib_func(
40 &self,
41 id: cairo_lang_sierra::program::ConcreteLibfuncLongId,
42 ) -> cairo_lang_sierra::ids::ConcreteLibfuncId;
43
44 #[salsa::interned]
45 fn intern_concrete_type(
46 &self,
47 id: SierraGeneratorTypeLongId,
48 ) -> cairo_lang_sierra::ids::ConcreteTypeId;
49
50 #[salsa::interned]
54 fn intern_sierra_function(
55 &self,
56 id: lowering::ids::FunctionId,
57 ) -> cairo_lang_sierra::ids::FunctionId;
58
59 #[salsa::invoke(crate::types::get_concrete_type_id)]
61 fn get_concrete_type_id(
62 &self,
63 type_id: semantic::TypeId,
64 ) -> Maybe<cairo_lang_sierra::ids::ConcreteTypeId>;
65
66 #[salsa::invoke(crate::types::get_index_enum_type_id)]
68 fn get_index_enum_type_id(
69 &self,
70 index_count: usize,
71 ) -> Maybe<cairo_lang_sierra::ids::ConcreteTypeId>;
72
73 #[salsa::invoke(crate::types::get_concrete_long_type_id)]
75 fn get_concrete_long_type_id(
76 &self,
77 type_id: semantic::TypeId,
78 ) -> Maybe<Arc<cairo_lang_sierra::program::ConcreteTypeLongId>>;
79
80 #[salsa::invoke(crate::types::is_self_referential)]
82 fn is_self_referential(&self, type_id: semantic::TypeId) -> Maybe<bool>;
83
84 #[salsa::invoke(crate::types::type_dependencies)]
89 fn type_dependencies(&self, type_id: semantic::TypeId) -> Maybe<Arc<[semantic::TypeId]>>;
90
91 #[salsa::invoke(crate::types::has_in_deps)]
92 #[salsa::cycle(crate::types::has_in_deps_cycle)]
93 fn has_in_deps(&self, type_id: semantic::TypeId, needle: semantic::TypeId) -> Maybe<bool>;
94
95 fn get_function_signature(
98 &self,
99 function_id: cairo_lang_sierra::ids::FunctionId,
100 ) -> Maybe<Arc<cairo_lang_sierra::program::FunctionSignature>>;
101
102 fn get_type_info(
104 &self,
105 concrete_type_id: cairo_lang_sierra::ids::ConcreteTypeId,
106 ) -> Maybe<Arc<cairo_lang_sierra::extensions::types::TypeInfo>>;
107
108 #[salsa::invoke(function_generator::priv_function_with_body_sierra_data)]
110 fn priv_function_with_body_sierra_data(
111 &self,
112 function_id: ConcreteFunctionWithBodyId,
113 ) -> function_generator::SierraFunctionWithBodyData;
114 #[salsa::invoke(function_generator::function_with_body_sierra)]
116 fn function_with_body_sierra(
117 &self,
118 function_id: ConcreteFunctionWithBodyId,
119 ) -> Maybe<Arc<pre_sierra::Function>>;
120
121 #[salsa::invoke(ap_change::get_ap_change)]
124 fn get_ap_change(&self, function_id: ConcreteFunctionWithBodyId) -> Maybe<SierraApChange>;
125
126 #[salsa::invoke(program_generator::get_sierra_program_for_functions)]
128 fn get_sierra_program_for_functions(
129 &self,
130 requested_function_ids: Vec<ConcreteFunctionWithBodyId>,
131 ) -> Maybe<Arc<SierraProgramWithDebug>>;
132
133 #[salsa::invoke(program_generator::get_sierra_program)]
135 fn get_sierra_program(
136 &self,
137 requested_crate_ids: Vec<CrateId>,
138 ) -> Maybe<Arc<SierraProgramWithDebug>>;
139}
140
141fn get_function_signature(
142 db: &dyn SierraGenGroup,
143 function_id: cairo_lang_sierra::ids::FunctionId,
144) -> Maybe<Arc<cairo_lang_sierra::program::FunctionSignature>> {
145 let lowered_function_id = function_id.lookup_intern(db);
151 let signature = lowered_function_id.signature(db.upcast())?;
152 let may_panic = db.function_may_panic(lowered_function_id)?;
153
154 let implicits = db
155 .function_implicits(lowered_function_id)?
156 .iter()
157 .map(|ty| db.get_concrete_type_id(*ty))
158 .collect::<Maybe<Vec<ConcreteTypeId>>>()?;
159
160 let mut all_params = implicits.clone();
162 let mut extra_rets = vec![];
163 for param in &signature.params {
164 let concrete_type_id = db.get_concrete_type_id(param.ty())?;
165 all_params.push(concrete_type_id.clone());
166 }
167 for var in &signature.extra_rets {
168 let concrete_type_id = db.get_concrete_type_id(var.ty())?;
169 extra_rets.push(concrete_type_id);
170 }
171
172 let mut ret_types = implicits;
173 if may_panic {
174 let panic_info = PanicSignatureInfo::new(db.upcast(), &signature);
175 ret_types.push(db.get_concrete_type_id(panic_info.actual_return_ty)?);
176 } else {
177 ret_types.extend(extra_rets);
178 if !signature.return_type.is_unit(db.upcast()) {
180 ret_types.push(db.get_concrete_type_id(signature.return_type)?);
181 }
182 }
183
184 Ok(Arc::new(cairo_lang_sierra::program::FunctionSignature {
185 param_types: all_params,
186 ret_types,
187 }))
188}
189
190fn get_type_info(
191 db: &dyn SierraGenGroup,
192 concrete_type_id: cairo_lang_sierra::ids::ConcreteTypeId,
193) -> Maybe<Arc<cairo_lang_sierra::extensions::types::TypeInfo>> {
194 let long_id = match concrete_type_id.lookup_intern(db) {
195 SierraGeneratorTypeLongId::Regular(long_id) => long_id,
196 SierraGeneratorTypeLongId::CycleBreaker(ty) => {
197 let long_id = db.get_concrete_long_type_id(ty)?.as_ref().clone();
198 let info = db.type_info(ImplLookupContext::default(), ty)?;
199 return Ok(Arc::new(cairo_lang_sierra::extensions::types::TypeInfo {
200 long_id,
201 storable: true,
202 droppable: info.droppable.is_ok(),
203 duplicatable: info.copyable.is_ok(),
204 zero_sized: false,
205 }));
206 }
207 SierraGeneratorTypeLongId::Phantom(ty) => {
208 let long_id = db.get_concrete_long_type_id(ty)?.as_ref().clone();
209 return Ok(Arc::new(cairo_lang_sierra::extensions::types::TypeInfo {
210 long_id,
211 storable: false,
212 droppable: false,
213 duplicatable: false,
214 zero_sized: true,
215 }));
216 }
217 };
218 let concrete_ty = cairo_lang_sierra::extensions::core::CoreType::specialize_by_id(
219 &SierraSignatureSpecializationContext(db),
220 &long_id.generic_id,
221 &long_id.generic_args,
222 )
223 .unwrap_or_else(|err| {
224 let mut long_id = long_id.as_ref().clone();
225 replace_ids::DebugReplacer { db }.replace_generic_args(&mut long_id.generic_args);
226 panic!("Got failure while specializing type `{long_id}`: {err}")
227 });
228 Ok(Arc::new(concrete_ty.info().clone()))
229}
230
231pub fn sierra_concrete_long_id(
233 db: &dyn SierraGenGroup,
234 concrete_type_id: cairo_lang_sierra::ids::ConcreteTypeId,
235) -> Maybe<Arc<cairo_lang_sierra::program::ConcreteTypeLongId>> {
236 match concrete_type_id.lookup_intern(db) {
237 SierraGeneratorTypeLongId::Regular(long_id) => Ok(long_id),
238 SierraGeneratorTypeLongId::Phantom(type_id)
239 | SierraGeneratorTypeLongId::CycleBreaker(type_id) => db.get_concrete_long_type_id(type_id),
240 }
241}