void BytecodeTranslatorVisitor::processNumericOperation(TokenKind op) { castTopsToCommonType(); switch (op) { case tADD: EMIT(TYPED(ADD)); break; case tSUB: EMIT(TYPED(SUB)); break; case tMUL: EMIT(TYPED(MUL)); break; default : EMIT(TYPED(DIV)); break; } popType(); ensureTopIsNumeric(); }
void BytecodeTranslatorVisitor::visitUnaryOpNode(UnaryOpNode* node) { onVisitNode(node); VISIT(node->operand()); switch (node->kind()) { case tNOT: { ensureTopType(VT_INT); /* if (!3.14) should fail */ Label L_True(bytecode()); Label L_End(bytecode()); EMIT(BC_ILOAD0); EMIT_BRANCH(BC_IFICMPE, L_True); EMIT(BC_ILOAD0); EMIT_BRANCH(BC_JA, L_End); EMIT_BIND(L_True); EMIT(BC_ILOAD1); EMIT_BIND(L_End); break; } case tSUB: ensureTopIsNumeric(); EMIT(TYPED(NEG)); break; default: ERROR("Unknown unary op"); } }
void BytecodeTranslatorVisitor::visitStoreNode(StoreNode* node) { onVisitNode(node); visitTyped(node->value(), node->var()->type()); pushType(node->var()->type()); if (node->op() == tINCRSET || node->op() == tDECRSET) { ensureTopIsNumeric(); EMIT_LOAD(node->var()); if (node->op() == tINCRSET) EMIT(TYPED(ADD)); else EMIT(TYPED(SUB)); } else if (node->op() != tASSIGN) ERROR("Invalid store operation"); EMIT_STORE(node->var()); popType(); pushType(VT_VOID); /* a = b = c is forbidden */ }
void BytecodeTranslatorVisitor::falseJump(AstNode* node, Label& label) { bool isComparison = false; if (node->isBinaryOpNode()) { TokenKind kind = node->asBinaryOpNode()->kind(); if (tEQ <= kind && kind <= tLE) isComparison = true; } if (!isComparison) { visitTyped(node, VT_INT); EMIT(BC_ILOAD0); EMIT_BRANCH(BC_IFICMPE, label); } else { /* Premature optimization is the root of all evil */ VISIT(node->asBinaryOpNode()->right()); ensureTopIsNumeric(); VISIT(node->asBinaryOpNode()->left()); ensureTopIsNumeric(); TokenKind kind = node->asBinaryOpNode()->kind(); castTopsToCommonType(); Instruction cmp = TYPED(CMP); bool hack = topType() == VT_INT; popType(); popType(); if (!hack) { EMIT(cmp); EMIT(BC_ILOAD0); } switch (kind) { case tEQ: EMIT_BRANCH(BC_IFICMPNE, label); break; case tNEQ: EMIT_BRANCH(BC_IFICMPE, label); break; case tGT: EMIT_BRANCH(hack ? BC_IFICMPLE : BC_IFICMPGE, label); break; case tGE: EMIT_BRANCH(hack ? BC_IFICMPL : BC_IFICMPG, label); break; case tLT: EMIT_BRANCH(hack ? BC_IFICMPGE : BC_IFICMPLE, label); break; default: EMIT_BRANCH(hack ? BC_IFICMPG : BC_IFICMPL, label); break; } } }
int main (void) { union { __m128i v; TYPE i[sizeof (__m128i) / sizeof (TYPE)]; } u, v; int i; u.v = foo (); v.v = bar (); for (i = 0; i < sizeof (u.i) / sizeof (u.i[0]); i++) { if (u.i[i] != ~v.i[i]) abort (); if (i < 3) { if (u.i[i] != (TYPED (0x11111111) << i)) abort (); } else if (u.i[i]) abort (); } return 0; }
void BytecodeTranslatorVisitor::processComparison(TokenKind kind) { castTopsToCommonType(); Instruction cmp = TYPED(CMP); int hack = topType() == VT_INT ? 3 : 0; popType(); popType(); pushType(VT_INT); if (kind == tNEQ) { EMIT(cmp); return; } if (!hack) { EMIT(cmp); EMIT(BC_ILOAD0); } Label L_Fail(bytecode()); Label L_End(bytecode()); switch (kind) { case tEQ: EMIT_BRANCH(BC_IFICMPE, L_Fail); break; case tGT: EMIT_BRANCH(BC_IFICMPG, L_Fail); break; case tGE: EMIT_BRANCH(BC_IFICMPGE, L_Fail); break; case tLT: EMIT_BRANCH(BC_IFICMPL, L_Fail); break; default : EMIT_BRANCH(BC_IFICMPLE, L_Fail); break; } EMIT(BC_ILOAD1 - hack); EMIT_BRANCH(BC_JA, L_End); EMIT_BIND(L_Fail); EMIT(BC_ILOAD0 + hack); EMIT_BIND(L_End); }