summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2015-11-17 21:26:11 -0800
committerAlon Zakai <alonzakai@gmail.com>2015-11-17 21:26:11 -0800
commitea0015403b3695d873a2c7eabc6fcdf0641b8e2e (patch)
treed0ab35da49e6ff1e47ceb730e86068dc7a555746
parent65db7e5e8f3994a7d4ca1b4e01f87eef13c7c87b (diff)
downloadbinaryen-ea0015403b3695d873a2c7eabc6fcdf0641b8e2e.tar.gz
binaryen-ea0015403b3695d873a2c7eabc6fcdf0641b8e2e.tar.bz2
binaryen-ea0015403b3695d873a2c7eabc6fcdf0641b8e2e.zip
fround improvements
-rw-r--r--src/asm2wasm.h35
-rw-r--r--test/unit.asm.js11
-rw-r--r--test/unit.wast14
3 files changed, 58 insertions, 2 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h
index 08f4e4141..3d430d712 100644
--- a/src/asm2wasm.h
+++ b/src/asm2wasm.h
@@ -334,10 +334,13 @@ private:
std::map<unsigned, Ref> tempNums;
- Literal getLiteral(Ref ast) {
+ Literal checkLiteral(Ref ast) {
if (ast[0] == NUM) {
return Literal((int32_t)ast[1]->getInteger());
} else if (ast[0] == UNARY_PREFIX) {
+ if (ast[1] == PLUS && ast[2][0] == NUM) {
+ return Literal((double)ast[2][1]->getNumber());
+ }
if (ast[1] == MINUS && ast[2][0] == NUM) {
double num = -ast[2][1]->getNumber();
assert(isInteger32(num));
@@ -347,7 +350,13 @@ private:
return Literal((double)-ast[2][2][1]->getNumber());
}
}
- abort();
+ return Literal();
+ }
+
+ Literal getLiteral(Ref ast) {
+ Literal ret = checkLiteral(ast);
+ if (ret.type == none) abort();
+ return ret;
}
Function* processFunction(Ref ast);
@@ -880,6 +889,28 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) {
ret->type = WasmType::i32;
return ret;
}
+ if (name == Math_fround) {
+ assert(ast[2]->size() == 1);
+ Literal lit = checkLiteral(ast[2][0]);
+ if (lit.type == i32) {
+ return allocator.alloc<Const>()->set(Literal((float)lit.geti32()));
+ } else if (lit.type == f64) {
+ return allocator.alloc<Const>()->set(Literal((float)lit.getf64()));
+ }
+ auto ret = allocator.alloc<Convert>();
+ ret->value = process(ast[2][0]);
+ if (ret->value->type == f64) {
+ ret->op = DemoteFloat64;
+ } else if (ret->value->type == i32) {
+ ret->op = ConvertSInt32;
+ } else if (ret->value->type == f32) {
+ return ret->value;
+ } else {
+ abort_on("confusing fround target", ast[2][0]);
+ }
+ ret->type = WasmType::f32;
+ return ret;
+ }
Call* ret;
if (wasm.importsMap.find(name) != wasm.importsMap.end()) {
Ref parent = astStackHelper.getParent();
diff --git a/test/unit.asm.js b/test/unit.asm.js
index 77e2c5585..5695c3059 100644
--- a/test/unit.asm.js
+++ b/test/unit.asm.js
@@ -4,6 +4,7 @@ function () {
var t = global.NaN, u = global.Infinity;
var Int = 0;
var Double = 0.0;
+ var Math_fround = global.Math.fround;
function big_negative() {
var temp = 0.0;
@@ -64,6 +65,16 @@ function () {
x = (4294967295 / 2)&-1;
return x | 0;
}
+ function fr(x) {
+ x = Math_fround(x);
+ var y = Math_fround(0), z = 0.0;
+ Math_fround(z);
+ Math_fround(y);
+ Math_fround(5);
+ Math_fround(0);
+ Math_fround(5.0);
+ Math_fround(0.0);
+ }
function z() {
}
diff --git a/test/unit.wast b/test/unit.wast
index 34dea557f..24692ba1c 100644
--- a/test/unit.wast
+++ b/test/unit.wast
@@ -233,6 +233,20 @@
(get_local $x)
)
)
+ (func $fr (param $x f32)
+ (local $y f32)
+ (local $z f64)
+ (block
+ (f32.demote/f64
+ (get_local $z)
+ )
+ (get_local $y)
+ (f32.const 5)
+ (f32.const 0)
+ (f32.const 5)
+ (f32.const 0)
+ )
+ )
(func $z
(nop)
)