예제 #1
0
파일: expr.c 프로젝트: Acidburn0zzz/yasm
int
yasm_expr__bc_dist_subst(yasm_expr **ep, void *cbd,
                         void (*callback) (unsigned int subst,
                                           yasm_bytecode *precbc,
                                           yasm_bytecode *precbc2,
                                           void *cbd))
{
    bc_dist_subst_cbd my_cbd;   /* callback info for low-level callback */
    my_cbd.callback = callback;
    my_cbd.cbd = cbd;
    my_cbd.subst = 0;
    *ep = yasm_expr__level_tree(*ep, 1, 1, 1, 0, &expr_xform_bc_dist_subst,
                                &my_cbd);
    return my_cbd.subst;
}
예제 #2
0
int
yasm_value_finalize(yasm_value *value, yasm_bytecode *precbc)
{
    if (!value->abs)
        return 0;

    value->abs = yasm_expr__level_tree(value->abs, 1, 1, 0, 0, NULL, NULL);

    /* quit early if there was an issue in simplify() */
    if (yasm_error_occurred())
        return 1;

    /* Strip top-level AND masking to an all-1s mask the same size
     * of the value size.  This allows forced avoidance of overflow warnings.
     */
    if (value->abs->op == YASM_EXPR_AND) {
        int term;

        /* Calculate 1<<size - 1 value */
        yasm_intnum *mask = yasm_intnum_create_uint(1);
        yasm_intnum *mask_tmp = yasm_intnum_create_uint(value->size);
        yasm_intnum_calc(mask, YASM_EXPR_SHL, mask_tmp);
        yasm_intnum_set_uint(mask_tmp, 1);
        yasm_intnum_calc(mask, YASM_EXPR_SUB, mask_tmp);
        yasm_intnum_destroy(mask_tmp);

        /* Walk terms and delete matching masks */
        for (term=value->abs->numterms-1; term>=0; term--) {
            if (value->abs->terms[term].type == YASM_EXPR_INT &&
                yasm_intnum_compare(value->abs->terms[term].data.intn,
                                    mask) == 0) {
                /* Delete the intnum */
                yasm_intnum_destroy(value->abs->terms[term].data.intn);

                /* Slide everything to its right over by 1 */
                if (term != value->abs->numterms-1) /* if it wasn't last.. */
                    memmove(&value->abs->terms[term],
                            &value->abs->terms[term+1],
                            (value->abs->numterms-1-term)*
                                sizeof(yasm_expr__item));

                /* Update numterms */
                value->abs->numterms--;

                /* Indicate warnings have been disabled */
                value->no_warn = 1;
            }
        }
        if (value->abs->numterms == 1)
            value->abs->op = YASM_EXPR_IDENT;
        yasm_intnum_destroy(mask);
    }

    /* Handle trivial (IDENT) cases immediately */
    if (value->abs->op == YASM_EXPR_IDENT) {
        switch (value->abs->terms[0].type) {
            case YASM_EXPR_INT:
                if (yasm_intnum_is_zero(value->abs->terms[0].data.intn)) {
                    yasm_expr_destroy(value->abs);
                    value->abs = NULL;
                }
                return 0;
            case YASM_EXPR_REG:
            case YASM_EXPR_FLOAT:
                return 0;
            case YASM_EXPR_SYM:
                value->rel = value->abs->terms[0].data.sym;
                yasm_expr_destroy(value->abs);
                value->abs = NULL;
                return 0;
            case YASM_EXPR_EXPR:
                /* Bring up lower values. */
                while (value->abs->op == YASM_EXPR_IDENT
                       && value->abs->terms[0].type == YASM_EXPR_EXPR) {
                    yasm_expr *sube = value->abs->terms[0].data.expn;
                    yasm_xfree(value->abs);
                    value->abs = sube;
                }
                break;
            default:
                yasm_internal_error(N_("unexpected expr term type"));
        }
    }

    if (value_finalize_scan(value, value->abs, precbc, 0))
        return 1;

    value->abs = yasm_expr__level_tree(value->abs, 1, 1, 0, 0, NULL, NULL);

    /* Simplify 0 in abs to NULL */
    if (value->abs->op == YASM_EXPR_IDENT
        && value->abs->terms[0].type == YASM_EXPR_INT
        && yasm_intnum_is_zero(value->abs->terms[0].data.intn)) {
        yasm_expr_destroy(value->abs);
        value->abs = NULL;
    }
    return 0;
}