phillipstanleymarbell / Noisy-lang-compiler

Noisy language compiler
MIT License
17 stars 1 forks source link

Bug with `asuint_32` #641

Open PeiMu opened 1 year ago

PeiMu commented 1 year ago

When we analyze the function asuint in the test case sincosf.c, it always gives the result range as [0, 0]. The IR is:

; Function Attrs: noinline nounwind uwtable
define internal i32 @asuint(double %0) #0 !dbg !254 {
  %2 = alloca %union.anon.0, align 4
  call void @llvm.dbg.value(metadata double %0, metadata !255, metadata !DIExpression()), !dbg !256
  call void @llvm.dbg.declare(metadata %union.anon.0* %2, metadata !257, metadata !DIExpression()), !dbg !262
  %3 = bitcast %union.anon.0* %2 to float*, !dbg !263
  %4 = fptrunc double %0 to float, !dbg !264
  store float %4, float* %3, align 4, !dbg !263
  %5 = bitcast %union.anon.0* %2 to i32*, !dbg !265
  %6 = load i32, i32* %5, align 4, !dbg !265
  ret i32 %6, !dbg !266
}

This means the range of %5 is completely wrong.

In our current code, we use lowRange = static_cast<double>(*reinterpret_cast<int32_t *>(&originLow)); to get the value of %5. I also try with a stand-alone cpp code to test it, and the result is correct.

uint32_t asuint_32(double f) {
  union {
    float f;
    uint32_t i;
  } u = {static_cast<float>(f)};
  return u.i;
}

int32_t long_word_32 = *reinterpret_cast<int32_t*>(&value);
printf("long_word_32 static cast: %lu\n", static_cast<double>(long_word_32));