summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/wasm-linker.cpp8
-rw-r--r--src/wasm-linker.h2
-rw-r--r--test/dot_s/indirect-import.c6
-rw-r--r--test/dot_s/indirect-import.s14
-rw-r--r--test/dot_s/indirect-import.wast4
5 files changed, 28 insertions, 6 deletions
diff --git a/src/wasm-linker.cpp b/src/wasm-linker.cpp
index 1aba37b1b..d6c0edb4a 100644
--- a/src/wasm-linker.cpp
+++ b/src/wasm-linker.cpp
@@ -145,7 +145,7 @@ void Linker::layout() {
if (FunctionType* f = out.getExternType(name)) {
// Address of an imported function is taken, but imports do not have addresses in wasm.
// Generate a thunk to forward to the call_import.
- Function* thunk = generateImportThunk(name, f);
+ Function* thunk = getImportThunk(name, f);
ensureFunctionIndex(thunk->name);
*(relocation->data) = functionIndexes[thunk->name] + relocation->addend;
} else {
@@ -381,12 +381,14 @@ void Linker::makeDynCallThunks() {
}
}
-Function* Linker::generateImportThunk(Name name, const FunctionType* funcType) {
+Function* Linker::getImportThunk(Name name, const FunctionType* funcType) {
+ Name thunkName = std::string("__importThunk_") + name.c_str();
+ if (Function* thunk = out.wasm.checkFunction(thunkName)) return thunk;
wasm::Builder wasmBuilder(out.wasm);
std::vector<NameType> params;
Index p = 0;
for (const auto& ty : funcType->params) params.emplace_back(std::to_string(p++), ty);
- Function *f = wasmBuilder.makeFunction(std::string("__importThunk_") + name.c_str(), std::move(params), funcType->result, {});
+ Function *f = wasmBuilder.makeFunction(thunkName, std::move(params), funcType->result, {});
std::vector<Expression*> args;
for (Index i = 0; i < funcType->params.size(); ++i) {
args.push_back(wasmBuilder.makeGetLocal(i, funcType->params[i]));
diff --git a/src/wasm-linker.h b/src/wasm-linker.h
index a0684d02b..97e1c9cd5 100644
--- a/src/wasm-linker.h
+++ b/src/wasm-linker.h
@@ -277,7 +277,7 @@ class Linker {
out.wasm.addExport(exp);
}
- Function* generateImportThunk(Name name, const FunctionType* t);
+ Function* getImportThunk(Name name, const FunctionType* t);
// The output module (linked executable)
LinkerObject out;
diff --git a/test/dot_s/indirect-import.c b/test/dot_s/indirect-import.c
index 006424d84..679d862c7 100644
--- a/test/dot_s/indirect-import.c
+++ b/test/dot_s/indirect-import.c
@@ -23,5 +23,9 @@ intptr_t bar() {
ijidf(1LL, 2, 3.0, 4.0f);
void (*vs)(struct big) = &extern_struct;
struct big (*s)(void) = &extern_sret;
- return (intptr_t)fd;
+ return (intptr_t)fd;
+}
+
+intptr_t baz() {
+ return (intptr_t)extern_v;
}
diff --git a/test/dot_s/indirect-import.s b/test/dot_s/indirect-import.s
index 5131d86f3..f09291d84 100644
--- a/test/dot_s/indirect-import.s
+++ b/test/dot_s/indirect-import.s
@@ -45,8 +45,20 @@ bar: # @bar
.Lfunc_end0:
.size bar, .Lfunc_end0-bar
+ .hidden baz
+ .globl baz
+ .type baz,@function
+baz: # @baz
+ .result i32
+# BB#0: # %entry
+ i32.const $push0=, extern_v@FUNCTION
+ # fallthrough-return: $pop0
+ .endfunc
+.Lfunc_end1:
+ .size baz, .Lfunc_end1-baz
+
- .ident "clang version 3.9.0 (trunk 271427) (llvm/trunk 271429)"
+ .ident "clang version 3.9.0 (trunk 271579) (llvm/trunk 271699)"
.functype extern_fd, f32, f64
.functype extern_vj, void, i64
.functype extern_v, void
diff --git a/test/dot_s/indirect-import.wast b/test/dot_s/indirect-import.wast
index f3a989461..b24b5cd59 100644
--- a/test/dot_s/indirect-import.wast
+++ b/test/dot_s/indirect-import.wast
@@ -13,6 +13,7 @@
(import $extern_struct "env" "extern_struct" (param i32))
(import $extern_sret "env" "extern_sret" (param i32))
(export "bar" $bar)
+ (export "baz" $baz)
(export "dynCall_fd" $dynCall_fd)
(export "dynCall_vj" $dynCall_vj)
(export "dynCall_v" $dynCall_v)
@@ -80,6 +81,9 @@
)
(get_local $1)
)
+ (func $baz (result i32)
+ (i32.const 2)
+ )
(func $__importThunk_extern_fd (type $FUNCSIG$fd) (param $0 f64) (result f32)
(call_import $extern_fd
(get_local $0)