@@ -16,11 +16,11 @@ use cairo_lang_utils::unordered_hash_map::UnorderedHashMap;
16
16
use cairo_lang_utils:: unordered_hash_set:: UnorderedHashSet ;
17
17
use cairo_lang_utils:: { Intern , LookupIntern , Upcast } ;
18
18
use defs:: ids:: NamedLanguageElementId ;
19
- use itertools:: { Itertools , chain} ;
19
+ use itertools:: { Itertools , chain, zip_eq } ;
20
20
use num_traits:: ToPrimitive ;
21
21
22
22
use crate :: add_withdraw_gas:: add_withdraw_gas;
23
- use crate :: blocks:: Blocks ;
23
+ use crate :: blocks:: { Blocks , BlocksBuilder } ;
24
24
use crate :: borrow_check:: {
25
25
PotentialDestructCalls , borrow_check, borrow_check_possible_withdraw_gas,
26
26
} ;
@@ -29,17 +29,21 @@ use crate::concretize::concretize_lowered;
29
29
use crate :: destructs:: add_destructs;
30
30
use crate :: diagnostic:: { LoweringDiagnostic , LoweringDiagnosticKind } ;
31
31
use crate :: graph_algorithms:: feedback_set:: flag_add_withdraw_gas;
32
- use crate :: ids:: { ConcreteFunctionWithBodyId , FunctionId , FunctionLongId } ;
32
+ use crate :: ids:: {
33
+ ConcreteFunctionWithBodyId , FunctionId , FunctionLongId , LocationId , SpecializedFunction ,
34
+ } ;
33
35
use crate :: inline:: get_inline_diagnostics;
34
36
use crate :: inline:: statements_weights:: { ApproxCasmInlineWeight , InlineWeight } ;
37
+ use crate :: lower:: context:: { VarRequest , VariableAllocator } ;
35
38
use crate :: lower:: { MultiLowering , lower_semantic_function} ;
36
39
use crate :: optimizations:: config:: OptimizationConfig ;
37
40
use crate :: optimizations:: scrub_units:: scrub_units;
38
41
use crate :: optimizations:: strategy:: { OptimizationStrategy , OptimizationStrategyId } ;
39
42
use crate :: panic:: lower_panics;
40
43
use crate :: utils:: InliningStrategy ;
41
44
use crate :: {
42
- BlockEnd , BlockId , DependencyType , Location , Lowered , LoweringStage , MatchInfo , Statement , ids,
45
+ Block , BlockEnd , BlockId , DependencyType , Location , Lowered , LoweringStage , MatchInfo ,
46
+ Statement , StatementCall , StatementConst , VarUsage , VariableId , ids,
43
47
} ;
44
48
45
49
/// A trait for estimation of the code size of a function.
@@ -432,34 +436,97 @@ fn lowered_body(
432
436
function : ids:: ConcreteFunctionWithBodyId ,
433
437
stage : LoweringStage ,
434
438
) -> Maybe < Arc < Lowered > > {
435
- match stage {
439
+ let lowered = match stage {
436
440
LoweringStage :: Monomorphized => {
437
- let generic_function_id = function. function_with_body_id ( db) ;
441
+ let generic_function_id = match function. lookup_intern ( db) {
442
+ ids:: ConcreteFunctionWithBodyLongId :: Semantic ( id) => {
443
+ ids:: FunctionWithBodyLongId :: Semantic ( id. function_with_body_id ( db) )
444
+ }
445
+ ids:: ConcreteFunctionWithBodyLongId :: Generated ( id) => {
446
+ id. function_with_body_long_id ( db)
447
+ }
448
+ ids:: ConcreteFunctionWithBodyLongId :: Specialized ( specialized) => {
449
+ return Ok ( Arc :: new ( specialized_function_lowered ( db, specialized) ?) ) ;
450
+ }
451
+ }
452
+ . intern ( db) ;
453
+
438
454
db. function_with_body_lowering_diagnostics ( generic_function_id) ?. check_error_free ( ) ?;
439
455
let mut lowered = ( * db. function_with_body_lowering ( generic_function_id) ?) . clone ( ) ;
440
456
concretize_lowered ( db, & mut lowered, & function. substitution ( db) ?) ?;
441
- Ok ( Arc :: new ( lowered) )
457
+ lowered
442
458
}
443
459
LoweringStage :: PreOptimizations => {
444
460
let mut lowered = ( * db. lowered_body ( function, LoweringStage :: Monomorphized ) ?) . clone ( ) ;
445
461
add_withdraw_gas ( db, function, & mut lowered) ?;
446
462
lower_panics ( db, function, & mut lowered) ?;
447
463
add_destructs ( db, function, & mut lowered) ;
448
464
scrub_units ( db, & mut lowered) ;
449
- Ok ( Arc :: new ( lowered) )
465
+ lowered
450
466
}
451
467
LoweringStage :: PostBaseline => {
452
468
let mut lowered =
453
469
( * db. lowered_body ( function, LoweringStage :: PreOptimizations ) ?) . clone ( ) ;
454
470
db. baseline_optimization_strategy ( ) . apply_strategy ( db, function, & mut lowered) ?;
455
- Ok ( Arc :: new ( lowered) )
471
+ lowered
456
472
}
457
473
LoweringStage :: Final => {
458
474
let mut lowered = ( * db. lowered_body ( function, LoweringStage :: PostBaseline ) ?) . clone ( ) ;
459
475
db. final_optimization_strategy ( ) . apply_strategy ( db, function, & mut lowered) ?;
460
- Ok ( Arc :: new ( lowered) )
476
+ lowered
477
+ }
478
+ } ;
479
+ Ok ( Arc :: new ( lowered) )
480
+ }
481
+
482
+ /// Returns the lowering of a specialized function.
483
+ fn specialized_function_lowered (
484
+ db : & dyn LoweringGroup ,
485
+ specialized : SpecializedFunction ,
486
+ ) -> Maybe < Lowered > {
487
+ let base = db. lowered_body ( specialized. base , LoweringStage :: Monomorphized ) ?;
488
+ let base_semantic = specialized. base . base_semantic_function ( db) ;
489
+ let mut variables =
490
+ VariableAllocator :: new ( db, base_semantic. function_with_body_id ( db) , Default :: default ( ) ) ?;
491
+ let mut statement = vec ! [ ] ;
492
+ let mut parameters = vec ! [ ] ;
493
+ for ( param, arg) in zip_eq ( & base. parameters , specialized. args . iter ( ) ) {
494
+ let var_id = variables. variables . alloc ( base. variables [ * param] . clone ( ) ) ;
495
+ if let Some ( arg) = arg {
496
+ statement. push ( Statement :: Const ( StatementConst { value : arg. clone ( ) , output : var_id } ) ) ;
497
+ continue ;
461
498
}
499
+ parameters. push ( var_id) ;
462
500
}
501
+ let location = LocationId :: from_stable_location (
502
+ db,
503
+ specialized. base . base_semantic_function ( db) . stable_location ( db) ,
504
+ ) ;
505
+ let inputs =
506
+ variables. variables . iter ( ) . map ( |( var_id, _) | VarUsage { var_id, location } ) . collect ( ) ;
507
+ let outputs: Vec < VariableId > =
508
+ chain ! ( base. signature. extra_rets. iter( ) . map( |ret| ret. ty( ) ) , [ base. signature. return_type] )
509
+ . map ( |ty| variables. new_var ( VarRequest { ty, location } ) )
510
+ . collect_vec ( ) ;
511
+ let mut block_builder = BlocksBuilder :: new ( ) ;
512
+ let ret_usage =
513
+ outputs. iter ( ) . map ( |var_id| VarUsage { var_id : * var_id, location } ) . collect_vec ( ) ;
514
+ statement. push ( Statement :: Call ( StatementCall {
515
+ function : specialized. base . function_id ( db) ?,
516
+ with_coupon : false ,
517
+ inputs,
518
+ outputs,
519
+ location,
520
+ } ) ) ;
521
+ block_builder
522
+ . alloc ( Block { statements : statement, end : BlockEnd :: Return ( ret_usage, location) } ) ;
523
+ Ok ( Lowered {
524
+ signature : specialized. signature ( db) ?,
525
+ variables : variables. variables ,
526
+ blocks : block_builder. build ( ) . unwrap ( ) ,
527
+ parameters,
528
+ diagnostics : Default :: default ( ) ,
529
+ } )
463
530
}
464
531
465
532
/// Given the lowering of a function, returns the set of direct dependencies of that function,
0 commit comments