/* Look for simple "left" identities like 0+x, 1*x, etc. */ static int expr_can_destroy_int_left(yasm_expr_op op, yasm_intnum *intn) { int iszero = yasm_intnum_is_zero(intn); return ((yasm_intnum_is_pos1(intn) && op == YASM_EXPR_MUL) || (iszero && op == YASM_EXPR_ADD) || (yasm_intnum_is_neg1(intn) && op == YASM_EXPR_AND) || (!iszero && op == YASM_EXPR_LAND) || (iszero && op == YASM_EXPR_OR) || (iszero && op == YASM_EXPR_LOR)); }
/* Look for simple "right" identities like x+|-0, x*&/1 */ static int expr_can_destroy_int_right(yasm_expr_op op, yasm_intnum *intn) { int iszero = yasm_intnum_is_zero(intn); int ispos1 = yasm_intnum_is_pos1(intn); return ((ispos1 && op == YASM_EXPR_MUL) || (ispos1 && op == YASM_EXPR_DIV) || (iszero && op == YASM_EXPR_ADD) || (iszero && op == YASM_EXPR_SUB) || (yasm_intnum_is_neg1(intn) && op == YASM_EXPR_AND) || (!iszero && op == YASM_EXPR_LAND) || (iszero && op == YASM_EXPR_OR) || (iszero && op == YASM_EXPR_LOR) || (iszero && op == YASM_EXPR_SHL) || (iszero && op == YASM_EXPR_SHR)); }
static int run_input_test(Test_Entry *test) { char *valstr = yasm__xstrdup(test->input); yasm_intnum *intn = yasm_intnum_create_hex(valstr); yasm_intnum *testn; unsigned long size; yasm_xfree(valstr); if (test->negate) yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL); testn = yasm_intnum_create_leb128(test->result, test->sign, &size); if (size != test->outsize) { yasm_intnum_destroy(testn); yasm_intnum_destroy(intn); sprintf(failmsg, "%ssigned %s%s create() bad size: expected %lu, got %lu!", test->sign?"":"un", test->negate?"-":"", test->input, test->outsize, size); return 1; } yasm_intnum_calc(intn, YASM_EXPR_EQ, testn); if (!yasm_intnum_is_pos1(intn)) { yasm_intnum_destroy(testn); yasm_intnum_destroy(intn); sprintf(failmsg, "%ssigned %s%s create() bad output!", test->sign?"":"un", test->negate?"-":"", test->input); return 1; } yasm_intnum_destroy(testn); yasm_intnum_destroy(intn); return 0; }
/* Check for and simplify identities. Returns new number of expr terms. * Sets e->op = EXPR_IDENT if numterms ends up being 1. * Uses numterms parameter instead of e->numterms for basis of "new" number * of terms. * Assumes int_term is *only* integer term in e. * NOTE: Really designed to only be used by expr_level_op(). */ static int expr_simplify_identity(yasm_expr *e, int numterms, int *int_term, int simplify_reg_mul) { int i; int save_numterms; /* Don't do this step if it's 1*REG. Save and restore numterms so * yasm_expr__contains() works correctly. */ save_numterms = e->numterms; e->numterms = numterms; if (simplify_reg_mul || e->op != YASM_EXPR_MUL || !yasm_intnum_is_pos1(e->terms[*int_term].data.intn) || !yasm_expr__contains(e, YASM_EXPR_REG)) { /* Check for simple identities that delete the intnum. * Don't delete if the intnum is the only thing in the expn. */ if ((*int_term == 0 && numterms > 1 && expr_can_destroy_int_left(e->op, e->terms[0].data.intn)) || (*int_term > 0 && expr_can_destroy_int_right(e->op, e->terms[*int_term].data.intn))) { /* Delete the intnum */ yasm_intnum_destroy(e->terms[*int_term].data.intn); /* Slide everything to its right over by 1 */ if (*int_term != numterms-1) /* if it wasn't last.. */ memmove(&e->terms[*int_term], &e->terms[*int_term+1], (numterms-1-*int_term)*sizeof(yasm_expr__item)); /* Update numterms */ numterms--; *int_term = -1; /* no longer an int term */ } } e->numterms = save_numterms; /* Check for simple identites that delete everything BUT the intnum. * Don't bother if the intnum is the only thing in the expn. */ if (numterms > 1 && *int_term != -1 && expr_is_constant(e->op, e->terms[*int_term].data.intn)) { /* Loop through, deleting everything but the integer term */ for (i=0; i<e->numterms; i++) if (i != *int_term) expr_delete_term(&e->terms[i], 1); /* Move integer term to the first term (if not already there) */ if (*int_term != 0) e->terms[0] = e->terms[*int_term]; /* structure copy */ /* Set numterms to 1 */ numterms = 1; } /* Compute NOT, NEG, and LNOT on single intnum. */ if (numterms == 1 && *int_term == 0 && (e->op == YASM_EXPR_NOT || e->op == YASM_EXPR_NEG || e->op == YASM_EXPR_LNOT)) yasm_intnum_calc(e->terms[0].data.intn, e->op, NULL); /* Change expression to IDENT if possible. */ if (numterms == 1) e->op = YASM_EXPR_IDENT; /* Return the updated numterms */ return numterms; }