tomlokhorst / language-cil

Manipulating Common Intermediate Language AST in Haskell
Other
20 stars 8 forks source link

Arithmetic overflow detection #4

Closed dmcclean closed 13 years ago

dmcclean commented 13 years ago

Arithmetic operations which can overflow have flavors which detect overflows and throw exceptions.

Examples: add (no check) add.ovf (signed overflow check) add.ovf.un (unsigned overflow check)

Stylistically, what's the best way to represent this in the Build module? Making three functions for each such instruction family? Or

data OverflowCheck = SilentOverflow | SignedOverflow | UnsignedOverflow

and changing, e.g., add from:

add :: MethodDecl

to:

add :: OverflowCheck -> MethodDecl

Here are the relevant instructions: add (3 flavors), a whole bunch of conversion instructions which aren't implemented yet, mul (3 flavors), sub (3 flavors)

Vaguely related things to consider:

div and rem (there's an unsigned flavor of division, unrelated to overflow concerns)

neg (strangely only one silent flavor, you need to use sub.ovf to detect the overflow from negating the most negative integer of a certain size),

There are also signed and unsigned flavors of all the comparison and compare-and-branch instructions, but it's weird because the unsigned comparison/compare-and-branch instructions are overloaded to also perform a "compare and branch if less than, or if unordered" instruction on floating-point values, so it would seem that we would definitely want separate building functions there.

dmcclean commented 13 years ago

I was thinking we could make a Build method neg.ovf that did the ldc.i4.0 and then sub.ovf. Unfortunately we can't really, because that ends up doing the subtraction in the wrong order.

tomlokhorst commented 13 years ago

I think its best to add three different functions in the Build module, for each of the three opcodes (add, add.ovf, and add.ovf.un).

I've tried to make code (that uses Build functions) look as much as CIL as possible, i.e. a DSL. I'd like to keep add :: ModuleDecl as the simple, default, case.

The only place where the opcode doesn't directly map to a single build function is where the function can locally chose the optimal implementation. E.g. ldc_i4 :: Integer -> MethodDecl can, based on its argument, choose the best opcode.

dmcclean commented 13 years ago

Well, I'm new to Git and I'm having issues with it. I can't figure out how to merge your changes back into my fork, and until I can figure it out the changes I made to fix this issue are stuck in my fork.

tomlokhorst commented 13 years ago

I'm also still learning new stuff about git. I think this is the way to merge my changes back into your fork:

$ git remote add upstream git://github.com/tomlokhorst/language-cil.git
$ git pull upstream master

The merge results in a whole bunch of conflicts between your work and mine, which will have to be resolved manually.

However, you can instead choose to let it always pick my version:

$ git pull -s recursive -X theirs upstream master

This will successfully do the merge and only introduces a single error (the import of the Prelude doesn't hide div). Once that error is fixed, I think you branch is in a good state again.

tomlokhorst commented 13 years ago

This has been merged https://github.com/tomlokhorst/language-cil/commit/eeb6c10e1e944eedeaef53135c94d4952d5a88cf