I'm Susumu Yamazaki, also known as ZACKY.
Now that we know how to detect integer addition, subtraction, and multiplication overflows, let's report.
Click here for "ZEAM Development Log Table of Contents"
Use the function __builtin _ * _ overflow
.
If it is a signed 64-bit integer, it will be __builtin_saddl_overflow
.
Click here for documentation.
Clang Language Extensions — Clang 4 documentation
The C language code looks like this.
static
ERL_NIF_TERM asm_1_nif_ii(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
{
long a, b;
if(__builtin_expect((enif_get_int64(env, argv[0], &a) == 0), 0)) {
goto error;
}
if(__builtin_expect((enif_get_int64(env, argv[1], &b) == 0), 0)) {
goto error;
}
long result;
if(__builtin_expect(__builtin_saddl_overflow(a, b, &result), 0)) {
goto error2;
}
return enif_make_int64(env, result);
error:
return arithmetic_error;
error2:
return error_atom;
}
If you use __built_in_expect
, it will be optimized considering branch prediction. For details, refer to "ZEAM Development Log v.0.4.2 Optimized Type Polymorphic and Type Safe NIF Code from the Viewpoint of Branch Prediction". ..
def main do
IO.puts asm_1(1, 2)
IO.puts asm_1(1.0, 2)
IO.puts asm_1(1, 2.0)
IO.puts asm_1(1.0, 2.0)
IO.puts asm_1(@max_int, 0)
IO.puts asm_1(@min_int, 0)
try do
IO.puts asm_1(@max_int, 1)
rescue
error in [ArithmeticError] -> IO.puts "it needs BigNum!: #{Exception.message(error)}"
end
try do
IO.puts asm_1(@max_int + 1, 1)
rescue
error in [ArithmeticError] -> IO.puts "it needs BigNum!: #{Exception.message(error)}"
end
end
When I try to run it, I get an exception due to the overflow.
$ mix run -e "NifLlvm.main"
make: `priv/libnifllvm.so' is up to date.
3
3.0
3.0
3.0
9223372036854775807
-9223372036854775808
it needs BigNum!: bad argument in arithmetic expression
it needs BigNum!: bad argument in arithmetic expression
Looking at the assembly code, the overflow jump instruction is generated as intended.
##DEBUG_VALUE: asm_1_nif_ii:a <- %rsi
.loc 3 26 22 is_stmt 0 ## native/lib.c:26:22
addq -24(%rbp), %rsi
Ltmp27:
.loc 3 26 5 ## native/lib.c:26:5
jo LBB4_5
LLVM seems to code like this.
%19 = call { i64, i1 } @llvm.sadd.with.overflow.i64(i64 %17, i64 %18), !dbg !181
%20 = extractvalue { i64, i1 } %19, 1, !dbg !181
call void @llvm.dbg.value(metadata i64 %22, metadata !160, metadata !DIExpression()), !dbg !182
br i1 %20, label %26, label %21, !dbg !183, !prof !171
Click here for the GitHub repository for the entire source code
Since I had a good idea of what kind of code should be generated on the backend, next time "ZEAM development log v.0.4.4 INT64 judgment is easily judged by macro" / items / 878489ce88f380f0ae60), we will start to consider the front end. looking forward to!
: stars :: stars :: stars: Notice: Elixir Mokumokukai (remote participation OK, with introductory track) will be held on September 28th </ b>: stars :: stars :: stars:
"fukuoka.ex # 14: Elixir / Phoenix Mokumokukai-There is also an introduction" </ b> on September 28, 2018 Held on friday
Last time, we officially accepted "remote participation by Zoom" that was recruited like a guerrilla, so you can also participate from metropolitan areas and regions other than Fukuoka (If you apply, you can connpass the Zoom URL later. I will send it by email)
In addition, until now, it was only for Mokumokukai for experienced Elixir / Phoenix, but from this time, we have also added an introductory track and upgraded it so that you can ask questions to fukuoka.ex Advisors / Cast.
I, Yamazaki will also participate! I'm thinking of making something that is an extension of this article.
Click here to apply
https://fukuokaex.connpass.com/event/100659/
Recommended Posts