summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorDerek Schuff <dschuff@chromium.org>2016-06-02 14:30:30 -0700
committerDerek Schuff <dschuff@chromium.org>2016-06-02 14:30:30 -0700
commitd4dc216888d5028f41e6189e65001694e49a66c2 (patch)
tree35ac5962bedb07fa732b34b62f7b7c3d68280ce4 /test
parentd595e89003dc3636952de4c561679e3a077e6015 (diff)
downloadbinaryen-d4dc216888d5028f41e6189e65001694e49a66c2.tar.gz
binaryen-d4dc216888d5028f41e6189e65001694e49a66c2.tar.bz2
binaryen-d4dc216888d5028f41e6189e65001694e49a66c2.zip
Generate thunks for address-taken imports (#554)
Under emscripten, C code can take the address of a function implemented in Javascript (which is exposed via an import in wasm). Because imports do not have linear memory address in wasm, we need to generate a thunk to be the target of the indirect call; it call the import directly. This is facilited by a new .s directive (.functype) which declares the types of functions which are declared but not defined. Fixes https://github.com/WebAssembly/binaryen/issues/392
Diffstat (limited to 'test')
-rw-r--r--test/dot_s/indirect-import.c27
-rw-r--r--test/dot_s/indirect-import.s55
-rw-r--r--test/dot_s/indirect-import.wast147
3 files changed, 229 insertions, 0 deletions
diff --git a/test/dot_s/indirect-import.c b/test/dot_s/indirect-import.c
new file mode 100644
index 000000000..006424d84
--- /dev/null
+++ b/test/dot_s/indirect-import.c
@@ -0,0 +1,27 @@
+#include <stdint.h>
+
+struct big {
+ float a;
+ double b;
+ int32_t c;
+};
+
+float extern_fd(double);
+void extern_vj(uint64_t);
+void extern_v(void);
+int32_t extern_ijidf(int64_t, int32_t, double, float);
+void extern_struct(struct big);
+struct big extern_sret(void);
+
+intptr_t bar() {
+ float (*fd)(double) = &extern_fd;
+ void (*vj)(uint64_t) = &extern_vj;
+ vj(1ULL);
+ void (*v)(void) = &extern_v;
+ v();
+ int32_t (*ijidf)(int64_t, int32_t, double, float) = &extern_ijidf;
+ ijidf(1LL, 2, 3.0, 4.0f);
+ void (*vs)(struct big) = &extern_struct;
+ struct big (*s)(void) = &extern_sret;
+ return (intptr_t)fd;
+}
diff --git a/test/dot_s/indirect-import.s b/test/dot_s/indirect-import.s
new file mode 100644
index 000000000..5131d86f3
--- /dev/null
+++ b/test/dot_s/indirect-import.s
@@ -0,0 +1,55 @@
+ .text
+ .file "indirect-import.ll"
+ .hidden bar
+ .globl bar
+ .type bar,@function
+bar: # @bar
+ .result i32
+ .local i32, i32
+# BB#0: # %entry
+ i32.const $push13=, 0
+ i32.const $push10=, 0
+ i32.load $push11=, __stack_pointer($pop10)
+ i32.const $push12=, 32
+ i32.sub $push17=, $pop11, $pop12
+ i32.store $push20=, __stack_pointer($pop13), $pop17
+ tee_local $push19=, $0=, $pop20
+ i32.const $push0=, extern_fd@FUNCTION
+ i32.store $drop=, 28($pop19), $pop0
+ i32.const $push1=, extern_vj@FUNCTION
+ i32.store $drop=, 24($0), $pop1
+ i64.const $push2=, 1
+ call extern_vj@FUNCTION, $pop2
+ i32.const $push3=, extern_v@FUNCTION
+ i32.store $drop=, 20($0), $pop3
+ call extern_v@FUNCTION
+ i32.const $push4=, extern_ijidf@FUNCTION
+ i32.store $drop=, 16($0), $pop4
+ i64.const $push18=, 1
+ i32.const $push7=, 2
+ f64.const $push6=, 0x1.8p1
+ f32.const $push5=, 0x1p2
+ i32.call $drop=, extern_ijidf@FUNCTION, $pop18, $pop7, $pop6, $pop5
+ i32.const $push8=, extern_struct@FUNCTION
+ i32.store $drop=, 12($0), $pop8
+ i32.const $push9=, extern_sret@FUNCTION
+ i32.store $drop=, 8($0), $pop9
+ i32.load $1=, 28($0)
+ i32.const $push16=, 0
+ i32.const $push14=, 32
+ i32.add $push15=, $0, $pop14
+ i32.store $drop=, __stack_pointer($pop16), $pop15
+ copy_local $push21=, $1
+ # fallthrough-return: $pop21
+ .endfunc
+.Lfunc_end0:
+ .size bar, .Lfunc_end0-bar
+
+
+ .ident "clang version 3.9.0 (trunk 271427) (llvm/trunk 271429)"
+ .functype extern_fd, f32, f64
+ .functype extern_vj, void, i64
+ .functype extern_v, void
+ .functype extern_ijidf, i32, i64, i32, f64, f32
+ .functype extern_struct, void, i32
+ .functype extern_sret, void, i32
diff --git a/test/dot_s/indirect-import.wast b/test/dot_s/indirect-import.wast
new file mode 100644
index 000000000..8ffeea168
--- /dev/null
+++ b/test/dot_s/indirect-import.wast
@@ -0,0 +1,147 @@
+(module
+ (memory 1)
+ (export "memory" memory)
+ (type $FUNCSIG$ijidf (func (param i64 i32 f64 f32) (result i32)))
+ (type $FUNCSIG$v (func))
+ (type $FUNCSIG$vj (func (param i64)))
+ (type $FUNCSIG$fd (func (param f64) (result f32)))
+ (type $FUNCSIG$vi (func (param i32)))
+ (import $extern_ijidf "env" "extern_ijidf" (param i64 i32 f64 f32) (result i32))
+ (import $extern_v "env" "extern_v")
+ (import $extern_vj "env" "extern_vj" (param i64))
+ (import $extern_fd "env" "extern_fd" (param f64) (result f32))
+ (import $extern_struct "env" "extern_struct" (param i32))
+ (import $extern_sret "env" "extern_sret" (param i32))
+ (export "bar" $bar)
+ (export "dynCall_fd" $dynCall_fd)
+ (export "dynCall_vj" $dynCall_vj)
+ (export "dynCall_v" $dynCall_v)
+ (export "dynCall_ijidf" $dynCall_ijidf)
+ (export "dynCall_vi" $dynCall_vi)
+ (table $__importThunk_extern_fd $__importThunk_extern_vj $__importThunk_extern_v $__importThunk_extern_ijidf $__importThunk_extern_struct $__importThunk_extern_sret)
+ (func $bar (result i32)
+ (local $0 i32)
+ (local $1 i32)
+ (i32.store offset=28
+ (set_local $0
+ (i32.store offset=4
+ (i32.const 0)
+ (i32.sub
+ (i32.load offset=4
+ (i32.const 0)
+ )
+ (i32.const 32)
+ )
+ )
+ )
+ (i32.const 0)
+ )
+ (i32.store offset=24
+ (get_local $0)
+ (i32.const 1)
+ )
+ (call_import $extern_vj
+ (i64.const 1)
+ )
+ (i32.store offset=20
+ (get_local $0)
+ (i32.const 2)
+ )
+ (call_import $extern_v)
+ (i32.store offset=16
+ (get_local $0)
+ (i32.const 3)
+ )
+ (call_import $extern_ijidf
+ (i64.const 1)
+ (i32.const 2)
+ (f64.const 3)
+ (f32.const 4)
+ )
+ (i32.store offset=12
+ (get_local $0)
+ (i32.const 4)
+ )
+ (i32.store offset=8
+ (get_local $0)
+ (i32.const 5)
+ )
+ (set_local $1
+ (i32.load offset=28
+ (get_local $0)
+ )
+ )
+ (i32.store offset=4
+ (i32.const 0)
+ (i32.add
+ (get_local $0)
+ (i32.const 32)
+ )
+ )
+ (get_local $1)
+ )
+ (func $__importThunk_extern_fd (type $FUNCSIG$fd) (param $0 f64) (result f32)
+ (call_import $extern_fd
+ (get_local $0)
+ )
+ )
+ (func $__importThunk_extern_vj (type $FUNCSIG$vj) (param $0 i64)
+ (call_import $extern_vj
+ (get_local $0)
+ )
+ )
+ (func $__importThunk_extern_v (type $FUNCSIG$v)
+ (call_import $extern_v)
+ )
+ (func $__importThunk_extern_ijidf (type $FUNCSIG$ijidf) (param $0 i64) (param $1 i32) (param $2 f64) (param $3 f32) (result i32)
+ (call_import $extern_ijidf
+ (get_local $0)
+ (get_local $1)
+ (get_local $2)
+ (get_local $3)
+ )
+ )
+ (func $__importThunk_extern_struct (type $FUNCSIG$vi) (param $0 i32)
+ (call_import $extern_struct
+ (get_local $0)
+ )
+ )
+ (func $__importThunk_extern_sret (type $FUNCSIG$vi) (param $0 i32)
+ (call_import $extern_sret
+ (get_local $0)
+ )
+ )
+ (func $dynCall_fd (param $fptr i32) (param $0 f64) (result f32)
+ (call_indirect $FUNCSIG$fd
+ (get_local $fptr)
+ (get_local $0)
+ )
+ )
+ (func $dynCall_vj (param $fptr i32) (param $0 i64)
+ (call_indirect $FUNCSIG$vj
+ (get_local $fptr)
+ (get_local $0)
+ )
+ )
+ (func $dynCall_v (param $fptr i32)
+ (call_indirect $FUNCSIG$v
+ (get_local $fptr)
+ )
+ )
+ (func $dynCall_ijidf (param $fptr i32) (param $0 i64) (param $1 i32) (param $2 f64) (param $3 f32) (result i32)
+ (call_indirect $FUNCSIG$ijidf
+ (get_local $fptr)
+ (get_local $0)
+ (get_local $1)
+ (get_local $2)
+ (get_local $3)
+ )
+ )
+ (func $dynCall_vi (param $fptr i32) (param $0 i32)
+ (call_indirect $FUNCSIG$vi
+ (get_local $fptr)
+ (get_local $0)
+ )
+ )
+)
+;; METADATA: { "asmConsts": {},"staticBump": 12, "initializers": [] }