Example #1
0
exprtree*
make_for (scanner_ident_t *counter_name_ident, exprtree *counter_init, exprtree *start, exprtree *end, exprtree *body)
{
    scanner_region_t region = counter_name_ident->region;

    if (start->result.length != 1 || end->result.length != 1 || start->result.number != end->result.number)
    {
	sprintf(error_string, _("The start and end of a for loop interval must be tuples of the same tag and length 1."));
	error_region = region;
	JUMP(1);
    }
    else
    {
	char end_name_buf[MAX_GENSYM_LEN];
	char *end_name = gensym(end_name_buf);
	scanner_ident_t *end_name_ident = scanner_make_ident(scanner_null_region, end_name);
	exprtree *end_init = make_assignment(end_name_ident, end);
	exprtree *init = make_sequence(counter_init, end_init);
	exprtree *inc = make_assignment(counter_name_ident,
					make_function_from_string("__add",
								  exprlist_append(make_var(counter_name_ident),
										  make_int_number(1, scanner_null_region)),
								  scanner_null_region));
	exprtree *invariant = make_function_from_string("__lessequal", exprlist_append(make_var(counter_name_ident),
										       make_var(end_name_ident)),
							scanner_null_region);

	free(end_name_ident);

	return make_sequence(init, make_while(invariant, make_sequence(body, inc)));
    }
}
Example #2
0
/**
 * For binary operations, there are two cases that need special treatment:
 *     a = k # a
 *     a = b # a
 * If # is commutable then these can be reversed.  Otherwise they will be
 * translated to t = a; a = k/b # t.
 * After the first phase there are three cases that are already in i386 form:
 *     a = a # a
 *     a = a # b
 *     a = a # k
 * There are five cases that need processing:
 *     a = k # k   (should really be handled by constant optimisation)
 *     a = k # b
 *     a = b # k
 *     a = b # b
 *     a = b # c
 * All are translated to a = (k/b); a = a # (k/b/c)
 */
