diff options
Diffstat (limited to 'src')
116 files changed, 2945 insertions, 1508 deletions
diff --git a/src/abi/js.h b/src/abi/js.h index 8391346c8..52ca5657f 100644 --- a/src/abi/js.h +++ b/src/abi/js.h @@ -54,10 +54,12 @@ ensureScratchMemoryHelpers(Module* wasm, cashew::IString specific = cashew::IString()) { auto ensureImport = [&](Name name, const std::vector<Type> params, Type result) { - if (wasm->getFunctionOrNull(name)) + if (wasm->getFunctionOrNull(name)) { return; - if (specific.is() && name != specific) + } + if (specific.is() && name != specific) { return; + } auto func = make_unique<Function>(); func->name = name; func->params = params; diff --git a/src/asm2wasm.h b/src/asm2wasm.h index ba6a3df57..a4598c556 100644 --- a/src/asm2wasm.h +++ b/src/asm2wasm.h @@ -167,12 +167,15 @@ std::vector<Ref> AstStackHelper::astStack; static bool startsWith(const char* string, const char* prefix) { while (1) { - if (*prefix == 0) + if (*prefix == 0) { return true; - if (*string == 0) + } + if (*string == 0) { return false; - if (*string++ != *prefix++) + } + if (*string++ != *prefix++) { return false; + } } }; @@ -191,8 +194,9 @@ struct Asm2WasmPreProcessor { char* allocatedCopy = nullptr; ~Asm2WasmPreProcessor() { - if (allocatedCopy) + if (allocatedCopy) { free(allocatedCopy); + } } char* process(char* input) { @@ -231,14 +235,18 @@ struct Asm2WasmPreProcessor { memoryGrowth = true; // clean out this function, we don't need it. first where it starts char* growthFuncStart = growthSign; - while (*growthFuncStart != '{') + while (*growthFuncStart != '{') { growthFuncStart--; // skip body - while (*growthFuncStart != '(') + } + while (*growthFuncStart != '(') { growthFuncStart--; // skip params - while (*growthFuncStart != ' ') + } + while (*growthFuncStart != ' ') { growthFuncStart--; // skip function name - while (*growthFuncStart != 'f') + } + while (*growthFuncStart != 'f') { growthFuncStart--; // skip 'function' + } assert(strstr(growthFuncStart, "function ") == growthFuncStart); char* growthFuncEnd = strchr(growthSign, '}'); assert(growthFuncEnd > growthFuncStart + 5); @@ -381,8 +389,9 @@ struct AdjustDebugInfo void visitBlock(Block* curr) { // look for a debug info call that is unreachable - if (curr->list.size() == 0) + if (curr->list.size() == 0) { return; + } auto* back = curr->list.back(); for (Index i = 1; i < curr->list.size(); i++) { if (checkDebugInfo(curr->list[i]) && !checkDebugInfo(curr->list[i - 1])) { @@ -621,38 +630,49 @@ private: Type leftType = leftWasm->type; bool isInteger = leftType == Type::i32; - if (op == PLUS) + if (op == PLUS) { return isInteger ? BinaryOp::AddInt32 : (leftType == f32 ? BinaryOp::AddFloat32 : BinaryOp::AddFloat64); - if (op == MINUS) + } + if (op == MINUS) { return isInteger ? BinaryOp::SubInt32 : (leftType == f32 ? BinaryOp::SubFloat32 : BinaryOp::SubFloat64); - if (op == MUL) + } + if (op == MUL) { return isInteger ? BinaryOp::MulInt32 : (leftType == f32 ? BinaryOp::MulFloat32 : BinaryOp::MulFloat64); - if (op == AND) + } + if (op == AND) { return BinaryOp::AndInt32; - if (op == OR) + } + if (op == OR) { return BinaryOp::OrInt32; - if (op == XOR) + } + if (op == XOR) { return BinaryOp::XorInt32; - if (op == LSHIFT) + } + if (op == LSHIFT) { return BinaryOp::ShlInt32; - if (op == RSHIFT) + } + if (op == RSHIFT) { return BinaryOp::ShrSInt32; - if (op == TRSHIFT) + } + if (op == TRSHIFT) { return BinaryOp::ShrUInt32; - if (op == EQ) + } + if (op == EQ) { return isInteger ? BinaryOp::EqInt32 : (leftType == f32 ? BinaryOp::EqFloat32 : BinaryOp::EqFloat64); - if (op == NE) + } + if (op == NE) { return isInteger ? BinaryOp::NeInt32 : (leftType == f32 ? BinaryOp::NeFloat32 : BinaryOp::NeFloat64); + } bool isUnsigned = isUnsignedCoercion(left) || isUnsignedCoercion(right); @@ -728,10 +748,12 @@ private: } if (ast[1] == MINUS && ast[2]->isNumber()) { double num = -ast[2]->getNumber(); - if (isSInteger32(num)) + if (isSInteger32(num)) { return Literal((int32_t)num); - if (isUInteger32(num)) + } + if (isUInteger32(num)) { return Literal((uint32_t)num); + } assert(false && "expected signed or unsigned int32"); } if (ast[1] == PLUS && ast[2]->isArray(UNARY_PREFIX) && @@ -758,10 +780,11 @@ private: } void fixCallType(Expression* call, Type type) { - if (call->is<Call>()) + if (call->is<Call>()) { call->cast<Call>()->type = type; - else if (call->is<CallIndirect>()) + } else if (call->is<CallIndirect>()) { call->cast<CallIndirect>()->type = type; + } } FunctionType* getBuiltinFunctionType(Name module, @@ -771,12 +794,15 @@ private: if (base == ABS) { assert(operands && operands->size() == 1); Type type = (*operands)[0]->type; - if (type == i32) + if (type == i32) { return ensureFunctionType("ii", &wasm); - if (type == f32) + } + if (type == f32) { return ensureFunctionType("ff", &wasm); - if (type == f64) + } + if (type == f64) { return ensureFunctionType("dd", &wasm); + } } } return nullptr; @@ -784,8 +810,9 @@ private: // ensure a nameless block Block* blockify(Expression* expression) { - if (expression->is<Block>() && !expression->cast<Block>()->name.is()) + if (expression->is<Block>() && !expression->cast<Block>()->name.is()) { return expression->dynCast<Block>(); + } auto ret = allocator.alloc<Block>(); ret->list.push_back(expression); ret->finalize(); @@ -797,8 +824,9 @@ private: } Expression* truncateToInt32(Expression* value) { - if (value->type == i64) + if (value->type == i64) { return builder.makeUnary(UnaryOp::WrapInt64, value); + } // either i32, or a call_import whose type we don't know yet (but would be // legalized to i32 anyhow) return value; @@ -1024,8 +1052,9 @@ void Asm2WasmBuilder::processAsm(Ref ast) { if (runOptimizationPasses) { Index numFunctions = 0; for (unsigned i = 1; i < body->size(); i++) { - if (body[i][0] == DEFUN) + if (body[i][0] == DEFUN) { numFunctions++; + } } optimizingBuilder = make_unique<OptimizingIncrementalModuleBuilder>( &wasm, @@ -1396,8 +1425,9 @@ void Asm2WasmBuilder::processAsm(Ref ast) { numShown = make_unique<std::atomic<int>>(); numShown->store(0); } - if (numShown->load() >= MAX_SHOWN) + if (numShown->load() >= MAX_SHOWN) { return; + } std::cerr << why << " in call from " << getFunction()->name << " to " << calledFunc->name << " (this is likely due to undefined behavior in C, like " @@ -1458,8 +1488,9 @@ void Asm2WasmBuilder::processAsm(Ref ast) { // fill things out: add extra params as needed, etc. asm tolerates ffi // overloading, wasm does not auto iter = parent->importedFunctionTypes.find(curr->target); - if (iter == parent->importedFunctionTypes.end()) + if (iter == parent->importedFunctionTypes.end()) { return; // one of our fake imports for callIndirect fixups + } auto type = iter->second.get(); for (size_t i = 0; i < type->params.size(); i++) { if (i >= curr->operands.size()) { @@ -1539,31 +1570,36 @@ void Asm2WasmBuilder::processAsm(Ref ast) { if (auto* call = target->dynCast<Call>()) { auto tableName = call->target; if (parent->functionTableStarts.find(tableName) == - parent->functionTableStarts.end()) + parent->functionTableStarts.end()) { return; + } curr->target = parent->builder.makeConst( Literal((int32_t)parent->functionTableStarts[tableName])); return; } auto* add = target->dynCast<Binary>(); - if (!add) + if (!add) { return; + } if (add->right->is<Call>()) { auto* offset = add->right->cast<Call>(); auto tableName = offset->target; if (parent->functionTableStarts.find(tableName) == - parent->functionTableStarts.end()) + parent->functionTableStarts.end()) { return; + } add->right = parent->builder.makeConst( Literal((int32_t)parent->functionTableStarts[tableName])); } else { auto* offset = add->left->dynCast<Call>(); - if (!offset) + if (!offset) { return; + } auto tableName = offset->target; if (parent->functionTableStarts.find(tableName) == - parent->functionTableStarts.end()) + parent->functionTableStarts.end()) { return; + } add->left = parent->builder.makeConst( Literal((int32_t)parent->functionTableStarts[tableName])); } @@ -1690,10 +1726,12 @@ void Asm2WasmBuilder::processAsm(Ref ast) { Name tempRet0; { Expression* curr = wasm.getFunction(getTempRet0)->body; - if (curr->is<Block>()) + if (curr->is<Block>()) { curr = curr->cast<Block>()->list.back(); - if (curr->is<Return>()) + } + if (curr->is<Return>()) { curr = curr->cast<Return>()->value; + } auto* get = curr->cast<GetGlobal>(); tempRet0 = get->name; } @@ -1795,8 +1833,9 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { bool addedI32Temp = false; auto ensureI32Temp = [&]() { - if (addedI32Temp) + if (addedI32Temp) { return; + } addedI32Temp = true; Builder::addVar(function, I32_TEMP, i32); functionVariables.insert(I32_TEMP); @@ -1878,8 +1917,9 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { // global.set does not return; if our value is trivially not used, don't // emit a load (if nontrivially not used, opts get it later) auto parent = astStackHelper.getParent(); - if (!parent || parent->isArray(BLOCK) || parent->isArray(IF)) + if (!parent || parent->isArray(BLOCK) || parent->isArray(IF)) { return ret; + } return builder.makeSequence( ret, builder.makeGetGlobal(name, ret->value->type)); } @@ -2294,51 +2334,61 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { switch (name.str[0]) { case 'l': { auto align = num == 2 ? ast[2][1]->getInteger() : 0; - if (name == LOAD1) + if (name == LOAD1) { return builder.makeLoad(1, true, 0, 1, process(ast[2][0]), i32); - if (name == LOAD2) + } + if (name == LOAD2) { return builder.makeLoad( 2, true, 0, indexOr(align, 2), process(ast[2][0]), i32); - if (name == LOAD4) + } + if (name == LOAD4) { return builder.makeLoad( 4, true, 0, indexOr(align, 4), process(ast[2][0]), i32); - if (name == LOAD8) + } + if (name == LOAD8) { return builder.makeLoad( 8, true, 0, indexOr(align, 8), process(ast[2][0]), i64); - if (name == LOADF) + } + if (name == LOADF) { return builder.makeLoad( 4, true, 0, indexOr(align, 4), process(ast[2][0]), f32); - if (name == LOADD) + } + if (name == LOADD) { return builder.makeLoad( 8, true, 0, indexOr(align, 8), process(ast[2][0]), f64); + } break; } case 's': { auto align = num == 3 ? ast[2][2]->getInteger() : 0; - if (name == STORE1) + if (name == STORE1) { return builder.makeStore( 1, 0, 1, process(ast[2][0]), process(ast[2][1]), i32); - if (name == STORE2) + } + if (name == STORE2) { return builder.makeStore(2, 0, indexOr(align, 2), process(ast[2][0]), process(ast[2][1]), i32); - if (name == STORE4) + } + if (name == STORE4) { return builder.makeStore(4, 0, indexOr(align, 4), process(ast[2][0]), process(ast[2][1]), i32); - if (name == STORE8) + } + if (name == STORE8) { return builder.makeStore(8, 0, indexOr(align, 8), process(ast[2][0]), process(ast[2][1]), i64); + } if (name == STOREF) { auto* value = process(ast[2][1]); if (value->type == f64) { @@ -2349,13 +2399,14 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { return builder.makeStore( 4, 0, indexOr(align, 4), process(ast[2][0]), value, f32); } - if (name == STORED) + if (name == STORED) { return builder.makeStore(8, 0, indexOr(align, 8), process(ast[2][0]), process(ast[2][1]), f64); + } break; } case 'i': { @@ -2372,33 +2423,44 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { return value; } } - if (name == I32_CTTZ) + if (name == I32_CTTZ) { return builder.makeUnary(UnaryOp::CtzInt32, value); - if (name == I32_CTPOP) + } + if (name == I32_CTPOP) { return builder.makeUnary(UnaryOp::PopcntInt32, value); - if (name == I32_BC2F) + } + if (name == I32_BC2F) { return builder.makeUnary(UnaryOp::ReinterpretInt32, value); - if (name == I32_BC2I) + } + if (name == I32_BC2I) { return builder.makeUnary(UnaryOp::ReinterpretFloat32, value); + } - if (name == I64_TRUNC) + if (name == I64_TRUNC) { return builder.makeUnary(UnaryOp::WrapInt64, value); - if (name == I64_SEXT) + } + if (name == I64_SEXT) { return builder.makeUnary(UnaryOp::ExtendSInt32, value); - if (name == I64_ZEXT) + } + if (name == I64_ZEXT) { return builder.makeUnary(UnaryOp::ExtendUInt32, value); - if (name == I64_S2F) + } + if (name == I64_S2F) { return builder.makeUnary(UnaryOp::ConvertSInt64ToFloat32, value); - if (name == I64_S2D) + } + if (name == I64_S2D) { return builder.makeUnary(UnaryOp::ConvertSInt64ToFloat64, value); - if (name == I64_U2F) + } + if (name == I64_U2F) { return builder.makeUnary(UnaryOp::ConvertUInt64ToFloat32, value); - if (name == I64_U2D) + } + if (name == I64_U2D) { return builder.makeUnary(UnaryOp::ConvertUInt64ToFloat64, value); + } if (name == I64_F2S) { Unary* conv = builder.makeUnary(UnaryOp::TruncSFloat32ToInt64, value); @@ -2419,30 +2481,40 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { builder.makeUnary(UnaryOp::TruncUFloat64ToInt64, value); return makeTrappingUnary(conv, trappingFunctions); } - if (name == I64_BC2D) + if (name == I64_BC2D) { return builder.makeUnary(UnaryOp::ReinterpretInt64, value); - if (name == I64_BC2I) + } + if (name == I64_BC2I) { return builder.makeUnary(UnaryOp::ReinterpretFloat64, value); - if (name == I64_CTTZ) + } + if (name == I64_CTTZ) { return builder.makeUnary(UnaryOp::CtzInt64, value); - if (name == I64_CTLZ) + } + if (name == I64_CTLZ) { return builder.makeUnary(UnaryOp::ClzInt64, value); - if (name == I64_CTPOP) + } + if (name == I64_CTPOP) { return builder.makeUnary(UnaryOp::PopcntInt64, value); - if (name == I64_ATOMICS_LOAD) + } + if (name == I64_ATOMICS_LOAD) { return builder.makeAtomicLoad(8, 0, value, i64); + } } else if (num == 2) { // 2 params,binary - if (name == I64_CONST) + if (name == I64_CONST) { return builder.makeConst(getLiteral(ast)); + } auto* left = process(ast[2][0]); auto* right = process(ast[2][1]); // maths - if (name == I64_ADD) + if (name == I64_ADD) { return builder.makeBinary(BinaryOp::AddInt64, left, right); - if (name == I64_SUB) + } + if (name == I64_SUB) { return builder.makeBinary(BinaryOp::SubInt64, left, right); - if (name == I64_MUL) + } + if (name == I64_MUL) { return builder.makeBinary(BinaryOp::MulInt64, left, right); + } if (name == I64_UDIV) { Binary* div = builder.makeBinary(BinaryOp::DivUInt64, left, right); @@ -2463,39 +2535,55 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { builder.makeBinary(BinaryOp::RemSInt64, left, right); return makeTrappingBinary(rem, trappingFunctions); } - if (name == I64_AND) + if (name == I64_AND) { return builder.makeBinary(BinaryOp::AndInt64, left, right); - if (name == I64_OR) + } + if (name == I64_OR) { return builder.makeBinary(BinaryOp::OrInt64, left, right); - if (name == I64_XOR) + } + if (name == I64_XOR) { return builder.makeBinary(BinaryOp::XorInt64, left, right); - if (name == I64_SHL) + } + if (name == I64_SHL) { return builder.makeBinary(BinaryOp::ShlInt64, left, right); - if (name == I64_ASHR) + } + if (name == I64_ASHR) { return builder.makeBinary(BinaryOp::ShrSInt64, left, right); - if (name == I64_LSHR) + } + if (name == I64_LSHR) { return builder.makeBinary(BinaryOp::ShrUInt64, left, right); + } // comps - if (name == I64_EQ) + if (name == I64_EQ) { return builder.makeBinary(BinaryOp::EqInt64, left, right); - if (name == I64_NE) + } + if (name == I64_NE) { return builder.makeBinary(BinaryOp::NeInt64, left, right); - if (name == I64_ULE) + } + if (name == I64_ULE) { return builder.makeBinary(BinaryOp::LeUInt64, left, right); - if (name == I64_SLE) + } + if (name == I64_SLE) { return builder.makeBinary(BinaryOp::LeSInt64, left, right); - if (name == I64_UGE) + } + if (name == I64_UGE) { return builder.makeBinary(BinaryOp::GeUInt64, left, right); - if (name == I64_SGE) + } + if (name == I64_SGE) { return builder.makeBinary(BinaryOp::GeSInt64, left, right); - if (name == I64_ULT) + } + if (name == I64_ULT) { return builder.makeBinary(BinaryOp::LtUInt64, left, right); - if (name == I64_SLT) + } + if (name == I64_SLT) { return builder.makeBinary(BinaryOp::LtSInt64, left, right); - if (name == I64_UGT) + } + if (name == I64_UGT) { return builder.makeBinary(BinaryOp::GtUInt64, left, right); - if (name == I64_SGT) + } + if (name == I64_SGT) { return builder.makeBinary(BinaryOp::GtSInt64, left, right); + } // atomics if (name == I64_ATOMICS_STORE) { wasm.memory.shared = true; @@ -2545,14 +2633,16 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { break; } case 'f': { - if (name == F32_COPYSIGN) + if (name == F32_COPYSIGN) { return builder.makeBinary(BinaryOp::CopySignFloat32, process(ast[2][0]), process(ast[2][1])); - if (name == F64_COPYSIGN) + } + if (name == F64_COPYSIGN) { return builder.makeBinary(BinaryOp::CopySignFloat64, process(ast[2][0]), process(ast[2][1])); + } break; } default: {} @@ -2960,10 +3050,12 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { min = index; max = index; } else { - if (index < min) + if (index < min) { min = index; - if (index > max) + } + if (index > max) { max = index; + } } } } @@ -3059,8 +3151,9 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { breakWhenNotMatching->name = br->default_; } for (size_t i = 0; i < br->targets.size(); i++) { - if (br->targets[i].isNull()) + if (br->targets[i].isNull()) { br->targets[i] = br->default_; + } } } else { // we can't switch, make an if-chain instead of br_table @@ -3087,8 +3180,9 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { builder.makeBreak(name), chain); chain = iff; - if (!first) + if (!first) { first = iff; + } } auto next = allocator.alloc<Block>(); top->name = name; @@ -3153,10 +3247,12 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { processStatements = [&](Ref ast, unsigned from) -> Expression* { unsigned size = ast->size() - from; - if (size == 0) + if (size == 0) { return allocator.alloc<Nop>(); - if (size == 1) + } + if (size == 1) { return process(ast[from]); + } auto block = allocator.alloc<Block>(); for (unsigned i = from; i < ast->size(); i++) { block->list.push_back(process(ast[i])); diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 5842e5afe..b3b52bfcf 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -108,10 +108,11 @@ static PassOptions globalPassOptions = static int tracing = 0; void traceNameOrNULL(const char* name, std::ostream& out = std::cout) { - if (name) + if (name) { out << "\"" << name << "\""; - else + } else { out << "NULL"; + } } std::map<BinaryenFunctionTypeRef, size_t> functionTypes; @@ -400,10 +401,11 @@ BinaryenFunctionTypeRef BinaryenAddFunctionType(BinaryenModuleRef module, BinaryenIndex numParams) { auto* wasm = (Module*)module; auto ret = make_unique<FunctionType>(); - if (name) + if (name) { ret->name = name; - else + } else { ret->name = Name::fromInt(wasm->functionTypes.size()); + } ret->result = Type(result); for (BinaryenIndex i = 0; i < numParams; i++) { ret->params.push_back(Type(paramTypes[i])); @@ -413,13 +415,15 @@ BinaryenFunctionTypeRef BinaryenAddFunctionType(BinaryenModuleRef module, std::cout << " {\n"; std::cout << " BinaryenType paramTypes[] = { "; for (BinaryenIndex i = 0; i < numParams; i++) { - if (i > 0) + if (i > 0) { std::cout << ", "; + } std::cout << paramTypes[i]; } - if (numParams == 0) + if (numParams == 0) { // ensure the array is not empty, otherwise a compiler error on VS std::cout << "0"; + } std::cout << " };\n"; size_t id = functionTypes.size(); std::cout << " functionTypes[" << id @@ -811,29 +815,34 @@ BinaryenExpressionRef BinaryenBlock(BinaryenModuleRef module, BinaryenIndex numChildren, BinaryenType type) { auto* ret = ((Module*)module)->allocator.alloc<Block>(); - if (name) + if (name) { ret->name = name; + } for (BinaryenIndex i = 0; i < numChildren; i++) { ret->list.push_back((Expression*)children[i]); } - if (type != BinaryenTypeAuto()) + if (type != BinaryenTypeAuto()) { ret->finalize(Type(type)); - else + } else { ret->finalize(); + } if (tracing) { std::cout << " {\n"; std::cout << " BinaryenExpressionRef children[] = { "; for (BinaryenIndex i = 0; i < numChildren; i++) { - if (i > 0) + if (i > 0) { std::cout << ", "; - if (i % 6 == 5) + } + if (i % 6 == 5) { std::cout << "\n "; // don't create hugely long lines + } std::cout << "expressions[" << expressions[children[i]] << "]"; } - if (numChildren == 0) + if (numChildren == 0) { // ensure the array is not empty, otherwise a compiler error on VS std::cout << "0"; + } std::cout << " };\n "; traceExpression( ret, "BinaryenBlock", StringLit(name), "children", numChildren, type); @@ -895,13 +904,15 @@ BinaryenExpressionRef BinaryenSwitch(BinaryenModuleRef module, std::cout << " {\n"; std::cout << " const char* names[] = { "; for (BinaryenIndex i = 0; i < numNames; i++) { - if (i > 0) + if (i > 0) { std::cout << ", "; + } std::cout << "\"" << names[i] << "\""; } - if (numNames == 0) - std::cout << "0"; // ensure the array is not empty, otherwise a compiler - // error on VS + if (numNames == 0) { + // ensure the array is not empty, otherwise a compiler error on VS + std::cout << "0"; + } std::cout << " };\n "; traceExpression(ret, "BinaryenSwitch", @@ -933,13 +944,15 @@ BinaryenExpressionRef BinaryenCall(BinaryenModuleRef module, std::cout << " {\n"; std::cout << " BinaryenExpressionRef operands[] = { "; for (BinaryenIndex i = 0; i < numOperands; i++) { - if (i > 0) + if (i > 0) { std::cout << ", "; + } std::cout << "expressions[" << expressions[operands[i]] << "]"; } - if (numOperands == 0) + if (numOperands == 0) { // ensure the array is not empty, otherwise a compiler error on VS std::cout << "0"; + } std::cout << " };\n "; traceExpression(ret, "BinaryenCall", @@ -970,13 +983,15 @@ BinaryenExpressionRef BinaryenCallIndirect(BinaryenModuleRef module, std::cout << " {\n"; std::cout << " BinaryenExpressionRef operands[] = { "; for (BinaryenIndex i = 0; i < numOperands; i++) { - if (i > 0) + if (i > 0) { std::cout << ", "; + } std::cout << "expressions[" << expressions[operands[i]] << "]"; } - if (numOperands == 0) + if (numOperands == 0) { // ensure the array is not empty, otherwise a compiler error on VS std::cout << "0"; + } std::cout << " };\n "; traceExpression(ret, "BinaryenCallIndirect", @@ -1197,13 +1212,15 @@ BinaryenExpressionRef BinaryenHost(BinaryenModuleRef module, std::cout << " {\n"; std::cout << " BinaryenExpressionRef operands[] = { "; for (BinaryenIndex i = 0; i < numOperands; i++) { - if (i > 0) + if (i > 0) { std::cout << ", "; + } std::cout << "expressions[" << expressions[operands[i]] << "]"; } - if (numOperands == 0) + if (numOperands == 0) { // ensure the array is not empty, otherwise a compiler error on VS std::cout << "0"; + } std::cout << " };\n "; traceExpression( ret, "BinaryenHost", StringLit(name), "operands", numOperands); @@ -1211,8 +1228,9 @@ BinaryenExpressionRef BinaryenHost(BinaryenModuleRef module, } ret->op = HostOp(op); - if (name) + if (name) { ret->nameOperand = name; + } for (BinaryenIndex i = 0; i < numOperands; i++) { ret->operands.push_back((Expression*)operands[i]); } @@ -2619,13 +2637,15 @@ BinaryenFunctionRef BinaryenAddFunction(BinaryenModuleRef module, std::cout << " {\n"; std::cout << " BinaryenType varTypes[] = { "; for (BinaryenIndex i = 0; i < numVarTypes; i++) { - if (i > 0) + if (i > 0) { std::cout << ", "; + } std::cout << varTypes[i]; } - if (numVarTypes == 0) + if (numVarTypes == 0) { // ensure the array is not empty, otherwise a compiler error on VS std::cout << "0"; + } std::cout << " };\n"; auto id = functions.size(); functions[ret] = id; @@ -2887,8 +2907,9 @@ void BinaryenSetFunctionTable(BinaryenModuleRef module, std::cout << " {\n"; std::cout << " const char* funcNames[] = { "; for (BinaryenIndex i = 0; i < numFuncNames; i++) { - if (i > 0) + if (i > 0) { std::cout << ", "; + } std::cout << "\"" << funcNames[i] << "\""; } std::cout << " };\n"; @@ -2926,51 +2947,60 @@ void BinaryenSetMemory(BinaryenModuleRef module, for (BinaryenIndex i = 0; i < numSegments; i++) { std::cout << " const char segment" << i << "[] = { "; for (BinaryenIndex j = 0; j < segmentSizes[i]; j++) { - if (j > 0) + if (j > 0) { std::cout << ", "; + } std::cout << int(segments[i][j]); } std::cout << " };\n"; } std::cout << " const char* segments[] = { "; for (BinaryenIndex i = 0; i < numSegments; i++) { - if (i > 0) + if (i > 0) { std::cout << ", "; + } std::cout << "segment" << i; } - if (numSegments == 0) + if (numSegments == 0) { // ensure the array is not empty, otherwise a compiler error on VS std::cout << "0"; + } std::cout << " };\n"; std::cout << " int8_t segmentPassive[] = { "; for (BinaryenIndex i = 0; i < numSegments; i++) { - if (i > 0) + if (i > 0) { std::cout << ", "; + } std::cout << int(segmentPassive[i]); } - if (numSegments == 0) + if (numSegments == 0) { // ensure the array is not empty, otherwise a compiler error on VS std::cout << "0"; + } std::cout << " };\n"; std::cout << " BinaryenExpressionRef segmentOffsets[] = { "; for (BinaryenIndex i = 0; i < numSegments; i++) { - if (i > 0) + if (i > 0) { std::cout << ", "; + } std::cout << "expressions[" << expressions[segmentOffsets[i]] << "]"; } - if (numSegments == 0) + if (numSegments == 0) { // ensure the array is not empty, otherwise a compiler error on VS std::cout << "0"; + } std::cout << " };\n"; std::cout << " BinaryenIndex segmentSizes[] = { "; for (BinaryenIndex i = 0; i < numSegments; i++) { - if (i > 0) + if (i > 0) { std::cout << ", "; + } std::cout << segmentSizes[i]; } - if (numSegments == 0) + if (numSegments == 0) { // ensure the array is not empty, otherwise a compiler error on VS std::cout << "0"; + } std::cout << " };\n"; std::cout << " BinaryenSetMemory(the_module, " << initial << ", " << maximum << ", "; @@ -3137,8 +3167,9 @@ void BinaryenModuleRunPasses(BinaryenModuleRef module, std::cout << " {\n"; std::cout << " const char* passes[] = { "; for (BinaryenIndex i = 0; i < numPasses; i++) { - if (i > 0) + if (i > 0) { std::cout << ", "; + } std::cout << "\"" << passes[i] << "\""; } std::cout << " };\n"; @@ -3439,8 +3470,9 @@ void BinaryenFunctionRunPasses(BinaryenFunctionRef func, std::cout << " {\n"; std::cout << " const char* passes[] = { "; for (BinaryenIndex i = 0; i < numPasses; i++) { - if (i > 0) + if (i > 0) { std::cout << ", "; + } std::cout << "\"" << passes[i] << "\""; } std::cout << " };\n"; @@ -3638,13 +3670,15 @@ void RelooperAddBranchForSwitch(RelooperBlockRef from, std::cout << " {\n"; std::cout << " BinaryenIndex indexes[] = { "; for (BinaryenIndex i = 0; i < numIndexes; i++) { - if (i > 0) + if (i > 0) { std::cout << ", "; + } std::cout << indexes[i]; } - if (numIndexes == 0) + if (numIndexes == 0) { // ensure the array is not empty, otherwise a compiler error on VS std::cout << "0"; + } std::cout << " };\n"; std::cout << " RelooperAddBranchForSwitch(relooperBlocks[" << relooperBlocks[from] << "], relooperBlocks[" diff --git a/src/cfg/Relooper.cpp b/src/cfg/Relooper.cpp index 8a15fe75c..87dd4e379 100644 --- a/src/cfg/Relooper.cpp +++ b/src/cfg/Relooper.cpp @@ -48,8 +48,9 @@ static wasm::Expression* HandleFollowupMultiples(wasm::Expression* Ret, Shape* Parent, RelooperBuilder& Builder, bool InLoop) { - if (!Parent->Next) + if (!Parent->Next) { return Ret; + } auto* Curr = Ret->dynCast<wasm::Block>(); if (!Curr || Curr->name.is()) { @@ -58,8 +59,9 @@ static wasm::Expression* HandleFollowupMultiples(wasm::Expression* Ret, // for each multiple after us, we create a block target for breaks to reach while (Parent->Next) { auto* Multiple = Shape::IsMultiple(Parent->Next); - if (!Multiple) + if (!Multiple) { break; + } for (auto& iter : Multiple->InnerMap) { int Id = iter.first; Shape* Body = iter.second; @@ -120,10 +122,12 @@ Branch::Branch(std::vector<wasm::Index>&& ValuesInit, wasm::Expression* Branch::Render(RelooperBuilder& Builder, Block* Target, bool SetLabel) { auto* Ret = Builder.makeBlock(); - if (Code) + if (Code) { Ret->list.push_back(Code); - if (SetLabel) + } + if (SetLabel) { Ret->list.push_back(Builder.makeSetLabel(Target->Id)); + } if (Type == Break) { Ret->list.push_back(Builder.makeBlockBreak(Target->Id)); } else if (Type == Continue) { @@ -170,8 +174,9 @@ wasm::Expression* Block::Render(RelooperBuilder& Builder, bool InLoop) { if (IsCheckedMultipleEntry && InLoop) { Ret->list.push_back(Builder.makeSetLabel(0)); } - if (Code) + if (Code) { Ret->list.push_back(Code); + } if (!ProcessedBranchesOut.size()) { Ret->finalize(); @@ -254,8 +259,9 @@ wasm::Expression* Block::Render(RelooperBuilder& Builder, bool InLoop) { Branch* Details; if (iter != ProcessedBranchesOut.end()) { Target = iter->first; - if (Target == DefaultTarget) + if (Target == DefaultTarget) { continue; // done at the end + } Details = iter->second; // must have a condition if this is not the default target assert(Details->Condition); @@ -318,8 +324,9 @@ wasm::Expression* Block::Render(RelooperBuilder& Builder, bool InLoop) { RemainingConditions = Now; } } - if (IsDefault) + if (IsDefault) { break; + } } // finalize the if-chains @@ -385,16 +392,18 @@ wasm::Expression* Block::Render(RelooperBuilder& Builder, bool InLoop) { // this is the default, and it has no content. So make the default be // the leave for (auto& Value : Table) { - if (Value == SwitchDefault) + if (Value == SwitchDefault) { Value = SwitchLeave; + } } SwitchDefault = SwitchLeave; } } if (Details->SwitchValues) { for (auto Value : *Details->SwitchValues) { - while (Table.size() <= Value) + while (Table.size() <= Value) { Table.push_back(SwitchDefault); + } Table[Value] = CurrName; } } @@ -478,10 +487,12 @@ Relooper::Relooper(wasm::Module* ModuleInit) } Relooper::~Relooper() { - for (unsigned i = 0; i < Blocks.size(); i++) + for (unsigned i = 0; i < Blocks.size(); i++) { delete Blocks[i]; - for (unsigned i = 0; i < Shapes.size(); i++) + } + for (unsigned i = 0; i < Shapes.size(); i++) { delete Shapes[i]; + } } void Relooper::AddBlock(Block* New, int Id) { @@ -508,8 +519,9 @@ struct Liveness : public RelooperRecursor { while (ToInvestigate.size() > 0) { Block* Curr = ToInvestigate.front(); ToInvestigate.pop_front(); - if (contains(Live, Curr)) + if (contains(Live, Curr)) { continue; + } Live.insert(Curr); for (auto& iter : Curr->BranchesOut) { ToInvestigate.push_back(iter.first); @@ -905,20 +917,24 @@ private: template<typename T> static bool IsPossibleUniquePtrEquivalent(std::unique_ptr<T>& A, std::unique_ptr<T>& B) { - if (A == B) + if (A == B) { return true; - if (!A || !B) + } + if (!A || !B) { return false; + } return *A == *B; } // Checks if code is equivalent, allowing the code to also be nullptr static bool IsPossibleCodeEquivalent(wasm::Expression* A, wasm::Expression* B) { - if (A == B) + if (A == B) { return true; - if (!A || !B) + } + if (!A || !B) { return false; + } return IsCodeEquivalent(A, B); } @@ -1025,8 +1041,9 @@ void Relooper::Calculate(Block* Entry) { // Add incoming branches from live blocks, ignoring dead code for (unsigned i = 0; i < Blocks.size(); i++) { Block* Curr = Blocks[i]; - if (!contains(Live.Live, Curr)) + if (!contains(Live.Live, Curr)) { continue; + } for (auto& iter : Curr->BranchesOut) { iter.first->BranchesIn.insert(Curr); } @@ -1282,10 +1299,11 @@ void Relooper::Calculate(Block* Entry) { Queue.pop_front(); // Curr must be in the ownership map if we are in the queue Block* Owner = Helper.Ownership[Curr]; - if (!Owner) + if (!Owner) { // we have been invalidated meanwhile after being reached from two // entries continue; + } // Add all children for (auto& iter : Curr->BranchesOut) { Block* New = iter.first; @@ -1298,8 +1316,9 @@ void Relooper::Calculate(Block* Entry) { continue; } Block* NewOwner = Known->second; - if (!NewOwner) + if (!NewOwner) { continue; // We reached an invalidated node + } if (NewOwner != Owner) { // Invalidate this and all reachable that we have seen - we reached // this from two locations @@ -1321,8 +1340,9 @@ void Relooper::Calculate(Block* Entry) { BlockList ToInvalidate; for (auto* Child : CurrGroup) { for (auto* Parent : Child->BranchesIn) { - if (Ignore && contains(*Ignore, Parent)) + if (Ignore && contains(*Ignore, Parent)) { continue; + } if (Helper.Ownership[Parent] != Helper.Ownership[Child]) { ToInvalidate.push_back(Child); } @@ -1436,8 +1456,9 @@ void Relooper::Calculate(Block* Entry) { NextEntries = &TempEntries[CurrTempIndex]; NextEntries->clear(); - if (Entries->size() == 0) + if (Entries->size() == 0) { return Ret; + } if (Entries->size() == 1) { Block* Curr = *(Entries->begin()); if (Curr->BranchesIn.size() == 0) { @@ -1525,8 +1546,9 @@ void Relooper::Calculate(Block* Entry) { break; } } - if (!DeadEnd) + if (!DeadEnd) { break; + } } if (DeadEnd) { PrintDebug("Removing nesting by not handling large group " diff --git a/src/cfg/cfg-traversal.h b/src/cfg/cfg-traversal.h index abaf63c5b..79c561de0 100644 --- a/src/cfg/cfg-traversal.h +++ b/src/cfg/cfg-traversal.h @@ -79,22 +79,26 @@ struct CFGWalker : public ControlFlowWalker<SubType, VisitorType> { } void link(BasicBlock* from, BasicBlock* to) { - if (!from || !to) + if (!from || !to) { return; // if one of them is not reachable, ignore + } from->out.push_back(to); to->in.push_back(from); } static void doEndBlock(SubType* self, Expression** currp) { auto* curr = (*currp)->cast<Block>(); - if (!curr->name.is()) + if (!curr->name.is()) { return; + } auto iter = self->branches.find(curr); - if (iter == self->branches.end()) + if (iter == self->branches.end()) { return; + } auto& origins = iter->second; - if (origins.size() == 0) + if (origins.size() == 0) { return; + } // we have branches to here, so we need a new block auto* last = self->currBasicBlock; self->startBasicBlock(); @@ -270,8 +274,9 @@ struct CFGWalker : public ControlFlowWalker<SubType, VisitorType> { queue.erase(iter); alive.insert(curr); for (auto* out : curr->out) { - if (!alive.count(out)) + if (!alive.count(out)) { queue.insert(out); + } } } return alive; @@ -305,8 +310,9 @@ struct CFGWalker : public ControlFlowWalker<SubType, VisitorType> { std::map<BasicBlock*, size_t> debugIds; void generateDebugIds() { - if (debugIds.size() > 0) + if (debugIds.size() > 0) { return; + } for (auto& block : basicBlocks) { debugIds[block.get()] = debugIds.size(); } diff --git a/src/cfg/liveness-traversal.h b/src/cfg/liveness-traversal.h index b26898460..a0ce214bc 100644 --- a/src/cfg/liveness-traversal.h +++ b/src/cfg/liveness-traversal.h @@ -50,10 +50,12 @@ struct LivenessAction { LivenessAction(What what, Index index, Expression** origin) : what(what), index(index), origin(origin), effective(false) { assert(what != Other); - if (what == Get) + if (what == Get) { assert((*origin)->is<GetLocal>()); - if (what == Set) + } + if (what == Set) { assert((*origin)->is<SetLocal>()); + } } LivenessAction(Expression** origin) : what(Other), origin(origin) {} @@ -153,14 +155,17 @@ struct LivenessWalker : public CFGWalker<SubType, VisitorType, Liveness> { // need to count to see if worth it. // TODO: an if can have two copies GetLocal* getCopy(SetLocal* set) { - if (auto* get = set->value->dynCast<GetLocal>()) + if (auto* get = set->value->dynCast<GetLocal>()) { return get; + } if (auto* iff = set->value->dynCast<If>()) { - if (auto* get = iff->ifTrue->dynCast<GetLocal>()) + if (auto* get = iff->ifTrue->dynCast<GetLocal>()) { return get; + } if (iff->ifFalse) { - if (auto* get = iff->ifFalse->dynCast<GetLocal>()) + if (auto* get = iff->ifFalse->dynCast<GetLocal>()) { return get; + } } } return nullptr; @@ -188,8 +193,9 @@ struct LivenessWalker : public CFGWalker<SubType, VisitorType, Liveness> { // keep working while stuff is flowing std::unordered_set<BasicBlock*> queue; for (auto& curr : CFGWalker<SubType, VisitorType, Liveness>::basicBlocks) { - if (liveBlocks.count(curr.get()) == 0) + if (liveBlocks.count(curr.get()) == 0) { continue; // ignore dead blocks + } queue.insert(curr.get()); // do the first scan through the block, starting with nothing live at the // end, and updating the liveness at the start @@ -203,15 +209,17 @@ struct LivenessWalker : public CFGWalker<SubType, VisitorType, Liveness> { auto* curr = *iter; queue.erase(iter); LocalSet live; - if (!mergeStartsAndCheckChange(curr->out, curr->contents.end, live)) + if (!mergeStartsAndCheckChange(curr->out, curr->contents.end, live)) { continue; + } assert(curr->contents.end.size() < live.size()); curr->contents.end = live; scanLivenessThroughActions(curr->contents.actions, live); // liveness is now calculated at the start. if something // changed, all predecessor blocks need recomputation - if (curr->contents.start == live) + if (curr->contents.start == live) { continue; + } assert(curr->contents.start.size() < live.size()); curr->contents.start = live; for (auto* in : curr->in) { @@ -226,8 +234,9 @@ struct LivenessWalker : public CFGWalker<SubType, VisitorType, Liveness> { bool mergeStartsAndCheckChange(std::vector<BasicBlock*>& blocks, LocalSet& old, LocalSet& ret) { - if (blocks.size() == 0) + if (blocks.size() == 0) { return false; + } ret = blocks[0]->contents.start; if (blocks.size() > 1) { // more than one, so we must merge diff --git a/src/dataflow/graph.h b/src/dataflow/graph.h index f93621a91..f41346857 100644 --- a/src/dataflow/graph.h +++ b/src/dataflow/graph.h @@ -110,13 +110,15 @@ struct Graph : public UnifiedExpressionVisitor<Graph, Node*> { module = moduleInit; auto numLocals = func->getNumLocals(); - if (numLocals == 0) + if (numLocals == 0) { return; // nothing to do + } // Set up initial local state IR. setInReachable(); for (Index i = 0; i < numLocals; i++) { - if (!isRelevantType(func->getLocalType(i))) + if (!isRelevantType(func->getLocalType(i))) { continue; + } Node* node; auto type = func->getLocalType(i); if (func->isParam(i)) { @@ -167,8 +169,9 @@ struct Graph : public UnifiedExpressionVisitor<Graph, Node*> { assert(!node->isBad()); Builder builder(*module); auto type = node->getWasmType(); - if (!isConcreteType(type)) + if (!isConcreteType(type)) { return &bad; + } auto* zero = makeZero(type); auto* expr = builder.makeBinary( Abstract::getBinary(type, equal ? Abstract::Eq : Abstract::Ne), @@ -313,8 +316,9 @@ struct Graph : public UnifiedExpressionVisitor<Graph, Node*> { auto& breaks = breakStates[curr->name]; // Phis are possible, check for them. for (Index i = 0; i < numLocals; i++) { - if (!isRelevantType(func->getLocalType(i))) + if (!isRelevantType(func->getLocalType(i))) { continue; + } bool needPhi = false; // We replaced the proper value with a Var. If it's still that // Var - or it's the original proper value, which can happen with @@ -420,8 +424,9 @@ struct Graph : public UnifiedExpressionVisitor<Graph, Node*> { // These are ok as-is. // Check if our child is supported. auto* value = expandFromI1(visit(curr->value), curr); - if (value->isBad()) + if (value->isBad()) { return value; + } // Great, we are supported! auto* ret = addNode(Node::makeExpr(curr, curr)); ret->addValue(value); @@ -432,8 +437,9 @@ struct Graph : public UnifiedExpressionVisitor<Graph, Node*> { // These can be implemented using a binary. // Check if our child is supported. auto* value = expandFromI1(visit(curr->value), curr); - if (value->isBad()) + if (value->isBad()) { return value; + } // Great, we are supported! return makeZeroComp(value, true, curr); } @@ -491,11 +497,13 @@ struct Graph : public UnifiedExpressionVisitor<Graph, Node*> { // These are ok as-is. // Check if our children are supported. auto* left = expandFromI1(visit(curr->left), curr); - if (left->isBad()) + if (left->isBad()) { return left; + } auto* right = expandFromI1(visit(curr->right), curr); - if (right->isBad()) + if (right->isBad()) { return right; + } // Great, we are supported! auto* ret = addNode(Node::makeExpr(curr, curr)); ret->addValue(left); @@ -556,14 +564,17 @@ struct Graph : public UnifiedExpressionVisitor<Graph, Node*> { } Node* doVisitSelect(Select* curr) { auto* ifTrue = expandFromI1(visit(curr->ifTrue), curr); - if (ifTrue->isBad()) + if (ifTrue->isBad()) { return ifTrue; + } auto* ifFalse = expandFromI1(visit(curr->ifFalse), curr); - if (ifFalse->isBad()) + if (ifFalse->isBad()) { return ifFalse; + } auto* condition = ensureI1(visit(curr->condition), curr); - if (condition->isBad()) + if (condition->isBad()) { return condition; + } // Great, we are supported! auto* ret = addNode(Node::makeExpr(curr, curr)); ret->addValue(condition); @@ -661,8 +672,9 @@ struct Graph : public UnifiedExpressionVisitor<Graph, Node*> { Index numLocals = func->getNumLocals(); Node* block = nullptr; for (Index i = 0; i < numLocals; i++) { - if (!isRelevantType(func->getLocalType(i))) + if (!isRelevantType(func->getLocalType(i))) { continue; + } // Process the inputs. If any is bad, the phi is bad. bool bad = false; for (auto& state : states) { @@ -673,8 +685,9 @@ struct Graph : public UnifiedExpressionVisitor<Graph, Node*> { break; } } - if (bad) + if (bad) { continue; + } // Nothing is bad, proceed. Node* first = nullptr; for (auto& state : states) { @@ -724,16 +737,18 @@ struct Graph : public UnifiedExpressionVisitor<Graph, Node*> { // the set. SetLocal* getSet(Node* node) { auto iter = nodeParentMap.find(node); - if (iter == nodeParentMap.end()) + if (iter == nodeParentMap.end()) { return nullptr; + } return iter->second->dynCast<SetLocal>(); } // Given an expression, return the parent if such exists. Expression* getParent(Expression* curr) { auto iter = expressionParentMap.find(curr); - if (iter == expressionParentMap.end()) + if (iter == expressionParentMap.end()) { return nullptr; + } return iter->second; } diff --git a/src/dataflow/node.h b/src/dataflow/node.h index 8977ab41c..2966034ac 100644 --- a/src/dataflow/node.h +++ b/src/dataflow/node.h @@ -170,8 +170,9 @@ struct Node { } bool operator==(const Node& other) { - if (type != other.type) + if (type != other.type) { return false; + } switch (type) { case Var: case Block: @@ -183,15 +184,18 @@ struct Node { break; } case Cond: - if (index != other.index) + if (index != other.index) { return false; + } default: {} } - if (values.size() != other.values.size()) + if (values.size() != other.values.size()) { return false; + } for (Index i = 0; i < values.size(); i++) { - if (*(values[i]) != *(other.values[i])) + if (*(values[i]) != *(other.values[i])) { return false; + } } return true; } diff --git a/src/dataflow/utils.h b/src/dataflow/utils.h index 337dfec5e..4408c6080 100644 --- a/src/dataflow/utils.h +++ b/src/dataflow/utils.h @@ -35,8 +35,9 @@ namespace DataFlow { inline std::ostream& dump(Node* node, std::ostream& o, size_t indent = 0) { auto doIndent = [&]() { - for (size_t i = 0; i < indent; i++) + for (size_t i = 0; i < indent; i++) { o << ' '; + } }; doIndent(); o << '[' << node << ' '; diff --git a/src/emscripten-optimizer/istring.h b/src/emscripten-optimizer/istring.h index 320a3e590..21f94fcb9 100644 --- a/src/emscripten-optimizer/istring.h +++ b/src/emscripten-optimizer/istring.h @@ -136,12 +136,15 @@ struct IString { const char* stripPrefix(const char* prefix) const { const char* ptr = str; while (true) { - if (*prefix == 0) + if (*prefix == 0) { return ptr; - if (*ptr == 0) + } + if (*ptr == 0) { return nullptr; - if (*ptr++ != *prefix++) + } + if (*ptr++ != *prefix++) { return nullptr; + } } } @@ -191,11 +194,13 @@ public: strncpy(curr, init, size); while (1) { char* end = strchr(curr, ' '); - if (end) + if (end) { *end = 0; + } insert(curr); - if (!end) + if (!end) { break; + } curr = end + 1; } } diff --git a/src/emscripten-optimizer/optimizer-shared.cpp b/src/emscripten-optimizer/optimizer-shared.cpp index 3ac3ca7ea..172b9f45f 100644 --- a/src/emscripten-optimizer/optimizer-shared.cpp +++ b/src/emscripten-optimizer/optimizer-shared.cpp @@ -61,27 +61,32 @@ AsmType detectType(Ref node, if (node->isString()) { if (asmData) { AsmType ret = asmData->getType(node->getCString()); - if (ret != ASM_NONE) + if (ret != ASM_NONE) { return ret; + } } if (!inVarDef) { - if (node == INF || node == NaN) + if (node == INF || node == NaN) { return ASM_DOUBLE; - if (node == TEMP_RET0) + } + if (node == TEMP_RET0) { return ASM_INT; + } return ASM_NONE; } // We are in a variable definition, where Math_fround(0) optimized into a // global constant becomes f0 = Math_fround(0) - if (ASM_FLOAT_ZERO.isNull()) + if (ASM_FLOAT_ZERO.isNull()) { ASM_FLOAT_ZERO = node->getIString(); - else + } else { assert(node == ASM_FLOAT_ZERO); + } return ASM_FLOAT; } if (node->isNumber()) { - if (!wasm::isInteger(node->getNumber())) + if (!wasm::isInteger(node->getNumber())) { return ASM_DOUBLE; + } return ASM_INT; } switch (node[0]->getCString()[0]) { @@ -105,20 +110,21 @@ AsmType detectType(Ref node, if (node[0] == CALL) { if (node[1]->isString()) { IString name = node[1]->getIString(); - if (name == MATH_FROUND || name == minifiedFround) + if (name == MATH_FROUND || name == minifiedFround) { return ASM_FLOAT; - else if (allowI64 && (name == INT64 || name == INT64_CONST)) + } else if (allowI64 && (name == INT64 || name == INT64_CONST)) { return ASM_INT64; - else if (name == SIMD_FLOAT32X4 || name == SIMD_FLOAT32X4_CHECK) + } else if (name == SIMD_FLOAT32X4 || name == SIMD_FLOAT32X4_CHECK) { return ASM_FLOAT32X4; - else if (name == SIMD_FLOAT64X2 || name == SIMD_FLOAT64X2_CHECK) + } else if (name == SIMD_FLOAT64X2 || name == SIMD_FLOAT64X2_CHECK) { return ASM_FLOAT64X2; - else if (name == SIMD_INT8X16 || name == SIMD_INT8X16_CHECK) + } else if (name == SIMD_INT8X16 || name == SIMD_INT8X16_CHECK) { return ASM_INT8X16; - else if (name == SIMD_INT16X8 || name == SIMD_INT16X8_CHECK) + } else if (name == SIMD_INT16X8 || name == SIMD_INT16X8_CHECK) { return ASM_INT16X8; - else if (name == SIMD_INT32X4 || name == SIMD_INT32X4_CHECK) + } else if (name == SIMD_INT32X4 || name == SIMD_INT32X4_CHECK) { return ASM_INT32X4; + } } return ASM_NONE; } else if (node[0] == CONDITIONAL) { @@ -155,8 +161,9 @@ AsmType detectType(Ref node, } else if (node[0] == SUB) { assert(node[1]->isString()); HeapInfo info = parseHeap(node[1][1]->getCString()); - if (info.valid) + if (info.valid) { return ASM_NONE; + } return info.floaty ? ASM_DOUBLE : ASM_INT; // XXX ASM_FLOAT? } break; @@ -179,12 +186,15 @@ AsmSign detectSign(Ref node, IString minifiedFround) { } if (node->isNumber()) { double value = node->getNumber(); - if (value < 0) + if (value < 0) { return ASM_SIGNED; - if (value > uint32_t(-1) || fmod(value, 1) != 0) + } + if (value > uint32_t(-1) || fmod(value, 1) != 0) { return ASM_NONSIGNED; - if (wasm::isSInteger32(value)) + } + if (wasm::isSInteger32(value)) { return ASM_FLEXIBLE; + } return ASM_UNSIGNED; } IString type = node[0]->getIString(); @@ -192,8 +202,9 @@ AsmSign detectSign(Ref node, IString minifiedFround) { IString op = node[1]->getIString(); switch (op.str[0]) { case '>': { - if (op == TRSHIFT) + if (op == TRSHIFT) { return ASM_UNSIGNED; + } } // fallthrough case '|': case '&': @@ -228,8 +239,9 @@ AsmSign detectSign(Ref node, IString minifiedFround) { return detectSign(node[2], minifiedFround); } else if (type == CALL) { if (node[1]->isString() && - (node[1] == MATH_FROUND || node[1] == minifiedFround)) + (node[1] == MATH_FROUND || node[1] == minifiedFround)) { return ASM_NONSIGNED; + } } else if (type == SEQ) { return detectSign(node[2], minifiedFround); } diff --git a/src/emscripten-optimizer/optimizer.h b/src/emscripten-optimizer/optimizer.h index 36a9322fd..e30347025 100644 --- a/src/emscripten-optimizer/optimizer.h +++ b/src/emscripten-optimizer/optimizer.h @@ -64,8 +64,9 @@ struct AsmData { AsmType getType(const cashew::IString& name) { auto ret = locals.find(name); - if (ret != locals.end()) + if (ret != locals.end()) { return ret->second.type; + } return ASM_NONE; } void setType(const cashew::IString& name, AsmType type) { diff --git a/src/emscripten-optimizer/parser.h b/src/emscripten-optimizer/parser.h index d180ea12c..1d4cda79b 100644 --- a/src/emscripten-optimizer/parser.h +++ b/src/emscripten-optimizer/parser.h @@ -160,16 +160,19 @@ template<class NodeRef, class Builder> class Parser { } if (curr[0] == '/' && curr[1] == '/') { curr += 2; - while (*curr && *curr != '\n') + while (*curr && *curr != '\n') { curr++; - if (*curr) + } + if (*curr) { curr++; + } continue; } if (curr[0] == '/' && curr[1] == '*') { curr += 2; - while (*curr && (curr[0] != '*' || curr[1] != '/')) + while (*curr && (curr[0] != '*' || curr[1] != '/')) { curr++; + } curr += 2; continue; } @@ -180,9 +183,11 @@ template<class NodeRef, class Builder> class Parser { static bool isDigit(char x) { return x >= '0' && x <= '9'; } static bool hasChar(const char* list, char x) { - while (*list) - if (*list++ == x) + while (*list) { + if (*list++ == x) { return true; + } + } return false; } @@ -247,8 +252,9 @@ template<class NodeRef, class Builder> class Parser { } else if (*src >= 'A' && *src <= 'F') { num *= 16; num += *src - 'A' + 10; - } else + } else { break; + } src++; } } else { @@ -402,12 +408,15 @@ template<class NodeRef, class Builder> class Parser { return parseExpression(parseFrag(frag), src, seps); } case SEPARATOR: { - if (frag.str == OPEN_PAREN) + if (frag.str == OPEN_PAREN) { return parseExpression(parseAfterParen(src), src, seps); - if (frag.str == OPEN_BRACE) + } + if (frag.str == OPEN_BRACE) { return parseExpression(parseAfterBrace(src), src, seps); - if (frag.str == OPEN_CURLY) + } + if (frag.str == OPEN_CURLY) { return parseExpression(parseAfterCurly(src), src, seps); + } abort(); } case OPERATOR: { @@ -439,30 +448,31 @@ template<class NodeRef, class Builder> class Parser { NodeRef parseAfterKeyword(Frag& frag, char*& src, const char* seps) { skipSpace(src); - if (frag.str == FUNCTION) + if (frag.str == FUNCTION) { return parseFunction(src, seps); - else if (frag.str == VAR) + } else if (frag.str == VAR) { return parseVar(src, seps, false); - else if (frag.str == CONST) + } else if (frag.str == CONST) { return parseVar(src, seps, true); - else if (frag.str == RETURN) + } else if (frag.str == RETURN) { return parseReturn(src, seps); - else if (frag.str == IF) + } else if (frag.str == IF) { return parseIf(src, seps); - else if (frag.str == DO) + } else if (frag.str == DO) { return parseDo(src, seps); - else if (frag.str == WHILE) + } else if (frag.str == WHILE) { return parseWhile(src, seps); - else if (frag.str == BREAK) + } else if (frag.str == BREAK) { return parseBreak(src, seps); - else if (frag.str == CONTINUE) + } else if (frag.str == CONTINUE) { return parseContinue(src, seps); - else if (frag.str == SWITCH) + } else if (frag.str == SWITCH) { return parseSwitch(src, seps); - else if (frag.str == NEW) + } else if (frag.str == NEW) { return parseNew(src, seps); - else if (frag.str == FOR) + } else if (frag.str == FOR) { return parseFor(src, seps); + } dump(frag.str.str, src); abort(); return nullptr; @@ -482,15 +492,17 @@ template<class NodeRef, class Builder> class Parser { src++; while (1) { skipSpace(src); - if (*src == ')') + if (*src == ')') { break; + } Frag arg(src); assert(arg.type == IDENT); src += arg.size; Builder::appendArgumentToFunction(ret, arg.str); skipSpace(src); - if (*src == ')') + if (*src == ')') { break; + } if (*src == ',') { src++; continue; @@ -507,8 +519,9 @@ template<class NodeRef, class Builder> class Parser { NodeRef ret = Builder::makeVar(is_const); while (1) { skipSpace(src); - if (*src == ';') + if (*src == ';') { break; + } Frag name(src); assert(name.type == IDENT); NodeRef value; @@ -521,8 +534,9 @@ template<class NodeRef, class Builder> class Parser { } Builder::appendToVar(ret, name.str, value); skipSpace(src); - if (*src == ';') + if (*src == ';') { break; + } if (*src == ',') { src++; continue; @@ -538,8 +552,9 @@ template<class NodeRef, class Builder> class Parser { NodeRef value = !hasChar(seps, *src) ? parseElement(src, seps) : nullptr; skipSpace(src); assert(hasChar(seps, *src)); - if (*src == ';') + if (*src == ';') { src++; + } return Builder::makeReturn(value); } @@ -597,16 +612,18 @@ template<class NodeRef, class Builder> class Parser { NodeRef parseBreak(char*& src, const char* seps) { skipSpace(src); Frag next(src); - if (next.type == IDENT) + if (next.type == IDENT) { src += next.size; + } return Builder::makeBreak(next.type == IDENT ? next.str : IString()); } NodeRef parseContinue(char*& src, const char* seps) { skipSpace(src); Frag next(src); - if (next.type == IDENT) + if (next.type == IDENT) { src += next.size; + } return Builder::makeContinue(next.type == IDENT ? next.str : IString()); } @@ -618,8 +635,9 @@ template<class NodeRef, class Builder> class Parser { while (1) { // find all cases and possibly a default skipSpace(src); - if (*src == '}') + if (*src == '}') { break; + } Frag next(src); if (next.type == KEYWORD) { if (next.str == CASE) { @@ -681,10 +699,12 @@ template<class NodeRef, class Builder> class Parser { NodeRef parseAfterIdent(Frag& frag, char*& src, const char* seps) { skipSpace(src); - if (*src == '(') + if (*src == '(') { return parseExpression(parseCall(parseFrag(frag), src), src, seps); - if (*src == '[') + } + if (*src == '[') { return parseExpression(parseIndexing(parseFrag(frag), src), src, seps); + } if (*src == ':' && expressionPartsStack.back().size() == 0) { src++; skipSpace(src); @@ -697,8 +717,9 @@ template<class NodeRef, class Builder> class Parser { } return Builder::makeLabel(frag.str, inner); } - if (*src == '.') + if (*src == '.') { return parseExpression(parseDotting(parseFrag(frag), src), src, seps); + } return parseExpression(parseFrag(frag), src, seps); } @@ -709,12 +730,14 @@ template<class NodeRef, class Builder> class Parser { NodeRef ret = Builder::makeCall(target); while (1) { skipSpace(src); - if (*src == ')') + if (*src == ')') { break; + } Builder::appendToCall(ret, parseElement(src, ",)")); skipSpace(src); - if (*src == ')') + if (*src == ')') { break; + } if (*src == ',') { src++; continue; @@ -767,13 +790,15 @@ template<class NodeRef, class Builder> class Parser { while (1) { skipSpace(src); assert(*src); - if (*src == ']') + if (*src == ']') { break; + } NodeRef element = parseElement(src, ",]"); Builder::appendToArray(ret, element); skipSpace(src); - if (*src == ']') + if (*src == ']') { break; + } if (*src == ',') { src++; continue; @@ -790,8 +815,9 @@ template<class NodeRef, class Builder> class Parser { while (1) { skipSpace(src); assert(*src); - if (*src == '}') + if (*src == '}') { break; + } Frag key(src); assert(key.type == IDENT || key.type == STRING); src += key.size; @@ -801,8 +827,9 @@ template<class NodeRef, class Builder> class Parser { NodeRef value = parseElement(src, ",}"); Builder::appendToObject(ret, key.str, value); skipSpace(src); - if (*src == '}') + if (*src == '}') { break; + } if (*src == ',') { src++; continue; @@ -868,8 +895,9 @@ template<class NodeRef, class Builder> class Parser { parts.push_back(initial); } NodeRef last = parseElement(src, seps); - if (!top) + if (!top) { return last; + } { // |parts| may have been invalidated by that call ExpressionParts& parts = expressionPartsStack.back(); @@ -880,11 +908,13 @@ template<class NodeRef, class Builder> class Parser { if (ops.rtl) { // right to left for (int i = parts.size() - 1; i >= 0; i--) { - if (parts[i].isNode) + if (parts[i].isNode) { continue; + } IString op = parts[i].getOp(); - if (!ops.ops.has(op)) + if (!ops.ops.has(op)) { continue; + } if (ops.type == OperatorClass::Binary && i > 0 && i < (int)parts.size() - 1) { parts[i] = @@ -893,20 +923,23 @@ template<class NodeRef, class Builder> class Parser { parts.erase(parts.begin() + i - 1); } else if (ops.type == OperatorClass::Prefix && i < (int)parts.size() - 1) { - if (i > 0 && parts[i - 1].isNode) + if (i > 0 && parts[i - 1].isNode) { // cannot apply prefix operator if it would join two nodes continue; + } parts[i] = Builder::makePrefix(op, parts[i + 1].getNode()); parts.erase(parts.begin() + i + 1); } else if (ops.type == OperatorClass::Tertiary) { // we must be at X ? Y : Z // ^ // dumpParts(parts, i); - if (op != COLON) + if (op != COLON) { continue; + } assert(i < (int)parts.size() - 1 && i >= 3); - if (parts[i - 2].getOp() != QUESTION) + if (parts[i - 2].getOp() != QUESTION) { continue; // e.g. x ? y ? 1 : 0 : 2 + } parts[i - 3] = Builder::makeConditional(parts[i - 3].getNode(), parts[i - 1].getNode(), parts[i + 1].getNode()); @@ -918,11 +951,13 @@ template<class NodeRef, class Builder> class Parser { } else { // left to right for (int i = 0; i < (int)parts.size(); i++) { - if (parts[i].isNode) + if (parts[i].isNode) { continue; + } IString op = parts[i].getOp(); - if (!ops.ops.has(op)) + if (!ops.ops.has(op)) { continue; + } if (ops.type == OperatorClass::Binary && i > 0 && i < (int)parts.size() - 1) { parts[i] = @@ -932,9 +967,10 @@ template<class NodeRef, class Builder> class Parser { i--; } else if (ops.type == OperatorClass::Prefix && i < (int)parts.size() - 1) { - if (i > 0 && parts[i - 1].isNode) + if (i > 0 && parts[i - 1].isNode) { // cannot apply prefix operator if it would join two nodes continue; + } parts[i] = Builder::makePrefix(op, parts[i + 1].getNode()); parts.erase(parts.begin() + i + 1); // allow a previous prefix operator to cascade @@ -960,23 +996,27 @@ template<class NodeRef, class Builder> class Parser { // dump("parseBlock", src); while (1) { skipSpace(src); - if (*src == 0) + if (*src == 0) { break; + } if (*src == ';') { src++; // skip a statement in this block continue; } - if (hasChar(seps, *src)) + if (hasChar(seps, *src)) { break; + } if (!!keywordSep1) { Frag next(src); - if (next.type == KEYWORD && next.str == keywordSep1) + if (next.type == KEYWORD && next.str == keywordSep1) { break; + } } if (!!keywordSep2) { Frag next(src); - if (next.type == KEYWORD && next.str == keywordSep2) + if (next.type == KEYWORD && next.str == keywordSep2) { break; + } } NodeRef element = parseElementOrStatement(src, seps); Builder::appendToBlock(block, element); @@ -1061,12 +1101,14 @@ template<class NodeRef, class Builder> class Parser { while (*curr) { if (*curr == '\n') { newlinesLeft--; - if (newlinesLeft == 0) + if (newlinesLeft == 0) { break; + } } charsLeft--; - if (charsLeft == 0) + if (charsLeft == 0) { break; + } fprintf(stderr, "%c", *curr++); } fprintf(stderr, "\n\n"); diff --git a/src/emscripten-optimizer/simple_ast.cpp b/src/emscripten-optimizer/simple_ast.cpp index 5853b3289..6afa0a66e 100644 --- a/src/emscripten-optimizer/simple_ast.cpp +++ b/src/emscripten-optimizer/simple_ast.cpp @@ -105,10 +105,11 @@ void Value::stringify(std::ostream& os, bool pretty) { } for (size_t i = 0; i < arr->size(); i++) { if (i > 0) { - if (pretty) + if (pretty) { os << "," << std::endl; - else + } else { os << ", "; + } } indentify(); (*arr)[i]->stringify(os, pretty); @@ -141,8 +142,9 @@ void Value::stringify(std::ostream& os, bool pretty) { first = false; } else { os << ", "; - if (pretty) + if (pretty) { os << std::endl; + } } indentify(); os << '"' << i.first.c_str() << "\": "; @@ -178,10 +180,11 @@ void Value::stringify(std::ostream& os, bool pretty) { void dump(const char* str, Ref node, bool pretty) { std::cerr << str << ": "; - if (!!node) + if (!!node) { node->stringify(std::cerr, pretty); - else + } else { std::cerr << "(nullptr)"; + } std::cerr << std::endl; } diff --git a/src/emscripten-optimizer/simple_ast.h b/src/emscripten-optimizer/simple_ast.h index e4f2c1f86..bcfce9712 100644 --- a/src/emscripten-optimizer/simple_ast.h +++ b/src/emscripten-optimizer/simple_ast.h @@ -153,8 +153,9 @@ struct Value { void free() { if (type == Array) { arr->clear(); - } else if (type == Object) + } else if (type == Object) { delete obj; + } type = Null; num = 0; } @@ -286,8 +287,9 @@ struct Value { } bool operator==(const Value& other) { - if (type != other.type) + if (type != other.type) { return false; + } switch (other.type) { case String: return str == other.str; @@ -334,8 +336,9 @@ struct Value { arr->push_back(temp); curr = temp->parse(curr); skip(); - if (*curr == ']') + if (*curr == ']') { break; + } assert(*curr == ','); curr++; skip(); @@ -377,8 +380,9 @@ struct Value { curr = value->parse(curr); (*obj)[key] = value; skip(); - if (*curr == '}') + if (*curr == '}') { break; + } assert(*curr == ','); curr++; skip(); @@ -411,8 +415,9 @@ struct Value { void setSize(size_t size) { assert(isArray()); auto old = arr->size(); - if (old != size) + if (old != size) { arr->resize(size); + } if (old < size) { for (auto i = old; i < size; i++) { (*arr)[i] = arena.alloc<Value>(); @@ -439,8 +444,9 @@ struct Value { Ref back() { assert(isArray()); - if (arr->size() == 0) + if (arr->size() == 0) { return nullptr; + } return arr->back(); } @@ -452,8 +458,9 @@ struct Value { int indexOf(Ref other) { assert(isArray()); for (size_t i = 0; i < arr->size(); i++) { - if (other == (*arr)[i]) + if (other == (*arr)[i]) { return i; + } } return -1; } @@ -474,8 +481,9 @@ struct Value { ret->setArray(); for (size_t i = 0; i < arr->size(); i++) { Ref curr = (*arr)[i]; - if (func(curr)) + if (func(curr)) { ret->push_back(curr); + } } return ret; } @@ -586,8 +594,9 @@ struct JSPrinter { void emit(char c) { maybeSpace(c); - if (!pretty && c == '}' && buffer[used - 1] == ';') + if (!pretty && c == '}' && buffer[used - 1] == ';') { used--; // optimize ;} into }, the ; is not separating anything + } ensure(1); buffer[used++] = c; } @@ -601,30 +610,35 @@ struct JSPrinter { } void newline() { - if (!pretty) + if (!pretty) { return; + } emit('\n'); - for (int i = 0; i < indent; i++) + for (int i = 0; i < indent; i++) { emit(' '); + } } void space() { - if (pretty) + if (pretty) { emit(' '); + } } void safeSpace() { - if (pretty) + if (pretty) { emit(' '); - else + } else { possibleSpace = true; + } } void maybeSpace(char s) { if (possibleSpace) { possibleSpace = false; - if (isIdentPart(s)) + if (isIdentPart(s)) { emit(' '); + } } } @@ -635,15 +649,18 @@ struct JSPrinter { bool isDefun(Ref node) { return node->isArray() && node[0] == DEFUN; } bool endsInBlock(Ref node) { - if (node->isArray() && node[0] == BLOCK) + if (node->isArray() && node[0] == BLOCK) { return true; + } // Check for a label on a block - if (node->isArray() && node[0] == LABEL && endsInBlock(node[2])) + if (node->isArray() && node[0] == LABEL && endsInBlock(node[2])) { return true; + } // Check for an if if (node->isArray() && node[0] == IF && - endsInBlock(ifHasElse(node) ? node[3] : node[2])) + endsInBlock(ifHasElse(node) ? node[3] : node[2])) { return true; + } return false; } @@ -670,119 +687,133 @@ struct JSPrinter { IString type = node[0]->getIString(); switch (type.str[0]) { case 'a': { - if (type == ARRAY) + if (type == ARRAY) { printArray(node); - else + } else { abort(); + } break; } case 'b': { - if (type == BINARY) + if (type == BINARY) { printBinary(node); - else if (type == BLOCK) + } else if (type == BLOCK) { printBlock(node); - else if (type == BREAK) + } else if (type == BREAK) { printBreak(node); - else + } else { abort(); + } break; } case 'c': { - if (type == CALL) + if (type == CALL) { printCall(node); - else if (type == CONDITIONAL) + } else if (type == CONDITIONAL) { printConditional(node); - else if (type == CONTINUE) + } else if (type == CONTINUE) { printContinue(node); - else + } else { abort(); + } break; } case 'd': { - if (type == DEFUN) + if (type == DEFUN) { printDefun(node); - else if (type == DO) + } else if (type == DO) { printDo(node); - else if (type == DOT) + } else if (type == DOT) { printDot(node); - else + } else { abort(); + } break; } case 'i': { - if (type == IF) + if (type == IF) { printIf(node); - else + } else { abort(); + } break; } case 'l': { - if (type == LABEL) + if (type == LABEL) { printLabel(node); - else + } else { abort(); + } break; } case 'n': { - if (type == NEW) + if (type == NEW) { printNew(node); - else + } else { abort(); + } break; } case 'o': { - if (type == OBJECT) + if (type == OBJECT) { printObject(node); + } break; } case 'r': { - if (type == RETURN) + if (type == RETURN) { printReturn(node); - else + } else { abort(); + } break; } case 's': { - if (type == SUB) + if (type == SUB) { printSub(node); - else if (type == SEQ) + } else if (type == SEQ) { printSeq(node); - else if (type == SWITCH) + } else if (type == SWITCH) { printSwitch(node); - else if (type == STRING) + } else if (type == STRING) { printString(node); - else + } else { abort(); + } break; } case 't': { - if (type == TOPLEVEL) + if (type == TOPLEVEL) { printToplevel(node); - else if (type == TRY) + } else if (type == TRY) { printTry(node); - else + } else { abort(); + } break; } case 'u': { - if (type == UNARY_PREFIX) + if (type == UNARY_PREFIX) { printUnaryPrefix(node); - else + } else { abort(); + } break; } case 'v': { - if (type == VAR) + if (type == VAR) { printVar(node); - else + } else { abort(); + } break; } case 'w': { - if (type == WHILE) + if (type == WHILE) { printWhile(node); - else + } else { abort(); + } break; } default: { @@ -796,8 +827,9 @@ struct JSPrinter { void print(Ref node, const char* otherwise) { auto last = used; print(node); - if (used == last) + if (used == last) { emit(otherwise); + } } void printStats(Ref stats) { @@ -805,10 +837,11 @@ struct JSPrinter { for (size_t i = 0; i < stats->size(); i++) { Ref curr = stats[i]; if (!isNothing(curr)) { - if (first) + if (first) { first = false; - else + } else { newline(); + } print(curr); if (!isDefun(curr) && !endsInBlock(curr) && !isIf(curr)) { emit(';'); @@ -843,8 +876,9 @@ struct JSPrinter { emit('('); Ref args = node[2]; for (size_t i = 0; i < args->size(); i++) { - if (i > 0) + if (i > 0) { (pretty ? emit(", ") : emit(',')); + } emit(args[i]->getCString()); } emit(')'); @@ -906,8 +940,9 @@ struct JSPrinter { } } bool neg = d < 0; - if (neg) + if (neg) { d = -d; + } // try to emit the fewest necessary characters bool integer = fmod(d, 1) == 0; #define BUFFERSIZE 1000 @@ -940,8 +975,9 @@ struct JSPrinter { sscanf(buffer, "%lf", &temp); // errv("%.18f, %.18e => %s => %.18f, %.18e (%d), ", d, d, // buffer, temp, temp, temp == d); - if (temp == d) + if (temp == d) { break; + } } } else { // integer @@ -973,8 +1009,9 @@ struct JSPrinter { if (dot) { // remove trailing zeros char* end = dot + 1; - while (*end >= '0' && *end <= '9') + while (*end >= '0' && *end <= '9') { end++; + } end--; while (*end == '0') { char* copy = end; @@ -999,8 +1036,9 @@ struct JSPrinter { char* test = end; // remove zeros, and also doubles can use at most 24 digits, we can // truncate any extras even if not zero - while ((*test == '0' || test - buffer > 24) && test > buffer) + while ((*test == '0' || test - buffer > 24) && test > buffer) { test--; + } int num = end - test; if (num >= 3) { test++; @@ -1092,10 +1130,12 @@ struct JSPrinter { int parentPrecedence = getPrecedence(parent, true); int childPrecedence = getPrecedence(child, false); - if (childPrecedence > parentPrecedence) + if (childPrecedence > parentPrecedence) { return true; // child is definitely a danger - if (childPrecedence < parentPrecedence) + } + if (childPrecedence < parentPrecedence) { return false; // definitely cool + } // equal precedence, so associativity (rtl/ltr) is what matters // (except for some exceptions, where multiple operators can combine into // confusion) @@ -1106,24 +1146,29 @@ struct JSPrinter { return true; } } - if (childPosition == 0) + if (childPosition == 0) { return true; // child could be anywhere, so always paren - if (childPrecedence < 0) + } + if (childPrecedence < 0) { return false; // both precedences are safe + } // check if child is on the dangerous side - if (OperatorClass::getRtl(parentPrecedence)) + if (OperatorClass::getRtl(parentPrecedence)) { return childPosition < 0; - else + } else { return childPosition > 0; + } } void printChild(Ref child, Ref parent, int childPosition = 0) { bool parens = needParens(parent, child, childPosition); - if (parens) + if (parens) { emit('('); + } print(child); - if (parens) + if (parens) { emit(')'); + } } void printBinary(Ref node) { @@ -1145,12 +1190,15 @@ struct JSPrinter { ensure(1); // we temporarily append a 0 char* curr = buffer + last; // ensure might invalidate buffer[used] = 0; - if (strstr(curr, "infinity")) + if (strstr(curr, "infinity")) { return; - if (strstr(curr, "nan")) + } + if (strstr(curr, "nan")) { return; - if (strchr(curr, '.')) + } + if (strchr(curr, '.')) { return; // already a decimal point, all good + } char* e = strchr(curr, 'e'); if (!e) { emit(".0"); @@ -1193,8 +1241,9 @@ struct JSPrinter { emit('('); Ref args = node[2]; for (size_t i = 0; i < args->size(); i++) { - if (i > 0) + if (i > 0) { (pretty ? emit(", ") : emit(',')); + } printChild(args[i], node, 0); } emit(')'); @@ -1238,10 +1287,11 @@ struct JSPrinter { auto curr = used; printStats(c[1]); indent--; - if (curr != used) + if (curr != used) { newline(); - else + } else { used--; // avoid the extra indentation we added tentatively + } } else { newline(); } @@ -1269,8 +1319,9 @@ struct JSPrinter { emit("var "); Ref args = node[1]; for (size_t i = 0; i < args->size(); i++) { - if (i > 0) + if (i > 0) { (pretty ? emit(", ") : emit(',')); + } emit(args[i][0]->getCString()); if (args[i]->size() > 1) { space(); @@ -1377,8 +1428,9 @@ struct JSPrinter { emit('['); Ref args = node[1]; for (size_t i = 0; i < args->size(); i++) { - if (i > 0) + if (i > 0) { (pretty ? emit(", ") : emit(',')); + } print(args[i]); } emit(']'); @@ -1413,11 +1465,13 @@ struct JSPrinter { } check++; } - if (needQuote) + if (needQuote) { emit('"'); + } emit(str); - if (needQuote) + if (needQuote) { emit('"'); + } emit(":"); space(); print(args[i][1]); @@ -1467,8 +1521,9 @@ public: target[1]->setArray(block[1]->getArray()); } else if (target[0] == DEFUN) { target[3]->setArray(block[1]->getArray()); - } else + } else { abort(); + } } static void appendToBlock(Ref block, Ref element) { @@ -1583,8 +1638,9 @@ public: static void appendToVar(Ref var, IString name, Ref value) { assert(var[0] == VAR); Ref array = &makeRawArray(1)->push_back(makeRawString(name)); - if (!!value) + if (!!value) { array->push_back(value); + } var[1]->push_back(array); } diff --git a/src/ir/ExpressionAnalyzer.cpp b/src/ir/ExpressionAnalyzer.cpp index aaab9050c..de37cd08b 100644 --- a/src/ir/ExpressionAnalyzer.cpp +++ b/src/ir/ExpressionAnalyzer.cpp @@ -35,22 +35,26 @@ bool ExpressionAnalyzer::isResultUsed(ExpressionStack& stack, Function* func) { if (curr->is<Block>()) { auto* block = curr->cast<Block>(); for (size_t j = 0; j < block->list.size() - 1; j++) { - if (block->list[j] == above) + if (block->list[j] == above) { return false; + } } assert(block->list.back() == above); // continue down } else if (curr->is<If>()) { auto* iff = curr->cast<If>(); - if (above == iff->condition) + if (above == iff->condition) { return true; - if (!iff->ifFalse) + } + if (!iff->ifFalse) { return false; + } assert(above == iff->ifTrue || above == iff->ifFalse); // continue down } else { - if (curr->is<Drop>()) + if (curr->is<Drop>()) { return false; + } return true; // all other node types use the result } } @@ -66,23 +70,27 @@ bool ExpressionAnalyzer::isResultDropped(ExpressionStack& stack) { if (curr->is<Block>()) { auto* block = curr->cast<Block>(); for (size_t j = 0; j < block->list.size() - 1; j++) { - if (block->list[j] == above) + if (block->list[j] == above) { return false; + } } assert(block->list.back() == above); // continue down } else if (curr->is<If>()) { auto* iff = curr->cast<If>(); - if (above == iff->condition) + if (above == iff->condition) { return false; - if (!iff->ifFalse) + } + if (!iff->ifFalse) { return false; + } assert(above == iff->ifTrue || above == iff->ifFalse); // continue down } else { - if (curr->is<Drop>()) + if (curr->is<Drop>()) { return true; // dropped - return false; // all other node types use the result + } + return false; // all other node types use the result } } return false; @@ -238,8 +246,9 @@ bool ExpressionAnalyzer::flexibleEqual(Expression* left, // Comparison is by value, except for names, which must match. bool operator==(const Immediates& other) { - if (scopeNames.size() != other.scopeNames.size()) + if (scopeNames.size() != other.scopeNames.size()) { return false; + } for (Index i = 0; i < scopeNames.size(); i++) { auto leftName = scopeNames[i]; auto rightName = other.scopeNames[i]; @@ -254,18 +263,24 @@ bool ExpressionAnalyzer::flexibleEqual(Expression* left, return false; } } - if (nonScopeNames != other.nonScopeNames) + if (nonScopeNames != other.nonScopeNames) { return false; - if (ints != other.ints) + } + if (ints != other.ints) { return false; - if (literals != other.literals) + } + if (literals != other.literals) { return false; - if (types != other.types) + } + if (types != other.types) { return false; - if (indexes != other.indexes) + } + if (indexes != other.indexes) { return false; - if (addresses != other.addresses) + } + if (addresses != other.addresses) { return false; + } return true; } @@ -283,8 +298,9 @@ bool ExpressionAnalyzer::flexibleEqual(Expression* left, }; bool noteNames(Name left, Name right) { - if (left.is() != right.is()) + if (left.is() != right.is()) { return false; + } if (left.is()) { assert(rightNames.find(left) == rightNames.end()); rightNames[left] = right; @@ -306,28 +322,35 @@ bool ExpressionAnalyzer::flexibleEqual(Expression* left, leftStack.pop_back(); right = rightStack.back(); rightStack.pop_back(); - if (!left != !right) + if (!left != !right) { return false; - if (!left) + } + if (!left) { continue; - if (comparer(left, right)) + } + if (comparer(left, right)) { continue; // comparison hook, before all the rest + } // continue with normal structural comparison - if (left->_id != right->_id) + if (left->_id != right->_id) { return false; + } // Blocks and loops introduce scoping. if (auto* block = left->dynCast<Block>()) { - if (!noteNames(block->name, right->cast<Block>()->name)) + if (!noteNames(block->name, right->cast<Block>()->name)) { return false; + } } else if (auto* loop = left->dynCast<Loop>()) { - if (!noteNames(loop->name, right->cast<Loop>()->name)) + if (!noteNames(loop->name, right->cast<Loop>()->name)) { return false; + } } else { // For all other nodes, compare their immediate values visitImmediates(left, leftImmediates); visitImmediates(right, rightImmediates); - if (leftImmediates != rightImmediates) + if (leftImmediates != rightImmediates) { return false; + } leftImmediates.clear(); rightImmediates.clear(); } @@ -343,11 +366,13 @@ bool ExpressionAnalyzer::flexibleEqual(Expression* left, } // The number of child nodes must match (e.g. return has an optional // one). - if (counter != 0) + if (counter != 0) { return false; + } } - if (leftStack.size() > 0 || rightStack.size() > 0) + if (leftStack.size() > 0 || rightStack.size() > 0) { return false; + } return true; } }; @@ -377,8 +402,9 @@ HashType ExpressionAnalyzer::hash(Expression* curr) { while (stack.size() > 0) { curr = stack.back(); stack.pop_back(); - if (!curr) + if (!curr) { continue; + } hash(curr->_id); // we often don't need to hash the type, as it is tied to other values // we are hashing anyhow, but there are exceptions: for example, a diff --git a/src/ir/ExpressionManipulator.cpp b/src/ir/ExpressionManipulator.cpp index 6d35ef97f..fcdfdf152 100644 --- a/src/ir/ExpressionManipulator.cpp +++ b/src/ir/ExpressionManipulator.cpp @@ -34,11 +34,13 @@ flexibleCopy(Expression* original, Module& wasm, CustomCopier custom) { : wasm(wasm), custom(custom), builder(wasm) {} Expression* copy(Expression* curr) { - if (!curr) + if (!curr) { return nullptr; + } auto* ret = custom(curr); - if (ret) + if (ret) { return ret; + } return Visitor<Copier, Expression*>::visit(curr); } diff --git a/src/ir/LocalGraph.cpp b/src/ir/LocalGraph.cpp index 1a2ccc0a2..a66009ec2 100644 --- a/src/ir/LocalGraph.cpp +++ b/src/ir/LocalGraph.cpp @@ -58,8 +58,9 @@ struct Flower : public CFGWalker<Flower, Visitor<Flower>, Info> { static void doVisitGetLocal(Flower* self, Expression** currp) { auto* curr = (*currp)->cast<GetLocal>(); // if in unreachable code, skip - if (!self->currBasicBlock) + if (!self->currBasicBlock) { return; + } self->currBasicBlock->contents.actions.emplace_back(curr); self->locations[curr] = currp; } @@ -67,8 +68,9 @@ struct Flower : public CFGWalker<Flower, Visitor<Flower>, Info> { static void doVisitSetLocal(Flower* self, Expression** currp) { auto* curr = (*currp)->cast<SetLocal>(); // if in unreachable code, skip - if (!self->currBasicBlock) + if (!self->currBasicBlock) { return; + } self->currBasicBlock->contents.actions.emplace_back(curr); self->currBasicBlock->contents.lastSets[curr->index] = curr; self->locations[curr] = currp; @@ -119,8 +121,9 @@ struct Flower : public CFGWalker<Flower, Visitor<Flower>, Info> { auto& block = basicBlocks[i]; auto& flowBlock = flowBlocks[i]; // Get the equivalent block to entry in the flow list - if (block.get() == entry) + if (block.get() == entry) { entryFlowBlock = &flowBlock; + } flowBlock.lastTraversedIteration = NULL_ITERATION; flowBlock.actions.swap(block->contents.actions); // Map in block to flow blocks @@ -171,8 +174,9 @@ struct Flower : public CFGWalker<Flower, Visitor<Flower>, Info> { // can do that for all gets as a whole, they will get the same results. for (Index index = 0; index < numLocals; index++) { auto& gets = allGets[index]; - if (gets.empty()) + if (gets.empty()) { continue; + } work.push_back(&block); // Note that we may need to revisit the later parts of this initial // block, if we are in a loop, so don't mark it as seen. diff --git a/src/ir/ReFinalize.cpp b/src/ir/ReFinalize.cpp index 2bf68970d..ca058e2be 100644 --- a/src/ir/ReFinalize.cpp +++ b/src/ir/ReFinalize.cpp @@ -91,8 +91,9 @@ void ReFinalize::visitBlock(Block* curr) { return; } } - if (curr->type == unreachable) + if (curr->type == unreachable) { return; + } // type is none, but we might be unreachable if (curr->type == none) { for (auto* child : curr->list) { diff --git a/src/ir/bits.h b/src/ir/bits.h index a2b8fcde4..faae4c723 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -27,8 +27,9 @@ struct Bits { // get a mask to keep only the low # of bits static int32_t lowBitMask(int32_t bits) { uint32_t ret = -1; - if (bits >= 32) + if (bits >= 32) { return ret; + } return ret >> (32 - bits); } @@ -36,14 +37,17 @@ struct Bits { // bit, and all zeros from there. returns the number of masked bits, or 0 if // this is not such a mask static uint32_t getMaskedBits(uint32_t mask) { - if (mask == uint32_t(-1)) + if (mask == uint32_t(-1)) { return 32; // all the bits - if (mask == 0) + } + if (mask == 0) { return 0; // trivially not a mask + } // otherwise, see if adding one turns this into a 1-bit thing, 00011111 + 1 // => 00100000 - if (PopCount(mask + 1) != 1) + if (PopCount(mask + 1) != 1) { return 0; + } // this is indeed a mask return 32 - CountLeadingZeroes(mask); } diff --git a/src/ir/branch-utils.h b/src/ir/branch-utils.h index f62941e15..ce7d7b0f6 100644 --- a/src/ir/branch-utils.h +++ b/src/ir/branch-utils.h @@ -155,47 +155,57 @@ struct BranchSeeker : public PostWalker<BranchSeeker> { void noteFound(Expression* value) { found++; - if (found == 1) + if (found == 1) { valueType = unreachable; - if (!value) + } + if (!value) { valueType = none; - else if (value->type != unreachable) + } else if (value->type != unreachable) { valueType = value->type; + } } void visitBreak(Break* curr) { if (!named) { // ignore an unreachable break - if (curr->condition && curr->condition->type == unreachable) + if (curr->condition && curr->condition->type == unreachable) { return; - if (curr->value && curr->value->type == unreachable) + } + if (curr->value && curr->value->type == unreachable) { return; + } } // check the break - if (curr->name == target) + if (curr->name == target) { noteFound(curr->value); + } } void visitSwitch(Switch* curr) { if (!named) { // ignore an unreachable switch - if (curr->condition->type == unreachable) + if (curr->condition->type == unreachable) { return; - if (curr->value && curr->value->type == unreachable) + } + if (curr->value && curr->value->type == unreachable) { return; + } } // check the switch for (auto name : curr->targets) { - if (name == target) + if (name == target) { noteFound(curr->value); + } } - if (curr->default_ == target) + if (curr->default_ == target) { noteFound(curr->value); + } } static bool hasReachable(Expression* tree, Name target) { - if (!target.is()) + if (!target.is()) { return false; + } BranchSeeker seeker(target); seeker.named = false; seeker.walk(tree); @@ -203,8 +213,9 @@ struct BranchSeeker : public PostWalker<BranchSeeker> { } static Index countReachable(Expression* tree, Name target) { - if (!target.is()) + if (!target.is()) { return 0; + } BranchSeeker seeker(target); seeker.named = false; seeker.walk(tree); @@ -212,16 +223,18 @@ struct BranchSeeker : public PostWalker<BranchSeeker> { } static bool hasNamed(Expression* tree, Name target) { - if (!target.is()) + if (!target.is()) { return false; + } BranchSeeker seeker(target); seeker.walk(tree); return seeker.found > 0; } static Index countNamed(Expression* tree, Name target) { - if (!target.is()) + if (!target.is()) { return 0; + } BranchSeeker seeker(target); seeker.walk(tree); return seeker.found; diff --git a/src/ir/cost.h b/src/ir/cost.h index 95c2178d9..5e09ee90e 100644 --- a/src/ir/cost.h +++ b/src/ir/cost.h @@ -33,8 +33,9 @@ struct CostAnalyzer : public Visitor<CostAnalyzer, Index> { Index visitBlock(Block* curr) { Index ret = 0; - for (auto* child : curr->list) + for (auto* child : curr->list) { ret += visit(child); + } return ret; } Index visitIf(If* curr) { @@ -52,14 +53,16 @@ struct CostAnalyzer : public Visitor<CostAnalyzer, Index> { // XXX this does not take into account if the call is to an import, which // may be costlier in general Index ret = 4; - for (auto* child : curr->operands) + for (auto* child : curr->operands) { ret += visit(child); + } return ret; } Index visitCallIndirect(CallIndirect* curr) { Index ret = 6 + visit(curr->target); - for (auto* child : curr->operands) + for (auto* child : curr->operands) { ret += visit(child); + } return ret; } Index visitGetLocal(GetLocal* curr) { return 0; } diff --git a/src/ir/effects.h b/src/ir/effects.h index 9a3f29d8a..bbcce07de 100644 --- a/src/ir/effects.h +++ b/src/ir/effects.h @@ -30,8 +30,9 @@ struct EffectAnalyzer EffectAnalyzer(PassOptions& passOptions, Expression* ast = nullptr) { ignoreImplicitTraps = passOptions.ignoreImplicitTraps; debugInfo = passOptions.debugInfo; - if (ast) + if (ast) { analyze(ast); + } } bool ignoreImplicitTraps; @@ -41,8 +42,9 @@ struct EffectAnalyzer breakNames.clear(); walk(ast); // if we are left with breaks, they are external - if (breakNames.size() > 0) + if (breakNames.size() > 0) { branches = true; + } } // Core effect tracking @@ -115,8 +117,9 @@ struct EffectAnalyzer } } for (auto local : localsRead) { - if (other.localsWritten.count(local)) + if (other.localsWritten.count(local)) { return true; + } } if ((accessesGlobal() && other.calls) || (other.accessesGlobal() && calls)) { @@ -129,8 +132,9 @@ struct EffectAnalyzer } } for (auto global : globalsRead) { - if (other.globalsWritten.count(global)) + if (other.globalsWritten.count(global)) { return true; + } } // we are ok to reorder implicit traps, but not conditionalize them if ((implicitTrap && other.branches) || (other.implicitTrap && branches)) { @@ -151,14 +155,18 @@ struct EffectAnalyzer writesMemory = writesMemory || other.writesMemory; implicitTrap = implicitTrap || other.implicitTrap; isAtomic = isAtomic || other.isAtomic; - for (auto i : other.localsRead) + for (auto i : other.localsRead) { localsRead.insert(i); - for (auto i : other.localsWritten) + } + for (auto i : other.localsWritten) { localsWritten.insert(i); - for (auto i : other.globalsRead) + } + for (auto i : other.globalsRead) { globalsRead.insert(i); - for (auto i : other.globalsWritten) + } + for (auto i : other.globalsWritten) { globalsWritten.insert(i); + } } // the checks above happen after the node's children were processed, in the @@ -183,13 +191,15 @@ struct EffectAnalyzer std::set<Name> breakNames; void visitBlock(Block* curr) { - if (curr->name.is()) + if (curr->name.is()) { breakNames.erase(curr->name); // these were internal breaks + } } void visitIf(If* curr) {} void visitLoop(Loop* curr) { - if (curr->name.is()) + if (curr->name.is()) { breakNames.erase(curr->name); // these were internal breaks + } // if the loop is unreachable, then there is branching control flow: // (1) if the body is unreachable because of a (return), uncaught (br) // etc., then we already noted branching, so it is ok to mark it again @@ -228,28 +238,32 @@ struct EffectAnalyzer void visitLoad(Load* curr) { readsMemory = true; isAtomic |= curr->isAtomic; - if (!ignoreImplicitTraps) + if (!ignoreImplicitTraps) { implicitTrap = true; + } } void visitStore(Store* curr) { writesMemory = true; isAtomic |= curr->isAtomic; - if (!ignoreImplicitTraps) + if (!ignoreImplicitTraps) { implicitTrap = true; + } } void visitAtomicRMW(AtomicRMW* curr) { readsMemory = true; writesMemory = true; isAtomic = true; - if (!ignoreImplicitTraps) + if (!ignoreImplicitTraps) { implicitTrap = true; + } } void visitAtomicCmpxchg(AtomicCmpxchg* curr) { readsMemory = true; writesMemory = true; isAtomic = true; - if (!ignoreImplicitTraps) + if (!ignoreImplicitTraps) { implicitTrap = true; + } } void visitAtomicWait(AtomicWait* curr) { readsMemory = true; @@ -258,8 +272,9 @@ struct EffectAnalyzer // write. writesMemory = true; isAtomic = true; - if (!ignoreImplicitTraps) + if (!ignoreImplicitTraps) { implicitTrap = true; + } } void visitAtomicNotify(AtomicNotify* curr) { // AtomicNotify doesn't strictly write memory, but it does modify the @@ -268,8 +283,9 @@ struct EffectAnalyzer readsMemory = true; writesMemory = true; isAtomic = true; - if (!ignoreImplicitTraps) + if (!ignoreImplicitTraps) { implicitTrap = true; + } }; void visitSIMDExtract(SIMDExtract* curr) {} void visitSIMDReplace(SIMDReplace* curr) {} @@ -278,25 +294,29 @@ struct EffectAnalyzer void visitSIMDShift(SIMDShift* curr) {} void visitMemoryInit(MemoryInit* curr) { writesMemory = true; - if (!ignoreImplicitTraps) + if (!ignoreImplicitTraps) { implicitTrap = true; + } } void visitDataDrop(DataDrop* curr) { // prevent reordering with memory.init readsMemory = true; - if (!ignoreImplicitTraps) + if (!ignoreImplicitTraps) { implicitTrap = true; + } } void visitMemoryCopy(MemoryCopy* curr) { readsMemory = true; writesMemory = true; - if (!ignoreImplicitTraps) + if (!ignoreImplicitTraps) { implicitTrap = true; + } } void visitMemoryFill(MemoryFill* curr) { writesMemory = true; - if (!ignoreImplicitTraps) + if (!ignoreImplicitTraps) { implicitTrap = true; + } } void visitConst(Const* curr) {} void visitUnary(Unary* curr) { diff --git a/src/ir/equivalent_sets.h b/src/ir/equivalent_sets.h index fc4b1db3d..657ff9894 100644 --- a/src/ir/equivalent_sets.h +++ b/src/ir/equivalent_sets.h @@ -67,8 +67,9 @@ struct EquivalentSets { // Checks whether two indexes contain the same data. bool check(Index a, Index b) { - if (a == b) + if (a == b) { return true; + } if (auto* set = getEquivalents(a)) { if (set->find(b) != set->end()) { return true; diff --git a/src/ir/function-utils.h b/src/ir/function-utils.h index 446bcc8bb..61af153a0 100644 --- a/src/ir/function-utils.h +++ b/src/ir/function-utils.h @@ -28,18 +28,23 @@ namespace FunctionUtils { // everything but their name (which can't be the same, in the same // module!) - same params, vars, body, result, etc. inline bool equal(Function* left, Function* right) { - if (left->getNumParams() != right->getNumParams()) + if (left->getNumParams() != right->getNumParams()) { return false; - if (left->getNumVars() != right->getNumVars()) + } + if (left->getNumVars() != right->getNumVars()) { return false; + } for (Index i = 0; i < left->getNumLocals(); i++) { - if (left->getLocalType(i) != right->getLocalType(i)) + if (left->getLocalType(i) != right->getLocalType(i)) { return false; + } } - if (left->result != right->result) + if (left->result != right->result) { return false; - if (left->type != right->type) + } + if (left->type != right->type) { return false; + } if (!left->imported() && !right->imported()) { return ExpressionAnalyzer::equal(left->body, right->body); } diff --git a/src/ir/global-utils.h b/src/ir/global-utils.h index b32605805..113a37f31 100644 --- a/src/ir/global-utils.h +++ b/src/ir/global-utils.h @@ -38,8 +38,9 @@ getGlobalInitializedToImport(Module& wasm, Name module, Name base) { imported = import->name; } }); - if (imported.isNull()) + if (imported.isNull()) { return nullptr; + } // find a global inited to it Global* ret = nullptr; ModuleUtils::iterDefinedGlobals(wasm, [&](Global* defined) { diff --git a/src/ir/hashed.h b/src/ir/hashed.h index 676b82cb4..a3d285cf5 100644 --- a/src/ir/hashed.h +++ b/src/ir/hashed.h @@ -44,8 +44,9 @@ struct ExpressionHasher { struct ExpressionComparer { bool operator()(const HashedExpression a, const HashedExpression b) const { - if (a.hash != b.hash) + if (a.hash != b.hash) { return false; + } return ExpressionAnalyzer::equal(a.expr, b.expr); } }; diff --git a/src/ir/load-utils.h b/src/ir/load-utils.h index 36e94d0af..c7e9bad99 100644 --- a/src/ir/load-utils.h +++ b/src/ir/load-utils.h @@ -28,8 +28,9 @@ namespace LoadUtils { // fill in bits either signed or unsigned wise) inline bool isSignRelevant(Load* load) { auto type = load->type; - if (load->type == unreachable) + if (load->type == unreachable) { return false; + } return !isFloatType(type) && load->bytes < getTypeSize(type); } diff --git a/src/ir/memory-utils.h b/src/ir/memory-utils.h index c1edc8ce9..fd4b865f4 100644 --- a/src/ir/memory-utils.h +++ b/src/ir/memory-utils.h @@ -29,16 +29,18 @@ namespace wasm { namespace MemoryUtils { // flattens memory into a single data segment. returns true if successful inline bool flatten(Memory& memory) { - if (memory.segments.size() == 0) + if (memory.segments.size() == 0) { return true; + } std::vector<char> data; for (auto& segment : memory.segments) { if (segment.isPassive) { return false; } auto* offset = segment.offset->dynCast<Const>(); - if (!offset) + if (!offset) { return false; + } } for (auto& segment : memory.segments) { auto* offset = segment.offset->dynCast<Const>(); @@ -121,10 +123,12 @@ inline bool ensureLimitedSegments(Module& module) { // drop empty segments and pass through dynamic-offset segments for (auto& segment : memory.segments) { - if (isEmpty(segment)) + if (isEmpty(segment)) { continue; - if (isConstantOffset(segment)) + } + if (isConstantOffset(segment)) { continue; + } mergedSegments.push_back(segment); } @@ -135,8 +139,9 @@ inline bool ensureLimitedSegments(Module& module) { }; for (Index i = 0; i < memory.segments.size(); i++) { auto& segment = memory.segments[i]; - if (!isRelevant(segment)) + if (!isRelevant(segment)) { continue; + } if (mergedSegments.size() + 2 < WebLimitations::MaxDataSegments) { mergedSegments.push_back(segment); continue; @@ -146,8 +151,9 @@ inline bool ensureLimitedSegments(Module& module) { auto start = segment.offset->cast<Const>()->value.getInteger(); for (Index j = i + 1; j < memory.segments.size(); j++) { auto& segment = memory.segments[j]; - if (!isRelevant(segment)) + if (!isRelevant(segment)) { continue; + } auto offset = segment.offset->cast<Const>()->value.getInteger(); start = std::min(start, offset); } @@ -159,8 +165,9 @@ inline bool ensureLimitedSegments(Module& module) { Memory::Segment combined(c); for (Index j = i; j < memory.segments.size(); j++) { auto& segment = memory.segments[j]; - if (!isRelevant(segment)) + if (!isRelevant(segment)) { continue; + } auto offset = segment.offset->cast<Const>()->value.getInteger(); auto needed = offset + segment.data.size() - start; if (combined.data.size() < needed) { diff --git a/src/ir/type-updating.h b/src/ir/type-updating.h index e387483ee..ef9fe78e9 100644 --- a/src/ir/type-updating.h +++ b/src/ir/type-updating.h @@ -194,8 +194,9 @@ struct TypeUpdater // alters the type of a node to a new type. // this propagates the type change through all the parents. void changeTypeTo(Expression* curr, Type newType) { - if (curr->type == newType) + if (curr->type == newType) { return; // nothing to do + } curr->type = newType; propagateTypesUp(curr); } @@ -208,13 +209,15 @@ struct TypeUpdater // the one thing we need to do here is propagate unreachability, // no other change is possible void propagateTypesUp(Expression* curr) { - if (curr->type != unreachable) + if (curr->type != unreachable) { return; + } while (1) { auto* child = curr; curr = parents[child]; - if (!curr) + if (!curr) { return; + } // get ready to apply unreachability to this node if (curr->type == unreachable) { return; // already unreachable, stop here diff --git a/src/ir/utils.h b/src/ir/utils.h index 9be8947a1..4e941b8d0 100644 --- a/src/ir/utils.h +++ b/src/ir/utils.h @@ -248,8 +248,9 @@ struct AutoDrop : public WalkerPass<ExpressionStackWalker<AutoDrop>> { void reFinalize() { ReFinalizeNode::updateStack(expressionStack); } void visitBlock(Block* curr) { - if (curr->list.size() == 0) + if (curr->list.size() == 0) { return; + } for (Index i = 0; i < curr->list.size() - 1; i++) { auto* child = curr->list[i]; if (isConcreteType(child->type)) { @@ -264,11 +265,13 @@ struct AutoDrop : public WalkerPass<ExpressionStackWalker<AutoDrop>> { void visitIf(If* curr) { bool acted = false; - if (maybeDrop(curr->ifTrue)) + if (maybeDrop(curr->ifTrue)) { acted = true; + } if (curr->ifFalse) { - if (maybeDrop(curr->ifFalse)) + if (maybeDrop(curr->ifFalse)) { acted = true; + } } if (acted) { reFinalize(); diff --git a/src/literal.h b/src/literal.h index ff50b2e61..9ffa79032 100644 --- a/src/literal.h +++ b/src/literal.h @@ -412,10 +412,12 @@ template<> struct hash<wasm::Literal> { }; template<> struct less<wasm::Literal> { bool operator()(const wasm::Literal& a, const wasm::Literal& b) const { - if (a.type < b.type) + if (a.type < b.type) { return true; - if (a.type > b.type) + } + if (a.type > b.type) { return false; + } switch (a.type) { case wasm::Type::i32: return a.geti32() < b.geti32(); diff --git a/src/mixed_arena.h b/src/mixed_arena.h index 36bf22a5e..079ce9028 100644 --- a/src/mixed_arena.h +++ b/src/mixed_arena.h @@ -113,8 +113,9 @@ struct MixedArena { // otherwise, the cmpxchg updated seen, and we continue to loop curr = seen; } - if (allocated) + if (allocated) { delete allocated; + } return curr->allocSpace(size, align); } // First, move the current index in the last chunk to an aligned position. @@ -125,8 +126,9 @@ struct MixedArena { assert(size <= numChunks * CHUNK_SIZE); auto* allocation = wasm::aligned_malloc(MAX_ALIGN, numChunks * CHUNK_SIZE); - if (!allocation) + if (!allocation) { abort(); + } chunks.push_back(allocation); index = 0; } @@ -155,8 +157,9 @@ struct MixedArena { ~MixedArena() { clear(); - if (next.load()) + if (next.load()) { delete next.load(); + } } }; diff --git a/src/parsing.h b/src/parsing.h index 8432b41f2..9b2cb490b 100644 --- a/src/parsing.h +++ b/src/parsing.h @@ -143,16 +143,19 @@ parseConst(cashew::IString s, Type type, MixedArena& allocator) { if (modifier) { std::istringstream istr(modifier); istr >> std::hex >> pattern; - if (istr.fail()) + if (istr.fail()) { throw ParseException("invalid f32 format"); + } pattern |= 0x7f800000U; } else { pattern = 0x7fc00000U; } - if (negative) + if (negative) { pattern |= 0x80000000U; - if (!std::isnan(bit_cast<float>(pattern))) + } + if (!std::isnan(bit_cast<float>(pattern))) { pattern |= 1U; + } ret->value = Literal(pattern).castToF32(); break; } @@ -161,16 +164,19 @@ parseConst(cashew::IString s, Type type, MixedArena& allocator) { if (modifier) { std::istringstream istr(modifier); istr >> std::hex >> pattern; - if (istr.fail()) + if (istr.fail()) { throw ParseException("invalid f64 format"); + } pattern |= 0x7ff0000000000000ULL; } else { pattern = 0x7ff8000000000000UL; } - if (negative) + if (negative) { pattern |= 0x8000000000000000ULL; - if (!std::isnan(bit_cast<double>(pattern))) + } + if (!std::isnan(bit_cast<double>(pattern))) { pattern |= 1ULL; + } ret->value = Literal(pattern).castToF64(); break; } @@ -200,20 +206,23 @@ parseConst(cashew::IString s, Type type, MixedArena& allocator) { if ((str[0] == '0' && str[1] == 'x') || (str[0] == '-' && str[1] == '0' && str[2] == 'x')) { bool negative = str[0] == '-'; - if (negative) + if (negative) { str++; + } std::istringstream istr(str); uint32_t temp; istr >> std::hex >> temp; - if (istr.fail()) + if (istr.fail()) { throw ParseException("invalid i32 format"); + } ret->value = Literal(negative ? -temp : temp); } else { std::istringstream istr(str[0] == '-' ? str + 1 : str); uint32_t temp; istr >> temp; - if (istr.fail()) + if (istr.fail()) { throw ParseException("invalid i32 format"); + } ret->value = Literal(str[0] == '-' ? -temp : temp); } break; @@ -222,20 +231,23 @@ parseConst(cashew::IString s, Type type, MixedArena& allocator) { if ((str[0] == '0' && str[1] == 'x') || (str[0] == '-' && str[1] == '0' && str[2] == 'x')) { bool negative = str[0] == '-'; - if (negative) + if (negative) { str++; + } std::istringstream istr(str); uint64_t temp; istr >> std::hex >> temp; - if (istr.fail()) + if (istr.fail()) { throw ParseException("invalid i64 format"); + } ret->value = Literal(negative ? -temp : temp); } else { std::istringstream istr(str[0] == '-' ? str + 1 : str); uint64_t temp; istr >> temp; - if (istr.fail()) + if (istr.fail()) { throw ParseException("invalid i64 format"); + } ret->value = Literal(str[0] == '-' ? -temp : temp); } break; @@ -275,13 +287,15 @@ struct UniqueNameMapper { Index otherIndex = 0; Name getPrefixedName(Name prefix) { - if (reverseLabelMapping.find(prefix) == reverseLabelMapping.end()) + if (reverseLabelMapping.find(prefix) == reverseLabelMapping.end()) { return prefix; + } // make sure to return a unique name not already on the stack while (1) { Name ret = Name(prefix.str + std::to_string(otherIndex++)); - if (reverseLabelMapping.find(ret) == reverseLabelMapping.end()) + if (reverseLabelMapping.find(ret) == reverseLabelMapping.end()) { return ret; + } } } @@ -331,21 +345,25 @@ struct UniqueNameMapper { static void doPreVisitControlFlow(Walker* self, Expression** currp) { auto* curr = *currp; if (auto* block = curr->dynCast<Block>()) { - if (block->name.is()) + if (block->name.is()) { block->name = self->mapper.pushLabelName(block->name); + } } else if (auto* loop = curr->dynCast<Loop>()) { - if (loop->name.is()) + if (loop->name.is()) { loop->name = self->mapper.pushLabelName(loop->name); + } } } static void doPostVisitControlFlow(Walker* self, Expression** currp) { auto* curr = *currp; if (auto* block = curr->dynCast<Block>()) { - if (block->name.is()) + if (block->name.is()) { self->mapper.popLabelName(block->name); + } } else if (auto* loop = curr->dynCast<Loop>()) { - if (loop->name.is()) + if (loop->name.is()) { self->mapper.popLabelName(loop->name); + } } } diff --git a/src/pass.h b/src/pass.h index 720e5c992..3917c8908 100644 --- a/src/pass.h +++ b/src/pass.h @@ -133,8 +133,9 @@ struct PassRunner { void add(std::string passName) { auto pass = PassRegistry::get()->createPass(passName); - if (!pass) + if (!pass) { Fatal() << "Could not find pass: " << passName << "\n"; + } doAdd(pass); } diff --git a/src/passes/CoalesceLocals.cpp b/src/passes/CoalesceLocals.cpp index a085b61fb..af13419d3 100644 --- a/src/passes/CoalesceLocals.cpp +++ b/src/passes/CoalesceLocals.cpp @@ -70,8 +70,9 @@ struct CoalesceLocals std::vector<bool> interferences; void interfere(Index i, Index j) { - if (i == j) + if (i == j) { return; + } interferences[std::min(i, j) * numLocals + std::max(i, j)] = 1; } @@ -112,10 +113,11 @@ void CoalesceLocals::increaseBackEdgePriorities() { auto& in = loopTop->in; for (Index i = 1; i < in.size(); i++) { auto* arrivingBlock = in[i]; - if (arrivingBlock->out.size() > 1) + if (arrivingBlock->out.size() > 1) { // we just want unconditional branches to the loop top, true phi // fragments continue; + } for (auto& action : arrivingBlock->contents.actions) { if (action.isSet()) { auto* set = (*action.origin)->cast<SetLocal>(); @@ -134,8 +136,9 @@ void CoalesceLocals::calculateInterferences() { interferences.resize(numLocals * numLocals); std::fill(interferences.begin(), interferences.end(), false); for (auto& curr : basicBlocks) { - if (liveBlocks.count(curr.get()) == 0) + if (liveBlocks.count(curr.get()) == 0) { continue; // ignore dead blocks + } // everything coming in might interfere, as it might come from a different // block auto live = curr->contents.end; @@ -306,8 +309,9 @@ std::vector<Index> adjustOrderByPriorities(std::vector<Index>& baseline, } void CoalesceLocals::pickIndices(std::vector<Index>& indices) { - if (numLocals == 0) + if (numLocals == 0) { return; + } if (numLocals == 1) { indices.push_back(0); return; @@ -420,8 +424,9 @@ void CoalesceLocalsWithLearning::pickIndices(std::vector<Index>& indices) { double getFitness() { return fitness; } void dump(std::string text) { std::cout << text + ": ( "; - for (Index i = 0; i < size(); i++) + for (Index i = 0; i < size(); i++) { std::cout << (*this)[i] << " "; + } std::cout << ")\n"; std::cout << "of quality: " << getFitness() << "\n"; } @@ -445,8 +450,9 @@ void CoalesceLocalsWithLearning::pickIndices(std::vector<Index>& indices) { // secondarily, it is nice to not reorder locals unnecessarily double fragment = 1.0 / (2.0 * parent->numLocals); for (Index i = 0; i < parent->numLocals; i++) { - if ((*order)[i] == i) + if ((*order)[i] == i) { fitness += fragment; // boost for each that wasn't moved + } } // removing copies is a secondary concern fitness = (100 * fitness) + removedCopies; @@ -534,8 +540,9 @@ void CoalesceLocalsWithLearning::pickIndices(std::vector<Index>& indices) { while (1) { learner.runGeneration(); auto newBest = learner.getBest()->getFitness(); - if (newBest == oldBest) + if (newBest == oldBest) { break; // unlikely we can improve + } oldBest = newBest; #ifdef CFG_LEARN_DEBUG learner.getBest()->dump("current best"); diff --git a/src/passes/CodeFolding.cpp b/src/passes/CodeFolding.cpp index 0479472d8..d60bc76d1 100644 --- a/src/passes/CodeFolding.cpp +++ b/src/passes/CodeFolding.cpp @@ -179,19 +179,23 @@ struct CodeFolding : public WalkerPass<ControlFlowWalker<CodeFolding>> { } void visitBlock(Block* curr) { - if (curr->list.empty()) + if (curr->list.empty()) { return; - if (!curr->name.is()) + } + if (!curr->name.is()) { return; - if (unoptimizables.count(curr->name) > 0) + } + if (unoptimizables.count(curr->name) > 0) { return; + } // we can't optimize a fallthrough value if (isConcreteType(curr->list.back()->type)) { return; } auto iter = breakTails.find(curr->name); - if (iter == breakTails.end()) + if (iter == breakTails.end()) { return; + } // looks promising auto& tails = iter->second; // see if there is a fallthrough @@ -208,8 +212,9 @@ struct CodeFolding : public WalkerPass<ControlFlowWalker<CodeFolding>> { } void visitIf(If* curr) { - if (!curr->ifFalse) + if (!curr->ifFalse) { return; + } // if both sides are identical, this is easy to fold if (ExpressionAnalyzer::equal(curr->ifTrue, curr->ifFalse)) { Builder builder(*getModule()); @@ -304,14 +309,17 @@ private: // identical in all paths leading to the block exit can be merged. template<typename T> void optimizeExpressionTails(std::vector<Tail>& tails, T* curr) { - if (tails.size() < 2) + if (tails.size() < 2) { return; + } // see if anything is untoward, and we should not do this for (auto& tail : tails) { - if (tail.expr && modifieds.count(tail.expr) > 0) + if (tail.expr && modifieds.count(tail.expr) > 0) { return; - if (modifieds.count(tail.block) > 0) + } + if (modifieds.count(tail.block) > 0) { return; + } // if we were not modified, then we should be valid for processing tail.validate(); } @@ -345,8 +353,9 @@ private: break; } } - if (stop) + if (stop) { break; + } auto* item = getMergeable(tails[0], num); for (auto& tail : tails) { if (!ExpressionAnalyzer::equal(item, getMergeable(tail, num))) { @@ -355,18 +364,21 @@ private: break; } } - if (stop) + if (stop) { break; + } // we may have found another one we can merge - can we move it? - if (!canMove({item}, curr)) + if (!canMove({item}, curr)) { break; + } // we found another one we can merge mergeable.push_back(item); num++; saved += Measurer::measure(item); } - if (saved == 0) + if (saved == 0) { return; + } // we may be able to save enough. if (saved < WORTH_ADDING_BLOCK_TO_REMOVE_THIS_MUCH) { // it's not obvious we can save enough. see if we get rid @@ -463,17 +475,20 @@ private: // deeper merges first. // returns whether we optimized something. bool optimizeTerminatingTails(std::vector<Tail>& tails, Index num = 0) { - if (tails.size() < 2) + if (tails.size() < 2) { return false; + } // remove things that are untoward and cannot be optimized tails.erase( std::remove_if(tails.begin(), tails.end(), [&](Tail& tail) { - if (tail.expr && modifieds.count(tail.expr) > 0) + if (tail.expr && modifieds.count(tail.expr) > 0) { return true; - if (tail.block && modifieds.count(tail.block) > 0) + } + if (tail.block && modifieds.count(tail.block) > 0) { return true; + } // if we were not modified, then we should be valid for // processing tail.validate(); @@ -544,8 +559,9 @@ private: next.erase(std::remove_if(next.begin(), next.end(), [&](Tail& tail) { - if (effectiveSize(tail) < num + 1) + if (effectiveSize(tail) < num + 1) { return true; + } auto* newItem = getItem(tail, num); // ignore tails that break to outside blocks. we // want to move code to the very outermost @@ -578,12 +594,14 @@ private: for (auto& tail : next) { auto* item = getItem(tail, num); auto hash = hashes[item]; - if (seen.count(hash)) + if (seen.count(hash)) { continue; + } seen.insert(hash); auto& items = hashed[hash]; - if (items.size() == 1) + if (items.size() == 1) { continue; + } assert(items.size() > 0); // look for an item that has another match. while (items.size() >= 2) { @@ -632,11 +650,13 @@ private: // we explored deeper (higher num) options, but perhaps there // was nothing there while there is something we can do at this level // but if we are at num == 0, then we found nothing at all - if (num == 0) + if (num == 0) { return false; + } // if not worth it, stop - if (!worthIt(num, tails)) + if (!worthIt(num, tails)) { return false; + } // this is worth doing, do it! auto mergeable = getTailItems(num, tails); // the elements we can merge // since we managed a merge, then it might open up more opportunities later @@ -680,8 +700,9 @@ private: // rules, and now it won't be toplevel in the function, it can // change) auto* toplevel = old->dynCast<Block>(); - if (toplevel) + if (toplevel) { toplevel->finalize(); + } if (old->type != unreachable) { inner->list.push_back(builder.makeReturn(old)); } else { diff --git a/src/passes/CodePushing.cpp b/src/passes/CodePushing.cpp index 342cb5182..88e363541 100644 --- a/src/passes/CodePushing.cpp +++ b/src/passes/CodePushing.cpp @@ -50,8 +50,9 @@ struct LocalAnalyzer : public PostWalker<LocalAnalyzer> { std::fill(sfa.begin() + func->getNumParams(), sfa.end(), true); walk(func->body); for (Index i = 0; i < num; i++) { - if (numSets[i] == 0) + if (numSets[i] == 0) { sfa[i] = false; + } } } @@ -117,8 +118,9 @@ public: private: SetLocal* isPushable(Expression* curr) { auto* set = curr->dynCast<SetLocal>(); - if (!set) + if (!set) { return nullptr; + } auto index = set->index; // to be pushable, this must be SFA and the right # of gets, // but also have no side effects, as it may not execute if pushed. @@ -137,8 +139,9 @@ private: if (auto* drop = curr->dynCast<Drop>()) { curr = drop->value; } - if (curr->is<If>()) + if (curr->is<If>()) { return true; + } if (auto* br = curr->dynCast<Break>()) { return !!br->condition; } @@ -249,8 +252,9 @@ struct CodePushing : public WalkerPass<PostWalker<CodePushing>> { // Pushing code only makes sense if we are size 3 or above: we need // one element to push, an element to push it past, and an element to use // what we pushed. - if (curr->list.size() < 3) + if (curr->list.size() < 3) { return; + } // At this point in the postorder traversal we have gone through all our // children. Therefore any variable whose gets seen so far is equal to the // total gets must have no further users after this block. And therefore diff --git a/src/passes/ConstHoisting.cpp b/src/passes/ConstHoisting.cpp index f67a48645..749a3361f 100644 --- a/src/passes/ConstHoisting.cpp +++ b/src/passes/ConstHoisting.cpp @@ -72,8 +72,9 @@ struct ConstHoisting : public WalkerPass<PostWalker<ConstHoisting>> { private: bool worthHoisting(Literal value, Index num) { - if (num < MIN_USES) + if (num < MIN_USES) { return false; + } // measure the size of the constant Index size = 0; switch (value.type) { diff --git a/src/passes/DataFlowOpts.cpp b/src/passes/DataFlowOpts.cpp index 3391359ef..62d2e5f24 100644 --- a/src/passes/DataFlowOpts.cpp +++ b/src/passes/DataFlowOpts.cpp @@ -81,11 +81,13 @@ struct DataFlowOpts : public WalkerPass<PostWalker<DataFlowOpts>> { } void workOn(DataFlow::Node* node) { - if (node->isConst()) + if (node->isConst()) { return; + } // If there are no uses, there is no point to work. - if (nodeUsers.getNumUses(node) == 0) + if (nodeUsers.getNumUses(node) == 0) { return; + } // Optimize: Look for nodes that we can easily convert into // something simpler. // TODO: we can expressionify and run full normal opts on that, @@ -144,8 +146,9 @@ struct DataFlowOpts : public WalkerPass<PostWalker<DataFlowOpts>> { // Get the optimized thing auto* result = func->body; // It may not be a constant, e.g. 0 / 0 does not optimize to 0 - if (!result->is<Const>()) + if (!result->is<Const>()) { return; + } // All good, copy it. node->expr = Builder(*getModule()).makeConst(result->cast<Const>()->value); assert(node->isConst()); diff --git a/src/passes/DeadArgumentElimination.cpp b/src/passes/DeadArgumentElimination.cpp index 0c6561ef6..3735c79d0 100644 --- a/src/passes/DeadArgumentElimination.cpp +++ b/src/passes/DeadArgumentElimination.cpp @@ -307,8 +307,9 @@ struct DAE : public Pass { auto& calls = pair.second; auto* func = module->getFunction(name); auto numParams = func->getNumParams(); - if (numParams == 0) + if (numParams == 0) { continue; + } // Iterate downwards, as we may remove more than one. Index i = numParams - 1; while (1) { @@ -331,8 +332,9 @@ struct DAE : public Pass { changed.insert(func); } } - if (i == 0) + if (i == 0) { break; + } i--; } } diff --git a/src/passes/DeadCodeElimination.cpp b/src/passes/DeadCodeElimination.cpp index d23713060..c77edf357 100644 --- a/src/passes/DeadCodeElimination.cpp +++ b/src/passes/DeadCodeElimination.cpp @@ -49,8 +49,9 @@ struct DeadCodeElimination Expression* replaceCurrent(Expression* expression) { auto* old = getCurrent(); - if (old == expression) + if (old == expression) { return expression; + } super::replaceCurrent(expression); // also update the type updater typeUpdater.noteReplacement(old, expression); @@ -333,8 +334,9 @@ struct DeadCodeElimination // we don't need to drop unreachable nodes Expression* drop(Expression* toDrop) { - if (toDrop->type == unreachable) + if (toDrop->type == unreachable) { return toDrop; + } return Builder(*getModule()).makeDrop(toDrop); } @@ -362,8 +364,9 @@ struct DeadCodeElimination void visitCall(Call* curr) { handleCall(curr); } void visitCallIndirect(CallIndirect* curr) { - if (handleCall(curr) != curr) + if (handleCall(curr) != curr) { return; + } if (isUnreachable(curr->target)) { auto* block = getModule()->allocator.alloc<Block>(); for (auto* operand : curr->operands) { diff --git a/src/passes/Directize.cpp b/src/passes/Directize.cpp index 8f75c8f57..54315dc77 100644 --- a/src/passes/Directize.cpp +++ b/src/passes/Directize.cpp @@ -93,17 +93,21 @@ private: struct Directize : public Pass { void run(PassRunner* runner, Module* module) override { - if (!module->table.exists) + if (!module->table.exists) { return; - if (module->table.imported()) + } + if (module->table.imported()) { return; + } for (auto& ex : module->exports) { - if (ex->kind == ExternalKind::Table) + if (ex->kind == ExternalKind::Table) { return; + } } FlatTable flatTable(module->table); - if (!flatTable.valid) + if (!flatTable.valid) { return; + } // The table exists and is constant, so this is possible. { PassRunner runner(module); diff --git a/src/passes/DuplicateFunctionElimination.cpp b/src/passes/DuplicateFunctionElimination.cpp index 3caa43e1d..3f048d79a 100644 --- a/src/passes/DuplicateFunctionElimination.cpp +++ b/src/passes/DuplicateFunctionElimination.cpp @@ -85,19 +85,22 @@ struct DuplicateFunctionElimination : public Pass { for (auto& pair : hashGroups) { auto& group = pair.second; Index size = group.size(); - if (size == 1) + if (size == 1) { continue; + } // The groups should be fairly small, and even if a group is large we // should have almost all of them identical, so we should not hit actual // O(N^2) here unless the hash is quite poor. for (Index i = 0; i < size - 1; i++) { auto* first = group[i]; - if (duplicates.count(first->name)) + if (duplicates.count(first->name)) { continue; + } for (Index j = i + 1; j < size; j++) { auto* second = group[j]; - if (duplicates.count(second->name)) + if (duplicates.count(second->name)) { continue; + } if (FunctionUtils::equal(first, second)) { // great, we can replace the second with the first! replacements[second->name] = first->name; diff --git a/src/passes/Flatten.cpp b/src/passes/Flatten.cpp index a68fc9abe..55f3df6ab 100644 --- a/src/passes/Flatten.cpp +++ b/src/passes/Flatten.cpp @@ -128,9 +128,10 @@ struct Flatten rep = builder.makeGetLocal(temp, type); } iff->ifTrue = getPreludesWithExpression(originalIfTrue, iff->ifTrue); - if (iff->ifFalse) + if (iff->ifFalse) { iff->ifFalse = getPreludesWithExpression(originalIfFalse, iff->ifFalse); + } iff->finalize(); if (prelude) { ReFinalizeNode().visit(prelude); @@ -284,8 +285,9 @@ private: Expression* getPreludesWithExpression(Expression* preluder, Expression* after) { auto iter = preludes.find(preluder); - if (iter == preludes.end()) + if (iter == preludes.end()) { return after; + } // we have preludes auto& thePreludes = iter->second; auto* ret = Builder(*getModule()).makeBlock(thePreludes); diff --git a/src/passes/I64ToI32Lowering.cpp b/src/passes/I64ToI32Lowering.cpp index 26f40c284..e61e4055e 100644 --- a/src/passes/I64ToI32Lowering.cpp +++ b/src/passes/I64ToI32Lowering.cpp @@ -53,8 +53,9 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> { TempVar& operator=(TempVar&& rhs) { assert(!rhs.moved); // free overwritten idx - if (!moved) + if (!moved) { freeIdx(); + } idx = rhs.idx; rhs.moved = true; moved = false; @@ -62,8 +63,9 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> { } ~TempVar() { - if (!moved) + if (!moved) { freeIdx(); + } } bool operator==(const TempVar& rhs) { @@ -101,13 +103,15 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> { Pass* create() override { return new I64ToI32Lowering; } void doWalkModule(Module* module) { - if (!builder) + if (!builder) { builder = make_unique<Builder>(*module); + } // add new globals for high bits for (size_t i = 0, globals = module->globals.size(); i < globals; ++i) { auto* curr = module->globals[i].get(); - if (curr->type != i64) + if (curr->type != i64) { continue; + } originallyI64Globals.insert(curr->name); curr->type = i32; auto* high = builder->makeGlobal(makeHighName(curr->name), @@ -162,8 +166,9 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> { void doWalkFunction(Function* func) { Flat::verifyFlatness(func); // create builder here if this is first entry to module for this object - if (!builder) + if (!builder) { builder = make_unique<Builder>(*getModule()); + } indexMap.clear(); highBitVars.clear(); freeTemps.clear(); @@ -327,10 +332,12 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> { } void visitGetGlobal(GetGlobal* curr) { - if (!getFunction()) + if (!getFunction()) { return; // if in a global init, skip - we already handled that. - if (!originallyI64Globals.count(curr->name)) + } + if (!originallyI64Globals.count(curr->name)) { return; + } curr->type = i32; TempVar highBits = getTemp(); SetLocal* setHighBits = builder->makeSetLocal( @@ -341,10 +348,12 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> { } void visitSetGlobal(SetGlobal* curr) { - if (!originallyI64Globals.count(curr->name)) + if (!originallyI64Globals.count(curr->name)) { return; - if (handleUnreachable(curr)) + } + if (handleUnreachable(curr)) { return; + } TempVar highBits = fetchOutParam(curr->value); auto* setHigh = builder->makeSetGlobal( makeHighName(curr->name), builder->makeGetLocal(highBits, i32)); @@ -352,8 +361,9 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> { } void visitLoad(Load* curr) { - if (curr->type != i64) + if (curr->type != i64) { return; + } assert(!curr->isAtomic && "atomic load not implemented"); TempVar lowBits = getTemp(); TempVar highBits = getTemp(); @@ -392,8 +402,9 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> { } void visitStore(Store* curr) { - if (!hasOutParam(curr->value)) + if (!hasOutParam(curr->value)) { return; + } assert(curr->offset + 4 > curr->offset); assert(!curr->isAtomic && "atomic store not implemented"); TempVar highBits = fetchOutParam(curr->value); @@ -426,10 +437,12 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> { } void visitConst(Const* curr) { - if (!getFunction()) + if (!getFunction()) { return; // if in a global init, skip - we already handled that. - if (curr->type != i64) + } + if (curr->type != i64) { return; + } TempVar highBits = getTemp(); Const* lowVal = builder->makeConst(Literal(int32_t(curr->value.geti64() & 0xffffffff))); @@ -763,10 +776,12 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> { } void visitUnary(Unary* curr) { - if (!unaryNeedsLowering(curr->op)) + if (!unaryNeedsLowering(curr->op)) { return; - if (handleUnreachable(curr)) + } + if (handleUnreachable(curr)) { return; + } assert(hasOutParam(curr->value) || curr->type == i64 || curr->type == f64); switch (curr->op) { case ClzInt64: @@ -1265,10 +1280,12 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> { } void visitBinary(Binary* curr) { - if (handleUnreachable(curr)) + if (handleUnreachable(curr)) { return; - if (!binaryNeedsLowering(curr->op)) + } + if (!binaryNeedsLowering(curr->op)) { return; + } // left and right reachable, lower normally TempVar leftLow = getTemp(); TempVar leftHigh = fetchOutParam(curr->left); @@ -1374,8 +1391,9 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> { } void visitSelect(Select* curr) { - if (handleUnreachable(curr)) + if (handleUnreachable(curr)) { return; + } if (!hasOutParam(curr->ifTrue)) { assert(!hasOutParam(curr->ifFalse)); return; @@ -1402,15 +1420,17 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> { } void visitDrop(Drop* curr) { - if (!hasOutParam(curr->value)) + if (!hasOutParam(curr->value)) { return; + } // free temp var fetchOutParam(curr->value); } void visitReturn(Return* curr) { - if (!hasOutParam(curr->value)) + if (!hasOutParam(curr->value)) { return; + } TempVar lowBits = getTemp(); TempVar highBits = fetchOutParam(curr->value); SetLocal* setLow = builder->makeSetLocal(lowBits, curr->value); @@ -1468,8 +1488,9 @@ private: // unconditionally before themselves, so it is not valid for an if, // in particular. bool handleUnreachable(Expression* curr) { - if (curr->type != unreachable) + if (curr->type != unreachable) { return false; + } std::vector<Expression*> children; bool hasUnreachable = false; for (auto* child : ChildIterator(curr)) { @@ -1480,8 +1501,9 @@ private: } children.push_back(child); } - if (!hasUnreachable) + if (!hasUnreachable) { return false; + } // This has an unreachable child, so we can replace it with // the children. auto* block = builder->makeBlock(children); diff --git a/src/passes/Inlining.cpp b/src/passes/Inlining.cpp index 681109af8..11f452e17 100644 --- a/src/passes/Inlining.cpp +++ b/src/passes/Inlining.cpp @@ -79,17 +79,20 @@ struct FunctionInfo { bool worthInlining(PassOptions& options) { // if it's big, it's just not worth doing (TODO: investigate more) - if (size > FLEXIBLE_SIZE_LIMIT) + if (size > FLEXIBLE_SIZE_LIMIT) { return false; + } // if it's so small we have a guarantee that after we optimize the // size will not increase, inline it - if (size <= INLINING_OPTIMIZING_WILL_DECREASE_SIZE_LIMIT) + if (size <= INLINING_OPTIMIZING_WILL_DECREASE_SIZE_LIMIT) { return true; + } // if it has one use, then inlining it would likely reduce code size // since we are just moving code around, + optimizing, so worth it // if small enough that we are pretty sure its ok - if (calls == 1 && !usedGlobally && size <= CAREFUL_SIZE_LIMIT) + if (calls == 1 && !usedGlobally && size <= CAREFUL_SIZE_LIMIT) { return true; + } // more than one use, so we can't eliminate it after inlining, // so only worth it if we really care about speed and don't care // about size, and if it's lightweight so a good candidate for @@ -300,8 +303,9 @@ struct Inlining : public Pass { state.worthInlining.insert(func->name); } }); - if (state.worthInlining.size() == 0) + if (state.worthInlining.size() == 0) { return false; + } // fill in actionsForFunction, as we operate on it in parallel (each // function to its own entry) for (auto& func : module->functions) { @@ -323,16 +327,18 @@ struct Inlining : public Pass { // avoid risk of races // note that we do not risk stalling progress, as each iteration() will // inline at least one call before hitting this - if (inlinedUses.count(func->name)) + if (inlinedUses.count(func->name)) { continue; + } for (auto& action : state.actionsForFunction[func->name]) { auto* inlinedFunction = action.contents; // if we've inlined into a function, don't inline it in this iteration, // avoid risk of races // note that we do not risk stalling progress, as each iteration() will // inline at least one call before hitting this - if (inlinedInto.count(inlinedFunction)) + if (inlinedInto.count(inlinedFunction)) { continue; + } Name inlinedName = inlinedFunction->name; #ifdef INLINING_DEBUG std::cout << "inline " << inlinedName << " into " << func->name << '\n'; diff --git a/src/passes/LegalizeJSInterface.cpp b/src/passes/LegalizeJSInterface.cpp index 324590427..ad6d0c35b 100644 --- a/src/passes/LegalizeJSInterface.cpp +++ b/src/passes/LegalizeJSInterface.cpp @@ -105,13 +105,15 @@ struct LegalizeJSInterface : public Pass { void visitCall(Call* curr) { auto iter = illegalImportsToLegal->find(curr->target); - if (iter == illegalImportsToLegal->end()) + if (iter == illegalImportsToLegal->end()) { return; + } - if (iter->second == getFunction()->name) + if (iter->second == getFunction()->name) { // inside the stub function itself, is the one safe place to do the // call return; + } replaceCurrent(Builder(*getModule()) .makeCall(iter->second, curr->operands, curr->type)); } @@ -130,24 +132,27 @@ private: template<typename T> bool isIllegal(T* t) { for (auto param : t->params) { - if (param == i64) + if (param == i64) { return true; + } } return t->result == i64; } // Check if an export should be legalized. bool shouldBeLegalized(Export* ex, Function* func) { - if (full) + if (full) { return true; + } // We are doing minimal legalization - just what JS needs. return ex->name.startsWith("dynCall_"); } // Check if an import should be legalized. bool shouldBeLegalized(Function* im) { - if (full) + if (full) { return true; + } // We are doing minimal legalization - just what JS needs. return im->module == ENV && im->base.startsWith("invoke_"); } diff --git a/src/passes/LoopInvariantCodeMotion.cpp b/src/passes/LoopInvariantCodeMotion.cpp index e9f376bd3..b8e00ffce 100644 --- a/src/passes/LoopInvariantCodeMotion.cpp +++ b/src/passes/LoopInvariantCodeMotion.cpp @@ -208,8 +208,9 @@ struct LoopInvariantCodeMotion if (auto* set = curr->dynCast<SetLocal>()) { while (1) { auto* next = set->value->dynCast<SetLocal>(); - if (!next) + if (!next) { break; + } set = next; } if (set->value->is<GetLocal>() || set->value->is<Const>()) { @@ -226,8 +227,9 @@ struct LoopInvariantCodeMotion for (auto* set : sets) { // nullptr means a parameter or zero-init value; // no danger to us. - if (!set) + if (!set) { continue; + } // Check if the set is in the loop. If not, it's either before, // which is fine, or after, which is also fine - moving curr // to just outside the loop will preserve those relationships. diff --git a/src/passes/MemoryPacking.cpp b/src/passes/MemoryPacking.cpp index 11dbc1743..99eb2e285 100644 --- a/src/passes/MemoryPacking.cpp +++ b/src/passes/MemoryPacking.cpp @@ -57,8 +57,9 @@ struct MemoryPacking : public Pass { }; for (auto& segment : module->memory.segments) { - if (!isSplittable(segment)) + if (!isSplittable(segment)) { continue; + } // skip final zeros while (segment.data.size() > 0 && segment.data.back() == 0) { diff --git a/src/passes/MergeBlocks.cpp b/src/passes/MergeBlocks.cpp index 8df35abd2..973f17eec 100644 --- a/src/passes/MergeBlocks.cpp +++ b/src/passes/MergeBlocks.cpp @@ -259,16 +259,19 @@ optimizeBlock(Block* curr, Module* module, PassOptions& passOptions) { } } // If no block, we can't do anything. - if (!childBlock) + if (!childBlock) { continue; + } auto& childList = childBlock->list; auto childSize = childList.size(); - if (childSize == 0) + if (childSize == 0) { continue; + } // If the child has items after an unreachable, ignore it - dce should // have been run, and we prefer to not handle the complexity here. - if (hasDeadCode(childBlock)) + if (hasDeadCode(childBlock)) { continue; + } // In some cases we can remove only the head or the tail of the block, // and must keep some things in the child block. Index keepStart = childSize; @@ -314,8 +317,9 @@ optimizeBlock(Block* curr, Module* module, PassOptions& passOptions) { } // Maybe there's nothing to do, if we must keep it all in the // child anyhow. - if (keepStart == 0 && keepEnd == childSize) + if (keepStart == 0 && keepEnd == childSize) { continue; + } // There is something to do! bool keepingPart = keepStart < keepEnd; // Create a new merged list, and fill in the code before the @@ -411,20 +415,23 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks>> { Block* outer = nullptr, Expression** dependency1 = nullptr, Expression** dependency2 = nullptr) { - if (!child) + if (!child) { return outer; + } if ((dependency1 && *dependency1) || (dependency2 && *dependency2)) { // there are dependencies, things we must be reordered through. make sure // no problems there EffectAnalyzer childEffects(getPassOptions(), child); if (dependency1 && *dependency1 && EffectAnalyzer(getPassOptions(), *dependency1) - .invalidates(childEffects)) + .invalidates(childEffects)) { return outer; + } if (dependency2 && *dependency2 && EffectAnalyzer(getPassOptions(), *dependency2) - .invalidates(childEffects)) + .invalidates(childEffects)) { return outer; + } } if (auto* block = child->dynCast<Block>()) { if (!block->name.is() && block->list.size() >= 2) { @@ -489,14 +496,17 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks>> { // TODO: for now, just stop when we see any side effect. instead, we could // check effects carefully for reordering Block* outer = nullptr; - if (EffectAnalyzer(getPassOptions(), first).hasSideEffects()) + if (EffectAnalyzer(getPassOptions(), first).hasSideEffects()) { return; + } outer = optimize(curr, first, outer); - if (EffectAnalyzer(getPassOptions(), second).hasSideEffects()) + if (EffectAnalyzer(getPassOptions(), second).hasSideEffects()) { return; + } outer = optimize(curr, second, outer); - if (EffectAnalyzer(getPassOptions(), third).hasSideEffects()) + if (EffectAnalyzer(getPassOptions(), third).hasSideEffects()) { return; + } optimize(curr, third, outer); } void visitAtomicCmpxchg(AtomicCmpxchg* curr) { @@ -519,8 +529,10 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks>> { template<typename T> void handleCall(T* curr) { Block* outer = nullptr; for (Index i = 0; i < curr->operands.size(); i++) { - if (EffectAnalyzer(getPassOptions(), curr->operands[i]).hasSideEffects()) + if (EffectAnalyzer(getPassOptions(), curr->operands[i]) + .hasSideEffects()) { return; + } outer = optimize(curr, curr->operands[i], outer); } return; @@ -531,12 +543,15 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks>> { void visitCallIndirect(CallIndirect* curr) { Block* outer = nullptr; for (Index i = 0; i < curr->operands.size(); i++) { - if (EffectAnalyzer(getPassOptions(), curr->operands[i]).hasSideEffects()) + if (EffectAnalyzer(getPassOptions(), curr->operands[i]) + .hasSideEffects()) { return; + } outer = optimize(curr, curr->operands[i], outer); } - if (EffectAnalyzer(getPassOptions(), curr->target).hasSideEffects()) + if (EffectAnalyzer(getPassOptions(), curr->target).hasSideEffects()) { return; + } optimize(curr, curr->target, outer); } }; diff --git a/src/passes/MergeLocals.cpp b/src/passes/MergeLocals.cpp index fe9f4bb86..e8d42e8dd 100644 --- a/src/passes/MergeLocals.cpp +++ b/src/passes/MergeLocals.cpp @@ -96,8 +96,9 @@ struct MergeLocals } void optimizeCopies() { - if (copies.empty()) + if (copies.empty()) { return; + } // compute all dependencies LocalGraph preGraph(getFunction()); preGraph.computeInfluences(); diff --git a/src/passes/Metrics.cpp b/src/passes/Metrics.cpp index 0baca3e8b..ca558cd4f 100644 --- a/src/passes/Metrics.cpp +++ b/src/passes/Metrics.cpp @@ -179,8 +179,9 @@ struct Metrics o << title << "\n"; for (auto* key : keys) { auto value = counts[key]; - if (value == 0 && key[0] != '[') + if (value == 0 && key[0] != '[') { continue; + } o << " " << left << setw(15) << key << ": " << setw(8) << value; if (lastCounts.count(key)) { int before = lastCounts[key]; diff --git a/src/passes/NoExitRuntime.cpp b/src/passes/NoExitRuntime.cpp index 680b91b23..82a296cfc 100644 --- a/src/passes/NoExitRuntime.cpp +++ b/src/passes/NoExitRuntime.cpp @@ -41,8 +41,9 @@ struct NoExitRuntime : public WalkerPass<PostWalker<NoExitRuntime>> { void visitCall(Call* curr) { auto* import = getModule()->getFunctionOrNull(curr->target); - if (!import || !import->imported() || import->module != ENV) + if (!import || !import->imported() || import->module != ENV) { return; + } for (auto name : ATEXIT_NAMES) { if (name == import->base) { replaceCurrent(Builder(*getModule()).replaceWithIdenticalType(curr)); diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 8a9309554..85258dbb8 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -102,8 +102,9 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case ShrSInt32: { if (auto* shift = binary->right->dynCast<Const>()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); - if (maxBits == 32) + if (maxBits == 32) { return 32; + } auto shifts = std::min(Index(Bits::getEffectiveShifts(shift)), maxBits); // can ignore more shifts than zero us out @@ -227,11 +228,13 @@ struct LocalScanner : PostWalker<LocalScanner> { void visitSetLocal(SetLocal* curr) { auto* func = getFunction(); - if (func->isParam(curr->index)) + if (func->isParam(curr->index)) { return; + } auto type = getFunction()->getLocalType(curr->index); - if (type != i32 && type != i64) + if (type != i32 && type != i64) { return; + } // an integer var, worth processing auto* value = Properties::getFallthrough(curr->value); auto& info = localInfo[curr->index]; @@ -501,12 +504,14 @@ struct OptimizeInstructions } } auto* ret = optimizeAddedConstants(binary); - if (ret) + if (ret) { return ret; + } } else if (binary->op == SubInt32) { auto* ret = optimizeAddedConstants(binary); - if (ret) + if (ret) { return ret; + } } // a bunch of operations on a constant right side can be simplified if (auto* right = binary->right->dynCast<Const>()) { @@ -532,8 +537,9 @@ struct OptimizeInstructions } // some math operations have trivial results Expression* ret = optimizeWithConstantOnRight(binary); - if (ret) + if (ret) { return ret; + } // the square of some operations can be merged if (auto* left = binary->left->dynCast<Binary>()) { if (left->op == binary->op) { @@ -575,8 +581,9 @@ struct OptimizeInstructions // a bunch of operations on a constant left side can be simplified if (binary->left->is<Const>()) { Expression* ret = optimizeWithConstantOnLeft(binary); - if (ret) + if (ret) { return ret; + } } // bitwise operations if (binary->op == AndInt32) { @@ -895,8 +902,9 @@ private: if (binary->left->is<Const>() && !binary->right->is<Const>()) { return swap(); } - if (binary->right->is<Const>()) + if (binary->right->is<Const>()) { return; + } // Prefer a get on the right. if (binary->left->is<GetLocal>() && !binary->right->is<GetLocal>()) { return maybeSwap(); @@ -1085,8 +1093,9 @@ private: }; Expression* walked = binary; ZeroRemover(getPassOptions()).walk(walked); - if (constant == 0) + if (constant == 0) { return walked; // nothing more to do + } if (auto* c = walked->dynCast<Const>()) { assert(c->value.geti32() == 0); c->value = Literal(constant); @@ -1103,40 +1112,48 @@ private: Expression* conditionalizeExpensiveOnBitwise(Binary* binary) { // this operation can increase code size, so don't always do it auto& options = getPassRunner()->options; - if (options.optimizeLevel < 2 || options.shrinkLevel > 0) + if (options.optimizeLevel < 2 || options.shrinkLevel > 0) { return nullptr; + } const auto MIN_COST = 7; assert(binary->op == AndInt32 || binary->op == OrInt32); - if (binary->right->is<Const>()) + if (binary->right->is<Const>()) { return nullptr; // trivial + } // bitwise logical operator on two non-numerical values, check if they are // boolean auto* left = binary->left; auto* right = binary->right; - if (!Properties::emitsBoolean(left) || !Properties::emitsBoolean(right)) + if (!Properties::emitsBoolean(left) || !Properties::emitsBoolean(right)) { return nullptr; + } auto leftEffects = EffectAnalyzer(getPassOptions(), left); auto rightEffects = EffectAnalyzer(getPassOptions(), right); auto leftHasSideEffects = leftEffects.hasSideEffects(); auto rightHasSideEffects = rightEffects.hasSideEffects(); - if (leftHasSideEffects && rightHasSideEffects) + if (leftHasSideEffects && rightHasSideEffects) { return nullptr; // both must execute + } // canonicalize with side effects, if any, happening on the left if (rightHasSideEffects) { - if (CostAnalyzer(left).cost < MIN_COST) + if (CostAnalyzer(left).cost < MIN_COST) { return nullptr; // avoidable code is too cheap - if (leftEffects.invalidates(rightEffects)) + } + if (leftEffects.invalidates(rightEffects)) { return nullptr; // cannot reorder + } std::swap(left, right); } else if (leftHasSideEffects) { - if (CostAnalyzer(right).cost < MIN_COST) + if (CostAnalyzer(right).cost < MIN_COST) { return nullptr; // avoidable code is too cheap + } } else { // no side effects, reorder based on cost estimation auto leftCost = CostAnalyzer(left).cost; auto rightCost = CostAnalyzer(right).cost; - if (std::max(leftCost, rightCost) < MIN_COST) + if (std::max(leftCost, rightCost) < MIN_COST) { return nullptr; // avoidable code is too cheap + } // canonicalize with expensive code on the right if (leftCost > rightCost) { std::swap(left, right); @@ -1240,8 +1257,9 @@ private: auto* outerConst = outer->right->cast<Const>(); auto* innerConst = inner->right->cast<Const>(); auto* value = inner->left; - if (outerConst->value == innerConst->value) + if (outerConst->value == innerConst->value) { return value; + } // add a shift, by reusing the existing node innerConst->value = innerConst->value.sub(outerConst->value); return inner; diff --git a/src/passes/PostEmscripten.cpp b/src/passes/PostEmscripten.cpp index 6c9b84d7c..cc4b03a7f 100644 --- a/src/passes/PostEmscripten.cpp +++ b/src/passes/PostEmscripten.cpp @@ -35,8 +35,9 @@ struct PostEmscripten : public WalkerPass<PostWalker<PostEmscripten>> { void visitCall(Call* curr) { // special asm.js imports can be optimized auto* func = getModule()->getFunction(curr->target); - if (!func->imported()) + if (!func->imported()) { return; + } if (func->module == GLOBAL_MATH) { if (func->base == POW) { if (auto* exponent = curr->operands[1]->dynCast<Const>()) { diff --git a/src/passes/Precompute.cpp b/src/passes/Precompute.cpp index 074dd832c..02fd089ec 100644 --- a/src/passes/Precompute.cpp +++ b/src/passes/Precompute.cpp @@ -163,20 +163,24 @@ struct Precompute void visitExpression(Expression* curr) { // TODO: if local.get, only replace with a constant if we don't care about // size...? - if (curr->is<Const>() || curr->is<Nop>()) + if (curr->is<Const>() || curr->is<Nop>()) { return; + } // Until engines implement v128.const and we have SIMD-aware optimizations // that can break large v128.const instructions into smaller consts and // splats, do not try to precompute v128 expressions. - if (isVectorType(curr->type)) + if (isVectorType(curr->type)) { return; + } // try to evaluate this into a const Flow flow = precomputeExpression(curr); - if (isVectorType(flow.value.type)) + if (isVectorType(flow.value.type)) { return; + } if (flow.breaking()) { - if (flow.breakTo == NOTPRECOMPUTABLE_FLOW) + if (flow.breakTo == NOTPRECOMPUTABLE_FLOW) { return; + } if (flow.breakTo == RETURN_FLOW) { // this expression causes a return. if it's already a return, reuse the // node @@ -301,8 +305,9 @@ private: // mark it as such and add everything it influences to the work list, // as they may be constant too. if (auto* set = curr->dynCast<SetLocal>()) { - if (setValues[set].isConcrete()) + if (setValues[set].isConcrete()) { continue; // already known constant + } auto value = setValues[set] = precomputeValue(set->value); if (value.isConcrete()) { for (auto* get : localGraph.setInfluences[set]) { @@ -311,8 +316,9 @@ private: } } else { auto* get = curr->cast<GetLocal>(); - if (getValues[get].isConcrete()) + if (getValues[get].isConcrete()) { continue; // already known constant + } // for this get to have constant value, all sets must agree Literal value; bool first = true; diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 405097455..73d91b9ce 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -132,8 +132,9 @@ struct PrintExpressionContents : public Visitor<PrintExpressionContents> { } void visitLoad(Load* curr) { prepareColor(o) << printType(curr->type); - if (curr->isAtomic) + if (curr->isAtomic) { o << ".atomic"; + } o << ".load"; if (curr->type != unreachable && curr->bytes < getTypeSize(curr->type)) { if (curr->bytes == 1) { @@ -157,8 +158,9 @@ struct PrintExpressionContents : public Visitor<PrintExpressionContents> { } void visitStore(Store* curr) { prepareColor(o) << printType(curr->valueType); - if (curr->isAtomic) + if (curr->isAtomic) { o << ".atomic"; + } o << ".store"; if (curr->bytes < 4 || (curr->valueType == i64 && curr->bytes < 8)) { if (curr->bytes == 1) { @@ -1174,8 +1176,9 @@ struct PrintSExpression : public Visitor<PrintSExpression> { PrintSExpression(std::ostream& o) : o(o) { setMinify(false); - if (!full) + if (!full) { full = isFullForced(); + } } void printDebugLocation(const Function::DebugLocation& location) { @@ -1214,8 +1217,9 @@ struct PrintSExpression : public Visitor<PrintSExpression> { void setFull(bool full_) { full = full_; } void incIndent() { - if (minify) + if (minify) { return; + } o << '\n'; indent++; } @@ -1352,8 +1356,9 @@ struct PrintSExpression : public Visitor<PrintSExpression> { } incIndent(); } - if (curr->value && !curr->value->is<Nop>()) + if (curr->value && !curr->value->is<Nop>()) { printFullLine(curr->value); + } if (curr->condition) { printFullLine(curr->condition); } @@ -1363,8 +1368,9 @@ struct PrintSExpression : public Visitor<PrintSExpression> { o << '('; PrintExpressionContents(currFunction, o).visit(curr); incIndent(); - if (curr->value && !curr->value->is<Nop>()) + if (curr->value && !curr->value->is<Nop>()) { printFullLine(curr->value); + } printFullLine(curr->condition); decIndent(); } @@ -1618,8 +1624,9 @@ struct PrintSExpression : public Visitor<PrintSExpression> { // Module-level visitors void visitFunctionType(FunctionType* curr, Name* internalName = nullptr) { o << "(func"; - if (internalName) + if (internalName) { o << ' ' << *internalName; + } if (curr->params.size() > 0) { o << maybeSpace; o << '('; @@ -1803,13 +1810,15 @@ struct PrintSExpression : public Visitor<PrintSExpression> { printMedium(o, "table") << ' '; printName(curr->name, o) << ' '; o << curr->initial; - if (curr->hasMax()) + if (curr->hasMax()) { o << ' ' << curr->max; + } o << " funcref)"; } void visitTable(Table* curr) { - if (!curr->exists) + if (!curr->exists) { return; + } if (curr->imported()) { doIndent(o, indent); o << '('; @@ -1823,8 +1832,9 @@ struct PrintSExpression : public Visitor<PrintSExpression> { } for (auto& segment : curr->segments) { // Don't print empty segments - if (segment.data.empty()) + if (segment.data.empty()) { continue; + } doIndent(o, indent); o << '('; printMajor(o, "elem "); @@ -1845,15 +1855,18 @@ struct PrintSExpression : public Visitor<PrintSExpression> { printMedium(o, "shared "); } o << curr->initial; - if (curr->hasMax()) + if (curr->hasMax()) { o << ' ' << curr->max; - if (curr->shared) + } + if (curr->shared) { o << ")"; + } o << ")"; } void visitMemory(Memory* curr) { - if (!curr->exists) + if (!curr->exists) { return; + } if (curr->imported()) { doIndent(o, indent); o << '('; @@ -2104,8 +2117,9 @@ WasmPrinter::printStackIR(StackIR* ir, std::ostream& o, Function* func) { }; for (Index i = 0; i < (*ir).size(); i++) { auto* inst = (*ir)[i]; - if (!inst) + if (!inst) { continue; + } switch (inst->op) { case StackInst::Basic: { doIndent(); diff --git a/src/passes/PrintCallGraph.cpp b/src/passes/PrintCallGraph.cpp index 7df5a8875..6d9224a21 100644 --- a/src/passes/PrintCallGraph.cpp +++ b/src/passes/PrintCallGraph.cpp @@ -85,8 +85,9 @@ struct PrintCallGraph : public Pass { } void visitCall(Call* curr) { auto* target = module->getFunction(curr->target); - if (visitedTargets.count(target->name) > 0) + if (visitedTargets.count(target->name) > 0) { return; + } visitedTargets.insert(target->name); std::cout << " \"" << currFunction->name << "\" -> \"" << target->name << "\"; // call\n"; diff --git a/src/passes/ReReloop.cpp b/src/passes/ReReloop.cpp index 3a7c2ad87..0fbe22c71 100644 --- a/src/passes/ReReloop.cpp +++ b/src/passes/ReReloop.cpp @@ -91,8 +91,9 @@ struct ReReloop final : public Pass { CFG::Block* to, const std::set<Index>& values) { std::vector<Index> list; - for (auto i : values) + for (auto i : values) { list.push_back(i); + } from->AddSwitchBranchTo(to, std::move(list)); } diff --git a/src/passes/RedundantSetElimination.cpp b/src/passes/RedundantSetElimination.cpp index e03020da0..bd0e5b890 100644 --- a/src/passes/RedundantSetElimination.cpp +++ b/src/passes/RedundantSetElimination.cpp @@ -145,12 +145,14 @@ struct RedundantSetElimination bool isBlockMergeValue(BasicBlock* block, Index index, Index value) { auto iter = blockMergeValues.find(block); - if (iter == blockMergeValues.end()) + if (iter == blockMergeValues.end()) { return false; + } auto& mergeValues = iter->second; auto iter2 = mergeValues.find(index); - if (iter2 == mergeValues.end()) + if (iter2 == mergeValues.end()) { return false; + } return value == iter2->second; } diff --git a/src/passes/RelooperJumpThreading.cpp b/src/passes/RelooperJumpThreading.cpp index 9fcf7a4a8..855e89b7f 100644 --- a/src/passes/RelooperJumpThreading.cpp +++ b/src/passes/RelooperJumpThreading.cpp @@ -37,17 +37,21 @@ static Name getOuterName(int i) { } static If* isLabelCheckingIf(Expression* curr, Index labelIndex) { - if (!curr) + if (!curr) { return nullptr; + } auto* iff = curr->dynCast<If>(); - if (!iff) + if (!iff) { return nullptr; + } auto* condition = iff->condition->dynCast<Binary>(); - if (!(condition && condition->op == EqInt32)) + if (!(condition && condition->op == EqInt32)) { return nullptr; + } auto* left = condition->left->dynCast<GetLocal>(); - if (!(left && left->index == labelIndex)) + if (!(left && left->index == labelIndex)) { return nullptr; + } return iff; } @@ -56,13 +60,16 @@ static Index getCheckedLabelValue(If* iff) { } static SetLocal* isLabelSettingSetLocal(Expression* curr, Index labelIndex) { - if (!curr) + if (!curr) { return nullptr; + } auto* set = curr->dynCast<SetLocal>(); - if (!set) + if (!set) { return nullptr; - if (set->index != labelIndex) + } + if (set->index != labelIndex) { return nullptr; + } return set; } @@ -108,8 +115,9 @@ struct RelooperJumpThreading void visitBlock(Block* curr) { // look for the if label == X pattern auto& list = curr->list; - if (list.size() == 0) + if (list.size() == 0) { return; + } for (Index i = 0; i < list.size() - 1; i++) { // once we see something that might be irreducible, we must skip that if // and the rest of the dependents @@ -186,8 +194,9 @@ private: while (iff) { auto num = getCheckedLabelValue(iff); assert(labelChecks[num] > 0); - if (labelChecks[num] > 1) + if (labelChecks[num] > 1) { return true; // checked more than once, somewhere in function + } assert(labelChecksInOrigin[num] == 0); if (labelSetsInOrigin[num] != labelSets[num]) { assert(labelSetsInOrigin[num] < labelSets[num]); diff --git a/src/passes/RemoveNonJSOps.cpp b/src/passes/RemoveNonJSOps.cpp index 26ede65c5..dd23aa9bf 100644 --- a/src/passes/RemoveNonJSOps.cpp +++ b/src/passes/RemoveNonJSOps.cpp @@ -56,8 +56,9 @@ struct RemoveNonJSOpsPass : public WalkerPass<PostWalker<RemoveNonJSOpsPass>> { // Discover all of the intrinsics that we need to inject, lowering all // operations to intrinsic calls while we're at it. - if (!builder) + if (!builder) { builder = make_unique<Builder>(*module); + } PostWalker<RemoveNonJSOpsPass>::doWalkModule(module); if (neededIntrinsics.size() == 0) { @@ -142,8 +143,9 @@ struct RemoveNonJSOpsPass : public WalkerPass<PostWalker<RemoveNonJSOpsPass>> { } void doWalkFunction(Function* func) { - if (!builder) + if (!builder) { builder = make_unique<Builder>(*getModule()); + } PostWalker<RemoveNonJSOpsPass>::doWalkFunction(func); } diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp index 4b5c9613e..20811efef 100644 --- a/src/passes/RemoveUnusedBrs.cpp +++ b/src/passes/RemoveUnusedBrs.cpp @@ -36,13 +36,16 @@ static bool canTurnIfIntoBrIf(Expression* ifCondition, Expression* brValue, PassOptions& options) { // if the if isn't even reached, this is all dead code anyhow - if (ifCondition->type == unreachable) + if (ifCondition->type == unreachable) { return false; - if (!brValue) + } + if (!brValue) { return true; + } EffectAnalyzer value(options, brValue); - if (value.hasSideEffects()) + if (value.hasSideEffects()) { return false; + } return !EffectAnalyzer(options, ifCondition).invalidates(value); } @@ -219,8 +222,9 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> { } // when there isn't a value, we can do some trivial optimizations without // worrying about the value being executed before the condition - if (curr->value) + if (curr->value) { return; + } if (curr->targets.size() == 0) { // a switch with just a default always goes there Builder builder(*getModule()); @@ -344,19 +348,23 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> { // helpful, as it shortens the logical loop. it is also good to generate // an if-else instead of an if, as it might allow an eqz to be removed // by flipping arms) - if (!loop->name.is()) + if (!loop->name.is()) { return false; + } auto* block = loop->body->dynCast<Block>(); - if (!block) + if (!block) { return false; + } // does the last element break to the top of the loop? auto& list = block->list; - if (list.size() <= 1) + if (list.size() <= 1) { return false; + } auto* last = list.back()->dynCast<Break>(); if (!last || !ExpressionAnalyzer::isSimple(last) || - last->name != loop->name) + last->name != loop->name) { return false; + } // last is a simple break to the top of the loop. if we can conditionalize // it, it won't block things from flowing out and not needing breaks to do // so. @@ -391,8 +399,9 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> { auto blockifyMerge = [&](Expression* any, Expression* append) -> Block* { Block* block = nullptr; - if (any) + if (any) { block = any->dynCast<Block>(); + } // if the first isn't a block, or it's a block with a name (so we // might branch to the end, and so can't append to it, we might skip // that code!) then make a new block @@ -468,8 +477,9 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> { if (EffectAnalyzer(getPassOptions(), curr).branches) { return false; } - if (i == 0) + if (i == 0) { return false; + } i--; } } @@ -560,8 +570,9 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> { // optimized for (Index i = 0; i < flows.size(); i++) { auto* flow = (*flows[i])->dynCast<Return>(); - if (!flow) + if (!flow) { continue; + } if (!flow->value) { // return => nop ExpressionManipulator::nop(flow); @@ -689,10 +700,11 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> { auto& list = curr->list; for (Index i = 0; i < list.size(); i++) { auto* iff = list[i]->dynCast<If>(); - if (!iff || !iff->ifFalse) + if (!iff || !iff->ifFalse) { // if it lacked an if-false, it would already be a br_if, as that's // the easy case continue; + } auto* ifTrueBreak = iff->ifTrue->dynCast<Break>(); if (ifTrueBreak && !ifTrueBreak->condition && canTurnIfIntoBrIf( @@ -724,12 +736,14 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> { auto* br1 = list[i]->dynCast<Break>(); // avoid unreachable brs, as they are dead code anyhow, and after // merging them the outer scope could need type changes - if (!br1 || !br1->condition || br1->type == unreachable) + if (!br1 || !br1->condition || br1->type == unreachable) { continue; + } assert(!br1->value); auto* br2 = list[i + 1]->dynCast<Break>(); - if (!br2 || br1->name != br2->name) + if (!br2 || br1->name != br2->name) { continue; + } assert(!br2->value); // same target as previous, which has no value // a br_if and then a br[_if] with the same target right after it if (br2->condition) { @@ -862,8 +876,9 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> { const auto MAX_COST = 7; auto total = CostAnalyzer(iff->ifTrue).cost + CostAnalyzer(iff->ifFalse).cost; - if (total >= MAX_COST) + if (total >= MAX_COST) { return nullptr; + } } // Check if side effects allow this. EffectAnalyzer condition(passOptions, iff->condition); @@ -889,10 +904,12 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> { } void optimizeSetIf(Expression** currp) { - if (optimizeSetIfWithBrArm(currp)) + if (optimizeSetIfWithBrArm(currp)) { return; - if (optimizeSetIfWithCopyArm(currp)) + } + if (optimizeSetIfWithCopyArm(currp)) { return; + } } // If one arm is a br, we prefer a br_if and the set later: @@ -1003,8 +1020,9 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> { get = nullptr; } } - if (!get) + if (!get) { return false; + } // We can do it! bool tee = set->isTee(); assert(set->index == get->index); @@ -1045,8 +1063,9 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> { // TODO: consider also looking at <= etc. and not just eq void tablify(Block* block) { auto& list = block->list; - if (list.size() <= 1) + if (list.size() <= 1) { return; + } // Heuristics. These are slightly inspired by the constants from the // asm.js backend. @@ -1065,25 +1084,32 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> { // or nullptr otherwise auto getProperBrIf = [](Expression* curr) -> Break* { auto* br = curr->dynCast<Break>(); - if (!br) + if (!br) { return nullptr; - if (!br->condition || br->value) + } + if (!br->condition || br->value) { return nullptr; - if (br->type != none) + } + if (br->type != none) { // no value, so can be unreachable or none. ignore unreachable ones, // dce will clean it up return nullptr; + } auto* binary = br->condition->dynCast<Binary>(); - if (!binary) + if (!binary) { return nullptr; - if (binary->op != EqInt32) + } + if (binary->op != EqInt32) { return nullptr; + } auto* c = binary->right->dynCast<Const>(); - if (!c) + if (!c) { return nullptr; + } uint32_t value = c->value.geti32(); - if (value >= uint32_t(std::numeric_limits<int32_t>::max())) + if (value >= uint32_t(std::numeric_limits<int32_t>::max())) { return nullptr; + } return br; }; @@ -1092,8 +1118,9 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> { auto getProperBrIfConditionValue = [&getProperBrIf](Expression* curr) -> Expression* { auto* br = getProperBrIf(curr); - if (!br) + if (!br) { return nullptr; + } return br->condition->cast<Binary>()->left; }; @@ -1160,8 +1187,9 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> { Index i = 0; while (1) { defaultName = "tablify|" + std::to_string(i++); - if (usedNames.count(defaultName) == 0) + if (usedNames.count(defaultName) == 0) { break; + } } std::vector<Name> table; for (Index i = start; i < end; i++) { diff --git a/src/passes/RemoveUnusedModuleElements.cpp b/src/passes/RemoveUnusedModuleElements.cpp index 3338bb756..ca0817b20 100644 --- a/src/passes/RemoveUnusedModuleElements.cpp +++ b/src/passes/RemoveUnusedModuleElements.cpp @@ -256,8 +256,9 @@ struct RemoveUnusedModuleElements : public Pass { std::unordered_map<std::string, FunctionType*> canonicals; std::unordered_set<FunctionType*> needed; auto canonicalize = [&](Name name) { - if (!name.is()) + if (!name.is()) { return name; + } FunctionType* type = module->getFunctionType(name); auto sig = getSig(type); auto iter = canonicals.find(sig); diff --git a/src/passes/RemoveUnusedNames.cpp b/src/passes/RemoveUnusedNames.cpp index 86db53b0c..3db5a2173 100644 --- a/src/passes/RemoveUnusedNames.cpp +++ b/src/passes/RemoveUnusedNames.cpp @@ -61,15 +61,18 @@ struct RemoveUnusedNames : public WalkerPass<PostWalker<RemoveUnusedNames>> { auto& branches = branchesSeen[curr->name]; for (auto* branch : branches) { if (Break* br = branch->dynCast<Break>()) { - if (br->name == curr->name) + if (br->name == curr->name) { br->name = child->name; + } } else if (Switch* sw = branch->dynCast<Switch>()) { for (auto& target : sw->targets) { - if (target == curr->name) + if (target == curr->name) { target = child->name; + } } - if (sw->default_ == curr->name) + if (sw->default_ == curr->name) { sw->default_ = child->name; + } } else { WASM_UNREACHABLE(); } diff --git a/src/passes/ReorderLocals.cpp b/src/passes/ReorderLocals.cpp index 45796c0aa..e5e01af5d 100644 --- a/src/passes/ReorderLocals.cpp +++ b/src/passes/ReorderLocals.cpp @@ -47,16 +47,19 @@ struct ReorderLocals : public WalkerPass<PostWalker<ReorderLocals>> { // sort, keeping params in front (where they will not be moved) sort( newToOld.begin(), newToOld.end(), [this, curr](Index a, Index b) -> bool { - if (curr->isParam(a) && !curr->isParam(b)) + if (curr->isParam(a) && !curr->isParam(b)) { return true; - if (curr->isParam(b) && !curr->isParam(a)) + } + if (curr->isParam(b) && !curr->isParam(a)) { return false; + } if (curr->isParam(b) && curr->isParam(a)) { return a < b; } if (counts[a] == counts[b]) { - if (counts[a] == 0) + if (counts[a] == 0) { return a < b; + } return firstUses[a] < firstUses[b]; } return counts[a] > counts[b]; diff --git a/src/passes/SSAify.cpp b/src/passes/SSAify.cpp index 2f0f9439c..990a627f6 100644 --- a/src/passes/SSAify.cpp +++ b/src/passes/SSAify.cpp @@ -141,8 +141,9 @@ struct SSAify : public Pass { } continue; } - if (!allowMerges) + if (!allowMerges) { continue; + } // more than 1 set, need a phi: a new local written to at each of the sets auto new_ = addLocal(get->type); auto old = get->index; diff --git a/src/passes/SafeHeap.cpp b/src/passes/SafeHeap.cpp index a293ee5e9..2cc309a92 100644 --- a/src/passes/SafeHeap.cpp +++ b/src/passes/SafeHeap.cpp @@ -69,8 +69,9 @@ struct AccessInstrumenter : public WalkerPass<PostWalker<AccessInstrumenter>> { AccessInstrumenter* create() override { return new AccessInstrumenter; } void visitLoad(Load* curr) { - if (curr->type == unreachable) + if (curr->type == unreachable) { return; + } Builder builder(*getModule()); replaceCurrent( builder.makeCall(getLoadName(curr), @@ -82,8 +83,9 @@ struct AccessInstrumenter : public WalkerPass<PostWalker<AccessInstrumenter>> { } void visitStore(Store* curr) { - if (curr->type == unreachable) + if (curr->type == unreachable) { return; + } Builder builder(*getModule()); replaceCurrent( builder.makeCall(getStoreName(curr), @@ -161,22 +163,26 @@ struct SafeHeap : public Pass { // load funcs Load load; for (auto type : {i32, i64, f32, f64, v128}) { - if (type == v128 && !features.hasSIMD()) + if (type == v128 && !features.hasSIMD()) { continue; + } load.type = type; for (Index bytes : {1, 2, 4, 8, 16}) { load.bytes = bytes; if (bytes > getTypeSize(type) || (type == f32 && bytes != 4) || - (type == f64 && bytes != 8) || (type == v128 && bytes != 16)) + (type == f64 && bytes != 8) || (type == v128 && bytes != 16)) { continue; + } for (auto signed_ : {true, false}) { load.signed_ = signed_; - if (isFloatType(type) && signed_) + if (isFloatType(type) && signed_) { continue; + } for (Index align : {1, 2, 4, 8, 16}) { load.align = align; - if (align > bytes) + if (align > bytes) { continue; + } for (auto isAtomic : {true, false}) { load.isAtomic = isAtomic; if (isAtomic && !isPossibleAtomicOperation( @@ -192,8 +198,9 @@ struct SafeHeap : public Pass { // store funcs Store store; for (auto valueType : {i32, i64, f32, f64, v128}) { - if (valueType == v128 && !features.hasSIMD()) + if (valueType == v128 && !features.hasSIMD()) { continue; + } store.valueType = valueType; store.type = none; for (Index bytes : {1, 2, 4, 8, 16}) { @@ -201,12 +208,14 @@ struct SafeHeap : public Pass { if (bytes > getTypeSize(valueType) || (valueType == f32 && bytes != 4) || (valueType == f64 && bytes != 8) || - (valueType == v128 && bytes != 16)) + (valueType == v128 && bytes != 16)) { continue; + } for (Index align : {1, 2, 4, 8, 16}) { store.align = align; - if (align > bytes) + if (align > bytes) { continue; + } for (auto isAtomic : {true, false}) { store.isAtomic = isAtomic; if (isAtomic && !isPossibleAtomicOperation( @@ -223,8 +232,9 @@ struct SafeHeap : public Pass { // creates a function for a particular style of load void addLoadFunc(Load style, Module* module) { auto name = getLoadName(&style); - if (module->getFunctionOrNull(name)) + if (module->getFunctionOrNull(name)) { return; + } auto* func = new Function; func->name = name; func->params.push_back(i32); // pointer @@ -262,8 +272,9 @@ struct SafeHeap : public Pass { // creates a function for a particular type of store void addStoreFunc(Store style, Module* module) { auto name = getStoreName(&style); - if (module->getFunctionOrNull(name)) + if (module->getFunctionOrNull(name)) { return; + } auto* func = new Function; func->name = name; func->params.push_back(i32); // pointer diff --git a/src/passes/SimplifyLocals.cpp b/src/passes/SimplifyLocals.cpp index 6b714688f..71fd74f43 100644 --- a/src/passes/SimplifyLocals.cpp +++ b/src/passes/SimplifyLocals.cpp @@ -403,12 +403,14 @@ struct SimplifyLocals bool canSink(SetLocal* set) { // we can never move a tee - if (set->isTee()) + if (set->isTee()) { return false; + } // if in the first cycle, or not allowing tees, then we cannot sink if >1 // use as that would make a tee - if ((firstCycle || !allowTee) && getCounter.num[set->index] > 1) + if ((firstCycle || !allowTee) && getCounter.num[set->index] > 1) { return false; + } return true; } @@ -419,10 +421,12 @@ struct SimplifyLocals void optimizeLoopReturn(Loop* loop) { // If there is a sinkable thing in an eligible loop, we can optimize // it in a trivial way to the outside of the loop. - if (loop->type != none) + if (loop->type != none) { return; - if (sinkables.empty()) + } + if (sinkables.empty()) { return; + } Index goodIndex = sinkables.begin()->first; // Ensure we have a place to write the return values for, if not, we // need another cycle. @@ -455,9 +459,10 @@ struct SimplifyLocals } auto breaks = std::move(blockBreaks[block->name]); blockBreaks.erase(block->name); - if (breaks.size() == 0) + if (breaks.size() == 0) { // block has no branches TODO we might optimize trivial stuff here too return; + } // block does not already have a return value (if one break has one, they // all do) assert(!(*breaks[0].brp)->template cast<Break>()->value); @@ -479,8 +484,9 @@ struct SimplifyLocals break; } } - if (!found) + if (!found) { return; + } // If one of our brs is a br_if, then we will give it a value. since // the value executes before the condition, it is dangerous if we are // moving code out of the condition, @@ -578,8 +584,9 @@ struct SimplifyLocals assert(iff->ifFalse); // if this if already has a result, or is unreachable code, we have // nothing to do - if (iff->type != none) + if (iff->type != none) { return; + } // We now have the sinkables from both sides of the if, and can look // for something to sink. That is either a shared index on both sides, // *or* if one side is unreachable, we can sink anything from the other, @@ -622,8 +629,9 @@ struct SimplifyLocals } } } - if (!found) + if (!found) { return; + } // great, we can optimize! // ensure we have a place to write the return values for, if not, we // need another cycle @@ -695,11 +703,13 @@ struct SimplifyLocals // arm into a one-sided if. void optimizeIfReturn(If* iff, Expression** currp) { // If this if is unreachable code, we have nothing to do. - if (iff->type != none || iff->ifTrue->type != none) + if (iff->type != none || iff->ifTrue->type != none) { return; + } // Anything sinkable is good for us. - if (sinkables.empty()) + if (sinkables.empty()) { return; + } Index goodIndex = sinkables.begin()->first; // Ensure we have a place to write the return values for, if not, we // need another cycle. diff --git a/src/passes/Souperify.cpp b/src/passes/Souperify.cpp index 1cc3037fe..6d7176e40 100644 --- a/src/passes/Souperify.cpp +++ b/src/passes/Souperify.cpp @@ -86,8 +86,9 @@ struct UseFinder { LocalGraph& localGraph, std::vector<Expression*>& ret) { // If already handled, nothing to do here. - if (seenSets.count(set)) + if (seenSets.count(set)) { return; + } seenSets.insert(set); // Find all the uses of that set. auto& gets = localGraph.setInfluences[set]; @@ -190,8 +191,9 @@ struct Trace { } // Pull in all the dependencies, starting from the value itself. add(toInfer, 0); - if (bad) + if (bad) { return; + } // If we are trivial before adding pcs, we are still trivial, and // can ignore this. auto sizeBeforePathConditions = nodes.size(); @@ -385,8 +387,9 @@ struct Trace { } } for (auto& node : nodes) { - if (node == toInfer) + if (node == toInfer) { continue; + } if (auto* origin = node->origin) { auto uses = UseFinder().getUses(origin, graph, localGraph); for (auto* use : uses) { @@ -715,8 +718,9 @@ struct Souperify : public WalkerPass<PostWalker<Souperify>> { // Build the data-flow IR. DataFlow::Graph graph; graph.build(func, getModule()); - if (debug() >= 2) + if (debug() >= 2) { dump(graph, std::cout); + } // Build the local graph data structure. LocalGraph localGraph(func); localGraph.computeInfluences(); diff --git a/src/passes/SpillPointers.cpp b/src/passes/SpillPointers.cpp index 75fa72652..6c194eb60 100644 --- a/src/passes/SpillPointers.cpp +++ b/src/passes/SpillPointers.cpp @@ -50,8 +50,9 @@ struct SpillPointers // note calls in basic blocks template<typename T> void visitSpillable(T* curr) { // if in unreachable code, ignore - if (!currBasicBlock) + if (!currBasicBlock) { return; + } auto* pointer = getCurrentPointer(); currBasicBlock->contents.actions.emplace_back(pointer); // starts out as correct, may change later @@ -85,8 +86,9 @@ struct SpillPointers bool spilled = false; Index spillLocal = -1; for (auto& curr : basicBlocks) { - if (liveBlocks.count(curr.get()) == 0) + if (liveBlocks.count(curr.get()) == 0) { continue; // ignore dead blocks + } auto& liveness = curr->contents; auto& actions = liveness.actions; Index lastCall = -1; @@ -96,8 +98,9 @@ struct SpillPointers lastCall = i; } } - if (lastCall == Index(-1)) + if (lastCall == Index(-1)) { continue; // nothing to see here + } // scan through the block, spilling around the calls // TODO: we can filter on pointerMap everywhere LocalSet live = liveness.end; @@ -149,8 +152,9 @@ struct SpillPointers Function* func, Module* module) { auto* call = *origin; - if (call->type == unreachable) + if (call->type == unreachable) { return; // the call is never reached anyhow, ignore + } Builder builder(*module); auto* block = builder.makeBlock(); // move the operands into locals, as we must spill after they are executed diff --git a/src/passes/StackIR.cpp b/src/passes/StackIR.cpp index 2506eca27..1f182dbc3 100644 --- a/src/passes/StackIR.cpp +++ b/src/passes/StackIR.cpp @@ -94,8 +94,9 @@ private: bool inUnreachableCode = false; for (Index i = 0; i < insts.size(); i++) { auto* inst = insts[i]; - if (!inst) + if (!inst) { continue; + } if (inUnreachableCode) { // Does the unreachable code end here? if (isControlFlowBarrier(inst)) { @@ -143,8 +144,9 @@ private: #endif for (Index i = 0; i < insts.size(); i++) { auto* inst = insts[i]; - if (!inst) + if (!inst) { continue; + } // First, consume values from the stack as required. auto consumed = getNumConsumedValues(inst); #ifdef STACK_OPT_DEBUG @@ -194,8 +196,9 @@ private: while (1) { // If there's an actual value in the way, we've failed. auto index = values[j]; - if (index == null) + if (index == null) { break; + } auto* set = insts[index]->origin->cast<SetLocal>(); if (set->index == get->index) { // This might be a proper set-get pair, where the set is @@ -224,8 +227,9 @@ private: } } // We failed here. Can we look some more? - if (j == 0) + if (j == 0) { break; + } j--; } } @@ -247,8 +251,9 @@ private: // a branch to that if body void removeUnneededBlocks() { for (auto*& inst : insts) { - if (!inst) + if (!inst) { continue; + } if (auto* block = inst->origin->dynCast<Block>()) { if (!BranchUtils::BranchSeeker::hasNamed(block, block->name)) { // TODO optimize, maybe run remove-unused-names diff --git a/src/passes/Vacuum.cpp b/src/passes/Vacuum.cpp index 8874ffed2..43a5f8a09 100644 --- a/src/passes/Vacuum.cpp +++ b/src/passes/Vacuum.cpp @@ -56,8 +56,9 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum>> { Expression* optimize(Expression* curr, bool resultUsed, bool typeMatters) { auto type = curr->type; // An unreachable node must not be changed. - if (type == unreachable) + if (type == unreachable) { return curr; + } // We iterate on possible replacements. If a replacement changes the type, // stop and go back. auto* prev = curr; @@ -104,8 +105,9 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum>> { case Expression::Id::ConstId: case Expression::Id::GetLocalId: case Expression::Id::GetGlobalId: { - if (!resultUsed) + if (!resultUsed) { return nullptr; + } return curr; } @@ -326,8 +328,9 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum>> { } void visitLoop(Loop* curr) { - if (curr->body->is<Nop>()) + if (curr->body->is<Nop>()) { ExpressionManipulator::nop(curr); + } } void visitDrop(Drop* curr) { diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp index ae940a56d..7cfb21dfe 100644 --- a/src/passes/pass.cpp +++ b/src/passes/pass.cpp @@ -43,8 +43,9 @@ void PassRegistry::registerPass(const char* name, } Pass* PassRegistry::createPass(std::string name) { - if (passInfos.find(name) == passInfos.end()) + if (passInfos.find(name) == passInfos.end()) { return nullptr; + } auto ret = passInfos[name].create(); ret->name = name; return ret; diff --git a/src/shell-interface.h b/src/shell-interface.h index 1bbe97dd9..c07203a92 100644 --- a/src/shell-interface.h +++ b/src/shell-interface.h @@ -147,13 +147,16 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface { LiteralList& arguments, Type result, ModuleInstance& instance) override { - if (index >= table.size()) + if (index >= table.size()) { trap("callTable overflow"); + } auto* func = instance.wasm.getFunctionOrNull(table[index]); - if (!func) + if (!func) { trap("uninitialized table element"); - if (func->params.size() != arguments.size()) + } + if (func->params.size() != arguments.size()) { trap("callIndirect: bad # of arguments"); + } for (size_t i = 0; i < func->params.size(); i++) { if (func->params[i] != arguments[i].type) { trap("callIndirect: bad argument type"); diff --git a/src/support/archive.cpp b/src/support/archive.cpp index 66f9c192a..1704fd88e 100644 --- a/src/support/archive.cpp +++ b/src/support/archive.cpp @@ -46,8 +46,9 @@ std::string ArchiveMemberHeader::getName() const { } auto* end = static_cast<const uint8_t*>(memchr(fileName, endChar, sizeof(fileName))); - if (!end) + if (!end) { end = fileName + sizeof(fileName); + } return std::string((char*)(fileName), end - fileName); } @@ -81,16 +82,18 @@ Archive::Archive(Buffer& b, bool& error) return; } child_iterator end = child_end(); - if (it == end) + if (it == end) { return; // Empty archive. + } const Child* c = &*it; auto increment = [&]() { ++it; error = it.hasError(); - if (error) + if (error) { return true; + } c = &*it; return false; }; @@ -98,15 +101,17 @@ Archive::Archive(Buffer& b, bool& error) std::string name = c->getRawName(); if (name == "/") { symbolTable = c->getBuffer(); - if (increment() || it == end) + if (increment() || it == end) { return; + } name = c->getRawName(); } if (name == "//") { stringTable = c->getBuffer(); - if (increment() || it == end) + if (increment() || it == end) { return; + } setFirstRegular(*c); return; } @@ -120,8 +125,9 @@ Archive::Archive(Buffer& b, bool& error) Archive::Child::Child(const Archive* parent, const uint8_t* data, bool* error) : parent(parent), data(data) { - if (!data) + if (!data) { return; + } len = sizeof(ArchiveMemberHeader) + getHeader()->getSize(); startOfFile = sizeof(ArchiveMemberHeader); } @@ -180,8 +186,9 @@ std::string Archive::Child::getName() const { } Archive::child_iterator Archive::child_begin(bool SkipInternal) const { - if (data.size() == 0) + if (data.size() == 0) { return child_end(); + } if (SkipInternal) { child_iterator it; diff --git a/src/support/colors.cpp b/src/support/colors.cpp index d0dc5ceb3..6d06b69fd 100644 --- a/src/support/colors.cpp +++ b/src/support/colors.cpp @@ -34,8 +34,9 @@ void Colors::outputColorCode(std::ostream& stream, const char* colorCode) { (isatty(STDOUT_FILENO) && (!getenv("COLORS") || getenv("COLORS")[0] != '0')); // implicit }(); - if (has_color && !colors_disabled) + if (has_color && !colors_disabled) { stream << colorCode; + } } #elif defined(_WIN32) #include <io.h> diff --git a/src/support/command-line.cpp b/src/support/command-line.cpp index f3b9ffe25..f1b4fca4d 100644 --- a/src/support/command-line.cpp +++ b/src/support/command-line.cpp @@ -37,8 +37,9 @@ void printWrap(std::ostream& os, int leftPad, const std::string& content) { } os << nextWord; space -= nextWord.size() + 1; - if (space > 0) + if (space > 0) { os << ' '; + } nextWord.clear(); if (content[i] == '\n') { os << '\n'; @@ -56,8 +57,9 @@ Options::Options(const std::string& command, const std::string& description) Arguments::Zero, [this, command, description](Options* o, const std::string&) { std::cout << command; - if (positional != Arguments::Zero) + if (positional != Arguments::Zero) { std::cout << ' ' << positionalName; + } std::cout << "\n\n"; printWrap(std::cout, 0, description); std::cout << "\n\nOptions:\n"; @@ -109,8 +111,9 @@ void Options::parse(int argc, const char* argv[]) { size_t positionalsSeen = 0; auto dashes = [](const std::string& s) { for (size_t i = 0;; ++i) { - if (s[i] != '-') + if (s[i] != '-') { return i; + } } }; for (size_t i = 1, e = argc; i != e; ++i) { @@ -147,9 +150,11 @@ void Options::parse(int argc, const char* argv[]) { currentOption = currentOption.substr(0, equal); } Option* option = nullptr; - for (auto& o : options) - if (o.longName == currentOption || o.shortName == currentOption) + for (auto& o : options) { + if (o.longName == currentOption || o.shortName == currentOption) { option = &o; + } + } if (!option) { std::cerr << "Unknown option '" << currentOption << "'\n"; exit(EXIT_FAILURE); @@ -181,8 +186,9 @@ void Options::parse(int argc, const char* argv[]) { break; case Arguments::Optional: if (!argument.size()) { - if (i + 1 != e) + if (i + 1 != e) { argument = argv[++i]; + } } break; } diff --git a/src/support/file.cpp b/src/support/file.cpp index 3af7af44b..b4c410b5e 100644 --- a/src/support/file.cpp +++ b/src/support/file.cpp @@ -22,8 +22,9 @@ #include <limits> std::vector<char> wasm::read_stdin(Flags::DebugOption debug) { - if (debug == Flags::Debug) + if (debug == Flags::Debug) { std::cerr << "Loading stdin..." << std::endl; + } std::vector<char> input; char c; while (std::cin.get(c) && !std::cin.eof()) { @@ -36,12 +37,14 @@ template<typename T> T wasm::read_file(const std::string& filename, Flags::BinaryOption binary, Flags::DebugOption debug) { - if (debug == Flags::Debug) + if (debug == Flags::Debug) { std::cerr << "Loading '" << filename << "'..." << std::endl; + } std::ifstream infile; std::ios_base::openmode flags = std::ifstream::in; - if (binary == Flags::Binary) + if (binary == Flags::Binary) { flags |= std::ifstream::binary; + } infile.open(filename, flags); if (!infile.is_open()) { std::cerr << "Failed opening '" << filename << "'" << std::endl; @@ -58,8 +61,9 @@ T wasm::read_file(const std::string& filename, exit(EXIT_FAILURE); } T input(size_t(insize) + (binary == Flags::Binary ? 0 : 1), '\0'); - if (size_t(insize) == 0) + if (size_t(insize) == 0) { return input; + } infile.seekg(0); infile.read(&input[0], insize); if (binary == Flags::Text) { @@ -88,11 +92,13 @@ wasm::Output::Output(const std::string& filename, } std::streambuf* buffer; if (filename.size()) { - if (debug == Flags::Debug) + if (debug == Flags::Debug) { std::cerr << "Opening '" << filename << "'" << std::endl; + } auto flags = std::ofstream::out | std::ofstream::trunc; - if (binary == Flags::Binary) + if (binary == Flags::Binary) { flags |= std::ofstream::binary; + } outfile.open(filename, flags); if (!outfile.is_open()) { std::cerr << "Failed opening '" << filename << "'" << std::endl; diff --git a/src/support/json.h b/src/support/json.h index 8f2edc04d..d31fcf59b 100644 --- a/src/support/json.h +++ b/src/support/json.h @@ -224,8 +224,9 @@ struct Value { } bool operator==(const Value& other) { - if (type != other.type) + if (type != other.type) { return false; + } switch (other.type) { case String: return str == other.str; @@ -273,8 +274,9 @@ struct Value { arr->push_back(temp); curr = temp->parse(curr); skip(); - if (*curr == ']') + if (*curr == ']') { break; + } assert(*curr == ','); curr++; skip(); @@ -316,8 +318,9 @@ struct Value { curr = value->parse(curr); (*obj)[key] = value; skip(); - if (*curr == '}') + if (*curr == '}') { break; + } assert(*curr == ','); curr++; skip(); @@ -348,8 +351,9 @@ struct Value { void setSize(size_t size) { assert(isArray()); auto old = arr->size(); - if (old != size) + if (old != size) { arr->resize(size); + } if (old < size) { for (auto i = old; i < size; i++) { (*arr)[i] = Ref(new Value()); @@ -376,8 +380,9 @@ struct Value { Ref back() { assert(isArray()); - if (arr->size() == 0) + if (arr->size() == 0) { return nullptr; + } return arr->back(); } diff --git a/src/support/path.cpp b/src/support/path.cpp index 7ae68d719..e9817aca9 100644 --- a/src/support/path.cpp +++ b/src/support/path.cpp @@ -36,8 +36,9 @@ std::string getPathSeparator() { std::string getBinaryenRoot() { auto* envVar = getenv("BINARYEN_ROOT"); - if (envVar) + if (envVar) { return envVar; + } return "."; } diff --git a/src/support/small_vector.h b/src/support/small_vector.h index dd6afb526..7f00bd4a6 100644 --- a/src/support/small_vector.h +++ b/src/support/small_vector.h @@ -109,11 +109,13 @@ public: } bool operator==(const SmallVector<T, N>& other) const { - if (usedFixed != other.usedFixed) + if (usedFixed != other.usedFixed) { return false; + } for (size_t i = 0; i < usedFixed; i++) { - if (fixed[i] != other.fixed[i]) + if (fixed[i] != other.fixed[i]) { return false; + } } return flexible == other.flexible; } diff --git a/src/support/sorted_vector.h b/src/support/sorted_vector.h index e26d5e3af..872c2f8fb 100644 --- a/src/support/sorted_vector.h +++ b/src/support/sorted_vector.h @@ -61,9 +61,9 @@ struct SortedVector : public std::vector<Index> { void insert(Index x) { auto it = std::lower_bound(begin(), end(), x); - if (it == end()) + if (it == end()) { push_back(x); - else if (*it > x) { + } else if (*it > x) { Index i = it - begin(); resize(size() + 1); std::move_backward(begin() + i, begin() + size() - 1, end()); @@ -107,8 +107,9 @@ struct SortedVector : public std::vector<Index> { void dump(const char* str = nullptr) const { std::cout << "SortedVector " << (str ? str : "") << ": "; - for (auto x : *this) + for (auto x : *this) { std::cout << x << " "; + } std::cout << '\n'; } }; diff --git a/src/support/threads.cpp b/src/support/threads.cpp index 785994b4e..ab9de4175 100644 --- a/src/support/threads.cpp +++ b/src/support/threads.cpp @@ -114,8 +114,9 @@ std::mutex ThreadPool::workMutex; std::mutex ThreadPool::threadMutex; void ThreadPool::initialize(size_t num) { - if (num == 1) + if (num == 1) { return; // no multiple cores, don't create threads + } DEBUG_POOL("initialize()\n"); std::unique_lock<std::mutex> lock(threadMutex); // initial state before first resetThreadsAreReady() diff --git a/src/tools/asm2wasm.cpp b/src/tools/asm2wasm.cpp index 843106ffd..b1196850b 100644 --- a/src/tools/asm2wasm.cpp +++ b/src/tools/asm2wasm.cpp @@ -212,13 +212,15 @@ int main(int argc, const char* argv[]) { : Flags::Release)); char* start = pre.process(input.data()); - if (options.debug) + if (options.debug) { std::cerr << "parsing..." << std::endl; + } cashew::Parser<Ref, DotZeroValueBuilder> builder; Ref asmjs = builder.parseToplevel(start); - if (options.debug) + if (options.debug) { std::cerr << "wasming..." << std::endl; + } Module wasm; // set up memory @@ -294,8 +296,9 @@ int main(int argc, const char* argv[]) { } } - if (options.debug) + if (options.debug) { std::cerr << "emitting..." << std::endl; + } ModuleWriter writer; writer.setDebug(options.debug); writer.setDebugInfo(options.passOptions.debugInfo); @@ -307,6 +310,7 @@ int main(int argc, const char* argv[]) { } writer.write(wasm, options.extra["output"]); - if (options.debug) + if (options.debug) { std::cerr << "done." << std::endl; + } } diff --git a/src/tools/execution-results.h b/src/tools/execution-results.h index 2a42b941b..13771a69d 100644 --- a/src/tools/execution-results.h +++ b/src/tools/execution-results.h @@ -62,8 +62,9 @@ struct ExecutionResults { // execute all exported methods (that are therefore preserved through // opts) for (auto& exp : wasm.exports) { - if (exp->kind != ExternalKind::Function) + if (exp->kind != ExternalKind::Function) { continue; + } std::cout << "[fuzz-exec] calling " << exp->name << "\n"; auto* func = wasm.getFunction(exp->value); if (func->result != none) { diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h index f5b548ec6..16b04fe02 100644 --- a/src/tools/fuzzing.h +++ b/src/tools/fuzzing.h @@ -463,8 +463,9 @@ private: } Expression* makeDeNanOp(Expression* expr) { - if (allowNaNs) + if (allowNaNs) { return expr; + } if (expr->type == f32) { return builder.makeCall("deNan32", {expr}, f32); } else if (expr->type == f64) { @@ -566,8 +567,9 @@ private: void recombine(Function* func) { // Don't always do this. - if (oneIn(2)) + if (oneIn(2)) { return; + } // First, scan and group all expressions by type. struct Scanner : public PostWalker<Scanner, UnifiedExpressionVisitor<Scanner>> { @@ -583,8 +585,9 @@ private: // Potentially trim the list of possible picks, so replacements are more // likely to collide. for (auto& pair : scanner.exprsByType) { - if (oneIn(2)) + if (oneIn(2)) { continue; + } auto& list = pair.second; std::vector<Expression*> trimmed; size_t num = upToSquared(list.size()); @@ -630,8 +633,9 @@ private: void mutate(Function* func) { // Don't always do this. - if (oneIn(2)) + if (oneIn(2)) { return; + } struct Modder : public PostWalker<Modder, UnifiedExpressionVisitor<Modder>> { Module& wasm; @@ -688,8 +692,9 @@ private: void visitSwitch(Switch* curr) { for (auto name : curr->targets) { - if (replaceIfInvalid(name)) + if (replaceIfInvalid(name)) { return; + } } replaceIfInvalid(curr->default_); } @@ -708,23 +713,27 @@ private: void replace() { replaceCurrent(parent.makeTrivial(getCurrent()->type)); } bool hasBreakTarget(Name name) { - if (controlFlowStack.empty()) + if (controlFlowStack.empty()) { return false; + } Index i = controlFlowStack.size() - 1; while (1) { auto* curr = controlFlowStack[i]; if (Block* block = curr->template dynCast<Block>()) { - if (name == block->name) + if (name == block->name) { return true; + } } else if (Loop* loop = curr->template dynCast<Loop>()) { - if (name == loop->name) + if (name == loop->name) { return true; + } } else { // an if, ignorable assert(curr->template is<If>()); } - if (i == 0) + if (i == 0) { return false; + } i--; } } @@ -754,8 +763,9 @@ private: invocations.push_back(makeMemoryHashLogging()); } } - if (invocations.empty()) + if (invocations.empty()) { return; + } auto* invoker = new Function; invoker->name = func->name.str + std::string("_invoker"); invoker->result = none; @@ -821,20 +831,27 @@ private: Expression* _makeConcrete(Type type) { auto choice = upTo(100); - if (choice < 10) + if (choice < 10) { return makeConst(type); - if (choice < 30) + } + if (choice < 30) { return makeSetLocal(type); - if (choice < 50) + } + if (choice < 50) { return makeGetLocal(type); - if (choice < 60) + } + if (choice < 60) { return makeBlock(type); - if (choice < 70) + } + if (choice < 70) { return makeIf(type); - if (choice < 80) + } + if (choice < 80) { return makeLoop(type); - if (choice < 90) + } + if (choice < 90) { return makeBreak(type); + } using Self = TranslateToFuzzReader; auto options = FeatureOptions<Expression* (Self::*)(Type)>() .add(FeatureSet::MVP, @@ -869,16 +886,21 @@ private: } } choice = upTo(100); - if (choice < 50) + if (choice < 50) { return makeSetLocal(none); - if (choice < 60) + } + if (choice < 60) { return makeBlock(none); - if (choice < 70) + } + if (choice < 70) { return makeIf(none); - if (choice < 80) + } + if (choice < 80) { return makeLoop(none); - if (choice < 90) + } + if (choice < 90) { return makeBreak(none); + } using Self = TranslateToFuzzReader; auto options = FeatureOptions<Expression* (Self::*)(Type)>() .add(FeatureSet::MVP, @@ -1056,8 +1078,9 @@ private: } Expression* makeBreak(Type type) { - if (breakableStack.empty()) + if (breakableStack.empty()) { return makeTrivial(type); + } Expression* condition = nullptr; if (type != unreachable) { hangStack.push_back(nullptr); @@ -1110,18 +1133,21 @@ private: } switch (conditions) { case 0: { - if (!oneIn(4)) + if (!oneIn(4)) { continue; + } break; } case 1: { - if (!oneIn(2)) + if (!oneIn(2)) { continue; + } break; } default: { - if (oneIn(conditions + 1)) + if (oneIn(conditions + 1)) { continue; + } } } return builder.makeBreak(name); @@ -1142,8 +1168,9 @@ private: if (!wasm.functions.empty() && !oneIn(wasm.functions.size())) { target = vectorPick(wasm.functions).get(); } - if (target->result != type) + if (target->result != type) { continue; + } // we found one! std::vector<Expression*> args; for (auto argType : target->params) { @@ -1157,8 +1184,9 @@ private: Expression* makeCallIndirect(Type type) { auto& data = wasm.table.segments[0].data; - if (data.empty()) + if (data.empty()) { return make(type); + } // look for a call target with the right type Index start = upTo(data.size()); Index i = start; @@ -1170,10 +1198,12 @@ private: break; } i++; - if (i == data.size()) + if (i == data.size()) { i = 0; - if (i == start) + } + if (i == start) { return make(type); + } } // with high probability, make sure the type is valid otherwise, most are // going to trap @@ -1193,8 +1223,9 @@ private: Expression* makeGetLocal(Type type) { auto& locals = typeLocals[type]; - if (locals.empty()) + if (locals.empty()) { return makeConst(type); + } return builder.makeGetLocal(vectorPick(locals), type); } @@ -1207,8 +1238,9 @@ private: valueType = getConcreteType(); } auto& locals = typeLocals[valueType]; - if (locals.empty()) + if (locals.empty()) { return makeTrivial(type); + } auto* value = make(valueType); if (tee) { return builder.makeTeeLocal(vectorPick(locals), value); @@ -1219,8 +1251,9 @@ private: Expression* makeGetGlobal(Type type) { auto& globals = globalsByType[type]; - if (globals.empty()) + if (globals.empty()) { return makeConst(type); + } return builder.makeGetGlobal(vectorPick(globals), type); } @@ -1228,8 +1261,9 @@ private: assert(type == none); type = getConcreteType(); auto& globals = globalsByType[type]; - if (globals.empty()) + if (globals.empty()) { return makeTrivial(none); + } auto* value = make(type); return builder.makeSetGlobal(vectorPick(globals), value); } @@ -1300,13 +1334,16 @@ private: } Expression* makeLoad(Type type) { - if (!allowMemory) + if (!allowMemory) { return makeTrivial(type); + } auto* ret = makeNonAtomicLoad(type); - if (type != i32 && type != i64) + if (type != i32 && type != i64) { return ret; - if (!wasm.features.hasAtomics() || oneIn(2)) + } + if (!wasm.features.hasAtomics() || oneIn(2)) { return ret; + } // make it atomic auto* load = ret->cast<Load>(); wasm.memory.shared = true; @@ -1321,8 +1358,9 @@ private: // make a normal store, then make it unreachable auto* ret = makeNonAtomicStore(getConcreteType()); auto* store = ret->dynCast<Store>(); - if (!store) + if (!store) { return ret; + } switch (upTo(3)) { case 0: store->ptr = make(unreachable); @@ -1395,16 +1433,20 @@ private: } Expression* makeStore(Type type) { - if (!allowMemory) + if (!allowMemory) { return makeTrivial(type); + } auto* ret = makeNonAtomicStore(type); auto* store = ret->dynCast<Store>(); - if (!store) + if (!store) { return ret; - if (store->value->type != i32 && store->value->type != i64) + } + if (store->value->type != i32 && store->value->type != i64) { return store; - if (!wasm.features.hasAtomics() || oneIn(2)) + } + if (!wasm.features.hasAtomics() || oneIn(2)) { return store; + } // make it atomic wasm.memory.shared = true; store->isAtomic = true; @@ -2051,8 +2093,9 @@ private: Expression* makeSwitch(Type type) { assert(type == unreachable); - if (breakableStack.empty()) + if (breakableStack.empty()) { return make(type); + } // we need to find proper targets to break to; try a bunch int tries = TRIES; std::vector<Name> names; @@ -2103,8 +2146,9 @@ private: Expression* makeAtomic(Type type) { assert(wasm.features.hasAtomics()); - if (!allowMemory) + if (!allowMemory) { return makeTrivial(type); + } wasm.memory.shared = true; if (type == i32 && oneIn(2)) { if (ATOMIC_WAITS && oneIn(2)) { @@ -2330,8 +2374,9 @@ private: } Expression* makeBulkMemory(Type type) { - if (!allowMemory) + if (!allowMemory) { return makeTrivial(type); + } assert(wasm.features.hasBulkMemory()); assert(type == none); switch (upTo(4)) { @@ -2348,8 +2393,9 @@ private: } Expression* makeMemoryInit() { - if (!allowMemory) + if (!allowMemory) { return makeTrivial(none); + } uint32_t segment = upTo(wasm.memory.segments.size()); size_t totalSize = wasm.memory.segments[segment].data.size(); size_t offsetVal = upTo(totalSize); @@ -2361,14 +2407,16 @@ private: } Expression* makeDataDrop() { - if (!allowMemory) + if (!allowMemory) { return makeTrivial(none); + } return builder.makeDataDrop(upTo(wasm.memory.segments.size())); } Expression* makeMemoryCopy() { - if (!allowMemory) + if (!allowMemory) { return makeTrivial(none); + } Expression* dest = makePointer(); Expression* source = makePointer(); Expression* size = make(i32); @@ -2376,8 +2424,9 @@ private: } Expression* makeMemoryFill() { - if (!allowMemory) + if (!allowMemory) { return makeTrivial(none); + } Expression* dest = makePointer(); Expression* value = makePointer(); Expression* size = make(i32); @@ -2428,8 +2477,9 @@ private: // this isn't a perfectly uniform distribution, but it's fast // and reasonable Index upTo(Index x) { - if (x == 0) + if (x == 0) { return 0; + } Index raw; if (x <= 255) { raw = get(); @@ -2486,8 +2536,9 @@ private: template<typename T, typename... Args> T pickGivenNum(size_t num, T first, Args... args) { - if (num == 0) + if (num == 0) { return first; + } return pickGivenNum<T>(num - 1, args...); } diff --git a/src/tools/js-wrapper.h b/src/tools/js-wrapper.h index e39a015d6..32b46affa 100644 --- a/src/tools/js-wrapper.h +++ b/src/tools/js-wrapper.h @@ -83,8 +83,9 @@ static std::string generateJSWrapper(Module& wasm) { "});\n"; for (auto& exp : wasm.exports) { auto* func = wasm.getFunctionOrNull(exp->value); - if (!func) + if (!func) { continue; // something exported other than a function + } ret += "if (instance.exports.hangLimitInitializer) " "instance.exports.hangLimitInitializer();\n"; ret += "try {\n"; diff --git a/src/tools/optimization-options.h b/src/tools/optimization-options.h index 6fa9aac36..30f59f04d 100644 --- a/src/tools/optimization-options.h +++ b/src/tools/optimization-options.h @@ -177,8 +177,9 @@ struct OptimizationOptions : public ToolOptions { void runPasses(Module& wasm) { PassRunner passRunner(&wasm, passOptions); - if (debug) + if (debug) { passRunner.setDebug(true); + } for (auto& pass : passes) { if (pass == DEFAULT_OPT_PASSES) { passRunner.addDefaultOptimizationPasses(); diff --git a/src/tools/spec-wrapper.h b/src/tools/spec-wrapper.h index 516ce17a9..d481f0fa8 100644 --- a/src/tools/spec-wrapper.h +++ b/src/tools/spec-wrapper.h @@ -25,8 +25,9 @@ static std::string generateSpecWrapper(Module& wasm) { std::string ret; for (auto& exp : wasm.exports) { auto* func = wasm.getFunctionOrNull(exp->value); - if (!func) + if (!func) { continue; // something exported other than a function + } ret += std::string("(invoke \"hangLimitInitializer\") (invoke \"") + exp->name.str + "\" "; for (Type param : func->params) { diff --git a/src/tools/wasm-as.cpp b/src/tools/wasm-as.cpp index 253a93b3b..d45f10f81 100644 --- a/src/tools/wasm-as.cpp +++ b/src/tools/wasm-as.cpp @@ -105,12 +105,14 @@ int main(int argc, const char* argv[]) { Module wasm; try { - if (options.debug) + if (options.debug) { std::cerr << "s-parsing..." << std::endl; + } SExpressionParser parser(const_cast<char*>(input.c_str())); Element& root = *parser.root; - if (options.debug) + if (options.debug) { std::cerr << "w-parsing..." << std::endl; + } SExpressionWasmBuilder builder(wasm, *root[0]); } catch (ParseException& p) { p.dump(std::cerr); @@ -120,8 +122,9 @@ int main(int argc, const char* argv[]) { options.applyFeatures(wasm); if (options.extra["validate"] != "none") { - if (options.debug) + if (options.debug) { std::cerr << "Validating..." << std::endl; + } if (!wasm::WasmValidator().validate( wasm, WasmValidator::Globally | @@ -131,8 +134,9 @@ int main(int argc, const char* argv[]) { } } - if (options.debug) + if (options.debug) { std::cerr << "writing..." << std::endl; + } ModuleWriter writer; writer.setBinary(true); writer.setDebugInfo(debugInfo); @@ -145,6 +149,7 @@ int main(int argc, const char* argv[]) { } writer.write(wasm, options.extra["output"]); - if (options.debug) + if (options.debug) { std::cerr << "Done." << std::endl; + } } diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp index 2050b3ebc..6a967ece7 100644 --- a/src/tools/wasm-ctor-eval.cpp +++ b/src/tools/wasm-ctor-eval.cpp @@ -441,8 +441,9 @@ int main(int argc, const char* argv[]) { Module wasm; { - if (options.debug) + if (options.debug) { std::cerr << "reading...\n"; + } ModuleReader reader; reader.setDebug(options.debug); @@ -483,8 +484,9 @@ int main(int argc, const char* argv[]) { } if (options.extra.count("output") > 0) { - if (options.debug) + if (options.debug) { std::cerr << "writing..." << std::endl; + } ModuleWriter writer; writer.setDebug(options.debug); writer.setBinary(emitBinary); diff --git a/src/tools/wasm-dis.cpp b/src/tools/wasm-dis.cpp index 5b9cb9804..1dbe97656 100644 --- a/src/tools/wasm-dis.cpp +++ b/src/tools/wasm-dis.cpp @@ -56,8 +56,9 @@ int main(int argc, const char* argv[]) { }); options.parse(argc, argv); - if (options.debug) + if (options.debug) { std::cerr << "parsing binary..." << std::endl; + } Module wasm; try { ModuleReader().readBinary(options.extra["infile"], wasm, sourceMapFilename); @@ -71,14 +72,16 @@ int main(int argc, const char* argv[]) { Fatal() << "error in parsing wasm source mapping"; } - if (options.debug) + if (options.debug) { std::cerr << "Printing..." << std::endl; + } Output output(options.extra["output"], Flags::Text, options.debug ? Flags::Debug : Flags::Release); WasmPrinter::printModule(&wasm, output.getStream()); output << '\n'; - if (options.debug) + if (options.debug) { std::cerr << "Done." << std::endl; + } } diff --git a/src/tools/wasm-emscripten-finalize.cpp b/src/tools/wasm-emscripten-finalize.cpp index a23ba1c5a..e524e4732 100644 --- a/src/tools/wasm-emscripten-finalize.cpp +++ b/src/tools/wasm-emscripten-finalize.cpp @@ -193,12 +193,14 @@ int main(int argc, const char* argv[]) { std::vector<Name> initializerFunctions; if (wasm.table.imported()) { - if (wasm.table.base != "table") + if (wasm.table.base != "table") { wasm.table.base = Name("table"); + } } if (wasm.memory.imported()) { - if (wasm.table.base != "memory") + if (wasm.table.base != "memory") { wasm.memory.base = Name("memory"); + } } wasm.updateMaps(); diff --git a/src/tools/wasm-metadce.cpp b/src/tools/wasm-metadce.cpp index a6f5bb012..c87da8c9a 100644 --- a/src/tools/wasm-metadce.cpp +++ b/src/tools/wasm-metadce.cpp @@ -230,8 +230,9 @@ struct MetaDCEGraph { MetaDCEGraph* parent; void handleGlobal(Name name) { - if (!getFunction()) + if (!getFunction()) { return; // non-function stuff (initializers) are handled separately + } Name dceName; if (!getModule()->getGlobal(name)->imported()) { // its a global @@ -465,8 +466,9 @@ int main(int argc, const char* argv[]) { Module wasm; { - if (options.debug) + if (options.debug) { std::cerr << "reading...\n"; + } ModuleReader reader; reader.setDebug(options.debug); diff --git a/src/tools/wasm-opt.cpp b/src/tools/wasm-opt.cpp index e9f369d22..f7e8b5918 100644 --- a/src/tools/wasm-opt.cpp +++ b/src/tools/wasm-opt.cpp @@ -203,8 +203,9 @@ int main(int argc, const char* argv[]) { Module wasm; - if (options.debug) + if (options.debug) { std::cerr << "reading...\n"; + } if (!translateToFuzz) { ModuleReader reader; @@ -280,9 +281,10 @@ int main(int argc, const char* argv[]) { std::string firstOutput; if (extraFuzzCommand.size() > 0 && options.extra.count("output") > 0) { - if (options.debug) + if (options.debug) { std::cerr << "writing binary before opts, for extra fuzz command..." << std::endl; + } ModuleWriter writer; writer.setDebug(options.debug); writer.setBinary(emitBinary); @@ -316,8 +318,9 @@ int main(int argc, const char* argv[]) { } if (options.runningPasses()) { - if (options.debug) + if (options.debug) { std::cerr << "running passes...\n"; + } auto runPasses = [&]() { options.runPasses(*curr); if (options.passOptions.validate) { @@ -340,13 +343,15 @@ int main(int argc, const char* argv[]) { }; auto lastSize = getSize(); while (1) { - if (options.debug) + if (options.debug) { std::cerr << "running iteration for convergence (" << lastSize << ")...\n"; + } runPasses(); auto currSize = getSize(); - if (currSize >= lastSize) + if (currSize >= lastSize) { break; + } lastSize = currSize; } } @@ -359,8 +364,9 @@ int main(int argc, const char* argv[]) { if (options.extra.count("output") == 0) { std::cerr << "(no output file specified, not emitting output)\n"; } else { - if (options.debug) + if (options.debug) { std::cerr << "writing..." << std::endl; + } ModuleWriter writer; writer.setDebug(options.debug); writer.setBinary(emitBinary); diff --git a/src/tools/wasm-reduce.cpp b/src/tools/wasm-reduce.cpp index 87f64c1ae..54a915ec0 100644 --- a/src/tools/wasm-reduce.cpp +++ b/src/tools/wasm-reduce.cpp @@ -285,10 +285,12 @@ struct Reducer // TODO(tlively): -all should be replaced with an option to use the // existing feature set, once implemented. currCommand += working + " -all -o " + test + " " + pass; - if (debugInfo) + if (debugInfo) { currCommand += " -g "; - if (verbose) + } + if (verbose) { std::cerr << "| trying pass command: " << currCommand << "\n"; + } if (!ProgramResult(currCommand).failed()) { auto newSize = file_size(test); if (newSize < oldSize) { @@ -306,8 +308,9 @@ struct Reducer } } } - if (verbose) + if (verbose) { std::cerr << "| done with passes for now\n"; + } } // does one pass of slow and destructive reduction. returns whether it @@ -400,10 +403,12 @@ struct Reducer } auto* curr = getCurrent(); // std::cerr << "try " << curr << " => " << with << '\n'; - if (curr->type != with->type) + if (curr->type != with->type) { return false; - if (!shouldTryToReduce()) + } + if (!shouldTryToReduce()) { return false; + } replaceCurrent(with); if (!writeAndTestReduction()) { replaceCurrent(curr); @@ -425,10 +430,12 @@ struct Reducer if (!isOkReplacement(with)) { return false; } - if (child->type != with->type) + if (child->type != with->type) { return false; - if (!shouldTryToReduce()) + } + if (!shouldTryToReduce()) { return false; + } auto* before = child; child = with; if (!writeAndTestReduction()) { @@ -443,8 +450,9 @@ struct Reducer } std::string getLocation() { - if (getFunction()) + if (getFunction()) { return getFunction()->name.str; + } return "(non-function context)"; } @@ -455,15 +463,18 @@ struct Reducer void visitExpression(Expression* curr) { // type-based reductions if (curr->type == none) { - if (tryToReduceCurrentToNop()) + if (tryToReduceCurrentToNop()) { return; + } } else if (isConcreteType(curr->type)) { - if (tryToReduceCurrentToConst()) + if (tryToReduceCurrentToConst()) { return; + } } else { assert(curr->type == unreachable); - if (tryToReduceCurrentToUnreachable()) + if (tryToReduceCurrentToUnreachable()) { return; + } } // specific reductions if (auto* iff = curr->dynCast<If>()) { @@ -500,14 +511,16 @@ struct Reducer } } } else if (auto* block = curr->dynCast<Block>()) { - if (!shouldTryToReduce()) + if (!shouldTryToReduce()) { return; + } // replace a singleton auto& list = block->list; if (list.size() == 1 && !BranchUtils::BranchSeeker::hasNamed(block, block->name)) { - if (tryToReplaceCurrent(block->list[0])) + if (tryToReplaceCurrent(block->list[0])) { return; + } } // try to get rid of nops Index i = 0; @@ -544,21 +557,25 @@ struct Reducer // Finally, try to replace with a child. for (auto* child : ChildIterator(curr)) { if (isConcreteType(child->type) && curr->type == none) { - if (tryToReplaceCurrent(builder->makeDrop(child))) + if (tryToReplaceCurrent(builder->makeDrop(child))) { return; + } } else { - if (tryToReplaceCurrent(child)) + if (tryToReplaceCurrent(child)) { return; + } } } // If that didn't work, try to replace with a child + a unary conversion if (isConcreteType(curr->type) && !curr->is<Unary>()) { // but not if it's already unary for (auto* child : ChildIterator(curr)) { - if (child->type == curr->type) + if (child->type == curr->type) { continue; // already tried - if (!isConcreteType(child->type)) + } + if (!isConcreteType(child->type)) { continue; // no conversion + } Expression* fixed = nullptr; switch (curr->type) { case i32: { @@ -652,8 +669,9 @@ struct Reducer WASM_UNREACHABLE(); } assert(fixed->type == curr->type); - if (tryToReplaceCurrent(fixed)) + if (tryToReplaceCurrent(fixed)) { return; + } } } } @@ -684,8 +702,9 @@ struct Reducer first = item; break; } - if (!first.isNull()) + if (!first.isNull()) { break; + } } visitSegmented(curr, first, 100); } @@ -706,12 +725,14 @@ struct Reducer // when we succeed, try to shrink by more and more, similar to bisection size_t skip = 1; for (size_t i = 0; i < data.size() && !data.empty(); i++) { - if (!justShrank && !shouldTryToReduce(bonus)) + if (!justShrank && !shouldTryToReduce(bonus)) { continue; + } auto save = data; for (size_t j = 0; j < skip; j++) { - if (!data.empty()) + if (!data.empty()) { data.pop_back(); + } } auto justShrank = writeAndTestReduction(); if (justShrank) { @@ -727,13 +748,16 @@ struct Reducer } // the "opposite" of shrinking: copy a 'zero' element for (auto& segment : curr->segments) { - if (segment.data.empty()) + if (segment.data.empty()) { continue; + } for (auto& item : segment.data) { - if (!shouldTryToReduce(bonus)) + if (!shouldTryToReduce(bonus)) { continue; - if (item == zero) + } + if (item == zero) { continue; + } auto save = item; item = zero; if (writeAndTestReduction()) { @@ -766,8 +790,9 @@ struct Reducer for (size_t i = 0; i < functionNames.size(); i++) { if (!justRemoved && functionsWeTriedToRemove.count(functionNames[i]) == 1 && - !shouldTryToReduce(std::max((factor / 100) + 1, 1000))) + !shouldTryToReduce(std::max((factor / 100) + 1, 1000))) { continue; + } std::vector<Name> names; for (size_t j = 0; names.size() < skip && i + j < functionNames.size(); j++) { @@ -777,8 +802,9 @@ struct Reducer functionsWeTriedToRemove.insert(name); } } - if (names.size() == 0) + if (names.size() == 0) { continue; + } std::cout << "| try to remove " << names.size() << " functions (skip: " << skip << ")\n"; justRemoved = tryToRemoveFunctions(names); @@ -798,8 +824,9 @@ struct Reducer } skip = 1; for (size_t i = 0; i < exports.size(); i++) { - if (!shouldTryToReduce(std::max((factor / 100) + 1, 1000))) + if (!shouldTryToReduce(std::max((factor / 100) + 1, 1000))) { continue; + } std::vector<Export> currExports; for (size_t j = 0; currExports.size() < skip && i + j < exports.size(); j++) { @@ -891,11 +918,13 @@ struct Reducer break; } } - if (!other.isNull()) + if (!other.isNull()) { break; + } } - if (other.isNull()) + if (other.isNull()) { return; // we failed to find a replacement + } for (auto& segment : curr->segments) { for (auto& name : segment.data) { if (names.count(name)) { @@ -929,10 +958,12 @@ struct Reducer // try to replace condition with always true and always false void handleCondition(Expression*& condition) { - if (!condition) + if (!condition) { return; - if (condition->is<Const>()) + } + if (condition->is<Const>()) { return; + } auto* c = builder->makeConst(Literal(int32_t(0))); if (!tryToReplaceChild(condition, c)) { c->value = Literal(int32_t(1)); @@ -942,8 +973,9 @@ struct Reducer bool tryToReduceCurrentToNop() { auto* curr = getCurrent(); - if (curr->is<Nop>()) + if (curr->is<Nop>()) { return false; + } // try to replace with a trivial value Nop nop; if (tryToReplaceCurrent(&nop)) { @@ -956,12 +988,14 @@ struct Reducer // try to replace a concrete value with a trivial constant bool tryToReduceCurrentToConst() { auto* curr = getCurrent(); - if (curr->is<Const>()) + if (curr->is<Const>()) { return false; + } // try to replace with a trivial value Const* c = builder->makeConst(Literal(int32_t(0))); - if (tryToReplaceCurrent(c)) + if (tryToReplaceCurrent(c)) { return true; + } c->value = Literal::makeFromInt32(1, curr->type); c->type = curr->type; return tryToReplaceCurrent(c); @@ -969,8 +1003,9 @@ struct Reducer bool tryToReduceCurrentToUnreachable() { auto* curr = getCurrent(); - if (curr->is<Unreachable>()) + if (curr->is<Unreachable>()) { return false; + } // try to replace with a trivial value Unreachable un; if (tryToReplaceCurrent(&un)) { @@ -1065,10 +1100,12 @@ int main(int argc, const char* argv[]) { [&](Options* o, const std::string& argument) { input = argument; }); options.parse(argc, argv); - if (test.size() == 0) + if (test.size() == 0) { Fatal() << "test file not provided\n"; - if (working.size() == 0) + } + if (working.size() == 0) { Fatal() << "working file not provided\n"; + } if (!binary) { Colors::disable(); @@ -1124,8 +1161,9 @@ int main(int argc, const char* argv[]) { // feature set, once implemented. auto cmd = Path::getBinaryenBinaryTool("wasm-opt") + " " + input + " -all -o " + test; - if (!binary) + if (!binary) { cmd += " -S"; + } ProgramResult readWrite(cmd); if (readWrite.failed()) { stopIfNotForced("failed to read and write the binary", readWrite); @@ -1166,8 +1204,9 @@ int main(int argc, const char* argv[]) { std::cerr << "| after pass reduction: " << newSize << "\n"; // always stop after a pass reduction attempt, for final cleanup - if (stopping) + if (stopping) { break; + } // check if the full cycle (destructive/passes) has helped or not if (lastPostPassesSize && newSize >= lastPostPassesSize) { @@ -1208,8 +1247,9 @@ int main(int argc, const char* argv[]) { while (1) { std::cerr << "| reduce destructively... (factor: " << factor << ")\n"; lastDestructiveReductions = reducer.reduceDestructively(factor); - if (lastDestructiveReductions > 0) + if (lastDestructiveReductions > 0) { break; + } // we failed to reduce destructively if (factor == 1) { stopping = true; diff --git a/src/tools/wasm-shell.cpp b/src/tools/wasm-shell.cpp index 6141b1a37..652b3a352 100644 --- a/src/tools/wasm-shell.cpp +++ b/src/tools/wasm-shell.cpp @@ -125,8 +125,9 @@ static void run_asserts(Name moduleName, while (*i < root->size()) { Element& curr = *(*root)[*i]; IString id = curr[0]->str(); - if (id == MODULE) + if (id == MODULE) { break; + } *checked = true; Colors::red(std::cerr); std::cerr << *i << '/' << (root->size() - 1); @@ -228,8 +229,9 @@ static void run_asserts(Name moduleName, } } } - if (id == ASSERT_TRAP) + if (id == ASSERT_TRAP) { assert(trapped); + } } *i += 1; } @@ -281,8 +283,9 @@ int main(int argc, const char* argv[]) { bool checked = false; try { - if (options.debug) + if (options.debug) { std::cerr << "parsing text to s-expressions...\n"; + } SExpressionParser parser(input.data()); Element& root = *parser.root; @@ -299,8 +302,9 @@ int main(int argc, const char* argv[]) { } IString id = curr[0]->str(); if (id == MODULE) { - if (options.debug) + if (options.debug) { std::cerr << "parsing s-expressions to wasm...\n"; + } Colors::green(std::cerr); std::cerr << "BUILDING MODULE [line: " << curr.line << "]\n"; Colors::normal(std::cerr); diff --git a/src/tools/wasm2js.cpp b/src/tools/wasm2js.cpp index 6e4656878..823ab7f96 100644 --- a/src/tools/wasm2js.cpp +++ b/src/tools/wasm2js.cpp @@ -694,8 +694,9 @@ int main(int argc, const char* argv[]) { o->extra["infile"] = argument; }); options.parse(argc, argv); - if (options.debug) + if (options.debug) { flags.debug = true; + } Element* root = nullptr; Module wasm; @@ -728,13 +729,15 @@ int main(int argc, const char* argv[]) { Flags::Text, options.debug ? Flags::Debug : Flags::Release)); - if (options.debug) + if (options.debug) { std::cerr << "s-parsing..." << std::endl; + } sexprParser = make_unique<SExpressionParser>(input.data()); root = sexprParser->root; - if (options.debug) + if (options.debug) { std::cerr << "w-parsing..." << std::endl; + } sexprBuilder = make_unique<SExpressionWasmBuilder>(wasm, *(*root)[0]); } } catch (ParseException& p) { @@ -752,8 +755,9 @@ int main(int argc, const char* argv[]) { } } - if (options.debug) + if (options.debug) { std::cerr << "j-printing..." << std::endl; + } Output output(options.extra["output"], Flags::Text, options.debug ? Flags::Debug : Flags::Release); @@ -764,6 +768,7 @@ int main(int argc, const char* argv[]) { emitWasm(wasm, output, flags, options.passOptions, "asmFunc"); } - if (options.debug) + if (options.debug) { std::cerr << "done." << std::endl; + } } diff --git a/src/wasm-binary.h b/src/wasm-binary.h index aa13685e1..6f159740c 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -118,8 +118,9 @@ template<typename T, typename MiniT> struct LEB { } } value |= significant_payload << shift; - if (last) + if (last) { break; + } shift += 7; if (size_t(shift) >= sizeof(T) * 8) { throw ParseException("LEB overflow"); @@ -160,22 +161,25 @@ public: BufferWithRandomAccess(bool debug = false) : debug(debug) {} BufferWithRandomAccess& operator<<(int8_t x) { - if (debug) + if (debug) { std::cerr << "writeInt8: " << (int)(uint8_t)x << " (at " << size() << ")" << std::endl; + } push_back(x); return *this; } BufferWithRandomAccess& operator<<(int16_t x) { - if (debug) + if (debug) { std::cerr << "writeInt16: " << x << " (at " << size() << ")" << std::endl; + } push_back(x & 0xff); push_back(x >> 8); return *this; } BufferWithRandomAccess& operator<<(int32_t x) { - if (debug) + if (debug) { std::cerr << "writeInt32: " << x << " (at " << size() << ")" << std::endl; + } push_back(x & 0xff); x >>= 8; push_back(x & 0xff); @@ -186,8 +190,9 @@ public: return *this; } BufferWithRandomAccess& operator<<(int64_t x) { - if (debug) + if (debug) { std::cerr << "writeInt64: " << x << " (at " << size() << ")" << std::endl; + } push_back(x & 0xff); x >>= 8; push_back(x & 0xff); @@ -272,27 +277,31 @@ public: BufferWithRandomAccess& operator<<(uint64_t x) { return *this << (int64_t)x; } BufferWithRandomAccess& operator<<(float x) { - if (debug) + if (debug) { std::cerr << "writeFloat32: " << x << " (at " << size() << ")" << std::endl; + } return *this << Literal(x).reinterpreti32(); } BufferWithRandomAccess& operator<<(double x) { - if (debug) + if (debug) { std::cerr << "writeFloat64: " << x << " (at " << size() << ")" << std::endl; + } return *this << Literal(x).reinterpreti64(); } void writeAt(size_t i, uint16_t x) { - if (debug) + if (debug) { std::cerr << "backpatchInt16: " << x << " (at " << i << ")" << std::endl; + } (*this)[i] = x & 0xff; (*this)[i + 1] = x >> 8; } void writeAt(size_t i, uint32_t x) { - if (debug) + if (debug) { std::cerr << "backpatchInt32: " << x << " (at " << i << ")" << std::endl; + } (*this)[i] = x & 0xff; x >>= 8; (*this)[i + 1] = x & 0xff; @@ -305,24 +314,27 @@ public: // writes out an LEB to an arbitrary location. this writes the LEB as a full // 5 bytes, the fixed amount that can easily be set aside ahead of time void writeAtFullFixedSize(size_t i, U32LEB x) { - if (debug) + if (debug) { std::cerr << "backpatchU32LEB: " << x.value << " (at " << i << ")" << std::endl; + } // fill all 5 bytes, we have to do this when backpatching x.writeAt(this, i, MaxLEB32Bytes); } // writes out an LEB of normal size // returns how many bytes were written size_t writeAt(size_t i, U32LEB x) { - if (debug) + if (debug) { std::cerr << "writeAtU32LEB: " << x.value << " (at " << i << ")" << std::endl; + } return x.writeAt(this, i); } template<typename T> void writeTo(T& o) { - for (auto c : *this) + for (auto c : *this) { o << c; + } } std::vector<char> getAsChars() { diff --git a/src/wasm-builder.h b/src/wasm-builder.h index 8e7cc9908..9024ea6b1 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -547,10 +547,12 @@ public: // block Block* blockify(Expression* any, Expression* append = nullptr) { Block* block = nullptr; - if (any) + if (any) { block = any->dynCast<Block>(); - if (!block) + } + if (!block) { block = makeBlock(any); + } if (append) { block->list.push_back(append); block->finalize(); @@ -569,10 +571,12 @@ public: Block* blockifyWithName(Expression* any, Name name, Expression* append = nullptr) { Block* block = nullptr; - if (any) + if (any) { block = any->dynCast<Block>(); - if (!block || block->name.is()) + } + if (!block || block->name.is()) { block = makeBlock(any); + } block->name = name; if (append) { block->list.push_back(append); @@ -619,8 +623,9 @@ public: // Drop an expression if it has a concrete type Expression* dropIfConcretelyTyped(Expression* curr) { - if (!isConcreteType(curr->type)) + if (!isConcreteType(curr->type)) { return curr; + } return makeDrop(curr); } diff --git a/src/wasm-features.h b/src/wasm-features.h index d31715f18..6337f6af9 100644 --- a/src/wasm-features.h +++ b/src/wasm-features.h @@ -84,18 +84,24 @@ struct FeatureSet { } template<typename F> void iterFeatures(F f) { - if (hasAtomics()) + if (hasAtomics()) { f(Atomics); - if (hasBulkMemory()) + } + if (hasBulkMemory()) { f(BulkMemory); - if (hasMutableGlobals()) + } + if (hasMutableGlobals()) { f(MutableGlobals); - if (hasTruncSat()) + } + if (hasTruncSat()) { f(TruncSat); - if (hasSignExt()) + } + if (hasSignExt()) { f(SignExt); - if (hasSIMD()) + } + if (hasSIMD()) { f(SIMD); + } } bool operator<=(const FeatureSet& other) const { diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index dd6e2b073..02e065c5f 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -182,17 +182,20 @@ public: Flow visitIf(If* curr) { NOTE_ENTER("If"); Flow flow = visit(curr->condition); - if (flow.breaking()) + if (flow.breaking()) { return flow; + } NOTE_EVAL1(flow.value); if (flow.value.geti32()) { Flow flow = visit(curr->ifTrue); - if (!flow.breaking() && !curr->ifFalse) + if (!flow.breaking() && !curr->ifFalse) { flow.value = Literal(); // if_else returns a value, but if does not + } return flow; } - if (curr->ifFalse) + if (curr->ifFalse) { return visit(curr->ifFalse); + } return Flow(); } Flow visitLoop(Loop* curr) { @@ -200,8 +203,9 @@ public: while (1) { Flow flow = visit(curr->body); if (flow.breaking()) { - if (flow.breakTo == curr->name) + if (flow.breakTo == curr->name) { continue; // lol + } } // loop does not loop automatically, only continue achieves that return flow; @@ -213,16 +217,19 @@ public: Flow flow; if (curr->value) { flow = visit(curr->value); - if (flow.breaking()) + if (flow.breaking()) { return flow; + } } if (curr->condition) { Flow conditionFlow = visit(curr->condition); - if (conditionFlow.breaking()) + if (conditionFlow.breaking()) { return conditionFlow; + } condition = conditionFlow.value.getInteger() != 0; - if (!condition) + if (!condition) { return flow; + } } flow.breakTo = curr->name; return flow; @@ -233,14 +240,16 @@ public: Literal value; if (curr->value) { flow = visit(curr->value); - if (flow.breaking()) + if (flow.breaking()) { return flow; + } value = flow.value; NOTE_EVAL1(value); } flow = visit(curr->condition); - if (flow.breaking()) + if (flow.breaking()) { return flow; + } int64_t index = flow.value.getInteger(); Name target = curr->default_; if (index >= 0 && (size_t)index < curr->targets.size()) { @@ -263,8 +272,9 @@ public: Flow visitUnary(Unary* curr) { NOTE_ENTER("Unary"); Flow flow = visit(curr->value); - if (flow.breaking()) + if (flow.breaking()) { return flow; + } Literal value = flow.value; NOTE_EVAL1(value); switch (curr->op) { @@ -436,12 +446,14 @@ public: Flow visitBinary(Binary* curr) { NOTE_ENTER("Binary"); Flow flow = visit(curr->left); - if (flow.breaking()) + if (flow.breaking()) { return flow; + } Literal left = flow.value; flow = visit(curr->right); - if (flow.breaking()) + if (flow.breaking()) { return flow; + } Literal right = flow.value; NOTE_EVAL2(left, right); assert(isConcreteType(curr->left->type) ? left.type == curr->left->type @@ -465,53 +477,65 @@ public: case MulFloat64: return left.mul(right); case DivSInt32: { - if (right.getInteger() == 0) + if (right.getInteger() == 0) { trap("i32.div_s by 0"); + } if (left.getInteger() == std::numeric_limits<int32_t>::min() && - right.getInteger() == -1) + right.getInteger() == -1) { trap("i32.div_s overflow"); // signed division overflow + } return left.divS(right); } case DivUInt32: { - if (right.getInteger() == 0) + if (right.getInteger() == 0) { trap("i32.div_u by 0"); + } return left.divU(right); } case RemSInt32: { - if (right.getInteger() == 0) + if (right.getInteger() == 0) { trap("i32.rem_s by 0"); + } if (left.getInteger() == std::numeric_limits<int32_t>::min() && - right.getInteger() == -1) + right.getInteger() == -1) { return Literal(int32_t(0)); + } return left.remS(right); } case RemUInt32: { - if (right.getInteger() == 0) + if (right.getInteger() == 0) { trap("i32.rem_u by 0"); + } return left.remU(right); } case DivSInt64: { - if (right.getInteger() == 0) + if (right.getInteger() == 0) { trap("i64.div_s by 0"); - if (left.getInteger() == LLONG_MIN && right.getInteger() == -1LL) + } + if (left.getInteger() == LLONG_MIN && right.getInteger() == -1LL) { trap("i64.div_s overflow"); // signed division overflow + } return left.divS(right); } case DivUInt64: { - if (right.getInteger() == 0) + if (right.getInteger() == 0) { trap("i64.div_u by 0"); + } return left.divU(right); } case RemSInt64: { - if (right.getInteger() == 0) + if (right.getInteger() == 0) { trap("i64.rem_s by 0"); - if (left.getInteger() == LLONG_MIN && right.getInteger() == -1LL) + } + if (left.getInteger() == LLONG_MIN && right.getInteger() == -1LL) { return Literal(int64_t(0)); + } return left.remS(right); } case RemUInt64: { - if (right.getInteger() == 0) + if (right.getInteger() == 0) { trap("i64.rem_u by 0"); + } return left.remU(right); } case DivFloat32: @@ -763,8 +787,9 @@ public: Flow visitSIMDExtract(SIMDExtract* curr) { NOTE_ENTER("SIMDExtract"); Flow flow = this->visit(curr->vec); - if (flow.breaking()) + if (flow.breaking()) { return flow; + } Literal vec = flow.value; switch (curr->op) { case ExtractLaneSVecI8x16: @@ -789,12 +814,14 @@ public: Flow visitSIMDReplace(SIMDReplace* curr) { NOTE_ENTER("SIMDReplace"); Flow flow = this->visit(curr->vec); - if (flow.breaking()) + if (flow.breaking()) { return flow; + } Literal vec = flow.value; flow = this->visit(curr->value); - if (flow.breaking()) + if (flow.breaking()) { return flow; + } Literal value = flow.value; switch (curr->op) { case ReplaceLaneVecI8x16: @@ -815,40 +842,47 @@ public: Flow visitSIMDShuffle(SIMDShuffle* curr) { NOTE_ENTER("SIMDShuffle"); Flow flow = this->visit(curr->left); - if (flow.breaking()) + if (flow.breaking()) { return flow; + } Literal left = flow.value; flow = this->visit(curr->right); - if (flow.breaking()) + if (flow.breaking()) { return flow; + } Literal right = flow.value; return left.shuffleV8x16(right, curr->mask); } Flow visitSIMDBitselect(SIMDBitselect* curr) { NOTE_ENTER("SIMDBitselect"); Flow flow = this->visit(curr->left); - if (flow.breaking()) + if (flow.breaking()) { return flow; + } Literal left = flow.value; flow = this->visit(curr->right); - if (flow.breaking()) + if (flow.breaking()) { return flow; + } Literal right = flow.value; flow = this->visit(curr->cond); - if (flow.breaking()) + if (flow.breaking()) { return flow; + } Literal cond = flow.value; return cond.bitselectV128(left, right); } Flow visitSIMDShift(SIMDShift* curr) { NOTE_ENTER("SIMDShift"); Flow flow = this->visit(curr->vec); - if (flow.breaking()) + if (flow.breaking()) { return flow; + } Literal vec = flow.value; flow = this->visit(curr->shift); - if (flow.breaking()) + if (flow.breaking()) { return flow; + } Literal shift = flow.value; switch (curr->op) { case ShlVecI8x16: @@ -881,22 +915,26 @@ public: Flow visitSelect(Select* curr) { NOTE_ENTER("Select"); Flow ifTrue = visit(curr->ifTrue); - if (ifTrue.breaking()) + if (ifTrue.breaking()) { return ifTrue; + } Flow ifFalse = visit(curr->ifFalse); - if (ifFalse.breaking()) + if (ifFalse.breaking()) { return ifFalse; + } Flow condition = visit(curr->condition); - if (condition.breaking()) + if (condition.breaking()) { return condition; + } NOTE_EVAL1(condition.value); return condition.value.geti32() ? ifTrue : ifFalse; // ;-) } Flow visitDrop(Drop* curr) { NOTE_ENTER("Drop"); Flow value = visit(curr->value); - if (value.breaking()) + if (value.breaking()) { return value; + } return Flow(); } Flow visitReturn(Return* curr) { @@ -904,8 +942,9 @@ public: Flow flow; if (curr->value) { flow = visit(curr->value); - if (flow.breaking()) + if (flow.breaking()) { return flow; + } NOTE_EVAL1(flow.value); } flow.breakTo = RETURN_FLOW; @@ -923,24 +962,29 @@ public: Literal truncSFloat(Unary* curr, Literal value) { double val = value.getFloat(); - if (std::isnan(val)) + if (std::isnan(val)) { trap("truncSFloat of nan"); + } if (curr->type == i32) { if (value.type == f32) { - if (!isInRangeI32TruncS(value.reinterpreti32())) + if (!isInRangeI32TruncS(value.reinterpreti32())) { trap("i32.truncSFloat overflow"); + } } else { - if (!isInRangeI32TruncS(value.reinterpreti64())) + if (!isInRangeI32TruncS(value.reinterpreti64())) { trap("i32.truncSFloat overflow"); + } } return Literal(int32_t(val)); } else { if (value.type == f32) { - if (!isInRangeI64TruncS(value.reinterpreti32())) + if (!isInRangeI64TruncS(value.reinterpreti32())) { trap("i64.truncSFloat overflow"); + } } else { - if (!isInRangeI64TruncS(value.reinterpreti64())) + if (!isInRangeI64TruncS(value.reinterpreti64())) { trap("i64.truncSFloat overflow"); + } } return Literal(int64_t(val)); } @@ -948,24 +992,29 @@ public: Literal truncUFloat(Unary* curr, Literal value) { double val = value.getFloat(); - if (std::isnan(val)) + if (std::isnan(val)) { trap("truncUFloat of nan"); + } if (curr->type == i32) { if (value.type == f32) { - if (!isInRangeI32TruncU(value.reinterpreti32())) + if (!isInRangeI32TruncU(value.reinterpreti32())) { trap("i32.truncUFloat overflow"); + } } else { - if (!isInRangeI32TruncU(value.reinterpreti64())) + if (!isInRangeI32TruncU(value.reinterpreti64())) { trap("i32.truncUFloat overflow"); + } } return Literal(uint32_t(val)); } else { if (value.type == f32) { - if (!isInRangeI64TruncU(value.reinterpreti32())) + if (!isInRangeI64TruncU(value.reinterpreti32())) { trap("i64.truncUFloat overflow"); + } } else { - if (!isInRangeI64TruncU(value.reinterpreti64())) + if (!isInRangeI64TruncU(value.reinterpreti64())) { trap("i64.truncUFloat overflow"); + } } return Literal(uint64_t(val)); } @@ -1193,8 +1242,9 @@ public: // call an exported function Literal callExport(Name name, const LiteralList& arguments) { Export* export_ = wasm.getExportOrNull(name); - if (!export_) + if (!export_) { externalInterface->trap("callExport not found"); + } return callFunction(export_->value, arguments); } @@ -1203,12 +1253,14 @@ public: // get an exported global Literal getExport(Name name) { Export* export_ = wasm.getExportOrNull(name); - if (!export_) + if (!export_) { externalInterface->trap("getExport external not found"); + } Name internalName = export_->value; auto iter = globals.find(internalName); - if (iter == globals.end()) + if (iter == globals.end()) { externalInterface->trap("getExport internal not found"); + } return iter->second; } @@ -1333,8 +1385,9 @@ private: arguments.reserve(operands.size()); for (auto expression : operands) { Flow flow = this->visit(expression); - if (flow.breaking()) + if (flow.breaking()) { return flow; + } NOTE_EVAL1(flow.value); arguments.push_back(flow.value); } @@ -1346,8 +1399,9 @@ private: NOTE_NAME(curr->target); LiteralList arguments; Flow flow = generateArguments(curr->operands, arguments); - if (flow.breaking()) + if (flow.breaking()) { return flow; + } auto* func = instance.wasm.getFunction(curr->target); Flow ret; if (func->imported()) { @@ -1364,11 +1418,13 @@ private: NOTE_ENTER("CallIndirect"); LiteralList arguments; Flow flow = generateArguments(curr->operands, arguments); - if (flow.breaking()) + if (flow.breaking()) { return flow; + } Flow target = this->visit(curr->target); - if (target.breaking()) + if (target.breaking()) { return target; + } Index index = target.value.geti32(); return instance.externalInterface->callTable( index, arguments, curr->type, *instance.self()); @@ -1385,8 +1441,9 @@ private: NOTE_ENTER("SetLocal"); auto index = curr->index; Flow flow = this->visit(curr->value); - if (flow.breaking()) + if (flow.breaking()) { return flow; + } NOTE_EVAL1(index); NOTE_EVAL1(flow.value); assert(curr->isTee() ? flow.value.type == curr->type : true); @@ -1406,8 +1463,9 @@ private: NOTE_ENTER("SetGlobal"); auto name = curr->name; Flow flow = this->visit(curr->value); - if (flow.breaking()) + if (flow.breaking()) { return flow; + } NOTE_EVAL1(name); NOTE_EVAL1(flow.value); instance.globals[name] = flow.value; @@ -1417,8 +1475,9 @@ private: Flow visitLoad(Load* curr) { NOTE_ENTER("Load"); Flow flow = this->visit(curr->ptr); - if (flow.breaking()) + if (flow.breaking()) { return flow; + } NOTE_EVAL1(flow); auto addr = instance.getFinalAddress(curr, flow.value); auto ret = instance.externalInterface->load(curr, addr); @@ -1429,11 +1488,13 @@ private: Flow visitStore(Store* curr) { NOTE_ENTER("Store"); Flow ptr = this->visit(curr->ptr); - if (ptr.breaking()) + if (ptr.breaking()) { return ptr; + } Flow value = this->visit(curr->value); - if (value.breaking()) + if (value.breaking()) { return value; + } auto addr = instance.getFinalAddress(curr, ptr.value); NOTE_EVAL1(addr); NOTE_EVAL1(value); @@ -1444,11 +1505,13 @@ private: Flow visitAtomicRMW(AtomicRMW* curr) { NOTE_ENTER("AtomicRMW"); Flow ptr = this->visit(curr->ptr); - if (ptr.breaking()) + if (ptr.breaking()) { return ptr; + } auto value = this->visit(curr->value); - if (value.breaking()) + if (value.breaking()) { return value; + } NOTE_EVAL1(ptr); auto addr = instance.getFinalAddress(curr, ptr.value); NOTE_EVAL1(addr); @@ -1482,15 +1545,18 @@ private: Flow visitAtomicCmpxchg(AtomicCmpxchg* curr) { NOTE_ENTER("AtomicCmpxchg"); Flow ptr = this->visit(curr->ptr); - if (ptr.breaking()) + if (ptr.breaking()) { return ptr; + } NOTE_EVAL1(ptr); auto expected = this->visit(curr->expected); - if (expected.breaking()) + if (expected.breaking()) { return expected; + } auto replacement = this->visit(curr->replacement); - if (replacement.breaking()) + if (replacement.breaking()) { return replacement; + } auto addr = instance.getFinalAddress(curr, ptr.value); NOTE_EVAL1(addr); NOTE_EVAL1(expected); @@ -1505,17 +1571,20 @@ private: Flow visitAtomicWait(AtomicWait* curr) { NOTE_ENTER("AtomicWait"); Flow ptr = this->visit(curr->ptr); - if (ptr.breaking()) + if (ptr.breaking()) { return ptr; + } NOTE_EVAL1(ptr); auto expected = this->visit(curr->expected); NOTE_EVAL1(expected); - if (expected.breaking()) + if (expected.breaking()) { return expected; + } auto timeout = this->visit(curr->timeout); NOTE_EVAL1(timeout); - if (timeout.breaking()) + if (timeout.breaking()) { return timeout; + } auto bytes = getTypeSize(curr->expectedType); auto addr = instance.getFinalAddress(ptr.value, bytes); auto loaded = instance.doAtomicLoad(addr, bytes, curr->expectedType); @@ -1530,13 +1599,15 @@ private: Flow visitAtomicNotify(AtomicNotify* curr) { NOTE_ENTER("AtomicNotify"); Flow ptr = this->visit(curr->ptr); - if (ptr.breaking()) + if (ptr.breaking()) { return ptr; + } NOTE_EVAL1(ptr); auto count = this->visit(curr->notifyCount); NOTE_EVAL1(count); - if (count.breaking()) + if (count.breaking()) { return count; + } // TODO: add threads support! return Literal(int32_t(0)); // none woken up } @@ -1548,17 +1619,21 @@ private: case GrowMemory: { auto fail = Literal(int32_t(-1)); Flow flow = this->visit(curr->operands[0]); - if (flow.breaking()) + if (flow.breaking()) { return flow; + } int32_t ret = instance.memorySize; uint32_t delta = flow.value.geti32(); - if (delta > uint32_t(-1) / Memory::kPageSize) + if (delta > uint32_t(-1) / Memory::kPageSize) { return fail; - if (instance.memorySize >= uint32_t(-1) - delta) + } + if (instance.memorySize >= uint32_t(-1) - delta) { return fail; + } uint32_t newSize = instance.memorySize + delta; - if (newSize > instance.wasm.memory.max) + if (newSize > instance.wasm.memory.max) { return fail; + } instance.externalInterface->growMemory(instance.memorySize * Memory::kPageSize, newSize * Memory::kPageSize); @@ -1571,14 +1646,17 @@ private: Flow visitMemoryInit(MemoryInit* curr) { NOTE_ENTER("MemoryInit"); Flow dest = this->visit(curr->dest); - if (dest.breaking()) + if (dest.breaking()) { return dest; + } Flow offset = this->visit(curr->offset); - if (offset.breaking()) + if (offset.breaking()) { return offset; + } Flow size = this->visit(curr->size); - if (size.breaking()) + if (size.breaking()) { return size; + } NOTE_EVAL1(dest); NOTE_EVAL1(offset); NOTE_EVAL1(size); @@ -1620,14 +1698,17 @@ private: Flow visitMemoryCopy(MemoryCopy* curr) { NOTE_ENTER("MemoryCopy"); Flow dest = this->visit(curr->dest); - if (dest.breaking()) + if (dest.breaking()) { return dest; + } Flow source = this->visit(curr->source); - if (source.breaking()) + if (source.breaking()) { return source; + } Flow size = this->visit(curr->size); - if (size.breaking()) + if (size.breaking()) { return size; + } NOTE_EVAL1(dest); NOTE_EVAL1(source); NOTE_EVAL1(size); @@ -1662,14 +1743,17 @@ private: Flow visitMemoryFill(MemoryFill* curr) { NOTE_ENTER("MemoryFill"); Flow dest = this->visit(curr->dest); - if (dest.breaking()) + if (dest.breaking()) { return dest; + } Flow value = this->visit(curr->value); - if (value.breaking()) + if (value.breaking()) { return value; + } Flow size = this->visit(curr->size); - if (size.breaking()) + if (size.breaking()) { return size; + } NOTE_EVAL1(dest); NOTE_EVAL1(value); NOTE_EVAL1(size); @@ -1704,8 +1788,9 @@ public: // Internal function call. Must be public so that callTable implementations // can use it (refactor?) Literal callFunctionInternal(Name name, const LiteralList& arguments) { - if (callDepth > maxCallDepth) + if (callDepth > maxCallDepth) { externalInterface->trap("stack limit"); + } auto previousCallDepth = callDepth; callDepth++; auto previousFunctionStackSize = functionStack.size(); diff --git a/src/wasm-module-building.h b/src/wasm-module-building.h index 6f9a58eeb..63129f874 100644 --- a/src/wasm-module-building.h +++ b/src/wasm-module-building.h @@ -169,8 +169,9 @@ public: // Add a function to the module, and to be optimized void addFunction(Function* func) { wasm->addFunction(func); - if (!useWorkers()) + if (!useWorkers()) { return; // we optimize at the end in that case + } queueFunction(func); // notify workers if needed auto notify = availableFuncs.load(); @@ -240,8 +241,9 @@ private: } } DEBUG_THREAD("joining"); - for (auto& thread : threads) + for (auto& thread : threads) { thread->join(); + } DEBUG_THREAD("joined"); } diff --git a/src/wasm-stack.h b/src/wasm-stack.h index 124b70926..0355f60ee 100644 --- a/src/wasm-stack.h +++ b/src/wasm-stack.h @@ -246,8 +246,9 @@ public: this->setFunction(funcInit); this->mapLocalsAndEmitHeader(); for (auto* inst : *funcInit->stackIR) { - if (!inst) + if (!inst) { continue; // a nullptr is just something we can skip + } switch (inst->op) { case StackInst::Basic: case StackInst::BlockBegin: @@ -335,16 +336,21 @@ void StackWriter<Mode, Parent>::mapLocalsAndEmitHeader() { o << U32LEB((numLocalsByType[i32] ? 1 : 0) + (numLocalsByType[i64] ? 1 : 0) + (numLocalsByType[f32] ? 1 : 0) + (numLocalsByType[f64] ? 1 : 0) + (numLocalsByType[v128] ? 1 : 0)); - if (numLocalsByType[i32]) + if (numLocalsByType[i32]) { o << U32LEB(numLocalsByType[i32]) << binaryType(i32); - if (numLocalsByType[i64]) + } + if (numLocalsByType[i64]) { o << U32LEB(numLocalsByType[i64]) << binaryType(i64); - if (numLocalsByType[f32]) + } + if (numLocalsByType[f32]) { o << U32LEB(numLocalsByType[f32]) << binaryType(f32); - if (numLocalsByType[f64]) + } + if (numLocalsByType[f64]) { o << U32LEB(numLocalsByType[f64]) << binaryType(f64); - if (numLocalsByType[v128]) + } + if (numLocalsByType[v128]) { o << U32LEB(numLocalsByType[v128]) << binaryType(v128); + } } template<StackWriterMode Mode, typename Parent> @@ -570,8 +576,9 @@ void StackWriter<Mode, Parent>::visitBreak(Break* curr) { if (curr->value) { visitChild(curr->value); } - if (curr->condition) + if (curr->condition) { visitChild(curr->condition); + } if (!justAddToStack(curr)) { o << int8_t(curr->condition ? BinaryConsts::BrIf : BinaryConsts::Br) << U32LEB(getBreakIndex(curr->name)); @@ -601,8 +608,9 @@ void StackWriter<Mode, Parent>::visitSwitch(Switch* curr) { emitExtraUnreachable(); return; } - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } o << int8_t(BinaryConsts::TableSwitch) << U32LEB(curr->targets.size()); for (auto target : curr->targets) { o << U32LEB(getBreakIndex(target)); @@ -643,8 +651,9 @@ void StackWriter<Mode, Parent>::visitCallIndirect(CallIndirect* curr) { template<StackWriterMode Mode, typename Parent> void StackWriter<Mode, Parent>::visitGetLocal(GetLocal* curr) { - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } o << int8_t(BinaryConsts::GetLocal) << U32LEB(mappedLocals[curr->index]); } @@ -662,8 +671,9 @@ void StackWriter<Mode, Parent>::visitSetLocal(SetLocal* curr) { template<StackWriterMode Mode, typename Parent> void StackWriter<Mode, Parent>::visitGetGlobal(GetGlobal* curr) { - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } o << int8_t(BinaryConsts::GetGlobal) << U32LEB(parent.getGlobalIndex(curr->name)); } @@ -671,8 +681,9 @@ void StackWriter<Mode, Parent>::visitGetGlobal(GetGlobal* curr) { template<StackWriterMode Mode, typename Parent> void StackWriter<Mode, Parent>::visitSetGlobal(SetGlobal* curr) { visitChild(curr->value); - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } o << int8_t(BinaryConsts::SetGlobal) << U32LEB(parent.getGlobalIndex(curr->name)); } @@ -685,8 +696,9 @@ void StackWriter<Mode, Parent>::visitLoad(Load* curr) { emitExtraUnreachable(); return; } - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } if (!curr->isAtomic) { switch (curr->type) { case i32: { @@ -801,8 +813,9 @@ void StackWriter<Mode, Parent>::visitStore(Store* curr) { emitExtraUnreachable(); return; } - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } if (!curr->isAtomic) { switch (curr->valueType) { case i32: { @@ -903,18 +916,21 @@ template<StackWriterMode Mode, typename Parent> void StackWriter<Mode, Parent>::visitAtomicRMW(AtomicRMW* curr) { visitChild(curr->ptr); // stop if the rest isn't reachable anyhow - if (curr->ptr->type == unreachable) + if (curr->ptr->type == unreachable) { return; + } visitChild(curr->value); - if (curr->value->type == unreachable) + if (curr->value->type == unreachable) { return; + } if (curr->type == unreachable) { // don't even emit it; we don't know the right type emitExtraUnreachable(); return; } - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } o << int8_t(BinaryConsts::AtomicPrefix); @@ -978,21 +994,25 @@ template<StackWriterMode Mode, typename Parent> void StackWriter<Mode, Parent>::visitAtomicCmpxchg(AtomicCmpxchg* curr) { visitChild(curr->ptr); // stop if the rest isn't reachable anyhow - if (curr->ptr->type == unreachable) + if (curr->ptr->type == unreachable) { return; + } visitChild(curr->expected); - if (curr->expected->type == unreachable) + if (curr->expected->type == unreachable) { return; + } visitChild(curr->replacement); - if (curr->replacement->type == unreachable) + if (curr->replacement->type == unreachable) { return; + } if (curr->type == unreachable) { // don't even emit it; we don't know the right type emitExtraUnreachable(); return; } - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } o << int8_t(BinaryConsts::AtomicPrefix); switch (curr->type) { @@ -1039,16 +1059,20 @@ template<StackWriterMode Mode, typename Parent> void StackWriter<Mode, Parent>::visitAtomicWait(AtomicWait* curr) { visitChild(curr->ptr); // stop if the rest isn't reachable anyhow - if (curr->ptr->type == unreachable) + if (curr->ptr->type == unreachable) { return; + } visitChild(curr->expected); - if (curr->expected->type == unreachable) + if (curr->expected->type == unreachable) { return; + } visitChild(curr->timeout); - if (curr->timeout->type == unreachable) + if (curr->timeout->type == unreachable) { return; - if (justAddToStack(curr)) + } + if (justAddToStack(curr)) { return; + } o << int8_t(BinaryConsts::AtomicPrefix); switch (curr->expectedType) { @@ -1071,13 +1095,16 @@ template<StackWriterMode Mode, typename Parent> void StackWriter<Mode, Parent>::visitAtomicNotify(AtomicNotify* curr) { visitChild(curr->ptr); // stop if the rest isn't reachable anyhow - if (curr->ptr->type == unreachable) + if (curr->ptr->type == unreachable) { return; + } visitChild(curr->notifyCount); - if (curr->notifyCount->type == unreachable) + if (curr->notifyCount->type == unreachable) { return; - if (justAddToStack(curr)) + } + if (justAddToStack(curr)) { return; + } o << int8_t(BinaryConsts::AtomicPrefix) << int8_t(BinaryConsts::AtomicNotify); emitMemoryAccess(4, 4, 0); @@ -1086,8 +1113,9 @@ void StackWriter<Mode, Parent>::visitAtomicNotify(AtomicNotify* curr) { template<StackWriterMode Mode, typename Parent> void StackWriter<Mode, Parent>::visitSIMDExtract(SIMDExtract* curr) { visitChild(curr->vec); - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } o << int8_t(BinaryConsts::SIMDPrefix); switch (curr->op) { case ExtractLaneSVecI8x16: @@ -1122,8 +1150,9 @@ template<StackWriterMode Mode, typename Parent> void StackWriter<Mode, Parent>::visitSIMDReplace(SIMDReplace* curr) { visitChild(curr->vec); visitChild(curr->value); - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } o << int8_t(BinaryConsts::SIMDPrefix); switch (curr->op) { case ReplaceLaneVecI8x16: @@ -1153,8 +1182,9 @@ template<StackWriterMode Mode, typename Parent> void StackWriter<Mode, Parent>::visitSIMDShuffle(SIMDShuffle* curr) { visitChild(curr->left); visitChild(curr->right); - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::V8x16Shuffle); for (uint8_t m : curr->mask) { o << m; @@ -1166,8 +1196,9 @@ void StackWriter<Mode, Parent>::visitSIMDBitselect(SIMDBitselect* curr) { visitChild(curr->left); visitChild(curr->right); visitChild(curr->cond); - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::V128Bitselect); } @@ -1175,8 +1206,9 @@ template<StackWriterMode Mode, typename Parent> void StackWriter<Mode, Parent>::visitSIMDShift(SIMDShift* curr) { visitChild(curr->vec); visitChild(curr->shift); - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } o << int8_t(BinaryConsts::SIMDPrefix); switch (curr->op) { case ShlVecI8x16: @@ -1223,8 +1255,9 @@ void StackWriter<Mode, Parent>::visitMemoryInit(MemoryInit* curr) { visitChild(curr->dest); visitChild(curr->offset); visitChild(curr->size); - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } o << int8_t(BinaryConsts::MiscPrefix); o << U32LEB(BinaryConsts::MemoryInit); o << U32LEB(curr->segment) << int8_t(0); @@ -1232,8 +1265,9 @@ void StackWriter<Mode, Parent>::visitMemoryInit(MemoryInit* curr) { template<StackWriterMode Mode, typename Parent> void StackWriter<Mode, Parent>::visitDataDrop(DataDrop* curr) { - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } o << int8_t(BinaryConsts::MiscPrefix); o << U32LEB(BinaryConsts::DataDrop); o << U32LEB(curr->segment); @@ -1244,8 +1278,9 @@ void StackWriter<Mode, Parent>::visitMemoryCopy(MemoryCopy* curr) { visitChild(curr->dest); visitChild(curr->source); visitChild(curr->size); - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } o << int8_t(BinaryConsts::MiscPrefix); o << U32LEB(BinaryConsts::MemoryCopy); o << int8_t(0) << int8_t(0); @@ -1256,8 +1291,9 @@ void StackWriter<Mode, Parent>::visitMemoryFill(MemoryFill* curr) { visitChild(curr->dest); visitChild(curr->value); visitChild(curr->size); - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } o << int8_t(BinaryConsts::MiscPrefix); o << U32LEB(BinaryConsts::MemoryFill); o << int8_t(0); @@ -1265,8 +1301,9 @@ void StackWriter<Mode, Parent>::visitMemoryFill(MemoryFill* curr) { template<StackWriterMode Mode, typename Parent> void StackWriter<Mode, Parent>::visitConst(Const* curr) { - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } switch (curr->type) { case i32: { o << int8_t(BinaryConsts::I32Const) << S32LEB(curr->value.geti32()); @@ -1305,8 +1342,9 @@ void StackWriter<Mode, Parent>::visitUnary(Unary* curr) { emitExtraUnreachable(); return; } - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } switch (curr->op) { case ClzInt32: o << int8_t(BinaryConsts::I32Clz); @@ -1624,8 +1662,9 @@ void StackWriter<Mode, Parent>::visitBinary(Binary* curr) { emitExtraUnreachable(); return; } - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } switch (curr->op) { case AddInt32: o << int8_t(BinaryConsts::I32Add); @@ -2111,8 +2150,9 @@ void StackWriter<Mode, Parent>::visitSelect(Select* curr) { emitExtraUnreachable(); return; } - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } o << int8_t(BinaryConsts::Select); } @@ -2121,8 +2161,9 @@ void StackWriter<Mode, Parent>::visitReturn(Return* curr) { if (curr->value) { visitChild(curr->value); } - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } o << int8_t(BinaryConsts::Return); } @@ -2138,8 +2179,9 @@ void StackWriter<Mode, Parent>::visitHost(Host* curr) { break; } } - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } switch (curr->op) { case CurrentMemory: { o << int8_t(BinaryConsts::CurrentMemory); @@ -2155,23 +2197,26 @@ void StackWriter<Mode, Parent>::visitHost(Host* curr) { template<StackWriterMode Mode, typename Parent> void StackWriter<Mode, Parent>::visitNop(Nop* curr) { - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } o << int8_t(BinaryConsts::Nop); } template<StackWriterMode Mode, typename Parent> void StackWriter<Mode, Parent>::visitUnreachable(Unreachable* curr) { - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } o << int8_t(BinaryConsts::Unreachable); } template<StackWriterMode Mode, typename Parent> void StackWriter<Mode, Parent>::visitDrop(Drop* curr) { visitChild(curr->value); - if (justAddToStack(curr)) + if (justAddToStack(curr)) { return; + } o << int8_t(BinaryConsts::Drop); } diff --git a/src/wasm-traversal.h b/src/wasm-traversal.h index 2b495e025..5a2debcdf 100644 --- a/src/wasm-traversal.h +++ b/src/wasm-traversal.h @@ -957,17 +957,20 @@ struct ControlFlowWalker : public PostWalker<SubType, VisitorType> { while (1) { auto* curr = controlFlowStack[i]; if (Block* block = curr->template dynCast<Block>()) { - if (name == block->name) + if (name == block->name) { return curr; + } } else if (Loop* loop = curr->template dynCast<Loop>()) { - if (name == loop->name) + if (name == loop->name) { return curr; + } } else { // an if, ignorable assert(curr->template is<If>()); } - if (i == 0) + if (i == 0) { return nullptr; + } i--; } } @@ -1024,23 +1027,27 @@ struct ExpressionStackWalker : public PostWalker<SubType, VisitorType> { while (1) { auto* curr = expressionStack[i]; if (Block* block = curr->template dynCast<Block>()) { - if (name == block->name) + if (name == block->name) { return curr; + } } else if (Loop* loop = curr->template dynCast<Loop>()) { - if (name == loop->name) + if (name == loop->name) { return curr; + } } else { WASM_UNREACHABLE(); } - if (i == 0) + if (i == 0) { return nullptr; + } i--; } } Expression* getParent() { - if (expressionStack.size() == 1) + if (expressionStack.size() == 1) { return nullptr; + } assert(expressionStack.size() >= 2); return expressionStack[expressionStack.size() - 2]; } 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 } diff --git a/src/wasm2js.h b/src/wasm2js.h index 385f8877e..4e5bebb4c 100644 --- a/src/wasm2js.h +++ b/src/wasm2js.h @@ -60,12 +60,13 @@ IString EXPRESSION_RESULT("wasm2js$expresult"); // Appends extra to block, flattening out if extra is a block as well void flattenAppend(Ref ast, Ref extra) { int index; - if (ast[0] == BLOCK || ast[0] == TOPLEVEL) + if (ast[0] == BLOCK || ast[0] == TOPLEVEL) { index = 1; - else if (ast[0] == DEFUN) + } else if (ast[0] == DEFUN) { index = 3; - else + } else { abort(); + } if (extra->isArray() && extra[0] == BLOCK) { for (size_t i = 0; i < extra[1]->size(); i++) { ast[index]->push_back(extra[1][i]); @@ -752,8 +753,9 @@ Ref Wasm2JSBuilder::processFunctionBody(Module* m, bool isBlock(Ref ast) { return !!ast && ast->isArray() && ast[0] == BLOCK; } Ref blockify(Ref ast) { - if (isBlock(ast)) + if (isBlock(ast)) { return ast; + } Ref ret = ValueBuilder::makeBlock(); ret[1]->push_back(ValueBuilder::makeStatement(ast)); return ret; @@ -1994,8 +1996,9 @@ void Wasm2JSGlue::emitMemory( std::string buffer, std::string segmentWriter, std::function<std::string(std::string)> accessGlobal) { - if (wasm.memory.segments.empty()) + if (wasm.memory.segments.empty()) { return; + } auto expr = R"( function(mem) { @@ -2048,8 +2051,9 @@ void Wasm2JSGlue::emitScratchMemorySupport() { needScratchMemory = true; } }); - if (!needScratchMemory) + if (!needScratchMemory) { return; + } out << R"( var scratchBuffer = new ArrayBuffer(8); |