-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TIP-907: Track overflow in melvm #63
Comments
This is certainly an important functionality that MelVM is curently missing. However, an interesting, non-trivial question is how higher-level languages (Mil and Melodeon, in particular) can expose this functionality. Strategy 1: directly expose an "intrinsic" functionThe easiest way would be just to have a special expression that compiles to the
We could use it in contexts like this:
The problem here is that the presence of This is especially bad because Melodeon is otherwise a purely functional language. Being purely functional means that the compiler (in this case, really the Mil compiler) is free to do many sorts of rearrangements. For example, in general
and
are equivalent. Strictly speaking, the language doesn't even have an evaluation order that says that f() must be evaluated before g() --- for all we know everything could be lazy-evaluated, and we cannot observe the difference. Except if Thus, both the Melodeon and the Mil compiler must globally keep track of any function that calls (let (x some-expr)
(... x ....)) where (... some-expr ...) to save on loads and stores. But an overflow check breaks this: (let (x (+ foo bar))
(if (__overflow) x 0)) => ;; oof
(if (__overflow) (+ foo bar) 0) This strategy thus will impose significant complications on designing compiler optimizations and internal representations. Strategy 2: "Checked" blocksIn this strategy, the TIP will be modified to make the overflow bit "sticky", and a In particular, Mil exposes an expression
This can directly be exposed in Melodeon safely: def saturating_add(x: Nat, y: Nat) =
checked
x + y
catch ~0 The implementation overhead of this is much lower than strategy 1. It also makes it possible to catch overflow after a series of arithmetic operations, to save on constant checking in the middle. The costs:
Strategy 3: checked arithmetic in MilInstead of a general checked-block solution, we can introduce simply operations like The advantage of this over 2 is that we do not need to change the TIP, and everything is quite "functional" and nice. The disadvantage is a proliferation of Mil forms ( |
I chose an auto overflow flip originally for ease of use but am actually a fan of the performance benefits of a sticky flag. We would need the second opcode I agree the functional semantics don't fit so well with the stack machine model of melvm. But I don't see much of an efficient alternative. |
Summary
Proposing the addition of a sticky overflow flag to melvm, and
Oflo
/Cloflo
opcodes which push the flag's value to the stack and clears the flag to false respectively. This will allow programs to check if an arithmetic operation overflowed.Motivation
Right now overflow on arithmetic is not explicitly reported in melvm. While it can be determined in some cases by the remaining value of an arithmetic expression, an overflow flow flag can help in the case that a sequence of arithmetic is done concluding with a final check.
Proposed changes
Add an overflow boolean to melvm's execution state. When an arithmetic operation (+,-,*,^) overflows it sets the overflow flag to true. When an op does not overflow it sets the flag to false. So in
(x+y)+z
the first addition might overflow but if the second does not then the overflow flag will be false after this expression. Therefore a user should check overflow directly after an operation where needed.The
Oflo
opcode simply pushes the value in the overflow flag to the stack.** edit: considering changes discussed below
The text was updated successfully, but these errors were encountered: