Skip to content

Commit 6510a18

Browse files
author
Gilad Chase
committed
Add IntoBox instead of into_box in lowering
Currently is always mapped to into_box during sierra-gen, but soon in sierra-gen it can also be mapped into local_into_box when applicable.
1 parent 482afce commit 6510a18

File tree

15 files changed

+190
-52
lines changed

15 files changed

+190
-52
lines changed

crates/cairo-lang-lowering/src/cache/mod.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ use crate::objects::{
5454
};
5555
use crate::{
5656
Block, BlockEnd, Location, Lowered, MatchArm, MatchEnumInfo, MatchEnumValue, MatchInfo,
57-
StatementDesnap, StatementEnumConstruct, StatementSnapshot, StatementStructConstruct,
58-
VarRemapping, VarUsage, Variable,
57+
StatementDesnap, StatementEnumConstruct, StatementIntoBox, StatementSnapshot,
58+
StatementStructConstruct, VarRemapping, VarUsage, Variable,
5959
};
6060

6161
type LookupCache = (CacheLookups, Vec<(DefsFunctionWithBodyIdCached, MultiLoweringCached)>);
@@ -909,6 +909,9 @@ enum StatementCached {
909909
// Enums.
910910
EnumConstruct(StatementEnumConstructCached),
911911

912+
// Boxing.
913+
IntoBox(StatementIntoBoxCached),
914+
912915
Snapshot(StatementSnapshotCached),
913916
Desnap(StatementDesnapCached),
914917
}
@@ -933,6 +936,9 @@ impl StatementCached {
933936
Statement::Desnap(stmt) => {
934937
StatementCached::Desnap(StatementDesnapCached::new(stmt, ctx))
935938
}
939+
Statement::IntoBox(stmt) => {
940+
StatementCached::IntoBox(StatementIntoBoxCached::new(stmt, ctx))
941+
}
936942
}
937943
}
938944
fn embed<'db>(self, ctx: &mut CacheLoadingContext<'db>) -> Statement<'db> {
@@ -946,6 +952,7 @@ impl StatementCached {
946952
StatementCached::EnumConstruct(stmt) => Statement::EnumConstruct(stmt.embed(ctx)),
947953
StatementCached::Snapshot(stmt) => Statement::Snapshot(stmt.embed(ctx)),
948954
StatementCached::Desnap(stmt) => Statement::Desnap(stmt.embed(ctx)),
955+
StatementCached::IntoBox(stmt) => Statement::IntoBox(stmt.embed(ctx)),
949956
}
950957
}
951958
}
@@ -1246,6 +1253,23 @@ impl StatementDesnapCached {
12461253
}
12471254
}
12481255

1256+
#[derive(Serialize, Deserialize)]
1257+
struct StatementIntoBoxCached {
1258+
input: VarUsageCached,
1259+
output: usize,
1260+
}
1261+
impl StatementIntoBoxCached {
1262+
fn new<'db>(stmt: StatementIntoBox<'db>, ctx: &mut CacheSavingContext<'db>) -> Self {
1263+
Self { input: VarUsageCached::new(stmt.input, ctx), output: stmt.output.index() }
1264+
}
1265+
fn embed<'db>(self, ctx: &mut CacheLoadingContext<'db>) -> StatementIntoBox<'db> {
1266+
StatementIntoBox {
1267+
input: self.input.embed(ctx),
1268+
output: ctx.lowered_variables_id[self.output],
1269+
}
1270+
}
1271+
}
1272+
12491273
#[derive(Serialize, Deserialize, Clone)]
12501274
struct LocationCached {
12511275
/// The stable location of the object.

crates/cairo-lang-lowering/src/concretize/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ pub fn concretize_lowered<'db>(
6262
Statement::Snapshot(_)
6363
| Statement::Desnap(_)
6464
| Statement::StructConstruct(_)
65-
| Statement::StructDestructure(_) => {}
65+
| Statement::StructDestructure(_)
66+
| Statement::IntoBox(_) => {}
6667
}
6768
}
6869
if let BlockEnd::Match { info } = &mut block.end {

crates/cairo-lang-lowering/src/fmt.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use itertools::Itertools;
55
use salsa::Database;
66

77
use crate::objects::{
8-
MatchExternInfo, Statement, StatementCall, StatementConst, StatementStructDestructure,
9-
VariableId,
8+
MatchExternInfo, Statement, StatementCall, StatementConst, StatementIntoBox,
9+
StatementStructDestructure, VariableId,
1010
};
1111
use crate::{
1212
Block, BlockEnd, Lowered, MatchArm, MatchEnumInfo, MatchEnumValue, MatchInfo, StatementDesnap,
@@ -188,6 +188,7 @@ impl<'db> DebugWithDb<'db> for Statement<'db> {
188188
Statement::EnumConstruct(stmt) => stmt.fmt(f, ctx),
189189
Statement::Snapshot(stmt) => stmt.fmt(f, ctx),
190190
Statement::Desnap(stmt) => stmt.fmt(f, ctx),
191+
Statement::IntoBox(stmt) => stmt.fmt(f, ctx),
191192
}
192193
}
193194
}
@@ -365,3 +366,13 @@ impl<'db> DebugWithDb<'db> for StatementDesnap<'db> {
365366
write!(f, ")")
366367
}
367368
}
369+
370+
impl<'db> DebugWithDb<'db> for StatementIntoBox<'db> {
371+
type Db = LoweredFormatter<'db>;
372+
373+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>, ctx: &Self::Db) -> std::fmt::Result {
374+
write!(f, "into_box(")?;
375+
self.input.fmt(f, ctx)?;
376+
write!(f, ")")
377+
}
378+
}

