Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
277 changes: 176 additions & 101 deletions src/wasm2asm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1400,6 +1400,12 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) {
visit(curr->value, EXPRESSION_RESULT)
);
break;
case PromoteFloat32:
return makeAsmCoercion(visit(curr->value, EXPRESSION_RESULT),
ASM_DOUBLE);
case DemoteFloat64:
return makeAsmCoercion(visit(curr->value, EXPRESSION_RESULT),
ASM_FLOAT);
// TODO: more complex unary conversions
default:
std::cerr << "Unhandled unary float operator: " << curr
Expand Down Expand Up @@ -1438,112 +1444,181 @@ Ref Wasm2AsmBuilder::processFunctionBody(Function* func, IString result) {
Ref left = visit(curr->left, EXPRESSION_RESULT);
Ref right = visit(curr->right, EXPRESSION_RESULT);
Ref ret;
switch (curr->op) {
case AddInt32:
ret = ValueBuilder::makeBinary(left, PLUS, right);
break;
case SubInt32:
ret = ValueBuilder::makeBinary(left, MINUS, right);
break;
case MulInt32: {
if (curr->type == i32) {
// TODO: when one operand is a small int, emit a multiply
return ValueBuilder::makeCall(MATH_IMUL, left, right);
} else {
return ValueBuilder::makeBinary(left, MUL, right);
switch (curr->type) {
case i32: {
switch (curr->op) {
case AddInt32:
ret = ValueBuilder::makeBinary(left, PLUS, right);
break;
case SubInt32:
ret = ValueBuilder::makeBinary(left, MINUS, right);
break;
case MulInt32: {
if (curr->type == i32) {
// TODO: when one operand is a small int, emit a multiply
return ValueBuilder::makeCall(MATH_IMUL, left, right);
} else {
return ValueBuilder::makeBinary(left, MUL, right);
}
}
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 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));
} else {
return ValueBuilder::makeBinary(left, EQ, right);
}
}
case NeInt32: {
if (curr->left->type == i32) {
return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), NE,
makeSigning(right, ASM_SIGNED));
} else {
return ValueBuilder::makeBinary(left, NE, right);
}
}
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));
case RotLInt32:
return makeSigning(ValueBuilder::makeCall(WASM_ROTL32, left, right),
ASM_SIGNED);
case RotRInt32:
return makeSigning(ValueBuilder::makeCall(WASM_ROTR32, left, right),
ASM_SIGNED);
case EqFloat32:
return makeAsmCoercion(ValueBuilder::makeBinary(left, EQ, right),
ASM_FLOAT);
case EqFloat64:
return ValueBuilder::makeBinary(left, EQ, right);
case NeFloat32:
return makeAsmCoercion(ValueBuilder::makeBinary(left, NE, right),
ASM_FLOAT);
case NeFloat64:
return ValueBuilder::makeBinary(left, NE, right);
case GeFloat32:
return makeAsmCoercion(ValueBuilder::makeBinary(left, GE, right),
ASM_FLOAT);
case GeFloat64:
return ValueBuilder::makeBinary(left, GE, right);
case GtFloat32:
return makeAsmCoercion(ValueBuilder::makeBinary(left, GT, right),
ASM_FLOAT);
case GtFloat64:
return ValueBuilder::makeBinary(left, GT, right);
case LeFloat32:
return makeAsmCoercion(ValueBuilder::makeBinary(left, LE, right),
ASM_FLOAT);
case LeFloat64:
return ValueBuilder::makeBinary(left, LE, right);
case LtFloat32:
return makeAsmCoercion(ValueBuilder::makeBinary(left, LT, right),
ASM_FLOAT);
case LtFloat64:
return ValueBuilder::makeBinary(left, LT, right);
default: {
std::cerr << "Unhandled i32 binary operator: " << curr << std::endl;
abort();
}
}
}
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));
} else {
return ValueBuilder::makeBinary(left, EQ, right);
}
}
case NeInt32: {
if (curr->left->type == i32) {
return ValueBuilder::makeBinary(makeSigning(left, ASM_SIGNED), NE,
makeSigning(right, ASM_SIGNED));
} else {
return ValueBuilder::makeBinary(left, NE, right);
case f32:
case f64:
switch (curr->op) {
case AddFloat32:
case AddFloat64:
ret = ValueBuilder::makeBinary(left, PLUS, right);
break;
case SubFloat32:
case SubFloat64:
ret = ValueBuilder::makeBinary(left, MINUS, right);
break;
case MulFloat32:
case MulFloat64:
ret = ValueBuilder::makeBinary(left, MUL, right);
break;
case DivFloat32:
case DivFloat64:
ret = ValueBuilder::makeBinary(left, DIV, right);
break;
case MinFloat32:
case MinFloat64:
ret = ValueBuilder::makeCall(MATH_MIN, left, right);
break;
case MaxFloat32:
case MaxFloat64:
ret = ValueBuilder::makeCall(MATH_MAX, left, right);
break;
case CopySignFloat32:
case CopySignFloat64:
default:
std::cerr << "Unhandled binary float operator: " << curr << std::endl;
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));
case RotLInt32:
return makeSigning(ValueBuilder::makeCall(WASM_ROTL32, left, right),
ASM_SIGNED);
case RotRInt32:
return makeSigning(ValueBuilder::makeCall(WASM_ROTR32, left, right),
ASM_SIGNED);
default: {
std::cerr << "Unhandled binary operator: " << curr << std::endl;
if (curr->type == f32) {
return makeAsmCoercion(ret, ASM_FLOAT);
}
return ret;
default:
std::cerr << "Unhandled type in binary: " << curr << std::endl;
abort();
}
}
return makeAsmCoercion(ret, wasmToAsmType(curr->type));
}
Expand Down
Loading