summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/wasm/wasm-emscripten.cpp136
-rw-r--r--test/lit/wasm-emscripten-finalize/passive-pic.wat2
-rw-r--r--test/lld/em_asm_main_thread.wat2
-rw-r--r--test/lld/em_asm_main_thread.wat.out4
-rw-r--r--test/unit/input/em_asm_mangled_string.wat11
-rw-r--r--test/unit/test_finalize.py10
6 files changed, 16 insertions, 149 deletions
diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp
index d97121544..684c789c3 100644
--- a/src/wasm/wasm-emscripten.cpp
+++ b/src/wasm/wasm-emscripten.cpp
@@ -185,123 +185,6 @@ struct AsmConst {
std::string code;
};
-struct AsmConstWalker : public LinearExecutionWalker<AsmConstWalker> {
- Module& wasm;
- bool minimizeWasmChanges;
- StringConstantTracker stringTracker;
-
- std::vector<AsmConst> asmConsts;
- // last sets in the current basic block, per index
- std::map<Index, LocalSet*> sets;
-
- AsmConstWalker(Module& _wasm, bool minimizeWasmChanges)
- : wasm(_wasm), minimizeWasmChanges(minimizeWasmChanges),
- stringTracker(_wasm) {}
-
- void noteNonLinear(Expression* curr);
-
- void visitLocalSet(LocalSet* curr);
- void visitCall(Call* curr);
-
- void process();
-
-private:
- void createAsmConst(uint64_t id, std::string code);
- void addImports();
-
- std::vector<std::unique_ptr<Function>> queuedImports;
-};
-
-void AsmConstWalker::noteNonLinear(Expression* curr) {
- // End of this basic block; clear sets.
- sets.clear();
-}
-
-void AsmConstWalker::visitLocalSet(LocalSet* curr) { sets[curr->index] = curr; }
-
-void AsmConstWalker::visitCall(Call* curr) {
- auto* import = wasm.getFunction(curr->target);
- // Find calls to emscripten_asm_const* functions whose first argument is
- // is always a string constant.
- if (!import->imported()) {
- return;
- }
- auto importName = import->base;
- if (!importName.hasSubstring(EM_ASM_PREFIX)) {
- return;
- }
-
- auto* arg = curr->operands[0];
- while (!arg->dynCast<Const>()) {
- if (auto* get = arg->dynCast<LocalGet>()) {
- // The argument may be a local.get, in which case, the last set in this
- // basic block has the value.
- auto* set = sets[get->index];
- if (set) {
- assert(set->index == get->index);
- arg = set->value;
- } else {
- Fatal() << "local.get of unknown in arg0 of call to " << importName
- << " (used by EM_ASM* macros) in function "
- << getFunction()->name
- << ".\nThis might be caused by aggressive compiler "
- "transformations. Consider using EM_JS instead.";
- }
- continue;
- }
-
- if (auto* setlocal = arg->dynCast<LocalSet>()) {
- // The argument may be a local.tee, in which case we take first child
- // which is the value being copied into the local.
- if (setlocal->isTee()) {
- arg = setlocal->value;
- continue;
- }
- }
-
- if (auto* bin = arg->dynCast<Binary>()) {
- if (bin->op == AddInt32 || bin->op == AddInt64) {
- // In the dynamic linking case the address of the string constant
- // is the result of adding its offset to __memory_base.
- // In this case are only looking for the offset from __memory_base
- // the RHS of the addition is just what we want.
- arg = bin->right;
- continue;
- }
- }
-
- if (auto* unary = arg->dynCast<Unary>()) {
- if (unary->op == WrapInt64) {
- // This cast may be inserted around the string constant in the
- // Memory64Lowering pass.
- arg = unary->value;
- continue;
- }
- }
-
- Fatal() << "Unexpected arg0 type (" << *arg
- << ") in call to: " << importName;
- }
-
- auto* value = arg->cast<Const>();
- Address address = value->value.getUnsigned();
- asmConsts.push_back({address, stringTracker.stringAtAddr(address)});
-}
-
-void AsmConstWalker::process() {
- // Find and queue necessary imports
- walkModule(&wasm);
- // Add them after the walk, to avoid iterator invalidation on
- // the list of functions.
- addImports();
-}
-
-void AsmConstWalker::addImports() {
- for (auto& import : queuedImports) {
- wasm.addFunction(import.release());
- }
-}
-
struct SegmentRemover : WalkerPass<PostWalker<SegmentRemover>> {
SegmentRemover(Index segment) : segment(segment) {}
@@ -345,22 +228,21 @@ static Address getExportedAddress(Module& wasm, Export* export_) {
static std::vector<AsmConst> findEmAsmConsts(Module& wasm,
bool minimizeWasmChanges) {
+ // Newer version of emscripten/llvm export these symbols so we can use them to
+ // find all the EM_ASM constants. Sadly __start_em_asm and __stop_em_asm
+ // don't alwasy mark the start and end of segment because in dynamic linking
+ // we merge all data segments into one.
Export* start = wasm.getExportOrNull("__start_em_asm");
Export* end = wasm.getExportOrNull("__stop_em_asm");
+ if (!start && !end) {
+ BYN_TRACE("findEmAsmConsts: no start/stop symbols\n");
+ return {};
+ }
- // Older versions of emscripten don't export these symbols. Instead
- // we run AsmConstWalker in an attempt to derive the string addresses
- // from the code.
if (!start || !end) {
- AsmConstWalker walker(wasm, minimizeWasmChanges);
- walker.process();
- return walker.asmConsts;
+ Fatal() << "Found only one of __start_em_asm and __stop_em_asm";
}
- // Newer version of emscripten export this symbols and we
- // can use it ot find all the EM_ASM constants. Sadly __start_em_asm and
- // __stop_em_asm don't alwasy mark the start and end of segment because in
- // dynamic linking we merge all data segments into one.
std::vector<AsmConst> asmConsts;
StringConstantTracker stringTracker(wasm);
Address startAddress = getExportedAddress(wasm, start);
diff --git a/test/lit/wasm-emscripten-finalize/passive-pic.wat b/test/lit/wasm-emscripten-finalize/passive-pic.wat
index 14e6842a3..8b6ccb6d4 100644
--- a/test/lit/wasm-emscripten-finalize/passive-pic.wat
+++ b/test/lit/wasm-emscripten-finalize/passive-pic.wat
@@ -12,6 +12,8 @@
(import "env" "__memory_base" (global $__memory_base i32))
(import "env" "emscripten_asm_const_int" (func $emscripten_asm_const_int (param i32 i32 i32) (result i32)))
(data passive "xxxhello\00yyy")
+ (global (export "__start_em_asm") i32 (i32.const 3))
+ (global (export "__stop_em_asm") i32 (i32.const 9))
;; memory init function similar to those generated by wasm-ld
(start $__wasm_init_memory)
(func $__wasm_init_memory
diff --git a/test/lld/em_asm_main_thread.wat b/test/lld/em_asm_main_thread.wat
index 0435e9be0..65f530d69 100644
--- a/test/lld/em_asm_main_thread.wat
+++ b/test/lld/em_asm_main_thread.wat
@@ -12,6 +12,8 @@
(import "env" "emscripten_asm_const_int_sync_on_main_thread" (func $emscripten_asm_const_int_sync_on_main_thread (param i32 i32 i32) (result i32)))
(memory $0 2)
(data (i32.const 568) "{ Module.print(\"Hello world\"); }\00{ return $0 + $1; }\00{ Module.print(\"Got \" + $0); }\00")
+ (global (export "__start_em_asm") i32 (i32.const 568))
+ (global (export "__stop_em_asm") i32 (i32.const 652))
(table $0 1 1 funcref)
(global $global$0 (mut i32) (i32.const 66192))
(global $global$1 i32 (i32.const 66192))
diff --git a/test/lld/em_asm_main_thread.wat.out b/test/lld/em_asm_main_thread.wat.out
index 8fc99e081..91a022dbc 100644
--- a/test/lld/em_asm_main_thread.wat.out
+++ b/test/lld/em_asm_main_thread.wat.out
@@ -8,8 +8,10 @@
(type $0 (func (param i32 i32 i32) (result i32)))
(import "env" "emscripten_asm_const_int_sync_on_main_thread" (func $emscripten_asm_const_int_sync_on_main_thread (param i32 i32 i32) (result i32)))
(memory $0 2)
- (data (i32.const 568) "{ Module.print(\"Hello world\"); }\00{ return $0 + $1; }\00{ Module.print(\"Got \" + $0); }\00")
+ (data (i32.const 568) "")
(table $0 1 1 funcref)
+ (global $0 i32 (i32.const 568))
+ (global $1 i32 (i32.const 652))
(global $global$0 (mut i32) (i32.const 66192))
(global $global$1 i32 (i32.const 66192))
(global $global$2 i32 (i32.const 652))
diff --git a/test/unit/input/em_asm_mangled_string.wat b/test/unit/input/em_asm_mangled_string.wat
deleted file mode 100644
index aa856270d..000000000
--- a/test/unit/input/em_asm_mangled_string.wat
+++ /dev/null
@@ -1,11 +0,0 @@
-(module
- (import "env" "emscripten_asm_const_int" (func $emscripten_asm_const_int (param i32 i32 i32) (result i32)))
- (global $global$0 (mut i32) (i32.const 66192))
- (global $global$1 i32 (i32.const 652))
- (export "__data_end" (global $global$1))
- (export "main" (func $main))
- (func $main (param $0 i32) (param $1 i32) (result i32)
- (drop (call $emscripten_asm_const_int (local.get $0) (i32.const 0) (i32.const 0)))
- (i32.const 0)
- )
-)
diff --git a/test/unit/test_finalize.py b/test/unit/test_finalize.py
index b393177bd..6733155cb 100644
--- a/test/unit/test_finalize.py
+++ b/test/unit/test_finalize.py
@@ -1,18 +1,8 @@
-import os
-
from scripts.test import shared
from . import utils
class EmscriptenFinalizeTest(utils.BinaryenTestCase):
- def test_em_asm_mangled_string(self):
- p = shared.run_process(shared.WASM_EMSCRIPTEN_FINALIZE + [
- self.input_path('em_asm_mangled_string.wat'), '-o', os.devnull, '--global-base=1024'
- ], check=False, capture_output=True)
- self.assertNotEqual(p.returncode, 0)
- self.assertIn('Fatal: local.get of unknown in arg0 of call to emscripten_asm_const_int (used by EM_ASM* macros) in function main.', p.stderr)
- self.assertIn('This might be caused by aggressive compiler transformations. Consider using EM_JS instead.', p.stderr)
-
def do_output_test(self, args):
# without any output file specified, don't error, don't write the wasm,
# but do emit metadata