summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2024-06-13 12:03:09 -0700
committerGitHub <noreply@github.com>2024-06-13 12:03:09 -0700
commit000fa2a8ac8dd66b8ca53b0451702966d59da4d0 (patch)
tree88d0c406ee7bd11da5b800bfaff2bd7b1807b093
parent66610d84bc466d0826803d8e2951af48ca2f1bae (diff)
downloadbinaryen-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.h67
-rw-r--r--test/wasm2js/refs.2asm.js12
-rw-r--r--test/wasm2js/refs.2asm.js.opt12
-rw-r--r--test/wasm2js/refs.wast13
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)
+ )
)