Skip to content

Commit d7be2ef

Browse files
Add target-fork conditional compilation (#1940)
* Add target-fork conditional compilation * Close fork condition proof surfaces * Define fork condition source fallback * chore: auto-refresh derived artifacts * Close fork conditional proof surface * Close fork conditional generic induction case --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 38bb3a5 commit d7be2ef

21 files changed

Lines changed: 392 additions & 1 deletion

Compiler/CompilationModel/EcmAxiomCollection.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ where
2323
| _ => []
2424
collectExprEcmAxioms : Expr → List (String × String)
2525
| .ite cond a b => collectExprEcmAxioms cond ++ collectExprEcmAxioms a ++ collectExprEcmAxioms b
26+
| .forkIfAtLeast _ thenExpr elseExpr => collectExprEcmAxioms thenExpr ++ collectExprEcmAxioms elseExpr
2627
| _ => []
2728

2829
end Compiler.CompilationModel

Compiler/CompilationModel/ExpressionCompile.lean

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,8 @@ def compileExpr (fields : List Field)
453453
if args.length != inArity then
454454
throw s!"Compilation error: intrinsic {name} builtin {builtinName} expects {inArity} arg(s), got {args.length}"
455455
pure (YulExpr.call builtinName argExprs)
456+
| Expr.forkIfAtLeast required _thenExpr _elseExpr =>
457+
throw s!"Compilation error: unresolved fork_if_at_least {required}; compile through compileSpecsWithOptions so the branch can be selected from --target-fork before Yul emission"
456458
| Expr.eq a b => return yulBinOp "eq" (← compileExpr fields dynamicSource a) (← compileExpr fields dynamicSource b)
457459
| Expr.gt a b => return yulBinOp "gt" (← compileExpr fields dynamicSource a) (← compileExpr fields dynamicSource b)
458460
| Expr.sgt a b => return yulBinOp "sgt" (← compileExpr fields dynamicSource a) (← compileExpr fields dynamicSource b)

Compiler/CompilationModel/LogicalPurity.lean

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ partial def exprContainsCallLike (expr : Expr) : Bool :=
5151
exprContainsCallLike a || exprContainsCallLike b
5252
| Expr.intrinsic _ _ _ args =>
5353
exprListContainsCallLike args
54+
| Expr.forkIfAtLeast _ thenExpr elseExpr =>
55+
exprContainsCallLike thenExpr || exprContainsCallLike elseExpr
5456
| Expr.mulDivDown a b c | Expr.mulDivUp a b c
5557
| Expr.mulDiv512Down a b c | Expr.mulDiv512Up a b c =>
5658
exprContainsCallLike a || exprContainsCallLike b || exprContainsCallLike c
@@ -159,6 +161,8 @@ def exprContainsUnsafeLogicalCallLike (expr : Expr) : Bool :=
159161
exprContainsUnsafeLogicalCallLike a || exprContainsUnsafeLogicalCallLike b
160162
| Expr.intrinsic _ _ _ args =>
161163
exprListAnyUnsafeLogicalCallLike args
164+
| Expr.forkIfAtLeast _ thenExpr elseExpr =>
165+
exprContainsUnsafeLogicalCallLike thenExpr || exprContainsUnsafeLogicalCallLike elseExpr
162166
| Expr.mulDivDown a b c
163167
| Expr.mulDiv512Down a b c =>
164168
exprContainsUnsafeLogicalCallLike a || exprContainsUnsafeLogicalCallLike b || exprContainsUnsafeLogicalCallLike c

Compiler/CompilationModel/ScopeValidation.lean

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,9 @@ def validateScopedExprIdentifiers
367367
validateScopedExprIdentifiers context params paramScope dynamicParams localScope constructorArgCount b
368368
| Expr.intrinsic _ _ _ args =>
369369
validateScopedExprIdentifiersList context params paramScope dynamicParams localScope constructorArgCount args
370+
| Expr.forkIfAtLeast _ thenExpr elseExpr => do
371+
validateScopedExprIdentifiers context params paramScope dynamicParams localScope constructorArgCount thenExpr
372+
validateScopedExprIdentifiers context params paramScope dynamicParams localScope constructorArgCount elseExpr
370373
| Expr.wDivUp a b => do
371374
validateArithDuplicatedOperandPurity context [b]
372375
validateScopedExprIdentifiers context params paramScope dynamicParams localScope constructorArgCount a

Compiler/CompilationModel/Types.lean

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,14 @@ inductive Expr
483483
(lowering : Verity.Core.Intrinsics.YulLowering)
484484
(minFork : Verity.Core.Intrinsics.HardFork)
485485
(args : List Expr)
486+
/-- Compile-time fork selection. `thenExpr` is selected when the compiler
487+
target fork is at least `required`; otherwise `elseExpr` is selected.
488+
The unselected branch is removed before intrinsic fork gates and Yul
489+
lowering run, so this is suitable for explicit opcode/emulation fallback
490+
pairs without silently weakening `min_fork` on the intrinsic itself. -/
491+
| forkIfAtLeast
492+
(required : Verity.Core.Intrinsics.HardFork)
493+
(thenExpr elseExpr : Expr)
486494
| eq (a b : Expr)
487495
| ge (a b : Expr)
488496
| gt (a b : Expr) -- Greater than (strict)

Compiler/CompilationModel/UsageAnalysis.lean

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,9 @@ def exprUsesArrayElementKind (includePlain includeWord : Bool) : Expr → Bool
173173
exprUsesArrayElementKind includePlain includeWord b
174174
| Expr.intrinsic _ _ _ args =>
175175
exprListUsesArrayElementKind includePlain includeWord args
176+
| Expr.forkIfAtLeast _ thenExpr elseExpr =>
177+
exprUsesArrayElementKind includePlain includeWord thenExpr ||
178+
exprUsesArrayElementKind includePlain includeWord elseExpr
176179
| Expr.mulDivDown a b c | Expr.mulDivUp a b c | Expr.mulDiv512Down a b c | Expr.mulDiv512Up a b c =>
177180
exprUsesArrayElementKind includePlain includeWord a ||
178181
exprUsesArrayElementKind includePlain includeWord b ||
@@ -356,6 +359,8 @@ def exprUsesArrayElement : Expr → Bool
356359
Expr.ceilDiv a b =>
357360
exprUsesArrayElement a || exprUsesArrayElement b
358361
| Expr.intrinsic _ _ _ args => exprListUsesArrayElement args
362+
| Expr.forkIfAtLeast _ thenExpr elseExpr =>
363+
exprUsesArrayElement thenExpr || exprUsesArrayElement elseExpr
359364
| Expr.mulDivDown a b c | Expr.mulDivUp a b c | Expr.mulDiv512Down a b c | Expr.mulDiv512Up a b c =>
360365
exprUsesArrayElement a || exprUsesArrayElement b || exprUsesArrayElement c
361366
| Expr.bitNot a | Expr.logicalNot a =>
@@ -559,6 +564,8 @@ def exprUsesParamDynamicHeadWord : Expr → Bool
559564
| Expr.wMulDown a b | Expr.wDivUp a b | Expr.min a b | Expr.max a b | Expr.ceilDiv a b =>
560565
exprUsesParamDynamicHeadWord a || exprUsesParamDynamicHeadWord b
561566
| Expr.intrinsic _ _ _ args => exprListUsesParamDynamicHeadWord args
567+
| Expr.forkIfAtLeast _ thenExpr elseExpr =>
568+
exprUsesParamDynamicHeadWord thenExpr || exprUsesParamDynamicHeadWord elseExpr
562569
| Expr.mulDivDown a b c | Expr.mulDivUp a b c
563570
| Expr.mulDiv512Down a b c | Expr.mulDiv512Up a b c
564571
| Expr.ite a b c =>
@@ -701,6 +708,8 @@ def exprUsesMulDiv512 : Expr → Bool
701708
| Expr.wMulDown a b | Expr.wDivUp a b | Expr.min a b | Expr.max a b | Expr.ceilDiv a b =>
702709
exprUsesMulDiv512 a || exprUsesMulDiv512 b
703710
| Expr.intrinsic _ _ _ args => exprListUsesMulDiv512 args
711+
| Expr.forkIfAtLeast _ thenExpr elseExpr =>
712+
exprUsesMulDiv512 thenExpr || exprUsesMulDiv512 elseExpr
704713
| Expr.mulDivDown a b c | Expr.mulDivUp a b c | Expr.ite a b c =>
705714
exprUsesMulDiv512 a || exprUsesMulDiv512 b || exprUsesMulDiv512 c
706715
| Expr.literal _ | Expr.param _ | Expr.constructorArg _
@@ -859,6 +868,8 @@ def exprUsesStorageArrayElement : Expr → Bool
859868
Expr.ceilDiv a b =>
860869
exprUsesStorageArrayElement a || exprUsesStorageArrayElement b
861870
| Expr.intrinsic _ _ _ args => exprListUsesStorageArrayElement args
871+
| Expr.forkIfAtLeast _ thenExpr elseExpr =>
872+
exprUsesStorageArrayElement thenExpr || exprUsesStorageArrayElement elseExpr
862873
| Expr.mulDivDown a b c | Expr.mulDivUp a b c | Expr.mulDiv512Down a b c | Expr.mulDiv512Up a b c =>
863874
exprUsesStorageArrayElement a || exprUsesStorageArrayElement b || exprUsesStorageArrayElement c
864875
| Expr.bitNot a | Expr.logicalNot a =>
@@ -1021,6 +1032,8 @@ def exprUsesDynamicBytesEq : Expr → Bool
10211032
| Expr.ceilDiv a b =>
10221033
exprUsesDynamicBytesEq a || exprUsesDynamicBytesEq b
10231034
| Expr.intrinsic _ _ _ args => exprListUsesDynamicBytesEq args
1035+
| Expr.forkIfAtLeast _ thenExpr elseExpr =>
1036+
exprUsesDynamicBytesEq thenExpr || exprUsesDynamicBytesEq elseExpr
10241037
| Expr.mulDivDown a b c | Expr.mulDivUp a b c | Expr.mulDiv512Down a b c | Expr.mulDiv512Up a b c =>
10251038
exprUsesDynamicBytesEq a || exprUsesDynamicBytesEq b || exprUsesDynamicBytesEq c
10261039
| Expr.bitNot a | Expr.logicalNot a =>

Compiler/CompilationModel/Validation.lean

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,8 @@ def exprReadsStateOrEnv : Expr → Bool
302302
Expr.ceilDiv a b =>
303303
exprReadsStateOrEnv a || exprReadsStateOrEnv b
304304
| Expr.intrinsic _ _ _ args => exprListReadsStateOrEnv args
305+
| Expr.forkIfAtLeast _ thenExpr elseExpr =>
306+
exprReadsStateOrEnv thenExpr || exprReadsStateOrEnv elseExpr
305307
| Expr.mulDivDown a b c | Expr.mulDivUp a b c
306308
| Expr.mulDiv512Down a b c | Expr.mulDiv512Up a b c =>
307309
exprReadsStateOrEnv a || exprReadsStateOrEnv b || exprReadsStateOrEnv c
@@ -361,6 +363,8 @@ def exprWritesState : Expr → Bool
361363
| Expr.externalCall name args =>
362364
if name == builtinExpName then exprListWritesState args else true
363365
| Expr.intrinsic _ _ _ args => exprListWritesState args
366+
| Expr.forkIfAtLeast _ thenExpr elseExpr =>
367+
exprWritesState thenExpr || exprWritesState elseExpr
364368
| Expr.internalCall _ _ => true
365369
| Expr.adtConstruct _ _ args => exprListWritesState args
366370
| Expr.extcodesize addr =>
@@ -519,6 +523,8 @@ def exprHasUntrackableWrites : Expr → Bool
519523
| Expr.byte a b =>
520524
exprHasUntrackableWrites a || exprHasUntrackableWrites b
521525
| Expr.intrinsic _ _ _ args => exprListHasUntrackableWrites args
526+
| Expr.forkIfAtLeast _ thenExpr elseExpr =>
527+
exprHasUntrackableWrites thenExpr || exprHasUntrackableWrites elseExpr
522528
| Expr.lt a b | Expr.gt a b | Expr.slt a b | Expr.sgt a b | Expr.eq a b
523529
| Expr.ge a b | Expr.le a b | Expr.signextend a b
524530
| Expr.logicalAnd a b | Expr.logicalOr a b
@@ -671,6 +677,8 @@ def exprContainsExternalCall : Expr → Bool
671677
| Expr.byte a b =>
672678
exprContainsExternalCall a || exprContainsExternalCall b
673679
| Expr.intrinsic _ _ _ args => exprListContainsExternalCall args
680+
| Expr.forkIfAtLeast _ thenExpr elseExpr =>
681+
exprContainsExternalCall thenExpr || exprContainsExternalCall elseExpr
674682
| Expr.lt a b | Expr.gt a b | Expr.slt a b | Expr.sgt a b | Expr.eq a b
675683
| Expr.ge a b | Expr.le a b | Expr.signextend a b
676684
| Expr.logicalAnd a b | Expr.logicalOr a b
@@ -753,6 +761,8 @@ def exprMayContainExternalCall : Expr → Bool
753761
| Expr.byte a b =>
754762
exprMayContainExternalCall a || exprMayContainExternalCall b
755763
| Expr.intrinsic _ _ _ args => exprListMayContainExternalCall args
764+
| Expr.forkIfAtLeast _ thenExpr elseExpr =>
765+
exprMayContainExternalCall thenExpr || exprMayContainExternalCall elseExpr
756766
| Expr.lt a b | Expr.gt a b | Expr.slt a b | Expr.sgt a b | Expr.eq a b
757767
| Expr.ge a b | Expr.le a b | Expr.signextend a b
758768
| Expr.logicalAnd a b | Expr.logicalOr a b
@@ -1065,6 +1075,9 @@ def exprWritesStateWithFunctionEffects
10651075
exprWritesStateWithFunctionEffects effects a ||
10661076
exprWritesStateWithFunctionEffects effects b
10671077
| Expr.intrinsic _ _ _ args => exprListWritesStateWithFunctionEffects effects args
1078+
| Expr.forkIfAtLeast _ thenExpr elseExpr =>
1079+
exprWritesStateWithFunctionEffects effects thenExpr ||
1080+
exprWritesStateWithFunctionEffects effects elseExpr
10681081
| Expr.mulDivDown a b c | Expr.mulDivUp a b c
10691082
| Expr.mulDiv512Down a b c | Expr.mulDiv512Up a b c =>
10701083
exprWritesStateWithFunctionEffects effects a ||
@@ -1312,6 +1325,9 @@ def exprReadsStateOrEnvWithFunctionEffects
13121325
exprReadsStateOrEnvWithFunctionEffects effects a ||
13131326
exprReadsStateOrEnvWithFunctionEffects effects b
13141327
| Expr.intrinsic _ _ _ args => exprListReadsStateOrEnvWithFunctionEffects effects args
1328+
| Expr.forkIfAtLeast _ thenExpr elseExpr =>
1329+
exprReadsStateOrEnvWithFunctionEffects effects thenExpr ||
1330+
exprReadsStateOrEnvWithFunctionEffects effects elseExpr
13151331
| Expr.mulDivDown a b c | Expr.mulDivUp a b c
13161332
| Expr.mulDiv512Down a b c | Expr.mulDiv512Up a b c =>
13171333
exprReadsStateOrEnvWithFunctionEffects effects a ||
@@ -1633,6 +1649,8 @@ def exprContainsAdtConstruct : Expr → Bool
16331649
| Expr.byte a b =>
16341650
exprContainsAdtConstruct a || exprContainsAdtConstruct b
16351651
| Expr.intrinsic _ _ _ args => exprListContainsAdtConstruct args
1652+
| Expr.forkIfAtLeast _ thenExpr elseExpr =>
1653+
exprContainsAdtConstruct thenExpr || exprContainsAdtConstruct elseExpr
16361654
| Expr.lt a b | Expr.gt a b | Expr.slt a b | Expr.sgt a b | Expr.eq a b
16371655
| Expr.ge a b | Expr.le a b | Expr.signextend a b
16381656
| Expr.logicalAnd a b | Expr.logicalOr a b

Compiler/CompilationModel/ValidationCalls.lean

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,9 @@ def validateInternalCallShapesInExpr
242242
validateInternalCallShapesInExpr functions callerName b
243243
| Expr.intrinsic _ _ _ args =>
244244
validateInternalCallShapesInExprList functions callerName args
245+
| Expr.forkIfAtLeast _ thenExpr elseExpr => do
246+
validateInternalCallShapesInExpr functions callerName thenExpr
247+
validateInternalCallShapesInExpr functions callerName elseExpr
245248
| Expr.mulDivDown a b c | Expr.mulDivUp a b c
246249
| Expr.mulDiv512Down a b c | Expr.mulDiv512Up a b c => do
247250
validateInternalCallShapesInExpr functions callerName a
@@ -517,6 +520,9 @@ def validateExternalCallTargetsInExpr
517520
validateExternalCallTargetsInExpr externals context b
518521
| Expr.intrinsic _ _ _ args =>
519522
validateExternalCallTargetsInExprList externals context args
523+
| Expr.forkIfAtLeast _ thenExpr elseExpr => do
524+
validateExternalCallTargetsInExpr externals context thenExpr
525+
validateExternalCallTargetsInExpr externals context elseExpr
520526
| Expr.mulDivDown a b c | Expr.mulDivUp a b c
521527
| Expr.mulDiv512Down a b c | Expr.mulDiv512Up a b c => do
522528
validateExternalCallTargetsInExpr externals context a

Compiler/CompilationModel/ValidationHelpers.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ def collectExprNames : Expr → List String
112112
| Expr.byte index value => collectExprNames index ++ collectExprNames value
113113
| Expr.signextend byteIndex value => collectExprNames byteIndex ++ collectExprNames value
114114
| Expr.intrinsic _name _ _ args => collectExprListNames args
115+
| Expr.forkIfAtLeast _ thenExpr elseExpr => collectExprNames thenExpr ++ collectExprNames elseExpr
115116
| Expr.eq a b => collectExprNames a ++ collectExprNames b
116117
| Expr.ge a b => collectExprNames a ++ collectExprNames b
117118
| Expr.gt a b => collectExprNames a ++ collectExprNames b

Compiler/CompilationModel/ValidationInterop.lean

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ def validateInteropExpr (context : String) : Expr → Except String Unit
105105
validateInteropExpr context b
106106
| Expr.intrinsic _ _ _ args =>
107107
validateInteropExprList context args
108+
| Expr.forkIfAtLeast _ thenExpr elseExpr => do
109+
validateInteropExpr context thenExpr
110+
validateInteropExpr context elseExpr
108111
| Expr.mulDivDown a b c | Expr.mulDivUp a b c
109112
| Expr.mulDiv512Down a b c | Expr.mulDiv512Up a b c => do
110113
validateInteropExpr context a

0 commit comments

Comments
 (0)