Skip to content

Commit ae4c93a

Browse files
fixed sierra gen revcation of const aliases
1 parent 6003d66 commit ae4c93a

File tree

1 file changed

+34
-19
lines changed

1 file changed

+34
-19
lines changed

crates/cairo-lang-sierra-generator/src/local_variables.rs

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,13 @@ pub fn analyze_ap_changes<'db>(
7070

7171
let mut ctx = analysis.analyzer;
7272
let peeled_used_after_revoke: OrderedHashSet<_> =
73-
ctx.used_after_revoke.iter().map(|var| ctx.peel_aliases(var)).copied().collect();
73+
ctx.used_after_revoke.iter().map(|var| ctx.peel_aliases(var).variable_id).collect();
7474
// Any used after revoke variable that might be revoked should be a local.
7575
let locals: OrderedHashSet<VariableId> = ctx
7676
.used_after_revoke
7777
.iter()
7878
.filter(|var| ctx.might_be_revoked(&peeled_used_after_revoke, var))
79-
.map(|var| ctx.peel_aliases(var))
80-
.cloned()
79+
.map(|var| ctx.peel_aliases(var).variable_id)
8180
.collect();
8281
let mut need_ap_alignment = OrderedHashSet::default();
8382
if !root_info.known_ap_change {
@@ -115,6 +114,11 @@ struct CalledBlockInfo {
115114
introduced_vars: Vec<VariableId>,
116115
}
117116

117+
struct VarSource {
118+
variable_id: VariableId,
119+
allow_const: bool,
120+
}
121+
118122
/// Context for the find_local_variables logic.
119123
struct FindLocalsContext<'db, 'a> {
120124
db: &'db dyn Database,
@@ -127,9 +131,9 @@ struct FindLocalsContext<'db, 'a> {
127131
constants: UnorderedHashSet<VariableId>,
128132
/// A mapping of variables which are the same in the context of finding locals.
129133
/// I.e. if `aliases[var_id]` is local than var_id is also local.
130-
aliases: UnorderedHashMap<VariableId, VariableId>,
134+
aliases: UnorderedHashMap<VariableId, VarSource>,
131135
/// A mapping from partial param variables to the containing variable.
132-
partial_param_parents: UnorderedHashMap<VariableId, VariableId>,
136+
partial_param_parents: UnorderedHashMap<VariableId, VarSource>,
133137
}
134138

135139
pub type LoweredDemand = Demand<VariableId, ()>;
@@ -241,11 +245,13 @@ struct BranchInfo {
241245

242246
impl<'db, 'a> FindLocalsContext<'db, 'a> {
243247
/// Given a variable that might be an alias follow aliases until we get the original variable.
244-
pub fn peel_aliases(&'a self, mut var: &'a VariableId) -> &'a VariableId {
248+
pub fn peel_aliases(&'a self, mut var: &'a VariableId) -> VarSource {
249+
let mut allow_const = true;
245250
while let Some(alias) = self.aliases.get(var) {
246-
var = alias;
251+
var = &alias.variable_id;
252+
allow_const &= alias.allow_const;
247253
}
248-
var
254+
VarSource { variable_id: *var, allow_const }
249255
}
250256

251257
/// Return true if the variable might be revoked by ap changes.
@@ -258,19 +264,28 @@ impl<'db, 'a> FindLocalsContext<'db, 'a> {
258264
peeled_used_after_revoke: &OrderedHashSet<VariableId>,
259265
var: &VariableId,
260266
) -> bool {
261-
if self.constants.contains(var) {
267+
let mut peeled = self.peel_aliases(var);
268+
if self.constants.contains(&peeled.variable_id) {
262269
return false;
263270
}
264-
let mut peeled = self.peel_aliases(var);
265-
if self.non_ap_based.contains(peeled) {
271+
if self.non_ap_based.contains(&peeled.variable_id) {
266272
return false;
267273
}
268274
// In the case of partial params, we check if one of its ancestors is a local variable, or
269275
// will be used after the revoke, and thus will be used as a local variable. If that
270276
// is the case, then 'var' can not be revoked.
271-
while let Some(parent) = self.partial_param_parents.get(peeled) {
272-
peeled = self.peel_aliases(parent);
273-
if self.non_ap_based.contains(peeled) || peeled_used_after_revoke.contains(peeled) {
277+
278+
let mut allow_const = peeled.allow_const;
279+
while let Some(parent) = self.partial_param_parents.get(&peeled.variable_id) {
280+
allow_const &= parent.allow_const;
281+
peeled = self.peel_aliases(&parent.variable_id);
282+
allow_const &= peeled.allow_const;
283+
if self.non_ap_based.contains(&peeled.variable_id) {
284+
return false;
285+
}
286+
// If the variable parent-peel chain ends in a const, but the allow_const flag is false (i.e. the chain went through a libfunc that doesn't allow consts),
287+
// then the variable can be revoked as the saved const will be ap based.
288+
if peeled_used_after_revoke.contains(&peeled.variable_id) && (!self.constants.contains(&peeled.variable_id) || allow_const) {
274289
return false;
275290
}
276291
}
@@ -309,10 +324,10 @@ impl<'db, 'a> FindLocalsContext<'db, 'a> {
309324
for (var, output_info) in zip_eq(output_vars.iter(), var_output_infos.iter()) {
310325
match output_info.ref_info {
311326
OutputVarReferenceInfo::SameAsParam { param_idx } => {
312-
self.aliases.insert(*var, input_vars[param_idx].var_id);
327+
self.aliases.insert(*var, VarSource { variable_id: input_vars[param_idx].var_id, allow_const: _params_signatures[param_idx].allow_const });
313328
}
314329
OutputVarReferenceInfo::PartialParam { param_idx } => {
315-
self.partial_param_parents.insert(*var, input_vars[param_idx].var_id);
330+
self.partial_param_parents.insert(*var, VarSource { variable_id: input_vars[param_idx].var_id, allow_const: _params_signatures[param_idx].allow_const });
316331
}
317332
OutputVarReferenceInfo::Deferred(DeferredOutputKind::Const)
318333
| OutputVarReferenceInfo::NewLocalVar
@@ -387,12 +402,12 @@ impl<'db, 'a> FindLocalsContext<'db, 'a> {
387402
)
388403
}
389404
lowering::Statement::Snapshot(statement_snapshot) => {
390-
self.aliases.insert(statement_snapshot.original(), statement_snapshot.input.var_id);
391-
self.aliases.insert(statement_snapshot.snapshot(), statement_snapshot.input.var_id);
405+
self.aliases.insert(statement_snapshot.original(), VarSource { variable_id: statement_snapshot.input.var_id, allow_const:true});
406+
self.aliases.insert(statement_snapshot.snapshot(), VarSource { variable_id: statement_snapshot.input.var_id, allow_const:true});
392407
BranchInfo { known_ap_change: true }
393408
}
394409
lowering::Statement::Desnap(statement_desnap) => {
395-
self.aliases.insert(statement_desnap.output, statement_desnap.input.var_id);
410+
self.aliases.insert(statement_desnap.output, VarSource { variable_id: statement_desnap.input.var_id, allow_const:true});
396411
BranchInfo { known_ap_change: true }
397412
}
398413
};

0 commit comments

Comments
 (0)