diff options
Diffstat (limited to 'src/wasm2asm.h')
-rw-r--r-- | src/wasm2asm.h | 335 |
1 files changed, 233 insertions, 102 deletions
diff --git a/src/wasm2asm.h b/src/wasm2asm.h index f328918c2..4ad81816c 100644 --- a/src/wasm2asm.h +++ b/src/wasm2asm.h @@ -23,6 +23,7 @@ #define wasm_wasm2asm_h #include <cmath> +#include <numeric> #include "asmjs/shared-constants.h" #include "wasm.h" @@ -209,7 +210,11 @@ Ref Wasm2AsmBuilder::processWasm(Module* wasm) { addImport(asmFunc[3], import.get()); } // figure out the table size - tableSize = wasm->table.names.size(); + tableSize = std::accumulate(wasm->table.segments.begin(), + wasm->table.segments.end(), + 0, [&](size_t size, Table::Segment seg) -> size_t { + return size + seg.data.size(); + }); size_t pow2ed = 1; while (pow2ed < tableSize) { pow2ed <<= 1; @@ -287,19 +292,21 @@ void Wasm2AsmBuilder::addImport(Ref ast, Import *import) { void Wasm2AsmBuilder::addTables(Ref ast, Module *wasm) { std::map<std::string, std::vector<IString>> tables; // asm.js tables, sig => contents of table - for (size_t i = 0; i < wasm->table.names.size(); i++) { - Name name = wasm->table.names[i]; - auto func = wasm->getFunction(name); - std::string sig = getSig(func); - auto& table = tables[sig]; - if (table.size() == 0) { - // fill it with the first of its type seen. we have to fill with something; and for asm2wasm output, the first is the null anyhow - table.resize(tableSize); - for (size_t j = 0; j < tableSize; j++) { - table[j] = fromName(name); + for (Table::Segment& seg : wasm->table.segments) { + for (size_t i = 0; i < seg.data.size(); i++) { + Name name = seg.data[i]; + auto func = wasm->getFunction(name); + std::string sig = getSig(func); + auto& table = tables[sig]; + if (table.size() == 0) { + // fill it with the first of its type seen. we have to fill with something; and for asm2wasm output, the first is the null anyhow + table.resize(tableSize); + for (size_t j = 0; j < tableSize; j++) { + table[j] = fromName(name); + } + } else { + table[i] = fromName(name); } - } else { - table[i] = fromName(name); } } for (auto& pair : tables) { @@ -327,7 +334,7 @@ void Wasm2AsmBuilder::addExports(Ref ast, Module *wasm) { } Ref Wasm2AsmBuilder::processFunction(Function* func) { - if (debug) std::cerr << " processFunction " << func->name << '\n'; + if (debug) std::cerr << " processFunction " << func->name << std::endl; Ref ret = ValueBuilder::makeFunction(fromName(func->name)); frees.clear(); frees.resize(std::max(i32, std::max(f32, f64)) + 1); @@ -340,9 +347,10 @@ Ref Wasm2AsmBuilder::processFunction(Function* func) { ValueBuilder::appendArgumentToFunction(ret, name); ret[3]->push_back( ValueBuilder::makeStatement( - ValueBuilder::makeAssign( - ValueBuilder::makeName(name), - makeAsmCoercion(ValueBuilder::makeName(name), wasmToAsmType(func->getLocalType(i))) + ValueBuilder::makeBinary( + ValueBuilder::makeName(name), SET, + makeAsmCoercion(ValueBuilder::makeName(name), + wasmToAsmType(func->getLocalType(i))) ) ) ); @@ -542,7 +550,8 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) { return visit(curr, temp.temp); } - Ref visitForExpression(Expression* curr, WasmType type, IString& tempName) { // this result is for an asm expression slot, but it might be a statement + // this result is for an asm expression slot, but it might be a statement + Ref visitForExpression(Expression* curr, WasmType type, IString& tempName) { if (isStatement(curr)) { ScopedTemp temp(type, parent); tempName = temp.temp; @@ -557,7 +566,8 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) { // if it's not already a statement, then it's an expression, and we need to assign it // (if it is a statement, it already assigns to the result var) if (!isStatement(curr) && result != NO_RESULT) { - ret = ValueBuilder::makeStatement(ValueBuilder::makeAssign(ValueBuilder::makeName(result), ret)); + ret = ValueBuilder::makeStatement( + ValueBuilder::makeBinary(ValueBuilder::makeName(result), SET, ret)); } return ret; } @@ -573,7 +583,7 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) { // Expressions with control flow turn into a block, which we must // then handle, even if we are an expression. bool isBlock(Ref ast) { - return !!ast && ast[0] == BLOCK; + return !!ast && ast->isArray() && ast[0] == BLOCK; } Ref blockify(Ref ast) { @@ -588,7 +598,7 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) { std::map<Name, IString> breakResults; // Breaks to the top of a loop should be emitted as continues, to that loop's main label - std::map<Name, Name> continueLabels; + std::unordered_set<Name> continueLabels; IString fromName(Name name) { return parent->fromName(name); @@ -629,14 +639,11 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) { return condition; } Ref visitLoop(Loop *curr) { - Name asmLabel = curr->out.is() ? curr->out : curr->in; // label using the outside, normal for breaks. if no outside, then inside - if (curr->in.is()) continueLabels[curr->in] = asmLabel; + Name asmLabel = curr->name; + continueLabels.insert(asmLabel); Ref body = visit(curr->body, result); Ref ret = ValueBuilder::makeDo(body, ValueBuilder::makeInt(0)); - if (asmLabel.is()) { - ret = ValueBuilder::makeLabel(fromName(asmLabel), ret); - } - return ret; + return ValueBuilder::makeLabel(fromName(asmLabel), ret); } Ref visitBreak(Break *curr) { if (curr->condition) { @@ -653,7 +660,7 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) { if (iter == continueLabels.end()) { theBreak = ValueBuilder::makeBreak(fromName(curr->name)); } else { - theBreak = ValueBuilder::makeContinue(fromName(iter->second)); + theBreak = ValueBuilder::makeContinue(fromName(curr->name)); } if (!curr->value) return theBreak; // generate the value, including assigning to the result, and then do the break @@ -695,7 +702,9 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) { } theCall = makeAsmCoercion(theCall, wasmToAsmType(type)); if (result != NO_RESULT) { - theCall = ValueBuilder::makeStatement(ValueBuilder::makeAssign(ValueBuilder::makeName(result), theCall)); + theCall = ValueBuilder::makeStatement( + ValueBuilder::makeBinary( + ValueBuilder::makeName(result), SET, theCall)); } flattenAppend(ret, theCall); for (auto temp : temps) { @@ -717,10 +726,11 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) { return makeStatementizedCall(curr->operands, ValueBuilder::makeBlock(), theCall, result, curr->type); } Ref visitCallImport(CallImport *curr) { + std::cerr << "visitCallImport not implemented yet" << std::endl; abort(); } Ref visitCallIndirect(CallIndirect *curr) { - std::string stable = std::string("FUNCTION_TABLE_") + getSig(curr->fullType); + std::string stable = std::string("FUNCTION_TABLE_") + curr->fullType.c_str(); IString table = IString(stable.c_str(), false); auto makeTableCall = [&](Ref target) { return ValueBuilder::makeCall(ValueBuilder::makeSub( @@ -748,12 +758,17 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) { } Ref visitSetLocal(SetLocal *curr) { if (!isStatement(curr)) { - return ValueBuilder::makeAssign(ValueBuilder::makeName(fromName(func->getLocalName(curr->index))), visit(curr->value, EXPRESSION_RESULT)); + return ValueBuilder::makeBinary( + ValueBuilder::makeName(fromName(func->getLocalName(curr->index))), + SET, visit(curr->value, EXPRESSION_RESULT)); } ScopedTemp temp(curr->type, parent, result); // if result was provided, our child can just assign there. otherwise, allocate a temp for it to assign to. Ref ret = blockify(visit(curr->value, temp)); // the output was assigned to result, so we can just assign it to our target - ret[1]->push_back(ValueBuilder::makeStatement(ValueBuilder::makeAssign(ValueBuilder::makeName(fromName(func->getLocalName(curr->index))), temp.getAstName()))); + ret[1]->push_back(ValueBuilder::makeStatement( + ValueBuilder::makeBinary( + ValueBuilder::makeName(fromName(func->getLocalName(curr->index))), + SET, temp.getAstName()))); return ret; } Ref visitLoad(Load *curr) { @@ -785,36 +800,63 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) { case i32: { rest = makeAsmCoercion(visit(&load, EXPRESSION_RESULT), ASM_INT); for (size_t i = 1; i < curr->bytes; i++) { - load.offset += 1; + ++load.offset; Ref add = makeAsmCoercion(visit(&load, EXPRESSION_RESULT), ASM_INT); add = ValueBuilder::makeBinary(add, LSHIFT, ValueBuilder::makeNum(8*i)); rest = ValueBuilder::makeBinary(rest, OR, add); } break; } - default: abort(); + default: + std::cerr << "Unhandled type in load: " << curr->type << std::endl; + abort(); } return ValueBuilder::makeSeq(ptrSet, rest); } // normal load Ref ptr = visit(curr->ptr, EXPRESSION_RESULT); if (curr->offset) { - ptr = makeAsmCoercion(ValueBuilder::makeBinary(ptr, PLUS, ValueBuilder::makeNum(curr->offset)), ASM_INT); + ptr = makeAsmCoercion( + ValueBuilder::makeBinary(ptr, PLUS, ValueBuilder::makeNum(curr->offset)), + ASM_INT); } Ref ret; switch (curr->type) { case i32: { switch (curr->bytes) { - case 1: ret = ValueBuilder::makeSub(ValueBuilder::makeName(curr->signed_ ? HEAP8 : HEAPU8 ), ValueBuilder::makePtrShift(ptr, 0)); break; - case 2: ret = ValueBuilder::makeSub(ValueBuilder::makeName(curr->signed_ ? HEAP16 : HEAPU16), ValueBuilder::makePtrShift(ptr, 1)); break; - case 4: ret = ValueBuilder::makeSub(ValueBuilder::makeName(curr->signed_ ? HEAP32 : HEAPU32), ValueBuilder::makePtrShift(ptr, 2)); break; - default: abort(); + case 1: + ret = ValueBuilder::makeSub( + ValueBuilder::makeName(curr->signed_ ? HEAP8 : HEAPU8 ), + ValueBuilder::makePtrShift(ptr, 0)); + break; + case 2: + ret = ValueBuilder::makeSub( + ValueBuilder::makeName(curr->signed_ ? HEAP16 : HEAPU16), + ValueBuilder::makePtrShift(ptr, 1)); + break; + case 4: + ret = ValueBuilder::makeSub( + ValueBuilder::makeName(curr->signed_ ? HEAP32 : HEAPU32), + ValueBuilder::makePtrShift(ptr, 2)); + break; + default: + std::cerr << "Unhandled number of bytes in i32 load: " + << curr->bytes << std::endl; + abort(); } break; } - case f32: ret = ValueBuilder::makeSub(ValueBuilder::makeName(HEAPF32), ValueBuilder::makePtrShift(ptr, 2)); break; - case f64: ret = ValueBuilder::makeSub(ValueBuilder::makeName(HEAPF64), ValueBuilder::makePtrShift(ptr, 3)); break; - default: abort(); + case f32: + ret = ValueBuilder::makeSub(ValueBuilder::makeName(HEAPF32), + ValueBuilder::makePtrShift(ptr, 2)); + break; + case f64: + ret = ValueBuilder::makeSub(ValueBuilder::makeName(HEAPF64), + ValueBuilder::makePtrShift(ptr, 3)); + break; + default: + std::cerr << "Unhandled type in load: " << curr->type << std::endl; + abort(); } return makeAsmCoercion(ret, wasmToAsmType(curr->type)); } @@ -866,12 +908,12 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) { shift.value = Literal(int32_t(8*i)); shift.type = i32; Binary shifted(allocator); - shifted.op = ShrU; + shifted.op = ShrUInt64; shifted.left = &getValue; shifted.right = &shift; shifted.type = i32; Binary anded(allocator); - anded.op = And; + anded.op = AndInt32; anded.left = i > 0 ? static_cast<Expression*>(&shifted) : static_cast<Expression*>(&getValue); anded.right = &_255; anded.type = i32; @@ -882,11 +924,14 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) { } else { rest = ValueBuilder::makeSeq(rest, part); } - store.offset += 1; + ++store.offset; } break; } - default: abort(); + default: + std::cerr << "Unhandled type in store: " << curr->type + << std::endl; + abort(); } return ValueBuilder::makeSeq(ValueBuilder::makeSeq(ptrSet, valueSet), rest); } @@ -911,7 +956,11 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) { case f64: ret = ValueBuilder::makeSub(ValueBuilder::makeName(HEAPF64), ValueBuilder::makePtrShift(ptr, 3)); break; default: abort(); } - return ValueBuilder::makeAssign(ret, value); + return ValueBuilder::makeBinary(ret, SET, value); + } + Ref visitDrop(Drop *curr) { + assert(!isStatement(curr)); + return visitAndAssign(curr->value, result); } Ref visitConst(Const *curr) { switch (curr->type) { @@ -950,9 +999,10 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) { switch (curr->type) { case i32: { switch (curr->op) { - case Clz: return ValueBuilder::makeCall(MATH_CLZ32, value); - case Ctz: return ValueBuilder::makeCall(MATH_CTZ32, value); - case Popcnt: return ValueBuilder::makeCall(MATH_POPCNT32, value); + case ClzInt32: + return ValueBuilder::makeCall(MATH_CLZ32, value); + case PopcntInt32: + return ValueBuilder::makeCall(MATH_POPCNT32, value); default: abort(); } } @@ -960,26 +1010,58 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) { case f64: { Ref ret; switch (curr->op) { - case Neg: ret = ValueBuilder::makeUnary(MINUS, value); break; - case Abs: ret = ValueBuilder::makeCall(MATH_ABS, value); break; - case Ceil: ret = ValueBuilder::makeCall(MATH_CEIL, value); break; - case Floor: ret = ValueBuilder::makeCall(MATH_FLOOR, value); break; - case Trunc: ret = ValueBuilder::makeCall(MATH_TRUNC, value); break; - case Nearest: ret = ValueBuilder::makeCall(MATH_NEAREST, value); break; - case Sqrt: ret = ValueBuilder::makeCall(MATH_SQRT, value); break; - //case TruncSFloat32: ret = ValueBuilder::makePrefix(B_NOT, ValueBuilder::makePrefix(B_NOT, value)); break; - case PromoteFloat32: - //case ConvertSInt32: ret = ValueBuilder::makePrefix(PLUS, ValueBuilder::makeBinary(value, OR, ValueBuilder::makeNum(0))); break; - //case ConvertUInt32: ret = ValueBuilder::makePrefix(PLUS, ValueBuilder::makeBinary(value, TRSHIFT, ValueBuilder::makeNum(0))); break; - case DemoteFloat64: ret = value; break; - default: std::cerr << curr << '\n'; abort(); + case NegFloat32: + case NegFloat64: + ret = ValueBuilder::makeUnary(MINUS, visit(curr->value, + EXPRESSION_RESULT)); + break; + case AbsFloat32: + case AbsFloat64: + ret = ValueBuilder::makeCall(MATH_ABS, visit(curr->value, + EXPRESSION_RESULT)); + break; + case CeilFloat32: + case CeilFloat64: + ret = ValueBuilder::makeCall(MATH_CEIL, visit(curr->value, + EXPRESSION_RESULT)); + break; + case FloorFloat32: + case FloorFloat64: + ret = ValueBuilder::makeCall(MATH_FLOOR, + visit(curr->value, + EXPRESSION_RESULT)); + break; + case TruncFloat32: + case TruncFloat64: + ret = ValueBuilder::makeCall(MATH_TRUNC, + visit(curr->value, + EXPRESSION_RESULT)); + break; + case NearestFloat32: + case NearestFloat64: + ret = ValueBuilder::makeCall(MATH_NEAREST, + visit(curr->value, + EXPRESSION_RESULT)); + break; + case SqrtFloat32: + case SqrtFloat64: + ret = ValueBuilder::makeCall(MATH_SQRT, visit(curr->value, + EXPRESSION_RESULT)); + break; + // TODO: more complex unary conversions + default: + std::cerr << "Unhandled unary float operator: " << curr + << std::endl; + abort(); } if (curr->type == f32) { // doubles need much less coercing return makeAsmCoercion(ret, ASM_FLOAT); } return ret; } - default: abort(); + default: + std::cerr << "Unhandled type: " << curr << std::endl; + abort(); } } Ref visitBinary(Binary *curr) { @@ -1003,55 +1085,104 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) { Ref right = visit(curr->right, EXPRESSION_RESULT); Ref ret; switch (curr->op) { - case Add: ret = ValueBuilder::makeBinary(left, PLUS, right); break; - case Sub: ret = ValueBuilder::makeBinary(left, MINUS, right); break; - case Mul: { + case AddInt32: + ret = ValueBuilder::makeBinary(left, PLUS, right); + break; + case SubInt32: + ret = ValueBuilder::makeBinary(left, MINUS, right); + break; + case MulInt32: { if (curr->type == i32) { - return ValueBuilder::makeCall(MATH_IMUL, left, right); // TODO: when one operand is a small int, emit a multiply + // TODO: when one operand is a small int, emit a multiply + return ValueBuilder::makeCall(MATH_IMUL, left, right); } else { - return ValueBuilder::makeBinary(left, MINUS, right); break; + return ValueBuilder::makeBinary(left, MUL, right); } } - case DivS: ret = ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), DIV, makeSigning(right, ASM_SIGNED)); break; - case DivU: ret = ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), DIV, makeSigning(right, ASM_UNSIGNED)); break; - case RemS: ret = ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), MOD, makeSigning(right, ASM_SIGNED)); break; - case RemU: ret = ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), MOD, makeSigning(right, ASM_UNSIGNED)); break; - case And: ret = ValueBuilder::makeBinary(left, AND, right); break; - case Or: ret = ValueBuilder::makeBinary(left, OR, right); break; - case Xor: ret = ValueBuilder::makeBinary(left, XOR, right); break; - case Shl: ret = ValueBuilder::makeBinary(left, LSHIFT, right); break; - case ShrU: ret = ValueBuilder::makeBinary(left, TRSHIFT, right); break; - case ShrS: ret = ValueBuilder::makeBinary(left, RSHIFT, right); break; - case Div: ret = ValueBuilder::makeBinary(left, DIV, right); break; - case Min: ret = ValueBuilder::makeCall(MATH_MIN, left, right); break; - case Max: ret = ValueBuilder::makeCall(MATH_MAX, left, right); break; - case Eq: { + case DivSInt32: + ret = ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), DIV, + makeSigning(right, ASM_SIGNED)); + break; + case DivUInt32: + ret = ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), DIV, + makeSigning(right, ASM_UNSIGNED)); + break; + case RemSInt32: + ret = ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), MOD, + makeSigning(right, ASM_SIGNED)); + break; + case RemUInt32: + ret = ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), MOD, + makeSigning(right, ASM_UNSIGNED)); + break; + case AndInt32: + ret = ValueBuilder::makeBinary(left, AND, right); + break; + case OrInt32: + ret = ValueBuilder::makeBinary(left, OR, right); + break; + case XorInt32: + ret = ValueBuilder::makeBinary(left, XOR, right); + break; + case ShlInt32: + ret = ValueBuilder::makeBinary(left, LSHIFT, right); + break; + case ShrUInt32: + ret = ValueBuilder::makeBinary(left, TRSHIFT, right); + break; + case ShrSInt32: + ret = ValueBuilder::makeBinary(left, RSHIFT, right); + break; + case MinFloat32: + ret = ValueBuilder::makeCall(MATH_MIN, left, right); + break; + case MaxFloat32: + ret = ValueBuilder::makeCall(MATH_MAX, left, right); + break; + case EqInt32: { + // TODO: check if this condition is still valid/necessary if (curr->left->type == i32) { - return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), EQ, makeSigning(right, ASM_SIGNED)); + return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), EQ, + makeSigning(right, ASM_SIGNED)); } else { return ValueBuilder::makeBinary(left, EQ, right); } } - case Ne: { + case NeInt32: { if (curr->left->type == i32) { - return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), NE, makeSigning(right, ASM_SIGNED)); + return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), NE, + makeSigning(right, ASM_SIGNED)); } else { return ValueBuilder::makeBinary(left, NE, right); } } - case LtS: return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), LT, makeSigning(right, ASM_SIGNED)); - case LtU: return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), LT, makeSigning(right, ASM_UNSIGNED)); - case LeS: return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), LE, makeSigning(right, ASM_SIGNED)); - case LeU: return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), LE, makeSigning(right, ASM_UNSIGNED)); - case GtS: return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), GT, makeSigning(right, ASM_SIGNED)); - case GtU: return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), GT, makeSigning(right, ASM_UNSIGNED)); - case GeS: return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), GE, makeSigning(right, ASM_SIGNED)); - case GeU: return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), GE, makeSigning(right, ASM_UNSIGNED)); - case Lt: return ValueBuilder::makeBinary(left, LT, right); - case Le: return ValueBuilder::makeBinary(left, LE, right); - case Gt: return ValueBuilder::makeBinary(left, GT, right); - case Ge: return ValueBuilder::makeBinary(left, GE, right); - default: abort(); + case LtSInt32: + return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), LT, + makeSigning(right, ASM_SIGNED)); + case LtUInt32: + return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), LT, + makeSigning(right, ASM_UNSIGNED)); + case LeSInt32: + return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), LE, + makeSigning(right, ASM_SIGNED)); + case LeUInt32: + return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), LE, + makeSigning(right, ASM_UNSIGNED)); + case GtSInt32: + return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), GT, + makeSigning(right, ASM_SIGNED)); + case GtUInt32: + return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), GT, + makeSigning(right, ASM_UNSIGNED)); + case GeSInt32: + return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), GE, + makeSigning(right, ASM_SIGNED)); + case GeUInt32: + return ValueBuilder::makeBinary(makeSigning(left, ASM_UNSIGNED), GE, + makeSigning(right, ASM_UNSIGNED)); + default: + std::cerr << "Unhandled binary operator: " << curr << std::endl; + abort(); } return makeAsmCoercion(ret, wasmToAsmType(curr->type)); } @@ -1085,11 +1216,11 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) { tempCondition(i32, parent); return ValueBuilder::makeSeq( - ValueBuilder::makeAssign(tempCondition.getAstName(), condition), + ValueBuilder::makeBinary(tempCondition.getAstName(), SET, condition), ValueBuilder::makeSeq( - ValueBuilder::makeAssign(tempIfTrue.getAstName(), ifTrue), + ValueBuilder::makeBinary(tempIfTrue.getAstName(), SET, ifTrue), ValueBuilder::makeSeq( - ValueBuilder::makeAssign(tempIfFalse.getAstName(), ifFalse), + ValueBuilder::makeBinary(tempIfFalse.getAstName(), SET, ifFalse), ValueBuilder::makeConditional(tempCondition.getAstName(), tempIfTrue.getAstName(), tempIfFalse.getAstName()) ) ) |