summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/literal.cpp120
-rw-r--r--src/wasm/wasm-binary.cpp651
-rw-r--r--src/wasm/wasm-emscripten.cpp32
-rw-r--r--src/wasm/wasm-io.cpp15
-rw-r--r--src/wasm/wasm-s-parser.cpp441
-rw-r--r--src/wasm/wasm-type.cpp12
-rw-r--r--src/wasm/wasm-validator.cpp72
-rw-r--r--src/wasm/wasm.cpp38
8 files changed, 916 insertions, 465 deletions
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp
index be92ae03d..3d7303e23 100644
--- a/src/wasm/literal.cpp
+++ b/src/wasm/literal.cpp
@@ -144,10 +144,12 @@ void Literal::getBits(uint8_t (&buf)[16]) const {
}
bool Literal::operator==(const Literal& other) const {
- if (type != other.type)
+ if (type != other.type) {
return false;
- if (type == none)
+ }
+ if (type == none) {
return true;
+ }
uint8_t bits[16], other_bits[16];
getBits(bits);
other.getBits(other_bits);
@@ -238,8 +240,9 @@ void Literal::printDouble(std::ostream& o, double d) {
void Literal::printVec128(std::ostream& o, const std::array<uint8_t, 16>& v) {
o << std::hex;
for (auto i = 0; i < 16; i += 4) {
- if (i)
+ if (i) {
o << " ";
+ }
o << "0x" << std::setfill('0') << std::setw(8)
<< uint32_t(v[i] | (v[i + 1] << 8) | (v[i + 2] << 16) | (v[i + 3] << 24));
}
@@ -276,26 +279,32 @@ std::ostream& operator<<(std::ostream& o, Literal literal) {
}
Literal Literal::countLeadingZeroes() const {
- if (type == Type::i32)
+ if (type == Type::i32) {
return Literal((int32_t)CountLeadingZeroes(i32));
- if (type == Type::i64)
+ }
+ if (type == Type::i64) {
return Literal((int64_t)CountLeadingZeroes(i64));
+ }
WASM_UNREACHABLE();
}
Literal Literal::countTrailingZeroes() const {
- if (type == Type::i32)
+ if (type == Type::i32) {
return Literal((int32_t)CountTrailingZeroes(i32));
- if (type == Type::i64)
+ }
+ if (type == Type::i64) {
return Literal((int64_t)CountTrailingZeroes(i64));
+ }
WASM_UNREACHABLE();
}
Literal Literal::popCount() const {
- if (type == Type::i32)
+ if (type == Type::i32) {
return Literal((int32_t)PopCount(i32));
- if (type == Type::i64)
+ }
+ if (type == Type::i64) {
return Literal((int64_t)PopCount(i64));
+ }
WASM_UNREACHABLE();
}
@@ -315,24 +324,29 @@ Literal Literal::extendToF64() const {
}
Literal Literal::extendS8() const {
- if (type == Type::i32)
+ if (type == Type::i32) {
return Literal(int32_t(int8_t(geti32() & 0xFF)));
- if (type == Type::i64)
+ }
+ if (type == Type::i64) {
return Literal(int64_t(int8_t(geti64() & 0xFF)));
+ }
WASM_UNREACHABLE();
}
Literal Literal::extendS16() const {
- if (type == Type::i32)
+ if (type == Type::i32) {
return Literal(int32_t(int16_t(geti32() & 0xFFFF)));
- if (type == Type::i64)
+ }
+ if (type == Type::i64) {
return Literal(int64_t(int16_t(geti64() & 0xFFFF)));
+ }
WASM_UNREACHABLE();
}
Literal Literal::extendS32() const {
- if (type == Type::i64)
+ if (type == Type::i64) {
return Literal(int64_t(int32_t(geti64() & 0xFFFFFFFF)));
+ }
WASM_UNREACHABLE();
}
@@ -342,34 +356,42 @@ Literal Literal::wrapToI32() const {
}
Literal Literal::convertSIToF32() const {
- if (type == Type::i32)
+ if (type == Type::i32) {
return Literal(float(i32));
- if (type == Type::i64)
+ }
+ if (type == Type::i64) {
return Literal(float(i64));
+ }
WASM_UNREACHABLE();
}
Literal Literal::convertUIToF32() const {
- if (type == Type::i32)
+ if (type == Type::i32) {
return Literal(float(uint32_t(i32)));
- if (type == Type::i64)
+ }
+ if (type == Type::i64) {
return Literal(float(uint64_t(i64)));
+ }
WASM_UNREACHABLE();
}
Literal Literal::convertSIToF64() const {
- if (type == Type::i32)
+ if (type == Type::i32) {
return Literal(double(i32));
- if (type == Type::i64)
+ }
+ if (type == Type::i64) {
return Literal(double(i64));
+ }
WASM_UNREACHABLE();
}
Literal Literal::convertUIToF64() const {
- if (type == Type::i32)
+ if (type == Type::i32) {
return Literal(double(uint32_t(i32)));
- if (type == Type::i64)
+ }
+ if (type == Type::i64) {
return Literal(double(uint64_t(i64)));
+ }
WASM_UNREACHABLE();
}
@@ -551,23 +573,29 @@ Literal Literal::sqrt() const {
Literal Literal::demote() const {
auto f64 = getf64();
- if (std::isnan(f64))
+ if (std::isnan(f64)) {
return Literal(float(f64));
- if (std::isinf(f64))
+ }
+ if (std::isinf(f64)) {
return Literal(float(f64));
+ }
// when close to the limit, but still truncatable to a valid value, do that
// see
// https://github.com/WebAssembly/sexpr-wasm-prototype/blob/2d375e8d502327e814d62a08f22da9d9b6b675dc/src/wasm-interpreter.c#L247
uint64_t bits = reinterpreti64();
- if (bits > 0x47efffffe0000000ULL && bits < 0x47effffff0000000ULL)
+ if (bits > 0x47efffffe0000000ULL && bits < 0x47effffff0000000ULL) {
return Literal(std::numeric_limits<float>::max());
- if (bits > 0xc7efffffe0000000ULL && bits < 0xc7effffff0000000ULL)
+ }
+ if (bits > 0xc7efffffe0000000ULL && bits < 0xc7effffff0000000ULL) {
return Literal(-std::numeric_limits<float>::max());
+ }
// when we must convert to infinity, do that
- if (f64 < -std::numeric_limits<float>::max())
+ if (f64 < -std::numeric_limits<float>::max()) {
return Literal(-std::numeric_limits<float>::infinity());
- if (f64 > std::numeric_limits<float>::max())
+ }
+ if (f64 > std::numeric_limits<float>::max()) {
return Literal(std::numeric_limits<float>::infinity());
+ }
return Literal(float(getf64()));
}
@@ -1067,14 +1095,17 @@ Literal Literal::min(const Literal& other) const {
switch (type) {
case Type::f32: {
auto l = getf32(), r = other.getf32();
- if (l == r && l == 0)
+ if (l == r && l == 0) {
return Literal(std::signbit(l) ? l : r);
+ }
auto result = std::min(l, r);
bool lnan = std::isnan(l), rnan = std::isnan(r);
- if (!std::isnan(result) && !lnan && !rnan)
+ if (!std::isnan(result) && !lnan && !rnan) {
return Literal(result);
- if (!lnan && !rnan)
+ }
+ if (!lnan && !rnan) {
return Literal((int32_t)0x7fc00000).castToF32();
+ }
return Literal(lnan ? l : r)
.castToI32()
.or_(Literal(0xc00000))
@@ -1082,14 +1113,17 @@ Literal Literal::min(const Literal& other) const {
}
case Type::f64: {
auto l = getf64(), r = other.getf64();
- if (l == r && l == 0)
+ if (l == r && l == 0) {
return Literal(std::signbit(l) ? l : r);
+ }
auto result = std::min(l, r);
bool lnan = std::isnan(l), rnan = std::isnan(r);
- if (!std::isnan(result) && !lnan && !rnan)
+ if (!std::isnan(result) && !lnan && !rnan) {
return Literal(result);
- if (!lnan && !rnan)
+ }
+ if (!lnan && !rnan) {
return Literal((int64_t)0x7ff8000000000000LL).castToF64();
+ }
return Literal(lnan ? l : r)
.castToI64()
.or_(Literal(int64_t(0x8000000000000LL)))
@@ -1104,14 +1138,17 @@ Literal Literal::max(const Literal& other) const {
switch (type) {
case Type::f32: {
auto l = getf32(), r = other.getf32();
- if (l == r && l == 0)
+ if (l == r && l == 0) {
return Literal(std::signbit(l) ? r : l);
+ }
auto result = std::max(l, r);
bool lnan = std::isnan(l), rnan = std::isnan(r);
- if (!std::isnan(result) && !lnan && !rnan)
+ if (!std::isnan(result) && !lnan && !rnan) {
return Literal(result);
- if (!lnan && !rnan)
+ }
+ if (!lnan && !rnan) {
return Literal((int32_t)0x7fc00000).castToF32();
+ }
return Literal(lnan ? l : r)
.castToI32()
.or_(Literal(0xc00000))
@@ -1119,14 +1156,17 @@ Literal Literal::max(const Literal& other) const {
}
case Type::f64: {
auto l = getf64(), r = other.getf64();
- if (l == r && l == 0)
+ if (l == r && l == 0) {
return Literal(std::signbit(l) ? r : l);
+ }
auto result = std::max(l, r);
bool lnan = std::isnan(l), rnan = std::isnan(r);
- if (!std::isnan(result) && !lnan && !rnan)
+ if (!std::isnan(result) && !lnan && !rnan) {
return Literal(result);
- if (!lnan && !rnan)
+ }
+ if (!lnan && !rnan) {
return Literal((int64_t)0x7ff8000000000000LL).castToF64();
+ }
return Literal(lnan ? l : r)
.castToI64()
.or_(Literal(int64_t(0x8000000000000LL)))
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 6369a79fa..81020cf75 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -63,12 +63,15 @@ void WasmBinaryWriter::write() {
writeDataCount();
writeFunctions();
writeDataSegments();
- if (debugInfo)
+ if (debugInfo) {
writeNames();
- if (sourceMap && !sourceMapUrl.empty())
+ }
+ if (sourceMap && !sourceMapUrl.empty()) {
writeSourceMapUrl();
- if (symbolMap.size() > 0)
+ }
+ if (symbolMap.size() > 0) {
writeSymbolMap();
+ }
if (sourceMap) {
writeSourceMapEpilog();
@@ -81,8 +84,9 @@ void WasmBinaryWriter::write() {
}
void WasmBinaryWriter::writeHeader() {
- if (debug)
+ if (debug) {
std::cerr << "== writeHeader" << std::endl;
+ }
o << int32_t(BinaryConsts::Magic); // magic number \0asm
o << int32_t(BinaryConsts::Version);
}
@@ -109,8 +113,9 @@ void WasmBinaryWriter::writeResizableLimits(Address initial,
template<typename T> int32_t WasmBinaryWriter::startSection(T code) {
o << U32LEB(code);
- if (sourceMap)
+ if (sourceMap) {
sourceMapLocationsSizeAtSectionStart = sourceMapLocations.size();
+ }
return writeU32LEBPlaceholder(); // section size to be filled in later
}
@@ -144,20 +149,24 @@ WasmBinaryWriter::startSubsection(BinaryConsts::UserSections::Subsection code) {
void WasmBinaryWriter::finishSubsection(int32_t start) { finishSection(start); }
void WasmBinaryWriter::writeStart() {
- if (!wasm->start.is())
+ if (!wasm->start.is()) {
return;
- if (debug)
+ }
+ if (debug) {
std::cerr << "== writeStart" << std::endl;
+ }
auto start = startSection(BinaryConsts::Section::Start);
o << U32LEB(getFunctionIndex(wasm->start.str));
finishSection(start);
}
void WasmBinaryWriter::writeMemory() {
- if (!wasm->memory.exists || wasm->memory.imported())
+ if (!wasm->memory.exists || wasm->memory.imported()) {
return;
- if (debug)
+ }
+ if (debug) {
std::cerr << "== writeMemory" << std::endl;
+ }
auto start = startSection(BinaryConsts::Section::Memory);
o << U32LEB(1); // Define 1 memory
writeResizableLimits(wasm->memory.initial,
@@ -168,15 +177,18 @@ void WasmBinaryWriter::writeMemory() {
}
void WasmBinaryWriter::writeTypes() {
- if (wasm->functionTypes.size() == 0)
+ if (wasm->functionTypes.size() == 0) {
return;
- if (debug)
+ }
+ if (debug) {
std::cerr << "== writeTypes" << std::endl;
+ }
auto start = startSection(BinaryConsts::Section::Type);
o << U32LEB(wasm->functionTypes.size());
for (auto& type : wasm->functionTypes) {
- if (debug)
+ if (debug) {
std::cerr << "write one" << std::endl;
+ }
o << S32LEB(BinaryConsts::EncodedType::Func);
o << U32LEB(type->params.size());
for (auto param : type->params) {
@@ -195,18 +207,21 @@ void WasmBinaryWriter::writeTypes() {
int32_t WasmBinaryWriter::getFunctionTypeIndex(Name type) {
// TODO: optimize
for (size_t i = 0; i < wasm->functionTypes.size(); i++) {
- if (wasm->functionTypes[i]->name == type)
+ if (wasm->functionTypes[i]->name == type) {
return i;
+ }
}
abort();
}
void WasmBinaryWriter::writeImports() {
auto num = importInfo->getNumImports();
- if (num == 0)
+ if (num == 0) {
return;
- if (debug)
+ }
+ if (debug) {
std::cerr << "== writeImports" << std::endl;
+ }
auto start = startSection(BinaryConsts::Section::Import);
o << U32LEB(num);
auto writeImportHeader = [&](Importable* import) {
@@ -214,23 +229,26 @@ void WasmBinaryWriter::writeImports() {
writeInlineString(import->base.str);
};
ModuleUtils::iterImportedFunctions(*wasm, [&](Function* func) {
- if (debug)
+ if (debug) {
std::cerr << "write one function" << std::endl;
+ }
writeImportHeader(func);
o << U32LEB(int32_t(ExternalKind::Function));
o << U32LEB(getFunctionTypeIndex(func->type));
});
ModuleUtils::iterImportedGlobals(*wasm, [&](Global* global) {
- if (debug)
+ if (debug) {
std::cerr << "write one global" << std::endl;
+ }
writeImportHeader(global);
o << U32LEB(int32_t(ExternalKind::Global));
o << binaryType(global->type);
o << U32LEB(global->mutable_);
});
if (wasm->memory.imported()) {
- if (debug)
+ if (debug) {
std::cerr << "write one memory" << std::endl;
+ }
writeImportHeader(&wasm->memory);
o << U32LEB(int32_t(ExternalKind::Memory));
writeResizableLimits(wasm->memory.initial,
@@ -239,8 +257,9 @@ void WasmBinaryWriter::writeImports() {
wasm->memory.shared);
}
if (wasm->table.imported()) {
- if (debug)
+ if (debug) {
std::cerr << "write one table" << std::endl;
+ }
writeImportHeader(&wasm->table);
o << U32LEB(int32_t(ExternalKind::Table));
o << S32LEB(BinaryConsts::EncodedType::AnyFunc);
@@ -253,15 +272,18 @@ void WasmBinaryWriter::writeImports() {
}
void WasmBinaryWriter::writeFunctionSignatures() {
- if (importInfo->getNumDefinedFunctions() == 0)
+ if (importInfo->getNumDefinedFunctions() == 0) {
return;
- if (debug)
+ }
+ if (debug) {
std::cerr << "== writeFunctionSignatures" << std::endl;
+ }
auto start = startSection(BinaryConsts::Section::Function);
o << U32LEB(importInfo->getNumDefinedFunctions());
ModuleUtils::iterDefinedFunctions(*wasm, [&](Function* func) {
- if (debug)
+ if (debug) {
std::cerr << "write one" << std::endl;
+ }
o << U32LEB(getFunctionTypeIndex(func->type));
});
finishSection(start);
@@ -272,35 +294,42 @@ void WasmBinaryWriter::writeExpression(Expression* curr) {
}
void WasmBinaryWriter::writeFunctions() {
- if (importInfo->getNumDefinedFunctions() == 0)
+ if (importInfo->getNumDefinedFunctions() == 0) {
return;
- if (debug)
+ }
+ if (debug) {
std::cerr << "== writeFunctions" << std::endl;
+ }
auto start = startSection(BinaryConsts::Section::Code);
o << U32LEB(importInfo->getNumDefinedFunctions());
ModuleUtils::iterDefinedFunctions(*wasm, [&](Function* func) {
size_t sourceMapLocationsSizeAtFunctionStart = sourceMapLocations.size();
- if (debug)
+ if (debug) {
std::cerr << "write one at" << o.size() << std::endl;
+ }
size_t sizePos = writeU32LEBPlaceholder();
size_t start = o.size();
- if (debug)
+ if (debug) {
std::cerr << "writing" << func->name << std::endl;
+ }
// Emit Stack IR if present, and if we can
if (func->stackIR && !sourceMap) {
- if (debug)
+ if (debug) {
std::cerr << "write Stack IR" << std::endl;
+ }
StackIRFunctionStackWriter<WasmBinaryWriter>(func, *this, o, debug);
} else {
- if (debug)
+ if (debug) {
std::cerr << "write Binaryen IR" << std::endl;
+ }
FunctionStackWriter<WasmBinaryWriter>(func, *this, o, sourceMap, debug);
}
size_t size = o.size() - start;
assert(size <= std::numeric_limits<uint32_t>::max());
- if (debug)
+ if (debug) {
std::cerr << "body size: " << size << ", writing at " << sizePos
<< ", next starts at " << o.size() << std::endl;
+ }
auto sizeFieldSize = o.writeAt(sizePos, U32LEB(size));
if (sizeFieldSize != MaxLEB32Bytes) {
// we can save some room, nice
@@ -323,16 +352,19 @@ void WasmBinaryWriter::writeFunctions() {
}
void WasmBinaryWriter::writeGlobals() {
- if (importInfo->getNumDefinedGlobals() == 0)
+ if (importInfo->getNumDefinedGlobals() == 0) {
return;
- if (debug)
+ }
+ if (debug) {
std::cerr << "== writeglobals" << std::endl;
+ }
auto start = startSection(BinaryConsts::Section::Global);
auto num = importInfo->getNumDefinedGlobals();
o << U32LEB(num);
ModuleUtils::iterDefinedGlobals(*wasm, [&](Global* global) {
- if (debug)
+ if (debug) {
std::cerr << "write one" << std::endl;
+ }
o << binaryType(global->type);
o << U32LEB(global->mutable_);
writeExpression(global->init);
@@ -342,15 +374,18 @@ void WasmBinaryWriter::writeGlobals() {
}
void WasmBinaryWriter::writeExports() {
- if (wasm->exports.size() == 0)
+ if (wasm->exports.size() == 0) {
return;
- if (debug)
+ }
+ if (debug) {
std::cerr << "== writeexports" << std::endl;
+ }
auto start = startSection(BinaryConsts::Section::Export);
o << U32LEB(wasm->exports.size());
for (auto& curr : wasm->exports) {
- if (debug)
+ if (debug) {
std::cerr << "write one" << std::endl;
+ }
writeInlineString(curr->name.str);
o << U32LEB(int32_t(curr->kind));
switch (curr->kind) {
@@ -383,8 +418,9 @@ void WasmBinaryWriter::writeDataCount() {
}
void WasmBinaryWriter::writeDataSegments() {
- if (wasm->memory.segments.size() == 0)
+ if (wasm->memory.segments.size() == 0) {
return;
+ }
if (wasm->memory.segments.size() > WebLimitations::MaxDataSegments) {
std::cerr << "Some VMs may not accept this binary because it has a large "
<< "number of data segments. Run the limit-segments pass to "
@@ -418,10 +454,12 @@ uint32_t WasmBinaryWriter::getGlobalIndex(Name name) {
}
void WasmBinaryWriter::writeFunctionTableDeclaration() {
- if (!wasm->table.exists || wasm->table.imported())
+ if (!wasm->table.exists || wasm->table.imported()) {
return;
- if (debug)
+ }
+ if (debug) {
std::cerr << "== writeFunctionTableDeclaration" << std::endl;
+ }
auto start = startSection(BinaryConsts::Section::Table);
o << U32LEB(1); // Declare 1 table.
o << S32LEB(BinaryConsts::EncodedType::AnyFunc);
@@ -436,8 +474,9 @@ void WasmBinaryWriter::writeTableElements() {
if (!wasm->table.exists || wasm->table.segments.size() == 0) {
return;
}
- if (debug)
+ if (debug) {
std::cerr << "== writeTableElements" << std::endl;
+ }
auto start = startSection(BinaryConsts::Section::Element);
o << U32LEB(wasm->table.segments.size());
@@ -460,10 +499,12 @@ void WasmBinaryWriter::writeNames() {
hasContents = true;
getFunctionIndex(wasm->functions[0]->name); // generate mappedFunctions
}
- if (!hasContents)
+ if (!hasContents) {
return;
- if (debug)
+ }
+ if (debug) {
std::cerr << "== writeNames" << std::endl;
+ }
auto start = startSection(BinaryConsts::Section::User);
writeInlineString(BinaryConsts::UserSections::Name);
auto substart =
@@ -484,8 +525,9 @@ void WasmBinaryWriter::writeNames() {
}
void WasmBinaryWriter::writeSourceMapUrl() {
- if (debug)
+ if (debug) {
std::cerr << "== writeSourceMapUrl" << std::endl;
+ }
auto start = startSection(BinaryConsts::Section::User);
writeInlineString(BinaryConsts::UserSections::SourceMapUrl);
writeInlineString(sourceMapUrl.c_str());
@@ -509,8 +551,9 @@ void WasmBinaryWriter::initializeDebugInfo() {
void WasmBinaryWriter::writeSourceMapProlog() {
*sourceMap << "{\"version\":3,\"sources\":[";
for (size_t i = 0; i < wasm->debugInfoFileNames.size(); i++) {
- if (i > 0)
+ if (i > 0) {
*sourceMap << ",";
+ }
// TODO respect JSON string encoding, e.g. quotes and control chars.
*sourceMap << "\"" << wasm->debugInfoFileNames[i] << "\"";
}
@@ -695,20 +738,23 @@ void WasmBinaryWriter::emitBuffer(const char* data, size_t size) {
}
void WasmBinaryWriter::emitString(const char* str) {
- if (debug)
+ if (debug) {
std::cerr << "emitString " << str << std::endl;
+ }
emitBuffer(str, strlen(str) + 1);
}
void WasmBinaryWriter::finishUp() {
- if (debug)
+ if (debug) {
std::cerr << "finishUp" << std::endl;
+ }
// finish buffers
for (const auto& buffer : buffersToWrite) {
- if (debug)
+ if (debug) {
std::cerr << "writing buffer" << (int)buffer.data[0] << ","
<< (int)buffer.data[1] << " at " << o.size()
<< " and pointer is at " << buffer.pointerLocation << std::endl;
+ }
o.writeAt(buffer.pointerLocation, (uint32_t)o.size());
for (size_t i = 0; i < buffer.size; i++) {
o << (uint8_t)buffer.data[i];
@@ -727,8 +773,9 @@ void WasmBinaryBuilder::read() {
while (more()) {
uint32_t sectionCode = getU32LEB();
uint32_t payloadLen = getU32LEB();
- if (pos + payloadLen > input.size())
+ if (pos + payloadLen > input.size()) {
throwError("Section extends beyond end of input");
+ }
auto oldPos = pos;
@@ -840,129 +887,154 @@ void WasmBinaryBuilder::readUserSection(size_t payloadLen) {
}
uint8_t WasmBinaryBuilder::getInt8() {
- if (!more())
+ if (!more()) {
throwError("unexpected end of input");
- if (debug)
+ }
+ if (debug) {
std::cerr << "getInt8: " << (int)(uint8_t)input[pos] << " (at " << pos
<< ")" << std::endl;
+ }
return input[pos++];
}
uint16_t WasmBinaryBuilder::getInt16() {
- if (debug)
+ if (debug) {
std::cerr << "<==" << std::endl;
+ }
auto ret = uint16_t(getInt8());
ret |= uint16_t(getInt8()) << 8;
- if (debug)
+ if (debug) {
std::cerr << "getInt16: " << ret << "/0x" << std::hex << ret << std::dec
<< " ==>" << std::endl;
+ }
return ret;
}
uint32_t WasmBinaryBuilder::getInt32() {
- if (debug)
+ if (debug) {
std::cerr << "<==" << std::endl;
+ }
auto ret = uint32_t(getInt16());
ret |= uint32_t(getInt16()) << 16;
- if (debug)
+ if (debug) {
std::cerr << "getInt32: " << ret << "/0x" << std::hex << ret << std::dec
<< " ==>" << std::endl;
+ }
return ret;
}
uint64_t WasmBinaryBuilder::getInt64() {
- if (debug)
+ if (debug) {
std::cerr << "<==" << std::endl;
+ }
auto ret = uint64_t(getInt32());
ret |= uint64_t(getInt32()) << 32;
- if (debug)
+ if (debug) {
std::cerr << "getInt64: " << ret << "/0x" << std::hex << ret << std::dec
<< " ==>" << std::endl;
+ }
return ret;
}
uint8_t WasmBinaryBuilder::getLaneIndex(size_t lanes) {
- if (debug)
+ if (debug) {
std::cerr << "<==" << std::endl;
+ }
auto ret = getInt8();
- if (ret >= lanes)
+ if (ret >= lanes) {
throwError("Illegal lane index");
- if (debug)
+ }
+ if (debug) {
std::cerr << "getLaneIndex(" << lanes << "): " << ret << " ==>"
<< std::endl;
+ }
return ret;
}
Literal WasmBinaryBuilder::getFloat32Literal() {
- if (debug)
+ if (debug) {
std::cerr << "<==" << std::endl;
+ }
auto ret = Literal(getInt32());
ret = ret.castToF32();
- if (debug)
+ if (debug) {
std::cerr << "getFloat32: " << ret << " ==>" << std::endl;
+ }
return ret;
}
Literal WasmBinaryBuilder::getFloat64Literal() {
- if (debug)
+ if (debug) {
std::cerr << "<==" << std::endl;
+ }
auto ret = Literal(getInt64());
ret = ret.castToF64();
- if (debug)
+ if (debug) {
std::cerr << "getFloat64: " << ret << " ==>" << std::endl;
+ }
return ret;
}
Literal WasmBinaryBuilder::getVec128Literal() {
- if (debug)
+ if (debug) {
std::cerr << "<==" << std::endl;
+ }
std::array<uint8_t, 16> bytes;
for (auto i = 0; i < 16; ++i) {
bytes[i] = getInt8();
}
auto ret = Literal(bytes.data());
- if (debug)
+ if (debug) {
std::cerr << "getVec128: " << ret << " ==>" << std::endl;
+ }
return ret;
}
uint32_t WasmBinaryBuilder::getU32LEB() {
- if (debug)
+ if (debug) {
std::cerr << "<==" << std::endl;
+ }
U32LEB ret;
ret.read([&]() { return getInt8(); });
- if (debug)
+ if (debug) {
std::cerr << "getU32LEB: " << ret.value << " ==>" << std::endl;
+ }
return ret.value;
}
uint64_t WasmBinaryBuilder::getU64LEB() {
- if (debug)
+ if (debug) {
std::cerr << "<==" << std::endl;
+ }
U64LEB ret;
ret.read([&]() { return getInt8(); });
- if (debug)
+ if (debug) {
std::cerr << "getU64LEB: " << ret.value << " ==>" << std::endl;
+ }
return ret.value;
}
int32_t WasmBinaryBuilder::getS32LEB() {
- if (debug)
+ if (debug) {
std::cerr << "<==" << std::endl;
+ }
S32LEB ret;
ret.read([&]() { return (int8_t)getInt8(); });
- if (debug)
+ if (debug) {
std::cerr << "getS32LEB: " << ret.value << " ==>" << std::endl;
+ }
return ret.value;
}
int64_t WasmBinaryBuilder::getS64LEB() {
- if (debug)
+ if (debug) {
std::cerr << "<==" << std::endl;
+ }
S64LEB ret;
ret.read([&]() { return (int8_t)getInt8(); });
- if (debug)
+ if (debug) {
std::cerr << "getS64LEB: " << ret.value << " ==>" << std::endl;
+ }
return ret.value;
}
@@ -996,8 +1068,9 @@ Type WasmBinaryBuilder::getConcreteType() {
}
Name WasmBinaryBuilder::getInlineString() {
- if (debug)
+ if (debug) {
std::cerr << "<==" << std::endl;
+ }
auto len = getU32LEB();
std::string str;
for (size_t i = 0; i < len; i++) {
@@ -1009,61 +1082,71 @@ Name WasmBinaryBuilder::getInlineString() {
}
str = str + curr;
}
- if (debug)
+ if (debug) {
std::cerr << "getInlineString: " << str << " ==>" << std::endl;
+ }
return Name(str);
}
void WasmBinaryBuilder::verifyInt8(int8_t x) {
int8_t y = getInt8();
- if (x != y)
+ if (x != y) {
throwError("surprising value");
+ }
}
void WasmBinaryBuilder::verifyInt16(int16_t x) {
int16_t y = getInt16();
- if (x != y)
+ if (x != y) {
throwError("surprising value");
+ }
}
void WasmBinaryBuilder::verifyInt32(int32_t x) {
int32_t y = getInt32();
- if (x != y)
+ if (x != y) {
throwError("surprising value");
+ }
}
void WasmBinaryBuilder::verifyInt64(int64_t x) {
int64_t y = getInt64();
- if (x != y)
+ if (x != y) {
throwError("surprising value");
+ }
}
void WasmBinaryBuilder::ungetInt8() {
assert(pos > 0);
- if (debug)
+ if (debug) {
std::cerr << "ungetInt8 (at " << pos << ")" << std::endl;
+ }
pos--;
}
void WasmBinaryBuilder::readHeader() {
- if (debug)
+ if (debug) {
std::cerr << "== readHeader" << std::endl;
+ }
verifyInt32(BinaryConsts::Magic);
verifyInt32(BinaryConsts::Version);
}
void WasmBinaryBuilder::readStart() {
- if (debug)
+ if (debug) {
std::cerr << "== readStart" << std::endl;
+ }
startIndex = getU32LEB();
}
void WasmBinaryBuilder::readMemory() {
- if (debug)
+ if (debug) {
std::cerr << "== readMemory" << std::endl;
+ }
auto numMemories = getU32LEB();
- if (!numMemories)
+ if (!numMemories) {
return;
+ }
if (numMemories != 1) {
throwError("Must be exactly 1 memory");
}
@@ -1078,22 +1161,26 @@ void WasmBinaryBuilder::readMemory() {
}
void WasmBinaryBuilder::readSignatures() {
- if (debug)
+ if (debug) {
std::cerr << "== readSignatures" << std::endl;
+ }
size_t numTypes = getU32LEB();
- if (debug)
+ if (debug) {
std::cerr << "num: " << numTypes << std::endl;
+ }
for (size_t i = 0; i < numTypes; i++) {
- if (debug)
+ if (debug) {
std::cerr << "read one" << std::endl;
+ }
auto curr = make_unique<FunctionType>();
auto form = getS32LEB();
if (form != BinaryConsts::EncodedType::Func) {
throwError("bad signature form " + std::to_string(form));
}
size_t numParams = getU32LEB();
- if (debug)
+ if (debug) {
std::cerr << "num params: " << numParams << std::endl;
+ }
for (size_t j = 0; j < numParams; j++) {
curr->params.push_back(getConcreteType());
}
@@ -1126,25 +1213,30 @@ void WasmBinaryBuilder::getResizableLimits(Address& initial,
initial = getU32LEB();
bool hasMax = (flags & BinaryConsts::HasMaximum) != 0;
bool isShared = (flags & BinaryConsts::IsShared) != 0;
- if (isShared && !hasMax)
+ if (isShared && !hasMax) {
throwError("shared memory must have max size");
+ }
shared = isShared;
- if (hasMax)
+ if (hasMax) {
max = getU32LEB();
- else
+ } else {
max = defaultIfNoMax;
+ }
}
void WasmBinaryBuilder::readImports() {
- if (debug)
+ if (debug) {
std::cerr << "== readImports" << std::endl;
+ }
size_t num = getU32LEB();
- if (debug)
+ if (debug) {
std::cerr << "num: " << num << std::endl;
+ }
Builder builder(wasm);
for (size_t i = 0; i < num; i++) {
- if (debug)
+ if (debug) {
std::cerr << "read one" << std::endl;
+ }
auto module = getInlineString();
auto base = getInlineString();
auto kind = (ExternalKind)getU32LEB();
@@ -1176,14 +1268,16 @@ void WasmBinaryBuilder::readImports() {
wasm.table.name = Name(std::string("timport$") + std::to_string(i));
auto elementType = getS32LEB();
WASM_UNUSED(elementType);
- if (elementType != BinaryConsts::EncodedType::AnyFunc)
+ if (elementType != BinaryConsts::EncodedType::AnyFunc) {
throwError("Imported table type is not AnyFunc");
+ }
wasm.table.exists = true;
bool is_shared;
getResizableLimits(
wasm.table.initial, wasm.table.max, is_shared, Table::kUnlimitedSize);
- if (is_shared)
+ if (is_shared) {
throwError("Tables may not be shared");
+ }
break;
}
case ExternalKind::Memory: {
@@ -1228,14 +1322,17 @@ void WasmBinaryBuilder::requireFunctionContext(const char* error) {
}
void WasmBinaryBuilder::readFunctionSignatures() {
- if (debug)
+ if (debug) {
std::cerr << "== readFunctionSignatures" << std::endl;
+ }
size_t num = getU32LEB();
- if (debug)
+ if (debug) {
std::cerr << "num: " << num << std::endl;
+ }
for (size_t i = 0; i < num; i++) {
- if (debug)
+ if (debug) {
std::cerr << "read one" << std::endl;
+ }
auto index = getU32LEB();
if (index >= wasm.functionTypes.size()) {
throwError("invalid function type index for function");
@@ -1245,15 +1342,17 @@ void WasmBinaryBuilder::readFunctionSignatures() {
}
void WasmBinaryBuilder::readFunctions() {
- if (debug)
+ if (debug) {
std::cerr << "== readFunctions" << std::endl;
+ }
size_t total = getU32LEB();
if (total != functionTypes.size()) {
throwError("invalid function section size, must equal types");
}
for (size_t i = 0; i < total; i++) {
- if (debug)
+ if (debug) {
std::cerr << "read one at " << pos << std::endl;
+ }
size_t size = getU32LEB();
if (size == 0) {
throwError("empty function size");
@@ -1267,8 +1366,9 @@ void WasmBinaryBuilder::readFunctions() {
readNextDebugLocation();
auto type = functionTypes[i];
- if (debug)
+ if (debug) {
std::cerr << "reading " << i << std::endl;
+ }
func->type = type->name;
func->result = type->result;
for (size_t j = 0; j < type->params.size(); j++) {
@@ -1286,8 +1386,9 @@ void WasmBinaryBuilder::readFunctions() {
std::swap(func->prologLocation, debugLocation);
{
// process the function body
- if (debug)
+ if (debug) {
std::cerr << "processing function: " << i << std::endl;
+ }
nextLabel = 0;
debugLocation.clear();
willBeIgnored = false;
@@ -1312,20 +1413,24 @@ void WasmBinaryBuilder::readFunctions() {
debugLocation.clear();
functions.push_back(func);
}
- if (debug)
+ if (debug) {
std::cerr << " end function bodies" << std::endl;
+ }
}
void WasmBinaryBuilder::readExports() {
- if (debug)
+ if (debug) {
std::cerr << "== readExports" << std::endl;
+ }
size_t num = getU32LEB();
- if (debug)
+ if (debug) {
std::cerr << "num: " << num << std::endl;
+ }
std::set<Name> names;
for (size_t i = 0; i < num; i++) {
- if (debug)
+ if (debug) {
std::cerr << "read one" << std::endl;
+ }
auto curr = new Export;
curr->name = getInlineString();
if (names.count(curr->name) > 0) {
@@ -1344,8 +1449,9 @@ static int32_t readBase64VLQ(std::istream& in) {
uint32_t shift = 0;
while (1) {
auto ch = in.get();
- if (ch == EOF)
+ if (ch == EOF) {
throw MapParseException("unexpected EOF in the middle of VLQ");
+ }
if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch < 'g')) {
// last number digit
uint32_t digit = ch < 'a' ? ch - 'A' : ch - 'a' + 26;
@@ -1365,17 +1471,20 @@ static int32_t readBase64VLQ(std::istream& in) {
}
void WasmBinaryBuilder::readSourceMapHeader() {
- if (!sourceMap)
+ if (!sourceMap) {
return;
+ }
auto skipWhitespace = [&]() {
- while (sourceMap->peek() == ' ' || sourceMap->peek() == '\n')
+ while (sourceMap->peek() == ' ' || sourceMap->peek() == '\n') {
sourceMap->get();
+ }
};
auto maybeReadChar = [&](char expected) {
- if (sourceMap->peek() != expected)
+ if (sourceMap->peek() != expected) {
return false;
+ }
sourceMap->get();
return true;
};
@@ -1394,13 +1503,15 @@ void WasmBinaryBuilder::readSourceMapHeader() {
size_t pos;
while (1) {
int ch = sourceMap->get();
- if (ch == EOF)
+ if (ch == EOF) {
return false;
+ }
if (ch == '\"') {
if (matching) {
// we matched a terminating quote.
- if (pos == len)
+ if (pos == len) {
break;
+ }
matching = false;
} else {
matching = true;
@@ -1428,8 +1539,9 @@ void WasmBinaryBuilder::readSourceMapHeader() {
if (ch == EOF) {
throw MapParseException("unexpected EOF in the middle of string");
}
- if (ch == '\"')
+ if (ch == '\"') {
break;
+ }
vec.push_back(ch);
}
}
@@ -1473,8 +1585,9 @@ void WasmBinaryBuilder::readSourceMapHeader() {
}
void WasmBinaryBuilder::readNextDebugLocation() {
- if (!sourceMap)
+ if (!sourceMap) {
return;
+ }
while (nextDebugLocation.first && nextDebugLocation.first <= pos) {
if (nextDebugLocation.first < pos) {
@@ -1523,18 +1636,22 @@ Expression* WasmBinaryBuilder::readExpression() {
}
void WasmBinaryBuilder::readGlobals() {
- if (debug)
+ if (debug) {
std::cerr << "== readGlobals" << std::endl;
+ }
size_t num = getU32LEB();
- if (debug)
+ if (debug) {
std::cerr << "num: " << num << std::endl;
+ }
for (size_t i = 0; i < num; i++) {
- if (debug)
+ if (debug) {
std::cerr << "read one" << std::endl;
+ }
auto type = getConcreteType();
auto mutable_ = getU32LEB();
- if (mutable_ & ~1)
+ if (mutable_ & ~1) {
throwError("Global mutability must be 0 or 1");
+ }
auto* init = readExpression();
wasm.addGlobal(
Builder::makeGlobal("global$" + std::to_string(i),
@@ -1545,16 +1662,18 @@ void WasmBinaryBuilder::readGlobals() {
}
void WasmBinaryBuilder::processExpressions() {
- if (debug)
+ if (debug) {
std::cerr << "== processExpressions" << std::endl;
+ }
unreachableInTheWasmSense = false;
while (1) {
Expression* curr;
auto ret = readExpression(curr);
if (!curr) {
lastSeparator = ret;
- if (debug)
+ if (debug) {
std::cerr << "== processExpressions finished" << std::endl;
+ }
return;
}
expressionStack.push_back(curr);
@@ -1567,13 +1686,15 @@ void WasmBinaryBuilder::processExpressions() {
if (pos == endOfFunction) {
throwError("Reached function end without seeing End opcode");
}
- if (!more())
+ if (!more()) {
throwError("unexpected end of input");
+ }
auto peek = input[pos];
if (peek == BinaryConsts::End || peek == BinaryConsts::Else) {
- if (debug)
+ if (debug) {
std::cerr << "== processExpressions finished with unreachable"
<< std::endl;
+ }
readNextDebugLocation();
lastSeparator = BinaryConsts::ASTNodes(peek);
pos++;
@@ -1587,8 +1708,9 @@ void WasmBinaryBuilder::processExpressions() {
}
void WasmBinaryBuilder::skipUnreachableCode() {
- if (debug)
+ if (debug) {
std::cerr << "== skipUnreachableCode" << std::endl;
+ }
// preserve the stack, and restore it. it contains the instruction that made
// us unreachable, and we can ignore anything after it. things after it may
// pop, we want to undo that
@@ -1608,8 +1730,9 @@ void WasmBinaryBuilder::skipUnreachableCode() {
Expression* curr;
auto ret = readExpression(curr);
if (!curr) {
- if (debug)
+ if (debug) {
std::cerr << "== skipUnreachableCode finished" << std::endl;
+ }
lastSeparator = ret;
unreachableInTheWasmSense = false;
willBeIgnored = before;
@@ -1621,15 +1744,17 @@ void WasmBinaryBuilder::skipUnreachableCode() {
}
Expression* WasmBinaryBuilder::popExpression() {
- if (debug)
+ if (debug) {
std::cerr << "== popExpression" << std::endl;
+ }
if (expressionStack.empty()) {
if (unreachableInTheWasmSense) {
// in unreachable code, trying to pop past the polymorphic stack
// area results in receiving unreachables
- if (debug)
+ if (debug) {
std::cerr << "== popping unreachable from polymorphic stack"
<< std::endl;
+ }
return allocator.alloc<Unreachable>();
}
throwError(
@@ -1644,8 +1769,9 @@ Expression* WasmBinaryBuilder::popExpression() {
Expression* WasmBinaryBuilder::popNonVoidExpression() {
auto* ret = popExpression();
- if (ret->type != none)
+ if (ret->type != none) {
return ret;
+ }
// we found a void, so this is stacky code that we must handle carefully
Builder builder(wasm);
// add elements until we find a non-void
@@ -1654,8 +1780,9 @@ Expression* WasmBinaryBuilder::popNonVoidExpression() {
while (1) {
auto* curr = popExpression();
expressions.push_back(curr);
- if (curr->type != none)
+ if (curr->type != none) {
break;
+ }
}
auto* block = builder.makeBlock();
while (!expressions.empty()) {
@@ -1686,8 +1813,9 @@ Name WasmBinaryBuilder::getGlobalName(Index index) {
ModuleUtils::iterImportedGlobals(wasm, add);
ModuleUtils::iterDefinedGlobals(wasm, add);
}
- if (index == Index(-1))
+ if (index == Index(-1)) {
return Name("null"); // just a force-rebuild
+ }
if (mappedGlobals.count(index) == 0) {
throwError("bad global index");
}
@@ -1755,15 +1883,17 @@ void WasmBinaryBuilder::processFunctions() {
}
void WasmBinaryBuilder::readDataCount() {
- if (debug)
+ if (debug) {
std::cerr << "== readDataCount" << std::endl;
+ }
hasDataCount = true;
dataCount = getU32LEB();
}
void WasmBinaryBuilder::readDataSegments() {
- if (debug)
+ if (debug) {
std::cerr << "== readDataSegments" << std::endl;
+ }
auto num = getU32LEB();
for (size_t i = 0; i < num; i++) {
Memory::Segment curr;
@@ -1792,34 +1922,42 @@ void WasmBinaryBuilder::readDataSegments() {
}
void WasmBinaryBuilder::readFunctionTableDeclaration() {
- if (debug)
+ if (debug) {
std::cerr << "== readFunctionTableDeclaration" << std::endl;
+ }
auto numTables = getU32LEB();
- if (numTables != 1)
+ if (numTables != 1) {
throwError("Only 1 table definition allowed in MVP");
- if (wasm.table.exists)
+ }
+ if (wasm.table.exists) {
throwError("Table cannot be both imported and defined");
+ }
wasm.table.exists = true;
auto elemType = getS32LEB();
- if (elemType != BinaryConsts::EncodedType::AnyFunc)
+ if (elemType != BinaryConsts::EncodedType::AnyFunc) {
throwError("ElementType must be AnyFunc in MVP");
+ }
bool is_shared;
getResizableLimits(
wasm.table.initial, wasm.table.max, is_shared, Table::kUnlimitedSize);
- if (is_shared)
+ if (is_shared) {
throwError("Tables may not be shared");
+ }
}
void WasmBinaryBuilder::readTableElements() {
- if (debug)
+ if (debug) {
std::cerr << "== readTableElements" << std::endl;
+ }
auto numSegments = getU32LEB();
- if (numSegments >= Table::kMaxSize)
+ if (numSegments >= Table::kMaxSize) {
throwError("Too many segments");
+ }
for (size_t i = 0; i < numSegments; i++) {
auto tableIndex = getU32LEB();
- if (tableIndex != 0)
+ if (tableIndex != 0) {
throwError("Table elements must refer to table 0 in MVP");
+ }
wasm.table.segments.emplace_back(readExpression());
auto& indexSegment = functionTable[i];
@@ -1868,8 +2006,9 @@ static void escapeName(Name& name) {
}
void WasmBinaryBuilder::readNames(size_t payloadLen) {
- if (debug)
+ if (debug) {
std::cerr << "== readNames" << std::endl;
+ }
auto sectionPos = pos;
while (pos < sectionPos + payloadLen) {
auto nameType = getU32LEB();
@@ -1958,16 +2097,18 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
if (pos == endOfFunction) {
throwError("Reached function end without seeing End opcode");
}
- if (debug)
+ if (debug) {
std::cerr << "zz recurse into " << ++depth << " at " << pos << std::endl;
+ }
readNextDebugLocation();
std::set<Function::DebugLocation> currDebugLocation;
if (debugLocation.size()) {
currDebugLocation.insert(*debugLocation.begin());
}
uint8_t code = getInt8();
- if (debug)
+ if (debug) {
std::cerr << "readExpression seeing " << (int)code << std::endl;
+ }
switch (code) {
case BinaryConsts::Block:
visitBlock((curr = allocator.alloc<Block>())->cast<Block>());
@@ -2028,76 +2169,103 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
break;
case BinaryConsts::AtomicPrefix: {
code = static_cast<uint8_t>(getU32LEB());
- if (maybeVisitLoad(curr, code, /*isAtomic=*/true))
+ if (maybeVisitLoad(curr, code, /*isAtomic=*/true)) {
break;
- if (maybeVisitStore(curr, code, /*isAtomic=*/true))
+ }
+ if (maybeVisitStore(curr, code, /*isAtomic=*/true)) {
break;
- if (maybeVisitAtomicRMW(curr, code))
+ }
+ if (maybeVisitAtomicRMW(curr, code)) {
break;
- if (maybeVisitAtomicCmpxchg(curr, code))
+ }
+ if (maybeVisitAtomicCmpxchg(curr, code)) {
break;
- if (maybeVisitAtomicWait(curr, code))
+ }
+ if (maybeVisitAtomicWait(curr, code)) {
break;
- if (maybeVisitAtomicNotify(curr, code))
+ }
+ if (maybeVisitAtomicNotify(curr, code)) {
break;
+ }
throwError("invalid code after atomic prefix: " + std::to_string(code));
break;
}
case BinaryConsts::MiscPrefix: {
auto opcode = getU32LEB();
- if (maybeVisitTruncSat(curr, opcode))
+ if (maybeVisitTruncSat(curr, opcode)) {
break;
- if (maybeVisitMemoryInit(curr, opcode))
+ }
+ if (maybeVisitMemoryInit(curr, opcode)) {
break;
- if (maybeVisitDataDrop(curr, opcode))
+ }
+ if (maybeVisitDataDrop(curr, opcode)) {
break;
- if (maybeVisitMemoryCopy(curr, opcode))
+ }
+ if (maybeVisitMemoryCopy(curr, opcode)) {
break;
- if (maybeVisitMemoryFill(curr, opcode))
+ }
+ if (maybeVisitMemoryFill(curr, opcode)) {
break;
+ }
throwError("invalid code after nontrapping float-to-int prefix: " +
std::to_string(opcode));
break;
}
case BinaryConsts::SIMDPrefix: {
auto opcode = getU32LEB();
- if (maybeVisitSIMDBinary(curr, opcode))
+ if (maybeVisitSIMDBinary(curr, opcode)) {
break;
- if (maybeVisitSIMDUnary(curr, opcode))
+ }
+ if (maybeVisitSIMDUnary(curr, opcode)) {
break;
- if (maybeVisitSIMDConst(curr, opcode))
+ }
+ if (maybeVisitSIMDConst(curr, opcode)) {
break;
- if (maybeVisitSIMDLoad(curr, opcode))
+ }
+ if (maybeVisitSIMDLoad(curr, opcode)) {
break;
- if (maybeVisitSIMDStore(curr, opcode))
+ }
+ if (maybeVisitSIMDStore(curr, opcode)) {
break;
- if (maybeVisitSIMDExtract(curr, opcode))
+ }
+ if (maybeVisitSIMDExtract(curr, opcode)) {
break;
- if (maybeVisitSIMDReplace(curr, opcode))
+ }
+ if (maybeVisitSIMDReplace(curr, opcode)) {
break;
- if (maybeVisitSIMDShuffle(curr, opcode))
+ }
+ if (maybeVisitSIMDShuffle(curr, opcode)) {
break;
- if (maybeVisitSIMDBitselect(curr, opcode))
+ }
+ if (maybeVisitSIMDBitselect(curr, opcode)) {
break;
- if (maybeVisitSIMDShift(curr, opcode))
+ }
+ if (maybeVisitSIMDShift(curr, opcode)) {
break;
+ }
throwError("invalid code after SIMD prefix: " + std::to_string(opcode));
break;
}
default: {
// otherwise, the code is a subcode TODO: optimize
- if (maybeVisitBinary(curr, code))
+ if (maybeVisitBinary(curr, code)) {
break;
- if (maybeVisitUnary(curr, code))
+ }
+ if (maybeVisitUnary(curr, code)) {
break;
- if (maybeVisitConst(curr, code))
+ }
+ if (maybeVisitConst(curr, code)) {
break;
- if (maybeVisitLoad(curr, code, /*isAtomic=*/false))
+ }
+ if (maybeVisitLoad(curr, code, /*isAtomic=*/false)) {
break;
- if (maybeVisitStore(curr, code, /*isAtomic=*/false))
+ }
+ if (maybeVisitStore(curr, code, /*isAtomic=*/false)) {
break;
- if (maybeVisitHost(curr, code))
+ }
+ if (maybeVisitHost(curr, code)) {
break;
+ }
throwError("bad node code " + std::to_string(code));
break;
}
@@ -2105,8 +2273,9 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
if (curr && currDebugLocation.size()) {
currFunction->debugLocations[curr] = *currDebugLocation.begin();
}
- if (debug)
+ if (debug) {
std::cerr << "zz recurse from " << depth-- << " at " << pos << std::endl;
+ }
return BinaryConsts::ASTNodes(code);
}
@@ -2153,8 +2322,9 @@ void WasmBinaryBuilder::pushBlockElements(Block* curr,
}
void WasmBinaryBuilder::visitBlock(Block* curr) {
- if (debug)
+ if (debug) {
std::cerr << "zz node: Block" << std::endl;
+ }
// special-case Block and de-recurse nested blocks in their first position, as
// that is a common pattern that can be very highly nested.
std::vector<Block*> stack;
@@ -2228,8 +2398,9 @@ Expression* WasmBinaryBuilder::getBlockOrSingleton(Type type) {
}
void WasmBinaryBuilder::visitIf(If* curr) {
- if (debug)
+ if (debug) {
std::cerr << "zz node: If" << std::endl;
+ }
curr->type = getType();
curr->condition = popNonVoidExpression();
curr->ifTrue = getBlockOrSingleton(curr->type);
@@ -2243,8 +2414,9 @@ void WasmBinaryBuilder::visitIf(If* curr) {
}
void WasmBinaryBuilder::visitLoop(Loop* curr) {
- if (debug)
+ if (debug) {
std::cerr << "zz node: Loop" << std::endl;
+ }
curr->type = getType();
curr->name = getNextLabel();
breakStack.push_back({curr->name, 0});
@@ -2274,8 +2446,9 @@ void WasmBinaryBuilder::visitLoop(Loop* curr) {
WasmBinaryBuilder::BreakTarget
WasmBinaryBuilder::getBreakTarget(int32_t offset) {
- if (debug)
+ if (debug) {
std::cerr << "getBreakTarget " << offset << std::endl;
+ }
if (breakStack.size() < 1 + size_t(offset)) {
throwError("bad breakindex (low)");
}
@@ -2283,9 +2456,10 @@ WasmBinaryBuilder::getBreakTarget(int32_t offset) {
if (index >= breakStack.size()) {
throwError("bad breakindex (high)");
}
- if (debug)
+ if (debug) {
std::cerr << "breaktarget " << breakStack[index].name << " arity "
<< breakStack[index].arity << std::endl;
+ }
auto& ret = breakStack[index];
// if the break is in literally unreachable code, then we will not emit it
// anyhow, so do not note that the target has breaks to it
@@ -2296,39 +2470,47 @@ WasmBinaryBuilder::getBreakTarget(int32_t offset) {
}
void WasmBinaryBuilder::visitBreak(Break* curr, uint8_t code) {
- if (debug)
+ if (debug) {
std::cerr << "zz node: Break, code " << int32_t(code) << std::endl;
+ }
BreakTarget target = getBreakTarget(getU32LEB());
curr->name = target.name;
- if (code == BinaryConsts::BrIf)
+ if (code == BinaryConsts::BrIf) {
curr->condition = popNonVoidExpression();
- if (target.arity)
+ }
+ if (target.arity) {
curr->value = popNonVoidExpression();
+ }
curr->finalize();
}
void WasmBinaryBuilder::visitSwitch(Switch* curr) {
- if (debug)
+ if (debug) {
std::cerr << "zz node: Switch" << std::endl;
+ }
curr->condition = popNonVoidExpression();
auto numTargets = getU32LEB();
- if (debug)
+ if (debug) {
std::cerr << "targets: " << numTargets << std::endl;
+ }
for (size_t i = 0; i < numTargets; i++) {
curr->targets.push_back(getBreakTarget(getU32LEB()).name);
}
auto defaultTarget = getBreakTarget(getU32LEB());
curr->default_ = defaultTarget.name;
- if (debug)
+ if (debug) {
std::cerr << "default: " << curr->default_ << std::endl;
- if (defaultTarget.arity)
+ }
+ if (defaultTarget.arity) {
curr->value = popNonVoidExpression();
+ }
curr->finalize();
}
void WasmBinaryBuilder::visitCall(Call* curr) {
- if (debug)
+ if (debug) {
std::cerr << "zz node: Call" << std::endl;
+ }
auto index = getU32LEB();
FunctionType* type;
if (index < functionImports.size()) {
@@ -2353,16 +2535,18 @@ void WasmBinaryBuilder::visitCall(Call* curr) {
}
void WasmBinaryBuilder::visitCallIndirect(CallIndirect* curr) {
- if (debug)
+ if (debug) {
std::cerr << "zz node: CallIndirect" << std::endl;
+ }
auto index = getU32LEB();
if (index >= wasm.functionTypes.size()) {
throwError("bad call_indirect function index");
}
auto* fullType = wasm.functionTypes[index].get();
auto reserved = getU32LEB();
- if (reserved != 0)
+ if (reserved != 0) {
throwError("Invalid flags field in call_indirect");
+ }
curr->fullType = fullType->name;
auto num = fullType->params.size();
curr->operands.resize(num);
@@ -2375,8 +2559,9 @@ void WasmBinaryBuilder::visitCallIndirect(CallIndirect* curr) {
}
void WasmBinaryBuilder::visitGetLocal(GetLocal* curr) {
- if (debug)
+ if (debug) {
std::cerr << "zz node: GetLocal " << pos << std::endl;
+ }
requireFunctionContext("local.get");
curr->index = getU32LEB();
if (curr->index >= currFunction->getNumLocals()) {
@@ -2387,8 +2572,9 @@ void WasmBinaryBuilder::visitGetLocal(GetLocal* curr) {
}
void WasmBinaryBuilder::visitSetLocal(SetLocal* curr, uint8_t code) {
- if (debug)
+ if (debug) {
std::cerr << "zz node: Set|TeeLocal" << std::endl;
+ }
requireFunctionContext("local.set outside of function");
curr->index = getU32LEB();
if (curr->index >= currFunction->getNumLocals()) {
@@ -2401,16 +2587,18 @@ void WasmBinaryBuilder::visitSetLocal(SetLocal* curr, uint8_t code) {
}
void WasmBinaryBuilder::visitGetGlobal(GetGlobal* curr) {
- if (debug)
+ if (debug) {
std::cerr << "zz node: GetGlobal " << pos << std::endl;
+ }
auto index = getU32LEB();
curr->name = getGlobalName(index);
curr->type = wasm.getGlobal(curr->name)->type;
}
void WasmBinaryBuilder::visitSetGlobal(SetGlobal* curr) {
- if (debug)
+ if (debug) {
std::cerr << "zz node: SetGlobal" << std::endl;
+ }
auto index = getU32LEB();
curr->name = getGlobalName(index);
curr->value = popNonVoidExpression();
@@ -2419,8 +2607,9 @@ void WasmBinaryBuilder::visitSetGlobal(SetGlobal* curr) {
void WasmBinaryBuilder::readMemoryAccess(Address& alignment, Address& offset) {
auto rawAlignment = getU32LEB();
- if (rawAlignment > 4)
+ if (rawAlignment > 4) {
throwError("Alignment must be of a reasonable size");
+ }
alignment = Pow2(rawAlignment);
offset = getU32LEB();
}
@@ -2514,8 +2703,9 @@ bool WasmBinaryBuilder::maybeVisitLoad(Expression*& out,
default:
return false;
}
- if (debug)
+ if (debug) {
std::cerr << "zz node: Load" << std::endl;
+ }
} else {
switch (code) {
case BinaryConsts::I32AtomicLoad8U:
@@ -2557,8 +2747,9 @@ bool WasmBinaryBuilder::maybeVisitLoad(Expression*& out,
return false;
}
curr->signed_ = false;
- if (debug)
+ if (debug) {
std::cerr << "zz node: AtomicLoad" << std::endl;
+ }
}
curr->isAtomic = isAtomic;
@@ -2666,8 +2857,9 @@ bool WasmBinaryBuilder::maybeVisitStore(Expression*& out,
}
curr->isAtomic = isAtomic;
- if (debug)
+ if (debug) {
std::cerr << "zz node: Store" << std::endl;
+ }
readMemoryAccess(curr->align, curr->offset);
curr->value = popNonVoidExpression();
curr->ptr = popNonVoidExpression();
@@ -2678,8 +2870,9 @@ bool WasmBinaryBuilder::maybeVisitStore(Expression*& out,
bool WasmBinaryBuilder::maybeVisitAtomicRMW(Expression*& out, uint8_t code) {
if (code < BinaryConsts::AtomicRMWOps_Begin ||
- code > BinaryConsts::AtomicRMWOps_End)
+ code > BinaryConsts::AtomicRMWOps_End) {
return false;
+ }
auto* curr = allocator.alloc<AtomicRMW>();
// Set curr to the given opcode, type and size.
@@ -2725,12 +2918,14 @@ bool WasmBinaryBuilder::maybeVisitAtomicRMW(Expression*& out, uint8_t code) {
#undef SET_FOR_OP
#undef SET
- if (debug)
+ if (debug) {
std::cerr << "zz node: AtomicRMW" << std::endl;
+ }
Address readAlign;
readMemoryAccess(readAlign, curr->offset);
- if (readAlign != curr->bytes)
+ if (readAlign != curr->bytes) {
throwError("Align of AtomicRMW must match size");
+ }
curr->value = popNonVoidExpression();
curr->ptr = popNonVoidExpression();
curr->finalize();
@@ -2741,8 +2936,9 @@ bool WasmBinaryBuilder::maybeVisitAtomicRMW(Expression*& out, uint8_t code) {
bool WasmBinaryBuilder::maybeVisitAtomicCmpxchg(Expression*& out,
uint8_t code) {
if (code < BinaryConsts::AtomicCmpxchgOps_Begin ||
- code > BinaryConsts::AtomicCmpxchgOps_End)
+ code > BinaryConsts::AtomicCmpxchgOps_End) {
return false;
+ }
auto* curr = allocator.alloc<AtomicCmpxchg>();
// Set curr to the given type and size.
@@ -2776,12 +2972,14 @@ bool WasmBinaryBuilder::maybeVisitAtomicCmpxchg(Expression*& out,
WASM_UNREACHABLE();
}
- if (debug)
+ if (debug) {
std::cerr << "zz node: AtomicCmpxchg" << std::endl;
+ }
Address readAlign;
readMemoryAccess(readAlign, curr->offset);
- if (readAlign != curr->bytes)
+ if (readAlign != curr->bytes) {
throwError("Align of AtomicCpxchg must match size");
+ }
curr->replacement = popNonVoidExpression();
curr->expected = popNonVoidExpression();
curr->ptr = popNonVoidExpression();
@@ -2791,8 +2989,10 @@ bool WasmBinaryBuilder::maybeVisitAtomicCmpxchg(Expression*& out,
}
bool WasmBinaryBuilder::maybeVisitAtomicWait(Expression*& out, uint8_t code) {
- if (code < BinaryConsts::I32AtomicWait || code > BinaryConsts::I64AtomicWait)
+ if (code < BinaryConsts::I32AtomicWait ||
+ code > BinaryConsts::I64AtomicWait) {
return false;
+ }
auto* curr = allocator.alloc<AtomicWait>();
switch (code) {
@@ -2806,34 +3006,39 @@ bool WasmBinaryBuilder::maybeVisitAtomicWait(Expression*& out, uint8_t code) {
WASM_UNREACHABLE();
}
curr->type = i32;
- if (debug)
+ if (debug) {
std::cerr << "zz node: AtomicWait" << std::endl;
+ }
curr->timeout = popNonVoidExpression();
curr->expected = popNonVoidExpression();
curr->ptr = popNonVoidExpression();
Address readAlign;
readMemoryAccess(readAlign, curr->offset);
- if (readAlign != getTypeSize(curr->expectedType))
+ if (readAlign != getTypeSize(curr->expectedType)) {
throwError("Align of AtomicWait must match size");
+ }
curr->finalize();
out = curr;
return true;
}
bool WasmBinaryBuilder::maybeVisitAtomicNotify(Expression*& out, uint8_t code) {
- if (code != BinaryConsts::AtomicNotify)
+ if (code != BinaryConsts::AtomicNotify) {
return false;
+ }
auto* curr = allocator.alloc<AtomicNotify>();
- if (debug)
+ if (debug) {
std::cerr << "zz node: AtomicNotify" << std::endl;
+ }
curr->type = i32;
curr->notifyCount = popNonVoidExpression();
curr->ptr = popNonVoidExpression();
Address readAlign;
readMemoryAccess(readAlign, curr->offset);
- if (readAlign != getTypeSize(curr->type))
+ if (readAlign != getTypeSize(curr->type)) {
throwError("Align of AtomicNotify must match size");
+ }
curr->finalize();
out = curr;
return true;
@@ -2841,8 +3046,9 @@ bool WasmBinaryBuilder::maybeVisitAtomicNotify(Expression*& out, uint8_t code) {
bool WasmBinaryBuilder::maybeVisitConst(Expression*& out, uint8_t code) {
Const* curr;
- if (debug)
+ if (debug) {
std::cerr << "zz node: Const, code " << code << std::endl;
+ }
switch (code) {
case BinaryConsts::I32Const:
curr = allocator.alloc<Const>();
@@ -3089,8 +3295,9 @@ bool WasmBinaryBuilder::maybeVisitUnary(Expression*& out, uint8_t code) {
default:
return false;
}
- if (debug)
+ if (debug) {
std::cerr << "zz node: Unary" << std::endl;
+ }
curr->value = popNonVoidExpression();
curr->finalize();
out = curr;
@@ -3135,8 +3342,9 @@ bool WasmBinaryBuilder::maybeVisitTruncSat(Expression*& out, uint32_t code) {
default:
return false;
}
- if (debug)
+ if (debug) {
std::cerr << "zz node: Unary (nontrapping float-to-int)" << std::endl;
+ }
curr->value = popNonVoidExpression();
curr->finalize();
out = curr;
@@ -3270,8 +3478,9 @@ bool WasmBinaryBuilder::maybeVisitBinary(Expression*& out, uint8_t code) {
default:
return false;
}
- if (debug)
+ if (debug) {
std::cerr << "zz node: Binary" << std::endl;
+ }
curr->right = popNonVoidExpression();
curr->left = popNonVoidExpression();
curr->finalize();
@@ -3592,8 +3801,9 @@ bool WasmBinaryBuilder::maybeVisitSIMDBinary(Expression*& out, uint32_t code) {
default:
return false;
}
- if (debug)
+ if (debug) {
std::cerr << "zz node: Binary" << std::endl;
+ }
curr->right = popNonVoidExpression();
curr->left = popNonVoidExpression();
curr->finalize();
@@ -3972,8 +4182,9 @@ bool WasmBinaryBuilder::maybeVisitSIMDShift(Expression*& out, uint32_t code) {
}
void WasmBinaryBuilder::visitSelect(Select* curr) {
- if (debug)
+ if (debug) {
std::cerr << "zz node: Select" << std::endl;
+ }
curr->condition = popNonVoidExpression();
curr->ifFalse = popNonVoidExpression();
curr->ifTrue = popNonVoidExpression();
@@ -3981,8 +4192,9 @@ void WasmBinaryBuilder::visitSelect(Select* curr) {
}
void WasmBinaryBuilder::visitReturn(Return* curr) {
- if (debug)
+ if (debug) {
std::cerr << "zz node: Return" << std::endl;
+ }
requireFunctionContext("return");
if (currFunction->result != none) {
curr->value = popNonVoidExpression();
@@ -4008,29 +4220,34 @@ bool WasmBinaryBuilder::maybeVisitHost(Expression*& out, uint8_t code) {
default:
return false;
}
- if (debug)
+ if (debug) {
std::cerr << "zz node: Host" << std::endl;
+ }
auto reserved = getU32LEB();
- if (reserved != 0)
+ if (reserved != 0) {
throwError("Invalid reserved field on grow_memory/current_memory");
+ }
curr->finalize();
out = curr;
return true;
}
void WasmBinaryBuilder::visitNop(Nop* curr) {
- if (debug)
+ if (debug) {
std::cerr << "zz node: Nop" << std::endl;
+ }
}
void WasmBinaryBuilder::visitUnreachable(Unreachable* curr) {
- if (debug)
+ if (debug) {
std::cerr << "zz node: Unreachable" << std::endl;
+ }
}
void WasmBinaryBuilder::visitDrop(Drop* curr) {
- if (debug)
+ if (debug) {
std::cerr << "zz node: Drop" << std::endl;
+ }
curr->value = popNonVoidExpression();
curr->finalize();
}
diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp
index a6a84a974..453780720 100644
--- a/src/wasm/wasm-emscripten.cpp
+++ b/src/wasm/wasm-emscripten.cpp
@@ -86,8 +86,9 @@ Expression* EmscriptenGlueGenerator::generateLoadStackPointer() {
/* type =*/i32);
}
Global* stackPointer = getStackPointerGlobal();
- if (!stackPointer)
+ if (!stackPointer) {
Fatal() << "stack pointer global not found";
+ }
return builder.makeGetGlobal(stackPointer->name, i32);
}
@@ -103,8 +104,9 @@ EmscriptenGlueGenerator::generateStoreStackPointer(Expression* value) {
/* type =*/i32);
}
Global* stackPointer = getStackPointerGlobal();
- if (!stackPointer)
+ if (!stackPointer) {
Fatal() << "stack pointer global not found";
+ }
return builder.makeSetGlobal(stackPointer->name, value);
}
@@ -312,8 +314,9 @@ Function* EmscriptenGlueGenerator::generateMemoryGrowthFunction() {
void EmscriptenGlueGenerator::generateStackInitialization(Address addr) {
auto* stackPointer = getStackPointerGlobal();
assert(!stackPointer->imported());
- if (!stackPointer->init || !stackPointer->init->is<Const>())
+ if (!stackPointer->init || !stackPointer->init->is<Const>()) {
Fatal() << "stack pointer global is not assignable";
+ }
stackPointer->init->cast<Const>()->value = Literal(int32_t(addr));
}
@@ -322,8 +325,9 @@ inline void exportFunction(Module& wasm, Name name, bool must_export) {
assert(!must_export);
return;
}
- if (wasm.getExportOrNull(name))
+ if (wasm.getExportOrNull(name)) {
return; // Already exported
+ }
auto exp = new Export;
exp->name = exp->value = name;
exp->kind = ExternalKind::Function;
@@ -350,8 +354,9 @@ void EmscriptenGlueGenerator::generateDynCallThunks() {
std::vector<NameType> params;
params.emplace_back("fptr", i32); // function pointer param
int p = 0;
- for (const auto& ty : funcType->params)
+ for (const auto& ty : funcType->params) {
params.emplace_back(std::to_string(p++), ty);
+ }
Function* f =
builder.makeFunction(name, std::move(params), funcType->result, {});
Expression* fptr = builder.makeGetLocal(0, i32);
@@ -373,8 +378,9 @@ struct RemoveStackPointer : public PostWalker<RemoveStackPointer> {
void visitGetGlobal(GetGlobal* curr) {
if (getModule()->getGlobalOrNull(curr->name) == stackPointer) {
needStackSave = true;
- if (!builder)
+ if (!builder) {
builder = make_unique<Builder>(*getModule());
+ }
replaceCurrent(builder->makeCall(STACK_SAVE, {}, i32));
}
}
@@ -382,8 +388,9 @@ struct RemoveStackPointer : public PostWalker<RemoveStackPointer> {
void visitSetGlobal(SetGlobal* curr) {
if (getModule()->getGlobalOrNull(curr->name) == stackPointer) {
needStackRestore = true;
- if (!builder)
+ if (!builder) {
builder = make_unique<Builder>(*getModule());
+ }
replaceCurrent(builder->makeCall(STACK_RESTORE, {curr->value}, none));
}
}
@@ -398,8 +405,9 @@ private:
void EmscriptenGlueGenerator::replaceStackPointerGlobal() {
Global* stackPointer = getStackPointerGlobal();
- if (!stackPointer)
+ if (!stackPointer) {
return;
+ }
// Replace all uses of stack pointer global
RemoveStackPointer walker(stackPointer);
@@ -796,8 +804,9 @@ struct FixInvokeFunctionNamesWalker
}
static Name fixEmEHSjLjNames(const Name& name, const std::string& sig) {
- if (name == "emscripten_longjmp_jmpbuf")
+ if (name == "emscripten_longjmp_jmpbuf") {
return "emscripten_longjmp";
+ }
return fixEmExceptionInvoke(name, sig);
}
@@ -840,10 +849,11 @@ template<class C> void printSet(std::ostream& o, C& c) {
o << "[";
bool first = true;
for (auto& item : c) {
- if (first)
+ if (first) {
first = false;
- else
+ } else {
o << ",";
+ }
o << '"' << item << '"';
}
o << "]";
diff --git a/src/wasm/wasm-io.cpp b/src/wasm/wasm-io.cpp
index 1bdb76d5f..90df2de12 100644
--- a/src/wasm/wasm-io.cpp
+++ b/src/wasm/wasm-io.cpp
@@ -37,8 +37,9 @@ static void readTextData(std::string& input, Module& wasm) {
}
void ModuleReader::readText(std::string filename, Module& wasm) {
- if (debug)
+ if (debug) {
std::cerr << "reading text from " << filename << "\n";
+ }
auto input(read_file<std::string>(
filename, Flags::Text, debug ? Flags::Debug : Flags::Release));
readTextData(input, wasm);
@@ -64,8 +65,9 @@ static void readBinaryData(std::vector<char>& input,
void ModuleReader::readBinary(std::string filename,
Module& wasm,
std::string sourceMapFilename) {
- if (debug)
+ if (debug) {
std::cerr << "reading binary from " << filename << "\n";
+ }
auto input(read_file<std::vector<char>>(
filename, Flags::Binary, debug ? Flags::Debug : Flags::Release));
readBinaryData(input, wasm, sourceMapFilename, debug);
@@ -123,8 +125,9 @@ void ModuleWriter::writeText(Module& wasm, Output& output) {
}
void ModuleWriter::writeText(Module& wasm, std::string filename) {
- if (debug)
+ if (debug) {
std::cerr << "writing text to " << filename << "\n";
+ }
Output output(filename, Flags::Text, debug ? Flags::Debug : Flags::Release);
writeText(wasm, output);
}
@@ -140,8 +143,9 @@ void ModuleWriter::writeBinary(Module& wasm, Output& output) {
sourceMapStream->open(sourceMapFilename);
writer.setSourceMap(sourceMapStream.get(), sourceMapUrl);
}
- if (symbolMap.size() > 0)
+ if (symbolMap.size() > 0) {
writer.setSymbolMap(symbolMap);
+ }
writer.write();
buffer.writeTo(output);
if (sourceMapStream) {
@@ -150,8 +154,9 @@ void ModuleWriter::writeBinary(Module& wasm, Output& output) {
}
void ModuleWriter::writeBinary(Module& wasm, std::string filename) {
- if (debug)
+ if (debug) {
std::cerr << "writing binary to " << filename << "\n";
+ }
Output output(filename, Flags::Binary, debug ? Flags::Debug : Flags::Release);
writeBinary(wasm, output);
}
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index bb498329f..cd9eb690a 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -37,12 +37,15 @@ using cashew::IString;
namespace {
int unhex(char c) {
- if (c >= '0' && c <= '9')
+ if (c >= '0' && c <= '9') {
return c - '0';
- if (c >= 'a' && c <= 'f')
+ }
+ if (c >= 'a' && c <= 'f') {
return c - 'a' + 10;
- if (c >= 'A' && c <= 'F')
+ }
+ if (c >= 'A' && c <= 'F') {
return c - 'A' + 10;
+ }
throw wasm::ParseException("invalid hexadecimal");
}
} // namespace
@@ -58,28 +61,33 @@ static Address getCheckedAddress(const Element* s, const char* errorText) {
}
Element::List& Element::list() {
- if (!isList())
+ if (!isList()) {
throw ParseException("expected list", line, col);
+ }
return list_;
}
Element* Element::operator[](unsigned i) {
- if (!isList())
+ if (!isList()) {
throw ParseException("expected list", line, col);
- if (i >= list().size())
+ }
+ if (i >= list().size()) {
throw ParseException("expected more elements in list", line, col);
+ }
return list()[i];
}
IString Element::str() const {
- if (!isStr())
+ if (!isStr()) {
throw ParseException("expected string", line, col);
+ }
return str_;
}
const char* Element::c_str() const {
- if (!isStr())
+ if (!isStr()) {
throw ParseException("expected string", line, col);
+ }
return str_.str;
}
@@ -102,8 +110,9 @@ Element::setMetadata(size_t line_, size_t col_, SourceLocation* startLoc_) {
std::ostream& operator<<(std::ostream& o, Element& e) {
if (e.isList_) {
o << '(';
- for (auto item : e.list_)
+ for (auto item : e.list_) {
o << ' ' << *item;
+ }
o << " )";
} else {
o << e.str_.str;
@@ -130,8 +139,9 @@ Element* SExpressionParser::parse() {
Element* curr = allocator.alloc<Element>();
while (1) {
skipWhitespace();
- if (input[0] == 0)
+ if (input[0] == 0) {
break;
+ }
if (input[0] == '(') {
input++;
stack.push_back(curr);
@@ -156,29 +166,34 @@ Element* SExpressionParser::parse() {
curr->list().push_back(parseString());
}
}
- if (stack.size() != 0)
+ if (stack.size() != 0) {
throw ParseException("stack is not empty", curr->line, curr->col);
+ }
return curr;
}
void SExpressionParser::parseDebugLocation() {
// Extracting debug location (if valid)
char* debugLoc = input + 3; // skipping ";;@"
- while (debugLoc[0] && debugLoc[0] == ' ')
+ while (debugLoc[0] && debugLoc[0] == ' ') {
debugLoc++;
+ }
char* debugLocEnd = debugLoc;
- while (debugLocEnd[0] && debugLocEnd[0] != '\n')
+ while (debugLocEnd[0] && debugLocEnd[0] != '\n') {
debugLocEnd++;
+ }
char* pos = debugLoc;
- while (pos < debugLocEnd && pos[0] != ':')
+ while (pos < debugLocEnd && pos[0] != ':') {
pos++;
+ }
if (pos >= debugLocEnd) {
return; // no line number
}
std::string name(debugLoc, pos);
char* lineStart = ++pos;
- while (pos < debugLocEnd && pos[0] != ':')
+ while (pos < debugLocEnd && pos[0] != ':') {
pos++;
+ }
std::string lineStr(lineStart, pos);
if (pos >= debugLocEnd) {
return; // no column number
@@ -203,19 +218,22 @@ void SExpressionParser::skipWhitespace() {
if (input[2] == '@') {
parseDebugLocation();
}
- while (input[0] && input[0] != '\n')
+ while (input[0] && input[0] != '\n') {
input++;
+ }
line++;
- if (!input[0])
+ if (!input[0]) {
return;
+ }
lineStart = ++input;
} else if (input[0] == '(' && input[1] == ';') {
// Skip nested block comments.
input += 2;
int depth = 1;
while (1) {
- if (!input[0])
+ if (!input[0]) {
return;
+ }
if (input[0] == '(' && input[1] == ';') {
input += 2;
depth++;
@@ -252,15 +270,18 @@ Element* SExpressionParser::parseString() {
input++;
std::string str;
while (1) {
- if (input[0] == 0)
+ if (input[0] == 0) {
throw ParseException("unterminated string", line, start - lineStart);
- if (input[0] == '"')
+ }
+ if (input[0] == '"') {
break;
+ }
if (input[0] == '\\') {
str += input[0];
- if (input[1] == 0)
+ if (input[1] == 0) {
throw ParseException(
"unterminated string escape", line, start - lineStart);
+ }
str += input[1];
input += 2;
continue;
@@ -274,10 +295,12 @@ Element* SExpressionParser::parseString() {
->setMetadata(line, start - lineStart, loc);
}
while (input[0] && !isspace(input[0]) && input[0] != ')' && input[0] != '(' &&
- input[0] != ';')
+ input[0] != ';') {
input++;
- if (start == input)
+ }
+ if (start == input) {
throw ParseException("expected string", line, input - lineStart);
+ }
char temp = input[0];
input[0] = 0;
auto ret = allocator.alloc<Element>()
@@ -291,12 +314,15 @@ SExpressionWasmBuilder::SExpressionWasmBuilder(Module& wasm,
Element& module,
Name* moduleName)
: wasm(wasm), allocator(wasm.allocator) {
- if (module.size() == 0)
+ if (module.size() == 0) {
throw ParseException("empty toplevel, expected module");
- if (module[0]->str() != MODULE)
+ }
+ if (module[0]->str() != MODULE) {
throw ParseException("toplevel does not start with module");
- if (module.size() == 1)
+ }
+ if (module.size() == 1) {
return;
+ }
Index i = 1;
if (module[i]->dollared()) {
if (moduleName) {
@@ -338,55 +364,69 @@ SExpressionWasmBuilder::SExpressionWasmBuilder(Module& wasm,
bool SExpressionWasmBuilder::isImport(Element& curr) {
for (Index i = 0; i < curr.size(); i++) {
auto& x = *curr[i];
- if (x.isList() && x.size() > 0 && x[0]->isStr() && x[0]->str() == IMPORT)
+ if (x.isList() && x.size() > 0 && x[0]->isStr() && x[0]->str() == IMPORT) {
return true;
+ }
}
return false;
}
void SExpressionWasmBuilder::preParseImports(Element& curr) {
IString id = curr[0]->str();
- if (id == IMPORT)
+ if (id == IMPORT) {
parseImport(curr);
+ }
if (isImport(curr)) {
- if (id == FUNC)
+ if (id == FUNC) {
parseFunction(curr, true /* preParseImport */);
- else if (id == GLOBAL)
+ } else if (id == GLOBAL) {
parseGlobal(curr, true /* preParseImport */);
- else if (id == TABLE)
+ } else if (id == TABLE) {
parseTable(curr, true /* preParseImport */);
- else if (id == MEMORY)
+ } else if (id == MEMORY) {
parseMemory(curr, true /* preParseImport */);
- else
+ } else {
throw ParseException(
"fancy import we don't support yet", curr.line, curr.col);
+ }
}
}
void SExpressionWasmBuilder::parseModuleElement(Element& curr) {
- if (isImport(curr))
+ if (isImport(curr)) {
return; // already done
+ }
IString id = curr[0]->str();
- if (id == START)
+ if (id == START) {
return parseStart(curr);
- if (id == FUNC)
+ }
+ if (id == FUNC) {
return parseFunction(curr);
- if (id == MEMORY)
+ }
+ if (id == MEMORY) {
return parseMemory(curr);
- if (id == DATA)
+ }
+ if (id == DATA) {
return parseData(curr);
- if (id == EXPORT)
+ }
+ if (id == EXPORT) {
return parseExport(curr);
- if (id == IMPORT)
+ }
+ if (id == IMPORT) {
return; // already done
- if (id == GLOBAL)
+ }
+ if (id == GLOBAL) {
return parseGlobal(curr);
- if (id == TABLE)
+ }
+ if (id == TABLE) {
return parseTable(curr);
- if (id == ELEM)
+ }
+ if (id == ELEM) {
return parseElem(curr);
- if (id == TYPE)
+ }
+ if (id == TYPE) {
return; // already done
+ }
std::cerr << "bad module element " << id.str << '\n';
throw ParseException("unknown module element", curr.line, curr.col);
}
@@ -397,8 +437,9 @@ Name SExpressionWasmBuilder::getFunctionName(Element& s) {
} else {
// index
size_t offset = atoi(s.str().c_str());
- if (offset >= functionNames.size())
+ if (offset >= functionNames.size()) {
throw ParseException("unknown function in getFunctionName");
+ }
return functionNames[offset];
}
}
@@ -409,8 +450,9 @@ Name SExpressionWasmBuilder::getFunctionTypeName(Element& s) {
} else {
// index
size_t offset = atoi(s.str().c_str());
- if (offset >= functionTypeNames.size())
+ if (offset >= functionTypeNames.size()) {
throw ParseException("unknown function type in getFunctionTypeName");
+ }
return functionTypeNames[offset];
}
}
@@ -421,18 +463,21 @@ Name SExpressionWasmBuilder::getGlobalName(Element& s) {
} else {
// index
size_t offset = atoi(s.str().c_str());
- if (offset >= globalNames.size())
+ if (offset >= globalNames.size()) {
throw ParseException("unknown global in getGlobalName");
+ }
return globalNames[offset];
}
}
void SExpressionWasmBuilder::preParseFunctionType(Element& s) {
IString id = s[0]->str();
- if (id == TYPE)
+ if (id == TYPE) {
return parseType(s);
- if (id != FUNC)
+ }
+ if (id != FUNC) {
return;
+ }
size_t i = 1;
Name name, exportName;
i = parseFunctionNames(s, name, exportName);
@@ -449,13 +494,15 @@ void SExpressionWasmBuilder::preParseFunctionType(Element& s) {
Element& curr = *s[i];
IString id = curr[0]->str();
if (id == RESULT) {
- if (curr.size() > 2)
+ if (curr.size() > 2) {
throw ParseException("invalid result arity", curr.line, curr.col);
+ }
functionTypes[name] = stringToType(curr[1]->str());
} else if (id == TYPE) {
Name typeName = getFunctionTypeName(*curr[1]);
- if (!wasm.getFunctionTypeOrNull(typeName))
+ if (!wasm.getFunctionTypeOrNull(typeName)) {
throw ParseException("unknown function type", curr.line, curr.col);
+ }
type = wasm.getFunctionType(typeName);
functionTypes[name] = type->result;
} else if (id == PARAM && curr.size() > 1) {
@@ -487,8 +534,9 @@ void SExpressionWasmBuilder::preParseFunctionType(Element& s) {
if (need) {
functionType->name = Name::fromInt(wasm.functionTypes.size());
functionTypeNames.push_back(functionType->name);
- if (wasm.getFunctionTypeOrNull(functionType->name))
+ if (wasm.getFunctionTypeOrNull(functionType->name)) {
throw ParseException("duplicate function type", s.line, s.col);
+ }
wasm.addFunctionType(std::move(functionType));
}
}
@@ -547,8 +595,9 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
ex->name = exportName;
ex->value = name;
ex->kind = ExternalKind::Function;
- if (wasm.getExportOrNull(ex->name))
+ if (wasm.getExportOrNull(ex->name)) {
throw ParseException("duplicate export", s.line, s.col);
+ }
wasm.addExport(ex.release());
}
Expression* body = nullptr;
@@ -604,14 +653,16 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
currLocalTypes[name] = type;
}
} else if (id == RESULT) {
- if (curr.size() > 2)
+ if (curr.size() > 2) {
throw ParseException("invalid result arity", curr.line, curr.col);
+ }
result = stringToType(curr[1]->str());
} else if (id == TYPE) {
Name name = getFunctionTypeName(*curr[1]);
type = name;
- if (!wasm.getFunctionTypeOrNull(name))
+ if (!wasm.getFunctionTypeOrNull(name)) {
throw ParseException("unknown function type");
+ }
FunctionType* type = wasm.getFunctionType(name);
result = type->result;
for (size_t j = 0; j < type->params.size(); j++) {
@@ -628,8 +679,9 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
if (typeParams.size() > 0 && params.size() == 0) {
params = typeParams;
}
- if (!currFunction)
+ if (!currFunction) {
makeFunction();
+ }
Expression* ex = parseExpression(curr);
if (!body) {
body = ex;
@@ -650,15 +702,18 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
break;
}
}
- if (!type.is())
+ if (!type.is()) {
throw ParseException("no function type [internal error?]", s.line, s.col);
+ }
}
if (importModule.is()) {
// this is an import, actually
- if (!importBase.size())
+ if (!importBase.size()) {
throw ParseException("module but no base for import");
- if (!preParseImport)
+ }
+ if (!preParseImport) {
throw ParseException("!preParseImport in func");
+ }
auto im = make_unique<Function>();
im->name = name;
im->module = importModule;
@@ -666,17 +721,20 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
im->type = type;
FunctionTypeUtils::fillFunction(im.get(), wasm.getFunctionType(type));
functionTypes[name] = im->result;
- if (wasm.getFunctionOrNull(im->name))
+ if (wasm.getFunctionOrNull(im->name)) {
throw ParseException("duplicate import", s.line, s.col);
+ }
wasm.addFunction(im.release());
- if (currFunction)
+ if (currFunction) {
throw ParseException("import module inside function dec");
+ }
currLocalTypes.clear();
nameMapper.clear();
return;
}
- if (preParseImport)
+ if (preParseImport) {
throw ParseException("preParseImport in func");
+ }
if (brokeToAutoBlock) {
ensureAutoBlock();
autoBlock->name = FAKE_RETURN;
@@ -688,8 +746,9 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
makeFunction();
body = allocator.alloc<Nop>();
}
- if (currFunction->result != result)
+ if (currFunction->result != result) {
throw ParseException("bad func declaration", s.line, s.col);
+ }
currFunction->body = body;
currFunction->type = type;
if (s.startLoc) {
@@ -698,8 +757,9 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
if (s.endLoc) {
currFunction->epilogLocation.insert(getDebugLocation(*s.endLoc));
}
- if (wasm.getFunctionOrNull(currFunction->name))
+ if (wasm.getFunctionOrNull(currFunction->name)) {
throw ParseException("duplicate function", s.line, s.col);
+ }
wasm.addFunction(currFunction.release());
currLocalTypes.clear();
nameMapper.clear();
@@ -709,16 +769,20 @@ Type SExpressionWasmBuilder::stringToType(const char* str,
bool allowError,
bool prefix) {
if (str[0] == 'i') {
- if (str[1] == '3' && str[2] == '2' && (prefix || str[3] == 0))
+ if (str[1] == '3' && str[2] == '2' && (prefix || str[3] == 0)) {
return i32;
- if (str[1] == '6' && str[2] == '4' && (prefix || str[3] == 0))
+ }
+ if (str[1] == '6' && str[2] == '4' && (prefix || str[3] == 0)) {
return i64;
+ }
}
if (str[0] == 'f') {
- if (str[1] == '3' && str[2] == '2' && (prefix || str[3] == 0))
+ if (str[1] == '3' && str[2] == '2' && (prefix || str[3] == 0)) {
return f32;
- if (str[1] == '6' && str[2] == '4' && (prefix || str[3] == 0))
+ }
+ if (str[1] == '6' && str[2] == '4' && (prefix || str[3] == 0)) {
return f64;
+ }
}
if (str[0] == 'v') {
if (str[1] == '1' && str[2] == '2' && str[3] == '8' &&
@@ -726,24 +790,31 @@ Type SExpressionWasmBuilder::stringToType(const char* str,
return v128;
}
}
- if (allowError)
+ if (allowError) {
return none;
+ }
throw ParseException("invalid wasm type");
}
Type SExpressionWasmBuilder::stringToLaneType(const char* str) {
- if (strcmp(str, "i8x16") == 0)
+ if (strcmp(str, "i8x16") == 0) {
return i32;
- if (strcmp(str, "i16x8") == 0)
+ }
+ if (strcmp(str, "i16x8") == 0) {
return i32;
- if (strcmp(str, "i32x4") == 0)
+ }
+ if (strcmp(str, "i32x4") == 0) {
return i32;
- if (strcmp(str, "i64x2") == 0)
+ }
+ if (strcmp(str, "i64x2") == 0) {
return i64;
- if (strcmp(str, "f32x4") == 0)
+ }
+ if (strcmp(str, "f32x4") == 0) {
return f32;
- if (strcmp(str, "f64x2") == 0)
+ }
+ if (strcmp(str, "f64x2") == 0) {
return f64;
+ }
return none;
}
@@ -831,18 +902,21 @@ Expression* SExpressionWasmBuilder::makeHost(Element& s, HostOp op) {
}
Index SExpressionWasmBuilder::getLocalIndex(Element& s) {
- if (!currFunction)
+ if (!currFunction) {
throw ParseException("local access in non-function scope", s.line, s.col);
+ }
if (s.dollared()) {
auto ret = s.str();
- if (currFunction->localIndices.count(ret) == 0)
+ if (currFunction->localIndices.count(ret) == 0) {
throw ParseException("bad local name", s.line, s.col);
+ }
return currFunction->getLocalIndex(ret);
}
// this is a numeric index
Index ret = atoi(s.c_str());
- if (ret >= currFunction->getNumLocals())
+ if (ret >= currFunction->getNumLocals()) {
throw ParseException("bad local index", s.line, s.col);
+ }
return ret;
}
@@ -886,16 +960,18 @@ Expression* SExpressionWasmBuilder::makeSetGlobal(Element& s) {
auto ret = allocator.alloc<SetGlobal>();
ret->name = getGlobalName(*s[1]);
if (wasm.getGlobalOrNull(ret->name) &&
- !wasm.getGlobalOrNull(ret->name)->mutable_)
+ !wasm.getGlobalOrNull(ret->name)->mutable_) {
throw ParseException("global.set of immutable", s.line, s.col);
+ }
ret->value = parseExpression(s[2]);
ret->finalize();
return ret;
}
Expression* SExpressionWasmBuilder::makeBlock(Element& s) {
- if (!currFunction)
+ if (!currFunction) {
throw ParseException("block is unallowed outside of functions");
+ }
// special-case Block, because Block nesting (in their first element) can be
// incredibly deep
auto curr = allocator.alloc<Block>();
@@ -920,8 +996,9 @@ Expression* SExpressionWasmBuilder::makeBlock(Element& s) {
curr->name = nameMapper.pushLabelName(sName);
// block signature
curr->type = parseOptionalResultType(s, i);
- if (i >= s.size())
+ if (i >= s.size()) {
break; // empty block
+ }
auto& first = *s[i];
if (first[0]->str() == BLOCK) {
// recurse
@@ -994,8 +1071,9 @@ static Literal makeLanes(Element& s, MixedArena& allocator, Type lane_t) {
Expression* SExpressionWasmBuilder::makeConst(Element& s, Type type) {
if (type != v128) {
auto ret = parseConst(s[1]->str(), type, allocator);
- if (!ret)
+ if (!ret) {
throw ParseException("bad const");
+ }
return ret;
}
@@ -1044,14 +1122,15 @@ static uint8_t parseMemBytes(const char*& s, uint8_t fallback) {
ret = 1;
s++;
} else if (s[0] == '1') {
- if (s[1] != '6')
+ if (s[1] != '6') {
throw ParseException("expected 16 for memop size");
+ }
ret = 2;
s += 2;
} else if (s[0] == '3') {
- if (s[1] != '2')
+ if (s[1] != '2') {
throw ParseException("expected 32 for memop size");
- ;
+ };
ret = 4;
s += 2;
} else {
@@ -1070,26 +1149,31 @@ static size_t parseMemAttributes(Element& s,
while (!s[i]->isList()) {
const char* str = s[i]->c_str();
const char* eq = strchr(str, '=');
- if (!eq)
+ if (!eq) {
throw ParseException("missing = in memory attribute");
+ }
eq++;
- if (*eq == 0)
+ if (*eq == 0) {
throw ParseException("missing value in memory attribute", s.line, s.col);
+ }
char* endptr;
uint64_t value = strtoll(eq, &endptr, 10);
if (*endptr != 0) {
throw ParseException("bad memory attribute immediate", s.line, s.col);
}
if (str[0] == 'a') {
- if (value > std::numeric_limits<uint32_t>::max())
+ if (value > std::numeric_limits<uint32_t>::max()) {
throw ParseException("bad align", s.line, s.col);
+ }
*align = value;
} else if (str[0] == 'o') {
- if (value > std::numeric_limits<uint32_t>::max())
+ if (value > std::numeric_limits<uint32_t>::max()) {
throw ParseException("bad offset", s.line, s.col);
+ }
*offset = value;
- } else
+ } else {
throw ParseException("bad memory attribute");
+ }
i++;
}
return i;
@@ -1099,13 +1183,16 @@ static const char* findMemExtra(const Element& s, size_t skip, bool isAtomic) {
auto* str = s.c_str();
auto size = strlen(str);
auto* ret = strchr(str, '.');
- if (!ret)
+ if (!ret) {
throw ParseException("missing '.' in memory access", s.line, s.col);
+ }
ret += skip;
- if (isAtomic)
+ if (isAtomic) {
ret += 7; // after "type.atomic.load"
- if (ret > str + size)
+ }
+ if (ret > str + size) {
throw ParseException("memory access ends abruptly", s.line, s.col);
+ }
return ret;
}
@@ -1143,11 +1230,13 @@ Expression* SExpressionWasmBuilder::makeAtomicRMWOrCmpxchg(Element& s,
*s[0], 11 /* after "type.atomic.rmw" */, /* isAtomic = */ false);
auto bytes = parseMemBytes(extra, getTypeSize(type));
extra = strchr(extra, '.'); // after the optional '_u' and before the opcode
- if (!extra)
+ if (!extra) {
throw ParseException("malformed atomic rmw instruction");
+ }
extra++; // after the '.'
- if (!strncmp(extra, "cmpxchg", 7))
+ if (!strncmp(extra, "cmpxchg", 7)) {
return makeAtomicCmpxchg(s, type, bytes, extra);
+ }
return makeAtomicRMW(s, type, bytes, extra);
}
@@ -1158,24 +1247,26 @@ Expression* SExpressionWasmBuilder::makeAtomicRMW(Element& s,
auto ret = allocator.alloc<AtomicRMW>();
ret->type = type;
ret->bytes = bytes;
- if (!strncmp(extra, "add", 3))
+ if (!strncmp(extra, "add", 3)) {
ret->op = Add;
- else if (!strncmp(extra, "and", 3))
+ } else if (!strncmp(extra, "and", 3)) {
ret->op = And;
- else if (!strncmp(extra, "or", 2))
+ } else if (!strncmp(extra, "or", 2)) {
ret->op = Or;
- else if (!strncmp(extra, "sub", 3))
+ } else if (!strncmp(extra, "sub", 3)) {
ret->op = Sub;
- else if (!strncmp(extra, "xor", 3))
+ } else if (!strncmp(extra, "xor", 3)) {
ret->op = Xor;
- else if (!strncmp(extra, "xchg", 4))
+ } else if (!strncmp(extra, "xchg", 4)) {
ret->op = Xchg;
- else
+ } else {
throw ParseException("bad atomic rmw operator");
+ }
Address align;
size_t i = parseMemAttributes(s, &ret->offset, &align, ret->bytes);
- if (align != ret->bytes)
+ if (align != ret->bytes) {
throw ParseException("Align of Atomic RMW must match size");
+ }
ret->ptr = parseExpression(s[i]);
ret->value = parseExpression(s[i + 1]);
ret->finalize();
@@ -1191,8 +1282,9 @@ Expression* SExpressionWasmBuilder::makeAtomicCmpxchg(Element& s,
ret->bytes = bytes;
Address align;
size_t i = parseMemAttributes(s, &ret->offset, &align, ret->bytes);
- if (align != ret->bytes)
+ if (align != ret->bytes) {
throw ParseException("Align of Atomic Cmpxchg must match size");
+ }
ret->ptr = parseExpression(s[i]);
ret->expected = parseExpression(s[i + 1]);
ret->replacement = parseExpression(s[i + 2]);
@@ -1224,11 +1316,13 @@ static uint8_t parseLaneIndex(const Element* s, size_t lanes) {
const char* str = s->c_str();
char* end;
auto n = static_cast<unsigned long long>(strtoll(str, &end, 10));
- if (end == str || *end != '\0')
+ if (end == str || *end != '\0') {
throw ParseException("Expected lane index");
- if (n > lanes)
+ }
+ if (n > lanes) {
throw ParseException("lane index must be less than " +
std::to_string(lanes));
+ }
return uint8_t(n);
}
@@ -1353,10 +1447,12 @@ Expression* SExpressionWasmBuilder::makeIf(Element& s) {
Expression*
SExpressionWasmBuilder::makeMaybeBlock(Element& s, size_t i, Type type) {
Index stopAt = -1;
- if (s.size() == i)
+ if (s.size() == i) {
return allocator.alloc<Nop>();
- if (s.size() == i + 1)
+ }
+ if (s.size() == i + 1) {
return parseExpression(s[i]);
+ }
auto ret = allocator.alloc<Block>();
for (; i < s.size() && i < stopAt; i++) {
ret->list.push_back(parseExpression(s[i]));
@@ -1369,18 +1465,21 @@ SExpressionWasmBuilder::makeMaybeBlock(Element& s, size_t i, Type type) {
}
Type SExpressionWasmBuilder::parseOptionalResultType(Element& s, Index& i) {
- if (s.size() == i)
+ if (s.size() == i) {
return none;
+ }
// TODO(sbc): Remove support for old result syntax (bare streing) once the
// spec tests are updated.
- if (s[i]->isStr())
+ if (s[i]->isStr()) {
return stringToType(s[i++]->str());
+ }
Element& params = *s[i];
IString id = params[0]->str();
- if (id != RESULT)
+ if (id != RESULT) {
return none;
+ }
i++;
return stringToType(params[1]->str());
@@ -1414,8 +1513,9 @@ Expression* SExpressionWasmBuilder::makeCall(Element& s) {
}
Expression* SExpressionWasmBuilder::makeCallIndirect(Element& s) {
- if (!wasm.table.exists)
+ if (!wasm.table.exists) {
throw ParseException("no table");
+ }
auto ret = allocator.alloc<CallIndirect>();
Index i = 1;
Element& typeElement = *s[i];
@@ -1423,8 +1523,9 @@ Expression* SExpressionWasmBuilder::makeCallIndirect(Element& s) {
// type name given
IString type = typeElement[1]->str();
auto* fullType = wasm.getFunctionTypeOrNull(type);
- if (!fullType)
+ if (!fullType) {
throw ParseException("invalid call_indirect type", s.line, s.col);
+ }
ret->fullType = fullType->name;
i++;
} else {
@@ -1465,8 +1566,9 @@ Name SExpressionWasmBuilder::getLabel(Element& s) {
} catch (std::out_of_range&) {
throw ParseException("out of range break offset");
}
- if (offset > nameMapper.labelStack.size())
+ if (offset > nameMapper.labelStack.size()) {
throw ParseException("invalid label", s.line, s.col);
+ }
if (offset == nameMapper.labelStack.size()) {
// a break to the function's scope. this means we need an automatic block,
// with a name
@@ -1482,8 +1584,9 @@ Expression* SExpressionWasmBuilder::makeBreak(Element& s) {
size_t i = 1;
ret->name = getLabel(*s[i]);
i++;
- if (i == s.size())
+ if (i == s.size()) {
return ret;
+ }
if (s[0]->str() == BR_IF) {
if (i + 1 < s.size()) {
ret->value = parseExpression(s[i]);
@@ -1503,8 +1606,9 @@ Expression* SExpressionWasmBuilder::makeBreakTable(Element& s) {
while (!s[i]->isList()) {
ret->targets.push_back(getLabel(*s[i++]));
}
- if (ret->targets.size() == 0)
+ if (ret->targets.size() == 0) {
throw ParseException("switch with no targets");
+ }
ret->default_ = ret->targets.back();
ret->targets.pop_back();
ret->condition = parseExpression(s[i++]);
@@ -1533,8 +1637,9 @@ void SExpressionWasmBuilder::stringToBinary(const char* input,
data.resize(originalSize + size);
char* write = data.data() + originalSize;
while (1) {
- if (input[0] == 0)
+ if (input[0] == 0) {
break;
+ }
if (input[0] == '\\') {
if (input[1] == '"') {
*write++ = '"';
@@ -1578,15 +1683,17 @@ Index SExpressionWasmBuilder::parseMemoryLimits(Element& s, Index i) {
return i;
}
uint64_t max = atoll(s[i++]->c_str());
- if (max > Memory::kMaxSize)
+ if (max > Memory::kMaxSize) {
throw ParseException("total memory must be <= 4GB");
+ }
wasm.memory.max = max;
return i;
}
void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
- if (wasm.memory.exists)
+ if (wasm.memory.exists) {
throw ParseException("too many memories");
+ }
wasm.memory.exists = true;
wasm.memory.shared = false;
Index i = 1;
@@ -1601,8 +1708,9 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
ex->name = inner[1]->str();
ex->value = wasm.memory.name;
ex->kind = ExternalKind::Memory;
- if (wasm.getExportOrNull(ex->name))
+ if (wasm.getExportOrNull(ex->name)) {
throw ParseException("duplicate export", s.line, s.col);
+ }
wasm.addExport(ex.release());
i++;
} else if (inner[0]->str() == IMPORT) {
@@ -1614,8 +1722,9 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
parseMemoryLimits(inner, 1);
i++;
} else {
- if (!(inner.size() > 0 ? inner[0]->str() != IMPORT : true))
+ if (!(inner.size() > 0 ? inner[0]->str() != IMPORT : true)) {
throw ParseException("bad import ending");
+ }
// (memory (data ..)) format
auto offset = allocator.alloc<Const>()->set(Literal(int32_t(0)));
parseInnerData(*s[i], 1, offset, false);
@@ -1623,8 +1732,9 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
return;
}
}
- if (!wasm.memory.shared)
+ if (!wasm.memory.shared) {
i = parseMemoryLimits(s, i);
+ }
// Parse memory initializers.
while (i < s.size()) {
@@ -1652,8 +1762,9 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
}
void SExpressionWasmBuilder::parseData(Element& s) {
- if (!wasm.memory.exists)
+ if (!wasm.memory.exists) {
throw ParseException("data but no memory");
+ }
bool isPassive = false;
Expression* offset = nullptr;
Index i = 1;
@@ -1703,16 +1814,18 @@ void SExpressionWasmBuilder::parseExport(Element& s) {
} else if (inner[0]->str() == GLOBAL) {
ex->kind = ExternalKind::Global;
if (wasm.getGlobalOrNull(ex->value) &&
- wasm.getGlobal(ex->value)->mutable_)
+ wasm.getGlobal(ex->value)->mutable_) {
throw ParseException("cannot export a mutable global", s.line, s.col);
+ }
} else {
throw ParseException("invalid export");
}
} else if (!s[2]->dollared() && !std::isdigit(s[2]->str()[0])) {
ex->value = s[3]->str();
if (s[2]->str() == MEMORY) {
- if (!wasm.memory.exists)
+ if (!wasm.memory.exists) {
throw ParseException("memory exported but no memory");
+ }
ex->kind = ExternalKind::Memory;
} else if (s[2]->str() == TABLE) {
ex->kind = ExternalKind::Table;
@@ -1726,8 +1839,9 @@ void SExpressionWasmBuilder::parseExport(Element& s) {
ex->value = s[2]->str();
ex->kind = ExternalKind::Function;
}
- if (wasm.getExportOrNull(ex->name))
+ if (wasm.getExportOrNull(ex->name)) {
throw ParseException("duplicate export", s.line, s.col);
+ }
wasm.addExport(ex.release());
}
@@ -1741,13 +1855,15 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
kind = ExternalKind::Function;
} else if ((*s[3])[0]->str() == MEMORY) {
kind = ExternalKind::Memory;
- if (wasm.memory.exists)
+ if (wasm.memory.exists) {
throw ParseException("more than one memory");
+ }
wasm.memory.exists = true;
} else if ((*s[3])[0]->str() == TABLE) {
kind = ExternalKind::Table;
- if (wasm.table.exists)
+ if (wasm.table.exists) {
throw ParseException("more than one table");
+ }
wasm.table.exists = true;
} else if ((*s[3])[0]->str() == GLOBAL) {
kind = ExternalKind::Global;
@@ -1793,11 +1909,13 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
kind = ExternalKind::Function;
}
auto module = s[i++]->str();
- if (!s[i]->isStr())
+ if (!s[i]->isStr()) {
throw ParseException("no name for import");
+ }
auto base = s[i++]->str();
- if (!module.size() || !base.size())
+ if (!module.size() || !base.size()) {
throw ParseException("imports must have module and base");
+ }
// parse internals
Element& inner = newStyle ? *s[3] : s;
Index j = newStyle ? newStyleInner : i;
@@ -1814,16 +1932,18 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
type->result = stringToType(params[1]->str());
} else if (id == TYPE) {
IString name = params[1]->str();
- if (!wasm.getFunctionTypeOrNull(name))
+ if (!wasm.getFunctionTypeOrNull(name)) {
throw ParseException("bad function type for import");
+ }
*type = *wasm.getFunctionType(name);
} else {
throw ParseException("bad import element");
}
if (inner.size() > j + 1) {
Element& result = *inner[j + 1];
- if (result[0]->str() != RESULT)
+ if (result[0]->str() != RESULT) {
throw ParseException("expected result");
+ }
type->result = stringToType(result[1]->str());
}
}
@@ -1843,8 +1963,9 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
type = stringToType(inner[j]->str());
} else {
auto& inner2 = *inner[j];
- if (inner2[0]->str() != MUT)
+ if (inner2[0]->str() != MUT) {
throw ParseException("expected mut");
+ }
type = stringToType(inner2[1]->str());
mutable_ = true;
}
@@ -1874,8 +1995,9 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
wasm.memory.base = base;
if (inner[j]->isList()) {
auto& limits = *inner[j];
- if (!(limits[0]->isStr() && limits[0]->str() == "shared"))
+ if (!(limits[0]->isStr() && limits[0]->str() == "shared")) {
throw ParseException("bad memory limit declaration");
+ }
wasm.memory.shared = true;
parseMemoryLimits(limits, 1);
} else {
@@ -1905,8 +2027,9 @@ void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) {
ex->name = inner[1]->str();
ex->value = global->name;
ex->kind = ExternalKind::Global;
- if (wasm.getExportOrNull(ex->name))
+ if (wasm.getExportOrNull(ex->name)) {
throw ParseException("duplicate export", s.line, s.col);
+ }
wasm.addExport(ex.release());
exported = true;
i++;
@@ -1922,30 +2045,35 @@ void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) {
break;
}
}
- if (exported && mutable_)
+ if (exported && mutable_) {
throw ParseException("cannot export a mutable global", s.line, s.col);
+ }
if (type == none) {
type = stringToType(s[i++]->str());
}
if (importModule.is()) {
// this is an import, actually
- if (!importBase.size())
+ if (!importBase.size()) {
throw ParseException("module but no base for import");
- if (!preParseImport)
+ }
+ if (!preParseImport) {
throw ParseException("!preParseImport in global");
+ }
auto im = make_unique<Global>();
im->name = global->name;
im->module = importModule;
im->base = importBase;
im->type = type;
im->mutable_ = mutable_;
- if (wasm.getGlobalOrNull(im->name))
+ if (wasm.getGlobalOrNull(im->name)) {
throw ParseException("duplicate import", s.line, s.col);
+ }
wasm.addGlobal(im.release());
return;
}
- if (preParseImport)
+ if (preParseImport) {
throw ParseException("preParseImport in global");
+ }
global->type = type;
if (i < s.size()) {
global->init = parseExpression(s[i++]);
@@ -1953,25 +2081,30 @@ void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) {
throw ParseException("global without init", s.line, s.col);
}
global->mutable_ = mutable_;
- if (i != s.size())
+ if (i != s.size()) {
throw ParseException("extra import elements");
- if (wasm.getGlobalOrNull(global->name))
+ }
+ if (wasm.getGlobalOrNull(global->name)) {
throw ParseException("duplicate import", s.line, s.col);
+ }
wasm.addGlobal(global.release());
}
void SExpressionWasmBuilder::parseTable(Element& s, bool preParseImport) {
- if (wasm.table.exists)
+ if (wasm.table.exists) {
throw ParseException("more than one table");
+ }
wasm.table.exists = true;
Index i = 1;
- if (i == s.size())
+ if (i == s.size()) {
return; // empty table in old notation
+ }
if (s[i]->dollared()) {
wasm.table.name = s[i++]->str();
}
- if (i == s.size())
+ if (i == s.size()) {
return;
+ }
Name importModule, importBase;
if (s[i]->isList()) {
auto& inner = *s[i];
@@ -1980,13 +2113,15 @@ void SExpressionWasmBuilder::parseTable(Element& s, bool preParseImport) {
ex->name = inner[1]->str();
ex->value = wasm.table.name;
ex->kind = ExternalKind::Table;
- if (wasm.getExportOrNull(ex->name))
+ if (wasm.getExportOrNull(ex->name)) {
throw ParseException("duplicate export", s.line, s.col);
+ }
wasm.addExport(ex.release());
i++;
} else if (inner[0]->str() == IMPORT) {
- if (!preParseImport)
+ if (!preParseImport) {
throw ParseException("!preParseImport in table");
+ }
wasm.table.module = inner[1]->str();
wasm.table.base = inner[2]->str();
i++;
@@ -1994,8 +2129,9 @@ void SExpressionWasmBuilder::parseTable(Element& s, bool preParseImport) {
throw ParseException("invalid table");
}
}
- if (i == s.size())
+ if (i == s.size()) {
return;
+ }
if (!s[i]->dollared()) {
if (s[i]->str() == FUNCREF) {
// (table type (elem ..))
@@ -2044,8 +2180,9 @@ void SExpressionWasmBuilder::parseElem(Element& s) {
void SExpressionWasmBuilder::parseInnerElem(Element& s,
Index i,
Expression* offset) {
- if (!wasm.table.exists)
+ if (!wasm.table.exists) {
throw ParseException("elem without table", s.line, s.col);
+ }
if (!offset) {
offset = allocator.alloc<Const>()->set(Literal(int32_t(0)));
}
@@ -2071,8 +2208,9 @@ void SExpressionWasmBuilder::parseType(Element& s) {
type->params.push_back(stringToType(curr[j]->str()));
}
} else if (curr[0]->str() == RESULT) {
- if (curr.size() > 2)
+ if (curr.size() > 2) {
throw ParseException("invalid result arity", curr.line, curr.col);
+ }
type->result = stringToType(curr[1]->str());
}
}
@@ -2080,8 +2218,9 @@ void SExpressionWasmBuilder::parseType(Element& s) {
type->name = Name::fromInt(wasm.functionTypes.size());
}
functionTypeNames.push_back(type->name);
- if (wasm.getFunctionTypeOrNull(type->name))
+ if (wasm.getFunctionTypeOrNull(type->name)) {
throw ParseException("duplicate function type", s.line, s.col);
+ }
wasm.addFunctionType(std::move(type));
}
diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp
index 78ad6f628..449dff4db 100644
--- a/src/wasm/wasm-type.cpp
+++ b/src/wasm/wasm-type.cpp
@@ -69,14 +69,18 @@ FeatureSet getFeatures(Type type) {
}
Type getType(unsigned size, bool float_) {
- if (size < 4)
+ if (size < 4) {
return Type::i32;
- if (size == 4)
+ }
+ if (size == 4) {
return float_ ? Type::f32 : Type::i32;
- if (size == 8)
+ }
+ if (size == 8) {
return float_ ? Type::f64 : Type::i64;
- if (size == 16)
+ }
+ if (size == 16) {
return Type::v128;
+ }
WASM_UNREACHABLE();
}
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index ea8e92047..b84105c8d 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -66,8 +66,9 @@ struct ValidationInfo {
std::ostringstream& getStream(Function* func) {
std::unique_lock<std::mutex> lock(mutex);
auto iter = outputs.find(func);
- if (iter != outputs.end())
+ if (iter != outputs.end()) {
return *(iter->second.get());
+ }
auto& ret = outputs[func] = make_unique<std::ostringstream>();
return *ret.get();
}
@@ -78,8 +79,9 @@ struct ValidationInfo {
std::ostream& fail(S text, T curr, Function* func) {
valid.store(false);
auto& stream = getStream(func);
- if (quiet)
+ if (quiet) {
return stream;
+ }
auto& ret = printFailureHeader(func);
ret << text << ", on \n";
return printModuleComponent(curr, ret);
@@ -87,8 +89,9 @@ struct ValidationInfo {
std::ostream& printFailureHeader(Function* func) {
auto& stream = getStream(func);
- if (quiet)
+ if (quiet) {
return stream;
+ }
Colors::red(stream);
if (func) {
stream << "[wasm-validator error in function ";
@@ -220,16 +223,18 @@ public:
static void visitPreBlock(FunctionValidator* self, Expression** currp) {
auto* curr = (*currp)->cast<Block>();
- if (curr->name.is())
+ if (curr->name.is()) {
self->breakInfos[curr->name];
+ }
}
void visitBlock(Block* curr);
static void visitPreLoop(FunctionValidator* self, Expression** currp) {
auto* curr = (*currp)->cast<Loop>();
- if (curr->name.is())
+ if (curr->name.is()) {
self->breakInfos[curr->name];
+ }
}
void visitLoop(Loop* curr);
@@ -240,10 +245,12 @@ public:
PostWalker<FunctionValidator>::scan(self, currp);
auto* curr = *currp;
- if (curr->is<Block>())
+ if (curr->is<Block>()) {
self->pushTask(visitPreBlock, currp);
- if (curr->is<Loop>())
+ }
+ if (curr->is<Loop>()) {
self->pushTask(visitPreLoop, currp);
+ }
}
void noteBreak(Name name, Expression* value, Expression* curr);
@@ -319,8 +326,9 @@ private:
};
void FunctionValidator::noteLabelName(Name name) {
- if (!name.is())
+ if (!name.is()) {
return;
+ }
bool inserted;
std::tie(std::ignore, inserted) = labelNames.insert(name);
shouldBeTrue(
@@ -520,8 +528,9 @@ void FunctionValidator::noteBreak(Name name,
}
auto iter = breakInfos.find(name);
if (!shouldBeTrue(
- iter != breakInfos.end(), curr, "all break targets must be valid"))
+ iter != breakInfos.end(), curr, "all break targets must be valid")) {
return;
+ }
auto& info = iter->second;
if (!info.hasBeenSet()) {
info = BreakInfo(valueType, arity);
@@ -560,15 +569,18 @@ void FunctionValidator::visitSwitch(Switch* curr) {
}
void FunctionValidator::visitCall(Call* curr) {
- if (!info.validateGlobally)
+ if (!info.validateGlobally) {
return;
+ }
auto* target = getModule()->getFunctionOrNull(curr->target);
- if (!shouldBeTrue(!!target, curr, "call target must exist"))
+ if (!shouldBeTrue(!!target, curr, "call target must exist")) {
return;
+ }
if (!shouldBeTrue(curr->operands.size() == target->params.size(),
curr,
- "call param number must match"))
+ "call param number must match")) {
return;
+ }
for (size_t i = 0; i < curr->operands.size(); i++) {
if (!shouldBeEqualOrFirstIsUnreachable(curr->operands[i]->type,
target->params[i],
@@ -581,17 +593,20 @@ void FunctionValidator::visitCall(Call* curr) {
}
void FunctionValidator::visitCallIndirect(CallIndirect* curr) {
- if (!info.validateGlobally)
+ if (!info.validateGlobally) {
return;
+ }
auto* type = getModule()->getFunctionTypeOrNull(curr->fullType);
- if (!shouldBeTrue(!!type, curr, "call_indirect type must exist"))
+ if (!shouldBeTrue(!!type, curr, "call_indirect type must exist")) {
return;
+ }
shouldBeEqualOrFirstIsUnreachable(
curr->target->type, i32, curr, "indirect call target must be an i32");
if (!shouldBeTrue(curr->operands.size() == type->params.size(),
curr,
- "call param number must match"))
+ "call param number must match")) {
return;
+ }
for (size_t i = 0; i < curr->operands.size(); i++) {
if (!shouldBeEqualOrFirstIsUnreachable(curr->operands[i]->type,
type->params[i],
@@ -639,16 +654,18 @@ void FunctionValidator::visitSetLocal(SetLocal* curr) {
}
void FunctionValidator::visitGetGlobal(GetGlobal* curr) {
- if (!info.validateGlobally)
+ if (!info.validateGlobally) {
return;
+ }
shouldBeTrue(getModule()->getGlobalOrNull(curr->name),
curr,
"global.get name must be valid");
}
void FunctionValidator::visitSetGlobal(SetGlobal* curr) {
- if (!info.validateGlobally)
+ if (!info.validateGlobally) {
return;
+ }
auto* global = getModule()->getGlobalOrNull(curr->name);
if (shouldBeTrue(global,
curr,
@@ -674,10 +691,11 @@ void FunctionValidator::visitLoad(Load* curr) {
curr,
"Atomic load should be i32 or i64");
}
- if (curr->type == v128)
+ if (curr->type == v128) {
shouldBeTrue(getModule()->features.hasSIMD(),
curr,
"SIMD operation (SIMD is disabled)");
+ }
shouldBeFalse(curr->isAtomic && !getModule()->memory.shared,
curr,
"Atomic operation with non-shared memory");
@@ -704,10 +722,11 @@ void FunctionValidator::visitStore(Store* curr) {
curr,
"Atomic store should be i32 or i64");
}
- if (curr->valueType == v128)
+ if (curr->valueType == v128) {
shouldBeTrue(getModule()->features.hasSIMD(),
curr,
"SIMD operation (SIMD is disabled)");
+ }
shouldBeFalse(curr->isAtomic && !getModule()->memory.shared,
curr,
"Atomic operation with non-shared memory");
@@ -1232,8 +1251,9 @@ void FunctionValidator::visitUnary(Unary* curr) {
none,
curr,
"unaries must not receive a none as their input");
- if (curr->value->type == unreachable)
+ if (curr->value->type == unreachable) {
return; // nothing to check
+ }
switch (curr->op) {
case ClzInt32:
case CtzInt32:
@@ -1542,11 +1562,13 @@ void FunctionValidator::visitFunction(Function* curr) {
}
static bool checkOffset(Expression* curr, Address add, Address max) {
- if (curr->is<GetGlobal>())
+ if (curr->is<GetGlobal>()) {
return true;
+ }
auto* c = curr->dynCast<Const>();
- if (!c)
+ if (!c) {
return false;
+ }
uint64_t raw = c->value.getInteger();
if (raw > std::numeric_limits<Address::address_t>::max()) {
return false;
@@ -1763,10 +1785,11 @@ static void validateMemory(Module& module, ValidationInfo& info) {
info.shouldBeTrue(!curr.shared || curr.hasMax(),
"memory",
"shared memory must have max size");
- if (curr.shared)
+ if (curr.shared) {
info.shouldBeTrue(module.features.hasAtomics(),
"memory",
"memory is shared, but atomics are disabled");
+ }
for (auto& segment : curr.segments) {
Index size = segment.data.size();
if (segment.isPassive) {
@@ -1781,8 +1804,9 @@ static void validateMemory(Module& module, ValidationInfo& info) {
if (!info.shouldBeEqual(segment.offset->type,
i32,
segment.offset,
- "segment offset should be i32"))
+ "segment offset should be i32")) {
continue;
+ }
info.shouldBeTrue(checkOffset(segment.offset,
segment.data.size(),
curr.initial * Memory::kPageSize),
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index 22cce6e80..bf12c22d4 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -185,11 +185,13 @@ struct TypeSeeker : public PostWalker<TypeSeeker> {
void visitSwitch(Switch* curr) {
for (auto name : curr->targets) {
- if (name == targetName)
+ if (name == targetName) {
types.push_back(curr->value ? curr->value->type : none);
+ }
}
- if (curr->default_ == targetName)
+ if (curr->default_ == targetName) {
types.push_back(curr->value ? curr->value->type : none);
+ }
}
void visitBlock(Block* curr) {
@@ -243,15 +245,18 @@ static Type mergeTypes(std::vector<Type>& types) {
static void handleUnreachable(Block* block,
bool breakabilityKnown = false,
bool hasBreak = false) {
- if (block->type == unreachable)
+ if (block->type == unreachable) {
return; // nothing to do
- if (block->list.size() == 0)
+ }
+ if (block->list.size() == 0) {
return; // nothing to do
+ }
// if we are concrete, stop - even an unreachable child
// won't change that (since we have a break with a value,
// or the final child flows out a value)
- if (isConcreteType(block->type))
+ if (isConcreteType(block->type)) {
return;
+ }
// look for an unreachable child
for (auto* child : block->list) {
if (child->type == unreachable) {
@@ -280,11 +285,13 @@ void Block::finalize() {
// (return)
// (i32.const 10)
// )
- if (isConcreteType(type))
+ if (isConcreteType(type)) {
return;
+ }
// if we are unreachable, we are done
- if (type == unreachable)
+ if (type == unreachable) {
return;
+ }
// we may still be unreachable if we have an unreachable
// child
for (auto* child : list) {
@@ -398,20 +405,24 @@ void CallIndirect::finalize() {
}
bool FunctionType::structuralComparison(FunctionType& b) {
- if (result != b.result)
+ if (result != b.result) {
return false;
- if (params.size() != b.params.size())
+ }
+ if (params.size() != b.params.size()) {
return false;
+ }
for (size_t i = 0; i < params.size(); i++) {
- if (params[i] != b.params[i])
+ if (params[i] != b.params[i]) {
return false;
+ }
}
return true;
}
bool FunctionType::operator==(FunctionType& b) {
- if (name != b.name)
+ if (name != b.name) {
return false;
+ }
return structuralComparison(b);
}
bool FunctionType::operator!=(FunctionType& b) { return !(*this == b); }
@@ -419,10 +430,11 @@ bool FunctionType::operator!=(FunctionType& b) { return !(*this == b); }
bool SetLocal::isTee() { return type != none; }
void SetLocal::setTee(bool is) {
- if (is)
+ if (is) {
type = value->type;
- else
+ } else {
type = none;
+ }
finalize(); // type may need to be unreachable
}