summaryrefslogtreecommitdiff
path: root/src/wasm2js.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm2js.h')
-rw-r--r--src/wasm2js.h1022
1 files changed, 491 insertions, 531 deletions
diff --git a/src/wasm2js.h b/src/wasm2js.h
index be794decb..515b9335a 100644
--- a/src/wasm2js.h
+++ b/src/wasm2js.h
@@ -25,16 +25,11 @@
#include <cmath>
#include <numeric>
-#include "asmjs/shared-constants.h"
+#include "abi/js.h"
+#include "asm_v_wasm.h"
#include "asmjs/asmangle.h"
-#include "wasm.h"
-#include "wasm-builder.h"
-#include "wasm-io.h"
-#include "wasm-validator.h"
+#include "asmjs/shared-constants.h"
#include "emscripten-optimizer/optimizer.h"
-#include "mixed_arena.h"
-#include "asm_v_wasm.h"
-#include "abi/js.h"
#include "ir/effects.h"
#include "ir/find_all.h"
#include "ir/import-utils.h"
@@ -43,25 +38,34 @@
#include "ir/names.h"
#include "ir/table-utils.h"
#include "ir/utils.h"
+#include "mixed_arena.h"
#include "passes/passes.h"
#include "support/base64.h"
+#include "wasm-builder.h"
+#include "wasm-io.h"
+#include "wasm-validator.h"
+#include "wasm.h"
namespace wasm {
using namespace cashew;
-IString ASM_FUNC("asmFunc"),
- ABORT_FUNC("abort"),
- FUNCTION_TABLE("FUNCTION_TABLE"),
- NO_RESULT("wasm2js$noresult"), // no result at all
- EXPRESSION_RESULT("wasm2js$expresult"); // result in an expression, no temp var
+IString ASM_FUNC("asmFunc");
+IString ABORT_FUNC("abort");
+IString FUNCTION_TABLE("FUNCTION_TABLE");
+IString NO_RESULT("wasm2js$noresult"); // no result at all
+// result in an expression, no temp var
+IString EXPRESSION_RESULT("wasm2js$expresult");
// Appends extra to block, flattening out if extra is a block as well
void flattenAppend(Ref ast, Ref extra) {
int index;
- if (ast[0] == BLOCK || ast[0] == TOPLEVEL) index = 1;
- else if (ast[0] == DEFUN) index = 3;
- else abort();
+ if (ast[0] == BLOCK || ast[0] == TOPLEVEL)
+ index = 1;
+ else if (ast[0] == DEFUN)
+ index = 3;
+ else
+ abort();
if (extra->isArray() && extra[0] == BLOCK) {
for (size_t i = 0; i < extra[1]->size(); i++) {
ast[index]->push_back(extra[1][i]);
@@ -80,9 +84,7 @@ void sequenceAppend(Ref& ast, Ref extra) {
ast = ValueBuilder::makeSeq(ast, extra);
}
-IString stringToIString(std::string str) {
- return IString(str.c_str(), false);
-}
+IString stringToIString(std::string str) { return IString(str.c_str(), false); }
// Used when taking a wasm name and generating a JS identifier. Each scope here
// is used to ensure that all names have a unique name but the same wasm name
@@ -124,7 +126,7 @@ public:
Wasm2JSBuilder(Flags f, PassOptions options) : flags(f), options(options) {}
Ref processWasm(Module* wasm, Name funcName = ASM_FUNC);
- Ref processFunction(Module* wasm, Function* func, bool standalone=false);
+ Ref processFunction(Module* wasm, Function* func, bool standalone = false);
Ref processStandaloneFunction(Module* wasm, Function* func) {
return processFunction(wasm, func, true);
}
@@ -142,7 +144,9 @@ public:
} else {
size_t index = temps[type]++;
ret = IString((std::string("wasm2js_") + printType(type) + "$" +
- std::to_string(index)).c_str(), false);
+ std::to_string(index))
+ .c_str(),
+ false);
}
if (func->localIndices.find(ret) == func->localIndices.end()) {
Builder::addVar(func, ret, type);
@@ -151,9 +155,7 @@ public:
}
// Free a temp var.
- void freeTemp(Type type, IString temp) {
- frees[type].push_back(temp);
- }
+ void freeTemp(Type type, IString temp) { frees[type].push_back(temp); }
// Generates a mangled name from `name` within the specified scope.
//
@@ -170,7 +172,7 @@ public:
// First up check our cached of mangled names to avoid doing extra work
// below
- auto &mangledScope = mangledNames[(int) scope];
+ auto& mangledScope = mangledNames[(int)scope];
auto it = mangledScope.find(name.c_str());
if (it != mangledScope.end()) {
return it->second;
@@ -200,13 +202,15 @@ public:
// it's a bug currently if they're not globally unique. This should
// probably be fixed via a different namespace for exports or something
// like that.
- // XXX This is not actually a valid check atm, since functions are not in the
- // global-most scope, but rather in the "asmFunc" scope which is inside it.
- // Also, for emscripten style glue, we emit the exports as a return, so there
- // is no name placed into the scope. For these reasons, just warn here, don't
- // error.
+ // XXX This is not actually a valid check atm, since functions are not in
+ // the global-most scope, but rather in the "asmFunc" scope which is
+ // inside it. Also, for emscripten style glue, we emit the exports as
+ // a return, so there is no name placed into the scope. For these
+ // reasons, just warn here, don't error.
if (scope == NameScope::Top) {
- std::cerr << "wasm2js: warning: global scope may be colliding with other scope: " << mangled << '\n';
+ std::cerr << "wasm2js: warning: global scope may be colliding with "
+ "other scope: "
+ << mangled << '\n';
}
}
allMangledNames.insert(ret);
@@ -225,7 +229,7 @@ private:
// Mangled names cache by interned names.
// Utilizes the usually reused underlying cstring's pointer as the key.
- std::unordered_map<const char*, IString> mangledNames[(int) NameScope::Max];
+ std::unordered_map<const char*, IString> mangledNames[(int)NameScope::Max];
std::unordered_set<IString> allMangledNames;
// If a function is callable from outside, we'll need to cast the inputs
@@ -242,8 +246,8 @@ private:
void addMemoryGrowthFuncs(Ref ast, Module* wasm);
Wasm2JSBuilder() = delete;
- Wasm2JSBuilder(const Wasm2JSBuilder &) = delete;
- Wasm2JSBuilder &operator=(const Wasm2JSBuilder&) = delete;
+ Wasm2JSBuilder(const Wasm2JSBuilder&) = delete;
+ Wasm2JSBuilder& operator=(const Wasm2JSBuilder&) = delete;
};
Ref Wasm2JSBuilder::processWasm(Module* wasm, Name funcName) {
@@ -299,27 +303,24 @@ Ref Wasm2JSBuilder::processWasm(Module* wasm, Name funcName) {
ValueBuilder::appendArgumentToFunction(asmFunc, GLOBAL);
ValueBuilder::appendArgumentToFunction(asmFunc, ENV);
ValueBuilder::appendArgumentToFunction(asmFunc, BUFFER);
- asmFunc[3]->push_back(ValueBuilder::makeStatement(ValueBuilder::makeString(ALMOST_ASM)));
+ asmFunc[3]->push_back(
+ ValueBuilder::makeStatement(ValueBuilder::makeString(ALMOST_ASM)));
// add memory import
if (wasm->memory.exists && wasm->memory.imported()) {
Ref theVar = ValueBuilder::makeVar();
asmFunc[3]->push_back(theVar);
- ValueBuilder::appendToVar(theVar,
+ ValueBuilder::appendToVar(
+ theVar,
"memory",
- ValueBuilder::makeDot(
- ValueBuilder::makeName(ENV),
- ValueBuilder::makeName("memory")
- )
- );
+ ValueBuilder::makeDot(ValueBuilder::makeName(ENV),
+ ValueBuilder::makeName("memory")));
}
// create heaps, etc
addBasics(asmFunc[3]);
- ModuleUtils::iterImportedFunctions(*wasm, [&](Function* import) {
- addFunctionImport(asmFunc[3], import);
- });
- ModuleUtils::iterImportedGlobals(*wasm, [&](Global* import) {
- addGlobalImport(asmFunc[3], import);
- });
+ ModuleUtils::iterImportedFunctions(
+ *wasm, [&](Function* import) { addFunctionImport(asmFunc[3], import); });
+ ModuleUtils::iterImportedGlobals(
+ *wasm, [&](Global* import) { addGlobalImport(asmFunc[3], import); });
// make sure exports get their expected names
for (auto& e : wasm->exports) {
@@ -350,13 +351,14 @@ Ref Wasm2JSBuilder::processWasm(Module* wasm, Name funcName) {
Builder builder(allocator);
std::vector<Type> params;
std::vector<Type> vars;
- asmFunc[3]->push_back(processFunction(wasm, builder.makeFunction(
- WASM_FETCH_HIGH_BITS,
- std::move(params),
- i32,
- std::move(vars),
- builder.makeReturn(builder.makeGetGlobal(INT64_TO_32_HIGH_BITS, i32))
- )));
+ asmFunc[3]->push_back(processFunction(
+ wasm,
+ builder.makeFunction(WASM_FETCH_HIGH_BITS,
+ std::move(params),
+ i32,
+ std::move(vars),
+ builder.makeReturn(builder.makeGetGlobal(
+ INT64_TO_32_HIGH_BITS, i32)))));
auto e = new Export();
e->name = WASM_FETCH_HIGH_BITS;
e->value = WASM_FETCH_HIGH_BITS;
@@ -378,23 +380,17 @@ void Wasm2JSBuilder::addBasics(Ref ast) {
auto addHeap = [&](IString name, IString view) {
Ref theVar = ValueBuilder::makeVar();
ast->push_back(theVar);
- ValueBuilder::appendToVar(theVar,
+ ValueBuilder::appendToVar(
+ theVar,
name,
- ValueBuilder::makeNew(
- ValueBuilder::makeCall(
- ValueBuilder::makeDot(
- ValueBuilder::makeName(GLOBAL),
- view
- ),
- ValueBuilder::makeName(BUFFER)
- )
- )
- );
+ ValueBuilder::makeNew(ValueBuilder::makeCall(
+ ValueBuilder::makeDot(ValueBuilder::makeName(GLOBAL), view),
+ ValueBuilder::makeName(BUFFER))));
};
- addHeap(HEAP8, INT8ARRAY);
+ addHeap(HEAP8, INT8ARRAY);
addHeap(HEAP16, INT16ARRAY);
addHeap(HEAP32, INT32ARRAY);
- addHeap(HEAPU8, UINT8ARRAY);
+ addHeap(HEAPU8, UINT8ARRAY);
addHeap(HEAPU16, UINT16ARRAY);
addHeap(HEAPU32, UINT32ARRAY);
addHeap(HEAPF32, FLOAT32ARRAY);
@@ -403,16 +399,11 @@ void Wasm2JSBuilder::addBasics(Ref ast) {
auto addMath = [&](IString name, IString base) {
Ref theVar = ValueBuilder::makeVar();
ast->push_back(theVar);
- ValueBuilder::appendToVar(theVar,
+ ValueBuilder::appendToVar(
+ theVar,
name,
ValueBuilder::makeDot(
- ValueBuilder::makeDot(
- ValueBuilder::makeName(GLOBAL),
- MATH
- ),
- base
- )
- );
+ ValueBuilder::makeDot(ValueBuilder::makeName(GLOBAL), MATH), base));
};
addMath(MATH_IMUL, IMUL);
addMath(MATH_FROUND, FROUND);
@@ -426,61 +417,54 @@ void Wasm2JSBuilder::addBasics(Ref ast) {
// abort function
Ref abortVar = ValueBuilder::makeVar();
ast->push_back(abortVar);
- ValueBuilder::appendToVar(abortVar,
+ ValueBuilder::appendToVar(
+ abortVar,
"abort",
- ValueBuilder::makeDot(
- ValueBuilder::makeName(ENV),
- ABORT_FUNC
- )
- );
+ ValueBuilder::makeDot(ValueBuilder::makeName(ENV), ABORT_FUNC));
// TODO: this shouldn't be needed once we stop generating literal asm.js code
// NaN and Infinity variables
Ref nanVar = ValueBuilder::makeVar();
ast->push_back(nanVar);
- ValueBuilder::appendToVar(nanVar,
+ ValueBuilder::appendToVar(
+ nanVar,
"nan",
- ValueBuilder::makeDot(ValueBuilder::makeName(GLOBAL), "NaN")
- );
+ ValueBuilder::makeDot(ValueBuilder::makeName(GLOBAL), "NaN"));
Ref infinityVar = ValueBuilder::makeVar();
ast->push_back(infinityVar);
- ValueBuilder::appendToVar(infinityVar,
+ ValueBuilder::appendToVar(
+ infinityVar,
"infinity",
- ValueBuilder::makeDot(ValueBuilder::makeName(GLOBAL), "Infinity")
- );
+ ValueBuilder::makeDot(ValueBuilder::makeName(GLOBAL), "Infinity"));
}
void Wasm2JSBuilder::addFunctionImport(Ref ast, Function* import) {
- // The scratch memory helpers are emitted in the glue, see code and comments below.
+ // The scratch memory helpers are emitted in the glue, see code and comments
+ // below.
if (ABI::wasm2js::isScratchMemoryHelper(import->base)) {
return;
}
Ref theVar = ValueBuilder::makeVar();
ast->push_back(theVar);
- Ref module = ValueBuilder::makeName(ENV); // TODO: handle nested module imports
- ValueBuilder::appendToVar(theVar,
+ // TODO: handle nested module imports
+ Ref module = ValueBuilder::makeName(ENV);
+ ValueBuilder::appendToVar(
+ theVar,
fromName(import->name, NameScope::Top),
- ValueBuilder::makeDot(
- module,
- fromName(import->base, NameScope::Top)
- )
- );
+ ValueBuilder::makeDot(module, fromName(import->base, NameScope::Top)));
}
void Wasm2JSBuilder::addGlobalImport(Ref ast, Global* import) {
Ref theVar = ValueBuilder::makeVar();
ast->push_back(theVar);
- Ref module = ValueBuilder::makeName(ENV); // TODO: handle nested module imports
- Ref value = ValueBuilder::makeDot(
- module,
- fromName(import->base, NameScope::Top)
- );
+ // TODO: handle nested module imports
+ Ref module = ValueBuilder::makeName(ENV);
+ Ref value =
+ ValueBuilder::makeDot(module, fromName(import->base, NameScope::Top));
if (import->type == i32) {
value = makeAsmCoercion(value, ASM_INT);
}
- ValueBuilder::appendToVar(theVar,
- fromName(import->name, NameScope::Top),
- value
- );
+ ValueBuilder::appendToVar(
+ theVar, fromName(import->name, NameScope::Top), value);
}
void Wasm2JSBuilder::addTable(Ref ast, Module* wasm) {
@@ -505,7 +489,8 @@ void Wasm2JSBuilder::addTable(Ref ast, Module* wasm) {
if (!wasm->table.imported()) {
Ref theVar = ValueBuilder::makeVar();
ast->push_back(theVar);
- ValueBuilder::appendToVar(theVar, FUNCTION_TABLE, ValueBuilder::makeArray());
+ ValueBuilder::appendToVar(
+ theVar, FUNCTION_TABLE, ValueBuilder::makeArray());
}
// TODO: optimize for size
@@ -519,21 +504,14 @@ void Wasm2JSBuilder::addTable(Ref ast, Module* wasm) {
index = ValueBuilder::makeBinary(
ValueBuilder::makeName(stringToIString(asmangle(get->name.str))),
PLUS,
- ValueBuilder::makeNum(i)
- );
+ ValueBuilder::makeNum(i));
} else {
WASM_UNREACHABLE();
}
- ast->push_back(ValueBuilder::makeStatement(
- ValueBuilder::makeBinary(
- ValueBuilder::makeSub(
- ValueBuilder::makeName(FUNCTION_TABLE),
- index
- ),
- SET,
- ValueBuilder::makeName(fromName(segment.data[i], NameScope::Top))
- )
- ));
+ ast->push_back(ValueBuilder::makeStatement(ValueBuilder::makeBinary(
+ ValueBuilder::makeSub(ValueBuilder::makeName(FUNCTION_TABLE), index),
+ SET,
+ ValueBuilder::makeName(fromName(segment.data[i], NameScope::Top)))));
}
}
}
@@ -546,49 +524,37 @@ void Wasm2JSBuilder::addExports(Ref ast, Module* wasm) {
ValueBuilder::appendToObjectWithQuotes(
exports,
fromName(export_->name, NameScope::Top),
- ValueBuilder::makeName(fromName(export_->value, NameScope::Top))
- );
+ ValueBuilder::makeName(fromName(export_->value, NameScope::Top)));
}
if (export_->kind == ExternalKind::Memory) {
Ref descs = ValueBuilder::makeObject();
Ref growDesc = ValueBuilder::makeObject();
+ ValueBuilder::appendToObjectWithQuotes(descs, IString("grow"), growDesc);
ValueBuilder::appendToObjectWithQuotes(
- descs,
- IString("grow"),
- growDesc);
- ValueBuilder::appendToObjectWithQuotes(
- growDesc,
- IString("value"),
- ValueBuilder::makeName(WASM_GROW_MEMORY));
+ growDesc, IString("value"), ValueBuilder::makeName(WASM_GROW_MEMORY));
Ref bufferDesc = ValueBuilder::makeObject();
Ref bufferGetter = ValueBuilder::makeFunction(IString(""));
- bufferGetter[3]->push_back(ValueBuilder::makeReturn(
- ValueBuilder::makeName(BUFFER)
- ));
+ bufferGetter[3]->push_back(
+ ValueBuilder::makeReturn(ValueBuilder::makeName(BUFFER)));
ValueBuilder::appendToObjectWithQuotes(
- bufferDesc,
- IString("get"),
- bufferGetter);
+ bufferDesc, IString("get"), bufferGetter);
ValueBuilder::appendToObjectWithQuotes(
- descs,
- IString("buffer"),
- bufferDesc);
+ descs, IString("buffer"), bufferDesc);
Ref memory = ValueBuilder::makeCall(
- ValueBuilder::makeDot(ValueBuilder::makeName(IString("Object")), IString("create")),
- ValueBuilder::makeDot(ValueBuilder::makeName(IString("Object")), IString("prototype")));
- ValueBuilder::appendToCall(
- memory,
- descs);
+ ValueBuilder::makeDot(ValueBuilder::makeName(IString("Object")),
+ IString("create")),
+ ValueBuilder::makeDot(ValueBuilder::makeName(IString("Object")),
+ IString("prototype")));
+ ValueBuilder::appendToCall(memory, descs);
ValueBuilder::appendToObjectWithQuotes(
- exports,
- fromName(export_->name, NameScope::Top),
- memory);
+ exports, fromName(export_->name, NameScope::Top), memory);
}
}
if (wasm->memory.exists && wasm->memory.max > wasm->memory.initial) {
addMemoryGrowthFuncs(ast, wasm);
}
- ast->push_back(ValueBuilder::makeStatement(ValueBuilder::makeReturn(exports)));
+ ast->push_back(
+ ValueBuilder::makeStatement(ValueBuilder::makeReturn(exports)));
}
void Wasm2JSBuilder::addGlobal(Ref ast, Global* global) {
@@ -600,38 +566,38 @@ void Wasm2JSBuilder::addGlobal(Ref ast, Global* global) {
break;
}
case Type::f32: {
- theValue = ValueBuilder::makeCall(MATH_FROUND,
- makeAsmCoercion(ValueBuilder::makeDouble(const_->value.getf32()), ASM_DOUBLE)
- );
+ theValue = ValueBuilder::makeCall(
+ MATH_FROUND,
+ makeAsmCoercion(ValueBuilder::makeDouble(const_->value.getf32()),
+ ASM_DOUBLE));
break;
}
case Type::f64: {
- theValue = makeAsmCoercion(ValueBuilder::makeDouble(const_->value.getf64()), ASM_DOUBLE);
+ theValue = makeAsmCoercion(
+ ValueBuilder::makeDouble(const_->value.getf64()), ASM_DOUBLE);
break;
}
- default: {
- assert(false && "Top const type not supported");
- }
+ default: { assert(false && "Top const type not supported"); }
}
Ref theVar = ValueBuilder::makeVar();
ast->push_back(theVar);
- ValueBuilder::appendToVar(theVar,
- fromName(global->name, NameScope::Top),
- theValue
- );
+ ValueBuilder::appendToVar(
+ theVar, fromName(global->name, NameScope::Top), theValue);
} else if (auto* get = global->init->dynCast<GetGlobal>()) {
Ref theVar = ValueBuilder::makeVar();
ast->push_back(theVar);
- ValueBuilder::appendToVar(theVar,
+ ValueBuilder::appendToVar(
+ theVar,
fromName(global->name, NameScope::Top),
- ValueBuilder::makeName(fromName(get->name, NameScope::Top))
- );
+ ValueBuilder::makeName(fromName(get->name, NameScope::Top)));
} else {
assert(false && "Top init type not supported");
}
}
-Ref Wasm2JSBuilder::processFunction(Module* m, Function* func, bool standaloneFunction) {
+Ref Wasm2JSBuilder::processFunction(Module* m,
+ Function* func,
+ bool standaloneFunction) {
if (standaloneFunction) {
// We are only printing a function, not a whole module. Prepare it for
// translation now (if there were a module, we'd have done this for all
@@ -657,22 +623,17 @@ Ref Wasm2JSBuilder::processFunction(Module* m, Function* func, bool standaloneFu
temps.resize(std::max(i32, std::max(f32, f64)) + 1);
temps[i32] = temps[f32] = temps[f64] = 0;
// arguments
- bool needCoercions = options.optimizeLevel == 0 || standaloneFunction || functionsCallableFromOutside.count(func->name);
+ bool needCoercions = options.optimizeLevel == 0 || standaloneFunction ||
+ functionsCallableFromOutside.count(func->name);
for (Index i = 0; i < func->getNumParams(); i++) {
IString name = fromName(func->getLocalNameOrGeneric(i), NameScope::Local);
ValueBuilder::appendArgumentToFunction(ret, name);
if (needCoercions) {
- ret[3]->push_back(
- ValueBuilder::makeStatement(
- ValueBuilder::makeBinary(
- ValueBuilder::makeName(name), SET,
- makeAsmCoercion(
- ValueBuilder::makeName(name),
- wasmToAsmType(func->getLocalType(i))
- )
- )
- )
- );
+ ret[3]->push_back(ValueBuilder::makeStatement(ValueBuilder::makeBinary(
+ ValueBuilder::makeName(name),
+ SET,
+ makeAsmCoercion(ValueBuilder::makeName(name),
+ wasmToAsmType(func->getLocalType(i))))));
}
}
Ref theVar = ValueBuilder::makeVar();
@@ -685,20 +646,21 @@ Ref Wasm2JSBuilder::processFunction(Module* m, Function* func, bool standaloneFu
ValueBuilder::appendToVar(
theVar,
fromName(func->getLocalNameOrGeneric(i), NameScope::Local),
- makeAsmCoercedZero(wasmToAsmType(func->getLocalType(i)))
- );
+ makeAsmCoercedZero(wasmToAsmType(func->getLocalType(i))));
}
if (theVar[1]->size() == 0) {
ret[3]->splice(theVarIndex, 1);
}
- // checks
- assert(frees[i32].size() == temps[i32]); // all temp vars should be free at the end
- assert(frees[f32].size() == temps[f32]); // all temp vars should be free at the end
- assert(frees[f64].size() == temps[f64]); // all temp vars should be free at the end
+ // checks: all temp vars should be free at the end
+ assert(frees[i32].size() == temps[i32]);
+ assert(frees[f32].size() == temps[f32]);
+ assert(frees[f64].size() == temps[f64]);
return ret;
}
-Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standaloneFunction) {
+Ref Wasm2JSBuilder::processFunctionBody(Module* m,
+ Function* func,
+ bool standaloneFunction) {
struct ExpressionProcessor : public Visitor<ExpressionProcessor, Ref> {
Wasm2JSBuilder* parent;
IString result; // TODO: remove
@@ -707,8 +669,12 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
bool standaloneFunction;
MixedArena allocator;
- ExpressionProcessor(Wasm2JSBuilder* parent, Module* m, Function* func, bool standaloneFunction)
- : parent(parent), func(func), module(m), standaloneFunction(standaloneFunction) {}
+ ExpressionProcessor(Wasm2JSBuilder* parent,
+ Module* m,
+ Function* func,
+ bool standaloneFunction)
+ : parent(parent), func(func), module(m),
+ standaloneFunction(standaloneFunction) {}
// A scoped temporary variable.
struct ScopedTemp {
@@ -716,11 +682,15 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
Type type;
IString temp; // TODO: switch to indexes; avoid names
bool needFree;
- // @param possible if provided, this is a variable we can use as our temp. it has already been
- // allocated in a higher scope, and we can just assign to it as our result is
- // going there anyhow.
- ScopedTemp(Type type, Wasm2JSBuilder* parent, Function* func,
- IString possible = NO_RESULT) : parent(parent), type(type) {
+ // @param possible if provided, this is a variable we can use as our temp.
+ // it has already been allocated in a higher scope, and we
+ // can just assign to it as our result is going there
+ // anyhow.
+ ScopedTemp(Type type,
+ Wasm2JSBuilder* parent,
+ Function* func,
+ IString possible = NO_RESULT)
+ : parent(parent), type(type) {
assert(possible != EXPRESSION_RESULT);
if (possible == NO_RESULT) {
temp = parent->getTemp(type, func);
@@ -736,19 +706,17 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
}
}
- IString getName() {
- return temp;
- }
- Ref getAstName() {
- return ValueBuilder::makeName(temp);
- }
+ IString getName() { return temp; }
+ Ref getAstName() { return ValueBuilder::makeName(temp); }
};
Ref visit(Expression* curr, IString nextResult) {
IString old = result;
result = nextResult;
Ref ret = Visitor::visit(curr);
- result = old; // keep it consistent for the rest of this frame, which may call visit on multiple children
+ // keep it consistent for the rest of this frame, which may call visit on
+ // multiple children
+ result = old;
return ret;
}
@@ -759,7 +727,8 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
Ref visitAndAssign(Expression* curr, IString result) {
assert(result != NO_RESULT);
Ref ret = visit(curr, result);
- return ValueBuilder::makeStatement(ValueBuilder::makeBinary(ValueBuilder::makeName(result), SET, ret));
+ return ValueBuilder::makeStatement(
+ ValueBuilder::makeBinary(ValueBuilder::makeName(result), SET, ret));
}
Ref visitAndAssign(Expression* curr, ScopedTemp& temp) {
@@ -768,18 +737,18 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
// Expressions with control flow turn into a block, which we must
// then handle, even if we are an expression.
- bool isBlock(Ref ast) {
- return !!ast && ast->isArray() && ast[0] == BLOCK;
- }
+ bool isBlock(Ref ast) { return !!ast && ast->isArray() && ast[0] == BLOCK; }
Ref blockify(Ref ast) {
- if (isBlock(ast)) return ast;
+ if (isBlock(ast))
+ return ast;
Ref ret = ValueBuilder::makeBlock();
ret[1]->push_back(ValueBuilder::makeStatement(ast));
return ret;
}
- // Breaks to the top of a loop should be emitted as continues, to that loop's main label
+ // Breaks to the top of a loop should be emitted as continues, to that
+ // loop's main label
std::unordered_set<Name> continueLabels;
IString fromName(Name name, NameScope scope) {
@@ -791,15 +760,17 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
Ref visitBlock(Block* curr) {
Ref ret = ValueBuilder::makeBlock();
size_t size = curr->list.size();
- auto noResults = result == NO_RESULT ? size : size-1;
+ auto noResults = result == NO_RESULT ? size : size - 1;
for (size_t i = 0; i < noResults; i++) {
- flattenAppend(ret, ValueBuilder::makeStatement(visit(curr->list[i], NO_RESULT)));
+ flattenAppend(
+ ret, ValueBuilder::makeStatement(visit(curr->list[i], NO_RESULT)));
}
if (result != NO_RESULT) {
- flattenAppend(ret, visitAndAssign(curr->list[size-1], result));
+ flattenAppend(ret, visitAndAssign(curr->list[size - 1], result));
}
if (curr->name.is()) {
- ret = ValueBuilder::makeLabel(fromName(curr->name, NameScope::Label), ret);
+ ret =
+ ValueBuilder::makeLabel(fromName(curr->name, NameScope::Label), ret);
}
return ret;
}
@@ -822,7 +793,8 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
if (curr->body->type != unreachable) {
assert(curr->body->type == none); // flat IR
body = blockify(body);
- flattenAppend(body, ValueBuilder::makeBreak(fromName(asmLabel, NameScope::Label)));
+ flattenAppend(
+ body, ValueBuilder::makeBreak(fromName(asmLabel, NameScope::Label)));
}
Ref ret = ValueBuilder::makeWhile(ValueBuilder::makeInt(1), body);
return ValueBuilder::makeLabel(fromName(asmLabel, NameScope::Label), ret);
@@ -860,17 +832,23 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
ret[1]->push_back(theSwitch);
for (size_t i = 0; i < curr->targets.size(); i++) {
ValueBuilder::appendCaseToSwitch(theSwitch, ValueBuilder::makeNum(i));
- ValueBuilder::appendCodeToSwitch(theSwitch, blockify(makeBreakOrContinue(curr->targets[i])), false);
+ ValueBuilder::appendCodeToSwitch(
+ theSwitch, blockify(makeBreakOrContinue(curr->targets[i])), false);
}
ValueBuilder::appendDefaultToSwitch(theSwitch);
- ValueBuilder::appendCodeToSwitch(theSwitch, blockify(makeBreakOrContinue(curr->default_)), false);
+ ValueBuilder::appendCodeToSwitch(
+ theSwitch, blockify(makeBreakOrContinue(curr->default_)), false);
return ret;
}
Ref visitCall(Call* curr) {
- Ref theCall = ValueBuilder::makeCall(fromName(curr->target, NameScope::Top));
- // For wasm => wasm calls, we don't need coercions. TODO: even imports might be safe?
- bool needCoercions = parent->options.optimizeLevel == 0 || standaloneFunction || module->getFunction(curr->target)->imported();
+ Ref theCall =
+ ValueBuilder::makeCall(fromName(curr->target, NameScope::Top));
+ // For wasm => wasm calls, we don't need coercions. TODO: even imports
+ // might be safe?
+ bool needCoercions = parent->options.optimizeLevel == 0 ||
+ standaloneFunction ||
+ module->getFunction(curr->target)->imported();
for (auto operand : curr->operands) {
auto value = visit(operand, EXPRESSION_RESULT);
if (needCoercions) {
@@ -885,12 +863,14 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
}
Ref visitCallIndirect(CallIndirect* curr) {
- // If the target has effects that interact with the operands, we must reorder it to the start.
+ // If the target has effects that interact with the operands, we must
+ // reorder it to the start.
bool mustReorder = false;
EffectAnalyzer targetEffects(parent->options, curr->target);
if (targetEffects.hasAnything()) {
for (auto* operand : curr->operands) {
- if (targetEffects.invalidates(EffectAnalyzer(parent->options, operand))) {
+ if (targetEffects.invalidates(
+ EffectAnalyzer(parent->options, operand))) {
mustReorder = true;
break;
}
@@ -907,13 +887,12 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
}
sequenceAppend(ret, visitAndAssign(curr->target, idx));
Ref theCall = ValueBuilder::makeCall(ValueBuilder::makeSub(
- ValueBuilder::makeName(FUNCTION_TABLE),
- idx.getAstName()
- ));
+ ValueBuilder::makeName(FUNCTION_TABLE), idx.getAstName()));
for (size_t i = 0; i < temps.size(); i++) {
IString temp = temps[i]->temp;
- auto &operand = curr->operands[i];
- theCall[2]->push_back(makeAsmCoercion(ValueBuilder::makeName(temp), wasmToAsmType(operand->type)));
+ auto& operand = curr->operands[i];
+ theCall[2]->push_back(makeAsmCoercion(ValueBuilder::makeName(temp),
+ wasmToAsmType(operand->type)));
}
theCall = makeAsmCoercion(theCall, wasmToAsmType(curr->type));
sequenceAppend(ret, theCall);
@@ -923,10 +902,9 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
return ret;
} else {
// Target has no side effects, emit simple code
- Ref theCall = ValueBuilder::makeCall(ValueBuilder::makeSub(
- ValueBuilder::makeName(FUNCTION_TABLE),
- visit(curr->target, EXPRESSION_RESULT)
- ));
+ Ref theCall = ValueBuilder::makeCall(
+ ValueBuilder::makeSub(ValueBuilder::makeName(FUNCTION_TABLE),
+ visit(curr->target, EXPRESSION_RESULT)));
for (auto* operand : curr->operands) {
theCall[2]->push_back(visit(operand, EXPRESSION_RESULT));
}
@@ -936,26 +914,26 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
}
// TODO: remove
- Ref makeSetVar(Expression* curr, Expression* value, Name name, NameScope scope) {
+ Ref makeSetVar(Expression* curr,
+ Expression* value,
+ Name name,
+ NameScope scope) {
return ValueBuilder::makeBinary(
- ValueBuilder::makeName(fromName(name, scope)), SET,
- visit(value, EXPRESSION_RESULT)
- );
+ ValueBuilder::makeName(fromName(name, scope)),
+ SET,
+ visit(value, EXPRESSION_RESULT));
}
Ref visitGetLocal(GetLocal* curr) {
return ValueBuilder::makeName(
- fromName(func->getLocalNameOrGeneric(curr->index), NameScope::Local)
- );
+ fromName(func->getLocalNameOrGeneric(curr->index), NameScope::Local));
}
Ref visitSetLocal(SetLocal* curr) {
- return makeSetVar(
- curr,
- curr->value,
- func->getLocalNameOrGeneric(curr->index),
- NameScope::Local
- );
+ return makeSetVar(curr,
+ curr->value,
+ func->getLocalNameOrGeneric(curr->index),
+ NameScope::Local);
}
Ref visitGetGlobal(GetGlobal* curr) {
@@ -987,8 +965,10 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
rest = makeAsmCoercion(visit(&load, EXPRESSION_RESULT), ASM_INT);
for (size_t i = 1; i < curr->bytes; i++) {
++load.offset;
- Ref add = makeAsmCoercion(visit(&load, EXPRESSION_RESULT), ASM_INT);
- add = ValueBuilder::makeBinary(add, LSHIFT, ValueBuilder::makeNum(8*i));
+ Ref add =
+ makeAsmCoercion(visit(&load, EXPRESSION_RESULT), ASM_INT);
+ add = ValueBuilder::makeBinary(
+ add, LSHIFT, ValueBuilder::makeNum(8 * i));
rest = ValueBuilder::makeBinary(rest, OR, add);
}
break;
@@ -1008,18 +988,21 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
switch (curr->bytes) {
case 1:
ret = ValueBuilder::makeSub(
- ValueBuilder::makeName(LoadUtils::isSignRelevant(curr) && curr->signed_ ? HEAP8 : HEAPU8),
- ValueBuilder::makePtrShift(ptr, 0));
+ ValueBuilder::makeName(
+ LoadUtils::isSignRelevant(curr) && curr->signed_ ? HEAP8
+ : HEAPU8),
+ ValueBuilder::makePtrShift(ptr, 0));
break;
case 2:
ret = ValueBuilder::makeSub(
- ValueBuilder::makeName(LoadUtils::isSignRelevant(curr) && curr->signed_ ? HEAP16 : HEAPU16),
- ValueBuilder::makePtrShift(ptr, 1));
+ ValueBuilder::makeName(
+ LoadUtils::isSignRelevant(curr) && curr->signed_ ? HEAP16
+ : HEAPU16),
+ ValueBuilder::makePtrShift(ptr, 1));
break;
case 4:
- ret = ValueBuilder::makeSub(
- ValueBuilder::makeName(HEAP32),
- ValueBuilder::makePtrShift(ptr, 2));
+ ret = ValueBuilder::makeSub(ValueBuilder::makeName(HEAP32),
+ ValueBuilder::makePtrShift(ptr, 2));
break;
default: {
std::cerr << "Unhandled number of bytes in i32 load: "
@@ -1042,10 +1025,11 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
abort();
}
}
- // Coercions are not actually needed, as if the user reads beyond valid memory, it's
- // undefined behavior anyhow, and so we don't care much about slowness of undefined
- // values etc.
- bool needCoercions = parent->options.optimizeLevel == 0 || standaloneFunction;
+ // Coercions are not actually needed, as if the user reads beyond valid
+ // memory, it's undefined behavior anyhow, and so we don't care much about
+ // slowness of undefined values etc.
+ bool needCoercions =
+ parent->options.optimizeLevel == 0 || standaloneFunction;
if (needCoercions) {
ret = makeAsmCoercion(ret, wasmToAsmType(curr->type));
}
@@ -1053,7 +1037,8 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
}
Ref visitStore(Store* curr) {
- if (module->memory.initial < module->memory.max && curr->type != unreachable) {
+ if (module->memory.initial < module->memory.max &&
+ curr->type != unreachable) {
// In JS, if memory grows then it is dangerous to write
// HEAP[f()] = ..
// or
@@ -1117,7 +1102,7 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
_255.type = i32;
for (size_t i = 0; i < curr->bytes; i++) {
Const shift(allocator);
- shift.value = Literal(int32_t(8*i));
+ shift.value = Literal(int32_t(8 * i));
shift.type = i32;
Binary shifted(allocator);
shifted.op = ShrUInt32;
@@ -1126,7 +1111,8 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
shifted.type = i32;
Binary anded(allocator);
anded.op = AndInt32;
- anded.left = i > 0 ? static_cast<Expression*>(&shifted) : static_cast<Expression*>(&getValue);
+ anded.left = i > 0 ? static_cast<Expression*>(&shifted)
+ : static_cast<Expression*>(&getValue);
anded.right = &_255;
anded.type = i32;
store.value = &anded;
@@ -1141,12 +1127,13 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
break;
}
default: {
- std::cerr << "Unhandled type in store: " << curr->valueType
+ std::cerr << "Unhandled type in store: " << curr->valueType
<< std::endl;
abort();
}
}
- return ValueBuilder::makeSeq(ValueBuilder::makeSeq(ptrSet, valueSet), rest);
+ return ValueBuilder::makeSeq(ValueBuilder::makeSeq(ptrSet, valueSet),
+ rest);
}
// normal store
Ref ptr = makePointer(curr->ptr, curr->offset);
@@ -1155,15 +1142,31 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
switch (curr->valueType) {
case i32: {
switch (curr->bytes) {
- case 1: ret = ValueBuilder::makeSub(ValueBuilder::makeName(HEAP8), ValueBuilder::makePtrShift(ptr, 0)); break;
- case 2: ret = ValueBuilder::makeSub(ValueBuilder::makeName(HEAP16), ValueBuilder::makePtrShift(ptr, 1)); break;
- case 4: ret = ValueBuilder::makeSub(ValueBuilder::makeName(HEAP32), ValueBuilder::makePtrShift(ptr, 2)); break;
- default: abort();
+ case 1:
+ ret = ValueBuilder::makeSub(ValueBuilder::makeName(HEAP8),
+ ValueBuilder::makePtrShift(ptr, 0));
+ break;
+ case 2:
+ ret = ValueBuilder::makeSub(ValueBuilder::makeName(HEAP16),
+ ValueBuilder::makePtrShift(ptr, 1));
+ break;
+ case 4:
+ ret = ValueBuilder::makeSub(ValueBuilder::makeName(HEAP32),
+ ValueBuilder::makePtrShift(ptr, 2));
+ break;
+ default:
+ abort();
}
break;
}
- case f32: ret = ValueBuilder::makeSub(ValueBuilder::makeName(HEAPF32), ValueBuilder::makePtrShift(ptr, 2)); break;
- case f64: ret = ValueBuilder::makeSub(ValueBuilder::makeName(HEAPF64), ValueBuilder::makePtrShift(ptr, 3)); break;
+ case f32:
+ ret = ValueBuilder::makeSub(ValueBuilder::makeName(HEAPF32),
+ ValueBuilder::makePtrShift(ptr, 2));
+ break;
+ case f64:
+ ret = ValueBuilder::makeSub(ValueBuilder::makeName(HEAPF64),
+ ValueBuilder::makePtrShift(ptr, 3));
+ break;
default: {
std::cerr << "Unhandled type in store: " << curr->valueType
<< std::endl;
@@ -1173,19 +1176,18 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
return ValueBuilder::makeBinary(ret, SET, value);
}
- Ref visitDrop(Drop* curr) {
- return visit(curr->value, NO_RESULT);
- }
+ Ref visitDrop(Drop* curr) { return visit(curr->value, NO_RESULT); }
Ref visitConst(Const* curr) {
switch (curr->type) {
- case i32: return ValueBuilder::makeInt(curr->value.geti32());
+ case i32:
+ return ValueBuilder::makeInt(curr->value.geti32());
// An i64 argument translates to two actual arguments to asm.js
// functions, so we do a bit of a hack here to get our one `Ref` to look
// like two function arguments.
case i64: {
- auto lo = (unsigned) curr->value.geti64();
- auto hi = (unsigned) (curr->value.geti64() >> 32);
+ auto lo = (unsigned)curr->value.geti64();
+ auto hi = (unsigned)(curr->value.geti64() >> 32);
std::ostringstream out;
out << lo << "," << hi;
std::string os = out.str();
@@ -1203,11 +1205,15 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
case f64: {
double d = curr->value.getf64();
if (d == 0 && std::signbit(d)) { // negative zero
- return ValueBuilder::makeUnary(PLUS, ValueBuilder::makeUnary(MINUS, ValueBuilder::makeDouble(0)));
+ return ValueBuilder::makeUnary(
+ PLUS,
+ ValueBuilder::makeUnary(MINUS, ValueBuilder::makeDouble(0)));
}
- return ValueBuilder::makeUnary(PLUS, ValueBuilder::makeDouble(curr->value.getf64()));
+ return ValueBuilder::makeUnary(
+ PLUS, ValueBuilder::makeDouble(curr->value.getf64()));
}
- default: abort();
+ default:
+ abort();
}
}
@@ -1218,37 +1224,37 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
switch (curr->op) {
case ClzInt32:
return ValueBuilder::makeCall(
- MATH_CLZ32,
- visit(curr->value, EXPRESSION_RESULT)
- );
+ MATH_CLZ32, visit(curr->value, EXPRESSION_RESULT));
case CtzInt32:
case PopcntInt32:
std::cerr << "i32 unary should have been removed: " << curr
<< std::endl;
WASM_UNREACHABLE();
case EqZInt32:
- // XXX !x does change the type to bool, which is correct, but may be slower?
- return ValueBuilder::makeUnary(L_NOT, visit(curr->value, EXPRESSION_RESULT));
+ // XXX !x does change the type to bool, which is correct, but may
+ // be slower?
+ return ValueBuilder::makeUnary(
+ L_NOT, visit(curr->value, EXPRESSION_RESULT));
case ReinterpretFloat32: {
- ABI::wasm2js::ensureScratchMemoryHelpers(module, ABI::wasm2js::SCRATCH_STORE_F32);
- ABI::wasm2js::ensureScratchMemoryHelpers(module, ABI::wasm2js::SCRATCH_LOAD_I32);
-
- Ref store = ValueBuilder::makeCall(
- ABI::wasm2js::SCRATCH_STORE_F32,
- visit(curr->value, EXPRESSION_RESULT)
- );
- Ref load = ValueBuilder::makeCall(ABI::wasm2js::SCRATCH_LOAD_I32, ValueBuilder::makeInt(0));
+ ABI::wasm2js::ensureScratchMemoryHelpers(
+ module, ABI::wasm2js::SCRATCH_STORE_F32);
+ ABI::wasm2js::ensureScratchMemoryHelpers(
+ module, ABI::wasm2js::SCRATCH_LOAD_I32);
+
+ Ref store =
+ ValueBuilder::makeCall(ABI::wasm2js::SCRATCH_STORE_F32,
+ visit(curr->value, EXPRESSION_RESULT));
+ Ref load = ValueBuilder::makeCall(ABI::wasm2js::SCRATCH_LOAD_I32,
+ ValueBuilder::makeInt(0));
return ValueBuilder::makeSeq(store, load);
}
// generate (~~expr), what Emscripten does
case TruncSFloat32ToInt32:
case TruncSFloat64ToInt32:
return ValueBuilder::makeUnary(
- B_NOT,
- ValueBuilder::makeUnary(
- B_NOT,
- visit(curr->value, EXPRESSION_RESULT)
- ));
+ B_NOT,
+ ValueBuilder::makeUnary(B_NOT,
+ visit(curr->value, EXPRESSION_RESULT)));
// generate (~~expr >>> 0), what Emscripten does
case TruncUFloat32ToInt32:
@@ -1257,13 +1263,9 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
ValueBuilder::makeUnary(
B_NOT,
ValueBuilder::makeUnary(
- B_NOT,
- visit(curr->value, EXPRESSION_RESULT)
- )
- ),
+ B_NOT, visit(curr->value, EXPRESSION_RESULT))),
TRSHIFT,
- ValueBuilder::makeNum(0)
- );
+ ValueBuilder::makeNum(0));
default: {
std::cerr << "Unhandled unary i32 operator: " << curr
@@ -1279,37 +1281,27 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
case NegFloat32:
case NegFloat64:
ret = ValueBuilder::makeUnary(
- MINUS,
- visit(curr->value, EXPRESSION_RESULT)
- );
+ MINUS, visit(curr->value, EXPRESSION_RESULT));
break;
case AbsFloat32:
case AbsFloat64:
ret = ValueBuilder::makeCall(
- MATH_ABS,
- visit(curr->value, EXPRESSION_RESULT)
- );
+ MATH_ABS, visit(curr->value, EXPRESSION_RESULT));
break;
case CeilFloat32:
case CeilFloat64:
ret = ValueBuilder::makeCall(
- MATH_CEIL,
- visit(curr->value, EXPRESSION_RESULT)
- );
+ MATH_CEIL, visit(curr->value, EXPRESSION_RESULT));
break;
case FloorFloat32:
case FloorFloat64:
ret = ValueBuilder::makeCall(
- MATH_FLOOR,
- visit(curr->value, EXPRESSION_RESULT)
- );
+ MATH_FLOOR, visit(curr->value, EXPRESSION_RESULT));
break;
case SqrtFloat32:
case SqrtFloat64:
ret = ValueBuilder::makeCall(
- MATH_SQRT,
- visit(curr->value, EXPRESSION_RESULT)
- );
+ MATH_SQRT, visit(curr->value, EXPRESSION_RESULT));
break;
case PromoteFloat32:
return makeAsmCoercion(visit(curr->value, EXPRESSION_RESULT),
@@ -1318,14 +1310,15 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
return makeAsmCoercion(visit(curr->value, EXPRESSION_RESULT),
ASM_FLOAT);
case ReinterpretInt32: {
- ABI::wasm2js::ensureScratchMemoryHelpers(module, ABI::wasm2js::SCRATCH_STORE_I32);
- ABI::wasm2js::ensureScratchMemoryHelpers(module, ABI::wasm2js::SCRATCH_LOAD_F32);
-
- Ref store = ValueBuilder::makeCall(
- ABI::wasm2js::SCRATCH_STORE_I32,
- ValueBuilder::makeNum(0),
- visit(curr->value, EXPRESSION_RESULT)
- );
+ ABI::wasm2js::ensureScratchMemoryHelpers(
+ module, ABI::wasm2js::SCRATCH_STORE_I32);
+ ABI::wasm2js::ensureScratchMemoryHelpers(
+ module, ABI::wasm2js::SCRATCH_LOAD_F32);
+
+ Ref store =
+ ValueBuilder::makeCall(ABI::wasm2js::SCRATCH_STORE_I32,
+ ValueBuilder::makeNum(0),
+ visit(curr->value, EXPRESSION_RESULT));
Ref load = ValueBuilder::makeCall(ABI::wasm2js::SCRATCH_LOAD_F32);
return ValueBuilder::makeSeq(store, load);
}
@@ -1333,40 +1326,33 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
case ConvertSInt32ToFloat32:
return makeAsmCoercion(
makeAsmCoercion(visit(curr->value, EXPRESSION_RESULT), ASM_INT),
- ASM_FLOAT
- );
+ ASM_FLOAT);
case ConvertSInt32ToFloat64:
return makeAsmCoercion(
makeAsmCoercion(visit(curr->value, EXPRESSION_RESULT), ASM_INT),
- ASM_DOUBLE
- );
+ ASM_DOUBLE);
// Generate (expr >>> 0), followed by a coercion
case ConvertUInt32ToFloat32:
return makeAsmCoercion(
- ValueBuilder::makeBinary(
- visit(curr->value, EXPRESSION_RESULT),
- TRSHIFT,
- ValueBuilder::makeInt(0)
- ),
- ASM_FLOAT
- );
+ ValueBuilder::makeBinary(visit(curr->value, EXPRESSION_RESULT),
+ TRSHIFT,
+ ValueBuilder::makeInt(0)),
+ ASM_FLOAT);
case ConvertUInt32ToFloat64:
return makeAsmCoercion(
- ValueBuilder::makeBinary(
- visit(curr->value, EXPRESSION_RESULT),
- TRSHIFT,
- ValueBuilder::makeInt(0)
- ),
- ASM_DOUBLE
- );
+ ValueBuilder::makeBinary(visit(curr->value, EXPRESSION_RESULT),
+ TRSHIFT,
+ ValueBuilder::makeInt(0)),
+ ASM_DOUBLE);
// TODO: more complex unary conversions
case NearestFloat32:
case NearestFloat64:
case TruncFloat32:
case TruncFloat64:
- std::cerr << "operation should have been removed in previous passes"
- << std::endl;
+ std::cerr
+ << "operation should have been removed in previous passes"
+ << std::endl;
WASM_UNREACHABLE();
default:
@@ -1409,19 +1395,23 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
}
}
case DivSInt32:
- ret = ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), DIV,
+ ret = ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED),
+ DIV,
makeSigning(right, ASM_SIGNED));
break;
case DivUInt32:
- ret = ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), DIV,
+ ret = ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED),
+ DIV,
makeSigning(right, ASM_UNSIGNED));
break;
case RemSInt32:
- ret = ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), MOD,
+ ret = ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED),
+ MOD,
makeSigning(right, ASM_SIGNED));
break;
case RemUInt32:
- ret = ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), MOD,
+ ret = ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED),
+ MOD,
makeSigning(right, ASM_UNSIGNED));
break;
case AndInt32:
@@ -1443,36 +1433,46 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
ret = ValueBuilder::makeBinary(left, RSHIFT, right);
break;
case EqInt32: {
- return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), EQ,
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED),
+ EQ,
makeSigning(right, ASM_SIGNED));
}
case NeInt32: {
- return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), NE,
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED),
+ NE,
makeSigning(right, ASM_SIGNED));
}
case LtSInt32:
- return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), LT,
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED),
+ LT,
makeSigning(right, ASM_SIGNED));
case LtUInt32:
- return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), LT,
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED),
+ LT,
makeSigning(right, ASM_UNSIGNED));
case LeSInt32:
- return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), LE,
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED),
+ LE,
makeSigning(right, ASM_SIGNED));
case LeUInt32:
- return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), LE,
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED),
+ LE,
makeSigning(right, ASM_UNSIGNED));
case GtSInt32:
- return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), GT,
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED),
+ GT,
makeSigning(right, ASM_SIGNED));
case GtUInt32:
- return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), GT,
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED),
+ GT,
makeSigning(right, ASM_UNSIGNED));
case GeSInt32:
- return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), GE,
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED),
+ GE,
makeSigning(right, ASM_SIGNED));
case GeUInt32:
- return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), GE,
+ return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED),
+ GE,
makeSigning(right, ASM_UNSIGNED));
case EqFloat32:
case EqFloat64:
@@ -1497,7 +1497,8 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
std::cerr << "should be removed already" << std::endl;
WASM_UNREACHABLE();
default: {
- std::cerr << "Unhandled i32 binary operator: " << curr << std::endl;
+ std::cerr << "Unhandled i32 binary operator: " << curr
+ << std::endl;
abort();
}
}
@@ -1505,10 +1506,10 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
}
case f32:
case f64:
- switch (curr->op) {
- case AddFloat32:
- case AddFloat64:
- ret = ValueBuilder::makeBinary(left, PLUS, right);
+ switch (curr->op) {
+ case AddFloat32:
+ case AddFloat64:
+ ret = ValueBuilder::makeBinary(left, PLUS, right);
break;
case SubFloat32:
case SubFloat64:
@@ -1533,7 +1534,8 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
case CopySignFloat32:
case CopySignFloat64:
default:
- std::cerr << "Unhandled binary float operator: " << curr << std::endl;
+ std::cerr << "Unhandled binary float operator: " << curr
+ << std::endl;
abort();
}
if (curr->type == f32) {
@@ -1548,48 +1550,41 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
}
Ref visitSelect(Select* curr) {
- // If the condition has effects that interact with the operands, we must reorder it to the start.
- // We must also use locals if the values have side effects, as a JS conditional does not
- // visit both sides.
+ // If the condition has effects that interact with the operands, we must
+ // reorder it to the start. We must also use locals if the values have
+ // side effects, as a JS conditional does not visit both sides.
bool useLocals = false;
EffectAnalyzer conditionEffects(parent->options, curr->condition);
EffectAnalyzer ifTrueEffects(parent->options, curr->ifTrue);
EffectAnalyzer ifFalseEffects(parent->options, curr->ifFalse);
if (conditionEffects.invalidates(ifTrueEffects) ||
conditionEffects.invalidates(ifFalseEffects) ||
- ifTrueEffects.hasSideEffects() ||
- ifFalseEffects.hasSideEffects()) {
+ ifTrueEffects.hasSideEffects() || ifFalseEffects.hasSideEffects()) {
useLocals = true;
}
if (useLocals) {
ScopedTemp tempIfTrue(curr->type, parent, func),
- tempIfFalse(curr->type, parent, func),
- tempCondition(i32, parent, func);
+ tempIfFalse(curr->type, parent, func),
+ tempCondition(i32, parent, func);
Ref ifTrue = visit(curr->ifTrue, EXPRESSION_RESULT);
Ref ifFalse = visit(curr->ifFalse, EXPRESSION_RESULT);
Ref condition = visit(curr->condition, EXPRESSION_RESULT);
- return
+ return ValueBuilder::makeSeq(
+ ValueBuilder::makeBinary(tempIfTrue.getAstName(), SET, ifTrue),
ValueBuilder::makeSeq(
- ValueBuilder::makeBinary(tempIfTrue.getAstName(), SET, ifTrue),
+ ValueBuilder::makeBinary(tempIfFalse.getAstName(), SET, ifFalse),
ValueBuilder::makeSeq(
- ValueBuilder::makeBinary(tempIfFalse.getAstName(), SET, ifFalse),
- ValueBuilder::makeSeq(
- ValueBuilder::makeBinary(tempCondition.getAstName(), SET, condition),
- ValueBuilder::makeConditional(
- tempCondition.getAstName(),
- tempIfTrue.getAstName(),
- tempIfFalse.getAstName()
- )
- )
- )
- );
+ ValueBuilder::makeBinary(
+ tempCondition.getAstName(), SET, condition),
+ ValueBuilder::makeConditional(tempCondition.getAstName(),
+ tempIfTrue.getAstName(),
+ tempIfFalse.getAstName()))));
} else {
// Simple case without reordering.
return ValueBuilder::makeConditional(
visit(curr->condition, EXPRESSION_RESULT),
visit(curr->ifTrue, EXPRESSION_RESULT),
- visit(curr->ifFalse, EXPRESSION_RESULT)
- );
+ visit(curr->ifFalse, EXPRESSION_RESULT));
}
}
@@ -1598,7 +1593,9 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
return ValueBuilder::makeReturn(Ref());
}
Ref val = visit(curr->value, EXPRESSION_RESULT);
- bool needCoercion = parent->options.optimizeLevel == 0 || standaloneFunction || parent->functionsCallableFromOutside.count(func->name);
+ bool needCoercion =
+ parent->options.optimizeLevel == 0 || standaloneFunction ||
+ parent->functionsCallableFromOutside.count(func->name);
if (needCoercion) {
val = makeAsmCoercion(val, wasmToAsmType(curr->value->type));
}
@@ -1607,11 +1604,12 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
Ref visitHost(Host* curr) {
if (curr->op == HostOp::GrowMemory) {
- if (module->memory.exists && module->memory.max > module->memory.initial) {
- return ValueBuilder::makeCall(WASM_GROW_MEMORY,
- makeAsmCoercion(
- visit(curr->operands[0], EXPRESSION_RESULT),
- wasmToAsmType(curr->operands[0]->type)));
+ if (module->memory.exists &&
+ module->memory.max > module->memory.initial) {
+ return ValueBuilder::makeCall(
+ WASM_GROW_MEMORY,
+ makeAsmCoercion(visit(curr->operands[0], EXPRESSION_RESULT),
+ wasmToAsmType(curr->operands[0]->type)));
} else {
return ValueBuilder::makeCall(ABORT_FUNC);
}
@@ -1621,9 +1619,7 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
WASM_UNREACHABLE(); // TODO
}
- Ref visitNop(Nop* curr) {
- return ValueBuilder::makeToplevel();
- }
+ Ref visitNop(Nop* curr) { return ValueBuilder::makeToplevel(); }
Ref visitUnreachable(Unreachable* curr) {
return ValueBuilder::makeCall(ABORT_FUNC);
@@ -1634,14 +1630,15 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, Function* func, bool standalo
auto ret = visit(ptr, EXPRESSION_RESULT);
if (offset) {
ret = makeAsmCoercion(
- ValueBuilder::makeBinary(ret, PLUS, ValueBuilder::makeNum(offset)),
- ASM_INT);
+ ValueBuilder::makeBinary(ret, PLUS, ValueBuilder::makeNum(offset)),
+ ASM_INT);
}
return ret;
}
};
- return ExpressionProcessor(this, m, func, standaloneFunction).visit(func->body, NO_RESULT);
+ return ExpressionProcessor(this, m, func, standaloneFunction)
+ .visit(func->body, NO_RESULT);
}
void Wasm2JSBuilder::addMemoryGrowthFuncs(Ref ast, Module* wasm) {
@@ -1649,50 +1646,43 @@ void Wasm2JSBuilder::addMemoryGrowthFuncs(Ref ast, Module* wasm) {
ValueBuilder::appendArgumentToFunction(growMemoryFunc, IString("pagesToAdd"));
growMemoryFunc[3]->push_back(
- ValueBuilder::makeStatement(
- ValueBuilder::makeBinary(
- ValueBuilder::makeName(IString("pagesToAdd")), SET,
- makeAsmCoercion(
- ValueBuilder::makeName(IString("pagesToAdd")),
- AsmType::ASM_INT
- )
- )
- )
- );
+ ValueBuilder::makeStatement(ValueBuilder::makeBinary(
+ ValueBuilder::makeName(IString("pagesToAdd")),
+ SET,
+ makeAsmCoercion(ValueBuilder::makeName(IString("pagesToAdd")),
+ AsmType::ASM_INT))));
Ref oldPages = ValueBuilder::makeVar();
growMemoryFunc[3]->push_back(oldPages);
ValueBuilder::appendToVar(
oldPages,
IString("oldPages"),
- makeAsmCoercion(ValueBuilder::makeCall(WASM_CURRENT_MEMORY), AsmType::ASM_INT));
+ makeAsmCoercion(ValueBuilder::makeCall(WASM_CURRENT_MEMORY),
+ AsmType::ASM_INT));
Ref newPages = ValueBuilder::makeVar();
growMemoryFunc[3]->push_back(newPages);
ValueBuilder::appendToVar(
newPages,
IString("newPages"),
- makeAsmCoercion(ValueBuilder::makeBinary(
- ValueBuilder::makeName(IString("oldPages")),
- PLUS,
- ValueBuilder::makeName(IString("pagesToAdd"))
- ), AsmType::ASM_INT));
+ makeAsmCoercion(
+ ValueBuilder::makeBinary(ValueBuilder::makeName(IString("oldPages")),
+ PLUS,
+ ValueBuilder::makeName(IString("pagesToAdd"))),
+ AsmType::ASM_INT));
Ref block = ValueBuilder::makeBlock();
growMemoryFunc[3]->push_back(ValueBuilder::makeIf(
ValueBuilder::makeBinary(
- ValueBuilder::makeBinary(
- ValueBuilder::makeName(IString("oldPages")),
- LT,
- ValueBuilder::makeName(IString("newPages"))
- ),
+ ValueBuilder::makeBinary(ValueBuilder::makeName(IString("oldPages")),
+ LT,
+ ValueBuilder::makeName(IString("newPages"))),
IString("&&"),
- ValueBuilder::makeBinary(
- ValueBuilder::makeName(IString("newPages")),
- LT,
- ValueBuilder::makeInt(Memory::kMaxSize)
- )
- ), block, NULL));
+ ValueBuilder::makeBinary(ValueBuilder::makeName(IString("newPages")),
+ LT,
+ ValueBuilder::makeInt(Memory::kMaxSize))),
+ block,
+ NULL));
Ref newBuffer = ValueBuilder::makeVar();
ValueBuilder::appendToBlock(block, newBuffer);
@@ -1701,110 +1691,79 @@ void Wasm2JSBuilder::addMemoryGrowthFuncs(Ref ast, Module* wasm) {
IString("newBuffer"),
ValueBuilder::makeNew(ValueBuilder::makeCall(
ARRAY_BUFFER,
- ValueBuilder::makeCall(
- MATH_IMUL,
- ValueBuilder::makeName(IString("newPages")),
- ValueBuilder::makeInt(Memory::kPageSize)))));
+ ValueBuilder::makeCall(MATH_IMUL,
+ ValueBuilder::makeName(IString("newPages")),
+ ValueBuilder::makeInt(Memory::kPageSize)))));
Ref newHEAP8 = ValueBuilder::makeVar();
ValueBuilder::appendToBlock(block, newHEAP8);
ValueBuilder::appendToVar(
newHEAP8,
IString("newHEAP8"),
- ValueBuilder::makeNew(
- ValueBuilder::makeCall(
- ValueBuilder::makeDot(
- ValueBuilder::makeName(GLOBAL),
- INT8ARRAY
- ),
- ValueBuilder::makeName(IString("newBuffer"))
- )
- ));
-
- ValueBuilder::appendToBlock(block,
+ ValueBuilder::makeNew(ValueBuilder::makeCall(
+ ValueBuilder::makeDot(ValueBuilder::makeName(GLOBAL), INT8ARRAY),
+ ValueBuilder::makeName(IString("newBuffer")))));
+
+ ValueBuilder::appendToBlock(
+ block,
ValueBuilder::makeCall(
- ValueBuilder::makeDot(
- ValueBuilder::makeName(IString("newHEAP8")),
- IString("set")
- ),
- ValueBuilder::makeName(HEAP8)
- )
- );
-
- ValueBuilder::appendToBlock(block,
- ValueBuilder::makeBinary(
- ValueBuilder::makeName(HEAP8),
- SET,
- ValueBuilder::makeName(IString("newHEAP8"))
- )
- );
+ ValueBuilder::makeDot(ValueBuilder::makeName(IString("newHEAP8")),
+ IString("set")),
+ ValueBuilder::makeName(HEAP8)));
+
+ ValueBuilder::appendToBlock(
+ block,
+ ValueBuilder::makeBinary(ValueBuilder::makeName(HEAP8),
+ SET,
+ ValueBuilder::makeName(IString("newHEAP8"))));
auto setHeap = [&](IString name, IString view) {
- ValueBuilder::appendToBlock(block,
+ ValueBuilder::appendToBlock(
+ block,
ValueBuilder::makeBinary(
ValueBuilder::makeName(name),
SET,
- ValueBuilder::makeNew(
- ValueBuilder::makeCall(
- ValueBuilder::makeDot(
- ValueBuilder::makeName(GLOBAL),
- view
- ),
- ValueBuilder::makeName(IString("newBuffer"))
- )
- )
- )
- );
+ ValueBuilder::makeNew(ValueBuilder::makeCall(
+ ValueBuilder::makeDot(ValueBuilder::makeName(GLOBAL), view),
+ ValueBuilder::makeName(IString("newBuffer"))))));
};
setHeap(HEAP16, INT16ARRAY);
setHeap(HEAP32, INT32ARRAY);
- setHeap(HEAPU8, UINT8ARRAY);
+ setHeap(HEAPU8, UINT8ARRAY);
setHeap(HEAPU16, UINT16ARRAY);
setHeap(HEAPU32, UINT32ARRAY);
setHeap(HEAPF32, FLOAT32ARRAY);
setHeap(HEAPF64, FLOAT64ARRAY);
- ValueBuilder::appendToBlock(block,
- ValueBuilder::makeBinary(
- ValueBuilder::makeName(BUFFER),
- SET,
- ValueBuilder::makeName(IString("newBuffer"))
- )
- );
+ ValueBuilder::appendToBlock(
+ block,
+ ValueBuilder::makeBinary(ValueBuilder::makeName(BUFFER),
+ SET,
+ ValueBuilder::makeName(IString("newBuffer"))));
// apply the changes to the memory import
if (wasm->memory.imported()) {
- ValueBuilder::appendToBlock(block,
+ ValueBuilder::appendToBlock(
+ block,
ValueBuilder::makeBinary(
- ValueBuilder::makeDot(
- ValueBuilder::makeName("memory"),
- ValueBuilder::makeName(BUFFER)
- ),
+ ValueBuilder::makeDot(ValueBuilder::makeName("memory"),
+ ValueBuilder::makeName(BUFFER)),
SET,
- ValueBuilder::makeName(IString("newBuffer"))
- )
- );
+ ValueBuilder::makeName(IString("newBuffer"))));
}
growMemoryFunc[3]->push_back(
- ValueBuilder::makeReturn(
- ValueBuilder::makeName(IString("oldPages"))));
+ ValueBuilder::makeReturn(ValueBuilder::makeName(IString("oldPages"))));
Ref currentMemoryFunc = ValueBuilder::makeFunction(WASM_CURRENT_MEMORY);
currentMemoryFunc[3]->push_back(ValueBuilder::makeReturn(
- makeAsmCoercion(
- ValueBuilder::makeBinary(
- ValueBuilder::makeDot(
- ValueBuilder::makeName(BUFFER),
- IString("byteLength")
- ),
- DIV,
- ValueBuilder::makeInt(Memory::kPageSize)
- ),
- AsmType::ASM_INT
- )
- ));
+ makeAsmCoercion(ValueBuilder::makeBinary(
+ ValueBuilder::makeDot(ValueBuilder::makeName(BUFFER),
+ IString("byteLength")),
+ DIV,
+ ValueBuilder::makeInt(Memory::kPageSize)),
+ AsmType::ASM_INT)));
ast->push_back(growMemoryFunc);
ast->push_back(currentMemoryFunc);
}
@@ -1814,7 +1773,11 @@ void Wasm2JSBuilder::addMemoryGrowthFuncs(Ref ast, Module* wasm) {
// "glue" around that.
class Wasm2JSGlue {
public:
- Wasm2JSGlue(Module& wasm, Output& out, Wasm2JSBuilder::Flags flags, Name moduleName) : wasm(wasm), out(out), flags(flags), moduleName(moduleName) {}
+ Wasm2JSGlue(Module& wasm,
+ Output& out,
+ Wasm2JSBuilder::Flags flags,
+ Name moduleName)
+ : wasm(wasm), out(out), flags(flags), moduleName(moduleName) {}
void emitPre();
void emitPost();
@@ -1830,7 +1793,9 @@ private:
void emitPostEmscripten();
void emitPostES6();
- void emitMemory(std::string buffer, std::string segmentWriter, std::function<std::string (std::string)> accessGlobal);
+ void emitMemory(std::string buffer,
+ std::string segmentWriter,
+ std::function<std::string(std::string)> accessGlobal);
void emitScratchMemorySupport();
};
@@ -1845,7 +1810,8 @@ void Wasm2JSGlue::emitPre() {
}
void Wasm2JSGlue::emitPreEmscripten() {
- out << "function instantiate(asmLibraryArg, wasmMemory, FUNCTION_TABLE) {\n\n";
+ out
+ << "function instantiate(asmLibraryArg, wasmMemory, FUNCTION_TABLE) {\n\n";
}
void Wasm2JSGlue::emitPreES6() {
@@ -1853,7 +1819,8 @@ void Wasm2JSGlue::emitPreES6() {
auto noteImport = [&](Name module, Name base) {
// Right now codegen requires a flat namespace going into the module,
- // meaning we don't support importing the same name from multiple namespaces yet.
+ // meaning we don't support importing the same name from multiple namespaces
+ // yet.
if (baseModuleMap.count(base) && baseModuleMap[base] != module) {
Fatal() << "the name " << base << " cannot be imported from "
<< "two different modules yet\n";
@@ -1861,20 +1828,16 @@ void Wasm2JSGlue::emitPreES6() {
}
baseModuleMap[base] = module;
- out << "import { "
- << base.str
- << " } from '"
- << module.str
- << "';\n";
+ out << "import { " << base.str << " } from '" << module.str << "';\n";
};
ImportInfo imports(wasm);
- ModuleUtils::iterImportedGlobals(wasm, [&](Global* import) {
- noteImport(import->module, import->base);
- });
+ ModuleUtils::iterImportedGlobals(
+ wasm, [&](Global* import) { noteImport(import->module, import->base); });
ModuleUtils::iterImportedFunctions(wasm, [&](Function* import) {
- // The scratch memory helpers are emitted in the glue, see code and comments below.
+ // The scratch memory helpers are emitted in the glue, see code and comments
+ // below.
if (ABI::wasm2js::isScratchMemoryHelper(import->base)) {
return;
}
@@ -1932,8 +1895,7 @@ void Wasm2JSGlue::emitPostES6() {
{
auto pages = wasm.memory.initial == 0 ? 1 : wasm.memory.initial.addr;
out << "var mem" << moduleName.str << " = new ArrayBuffer("
- << pages * Memory::kPageSize
- << ");\n";
+ << pages * Memory::kPageSize << ");\n";
}
emitMemory(std::string("mem") + moduleName.str,
@@ -1943,23 +1905,24 @@ void Wasm2JSGlue::emitPostES6() {
// Actually invoke the `asmFunc` generated function, passing in all global
// values followed by all imports
out << "var ret" << moduleName.str << " = " << moduleName.str << "({"
- << "Math,"
- << "Int8Array,"
- << "Uint8Array,"
- << "Int16Array,"
- << "Uint16Array,"
- << "Int32Array,"
- << "Uint32Array,"
- << "Float32Array,"
- << "Float64Array,"
- << "NaN,"
- << "Infinity"
- << "}, {";
+ << "Math,"
+ << "Int8Array,"
+ << "Uint8Array,"
+ << "Int16Array,"
+ << "Uint16Array,"
+ << "Int32Array,"
+ << "Uint32Array,"
+ << "Float32Array,"
+ << "Float64Array,"
+ << "NaN,"
+ << "Infinity"
+ << "}, {";
out << "abort:function() { throw new Error('abort'); }";
ModuleUtils::iterImportedFunctions(wasm, [&](Function* import) {
- // The scratch memory helpers are emitted in the glue, see code and comments below.
+ // The scratch memory helpers are emitted in the glue, see code and comments
+ // below.
if (ABI::wasm2js::isScratchMemoryHelper(import->base)) {
return;
}
@@ -1984,25 +1947,24 @@ void Wasm2JSGlue::emitPostES6() {
continue;
}
std::ostringstream export_name;
- for (auto *ptr = exp->name.str; *ptr; ptr++) {
+ for (auto* ptr = exp->name.str; *ptr; ptr++) {
if (*ptr == '-') {
export_name << '_';
} else {
export_name << *ptr;
}
}
- out << "export var "
- << asmangle(exp->name.str)
- << " = ret"
- << moduleName.str
- << "."
- << asmangle(exp->name.str)
- << ";\n";
+ out << "export var " << asmangle(exp->name.str) << " = ret"
+ << moduleName.str << "." << asmangle(exp->name.str) << ";\n";
}
}
-void Wasm2JSGlue::emitMemory(std::string buffer, std::string segmentWriter, std::function<std::string (std::string)> accessGlobal) {
- if (wasm.memory.segments.empty()) return;
+void Wasm2JSGlue::emitMemory(
+ std::string buffer,
+ std::string segmentWriter,
+ std::function<std::string(std::string)> accessGlobal) {
+ if (wasm.memory.segments.empty())
+ return;
auto expr = R"(
function(mem) {
@@ -2022,11 +1984,11 @@ void Wasm2JSGlue::emitMemory(std::string buffer, std::string segmentWriter, std:
)";
// var assign$name = ($expr)(mem$name);
- out << "var " << segmentWriter
- << " = (" << expr << ")(" << buffer << ");\n";
+ out << "var " << segmentWriter << " = (" << expr << ")(" << buffer << ");\n";
auto globalOffset = [&](const Memory::Segment& segment) {
- if (auto* c = segment.offset->template dynCast<Const>()) {;
+ if (auto* c = segment.offset->template dynCast<Const>()) {
+ ;
return std::to_string(c->value.getInteger());
}
if (auto* get = segment.offset->template dynCast<GetGlobal>()) {
@@ -2039,11 +2001,8 @@ void Wasm2JSGlue::emitMemory(std::string buffer, std::string segmentWriter, std:
for (auto& seg : wasm.memory.segments) {
assert(!seg.isPassive && "passive segments not implemented yet");
- out << segmentWriter << "("
- << globalOffset(seg)
- << ", \""
- << base64Encode(seg.data)
- << "\");\n";
+ out << segmentWriter << "(" << globalOffset(seg) << ", \""
+ << base64Encode(seg.data) << "\");\n";
}
}
@@ -2058,7 +2017,8 @@ void Wasm2JSGlue::emitScratchMemorySupport() {
needScratchMemory = true;
}
});
- if (!needScratchMemory) return;
+ if (!needScratchMemory)
+ return;
out << R"(
var scratchBuffer = new ArrayBuffer(8);