static int i386ify_binary_operation(MODULE *module, FUNCTION *func, NODE *vertex)
{
    GRAPH *graph = func->graph;
    VARIABLE *dest = tree_get_child(vertex, 0);
    EXPRESSION *expr = tree_get_child(vertex, 1);
    EXPRESSION *arg0 = tree_get_child(expr, 0);
    EXPRESSION *arg1 = tree_get_child(expr, 1);
    
    int source_line = CAST_TO_AST(vertex)->source_line;
    
    /* First deal with special cases, where the first argument is not the
       destination but the second argument is. */
    if (!is_same_var(CAST_TO_EXPRESSION(dest), arg0) && is_same_var(CAST_TO_EXPRESSION(dest), arg1))
    {
        if (is_commutable_op(expr))
        {
            tree_get_child(expr, 0) = arg1;
            tree_get_child(expr, 1) = arg0;
        }
        else
        {
            TYPE *new_temp_type = arg1->type;
            EXPRESSION *new_temp = make_new_temp(module, func, new_temp_type, source_line);
            STATEMENT *new_assign = make_assignment(new_temp, arg1, source_line);
            tree_get_child(expr, 1) = tree_copy(new_temp);
            add_vertex(graph, CAST_TO_NODE(new_assign));
            replace_backward(graph, vertex, CAST_TO_NODE(new_assign), 0);
            add_edge(graph, CAST_TO_NODE(new_assign), vertex, 0);
        }
        
        /* Reset these as the above operations may have changed them, */
        arg0 = tree_get_child(expr, 0);
        arg1 = tree_get_child(expr, 1);
    }
    
    /* If instruction is already in i386 form, we don't need to process it. */
    if (is_same_var(CAST_TO_EXPRESSION(dest), arg0))
        return 0;
    
    /* Otherwise, translate a = b # c to a = b; a = a # c. */
    STATEMENT *new_assign = make_assignment(CAST_TO_EXPRESSION(tree_copy(dest)), arg0, source_line);
    tree_get_child(expr, 0) = tree_copy(dest);
    add_vertex(graph, CAST_TO_NODE(new_assign));
    replace_backward(graph, vertex, CAST_TO_NODE(new_assign), 0);
    add_edge(graph, CAST_TO_NODE(new_assign), vertex, 0);
        
    return 1;
}
Example #3
0
EXPRESSION *atomise_expression(MODULE *module, FUNCTION *func, BLOCK *block, EXPRESSION *expr, STATEMENT *before)
{
    if (is_atomic(expr))
        return expr;
    
    if (tree_is_type(expr, EXPR_TUPLE))
    {
        EXPRESSION *new_temp = make_empty_tuple(CAST_TO_AST(expr)->source_line);
        int i;
        for (i = 0; i < tree_num_children(expr); i++)
            tree_add_child(new_temp, atomise_expression(module, func, block, tree_get_child(expr, i), before));
        return new_temp;
    }
    
    EXPRESSION *new_temp = make_new_temp(module, func, expr->type, CAST_TO_AST(expr)->source_line);
    STATEMENT *new_assign = make_assignment(new_temp, expr, CAST_TO_AST(expr)->source_line);
    
    if (has_graph(func))
    {
        GRAPH *graph = func->graph;
        add_vertex(graph, CAST_TO_NODE(new_assign));
        inject_before(graph, CAST_TO_NODE(new_assign), CAST_TO_NODE(before), 0);
    }
    else
        tree_add_before(CAST_TO_NODE(block), CAST_TO_NODE(new_assign), CAST_TO_NODE(before));
    
    return new_temp;
}
Example #4
0
static STATEMENT *reduce_statement(MODULE *module, FUNCTION *func, BLOCK *block, STATEMENT *stmt)
{
    if (stmt == NULL)
        return stmt;
    
    if (tree_is_type(stmt, STMT_ASSIGN))
    {
        EXPRESSION *expr = tree_get_child(stmt, 1);
        expr = simplify_expression(module, func, block, expr, stmt);
        tree_get_child(stmt, 1) = expr;
    }
    else if (tree_is_type(stmt, STMT_IF))
    {
        EXPRESSION *cond = tree_get_child(stmt, 0);
        cond = simplify_expression(module, func, block, cond, stmt);
        tree_get_child(stmt, 0) = cond;
        reduce_block(module, func, tree_get_child(stmt, 1));
        reduce_block(module, func, tree_get_child(stmt, 2));
    }
    else if (tree_is_type(stmt, STMT_WHILE))
    {
        EXPRESSION *cond = tree_get_child(stmt, 0);
        BLOCK *body = tree_get_child(stmt, 1);
        if (!is_atomic(cond))
        {
            EXPRESSION *old_cond = cond;
            cond = atomise_expression(module, func, block, cond, stmt);
            tree_get_child(stmt, 0) = cond;
            STATEMENT *new_assign = make_assignment(cond, CAST_TO_EXPRESSION(tree_copy(old_cond)), CAST_TO_AST(cond)->source_line);
            tree_add_child(body, new_assign);
        }
        reduce_block(module, func, body);
    }
    else if (tree_is_type(stmt, STMT_RETURN))
    {
        EXPRESSION *expr = tree_get_child(stmt, 0);
        expr = atomise_expression(module, func, block, expr, stmt);
        tree_get_child(stmt, 0) = expr;
    }
    else if (tree_is_type(stmt, STMT_RESTART))
    {
        /* Do nothing. */
    }
    else
        error("Not sure how to reduce statement of type %d\n", tree_type(stmt));
    
    return stmt;
}
Example #5
0
/**
 * For unary operations, one case is already in i386 form:
 *     a = #a
 * There are two cases which need processing:
 *     a = #k   (should really be handled by constant optimisation)
 *     a = #b
 * These are both translated to a = k/b; a = #a
 */
