ZEAM Development Log v.0.4.3 Type Polyphase and Type Safe NIF Detects Overflow

Introduction

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"

How to detect integer overflow

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". ..

Execution result

  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/ image.png

Recommended Posts