summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/s2wasm.h59
-rw-r--r--test/dot_s/fix_em_ehsjlj_names.s (renamed from test/dot_s/invoke_wrapper.s)30
-rw-r--r--test/dot_s/fix_em_ehsjlj_names.wast (renamed from test/dot_s/invoke_wrapper.wast)6
3 files changed, 74 insertions, 21 deletions
diff --git a/src/s2wasm.h b/src/s2wasm.h
index a45f3aab4..a23cbb549 100644
--- a/src/s2wasm.h
+++ b/src/s2wasm.h
@@ -248,7 +248,8 @@ class S2WasmBuilder {
s++;
offset = -getInt();
}
- linkerObj->addRelocation(kind, target, cleanFunction(name), offset);
+ linkerObj->addRelocation(kind, target,
+ fixEmLongjmp(cleanFunction(name)), offset);
return true;
}
}
@@ -566,7 +567,7 @@ class S2WasmBuilder {
decl->name = "FUNCSIG$" + sig;
FunctionType *ty = wasm->checkFunctionType(decl->name);
- Name name = fixEmExceptionInvoke(rawName, sig);
+ Name name = fixEmEHSjLjNames(rawName, sig);
if (!ty) {
// The wasm module takes ownership of the FunctionType if we insert it.
// Otherwise it's already in the module and ours is freed.
@@ -891,7 +892,7 @@ class S2WasmBuilder {
}
}
Name target = linkerObj->resolveAlias(
- fixEmExceptionInvoke(rawTarget, curr->type, curr->operands),
+ fixEmEHSjLjNames(rawTarget, curr->type, curr->operands),
LinkerObject::Relocation::kFunction);
curr->target = target;
if (!linkerObj->isFunctionImplemented(target)) {
@@ -1347,6 +1348,52 @@ class S2WasmBuilder {
}
}
+ // Fixes function name hacks caused by LLVM exception & setjmp/longjmp
+ // handling pass for wasm.
+ // This does two things:
+ // 1. Change emscripten_longjmp_jmpbuf to emscripten_longjmp.
+ // In setjmp/longjmp handling pass in wasm backend, what we want to do is
+ // to change all function calls to longjmp to calls to emscripten_longjmp.
+ // Because we replace all calls to longjmp to emscripten_longjmp, the
+ // signature of that function should be the same as longjmp:
+ // emscripten_longjmp(jmp_buf, int)
+ // But after calling a function that might longjmp, while we test whether
+ // a longjmp occurred, we have to load an int address value and call
+ // emscripten_longjmp again with that address as the first argument. (Refer
+ // to lib/Target/WebAssembly/WebAssemblyEmscriptenEHSjLj.cpp in LLVM for
+ // details.)
+ // In this case we need the signature of emscripten_longjmp to be (int,
+ // int). So we need two different kinds of emscripten_longjmp signatures in
+ // LLVM IR. Both signatures will be lowered to (int, int) eventually, but
+ // in LLVM IR, types are not lowered yet.
+ // So we declare two functions in LLVM:
+ // emscripten_longjmp_jmpbuf(jmp_buf, int)
+ // emscripten_longjmp(int, int)
+ // And we change the name of emscripten_longjmp_jmpbuf to
+ // emscripten_longjmp here.
+ // 2. Converts invoke wrapper names.
+ // Refer to the comments in fixEmExceptionInvoke below.
+ template<typename ListType>
+ Name fixEmEHSjLjNames(const Name &name, WasmType result,
+ const ListType &operands) {
+ return fixEmEHSjLjNames(name, getSig(result, operands));
+ }
+
+ Name fixEmEHSjLjNames(const Name &name, const std::string &sig) {
+ if (name == "emscripten_longjmp_jmpbuf")
+ return "emscripten_longjmp";
+ return fixEmExceptionInvoke(name, sig);
+ }
+
+ // This version only converts emscripten_longjmp_jmpbuf and does not deal
+ // with invoke wrappers. This is used when we only have a function name as
+ // relocatable constant.
+ Name fixEmLongjmp(const Name &name) {
+ if (name == "emscripten_longjmp_jmpbuf")
+ return "emscripten_longjmp";
+ return name;
+ }
+
// Converts invoke wrapper names generated by LLVM backend to real invoke
// wrapper names that are expected by JavaScript glue code.
// This is required to support wasm exception handling (asm.js style).
@@ -1366,12 +1413,6 @@ class S2WasmBuilder {
// This function converts the names of invoke wrappers based on their lowered
// argument types and a return type. In the example above, the resulting new
// wrapper name becomes "invoke_vii".
- template<typename ListType>
- Name fixEmExceptionInvoke(const Name &name, WasmType result,
- const ListType &operands) {
- return fixEmExceptionInvoke(name, getSig(result, operands));
- }
-
Name fixEmExceptionInvoke(const Name &name, const std::string &sig) {
std::string nameStr = name.c_str();
if (nameStr.front() == '"' && nameStr.back() == '"') {
diff --git a/test/dot_s/invoke_wrapper.s b/test/dot_s/fix_em_ehsjlj_names.s
index 6de2f8b4c..15d4452b1 100644
--- a/test/dot_s/invoke_wrapper.s
+++ b/test/dot_s/fix_em_ehsjlj_names.s
@@ -1,5 +1,5 @@
.text
- .file "invoke_wrapper.bc"
+ .file "fix_em_ehsjlj_names.bc"
.type _Z5func1v,@function
_Z5func1v:
.endfunc
@@ -46,17 +46,20 @@ main:
i32.const $push3=, 2
i32.const $push2=, 3
i32.call $drop=, __invoke_i32_i32_i32_i32@FUNCTION, $pop5, $pop4, $pop3, $pop2
- i32.const $push9=, _Z5func3fd@FUNCTION
- f32.const $push8=, 0x1.8p0
- f64.const $push7=, 0x1.b333333333333p1
- f32.call $drop=, __invoke_float_float_double@FUNCTION, $pop9, $pop8, $pop7
- i32.const $push21=, _Z5func4P8mystructS_@FUNCTION
- i32.const $push37=, 32
- i32.add $push38=, $1, $pop37
- i32.const $push39=, 4
- i32.add $push40=, $1, $pop39
- i32.call $drop=, "__invoke_%struct.mystruct*_%struct.mystruct*_%struct.mystruct*"@FUNCTION, $pop21, $pop38, $pop40
- i32.const $push23=, 0
+ i32.const $push8=, _Z5func3fd@FUNCTION
+ f32.const $push7=, 0x1.8p0
+ f64.const $push6=, 0x1.b333333333333p1
+ f32.call $drop=, __invoke_float_float_double@FUNCTION, $pop8, $pop7, $pop6
+ i32.const $push9=, _Z5func4P8mystructS_@FUNCTION
+ i32.const $push10=, 32
+ i32.add $push11=, $1, $pop10
+ i32.const $push12=, 4
+ i32.add $push13=, $1, $pop12
+ i32.call $drop=, "__invoke_%struct.mystruct*_%struct.mystruct*_%struct.mystruct*"@FUNCTION, $pop9, $pop11, $pop13
+ i32.const $push14=, 5
+ i32.const $push15=, 6
+ call emscripten_longjmp_jmpbuf@FUNCTION, $pop15, $pop14
+ i32.const $push16=, 0
.endfunc
.Lfunc_end4:
.size main, .Lfunc_end4-main
@@ -65,3 +68,6 @@ main:
.functype __invoke_i32_i32_i32_i32, i32, i32, i32, i32, i32
.functype __invoke_float_float_double, f32, i32, f32, f64
.functype __invoke_%struct.mystruct*_%struct.mystruct*_%struct.mystruct*, i32, i32, i32, i32
+ .functype emscripten_longjmp_jmpbuf, void, i32, i32
+ .functype emscripten_longjmp, void, i32, i32
+
diff --git a/test/dot_s/invoke_wrapper.wast b/test/dot_s/fix_em_ehsjlj_names.wast
index d54e94d03..61ae5ef5e 100644
--- a/test/dot_s/invoke_wrapper.wast
+++ b/test/dot_s/fix_em_ehsjlj_names.wast
@@ -5,9 +5,11 @@
(type $FUNCSIG$iiiii (func (param i32 i32 i32 i32) (result i32)))
(type $FUNCSIG$fifd (func (param i32 f32 f64) (result f32)))
(type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32)))
+ (type $FUNCSIG$vii (func (param i32 i32)))
(type $FUNCSIG$v (func))
(type $FUNCSIG$ffd (func (param f32 f64) (result f32)))
(type $FUNCSIG$iii (func (param i32 i32) (result i32)))
+ (import $emscripten_longjmp "env" "emscripten_longjmp" (param i32 i32))
(import $invoke_ffd "env" "invoke_ffd" (param i32 f32 f64) (result f32))
(import $invoke_iii "env" "invoke_iii" (param i32 i32 i32) (result i32))
(import $invoke_iiii "env" "invoke_iiii" (param i32 i32 i32 i32) (result i32))
@@ -60,6 +62,10 @@
(i32.const 4)
)
)
+ (call_import $emscripten_longjmp
+ (i32.const 5)
+ (i32.const 6)
+ )
(i32.const 0)
)
(func $__wasm_nullptr (type $FUNCSIG$v)