summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xauto_update_tests.py2
-rwxr-xr-xcheck.py2
-rw-r--r--src/s2wasm-main.cpp13
-rw-r--r--src/s2wasm.h36
-rw-r--r--test/dot_s/alias.wast6
-rw-r--r--test/dot_s/basics.wast10
-rw-r--r--test/dot_s/bcp-1.wast17
-rw-r--r--test/dot_s/dyncall.c30
-rw-r--r--test/dot_s/dyncall.s97
-rw-r--r--test/dot_s/dyncall.wast84
m---------test/emscripten0
11 files changed, 280 insertions, 17 deletions
diff --git a/auto_update_tests.py b/auto_update_tests.py
index f0cba64ef..8cd2651ee 100755
--- a/auto_update_tests.py
+++ b/auto_update_tests.py
@@ -31,7 +31,7 @@ for dot_s_dir in ['dot_s', 'llvm_autogenerated']:
wasm = s.replace('.s', '.wast')
full = os.path.join('test', dot_s_dir, s)
stack_alloc = ['--allocate-stack=1024'] if dot_s_dir == 'llvm_autogenerated' else []
- cmd = [os.path.join('bin', 's2wasm'), full] + stack_alloc
+ cmd = [os.path.join('bin', 's2wasm'), full, '--emscripten-glue'] + stack_alloc
if s.startswith('start_'):
cmd.append('--start')
actual, err = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
diff --git a/check.py b/check.py
index 03e3a919a..f751f3e90 100755
--- a/check.py
+++ b/check.py
@@ -476,7 +476,7 @@ for dot_s_dir in ['dot_s', 'llvm_autogenerated']:
wasm = s.replace('.s', '.wast')
full = os.path.join('test', dot_s_dir, s)
stack_alloc = ['--allocate-stack=1024'] if dot_s_dir == 'llvm_autogenerated' else []
- cmd = [os.path.join('bin', 's2wasm'), full] + stack_alloc
+ cmd = [os.path.join('bin', 's2wasm'), full, '--emscripten-glue'] + stack_alloc
if s.startswith('start_'):
cmd.append('--start')
actual, err = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
diff --git a/src/s2wasm-main.cpp b/src/s2wasm-main.cpp
index d26ef3f1c..f22116978 100644
--- a/src/s2wasm-main.cpp
+++ b/src/s2wasm-main.cpp
@@ -29,6 +29,7 @@ using namespace wasm;
int main(int argc, const char *argv[]) {
bool ignoreUnknownSymbols = false;
+ bool generateEmscriptenGlue = false;
std::string startFunction;
Options options("s2wasm", "Link .s file into .wast");
options
@@ -68,6 +69,11 @@ int main(int argc, const char *argv[]) {
[](Options *o, const std::string &argument) {
o->extra["max-memory"] = argument;
})
+ .add("--emscripten-glue", "-e", "Generate emscripten glue",
+ Options::Arguments::Zero,
+ [&generateEmscriptenGlue](Options *, const std::string &) {
+ generateEmscriptenGlue = true;
+ })
.add_positional("INFILE", Options::Arguments::One,
[](Options *o, const std::string &argument) {
o->extra["infile"] = argument;
@@ -98,9 +104,12 @@ int main(int argc, const char *argv[]) {
stackAllocation, initialMem, maxMem, ignoreUnknownSymbols,
startFunction);
- if (options.debug) std::cerr << "Emscripten gluing..." << std::endl;
std::stringstream meta;
- s2wasm.emscriptenGlue(meta);
+ if (generateEmscriptenGlue) {
+ if (options.debug) std::cerr << "Emscripten gluing..." << std::endl;
+ // dyncall thunks
+ s2wasm.emscriptenGlue(meta);
+ }
if (options.debug) std::cerr << "Printing..." << std::endl;
Output output(options.extra["output"], Flags::Text, options.debug ? Flags::Debug : Flags::Release);
diff --git a/src/s2wasm.h b/src/s2wasm.h
index 2963af2fe..b78da8cfe 100644
--- a/src/s2wasm.h
+++ b/src/s2wasm.h
@@ -1249,20 +1249,28 @@ class S2WasmBuilder {
wasm.addExport(exp);
}
- void getDyncallThunk(const std::string& sig) {
- // hard-code the sig for testing for now. vi is the signature for static destructors
- assert(sig == "vi");
- auto* targetType = ensureFunctionType(sig, &wasm, wasm.allocator);
+ void makeDynCallThunks() {
+ std::unordered_set<std::string> sigs;
wasm::Builder wasmBuilder(wasm);
- std::vector<NameType> params {{"$0", i32}, {"$1", i32}};
- Function* f = wasmBuilder.makeFunction(std::string("dynCall_") + sig, std::move(params), none, {});
- auto* call = wasmBuilder.makeCallIndirect(
- targetType,
- wasmBuilder.makeGetLocal(params[0].name, params[0].type),
- {wasmBuilder.makeGetLocal(params[1].name, params[1].type)});
- auto* ret = wasmBuilder.makeReturn(call);
- f->body = ret;
- wasm.addFunction(f);
+ for (const auto& indirectFunc : wasm.table.names) {
+ std::string sig(getSig(wasm.getFunction(indirectFunc)));
+ auto* funcType = ensureFunctionType(sig, &wasm, wasm.allocator);
+ if (!sigs.insert(sig).second) continue; // Sig is already in the set
+ std::vector<NameType> params;
+ params.emplace_back("fptr", i32); // function pointer param
+ int p = 0;
+ for (const auto& ty : funcType->params) params.emplace_back("$" + std::to_string(p++), ty);
+ Function* f = wasmBuilder.makeFunction(std::string("dynCall_") + sig, std::move(params), funcType->result, {});
+ Expression* fptr = wasmBuilder.makeGetLocal("fptr", i32);
+ std::vector<Expression*> args;
+ for (unsigned i = 0; i < funcType->params.size(); ++i) {
+ args.push_back(wasmBuilder.makeGetLocal("$" + std::to_string(i), funcType->params[i]));
+ }
+ Expression* call = wasmBuilder.makeCallIndirect(funcType, fptr, std::move(args));
+ f->body = funcType->result == none ? call : wasmBuilder.makeReturn(call);
+ wasm.addFunction(f);
+ exportFunction(f->name, true);
+ }
}
void fix() {
@@ -1383,6 +1391,8 @@ public:
wasm.removeImport(EMSCRIPTEN_ASM_CONST); // we create _sig versions
+ makeDynCallThunks();
+
o << ";; METADATA: { ";
// find asmConst calls, and emit their metadata
struct AsmConstWalker : public PostWalker<AsmConstWalker> {
diff --git a/test/dot_s/alias.wast b/test/dot_s/alias.wast
index c9c64117b..64a58a94c 100644
--- a/test/dot_s/alias.wast
+++ b/test/dot_s/alias.wast
@@ -4,6 +4,7 @@
(type $FUNCSIG$v (func))
(export "__exit" $__exit)
(export "__needs_exit" $__needs_exit)
+ (export "dynCall_v" $dynCall_v)
(table $__exit)
(func $__exit (type $FUNCSIG$v)
(local $$0 i32)
@@ -15,5 +16,10 @@
(i32.const 0)
)
)
+ (func $dynCall_v (param $fptr i32)
+ (call_indirect $FUNCSIG$v
+ (get_local $fptr)
+ )
+ )
)
;; METADATA: { "asmConsts": {},"staticBump": 12, "initializers": [] }
diff --git a/test/dot_s/basics.wast b/test/dot_s/basics.wast
index cc1af6c6e..bc3951633 100644
--- a/test/dot_s/basics.wast
+++ b/test/dot_s/basics.wast
@@ -9,6 +9,7 @@
(type $FUNCSIG$iii (func (param i32 i32) (result i32)))
(import $puts "env" "puts" (param i32))
(export "main" $main)
+ (export "dynCall_iii" $dynCall_iii)
(table $main)
(func $main (type $FUNCSIG$iii) (param $$0 i32) (param $$1 i32) (result i32)
(call_import $puts
@@ -91,5 +92,14 @@
(get_local $$0)
)
)
+ (func $dynCall_iii (param $fptr i32) (param $$0 i32) (param $$1 i32) (result i32)
+ (return
+ (call_indirect $FUNCSIG$iii
+ (get_local $fptr)
+ (get_local $$0)
+ (get_local $$1)
+ )
+ )
+ )
)
;; METADATA: { "asmConsts": {},"staticBump": 52, "initializers": [] }
diff --git a/test/dot_s/bcp-1.wast b/test/dot_s/bcp-1.wast
index 13f113932..4e3fa51ea 100644
--- a/test/dot_s/bcp-1.wast
+++ b/test/dot_s/bcp-1.wast
@@ -33,6 +33,8 @@
(export "opt1" $opt1)
(export "opt2" $opt2)
(export "main" $main)
+ (export "dynCall_i" $dynCall_i)
+ (export "dynCall_ii" $dynCall_ii)
(table $bad0 $bad1 $bad5 $bad7 $bad8 $bad10 $bad2 $bad3 $bad6 $bad4 $bad9 $good0 $good1 $good2 $opt0 $opt1 $opt2)
(func $bad0 (type $FUNCSIG$i) (result i32)
(return
@@ -305,5 +307,20 @@
(call_import $abort)
(unreachable)
)
+ (func $dynCall_i (param $fptr i32) (result i32)
+ (return
+ (call_indirect $FUNCSIG$i
+ (get_local $fptr)
+ )
+ )
+ )
+ (func $dynCall_ii (param $fptr i32) (param $$0 i32) (result i32)
+ (return
+ (call_indirect $FUNCSIG$ii
+ (get_local $fptr)
+ (get_local $$0)
+ )
+ )
+ )
)
;; METADATA: { "asmConsts": {},"staticBump": 104, "initializers": [] }
diff --git a/test/dot_s/dyncall.c b/test/dot_s/dyncall.c
new file mode 100644
index 000000000..124b79d8b
--- /dev/null
+++ b/test/dot_s/dyncall.c
@@ -0,0 +1,30 @@
+#include <stdint.h>
+
+/* Used to generate dyncall.s */
+
+uint32_t i() {
+ return 0;
+}
+uint64_t jf(float f) {
+ return 0;
+}
+void vd(double d) {
+ return;
+}
+float ffjjdi(float f, uint64_t j, uint64_t j2, double d, uint32_t i) {
+ return 0.0;
+}
+
+/* Duplicates sig vd */
+void vd2(double d) {
+ return;
+}
+
+int main() {
+ asm(" i32.const $discard=, i@FUNCTION");
+ asm(" i32.const $discard=, jf@FUNCTION");
+ asm(" i32.const $discard=, vd@FUNCTION");
+ asm(" i32.const $discard=, ffjjdi@FUNCTION");
+ asm(" i32.const $discard=, vd2@FUNCTION");
+ return 0;
+}
diff --git a/test/dot_s/dyncall.s b/test/dot_s/dyncall.s
new file mode 100644
index 000000000..280a5bf37
--- /dev/null
+++ b/test/dot_s/dyncall.s
@@ -0,0 +1,97 @@
+ .text
+ .file "src/work/binaryen/test/dot_s/dyncall.c"
+ .section .text.i,"ax",@progbits
+ .hidden i
+ .globl i
+ .type i,@function
+i: # @i
+ .result i32
+# BB#0: # %entry
+ i32.const $push0=, 0
+ return $pop0
+ .endfunc
+.Lfunc_end0:
+ .size i, .Lfunc_end0-i
+
+ .section .text.jf,"ax",@progbits
+ .hidden jf
+ .globl jf
+ .type jf,@function
+jf: # @jf
+ .param f32
+ .result i64
+# BB#0: # %entry
+ i64.const $push0=, 0
+ return $pop0
+ .endfunc
+.Lfunc_end1:
+ .size jf, .Lfunc_end1-jf
+
+ .section .text.vd,"ax",@progbits
+ .hidden vd
+ .globl vd
+ .type vd,@function
+vd: # @vd
+ .param f64
+# BB#0: # %entry
+ return
+ .endfunc
+.Lfunc_end2:
+ .size vd, .Lfunc_end2-vd
+
+ .section .text.ffjjdi,"ax",@progbits
+ .hidden ffjjdi
+ .globl ffjjdi
+ .type ffjjdi,@function
+ffjjdi: # @ffjjdi
+ .param f32, i64, i64, f64, i32
+ .result f32
+# BB#0: # %entry
+ f32.const $push0=, 0x0p0
+ return $pop0
+ .endfunc
+.Lfunc_end3:
+ .size ffjjdi, .Lfunc_end3-ffjjdi
+
+ .section .text.vd2,"ax",@progbits
+ .hidden vd2
+ .globl vd2
+ .type vd2,@function
+vd2: # @vd2
+ .param f64
+# BB#0: # %entry
+ return
+ .endfunc
+.Lfunc_end4:
+ .size vd2, .Lfunc_end4-vd2
+
+ .section .text.main,"ax",@progbits
+ .hidden main
+ .globl main
+ .type main,@function
+main: # @main
+ .result i32
+# BB#0: # %entry
+ #APP
+ i32.const $discard=, i@FUNCTION
+ #NO_APP
+ #APP
+ i32.const $discard=, jf@FUNCTION
+ #NO_APP
+ #APP
+ i32.const $discard=, vd@FUNCTION
+ #NO_APP
+ #APP
+ i32.const $discard=, ffjjdi@FUNCTION
+ #NO_APP
+ #APP
+ i32.const $discard=, vd2@FUNCTION
+ #NO_APP
+ i32.const $push0=, 0
+ return $pop0
+ .endfunc
+.Lfunc_end5:
+ .size main, .Lfunc_end5-main
+
+
+ .ident "clang version 3.9.0 "
diff --git a/test/dot_s/dyncall.wast b/test/dot_s/dyncall.wast
new file mode 100644
index 000000000..3d82924f2
--- /dev/null
+++ b/test/dot_s/dyncall.wast
@@ -0,0 +1,84 @@
+(module
+ (memory 1)
+ (export "memory" memory)
+ (type $FUNCSIG$i (func (result i32)))
+ (type $FUNCSIG$jf (func (param f32) (result i64)))
+ (type $FUNCSIG$vd (func (param f64)))
+ (type $FUNCSIG$ffjjdi (func (param f32 i64 i64 f64 i32) (result f32)))
+ (export "i" $i)
+ (export "jf" $jf)
+ (export "vd" $vd)
+ (export "ffjjdi" $ffjjdi)
+ (export "vd2" $vd2)
+ (export "main" $main)
+ (export "dynCall_i" $dynCall_i)
+ (export "dynCall_jf" $dynCall_jf)
+ (export "dynCall_vd" $dynCall_vd)
+ (export "dynCall_ffjjdi" $dynCall_ffjjdi)
+ (table $i $jf $vd $ffjjdi $vd2)
+ (func $i (type $FUNCSIG$i) (result i32)
+ (return
+ (i32.const 0)
+ )
+ )
+ (func $jf (type $FUNCSIG$jf) (param $$0 f32) (result i64)
+ (return
+ (i64.const 0)
+ )
+ )
+ (func $vd (type $FUNCSIG$vd) (param $$0 f64)
+ (return)
+ )
+ (func $ffjjdi (type $FUNCSIG$ffjjdi) (param $$0 f32) (param $$1 i64) (param $$2 i64) (param $$3 f64) (param $$4 i32) (result f32)
+ (return
+ (f32.const 0)
+ )
+ )
+ (func $vd2 (type $FUNCSIG$vd) (param $$0 f64)
+ (return)
+ )
+ (func $main (result i32)
+ (i32.const 0)
+ (i32.const 1)
+ (i32.const 2)
+ (i32.const 3)
+ (i32.const 4)
+ (return
+ (i32.const 0)
+ )
+ )
+ (func $dynCall_i (param $fptr i32) (result i32)
+ (return
+ (call_indirect $FUNCSIG$i
+ (get_local $fptr)
+ )
+ )
+ )
+ (func $dynCall_jf (param $fptr i32) (param $$0 f32) (result i64)
+ (return
+ (call_indirect $FUNCSIG$jf
+ (get_local $fptr)
+ (get_local $$0)
+ )
+ )
+ )
+ (func $dynCall_vd (param $fptr i32) (param $$0 f64)
+ (call_indirect $FUNCSIG$vd
+ (get_local $fptr)
+ (get_local $$0)
+ )
+ )
+ (func $dynCall_ffjjdi (param $fptr i32) (param $$0 f32) (param $$1 i64) (param $$2 i64) (param $$3 f64) (param $$4 i32) (result f32)
+ (return
+ (call_indirect $FUNCSIG$ffjjdi
+ (get_local $fptr)
+ (get_local $$0)
+ (get_local $$1)
+ (get_local $$2)
+ (get_local $$3)
+ (get_local $$4)
+ )
+ )
+ )
+)
+;; METADATA: { "asmConsts": {},"staticBump": 12, "initializers": [] }
diff --git a/test/emscripten b/test/emscripten
-Subproject e480c6ed0194fc72c866c9d2eef697c221d1ae2
+Subproject b8420785844ae400de98ddb41db6bdfd7a227da