Skip to content

Commit 8a4d442

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

File tree

1 file changed

+58
-19
lines changed

1 file changed

+58
-19
lines changed

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

Lines changed: 58 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,31 @@ 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
287+
// (i.e. the chain went through a libfunc that doesn't allow consts),
288+
// then the variable can be revoked as the saved const will be ap based.
289+
if peeled_used_after_revoke.contains(&peeled.variable_id)
290+
&& (!self.constants.contains(&peeled.variable_id) || allow_const)
291+
{
274292
return false;
275293
}
276294
}
@@ -309,10 +327,22 @@ impl<'db, 'a> FindLocalsContext<'db, 'a> {
309327
for (var, output_info) in zip_eq(output_vars.iter(), var_output_infos.iter()) {
310328
match output_info.ref_info {
311329
OutputVarReferenceInfo::SameAsParam { param_idx } => {
312-
self.aliases.insert(*var, input_vars[param_idx].var_id);
330+
self.aliases.insert(
331+
*var,
332+
VarSource {
333+
variable_id: input_vars[param_idx].var_id,
334+
allow_const: _params_signatures[param_idx].allow_const,
335+
},
336+
);
313337
}
314338
OutputVarReferenceInfo::PartialParam { param_idx } => {
315-
self.partial_param_parents.insert(*var, input_vars[param_idx].var_id);
339+
self.partial_param_parents.insert(
340+
*var,
341+
VarSource {
342+
variable_id: input_vars[param_idx].var_id,
343+
allow_const: _params_signatures[param_idx].allow_const,
344+
},
345+
);
316346
}
317347
OutputVarReferenceInfo::Deferred(DeferredOutputKind::Const)
318348
| OutputVarReferenceInfo::NewLocalVar
@@ -387,12 +417,21 @@ impl<'db, 'a> FindLocalsContext<'db, 'a> {
387417
)
388418
}
389419
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);
420+
self.aliases.insert(
421+
statement_snapshot.original(),
422+
VarSource { variable_id: statement_snapshot.input.var_id, allow_const: true },
423+
);
424+
self.aliases.insert(
425+
statement_snapshot.snapshot(),
426+
VarSource { variable_id: statement_snapshot.input.var_id, allow_const: true },
427+
);
392428
BranchInfo { known_ap_change: true }
393429
}
394430
lowering::Statement::Desnap(statement_desnap) => {
395-
self.aliases.insert(statement_desnap.output, statement_desnap.input.var_id);
431+
self.aliases.insert(
432+
statement_desnap.output,
433+
VarSource { variable_id: statement_desnap.input.var_id, allow_const: true },
434+
);
396435
BranchInfo { known_ap_change: true }
397436
}
398437
};

0 commit comments

Comments
 (0)