From 7ff65e3f599cac7114ec117e124b7cb1211a0189 Mon Sep 17 00:00:00 2001 From: Ori Ziv Date: Wed, 24 Jun 2026 12:18:18 +0300 Subject: [PATCH] feature(sierra-gen): Added support for injecting constant values externally. --- Cargo.lock | 1 + .../src/profiling_test_data/major_test_cases | 376 +++++++++--------- crates/cairo-lang-sierra-generator/Cargo.toml | 1 + .../src/block_generator.rs | 69 +++- .../src/block_generator_test.rs | 13 + .../externally_provided_const | 33 ++ crates/cairo-lang-sierra-generator/src/db.rs | 50 ++- .../src/local_variables.rs | 27 +- 8 files changed, 369 insertions(+), 201 deletions(-) create mode 100644 crates/cairo-lang-sierra-generator/src/block_generator_test_data/externally_provided_const diff --git a/Cargo.lock b/Cargo.lock index c3505a55e8e..a1499ccd3b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1004,6 +1004,7 @@ dependencies = [ "indoc", "itertools 0.14.0", "log", + "num-bigint", "num-traits", "pretty_assertions", "rayon", diff --git a/crates/cairo-lang-runner/src/profiling_test_data/major_test_cases b/crates/cairo-lang-runner/src/profiling_test_data/major_test_cases index 3f937b75ed8..bfe1aae7de6 100644 --- a/crates/cairo-lang-runner/src/profiling_test_data/major_test_cases +++ b/crates/cairo-lang-runner/src/profiling_test_data/major_test_cases @@ -153,48 +153,48 @@ validate_call //! > expected_profiling_info Weight by sierra statement: - statement 419: 14 (contract_address_try_from_felt252([0], [7]) { fallthrough([8], [9]) 497([10]) }) - statement 437: 10 (array_slice([19], [23], [22], [24]) { fallthrough([25], [26]) 473([27]) }) - statement 446: 10 (array_slice([31], [35], [20], [32]) { fallthrough([36], [37]) 459([38]) }) - statement 457: 10 (store_temp>([44]) -> ([44])) - statement 327: 9 (withdraw_gas([0], [1]) { fallthrough([5], [6]) 370([7], [8]) }) - statement 349: 8 (array_append([3], [18]) -> ([21])) - statement 431: 8 (u32_try_from_felt252([8], [18]) { fallthrough([19], [20]) 479([21]) }) - statement 339: 6 (store_temp, core::option::Option::>)>>([14]) -> ([14])) - statement 443: 6 (u32_overflowing_sub([25], [29], [30]) { fallthrough([31], [32]) 465([33], [34]) }) - statement 344: 4 (store_temp>([2]) -> ([2])) - statement 354: 4 (store_temp>([16]) -> ([16])) - statement 355: 4 (store_temp>([21]) -> ([21])) - statement 414: 4 (array_snapshot_pop_front([2]) { fallthrough([3], [4]) 501([5]) }) - statement 421: 4 (store_temp>>([3]) -> ([3])) - statement 422: 4 (array_snapshot_pop_front([3]) { fallthrough([11], [12]) 492([13]) }) - statement 424: 4 (store_temp>>([11]) -> ([11])) - statement 425: 4 (array_snapshot_pop_front([11]) { fallthrough([14], [15]) 486([16]) }) - statement 430: 4 (store_temp>>([14]) -> ([14])) - statement 456: 4 (store_temp>([41]) -> ([41])) + statement 422: 14 (contract_address_try_from_felt252([0], [7]) { fallthrough([8], [9]) 500([10]) }) + statement 440: 10 (array_slice([19], [23], [22], [24]) { fallthrough([25], [26]) 476([27]) }) + statement 449: 10 (array_slice([31], [35], [20], [32]) { fallthrough([36], [37]) 462([38]) }) + statement 460: 10 (store_temp>([44]) -> ([44])) + statement 330: 9 (withdraw_gas([0], [1]) { fallthrough([5], [6]) 373([7], [8]) }) + statement 352: 8 (array_append([3], [18]) -> ([21])) + statement 434: 8 (u32_try_from_felt252([8], [18]) { fallthrough([19], [20]) 482([21]) }) + statement 342: 6 (store_temp, core::option::Option::>)>>([14]) -> ([14])) + statement 446: 6 (u32_overflowing_sub([25], [29], [30]) { fallthrough([31], [32]) 468([33], [34]) }) + statement 347: 4 (store_temp>([2]) -> ([2])) + statement 357: 4 (store_temp>([16]) -> ([16])) + statement 358: 4 (store_temp>([21]) -> ([21])) + statement 417: 4 (array_snapshot_pop_front([2]) { fallthrough([3], [4]) 504([5]) }) + statement 424: 4 (store_temp>>([3]) -> ([3])) + statement 425: 4 (array_snapshot_pop_front([3]) { fallthrough([11], [12]) 495([13]) }) + statement 427: 4 (store_temp>>([11]) -> ([11])) + statement 428: 4 (array_snapshot_pop_front([11]) { fallthrough([14], [15]) 489([16]) }) + statement 433: 4 (store_temp>>([14]) -> ([14])) + statement 459: 4 (store_temp>([41]) -> ([41])) statement 1: 3 (withdraw_gas([0], [1]) { fallthrough([3], [4]) 131([5], [6]) }) statement 83: 3 (array_snapshot_pop_front([64]) { fallthrough([65], [66]) 94([67]) }) statement 103: 3 (store_temp>([73]) -> ([73])) - statement 330: 3 (felt252_is_zero([9]) { fallthrough() 341([10]) }) + statement 333: 3 (felt252_is_zero([9]) { fallthrough() 344([10]) }) statement 63: 2 (store_temp>>([47]) -> ([47])) statement 64: 2 (array_snapshot_pop_front([47]) { fallthrough([48], [49]) 119([50]) }) statement 72: 2 (store_temp>([54]) -> ([54])) statement 73: 2 (store_temp>([53]) -> ([53])) - statement 343: 2 (store_temp([5]) -> ([5])) - statement 345: 2 (function_call([5], [2]) -> ([15], [16], [17])) - statement 346: 2 (enum_match>([17]) { fallthrough([18]) 359([19]) }) - statement 352: 2 (store_temp([15]) -> ([15])) - statement 353: 2 (store_temp([20]) -> ([20])) - statement 356: 2 (store_temp([23]) -> ([23])) - statement 357: 2 (function_call>([15], [20], [16], [21], [23]) -> ([24], [25], [26])) - statement 358: 2 (return([24], [25], [26])) - statement 418: 2 (store_temp([7]) -> ([7])) - statement 429: 2 (store_temp([18]) -> ([18])) - statement 436: 2 (store_temp([22]) -> ([22])) - statement 442: 2 (store_temp([29]) -> ([29])) - statement 447: 2 (branch_align() -> ()) - statement 455: 2 (store_temp([36]) -> ([36])) - statement 458: 2 (return([36], [41], [44])) + statement 346: 2 (store_temp([5]) -> ([5])) + statement 348: 2 (function_call([5], [2]) -> ([15], [16], [17])) + statement 349: 2 (enum_match>([17]) { fallthrough([18]) 362([19]) }) + statement 355: 2 (store_temp([15]) -> ([15])) + statement 356: 2 (store_temp([20]) -> ([20])) + statement 359: 2 (store_temp([23]) -> ([23])) + statement 360: 2 (function_call>([15], [20], [16], [21], [23]) -> ([24], [25], [26])) + statement 361: 2 (return([24], [25], [26])) + statement 421: 2 (store_temp([7]) -> ([7])) + statement 432: 2 (store_temp([18]) -> ([18])) + statement 439: 2 (store_temp([22]) -> ([22])) + statement 445: 2 (store_temp([29]) -> ([29])) + statement 450: 2 (branch_align() -> ()) + statement 458: 2 (store_temp([36]) -> ([36])) + statement 461: 2 (return([36], [41], [44])) statement 7: 1 (array_new() -> ([11])) statement 9: 1 (store_temp([12]) -> ([12])) statement 10: 1 (array_append([11], [12]) -> ([13])) @@ -245,9 +245,9 @@ Weight by sierra statement: statement 101: 1 (store_temp([70]) -> ([70])) statement 102: 1 (store_temp([2]) -> ([2])) statement 104: 1 (return([55], [70], [2], [73])) - statement 337: 1 (store_temp([5]) -> ([5])) - statement 338: 1 (store_temp([11]) -> ([11])) - statement 340: 1 (return([5], [11], [14])) + statement 340: 1 (store_temp([5]) -> ([5])) + statement 341: 1 (store_temp([11]) -> ([11])) + statement 343: 1 (return([5], [11], [14])) Weight by concrete libfunc: libfunc store_temp: 26 libfunc array_slice: 20 @@ -376,33 +376,33 @@ validate_call //! > expected_profiling_info Weight by sierra statement: - statement 383: 7 (contract_address_try_from_felt252([0], [7]) { fallthrough([8], [9]) 461([10]) }) - statement 291: 6 (withdraw_gas([0], [1]) { fallthrough([5], [6]) 334([7], [8]) }) - statement 303: 6 (store_temp, core::option::Option::>)>>([14]) -> ([14])) - statement 401: 5 (array_slice([19], [23], [22], [24]) { fallthrough([25], [26]) 437([27]) }) - statement 410: 5 (array_slice([31], [35], [20], [32]) { fallthrough([36], [37]) 423([38]) }) - statement 421: 5 (store_temp>([44]) -> ([44])) - statement 313: 4 (array_append([3], [18]) -> ([21])) - statement 395: 4 (u32_try_from_felt252([8], [18]) { fallthrough([19], [20]) 443([21]) }) + statement 386: 7 (contract_address_try_from_felt252([0], [7]) { fallthrough([8], [9]) 464([10]) }) + statement 294: 6 (withdraw_gas([0], [1]) { fallthrough([5], [6]) 337([7], [8]) }) + statement 306: 6 (store_temp, core::option::Option::>)>>([14]) -> ([14])) + statement 404: 5 (array_slice([19], [23], [22], [24]) { fallthrough([25], [26]) 440([27]) }) + statement 413: 5 (array_slice([31], [35], [20], [32]) { fallthrough([36], [37]) 426([38]) }) + statement 424: 5 (store_temp>([44]) -> ([44])) + statement 316: 4 (array_append([3], [18]) -> ([21])) + statement 398: 4 (u32_try_from_felt252([8], [18]) { fallthrough([19], [20]) 446([21]) }) statement 1: 3 (withdraw_gas([0], [1]) { fallthrough([3], [4]) 95([5], [6]) }) statement 47: 3 (array_snapshot_pop_front([40]) { fallthrough([41], [42]) 58([43]) }) statement 67: 3 (store_temp>([49]) -> ([49])) - statement 407: 3 (u32_overflowing_sub([25], [29], [30]) { fallthrough([31], [32]) 429([33], [34]) }) + statement 410: 3 (u32_overflowing_sub([25], [29], [30]) { fallthrough([31], [32]) 432([33], [34]) }) statement 27: 2 (store_temp>>([23]) -> ([23])) statement 28: 2 (array_snapshot_pop_front([23]) { fallthrough([24], [25]) 83([26]) }) statement 36: 2 (store_temp>([30]) -> ([30])) statement 37: 2 (store_temp>([29]) -> ([29])) - statement 294: 2 (felt252_is_zero([9]) { fallthrough() 305([10]) }) - statement 308: 2 (store_temp>([2]) -> ([2])) - statement 318: 2 (store_temp>([16]) -> ([16])) - statement 319: 2 (store_temp>([21]) -> ([21])) - statement 378: 2 (array_snapshot_pop_front([2]) { fallthrough([3], [4]) 465([5]) }) - statement 385: 2 (store_temp>>([3]) -> ([3])) - statement 386: 2 (array_snapshot_pop_front([3]) { fallthrough([11], [12]) 456([13]) }) - statement 388: 2 (store_temp>>([11]) -> ([11])) - statement 389: 2 (array_snapshot_pop_front([11]) { fallthrough([14], [15]) 450([16]) }) - statement 394: 2 (store_temp>>([14]) -> ([14])) - statement 420: 2 (store_temp>([41]) -> ([41])) + statement 297: 2 (felt252_is_zero([9]) { fallthrough() 308([10]) }) + statement 311: 2 (store_temp>([2]) -> ([2])) + statement 321: 2 (store_temp>([16]) -> ([16])) + statement 322: 2 (store_temp>([21]) -> ([21])) + statement 381: 2 (array_snapshot_pop_front([2]) { fallthrough([3], [4]) 468([5]) }) + statement 388: 2 (store_temp>>([3]) -> ([3])) + statement 389: 2 (array_snapshot_pop_front([3]) { fallthrough([11], [12]) 459([13]) }) + statement 391: 2 (store_temp>>([11]) -> ([11])) + statement 392: 2 (array_snapshot_pop_front([11]) { fallthrough([14], [15]) 453([16]) }) + statement 397: 2 (store_temp>>([14]) -> ([14])) + statement 423: 2 (store_temp>([41]) -> ([41])) statement 3: 1 (array_new() -> ([7])) statement 5: 1 (store_temp([8]) -> ([8])) statement 6: 1 (array_append([7], [8]) -> ([9])) @@ -429,24 +429,24 @@ Weight by sierra statement: statement 65: 1 (store_temp([46]) -> ([46])) statement 66: 1 (store_temp([2]) -> ([2])) statement 68: 1 (return([31], [46], [2], [49])) - statement 301: 1 (store_temp([5]) -> ([5])) - statement 302: 1 (store_temp([11]) -> ([11])) - statement 304: 1 (return([5], [11], [14])) - statement 307: 1 (store_temp([5]) -> ([5])) - statement 309: 1 (function_call([5], [2]) -> ([15], [16], [17])) - statement 310: 1 (enum_match>([17]) { fallthrough([18]) 323([19]) }) - statement 316: 1 (store_temp([15]) -> ([15])) - statement 317: 1 (store_temp([20]) -> ([20])) - statement 320: 1 (store_temp([23]) -> ([23])) - statement 321: 1 (function_call>([15], [20], [16], [21], [23]) -> ([24], [25], [26])) - statement 322: 1 (return([24], [25], [26])) - statement 382: 1 (store_temp([7]) -> ([7])) - statement 393: 1 (store_temp([18]) -> ([18])) - statement 400: 1 (store_temp([22]) -> ([22])) - statement 406: 1 (store_temp([29]) -> ([29])) - statement 411: 1 (branch_align() -> ()) - statement 419: 1 (store_temp([36]) -> ([36])) - statement 422: 1 (return([36], [41], [44])) + statement 304: 1 (store_temp([5]) -> ([5])) + statement 305: 1 (store_temp([11]) -> ([11])) + statement 307: 1 (return([5], [11], [14])) + statement 310: 1 (store_temp([5]) -> ([5])) + statement 312: 1 (function_call([5], [2]) -> ([15], [16], [17])) + statement 313: 1 (enum_match>([17]) { fallthrough([18]) 326([19]) }) + statement 319: 1 (store_temp([15]) -> ([15])) + statement 320: 1 (store_temp([20]) -> ([20])) + statement 323: 1 (store_temp([23]) -> ([23])) + statement 324: 1 (function_call>([15], [20], [16], [21], [23]) -> ([24], [25], [26])) + statement 325: 1 (return([24], [25], [26])) + statement 385: 1 (store_temp([7]) -> ([7])) + statement 396: 1 (store_temp([18]) -> ([18])) + statement 403: 1 (store_temp([22]) -> ([22])) + statement 409: 1 (store_temp([29]) -> ([29])) + statement 414: 1 (branch_align() -> ()) + statement 422: 1 (store_temp([36]) -> ([36])) + statement 425: 1 (return([36], [41], [44])) Weight by concrete libfunc: libfunc array_snapshot_pop_front: 11 libfunc store_temp: 11 @@ -730,32 +730,32 @@ erc20_transfer //! > expected_profiling_info Weight by sierra statement: - statement 724: 14 (storage_read_syscall([1], [2], [9], [7]) { fallthrough([10], [11], [12]) 786([13], [14], [15]) }) - statement 734: 14 (storage_read_syscall([10], [11], [8], [22]) { fallthrough([23], [24], [25]) 759([26], [27], [28]) }) - statement 272: 10 (storage_base_address_from_felt252([0], [28]) -> ([29], [30])) - statement 349: 10 (storage_base_address_from_felt252([67], [85]) -> ([86], [87])) - statement 374: 10 (storage_base_address_from_felt252([86], [112]) -> ([113], [114])) - statement 446: 10 (storage_base_address_from_felt252([146], [163]) -> ([164], [165])) + statement 727: 14 (storage_read_syscall([1], [2], [9], [7]) { fallthrough([10], [11], [12]) 789([13], [14], [15]) }) + statement 737: 14 (storage_read_syscall([10], [11], [8], [22]) { fallthrough([23], [24], [25]) 762([26], [27], [28]) }) + statement 275: 10 (storage_base_address_from_felt252([0], [28]) -> ([29], [30])) + statement 352: 10 (storage_base_address_from_felt252([67], [85]) -> ([86], [87])) + statement 377: 10 (storage_base_address_from_felt252([86], [112]) -> ([113], [114])) + statement 449: 10 (storage_base_address_from_felt252([146], [163]) -> ([164], [165])) statement 50: 9 (withdraw_gas([1], [2]) { fallthrough([5], [6]) 210([7], [8]) }) - statement 522: 9 (emit_event_syscall([210], [178], [237], [238]) { fallthrough([239], [240]) 535([241], [242], [243]) }) - statement 356: 8 (storage_write_syscall([68], [36], [92], [90], [88]) { fallthrough([93], [94]) 636([95], [96], [97]) }) - statement 366: 8 (storage_write_syscall([93], [94], [102], [101], [98]) { fallthrough([103], [104]) 617([105], [106], [107]) }) - statement 452: 8 (storage_write_syscall([147], [120], [169], [168], [166]) { fallthrough([170], [171]) 560([172], [173], [174]) }) - statement 459: 8 (storage_write_syscall([170], [171], [91], [176], [175]) { fallthrough([177], [178]) 546([179], [180], [181]) }) + statement 525: 9 (emit_event_syscall([210], [178], [237], [238]) { fallthrough([239], [240]) 538([241], [242], [243]) }) + statement 359: 8 (storage_write_syscall([68], [36], [92], [90], [88]) { fallthrough([93], [94]) 639([95], [96], [97]) }) + statement 369: 8 (storage_write_syscall([93], [94], [102], [101], [98]) { fallthrough([103], [104]) 620([105], [106], [107]) }) + statement 455: 8 (storage_write_syscall([147], [120], [169], [168], [166]) { fallthrough([170], [171]) 563([172], [173], [174]) }) + statement 462: 8 (storage_write_syscall([170], [171], [91], [176], [175]) { fallthrough([177], [178]) 549([179], [180], [181]) }) statement 58: 7 (contract_address_try_from_felt252([5], [14]) { fallthrough([15], [16]) 191([17]) }) - statement 747: 6 (store_temp>([37]) -> ([37])) + statement 750: 6 (store_temp>([37]) -> ([37])) statement 94: 5 (get_execution_info_v3_syscall([6], [3]) { fallthrough([43], [44], [45]) 137([46], [47], [48]) }) - statement 467: 5 (store_temp([187]) -> ([187])) - statement 727: 4 (u128s_from_felt252([0], [12]) { fallthrough([16], [17]) 769([18], [19], [20]) }) - statement 737: 4 (u128s_from_felt252([16], [25]) { fallthrough([29], [30]) 749([31], [32], [33]) }) + statement 470: 5 (store_temp([187]) -> ([187])) + statement 730: 4 (u128s_from_felt252([0], [12]) { fallthrough([16], [17]) 772([18], [19], [20]) }) + statement 740: 4 (u128s_from_felt252([16], [25]) { fallthrough([29], [30]) 752([31], [32], [33]) }) statement 37: 3 (store_temp>([28]) -> ([28])) statement 77: 3 (array_snapshot_pop_front([28]) { fallthrough([38], [39]) 92([40]) }) statement 127: 3 (store_temp,)>>([70]) -> ([70])) - statement 288: 3 (u128_overflowing_sub([34], [42], [46]) { fallthrough([47], [48]) 298([49], [50]) }) - statement 307: 3 (u128_overflowing_sub([54], [41], [61]) { fallthrough([62], [63]) 315([64], [65]) }) - statement 387: 3 (u128_overflowing_add([118], [126], [45]) { fallthrough([127], [128]) 397([129], [130]) }) - statement 405: 3 (u128_overflowing_add([134], [125], [44]) { fallthrough([141], [142]) 413([143], [144]) }) - statement 533: 3 (store_temp>([247]) -> ([247])) + statement 291: 3 (u128_overflowing_sub([34], [42], [46]) { fallthrough([47], [48]) 301([49], [50]) }) + statement 310: 3 (u128_overflowing_sub([54], [41], [61]) { fallthrough([62], [63]) 318([64], [65]) }) + statement 390: 3 (u128_overflowing_add([118], [126], [45]) { fallthrough([127], [128]) 400([129], [130]) }) + statement 408: 3 (u128_overflowing_add([134], [125], [44]) { fallthrough([141], [142]) 416([143], [144]) }) + statement 536: 3 (store_temp>([247]) -> ([247])) statement 1: 2 (const_as_box, Const>, 0>() -> ([4])) statement 4: 2 (store_temp>([6]) -> ([6])) statement 24: 2 (store_temp>([17]) -> ([17])) @@ -768,24 +768,24 @@ Weight by sierra statement: statement 74: 2 (u128s_from_felt252([23], [32]) { fallthrough([33], [34]) 150([35], [36], [37]) }) statement 76: 2 (store_temp>>([28]) -> ([28])) statement 111: 2 (store_temp([49]) -> ([49])) - statement 270: 2 (pedersen([2], [26], [19]) -> ([27], [28])) - statement 347: 2 (pedersen([27], [83], [82]) -> ([84], [85])) - statement 372: 2 (pedersen([84], [110], [109]) -> ([111], [112])) - statement 444: 2 (pedersen([111], [25], [161]) -> ([162], [163])) - statement 490: 2 (store_temp>([205]) -> ([211])) - statement 491: 2 (store_temp>([209]) -> ([212])) - statement 723: 2 (store_temp([9]) -> ([9])) - statement 726: 2 (store_temp([12]) -> ([12])) - statement 731: 2 (store_temp([10]) -> ([10])) - statement 732: 2 (store_temp([8]) -> ([8])) - statement 733: 2 (store_temp([22]) -> ([22])) - statement 736: 2 (store_temp([25]) -> ([25])) - statement 738: 2 (branch_align() -> ()) - statement 739: 2 (store_temp([23]) -> ([23])) - statement 744: 2 (store_temp([29]) -> ([29])) - statement 745: 2 (store_temp([34]) -> ([34])) - statement 746: 2 (store_temp([24]) -> ([24])) - statement 748: 2 (return([29], [34], [24], [37])) + statement 273: 2 (pedersen([2], [26], [19]) -> ([27], [28])) + statement 350: 2 (pedersen([27], [83], [82]) -> ([84], [85])) + statement 375: 2 (pedersen([84], [110], [109]) -> ([111], [112])) + statement 447: 2 (pedersen([111], [25], [161]) -> ([162], [163])) + statement 493: 2 (store_temp>([205]) -> ([211])) + statement 494: 2 (store_temp>([209]) -> ([212])) + statement 726: 2 (store_temp([9]) -> ([9])) + statement 729: 2 (store_temp([12]) -> ([12])) + statement 734: 2 (store_temp([10]) -> ([10])) + statement 735: 2 (store_temp([8]) -> ([8])) + statement 736: 2 (store_temp([22]) -> ([22])) + statement 739: 2 (store_temp([25]) -> ([25])) + statement 741: 2 (branch_align() -> ()) + statement 742: 2 (store_temp([23]) -> ([23])) + statement 747: 2 (store_temp([29]) -> ([29])) + statement 748: 2 (store_temp([34]) -> ([34])) + statement 749: 2 (store_temp([24]) -> ([24])) + statement 751: 2 (return([29], [34], [24], [37])) statement 5: 1 (cheatcode<10052436086942832998170947883001859293934451>([6]) -> ([7])) statement 8: 1 (array_new() -> ([9])) statement 10: 1 (store_temp([10]) -> ([10])) @@ -823,80 +823,80 @@ Weight by sierra statement: statement 125: 1 (store_temp([64]) -> ([64])) statement 126: 1 (store_temp([60]) -> ([60])) statement 128: 1 (return([59], [57], [64], [60], [70])) - statement 226: 1 (felt252_is_zero([9]) { fallthrough() 240([10]) }) - statement 244: 1 (felt252_is_zero([14]) { fallthrough() 258([15]) }) - statement 269: 1 (store_temp([26]) -> ([26])) - statement 271: 1 (store_temp([28]) -> ([28])) - statement 276: 1 (store_temp([29]) -> ([29])) - statement 277: 1 (store_temp([1]) -> ([1])) - statement 278: 1 (store_temp([3]) -> ([3])) - statement 279: 1 (store_temp>>([33]) -> ([33])) - statement 280: 1 (function_call, core::starknet::storage::MutableImpl::, core::starknet::storage_access::StoreUsingPacking::, core::starknet::storage_access::StoreUsingPacking::, core::starknet::storage_access::StoreUsingPacking::<(core::integer::u128,), core::integer::u128, core::starknet::storage_access::StorePackingTuple1::, core::starknet::storage_access::StoreUsingPacking::>, core::integer::u128Drop, core::tuple::TupleNextDrop::<(core::integer::u128,), core::tuple::TupleSplitTupleSize1::, core::tuple::IsTupleTupleSize1::, core::integer::u128Drop, core::tuple::TupleSize0Drop>, core::tuple::TupleSplitTupleSize1::>>>::read>([29], [1], [3], [33]) -> ([34], [35], [36], [37])) - statement 281: 1 (enum_match>([37]) { fallthrough([38]) 678([39]) }) - statement 289: 1 (branch_align() -> ()) - statement 293: 1 (store_temp([47]) -> ([54])) - statement 294: 1 (store_temp([51]) -> ([55])) - statement 295: 1 (store_temp([48]) -> ([56])) - statement 296: 1 (store_temp([53]) -> ([57])) - statement 297: 1 (jump() { 306() }) - statement 308: 1 (branch_align() -> ()) - statement 310: 1 (store_temp([62]) -> ([67])) - statement 311: 1 (store_temp([66]) -> ([68])) - statement 312: 1 (store_temp([63]) -> ([69])) - statement 313: 1 (store_temp([56]) -> ([70])) - statement 314: 1 (jump() { 340() }) - statement 340: 1 (enum_match([57]) { fallthrough([79]) 656([80]) }) - statement 346: 1 (store_temp([83]) -> ([83])) - statement 348: 1 (store_temp([85]) -> ([85])) - statement 355: 1 (store_temp([92]) -> ([92])) - statement 363: 1 (store_temp([93]) -> ([93])) - statement 364: 1 (store_temp([102]) -> ([102])) - statement 365: 1 (store_temp([101]) -> ([101])) - statement 371: 1 (store_temp([110]) -> ([110])) - statement 373: 1 (store_temp([112]) -> ([112])) - statement 378: 1 (store_temp([113]) -> ([113])) - statement 379: 1 (store_temp([103]) -> ([103])) - statement 380: 1 (store_temp([104]) -> ([104])) - statement 381: 1 (store_temp>>([117]) -> ([117])) - statement 382: 1 (function_call, core::starknet::storage::MutableImpl::, core::starknet::storage_access::StoreUsingPacking::, core::starknet::storage_access::StoreUsingPacking::, core::starknet::storage_access::StoreUsingPacking::<(core::integer::u128,), core::integer::u128, core::starknet::storage_access::StorePackingTuple1::, core::starknet::storage_access::StoreUsingPacking::>, core::integer::u128Drop, core::tuple::TupleNextDrop::<(core::integer::u128,), core::tuple::TupleSplitTupleSize1::, core::tuple::IsTupleTupleSize1::, core::integer::u128Drop, core::tuple::TupleSize0Drop>, core::tuple::TupleSplitTupleSize1::>>>::read>([113], [103], [104], [117]) -> ([118], [119], [120], [121])) - statement 383: 1 (enum_match>([121]) { fallthrough([122]) 600([123]) }) - statement 388: 1 (branch_align() -> ()) - statement 392: 1 (store_temp([127]) -> ([134])) - statement 393: 1 (store_temp([131]) -> ([135])) - statement 394: 1 (store_temp([128]) -> ([136])) - statement 395: 1 (store_temp([133]) -> ([137])) - statement 396: 1 (jump() { 405() }) - statement 406: 1 (branch_align() -> ()) - statement 408: 1 (store_temp([141]) -> ([146])) - statement 409: 1 (store_temp([145]) -> ([147])) - statement 410: 1 (store_temp([142]) -> ([148])) - statement 411: 1 (store_temp([136]) -> ([149])) - statement 412: 1 (jump() { 438() }) - statement 438: 1 (enum_match([137]) { fallthrough([158]) 578([159]) }) - statement 443: 1 (store_temp([25]) -> ([25])) - statement 445: 1 (store_temp([163]) -> ([163])) - statement 451: 1 (store_temp([169]) -> ([169])) - statement 456: 1 (store_temp([170]) -> ([170])) - statement 457: 1 (store_temp([91]) -> ([91])) - statement 458: 1 (store_temp([176]) -> ([176])) - statement 463: 1 (array_new() -> ([184])) - statement 464: 1 (array_new() -> ([185])) - statement 468: 1 (enum_match([187]) { fallthrough([188]) 493([189]) }) - statement 470: 1 (store_temp([177]) -> ([177])) - statement 483: 1 (store_temp([204]) -> ([204])) - statement 484: 1 (array_append([184], [204]) -> ([205])) - statement 485: 1 (array_append([185], [195]) -> ([206])) - statement 486: 1 (array_append([206], [197]) -> ([207])) - statement 487: 1 (array_append([207], [201]) -> ([208])) - statement 488: 1 (array_append([208], [203]) -> ([209])) - statement 489: 1 (store_temp([190]) -> ([210])) - statement 492: 1 (jump() { 516() }) - statement 524: 1 (store_temp([239]) -> ([239])) - statement 529: 1 (store_temp([164]) -> ([164])) - statement 530: 1 (store_temp([244]) -> ([244])) - statement 531: 1 (store_temp([162]) -> ([162])) - statement 532: 1 (store_temp([240]) -> ([240])) - statement 534: 1 (return([164], [244], [162], [240], [247])) + statement 229: 1 (felt252_is_zero([9]) { fallthrough() 243([10]) }) + statement 247: 1 (felt252_is_zero([14]) { fallthrough() 261([15]) }) + statement 272: 1 (store_temp([26]) -> ([26])) + statement 274: 1 (store_temp([28]) -> ([28])) + statement 279: 1 (store_temp([29]) -> ([29])) + statement 280: 1 (store_temp([1]) -> ([1])) + statement 281: 1 (store_temp([3]) -> ([3])) + statement 282: 1 (store_temp>>([33]) -> ([33])) + statement 283: 1 (function_call, core::starknet::storage::MutableImpl::, core::starknet::storage_access::StoreUsingPacking::, core::starknet::storage_access::StoreUsingPacking::, core::starknet::storage_access::StoreUsingPacking::<(core::integer::u128,), core::integer::u128, core::starknet::storage_access::StorePackingTuple1::, core::starknet::storage_access::StoreUsingPacking::>, core::integer::u128Drop, core::tuple::TupleNextDrop::<(core::integer::u128,), core::tuple::TupleSplitTupleSize1::, core::tuple::IsTupleTupleSize1::, core::integer::u128Drop, core::tuple::TupleSize0Drop>, core::tuple::TupleSplitTupleSize1::>>>::read>([29], [1], [3], [33]) -> ([34], [35], [36], [37])) + statement 284: 1 (enum_match>([37]) { fallthrough([38]) 681([39]) }) + statement 292: 1 (branch_align() -> ()) + statement 296: 1 (store_temp([47]) -> ([54])) + statement 297: 1 (store_temp([51]) -> ([55])) + statement 298: 1 (store_temp([48]) -> ([56])) + statement 299: 1 (store_temp([53]) -> ([57])) + statement 300: 1 (jump() { 309() }) + statement 311: 1 (branch_align() -> ()) + statement 313: 1 (store_temp([62]) -> ([67])) + statement 314: 1 (store_temp([66]) -> ([68])) + statement 315: 1 (store_temp([63]) -> ([69])) + statement 316: 1 (store_temp([56]) -> ([70])) + statement 317: 1 (jump() { 343() }) + statement 343: 1 (enum_match([57]) { fallthrough([79]) 659([80]) }) + statement 349: 1 (store_temp([83]) -> ([83])) + statement 351: 1 (store_temp([85]) -> ([85])) + statement 358: 1 (store_temp([92]) -> ([92])) + statement 366: 1 (store_temp([93]) -> ([93])) + statement 367: 1 (store_temp([102]) -> ([102])) + statement 368: 1 (store_temp([101]) -> ([101])) + statement 374: 1 (store_temp([110]) -> ([110])) + statement 376: 1 (store_temp([112]) -> ([112])) + statement 381: 1 (store_temp([113]) -> ([113])) + statement 382: 1 (store_temp([103]) -> ([103])) + statement 383: 1 (store_temp([104]) -> ([104])) + statement 384: 1 (store_temp>>([117]) -> ([117])) + statement 385: 1 (function_call, core::starknet::storage::MutableImpl::, core::starknet::storage_access::StoreUsingPacking::, core::starknet::storage_access::StoreUsingPacking::, core::starknet::storage_access::StoreUsingPacking::<(core::integer::u128,), core::integer::u128, core::starknet::storage_access::StorePackingTuple1::, core::starknet::storage_access::StoreUsingPacking::>, core::integer::u128Drop, core::tuple::TupleNextDrop::<(core::integer::u128,), core::tuple::TupleSplitTupleSize1::, core::tuple::IsTupleTupleSize1::, core::integer::u128Drop, core::tuple::TupleSize0Drop>, core::tuple::TupleSplitTupleSize1::>>>::read>([113], [103], [104], [117]) -> ([118], [119], [120], [121])) + statement 386: 1 (enum_match>([121]) { fallthrough([122]) 603([123]) }) + statement 391: 1 (branch_align() -> ()) + statement 395: 1 (store_temp([127]) -> ([134])) + statement 396: 1 (store_temp([131]) -> ([135])) + statement 397: 1 (store_temp([128]) -> ([136])) + statement 398: 1 (store_temp([133]) -> ([137])) + statement 399: 1 (jump() { 408() }) + statement 409: 1 (branch_align() -> ()) + statement 411: 1 (store_temp([141]) -> ([146])) + statement 412: 1 (store_temp([145]) -> ([147])) + statement 413: 1 (store_temp([142]) -> ([148])) + statement 414: 1 (store_temp([136]) -> ([149])) + statement 415: 1 (jump() { 441() }) + statement 441: 1 (enum_match([137]) { fallthrough([158]) 581([159]) }) + statement 446: 1 (store_temp([25]) -> ([25])) + statement 448: 1 (store_temp([163]) -> ([163])) + statement 454: 1 (store_temp([169]) -> ([169])) + statement 459: 1 (store_temp([170]) -> ([170])) + statement 460: 1 (store_temp([91]) -> ([91])) + statement 461: 1 (store_temp([176]) -> ([176])) + statement 466: 1 (array_new() -> ([184])) + statement 467: 1 (array_new() -> ([185])) + statement 471: 1 (enum_match([187]) { fallthrough([188]) 496([189]) }) + statement 473: 1 (store_temp([177]) -> ([177])) + statement 486: 1 (store_temp([204]) -> ([204])) + statement 487: 1 (array_append([184], [204]) -> ([205])) + statement 488: 1 (array_append([185], [195]) -> ([206])) + statement 489: 1 (array_append([206], [197]) -> ([207])) + statement 490: 1 (array_append([207], [201]) -> ([208])) + statement 491: 1 (array_append([208], [203]) -> ([209])) + statement 492: 1 (store_temp([190]) -> ([210])) + statement 495: 1 (jump() { 519() }) + statement 527: 1 (store_temp([239]) -> ([239])) + statement 532: 1 (store_temp([164]) -> ([164])) + statement 533: 1 (store_temp([244]) -> ([244])) + statement 534: 1 (store_temp([162]) -> ([162])) + statement 535: 1 (store_temp([240]) -> ([240])) + statement 537: 1 (return([164], [244], [162], [240], [247])) Weight by concrete libfunc: libfunc storage_base_address_from_felt252: 40 libfunc storage_write_syscall: 32 diff --git a/crates/cairo-lang-sierra-generator/Cargo.toml b/crates/cairo-lang-sierra-generator/Cargo.toml index 69b4a4345da..c7df8e87f20 100644 --- a/crates/cairo-lang-sierra-generator/Cargo.toml +++ b/crates/cairo-lang-sierra-generator/Cargo.toml @@ -25,6 +25,7 @@ cairo-lang-test-utils = { path = "../cairo-lang-test-utils", version = "=2.18.0" ] } cairo-lang-utils = { path = "../cairo-lang-utils", version = "=2.18.0", features = ["tracing"] } itertools = { workspace = true, default-features = true } +num-bigint = { workspace = true, default-features = true } num-traits = { workspace = true } rayon.workspace = true salsa.workspace = true diff --git a/crates/cairo-lang-sierra-generator/src/block_generator.rs b/crates/cairo-lang-sierra-generator/src/block_generator.rs index d0e7b77a2a8..3745d8fed79 100644 --- a/crates/cairo-lang-sierra-generator/src/block_generator.rs +++ b/crates/cairo-lang-sierra-generator/src/block_generator.rs @@ -2,21 +2,24 @@ #[path = "block_generator_test.rs"] mod test; +use cairo_lang_defs::ids::{NamedLanguageElementId, TopLevelLanguageElementId}; use cairo_lang_diagnostics::Maybe; use cairo_lang_lowering as lowering; use cairo_lang_lowering::BlockId; use cairo_lang_lowering::db::LoweringGroup; use cairo_lang_lowering::ids::LocationId; +use cairo_lang_semantic::items::constant::ConstValueId; use cairo_lang_sierra as sierra; use cairo_lang_utils::ordered_hash_map::OrderedHashMap; use itertools::{chain, enumerate, zip_eq}; use lowering::analysis::StatementLocation; use lowering::{MatchArm, VarUsage}; +use num_bigint::BigInt; use sierra::extensions::lib_func::SierraApChange; use sierra::program; use crate::block_generator::sierra::ids::ConcreteLibfuncId; -use crate::db::SierraGenGroup; +use crate::db::{EXTERNALLY_PROVIDED_CONST, SierraGenGroup}; use crate::expr_generator_context::{ExprGenerationResult, ExprGeneratorContext}; use crate::lifetime::{DropLocation, SierraGenVar, UseLocation}; use crate::local_variables::MIN_SIZE_FOR_LOCAL_INTO_BOX; @@ -331,15 +334,24 @@ fn generate_statement_call_code<'db>( statement: &lowering::StatementCall<'db>, statement_location: &StatementLocation, ) -> Maybe<()> { + let db = context.get_db(); + + // Handle the reserved `__externally_provided_const__` extern function: replace the call with a + // `const_as_immediate` of the value supplied by the installed `ExternalConstProvider`. + if let Some((extern_id, _)) = statement.function.get_extern(db) + && extern_id.name(db).long(db) == EXTERNALLY_PROVIDED_CONST + { + return generate_externally_provided_const_code(context, statement); + } + // Check if this is a user defined function or a libfunc. - let (body, libfunc_id) = - get_concrete_libfunc_id(context.get_db(), statement.function, statement.with_coupon); + let (body, libfunc_id) = get_concrete_libfunc_id(db, statement.function, statement.with_coupon); // Checks if the call invalidates ap tracking. - let libfunc_signature = get_libfunc_signature(context.get_db(), &libfunc_id); + let libfunc_signature = get_libfunc_signature(db, &libfunc_id); let [branch_signature] = &libfunc_signature.branch_signatures[..] else { panic!( "Unexpected branches in '{}'.", - DebugReplacer { db: context.get_db() }.replace_libfunc_id(&libfunc_id) + DebugReplacer { db }.replace_libfunc_id(&libfunc_id) ); }; if matches!(branch_signature.ap_change, SierraApChange::Unknown) { @@ -393,6 +405,53 @@ fn generate_statement_call_code<'db>( Ok(()) } +/// Generates Sierra code for a call to the reserved `__externally_provided_const__` extern +/// function, replacing it with a `const_as_immediate`. +/// +/// When an [`crate::db::ExternalConstProvider`] is installed, the value is taken from it (keyed by +/// the full path of the extern function, so distinct declarations in different modules resolve +/// independently) and validated against the declared return type; a provider returning an error +/// fails Sierra generation. When no provider is installed (e.g. generic compilation, profiling or +/// size estimation, which don't use the value), it defaults to a zero constant of the declared +/// type — build flows that need the real value install a provider (e.g. the two-pass class-hash +/// injection in `starknet`'s `compile_path`). +fn generate_externally_provided_const_code<'db>( + context: &mut ExprGeneratorContext<'db, '_>, + statement: &lowering::StatementCall<'db>, +) -> Maybe<()> { + let db = context.get_db(); + let [output] = statement.outputs[..] else { + panic!("`{EXTERNALLY_PROVIDED_CONST}` must have exactly one output."); + }; + // The declared return type, which the provided value must match. + let return_type = context.get_lowered_variable(output).ty; + + let value = match db.external_const_provider() { + Some(provider) => { + let (extern_id, _) = statement.function.get_extern(db).unwrap(); + let value = provider(db, &extern_id.full_path(db), return_type)?; + // The provider returns a value of an arbitrary type; ensure it matches the declared + // one, as a mismatch would produce a type-incorrect Sierra program. + if value.ty(db)? != return_type { + panic!( + "`{EXTERNALLY_PROVIDED_CONST}` provider returned a value whose type does not \ + match the declared return type." + ); + } + value + } + None => ConstValueId::from_int(db, return_type, &BigInt::ZERO), + }; + + let output_var = context.get_sierra_variable(output); + context.push_statement(simple_basic_statement( + const_libfunc_id_by_type(db, value, false), + &[], + &[output_var], + )); + Ok(()) +} + /// Returns if the variable at the given location should be duplicated. fn should_dup<'db>( context: &mut ExprGeneratorContext<'db, '_>, diff --git a/crates/cairo-lang-sierra-generator/src/block_generator_test.rs b/crates/cairo-lang-sierra-generator/src/block_generator_test.rs index 272544bd7e9..9e5b44938d8 100644 --- a/crates/cairo-lang-sierra-generator/src/block_generator_test.rs +++ b/crates/cairo-lang-sierra-generator/src/block_generator_test.rs @@ -1,8 +1,11 @@ +use std::sync::Arc; + use cairo_lang_debug::DebugWithDb; use cairo_lang_filesystem::flag::{Flag, FlagsGroup}; use cairo_lang_filesystem::ids::FlagLongId; use cairo_lang_lowering::db::LoweringGroup; use cairo_lang_lowering::{self as lowering, LoweringStage, ids}; +use cairo_lang_semantic::items::constant::ConstValueId; use cairo_lang_semantic::test_utils::setup_test_function; use cairo_lang_test_utils::parse_test_file::TestRunnerResult; use cairo_lang_utils::Intern; @@ -10,8 +13,10 @@ use cairo_lang_utils::ordered_hash_map::OrderedHashMap; use cairo_lang_utils::ordered_hash_set::OrderedHashSet; use lowering::fmt::LoweredFormatter; use lowering::ids::ConcreteFunctionWithBodyId; +use num_bigint::BigInt; use super::generate_function_result; +use crate::db::SierraGenGroup; use crate::expr_generator_context::ExprGeneratorContext; use crate::lifetime::find_variable_lifetime; use crate::replace_ids::replace_sierra_ids; @@ -28,6 +33,7 @@ cairo_lang_test_utils::test_file_test!( serialization: "serialization", early_return: "early_return", panic: "panic", + externally_provided_const: "externally_provided_const", }, block_generator_test ); @@ -43,6 +49,13 @@ fn block_generator_test( let add_withdraw_gas_flag_id = FlagLongId(Flag::ADD_WITHDRAW_GAS.into()); db.set_flag(add_withdraw_gas_flag_id, Some(Flag::AddWithdrawGas(false))); + // Install a test provider for the `__externally_provided_const__` extern function. It is inert + // unless that extern is actually called, and resolves every call to the constant `7777` of the + // declared return type. + db.set_external_const_provider(Some(Arc::new(|db, _full_path, ty| { + Ok(ConstValueId::from_int(db, ty, &BigInt::from(7777))) + }))); + // Parse code and create semantic model. let (test_function, semantic_diagnostics) = setup_test_function(db, inputs).split(); diff --git a/crates/cairo-lang-sierra-generator/src/block_generator_test_data/externally_provided_const b/crates/cairo-lang-sierra-generator/src/block_generator_test_data/externally_provided_const new file mode 100644 index 00000000000..56401898ce0 --- /dev/null +++ b/crates/cairo-lang-sierra-generator/src/block_generator_test_data/externally_provided_const @@ -0,0 +1,33 @@ +//! > Test that a call to `__externally_provided_const__` becomes a const_as_immediate. + +//! > test_runner_name +block_generator_test + +//! > function_code +extern fn __externally_provided_const__() -> felt252 nopanic; + +fn foo() -> felt252 { + __externally_provided_const__() +} + +//! > function_name +foo + +//! > semantic_diagnostics + +//! > lowering_diagnostics + +//! > sierra_gen_diagnostics + +//! > sierra_code +const_as_immediate>() -> ([0]) +PushValues([0]: felt252) -> ([0]) +return([0]) + +//! > lowering_flat +Parameters: +blk0 (root): +Statements: + (v0: core::felt252) <- test::__externally_provided_const__() +End: + Return(v0) diff --git a/crates/cairo-lang-sierra-generator/src/db.rs b/crates/cairo-lang-sierra-generator/src/db.rs index 8b11fad2c43..7c097305256 100644 --- a/crates/cairo-lang-sierra-generator/src/db.rs +++ b/crates/cairo-lang-sierra-generator/src/db.rs @@ -7,12 +7,13 @@ use cairo_lang_lowering as lowering; use cairo_lang_lowering::db::LoweringGroup; use cairo_lang_lowering::panic::PanicSignatureInfo; use cairo_lang_semantic as semantic; +use cairo_lang_semantic::items::constant::ConstValueId; use cairo_lang_sierra::extensions::lib_func::SierraApChange; use cairo_lang_sierra::extensions::{ConcreteType, GenericTypeEx}; use cairo_lang_sierra::ids::ConcreteTypeId; use lowering::ids::ConcreteFunctionWithBodyId; use salsa::plumbing::FromId; -use salsa::{Database, Id}; +use salsa::{Database, Id, Setter}; use crate::program_generator::{self, SierraProgramWithDebug}; use crate::replace_ids::SierraIdReplacer; @@ -33,6 +34,39 @@ pub enum SierraGeneratorTypeLongId<'db> { Phantom(semantic::TypeId<'db>), } +/// The reserved name of the extern function whose calls are replaced, at the Sierra generation +/// stage, by a constant value supplied by the installed [`ExternalConstProvider`]. It may be +/// declared anywhere; it is recognized solely by this name and never reaches Sierra. +pub const EXTERNALLY_PROVIDED_CONST: &str = "__externally_provided_const__"; + +/// A callback supplying the constant value for a call to the reserved +/// `__externally_provided_const__` extern function. +/// +/// It is given the full path of the (concrete) extern function being called and its declared +/// return type, and returns the [`ConstValueId`] that the call should be replaced with at the +/// Sierra generation stage. The provider is responsible for deciding what happens when no value is +/// available for the given path (e.g. returning an error). The returned value's type is validated +/// against the declared return type by the caller. +/// +/// Installed on the database by its constructor (e.g. by the build driver); it is not set by +/// default. +pub type ExternalConstProvider = Arc< + dyn for<'db> Fn(&'db dyn Database, &str, semantic::TypeId<'db>) -> Maybe> + + Send + + Sync, +>; + +#[salsa::input] +pub struct SierraGenGroupInput { + #[returns(ref)] + pub external_const_provider: Option, +} + +#[salsa::tracked] +pub fn sierra_gen_group_input(db: &dyn Database) -> SierraGenGroupInput { + SierraGenGroupInput::new(db, None) +} + /// Wrapper for the concrete libfunc long id, providing a unique id for each libfunc. #[salsa::interned(revisions = usize::MAX)] struct ConcreteLibfuncIdLongWrapper { @@ -272,6 +306,20 @@ pub trait SierraGenGroup: Database { program_generator::get_sierra_program(self.as_dyn_database(), (), requested_crate_ids) .maybe_as_ref() } + + /// Returns the installed [`ExternalConstProvider`], if any. + fn external_const_provider(&self) -> Option { + sierra_gen_group_input(self.as_dyn_database()) + .external_const_provider(self.as_dyn_database()) + .clone() + } + + /// Installs the [`ExternalConstProvider`] used to resolve calls to the reserved + /// `__externally_provided_const__` extern function. + fn set_external_const_provider(&mut self, provider: Option) { + let input = sierra_gen_group_input(self.as_dyn_database()); + input.set_external_const_provider(self).to(provider); + } } impl SierraGenGroup for T {} diff --git a/crates/cairo-lang-sierra-generator/src/local_variables.rs b/crates/cairo-lang-sierra-generator/src/local_variables.rs index 778a9aad800..7041e397960 100644 --- a/crates/cairo-lang-sierra-generator/src/local_variables.rs +++ b/crates/cairo-lang-sierra-generator/src/local_variables.rs @@ -2,6 +2,7 @@ #[path = "local_variables_test.rs"] mod test; +use cairo_lang_defs::ids::NamedLanguageElementId; use cairo_lang_diagnostics::Maybe; use cairo_lang_lowering as lowering; use cairo_lang_lowering::db::LoweringGroup; @@ -23,7 +24,7 @@ use lowering::{Lowered, MatchInfo, Statement, VarRemapping, VarUsage}; use salsa::Database; use crate::ap_tracking::{ApTrackingConfiguration, get_ap_tracking_configuration}; -use crate::db::SierraGenGroup; +use crate::db::{EXTERNALLY_PROVIDED_CONST, SierraGenGroup}; use crate::replace_ids::{DebugReplacer, SierraIdReplacer}; use crate::utils::{ enum_init_libfunc_id, get_concrete_libfunc_id, get_libfunc_signature, match_enum_libfunc_id, @@ -390,13 +391,25 @@ impl<'db, 'a> FindLocalsContext<'db, 'a> { BranchInfo { known_ap_change: true } } lowering::Statement::Call(statement_call) => { - let (_, concrete_function_id) = get_concrete_libfunc_id( - self.db, - statement_call.function, - statement_call.with_coupon, - ); + // The reserved `__externally_provided_const__` extern is replaced by a + // `const_as_immediate` at code generation, so treat it as a constant here (known + // ap-change, constant output) rather than resolving a (non-existent) libfunc. + if let Some((extern_id, _)) = statement_call.function.get_extern(self.db) + && extern_id.name(self.db).long(self.db) == EXTERNALLY_PROVIDED_CONST + { + if let [output] = statement_call.outputs[..] { + self.constants.insert(output); + } + BranchInfo { known_ap_change: true } + } else { + let (_, concrete_function_id) = get_concrete_libfunc_id( + self.db, + statement_call.function, + statement_call.with_coupon, + ); - self.analyze_call(concrete_function_id, inputs, outputs) + self.analyze_call(concrete_function_id, inputs, outputs) + } } lowering::Statement::StructConstruct(statement_struct_construct) => { let ty = self.db.get_concrete_type_id(