/* Check the result of a ternary operation. */ static void check_result_for_ternary(const irop_t *op, const test_data_t *data) { const opnd_t *result = &data->result; const opnd_t *opnd1 = &data->opnds[0]; const opnd_t *opnd2 = &data->opnds[1]; const opnd_t *opnd3 = &data->opnds[2]; vbits_t expected_vbits; /* Only handle those undef-kinds that actually occur. */ switch (op->undef_kind) { case UNDEF_ALL: expected_vbits = undefined_vbits(result->vbits.num_bits); break; case UNDEF_SAME: // SAME with respect to the 1-bits in all operands expected_vbits = or_vbits(or_vbits(opnd1->vbits, opnd2->vbits), opnd3->vbits); break; default: panic(__func__); } if (! equal_vbits(result->vbits, expected_vbits)) complain(op, data, expected_vbits); }
/* Ity_I1 values cannot be stored or loaded. So vex_inject_ir will load/store such a value from/to a 4-byte container. It uses 32to1 and 1Uto32, respectively. */ static void valgrind_set_vbits(opnd_t *opnd) { unsigned rc, num_bytes; /* 1-bit wide values cannot be read. So we read a 4 bytes here */ num_bytes = opnd->type == Ity_I1 ? 4 : sizeof_irtype(opnd->type); rc = VALGRIND_SET_VBITS(&opnd->value, &opnd->vbits.bits, num_bytes); assert(rc == 1); // Make sure the v-bits were set correctly vbits_t actual = { .num_bits = opnd->vbits.num_bits }; rc = VALGRIND_GET_VBITS(&opnd->value, &actual.bits, num_bytes); assert(rc == 1); assert(equal_vbits(opnd->vbits, actual)); } static void valgrind_get_vbits(opnd_t *opnd) { unsigned rc, num_bytes; /* 1-bit wide values cannot be stored. So we store them by writing a single byte */ num_bytes = opnd->type == Ity_I1 ? 4 : sizeof_irtype(opnd->type); opnd->vbits.num_bits = bitsof_irtype(opnd->type); rc = VALGRIND_GET_VBITS(&opnd->value, &opnd->vbits.bits, num_bytes); assert(rc == 1); }
void print_opnd(FILE *fp, const opnd_t *opnd) { fprintf(fp, "vbits = "); print_vbits(fp, opnd->vbits); /* Write the value only if it is defined. Otherwise, there will be error messages about it being undefined */ if (equal_vbits(opnd->vbits, defined_vbits(opnd->vbits.num_bits))) { fprintf(fp, " value = "); print_value(fp, opnd->value, opnd->vbits.num_bits); } }
/* Check the result of a ternary operation. */ static void check_result_for_ternary(const irop_t *op, const test_data_t *data) { const opnd_t *result = &data->result; const opnd_t *opnd1 = &data->opnds[0]; const opnd_t *opnd2 = &data->opnds[1]; const opnd_t *opnd3 = &data->opnds[2]; vbits_t expected_vbits; /* Only handle those undef-kinds that actually occur. */ switch (op->undef_kind) { case UNDEF_ALL: expected_vbits = undefined_vbits(result->vbits.num_bits); break; case UNDEF_SAME: // SAME with respect to the 1-bits in all operands expected_vbits = or_vbits(or_vbits(opnd1->vbits, opnd2->vbits), opnd3->vbits); break; case UNDEF_SOME: expected_vbits.num_bits = result->vbits.num_bits; if ((result->vbits.bits.u128[0] != 0) || (result->vbits.bits.u128[1] != 0)) { expected_vbits.bits.u128[0] = result->vbits.bits.u128[0]; expected_vbits.bits.u128[1] = result->vbits.bits.u128[1]; } else { /* The input had at least one vbit set but the result doesn't have any * bit set. Set them all so we will trigger the error on the call * to complain(). */ expected_vbits.bits.u128[0] = ~0x0ULL; expected_vbits.bits.u128[1] = ~0x0ULL; } break; default: panic(__func__); } if (! equal_vbits(result->vbits, expected_vbits)) complain(op, data, expected_vbits); }
/* Check the result of a unary operation. */ static void check_result_for_unary(const irop_t *op, const test_data_t *data) { const opnd_t *result = &data->result; const opnd_t *opnd = &data->opnds[0]; unsigned num_bits = result->vbits.num_bits; vbits_t expected_vbits; /* Only handle those undef-kinds that actually occur. */ switch (op->undef_kind) { case UNDEF_ALL: expected_vbits = undefined_vbits(num_bits); break; case UNDEF_SAME: expected_vbits = opnd->vbits; break; case UNDEF_TRUNC: expected_vbits = truncate_vbits(opnd->vbits, num_bits); break; case UNDEF_LEFT: expected_vbits = left_vbits(opnd->vbits, num_bits); break; case UNDEF_UPPER: assert(num_bits * 2 == opnd->vbits.num_bits); expected_vbits = upper_vbits(opnd->vbits); break; case UNDEF_SEXT: expected_vbits = sextend_vbits(opnd->vbits, num_bits); break; case UNDEF_ZEXT: expected_vbits = zextend_vbits(opnd->vbits, num_bits); break; default: panic(__func__); } if (! equal_vbits(result->vbits, expected_vbits)) complain(op, data, expected_vbits); }