diff options
author | Alon Zakai <azakai@google.com> | 2024-06-13 12:03:09 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-13 12:03:09 -0700 |
commit | 000fa2a8ac8dd66b8ca53b0451702966d59da4d0 (patch) | |
tree | 88d0c406ee7bd11da5b800bfaff2bd7b1807b093 | |
parent | 66610d84bc466d0826803d8e2951af48ca2f1bae (diff) | |
download | binaryen-000fa2a8ac8dd66b8ca53b0451702966d59da4d0.tar.gz binaryen-000fa2a8ac8dd66b8ca53b0451702966d59da4d0.tar.bz2 binaryen-000fa2a8ac8dd66b8ca53b0451702966d59da4d0.zip |
wasm2js: Generalize global initializer code to use the main codegen logic (#6659)
This avoids special-casing particular global init forms. After this we should
support everything in global inits that we support anywhere else.
-rw-r--r-- | src/wasm2js.h | 67 | ||||
-rw-r--r-- | test/wasm2js/refs.2asm.js | 12 | ||||
-rw-r--r-- | test/wasm2js/refs.2asm.js.opt | 12 | ||||
-rw-r--r-- | test/wasm2js/refs.wast | 13 |
4 files changed, 54 insertions, 50 deletions
diff --git a/src/wasm2js.h b/src/wasm2js.h index 034212b79..34260547d 100644 --- a/src/wasm2js.h +++ b/src/wasm2js.h @@ -192,7 +192,10 @@ public: // The second pass on an expression: process it fully, generating // JS - Ref processFunctionBody(Module* m, Function* func, bool standalone); + Ref processExpression(Expression* curr, + Module* m, + Function* func = nullptr, + bool standalone = false); Index getDataIndex(Name segment) { auto it = dataIndices.find(segment); @@ -323,7 +326,7 @@ private: void addTable(Ref ast, Module* wasm); void addStart(Ref ast, Module* wasm); void addExports(Ref ast, Module* wasm); - void addGlobal(Ref ast, Global* global); + void addGlobal(Ref ast, Global* global, Module* module); void addMemoryFuncs(Ref ast, Module* wasm); void addMemoryGrowFunc(Ref ast, Module* wasm); @@ -503,7 +506,7 @@ Ref Wasm2JSBuilder::processWasm(Module* wasm, Name funcName) { // globals bool generateFetchHighBits = false; ModuleUtils::iterDefinedGlobals(*wasm, [&](Global* global) { - addGlobal(asmFunc[3], global); + addGlobal(asmFunc[3], global, wasm); if (flags.allowAsserts && global->name == INT64_TO_32_HIGH_BITS) { generateFetchHighBits = true; } @@ -845,46 +848,12 @@ void Wasm2JSBuilder::addExports(Ref ast, Module* wasm) { ValueBuilder::makeStatement(ValueBuilder::makeReturn(exports))); } -void Wasm2JSBuilder::addGlobal(Ref ast, Global* global) { +void Wasm2JSBuilder::addGlobal(Ref ast, Global* global, Module* module) { Ref theVar = ValueBuilder::makeVar(); ast->push_back(theVar); - - auto* init = global->init; - Ref value; - - if (auto* const_ = init->dynCast<Const>()) { - TODO_SINGLE_COMPOUND(const_->type); - switch (const_->type.getBasic()) { - case Type::i32: { - value = ValueBuilder::makeInt(const_->value.geti32()); - break; - } - case Type::f32: { - value = ValueBuilder::makeCall( - MATH_FROUND, - makeJsCoercion(ValueBuilder::makeDouble(const_->value.getf32()), - JS_DOUBLE)); - break; - } - case Type::f64: { - value = makeJsCoercion(ValueBuilder::makeDouble(const_->value.getf64()), - JS_DOUBLE); - break; - } - default: { - assert(false && "Top const type not supported"); - } - } - } else if (auto* get = init->dynCast<GlobalGet>()) { - value = ValueBuilder::makeName(fromName(get->name, NameScope::Top)); - } else if (init->is<RefNull>()) { - value = ValueBuilder::makeName(NULL_); - } else { - assert(false && "Top init type not supported"); - } - + Ref init = processExpression(global->init, module); ValueBuilder::appendToVar( - theVar, fromName(global->name, NameScope::Top), value); + theVar, fromName(global->name, NameScope::Top), init); } Ref Wasm2JSBuilder::processFunction(Module* m, @@ -934,7 +903,8 @@ Ref Wasm2JSBuilder::processFunction(Module* m, size_t theVarIndex = ret[3]->size(); ret[3]->push_back(theVar); // body - flattenAppend(ret, processFunctionBody(m, func, standaloneFunction)); + flattenAppend(ret, + processExpression(func->body, m, func, standaloneFunction)); // vars, including new temp vars for (Index i = func->getVarIndexBase(); i < func->getNumLocals(); i++) { ValueBuilder::appendToVar( @@ -952,9 +922,10 @@ Ref Wasm2JSBuilder::processFunction(Module* m, return ret; } -Ref Wasm2JSBuilder::processFunctionBody(Module* m, - Function* func, - bool standaloneFunction) { +Ref Wasm2JSBuilder::processExpression(Expression* curr, + Module* m, + Function* func, + bool standaloneFunction) { // Switches are tricky to handle - in wasm they often come with // massively-nested "towers" of blocks, which if naively translated // to JS may exceed parse recursion limits of VMs. Therefore even when @@ -1092,9 +1063,9 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, : parent(parent), func(func), module(m), standaloneFunction(standaloneFunction) {} - Ref process() { - switchProcessor.walk(func->body); - return visit(func->body, NO_RESULT); + Ref process(Expression* curr) { + switchProcessor.walk(curr); + return visit(curr, NO_RESULT); } // A scoped temporary variable. @@ -2460,7 +2431,7 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, } }; - return ExpressionProcessor(this, m, func, standaloneFunction).process(); + return ExpressionProcessor(this, m, func, standaloneFunction).process(curr); } void Wasm2JSBuilder::addMemoryFuncs(Ref ast, Module* wasm) { diff --git a/test/wasm2js/refs.2asm.js b/test/wasm2js/refs.2asm.js index f538df6d6..f1d60af6c 100644 --- a/test/wasm2js/refs.2asm.js +++ b/test/wasm2js/refs.2asm.js @@ -13,6 +13,7 @@ function asmFunc(imports) { var Math_trunc = Math.trunc; var Math_sqrt = Math.sqrt; var global = null; + var global_ref = use_global_ref; function null_() { return null; } @@ -42,13 +43,21 @@ function asmFunc(imports) { return temp; } + function use_global_ref(x) { + var temp = null; + temp = global_ref; + global_ref = x; + return temp; + } + return { "null_": null_, "is_null": is_null, "ref_func": ref_func, "ref_eq": ref_eq, "ref_as": ref_as, - "use_global": use_global + "use_global": use_global, + "use_global_ref": use_global_ref }; } @@ -60,3 +69,4 @@ export var ref_func = retasmFunc.ref_func; export var ref_eq = retasmFunc.ref_eq; export var ref_as = retasmFunc.ref_as; export var use_global = retasmFunc.use_global; +export var use_global_ref = retasmFunc.use_global_ref; diff --git a/test/wasm2js/refs.2asm.js.opt b/test/wasm2js/refs.2asm.js.opt index 251e63475..fa1947215 100644 --- a/test/wasm2js/refs.2asm.js.opt +++ b/test/wasm2js/refs.2asm.js.opt @@ -13,6 +13,7 @@ function asmFunc(imports) { var Math_trunc = Math.trunc; var Math_sqrt = Math.sqrt; var global = null; + var global_ref = use_global_ref; function null_() { return null; } @@ -40,13 +41,21 @@ function asmFunc(imports) { return $1; } + function use_global_ref($0) { + var $1 = null; + $1 = global_ref; + global_ref = $0; + return $1; + } + return { "null_": null_, "is_null": is_null, "ref_func": ref_func, "ref_eq": ref_eq, "ref_as": ref_as, - "use_global": use_global + "use_global": use_global, + "use_global_ref": use_global_ref }; } @@ -58,3 +67,4 @@ export var ref_func = retasmFunc.ref_func; export var ref_eq = retasmFunc.ref_eq; export var ref_as = retasmFunc.ref_as; export var use_global = retasmFunc.use_global; +export var use_global_ref = retasmFunc.use_global_ref; diff --git a/test/wasm2js/refs.wast b/test/wasm2js/refs.wast index 964d0a60c..244cf2e97 100644 --- a/test/wasm2js/refs.wast +++ b/test/wasm2js/refs.wast @@ -1,6 +1,8 @@ (module (global $global (mut anyref) (ref.null any)) + (global $global-ref (mut funcref) (ref.func $use-global-ref)) + (func $null (export "null") (result anyref) (ref.null any) ) @@ -49,4 +51,15 @@ ) (local.get $temp) ) + + (func $use-global-ref (export "use-global-ref") (param $x funcref) (result funcref) + (local $temp funcref) + (local.set $temp + (global.get $global-ref) + ) + (global.set $global-ref + (local.get $x) + ) + (local.get $temp) + ) ) |