summaryrefslogtreecommitdiff
path: root/src/wasm-interpreter.h
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2015-11-11 11:28:48 -0800
committerAlon Zakai <alonzakai@gmail.com>2015-11-11 11:28:48 -0800
commitbe42e377272dbdee8c592706bbce8753aa6539b6 (patch)
treeff953204ab55aa2b544557ca1edbeb216e25645f /src/wasm-interpreter.h
parente21c014dfd50a2a0cd89b6988ccf74a48d12ad3f (diff)
downloadbinaryen-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.h82
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() {