Skip to content

Commit 000fa2a

Browse files
authored
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.
1 parent 66610d8 commit 000fa2a

File tree

4 files changed

+54
-50
lines changed

4 files changed

+54
-50
lines changed

src/wasm2js.h

Lines changed: 19 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,10 @@ class Wasm2JSBuilder {
192192

193193
// The second pass on an expression: process it fully, generating
194194
// JS
195-
Ref processFunctionBody(Module* m, Function* func, bool standalone);
195+
Ref processExpression(Expression* curr,
196+
Module* m,
197+
Function* func = nullptr,
198+
bool standalone = false);
196199

197200
Index getDataIndex(Name segment) {
198201
auto it = dataIndices.find(segment);
@@ -323,7 +326,7 @@ class Wasm2JSBuilder {
323326
void addTable(Ref ast, Module* wasm);
324327
void addStart(Ref ast, Module* wasm);
325328
void addExports(Ref ast, Module* wasm);
326-
void addGlobal(Ref ast, Global* global);
329+
void addGlobal(Ref ast, Global* global, Module* module);
327330
void addMemoryFuncs(Ref ast, Module* wasm);
328331
void addMemoryGrowFunc(Ref ast, Module* wasm);
329332

@@ -503,7 +506,7 @@ Ref Wasm2JSBuilder::processWasm(Module* wasm, Name funcName) {
503506
// globals
504507
bool generateFetchHighBits = false;
505508
ModuleUtils::iterDefinedGlobals(*wasm, [&](Global* global) {
506-
addGlobal(asmFunc[3], global);
509+
addGlobal(asmFunc[3], global, wasm);
507510
if (flags.allowAsserts && global->name == INT64_TO_32_HIGH_BITS) {
508511
generateFetchHighBits = true;
509512
}
@@ -845,46 +848,12 @@ void Wasm2JSBuilder::addExports(Ref ast, Module* wasm) {
845848
ValueBuilder::makeStatement(ValueBuilder::makeReturn(exports)));
846849
}
847850

848-
void Wasm2JSBuilder::addGlobal(Ref ast, Global* global) {
851+
void Wasm2JSBuilder::addGlobal(Ref ast, Global* global, Module* module) {
849852
Ref theVar = ValueBuilder::makeVar();
850853
ast->push_back(theVar);
851-
852-
auto* init = global->init;
853-
Ref value;
854-
855-
if (auto* const_ = init->dynCast<Const>()) {
856-
TODO_SINGLE_COMPOUND(const_->type);
857-
switch (const_->type.getBasic()) {
858-
case Type::i32: {
859-
value = ValueBuilder::makeInt(const_->value.geti32());
860-
break;
861-
}
862-
case Type::f32: {
863-
value = ValueBuilder::makeCall(
864-
MATH_FROUND,
865-
makeJsCoercion(ValueBuilder::makeDouble(const_->value.getf32()),
866-
JS_DOUBLE));
867-
break;
868-
}
869-
case Type::f64: {
870-
value = makeJsCoercion(ValueBuilder::makeDouble(const_->value.getf64()),
871-
JS_DOUBLE);
872-
break;
873-
}
874-
default: {
875-
assert(false && "Top const type not supported");
876-
}
877-
}
878-
} else if (auto* get = init->dynCast<GlobalGet>()) {
879-
value = ValueBuilder::makeName(fromName(get->name, NameScope::Top));
880-
} else if (init->is<RefNull>()) {
881-
value = ValueBuilder::makeName(NULL_);
882-
} else {
883-
assert(false && "Top init type not supported");
884-
}
885-
854+
Ref init = processExpression(global->init, module);
886855
ValueBuilder::appendToVar(
887-
theVar, fromName(global->name, NameScope::Top), value);
856+
theVar, fromName(global->name, NameScope::Top), init);
888857
}
889858

890859
Ref Wasm2JSBuilder::processFunction(Module* m,
@@ -934,7 +903,8 @@ Ref Wasm2JSBuilder::processFunction(Module* m,
934903
size_t theVarIndex = ret[3]->size();
935904
ret[3]->push_back(theVar);
936905
// body
937-
flattenAppend(ret, processFunctionBody(m, func, standaloneFunction));
906+
flattenAppend(ret,
907+
processExpression(func->body, m, func, standaloneFunction));
938908
// vars, including new temp vars
939909
for (Index i = func->getVarIndexBase(); i < func->getNumLocals(); i++) {
940910
ValueBuilder::appendToVar(
@@ -952,9 +922,10 @@ Ref Wasm2JSBuilder::processFunction(Module* m,
952922
return ret;
953923
}
954924

955-
Ref Wasm2JSBuilder::processFunctionBody(Module* m,
956-
Function* func,
957-
bool standaloneFunction) {
925+
Ref Wasm2JSBuilder::processExpression(Expression* curr,
926+
Module* m,
927+
Function* func,
928+
bool standaloneFunction) {
958929
// Switches are tricky to handle - in wasm they often come with
959930
// massively-nested "towers" of blocks, which if naively translated
960931
// to JS may exceed parse recursion limits of VMs. Therefore even when
@@ -1092,9 +1063,9 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
10921063
: parent(parent), func(func), module(m),
10931064
standaloneFunction(standaloneFunction) {}
10941065

1095-
Ref process() {
1096-
switchProcessor.walk(func->body);
1097-
return visit(func->body, NO_RESULT);
1066+
Ref process(Expression* curr) {
1067+
switchProcessor.walk(curr);
1068+
return visit(curr, NO_RESULT);
10981069
}
10991070

11001071
// A scoped temporary variable.
@@ -2460,7 +2431,7 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m,
24602431
}
24612432
};
24622433

2463-
return ExpressionProcessor(this, m, func, standaloneFunction).process();
2434+
return ExpressionProcessor(this, m, func, standaloneFunction).process(curr);
24642435
}
24652436

24662437
void Wasm2JSBuilder::addMemoryFuncs(Ref ast, Module* wasm) {

test/wasm2js/refs.2asm.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ function asmFunc(imports) {
1313
var Math_trunc = Math.trunc;
1414
var Math_sqrt = Math.sqrt;
1515
var global = null;
16+
var global_ref = use_global_ref;
1617
function null_() {
1718
return null;
1819
}
@@ -42,13 +43,21 @@ function asmFunc(imports) {
4243
return temp;
4344
}
4445

46+
function use_global_ref(x) {
47+
var temp = null;
48+
temp = global_ref;
49+
global_ref = x;
50+
return temp;
51+
}
52+
4553
return {
4654
"null_": null_,
4755
"is_null": is_null,
4856
"ref_func": ref_func,
4957
"ref_eq": ref_eq,
5058
"ref_as": ref_as,
51-
"use_global": use_global
59+
"use_global": use_global,
60+
"use_global_ref": use_global_ref
5261
};
5362
}
5463

@@ -60,3 +69,4 @@ export var ref_func = retasmFunc.ref_func;
6069
export var ref_eq = retasmFunc.ref_eq;
6170
export var ref_as = retasmFunc.ref_as;
6271
export var use_global = retasmFunc.use_global;
72+
export var use_global_ref = retasmFunc.use_global_ref;

test/wasm2js/refs.2asm.js.opt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ function asmFunc(imports) {
1313
var Math_trunc = Math.trunc;
1414
var Math_sqrt = Math.sqrt;
1515
var global = null;
16+
var global_ref = use_global_ref;
1617
function null_() {
1718
return null;
1819
}
@@ -40,13 +41,21 @@ function asmFunc(imports) {
4041
return $1;
4142
}
4243

44+
function use_global_ref($0) {
45+
var $1 = null;
46+
$1 = global_ref;
47+
global_ref = $0;
48+
return $1;
49+
}
50+
4351
return {
4452
"null_": null_,
4553
"is_null": is_null,
4654
"ref_func": ref_func,
4755
"ref_eq": ref_eq,
4856
"ref_as": ref_as,
49-
"use_global": use_global
57+
"use_global": use_global,
58+
"use_global_ref": use_global_ref
5059
};
5160
}
5261

@@ -58,3 +67,4 @@ export var ref_func = retasmFunc.ref_func;
5867
export var ref_eq = retasmFunc.ref_eq;
5968
export var ref_as = retasmFunc.ref_as;
6069
export var use_global = retasmFunc.use_global;
70+
export var use_global_ref = retasmFunc.use_global_ref;

test/wasm2js/refs.wast

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
(module
22
(global $global (mut anyref) (ref.null any))
33

4+
(global $global-ref (mut funcref) (ref.func $use-global-ref))
5+
46
(func $null (export "null") (result anyref)
57
(ref.null any)
68
)
@@ -49,4 +51,15 @@
4951
)
5052
(local.get $temp)
5153
)
54+
55+
(func $use-global-ref (export "use-global-ref") (param $x funcref) (result funcref)
56+
(local $temp funcref)
57+
(local.set $temp
58+
(global.get $global-ref)
59+
)
60+
(global.set $global-ref
61+
(local.get $x)
62+
)
63+
(local.get $temp)
64+
)
5265
)

0 commit comments

Comments
 (0)