예제 #1
0
//---------------------------chain_rule----------------------------------------
// Starting at 'operand', check if we know how to automatically generate other results
void ArchDesc::chain_rule(FILE *fp, const char *indent, const char *operand,
                          const Expr *icost, const char *irule, Dict &operands_chained_from,  ProductionState &status) {

    // Check if we have already generated chains from this starting point
    if( operands_chained_from[operand] != NULL ) {
        return;
    } else {
        operands_chained_from.Insert( operand, operand);
    }
    if( debug_output ) {
        fprintf(fp, "// chain rules starting from: %s  and  %s \n", (char *)operand, (char *)irule);    // %%%%% Explanation
    }

    ChainList *lst = (ChainList *)_chainRules[operand];
    if (lst) {
        // printf("\nChain from <%s> at cost #%s\n",operand, icost ? icost : "_");
        const char *result, *cost, *rule;
        for(lst->reset(); (lst->iter(result,cost,rule)) == true; ) {
            // Do not generate operands that are already available
            if( operands_chained_from[result] != NULL ) {
                continue;
            } else {
                // Compute the cost for previous match + chain_rule_cost
                // total_cost = icost + cost;
                Expr *total_cost = icost->clone();  // icost + cost
                total_cost->add(cost, *this);

                // Check for transitive chain rules
                Form *form = (Form *)_globalNames[rule];
                if ( ! form->is_instruction()) {
                    // printf("   result=%s cost=%s rule=%s\n", result, total_cost, rule);
                    // Check against other match costs, and update cost & rule vectors
                    const char *reduce_rule = strcmp(irule,"Invalid") ? irule : rule;
                    cost_check(fp, indent, ArchDesc::getMachOperEnum(result), total_cost, reduce_rule, status);
                    chain_rule(fp, indent, result, total_cost, irule, operands_chained_from, status);
                } else {
                    // printf("   result=%s cost=%s rule=%s\n", result, total_cost, rule);
                    // Check against other match costs, and update cost & rule vectors
                    cost_check(fp, indent, ArchDesc::getMachOperEnum(result), total_cost, rule, status);
                    chain_rule(fp, indent, result, total_cost, rule, operands_chained_from, status);
                }

                // If this is a member of an operand class, update class cost & rule
                expand_opclass( fp, indent, total_cost, result, status );
            }
        }
    }
}