diff options
author | Alon Zakai <alonzakai@gmail.com> | 2015-11-11 11:28:48 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2015-11-11 11:28:48 -0800 |
commit | be42e377272dbdee8c592706bbce8753aa6539b6 (patch) | |
tree | ff953204ab55aa2b544557ca1edbeb216e25645f /src/wasm-interpreter.h | |
parent | e21c014dfd50a2a0cd89b6988ccf74a48d12ad3f (diff) | |
download | binaryen-be42e377272dbdee8c592706bbce8753aa6539b6.tar.gz binaryen-be42e377272dbdee8c592706bbce8753aa6539b6.tar.bz2 binaryen-be42e377272dbdee8c592706bbce8753aa6539b6.zip |
more nan fixes
Diffstat (limited to 'src/wasm-interpreter.h')
-rw-r--r-- | src/wasm-interpreter.h | 82 |
1 files changed, 60 insertions, 22 deletions
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 0ec9a861f..b6f77b78d 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -362,29 +362,33 @@ private: } if (value.type == f32) { float v = value.getf32(); + float ret; switch (curr->op) { - case Neg: return Literal(-v); - case Abs: return Literal(std::abs(v)); - case Ceil: return Literal(std::ceil(v)); - case Floor: return Literal(std::floor(v)); - case Trunc: return Literal(std::trunc(v)); - case Nearest: return Literal(std::nearbyint(v)); - case Sqrt: return Literal(std::sqrt(v)); + case Neg: ret = -v; break; + case Abs: ret = std::abs(v); break; + case Ceil: ret = std::ceil(v); break; + case Floor: ret = std::floor(v); break; + case Trunc: ret = std::trunc(v); break; + case Nearest: ret = std::nearbyint(v); break; + case Sqrt: ret = std::sqrt(v); break; default: abort(); } + return Literal(fixNaN(v, ret)); } if (value.type == f64) { double v = value.getf64(); + double ret; switch (curr->op) { - case Neg: return Literal(-v); - case Abs: return Literal(std::abs(v)); - case Ceil: return Literal(std::ceil(v)); - case Floor: return Literal(std::floor(v)); - case Trunc: return Literal(std::trunc(v)); - case Nearest: return Literal(std::nearbyint(v)); - case Sqrt: return Literal(std::sqrt(v)); + case Neg: ret = -v; break; + case Abs: ret = std::abs(v); break; + case Ceil: ret = std::ceil(v); break; + case Floor: ret = std::floor(v); break; + case Trunc: ret = std::trunc(v); break; + case Nearest: ret = std::nearbyint(v); break; + case Sqrt: ret = std::sqrt(v); break; default: abort(); } + return Literal(fixNaN(v, ret)); } abort(); } @@ -487,7 +491,10 @@ private: case Sub: ret = l - r; break; case Mul: ret = l * r; break; case Div: ret = l / r; break; - case CopySign: ret = std::copysign(l, r); break; + case CopySign: { + ret = std::copysign(l, r); + return Literal(ret); + } case Min: { if (l == r && l == 0) ret = 1/l < 0 ? l : r; else ret = std::min(l, r); @@ -509,7 +516,10 @@ private: case Sub: ret = l - r; break; case Mul: ret = l * r; break; case Div: ret = l / r; break; - case CopySign: ret = std::copysign(l, r); break; + case CopySign: { + ret = std::copysign(l, r); + return Literal(ret); + } case Min: { if (l == r && l == 0) ret = 1/l < 0 ? l : r; else ret = std::min(l, r); @@ -634,7 +644,17 @@ private: case ConvertSInt64: return curr->type == f32 ? Literal(float(value.geti64())) : Literal(double(value.geti64())); case PromoteFloat32: return Literal(double(value.getf32())); case DemoteFloat64: return Literal(float(value.getf64())); - case ReinterpretInt: return curr->type == f32 ? Literal(value.reinterpretf32()) : Literal(value.reinterpretf64()); + case ReinterpretInt: { + if (curr->type == f32) { + float v = value.reinterpretf32(); + if (isnan(v)) { + return Literal(Literal(value.geti32() | 0x7fc00000).reinterpretf32()); + } + return Literal(value.reinterpretf32()); + } else { + return Literal(value.reinterpretf64()); + } + } default: abort(); } } @@ -685,22 +705,40 @@ private: return Flow(); } - float fixNaN(float l, float r, float result) { + float fixNaN(float u, float result) { + if (!isnan(result)) return result; + bool unan = isnan(u); + if (!unan) { + return Literal((int32_t)0x7fc00000).reinterpretf32(); + } + return result; + } + + double fixNaN(double u, double result) { if (!isnan(result)) return result; + bool unan = isnan(u); + if (!unan) { + return Literal((int64_t)0x7ff8000000000000LL).reinterpretf64(); + } + return result; + } + + float fixNaN(float l, float r, float result) { bool lnan = isnan(l), rnan = isnan(r); + if (!isnan(result) && !lnan && !rnan) return result; if (!lnan && !rnan) { return Literal((int32_t)0x7fc00000).reinterpretf32(); } - return result; + return Literal(Literal(lnan ? l : r).reinterpreti32() | 0xc00000).reinterpretf32(); } double fixNaN(double l, double r, double result) { - if (!isnan(result)) return result; bool lnan = isnan(l), rnan = isnan(r); + if (!isnan(result) && !lnan && !rnan) return result; if (!lnan && !rnan) { - return Literal((int64_t)0x7ff8000000000001LL).reinterpretf64(); + return Literal((int64_t)0x7ff8000000000000LL).reinterpretf64(); } - return result; + return Literal(int64_t(Literal(lnan ? l : r).reinterpreti64() | 0x8000000000000LL)).reinterpretf64(); } void trap() { |