summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2019-04-18 17:05:30 -0700
committerGitHub <noreply@github.com>2019-04-18 17:05:30 -0700
commita4baf2152d11c28964025759d2702fe7c48d321e (patch)
treea59d35b75c52029d870733553df0c3bbed3d63c7
parent5becae69e29c876f3ba46d6746764e409bd7fd9b (diff)
downloadbinaryen-a4baf2152d11c28964025759d2702fe7c48d321e.tar.gz
binaryen-a4baf2152d11c28964025759d2702fe7c48d321e.tar.bz2
binaryen-a4baf2152d11c28964025759d2702fe7c48d321e.zip
wasm2js: handle unreachable select and global.set (#2029)
-rw-r--r--src/passes/I64ToI32Lowering.cpp21
-rw-r--r--test/passes/flatten_i64-to-i32-lowering.txt102
-rw-r--r--test/passes/flatten_i64-to-i32-lowering.wast34
-rw-r--r--test/wasm2js/br.2asm.js4
-rw-r--r--test/wasm2js/br_table.2asm.js4
-rw-r--r--test/wasm2js/br_table_temp.2asm.js4
-rw-r--r--test/wasm2js/i64-select.2asm.js12
-rw-r--r--test/wasm2js/i64-select.wast21
-rw-r--r--test/wasm2js/select.2asm.js4
9 files changed, 195 insertions, 11 deletions
diff --git a/src/passes/I64ToI32Lowering.cpp b/src/passes/I64ToI32Lowering.cpp
index a1686d27d..33bb7229e 100644
--- a/src/passes/I64ToI32Lowering.cpp
+++ b/src/passes/I64ToI32Lowering.cpp
@@ -28,6 +28,7 @@
#include "support/name.h"
#include "wasm-builder.h"
#include "ir/flat.h"
+#include "ir/iteration.h"
#include "ir/memory-utils.h"
#include "ir/module-utils.h"
#include "ir/names.h"
@@ -464,6 +465,7 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
}
void visitSetGlobal(SetGlobal* curr) {
+ if (handleUnreachable(curr)) return;
if (!originallyI64Globals.count(curr->name)) return;
TempVar highBits = fetchOutParam(curr->value);
auto* setHigh = builder->makeSetGlobal(
@@ -1578,6 +1580,7 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
}
void visitSelect(Select* curr) {
+ if (handleUnreachable(curr)) return;
if (!hasOutParam(curr->ifTrue)) {
assert(!hasOutParam(curr->ifFalse));
return;
@@ -1669,6 +1672,24 @@ private:
highBitVars.erase(e);
return ret;
}
+
+ // If e.g. a select is unreachable, then one arm may have an out param
+ // but not the other. In this case dce should really have been run
+ // before; handle it in a simple way here.
+ bool handleUnreachable(Expression* curr) {
+ if (curr->type != unreachable) return false;
+ std::vector<Expression*> children;
+ for (auto* child : ChildIterator(curr)) {
+ if (isConcreteType(child->type)) {
+ child = builder->makeDrop(child);
+ }
+ children.push_back(child);
+ }
+ auto* block = builder->makeBlock(children);
+ assert(block->type == unreachable);
+ replaceCurrent(block);
+ return true;
+ }
};
Pass *createI64ToI32LoweringPass() {
diff --git a/test/passes/flatten_i64-to-i32-lowering.txt b/test/passes/flatten_i64-to-i32-lowering.txt
index 6863be7e8..7d9ff6835 100644
--- a/test/passes/flatten_i64-to-i32-lowering.txt
+++ b/test/passes/flatten_i64-to-i32-lowering.txt
@@ -78,6 +78,69 @@
)
)
)
+ (func $unreachable-select-i64 (; 2 ;) (type $FUNCSIG$j) (result i32)
+ (local $i64toi32_i32$0 i32)
+ (unreachable)
+ (block
+ (drop
+ (block (result i32)
+ (local.set $i64toi32_i32$0
+ (i32.const 0)
+ )
+ (i32.const 1)
+ )
+ )
+ (unreachable)
+ (drop
+ (i32.const 2)
+ )
+ )
+ (unreachable)
+ )
+ (func $unreachable-select-i64-b (; 3 ;) (type $FUNCSIG$j) (result i32)
+ (local $i64toi32_i32$0 i32)
+ (unreachable)
+ (block
+ (unreachable)
+ (drop
+ (block (result i32)
+ (local.set $i64toi32_i32$0
+ (i32.const 0)
+ )
+ (i32.const 3)
+ )
+ )
+ (drop
+ (i32.const 4)
+ )
+ )
+ (unreachable)
+ )
+ (func $unreachable-select-i64-c (; 4 ;) (type $FUNCSIG$j) (result i32)
+ (local $i64toi32_i32$0 i32)
+ (local $i64toi32_i32$1 i32)
+ (unreachable)
+ (block
+ (drop
+ (block (result i32)
+ (local.set $i64toi32_i32$0
+ (i32.const 0)
+ )
+ (i32.const 5)
+ )
+ )
+ (drop
+ (block (result i32)
+ (local.set $i64toi32_i32$1
+ (i32.const 0)
+ )
+ (i32.const 6)
+ )
+ )
+ (unreachable)
+ )
+ (unreachable)
+ )
)
(module
(type $0 (func (param i32 i32)))
@@ -88,6 +151,7 @@
(global $g$hi (mut i32) (global.get $f$hi))
(global $i64toi32_i32$HIGH_BITS (mut i32) (i32.const 0))
(export "exp" (func $1))
+ (export "unreach" (func $2))
(func $call (; 0 ;) (type $0) (param $0 i32) (param $0$hi i32)
(nop)
)
@@ -136,4 +200,42 @@
)
(nop)
)
+ (func $2 (; 2 ;) (type $1)
+ (local $0 i32)
+ (local $0$hi i32)
+ (local $1 i32)
+ (local $1$hi i32)
+ (local $i64toi32_i32$0 i32)
+ (block $label$1
+ (unreachable)
+ (unreachable)
+ )
+ (block
+ (local.set $1
+ (block (result i32)
+ (local.set $i64toi32_i32$0
+ (local.get $0$hi)
+ )
+ (local.get $0)
+ )
+ )
+ (local.set $1$hi
+ (local.get $i64toi32_i32$0)
+ )
+ )
+ (block
+ (global.set $f
+ (block (result i32)
+ (local.set $i64toi32_i32$0
+ (local.get $1$hi)
+ )
+ (local.get $1)
+ )
+ )
+ (global.set $f$hi
+ (local.get $i64toi32_i32$0)
+ )
+ )
+ (nop)
+ )
)
diff --git a/test/passes/flatten_i64-to-i32-lowering.wast b/test/passes/flatten_i64-to-i32-lowering.wast
index def4f3a34..29323d376 100644
--- a/test/passes/flatten_i64-to-i32-lowering.wast
+++ b/test/passes/flatten_i64-to-i32-lowering.wast
@@ -1,8 +1,29 @@
(module
- (import "env" "func" (func $import (result i64)))
- (func $defined (result i64)
- (i64.add (i64.const 1) (i64.const 2))
+ (import "env" "func" (func $import (result i64)))
+ (func $defined (result i64)
+ (i64.add (i64.const 1) (i64.const 2))
+ )
+ (func $unreachable-select-i64 (result i64)
+ (select
+ (i64.const 1)
+ (unreachable)
+ (i32.const 2)
+ )
+ )
+ (func $unreachable-select-i64-b (result i64)
+ (select
+ (unreachable)
+ (i64.const 3)
+ (i32.const 4)
+ )
+ )
+ (func $unreachable-select-i64-c (result i64)
+ (select
+ (i64.const 5)
+ (i64.const 6)
+ (unreachable)
)
+ )
)
(module
(global $f (mut i64) (i64.const 0x12345678ABCDEFAF))
@@ -12,4 +33,11 @@
(call $call (global.get $f))
(global.set $f (i64.const 0x1122334455667788))
)
+ (func "unreach"
+ (global.set $f
+ (block $label$1 (result i64)
+ (unreachable)
+ )
+ )
+ )
)
diff --git a/test/wasm2js/br.2asm.js b/test/wasm2js/br.2asm.js
index c30b7d2de..01f5d3941 100644
--- a/test/wasm2js/br.2asm.js
+++ b/test/wasm2js/br.2asm.js
@@ -262,7 +262,7 @@ function asmFunc(global, env, buffer) {
function $27($0, $1_1) {
$0 = $0 | 0;
$1_1 = $1_1 | 0;
- var $2_1 = 0, $3_1 = 0, $4_1 = 0, $5_1 = 0, $6_1 = 0;
+ var $2_1 = 0, $3_1 = 0, $4_1 = 0;
block : {
$2_1 = 5;
break block;
@@ -273,7 +273,7 @@ function asmFunc(global, env, buffer) {
function $28($0, $1_1) {
$0 = $0 | 0;
$1_1 = $1_1 | 0;
- var $2_1 = 0, $3_1 = 0, $4_1 = 0, $5_1 = 0, $6_1 = 0;
+ var $2_1 = 0, $3_1 = 0, $4_1 = 0;
block : {
$2_1 = $0;
$3_1 = 6;
diff --git a/test/wasm2js/br_table.2asm.js b/test/wasm2js/br_table.2asm.js
index 2a33ce688..7ff5e4c4d 100644
--- a/test/wasm2js/br_table.2asm.js
+++ b/test/wasm2js/br_table.2asm.js
@@ -49727,7 +49727,7 @@ function asmFunc(global, env, buffer) {
function $34($0, $1_1) {
$0 = $0 | 0;
$1_1 = $1_1 | 0;
- var $3_1 = 0, $4_1 = 0, $5_1 = 0, $6_1 = 0, $7_1 = 0;
+ var $3_1 = 0, $4_1 = 0, $5_1 = 0;
block : {
$3_1 = 5;
switch (0 | 0) {
@@ -49741,7 +49741,7 @@ function asmFunc(global, env, buffer) {
function $35($0, $1_1) {
$0 = $0 | 0;
$1_1 = $1_1 | 0;
- var $2_1 = 0, $4_1 = 0, $5_1 = 0, $6_1 = 0, $7_1 = 0;
+ var $2_1 = 0, $4_1 = 0, $5_1 = 0;
block : {
$2_1 = $0;
$4_1 = 6;
diff --git a/test/wasm2js/br_table_temp.2asm.js b/test/wasm2js/br_table_temp.2asm.js
index d12bfb2cb..a38640d64 100644
--- a/test/wasm2js/br_table_temp.2asm.js
+++ b/test/wasm2js/br_table_temp.2asm.js
@@ -49725,7 +49725,7 @@ function asmFunc(global, env, buffer) {
function $34($0, $1_1) {
$0 = $0 | 0;
$1_1 = $1_1 | 0;
- var $3_1 = 0, $4_1 = 0, $5_1 = 0, $6_1 = 0, $7_1 = 0;
+ var $3_1 = 0, $4_1 = 0, $5_1 = 0;
block : {
$3_1 = 5;
switch (0 | 0) {
@@ -49739,7 +49739,7 @@ function asmFunc(global, env, buffer) {
function $35($0, $1_1) {
$0 = $0 | 0;
$1_1 = $1_1 | 0;
- var $2_1 = 0, $4_1 = 0, $5_1 = 0, $6_1 = 0, $7_1 = 0;
+ var $2_1 = 0, $4_1 = 0, $5_1 = 0;
block : {
$2_1 = $0;
$4_1 = 6;
diff --git a/test/wasm2js/i64-select.2asm.js b/test/wasm2js/i64-select.2asm.js
index 414005b40..dc6889683 100644
--- a/test/wasm2js/i64-select.2asm.js
+++ b/test/wasm2js/i64-select.2asm.js
@@ -42,6 +42,18 @@ function asmFunc(global, env, buffer) {
return i64toi32_i32$3 | 0;
}
+ function unreachable_select_i64() {
+ return abort() | 0;
+ }
+
+ function unreachable_select_i64_b() {
+ return abort() | 0;
+ }
+
+ function unreachable_select_i64_c() {
+ return abort() | 0;
+ }
+
var FUNCTION_TABLE = [];
return {
diff --git a/test/wasm2js/i64-select.wast b/test/wasm2js/i64-select.wast
index e5f3a6bab..1fc356c88 100644
--- a/test/wasm2js/i64-select.wast
+++ b/test/wasm2js/i64-select.wast
@@ -20,4 +20,25 @@
)
)
)
+ (func $unreachable-select-i64 (result i64)
+ (select
+ (i64.const 1)
+ (unreachable)
+ (i32.const 268435456)
+ )
+ )
+ (func $unreachable-select-i64-b (result i64)
+ (select
+ (unreachable)
+ (i64.const 1)
+ (i32.const 268435456)
+ )
+ )
+ (func $unreachable-select-i64-c (result i64)
+ (select
+ (i64.const 1)
+ (i64.const 1)
+ (unreachable)
+ )
+ )
)
diff --git a/test/wasm2js/select.2asm.js b/test/wasm2js/select.2asm.js
index 1deedbbfd..893d6db56 100644
--- a/test/wasm2js/select.2asm.js
+++ b/test/wasm2js/select.2asm.js
@@ -65,13 +65,13 @@ function asmFunc(global, env, buffer) {
function $4(cond) {
cond = cond | 0;
- var $1_1 = 0, $2_1 = 0;
+ var $1_1 = 0;
return abort() | 0;
}
function $5(cond) {
cond = cond | 0;
- var $1_1 = 0, $2_1 = 0;
+ var $1_1 = 0;
return abort() | 0;
}