crates/cairo-lang-lowering/src/lower/generators.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
44
use cairo_lang_semantic as semantic;
55
use cairo_lang_semantic::ConcreteVariant;
6+
use cairo_lang_semantic::corelib::core_box_ty;
67
use cairo_lang_semantic::items::constant::ConstValueId;
78
use cairo_lang_utils::{Intern, extract_matches};
89
use itertools::chain;
@@ -15,7 +16,7 @@ use crate::objects::{
1516
Statement, StatementCall, StatementConst, StatementStructConstruct, StatementStructDestructure,
1617
VarUsage,
1718
};
18-
use crate::{StatementDesnap, StatementEnumConstruct, StatementSnapshot};
19+
use crate::{StatementDesnap, StatementEnumConstruct, StatementIntoBox, StatementSnapshot};
1920

2021
#[derive(Clone, Default)]
2122
pub struct StatementsBuilder<'db> {
@@ -256,3 +257,22 @@ impl<'db> StructConstruct<'db> {
256257
VarUsage { var_id: output, location: self.location }
257258
}
258259
}
260+
261+
/// Generator for [StatementIntoBox].
262+
pub struct IntoBox<'db> {
263+
pub input: VarUsage<'db>,
264+
pub location: LocationId<'db>,
265+
}
266+
impl<'db> IntoBox<'db> {
267+
pub fn add(
268+
self,
269+
ctx: &mut LoweringContext<'db, '_>,
270+
builder: &mut StatementsBuilder<'db>,
271+
) -> VarUsage<'db> {
272+
let input_ty = ctx.variables[self.input.var_id].ty;
273+
let output_ty = core_box_ty(ctx.db, input_ty);
274+
let output = ctx.new_var(VarRequest { ty: output_ty, location: self.location });
275+
builder.push_statement(Statement::IntoBox(StatementIntoBox { input: self.input, output }));
276+
VarUsage { var_id: output, location: self.location }
277+
}
278+
}

crates/cairo-lang-lowering/src/lower/mod.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1351,7 +1351,7 @@ fn perform_function_call<'db>(
13511351
function_call_info;
13521352