static int i386ify_unary_operation(MODULE *module, FUNCTION *func, NODE *vertex)
{
    GRAPH *graph = func->graph;
    VARIABLE *dest = tree_get_child(vertex, 0);
    EXPRESSION *expr = tree_get_child(vertex, 1);
    EXPRESSION *arg0 = tree_get_child(expr, 0);
    
    if (is_same_var(CAST_TO_EXPRESSION(dest), arg0))
        return 0;
    
    STATEMENT *new_assign = make_assignment(CAST_TO_EXPRESSION(tree_copy(dest)), arg0, CAST_TO_AST(vertex)->source_line);
    tree_get_child(expr, 0) = tree_copy(dest);
    add_vertex(graph, CAST_TO_NODE(new_assign));
    replace_backward(graph, vertex, CAST_TO_NODE(new_assign), 0);
    add_edge(graph, CAST_TO_NODE(new_assign), vertex, 0);
    
    return 1;
}
Example #6
0
static int i386ify_assignment(MODULE *module, FUNCTION *func, NODE *vertex)
{
    int changed = 0;
    GRAPH *graph = func->graph;
    VARIABLE *dest = tree_get_child(vertex, 0);
    EXPRESSION *expr = tree_get_child(vertex, 1);
    
    int source_line = CAST_TO_AST(vertex)->source_line;
    
    if (is_unary_op(expr))
        changed |= i386ify_unary_operation(module, func, vertex);
    
    if (is_binary_op(expr))
        changed |= i386ify_binary_operation(module, func, vertex);
    
    /* Expand tuple assignments. */
    if (tree_is_type(dest, EXPR_TUPLE) && tree_num_children(dest) >= 1)
    {
        int i;
        NODE *last = NULL;
        if (tree_num_children(dest) != tree_num_children(expr))
            error("Source and destinations have different cardinality!");
        for (i = 0; i < tree_num_children(dest); i++)
        {
            VARIABLE *dest2 = tree_get_child(dest, i);
            VARIABLE *src2 = tree_get_child(expr, i);
            STATEMENT *new_assign = make_assignment(CAST_TO_EXPRESSION(dest2), CAST_TO_EXPRESSION(src2), source_line);
            add_vertex(graph, CAST_TO_NODE(new_assign));
            if (last)
                add_edge(graph, last, CAST_TO_NODE(new_assign), 0);
            else
                replace_backward(graph, vertex, CAST_TO_NODE(new_assign), 0);
            last = CAST_TO_NODE(new_assign);
        }
        replace_forward(graph, vertex, last, 0);
        remove_vertex(graph, vertex);
        changed |= 1;
    }
    
    return changed;
}
Example #7
0
static EXPRESSION *simplify_expression(MODULE *module, FUNCTION *func, BLOCK *block, EXPRESSION *expr, STATEMENT *before)
{
    int i;
    
    int source_line = CAST_TO_AST(expr)->source_line;
    
    if (!has_graph(func) && is_short_circuit(expr))
    {
        TYPE *new_temp_type = CAST_TO_EXPRESSION(tree_get_child(expr, 0))->type;
        EXPRESSION *new_temp = make_new_temp(module, func, new_temp_type, source_line);
        STATEMENT *new_assign = make_assignment(new_temp, tree_get_child(expr, 0), source_line);
        tree_add_before(CAST_TO_NODE(block), CAST_TO_NODE(new_assign), CAST_TO_NODE(before));
        STATEMENT *new_assign2 = make_assignment(new_temp, tree_get_child(expr, 1), source_line);
        EXPRESSION *new_cond = new_temp;
        if (tree_is_type(expr, EXPR_OR))
            new_cond = make_unary_expression(EXPR_NOT, new_cond, source_line);
        STATEMENT *new_if = make_if(new_cond, make_block(NULL, new_assign2, 0), NULL, 0);
        tree_add_before(CAST_TO_NODE(block), CAST_TO_NODE(new_if), CAST_TO_NODE(before));
        return new_temp;
    }
    
    if (has_graph(func) && is_short_circuit(expr))
    {
        GRAPH *graph = func->graph;
        
        EXPRESSION *sub0 = tree_get_child(expr, 0);
        EXPRESSION *sub1 = tree_get_child(expr, 1);
        
        STATEMENT *new_test = make_test(sub0, source_line);
        
        EDGE_TYPE inner_type = tree_is_type(expr, EXPR_OR) ? EDGE_NO : EDGE_YES;
        EDGE_TYPE outer_type = tree_is_type(expr, EXPR_OR) ? EDGE_YES : EDGE_NO;
        
        add_vertex(graph, CAST_TO_NODE(new_test));
        HASH *subhash = get_from_hash(graph->forward, before, sizeof(void *));
        HASH_ITERATOR iter;
        for (hash_iterator(subhash, &iter); hash_iterator_valid(&iter); hash_iterator_next(&iter))
        {
            EDGE_TYPE type = (EDGE_TYPE) iter.entry->data;
            if (outer_type & type)
                add_edge(graph, CAST_TO_NODE(new_test), iter.entry->key, type);
            if (inner_type & type)
                inner_type = type;
        }
        inject_before(graph, CAST_TO_NODE(new_test), CAST_TO_NODE(before), inner_type);        
        
        return sub1;
    }
    
    if (is_simple(expr))
        return expr;
    
    if (tree_is_type(expr, EXPR_CALL))
    {
        EXPRESSION *args = CAST_TO_EXPRESSION(tree_get_child(expr, 1));
        args = atomise_expression(module, func, block, args, before);
        tree_get_child(expr, 1) = args;
        return expr;
    }
    
    for (i = 0; i < tree_num_children(expr); i++)
    {
        EXPRESSION *child = tree_get_child(expr, i);
        if (!is_atomic(child))
        {
            TYPE *new_temp_type = CAST_TO_EXPRESSION(child)->type;
            EXPRESSION *new_temp = make_new_temp(module, func, new_temp_type, CAST_TO_AST(child)->source_line);
            STATEMENT *new_assign = make_assignment(new_temp, child, CAST_TO_AST(child)->source_line);
            
            if (has_graph(func))
            {
                GRAPH *graph = func->graph;
                add_vertex(graph, CAST_TO_NODE(new_assign));
                inject_before(graph, CAST_TO_NODE(new_assign), CAST_TO_NODE(before), 0);
            }
            else
                tree_add_before(CAST_TO_NODE(block), CAST_TO_NODE(new_assign), CAST_TO_NODE(before));
            
            tree_get_child(expr, i) = new_temp;
        }
    }
    
    return expr;
}