summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/asm2wasm.cpp23
-rw-r--r--test/emcc_O2_hello_world.wast2
-rw-r--r--test/emcc_hello_world.wast2
-rw-r--r--test/unit.asm.js8
-rw-r--r--test/unit.wast7
5 files changed, 24 insertions, 18 deletions
diff --git a/src/asm2wasm.cpp b/src/asm2wasm.cpp
index 3e109e010..e20bbe5a1 100644
--- a/src/asm2wasm.cpp
+++ b/src/asm2wasm.cpp
@@ -443,19 +443,6 @@ private:
}
}
- // function table null thunks are always named b\d+
- bool isNullThunk(IString name) {
- const char *str = name.str;
- if (*str != 'b') return false;
- str++;
- while (1) {
- if (*str < '0' || *str > '9') return false;
- str++;
- if (*str == 0) break;
- }
- return true;
- }
-
wasm::Arena tempAllocator;
std::map<unsigned, Ref> tempNums;
@@ -586,17 +573,21 @@ void Asm2WasmModule::processAsm(Ref ast) {
views.emplace(name, View(bytes, integer, signed_));
} else if (value[0] == ARRAY) {
// function table. we "merge" them, so e.g. [foo, b1] , [b2, bar] => [foo, bar] , assuming b* are the aborting thunks
+ // when minified, we can't tell from the name b\d+, but null thunks appear multiple times in a table; others never do
// TODO: we can drop some b*s at the end of the table
Ref contents = value[1];
+ std::map<IString, unsigned> counts; // name -> how many times seen
+ for (unsigned k = 0; k < contents->size(); k++) {
+ IString curr = contents[k][1]->getIString();
+ counts[curr]++;
+ }
for (unsigned k = 0; k < contents->size(); k++) {
IString curr = contents[k][1]->getIString();
if (table.vars.size() <= k) {
table.vars.push_back(curr);
} else {
- if (isNullThunk(table.vars[k])) {
+ if (counts[curr] == 1) { // if just one appearance, not a null thunk
table.vars[k] = curr;
- } else {
- assert(isNullThunk(curr) && "cannot have aliasing function pointers");
}
}
}
diff --git a/test/emcc_O2_hello_world.wast b/test/emcc_O2_hello_world.wast
index 20b476bb3..1b3ff0336 100644
--- a/test/emcc_O2_hello_world.wast
+++ b/test/emcc_O2_hello_world.wast
@@ -21,7 +21,7 @@
(export "dynCall_ii" $dynCall_ii)
(export "dynCall_iiii" $dynCall_iiii)
(export "dynCall_vi" $dynCall_vi)
- (table $b2 $___stdio_close $___stdout_write $___stdio_seek $_cleanup_418 $___stdio_write $b2 $b2)
+ (table $b0 $___stdio_close $___stdout_write $___stdio_seek $_cleanup_418 $___stdio_write $b1 $b1)
(func $_malloc (param $i1 i32) (result i32)
(local $i2 i32)
(local $i3 i32)
diff --git a/test/emcc_hello_world.wast b/test/emcc_hello_world.wast
index 2705da73e..21394f768 100644
--- a/test/emcc_hello_world.wast
+++ b/test/emcc_hello_world.wast
@@ -25,7 +25,7 @@
(export "dynCall_ii" $dynCall_ii)
(export "dynCall_iiii" $dynCall_iiii)
(export "dynCall_vi" $dynCall_vi)
- (table $b2 $___stdio_close $___stdout_write $___stdio_seek $___stdio_write $_cleanup $b2 $b2)
+ (table $b0 $___stdio_close $___stdout_write $___stdio_seek $___stdio_write $_cleanup $b1 $b1)
(func $stackAlloc (param $size i32) (result i32)
(local $ret i32)
(block $topmost
diff --git a/test/unit.asm.js b/test/unit.asm.js
index 922923ea3..f737a3ddc 100644
--- a/test/unit.asm.js
+++ b/test/unit.asm.js
@@ -14,6 +14,14 @@ function () {
temp = t + u + (-u) + (-t);
}
+ function z() {
+ }
+ function w() {
+ }
+
+ var FUNCTION_TABLE_a = [ z, big_negative, z, z ];
+ var FUNCTION_TABLE_b = [ w, w, importedDoubles, w ];
+
return { big_negative: big_negative };
}
diff --git a/test/unit.wast b/test/unit.wast
index 5fecdcad3..346286b18 100644
--- a/test/unit.wast
+++ b/test/unit.wast
@@ -1,6 +1,7 @@
(module
(memory 16777216)
(export "big_negative" $big_negative)
+ (table $z $big_negative $importedDoubles $z)
(func $big_negative
(local $temp f64)
(block
@@ -44,4 +45,10 @@
)
)
)
+ (func $z
+ (nop)
+ )
+ (func $w
+ (nop)
+ )
)