13531353
// If the function is not extern, simply call it.
1354-
if function.try_get_extern_function_id(ctx.db).is_none() {
1354+
let Some(extern_function_id) = function.try_get_extern_function_id(ctx.db) else {
13551355
let call_result = generators::Call {
13561356
function: function.lowered(ctx.db),
13571357
inputs,
@@ -1390,6 +1390,16 @@ fn perform_function_call<'db>(
13901390

13911391
// Extern function.
13921392
assert!(coupon_input.is_none(), "Extern functions cannot have a __coupon__ argument.");
1393+
1394+
// Handle into_box specially - emit IntoBox instead of a call.
1395+
let info = ctx.db.core_info();
1396+
if extern_function_id == info.into_box {
1397+
assert!(extra_ret_tys.is_empty(), "into_box should not have extra return types");
1398+
let input = inputs.into_iter().exactly_one().expect("into_box expects exactly one input");
1399+
let res = generators::IntoBox { input, location }.add(ctx, &mut builder.statements);
1400+
return Ok((vec![], LoweredExpr::AtVariable(res)));
1401+
}
1402+
13931403
let ret_tys = extern_facade_return_tys(ctx, ret_ty);
13941404
let call_result = generators::Call {
13951405
function: function.lowered(ctx.db),

crates/cairo-lang-lowering/src/objects.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,9 @@ pub enum Statement<'db> {
294294

295295
Snapshot(StatementSnapshot<'db>),
296296
Desnap(StatementDesnap<'db>),
297+
298+
// Boxing.
299+
IntoBox(StatementIntoBox<'db>),
297300
}
298301
impl<'db> Statement<'db> {
299302
pub fn inputs(&self) -> &[VarUsage<'db>] {
@@ -305,6 +308,7 @@ impl<'db> Statement<'db> {
305308
Statement::EnumConstruct(stmt) => std::slice::from_ref(&stmt.input),
306309
Statement::Snapshot(stmt) => std::slice::from_ref(&stmt.input),
307310
Statement::Desnap(stmt) => std::slice::from_ref(&stmt.input),
311+
Statement::IntoBox(stmt) => std::slice::from_ref(&stmt.input),
308312
}
309313
}
310314

@@ -317,6 +321,7 @@ impl<'db> Statement<'db> {
317321
Statement::EnumConstruct(stmt) => std::slice::from_mut(&mut stmt.input),
318322
Statement::Snapshot(stmt) => std::slice::from_mut(&mut stmt.input),
319323
Statement::Desnap(stmt) => std::slice::from_mut(&mut stmt.input),
324+
Statement::IntoBox(stmt) => std::slice::from_mut(&mut stmt.input),
320325
}
321326
}
322327

@@ -329,6 +334,7 @@ impl<'db> Statement<'db> {
329334
Statement::EnumConstruct(stmt) => std::slice::from_ref(&stmt.output),
330335
Statement::Snapshot(stmt) => stmt.outputs.as_slice(),
331336
Statement::Desnap(stmt) => std::slice::from_ref(&stmt.output),
337+
Statement::IntoBox(stmt) => std::slice::from_ref(&stmt.output),
332338
}
333339
}
334340

@@ -341,6 +347,7 @@ impl<'db> Statement<'db> {
341347
Statement::EnumConstruct(stmt) => std::slice::from_mut(&mut stmt.output),
342348
Statement::Snapshot(stmt) => stmt.outputs.as_mut_slice(),
343349
Statement::Desnap(stmt) => std::slice::from_mut(&mut stmt.output),
350+
Statement::IntoBox(stmt) => std::slice::from_mut(&mut stmt.output),
344351
}
345352
}
346353
pub fn location(&self) -> Option<LocationId<'db>> {
@@ -353,6 +360,7 @@ impl<'db> Statement<'db> {
353360
Statement::EnumConstruct(stmt) => Some(stmt.input.location),
354361
Statement::Snapshot(stmt) => Some(stmt.input.location),
355362
Statement::Desnap(stmt) => Some(stmt.input.location),
363+
Statement::IntoBox(stmt) => Some(stmt.input.location),
356364
}
357365
}
358366
pub fn location_mut(&mut self) -> Option<&mut LocationId<'db>> {
@@ -364,6 +372,7 @@ impl<'db> Statement<'db> {
364372
Statement::EnumConstruct(stmt) => Some(&mut stmt.input.location),
365373
Statement::Snapshot(stmt) => Some(&mut stmt.input.location),
366374
Statement::Desnap(stmt) => Some(&mut stmt.input.location),
375+
Statement::IntoBox(stmt) => Some(&mut stmt.input.location),
367376
}
368377
}
369378
}
@@ -470,6 +479,15 @@ pub struct StatementDesnap<'db> {
470479
pub output: VariableId,
471480
}
472481

482+
/// A statement that constructs a box from a value.
483+
#[derive(Clone, Debug, PartialEq, Eq)]
484+
pub struct StatementIntoBox<'db> {
485+
/// The value to box.
486+
pub input: VarUsage<'db>,
487+
/// The variable to bind the boxed value to.
488+
pub output: VariableId,
489+
}
490+
473491
/// An arm of a match statement.
474492
#[derive(Clone, Debug, PartialEq, Eq)]
475493
pub struct MatchArm<'db> {

crates/cairo-lang-lowering/src/optimizations/const_folding.rs

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ use crate::utils::InliningStrategy;
4343
use crate::{
4444
Block, BlockEnd, BlockId, DependencyType, Lowered, LoweringStage, MatchArm, MatchEnumInfo,
4545
MatchExternInfo, MatchInfo, Statement, StatementCall, StatementConst, StatementDesnap,
46-
StatementEnumConstruct, StatementSnapshot, StatementStructConstruct,
46+
StatementEnumConstruct, StatementIntoBox, StatementSnapshot, StatementStructConstruct,
4747
StatementStructDestructure, VarRemapping, VarUsage, Variable, VariableArena, VariableId,
4848
};
4949

