Closed poorna2152 closed 2 years ago
Exceptions can be handled using the try catch
in the JS file.
Considering the div3-p.bal.
panic: divide by zero
div3-p.bal:9
This contains a line number in the original bal
file relevant to the error instruction.
panic: divide by zero
In the error object in Javascript. It has two properties. The message
and the stack
.
The stack
contains details where the exception was thrown. But it is a line in the WASM
file. The line of the error output is missing in the actual output.
Range of ints representable in WASM
-9223372036854775808 - 9223372036854775807
Range of ints representable based on the test cases -9223372036854775808 - 9223372036854775807
When outside this range it is expected to throw an Error.
But in WASM
it does not throw an error for this.(Behaves in a circular way: 9223372036854775807 + 1 = -9223372036854775808). Neither does Javascript. The BigInt in JavaScript is used to represent the i64
value send to console.log
. BigInt
does not have a upperbound on the numbers it can represent
Therefore should the handling of this Exception be done on the WAT code.
if op1 > 0 && op2 > 0 && result < 0
throw "overflow"
1) Debug line info options: a) Differ this for a later subset. b) "Bake-in" the lines as part of error creation c) Use https://yurydelendik.github.io/webassembly-dwarf/ Lets go with a) for now
2) Overflow detection https://github.com/WebAssembly/design/blob/main/FutureFeatures.md#integer-overflow-detection I think we'll have to do a per-check, but your proposed per-check is wrong. Please take a look at https://www.cs.utah.edu/~regehr/papers/overflow12.pdf Clang has support for this, but produced code looks ugly https://godbolt.org/z/o9bYTM1db maybe it's best one can do? not sure.
btw ballerina ints can have the value -9223372036854775808
Following checks for overflow,
if s1 > 0 && s2 > 0
if s1 > (INT_MAX − s2)
throw overflow
else if s1 < 0 && s2 < 0
if s1 < (INT_MIN − s2)
throw overflow
if s1 > 0 && s2 < 0
if s1 > (INT_MAX + s2)
throw overflow
else if s1 < 0 && s2 > 0
if s1 < (INT_MIN + s2)
throw overflow
if s1 > 0 && s2 > 0
if s2 > INT_MAX/s1
throw overflow
else if s1 < 0 && s2 < 0
if s2 < INT_MAX/s1
throw overflow
else if s1 < -1 && s2 > 0
if s2 > INT_MIN/s1
throw overflow
else if s1 > 0 && s2 < 0
if s2 < INT_MIN/s1
throw overflow
if s1 == INT_MIN && s2 == -1
throw overflow
The output WAT file for the add2-p.bal.
(module
(import "console" "log" (func $println (param i64)))
(tag $overflow)
(export "main" (func $main))
(export "add" (func $add))
(func $main
(local $0 i64)
(local $1 i64)
(local $2 i32)
(block
(block
(local.set $0
(i64.const 9223372036854775807))
(local.set $1
(call $add
(local.get $0)
(i64.const 1)))
(call $println
(local.get $1))
(return ))))
(func $add (param $0 i64) (param $1 i64) (result i64)
(local $2 i64)
(local $3 i32)
(block
(block
(try
(do
(block
(if
(i32.and
(i64.gt_s
(local.get $0)
(i64.const 0))
(i64.gt_s
(local.get $1)
(i64.const 0)))
(block
(if
(i64.gt_s
(local.get $0)
(i64.sub
(i64.const 9223372036854775807)
(local.get $1)))
(block
(throw $overflow))))
(block
(if
(i32.and
(i64.lt_s
(local.get $0)
(i64.const 0))
(i64.lt_s
(local.get $1)
(i64.const 0)))
(block
(if
(i64.lt_s
(local.get $0)
(i64.sub
(i64.const -9223372036854775808)
(local.get $1)))
(block
(throw $overflow)))))))
(local.set $2
(i64.add
(local.get $0)
(local.get $1))))))
(return
(local.get $2))))))
Is this the approach expected. If so this leads to duplicate code in the generated WAT file. Should we create a function for each of the add, sub, multiply and divide operations which check for overflows and call those on arithmetic operations.
Possible methods,
WebAssembly provides
try
,catch
,catchall
,throw
,rethrow
anddelegate
instructions for handling exceptions. However the exceptions which can be handled by thecatch
andcatchall
blocks are the exceptions which are explicitly thrown using thethrow
instruction. In the following program if the second parameter is 0 it is expected to throw a division by zero error. But this error is not caught by thecatchall
block. It is caught by the runtime.Following works because we are explicitly throwing the error when second parameter is zero.