@@ -308,6 +308,25 @@ impl<'db, 'mt> ConstFoldingContext<'db, 'mt> {
308308
};
309309
self.var_info.insert(*output, value);
310310
}
311+
Statement::IntoBox(StatementIntoBox { input, output }) => {
312+
let var_info = self.var_info.get(&input.var_id);
313+
let const_value = match var_info {
314+
Some(VarInfo::Const(val)) => Some(*val),
315+
Some(VarInfo::Snapshot(info)) => {
316+
try_extract_matches!(info.as_ref(), VarInfo::Const).copied()
317+
}
318+
_ => None,
319+
};
320+
let var_info =
321+
var_info.cloned().or_else(|| var_info_if_copy(self.variables, *input));
322+
if let Some(var_info) = var_info {
323+
self.var_info.insert(*output, VarInfo::Box(var_info.into()));
324+
}
325+
326+
if let Some(const_value) = const_value {
327+
*stmt = Statement::Const(StatementConst::new_boxed(const_value, *output));
328+
}
329+
}
311330
}
312331
}
313332

@@ -601,19 +620,6 @@ impl<'db, 'mt> ConstFoldingContext<'db, 'mt> {
601620
self.storage_base_address_const.concretize(db, vec![arg]).lowered(db);
602621
}
603622
None
604-
} else if id == self.into_box {
605-
let input = stmt.inputs[0];
606-
let var_info = self.var_info.get(&input.var_id);
607-
let const_value = match var_info {
608-
Some(VarInfo::Const(val)) => Some(*val),
609-
Some(VarInfo::Snapshot(info)) => {
610-
try_extract_matches!(info.as_ref(), VarInfo::Const).copied()
611-
}
612-
_ => None,
613-
};
614-
let var_info = var_info.cloned().or_else(|| var_info_if_copy(self.variables, input))?;
615-
self.var_info.insert(stmt.outputs[0], VarInfo::Box(var_info.into()));
616-
Some(Statement::Const(StatementConst::new_boxed(const_value?, stmt.outputs[0])))
617623
} else if id == self.unbox {
618624
if let VarInfo::Box(inner) = self.var_info.get(&stmt.inputs[0].var_id)? {
619625
let inner = inner.as_ref().clone();
@@ -1438,8 +1444,6 @@ pub struct ConstFoldingLibfuncInfo<'db> {
14381444
felt_mul: ExternFunctionId<'db>,
14391445
/// The `felt252_div` libfunc.
14401446
felt_div: ExternFunctionId<'db>,
1441-
/// The `into_box` libfunc.
1442-
into_box: ExternFunctionId<'db>,
14431447
/// The `unbox` libfunc.
14441448
unbox: ExternFunctionId<'db>,
14451449
/// The `box_forward_snapshot` libfunc.
@@ -1598,7 +1602,6 @@ impl<'db> ConstFoldingLibfuncInfo<'db> {
15981602
felt_add: core.extern_function_id("felt252_add"),
15991603
felt_mul: core.extern_function_id("felt252_mul"),
16001604
felt_div: core.extern_function_id("felt252_div"),
1601-
into_box: box_module.extern_function_id("into_box"),
16021605
unbox: box_module.extern_function_id("unbox"),
16031606
box_forward_snapshot: box_module.generic_function_id("box_forward_snapshot"),
16041607
eq_fns,

crates/cairo-lang-lowering/src/optimizations/dedup_blocks.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::ids::FunctionId;
1212
use crate::utils::{Rebuilder, RebuilderEx};
1313
use crate::{
1414
Block, BlockEnd, BlockId, Lowered, Statement, StatementCall, StatementConst, StatementDesnap,
15-
StatementEnumConstruct, StatementSnapshot, StatementStructConstruct,
15+
StatementEnumConstruct, StatementIntoBox, StatementSnapshot, StatementStructConstruct,
1616
StatementStructDestructure, VarRemapping, VarUsage, VariableArena, VariableId,
1717
};
1818

@@ -59,7 +59,10 @@ enum CanonicStatement<'db> {
5959
input: CanonicVar,
6060
output: CanonicVar,
6161
},
62-
62+
BoxConstruct {
63+
input: CanonicVar,
64+
output: CanonicVar,
65+
},
6366
Snapshot {
6467
input: CanonicVar,
6568
outputs: [CanonicVar; 2],
@@ -163,6 +166,12 @@ impl<'db, 'a> CanonicBlockBuilder<'db, 'a> {
163166
input: self.handle_input(input),
164167
output: self.handle_output(output),
165168
},
169+
Statement::IntoBox(StatementIntoBox { input, output }) => {
170+
CanonicStatement::BoxConstruct {
171+
input: self.handle_input(input),
172+
output: self.handle_output(output),
173+
}
174+
}
166175
}
167176
}
168177
}

0 commit comments

Comments
 (0)