functions.c
// Insert IR_MOVE instructions before IR_ARG instructions for
// - the first 6 single-register args.
// - the first 8 floating point args.
// The dst of the move will be constrained so that rdi, rsi, xmm0, xmm1 etc are allocated to it.
Insert IR_MOVE instructions before IR_ARG instructions for
the first 6 single-register args.
the first 8 floating point args.
The dst of the move will be constrained so that rdi, rsi, xmm0, xmm1 etc are allocated to it.
Insert IR_MOVE instructions before IR_ARG instructions for the first 6 single - register args . the first 8 floating point args . The dst of the move will be constrained so that rdi rsi xmm0 xmm1 etc are allocated to it .
void add_function_call_arg_moves_for_preg_class(Function *function, int preg_class) {
    int function_call_count = make_function_call_count(function);
    int register_count = preg_class == PC_INT ? 6 : 8;
    Value **arg_values = malloc(sizeof(Value *) * function_call_count * register_count);
    memset(arg_values, 0, sizeof(Value *) * function_call_count * register_count);
    int *param_indexes = malloc(sizeof(int) * function_call_count * register_count);
    memset(param_indexes, -1, sizeof(int) * function_call_count * register_count);
    char *has_struct_or_union_return_values = malloc(sizeof(char) * function_call_count);
    memset(has_struct_or_union_return_values, 0, sizeof(char) * function_call_count);
    FunctionParamLocations **param_locations = malloc(sizeof(FunctionParamLocations *) * function_call_count * register_count);
    memset(param_locations, -1, sizeof(FunctionParamLocations *) * function_call_count * register_count);
    make_vreg_count(function, 0);
    for (Tac *ir = function->ir; ir; ir = ir->next) {
        if (ir->operation == IR_ARG) {
            FunctionParamLocations *pl = ir->src1->function_call_arg_locations;
            if (ir->src1->has_struct_or_union_return_value) has_struct_or_union_return_values[ir->src1->int_value] = 1;
            for (int loc = 0; loc < pl->count; loc++) {
                int function_call_register_arg_index = preg_class == PC_INT
                    ? pl->locations[loc].int_register
                    : pl->locations[loc].sse_register;
                if (function_call_register_arg_index >= 0) {
                    int i = ir->src1->int_value * register_count + function_call_register_arg_index;
                    arg_values[i] = ir->src2;
                    param_indexes[i] = ir->src1->function_call_arg_index;
                    param_locations[i] = pl;
                }
            }
        }
        if (ir->operation == IR_CALL) {
            Value **call_arg = &(arg_values[ir->src1->int_value * register_count]);
            int has_struct_or_union_return_value = has_struct_or_union_return_values[ir->src1->int_value];
            int *param_index = &(param_indexes[ir->src1->int_value * register_count]);
            FunctionParamLocations **pls = &(param_locations[ir->src1->int_value * register_count]);
            Function *called_function = ir->src1->type->function;
            Value **function_call_values = malloc(sizeof(Value *) * register_count);
            memset(function_call_values, 0, sizeof(Value *) * register_count);
            int i = 0;
            if (has_struct_or_union_return_value && preg_class == PC_INT) {
                call_arg++;
                param_index++;
                pls++;
                i++;
            }
            while (i < register_count && *call_arg) {
                call_arg++;
                param_index++;
                pls++;
                i++;
            }
            call_arg--;
            param_index--;
            pls--;
            i--;
            for (; i >= 0; i--) {
                if (has_struct_or_union_return_value && preg_class == PC_INT && i == 0) break;
                Type *type;
                int pi = *param_index;
                if (pi >= 0 && pi < called_function->param_count) {
                    type = called_function->param_types[pi];
                }
                else
                    type = apply_default_function_call_argument_promotions((*call_arg)->type);
                int function_call_vreg;
                Type *function_call_vreg_type;
                if (type->type == TYPE_STRUCT_OR_UNION) {
                    FunctionParamLocation *location = lookup_location(preg_class, i, *pls);
                    function_call_vreg = make_struct_or_union_arg_move_instructions(function, ir, *call_arg, preg_class, i, location, &arg_register_set);
                    function_call_vreg_type = preg_class == PC_INT ? new_type(TYPE_LONG) : new_type(TYPE_DOUBLE);
                }
                else {
                    if (type->type == TYPE_ARRAY) type = decay_array_to_pointer(type);
                    if (type->type == TYPE_ENUM) type = new_type(TYPE_INT);
                    function_call_vreg = add_arg_move_to_register(function, ir, type, *call_arg, preg_class, i, &arg_register_set);
                    function_call_vreg_type = (*call_arg)->type;
                }
                function_call_values[i] = new_value();
                function_call_values[i]->type = function_call_vreg_type;
                function_call_values[i]->vreg = function_call_vreg;
                call_arg--;
                param_index--;
                pls--;
            }
            add_ir_call_reg_instructions(ir, function_call_values, register_count);
        }
    }
}
void add_function_call_arg_moves_for_preg_class ( Function * function , int preg_class ) { int function_call_count = make_function_call_count ( function ) ; int register_count = preg_class == PC_INT ? 6 : 8 ; Value * * arg_values = malloc ( sizeof ( Value * ) * function_call_count * register_count ) ; memset ( arg_values , 0 , sizeof ( Value * ) * function_call_count * register_count ) ; int * param_indexes = malloc ( sizeof ( int ) * function_call_count * register_count ) ; memset ( param_indexes , -1 , sizeof ( int ) * function_call_count * register_count ) ; char * has_struct_or_union_return_values = malloc ( sizeof ( char ) * function_call_count ) ; memset ( has_struct_or_union_return_values , 0 , sizeof ( char ) * function_call_count ) ; FunctionParamLocations * * param_locations = malloc ( sizeof ( FunctionParamLocations * ) * function_call_count * register_count ) ; memset ( param_locations , -1 , sizeof ( FunctionParamLocations * ) * function_call_count * register_count ) ; make_vreg_count ( function , 0 ) ; for ( Tac * ir = function -> ir ; ir ; ir = ir -> next ) { if ( ir -> operation == IR_ARG ) { FunctionParamLocations * pl = ir -> src1 -> function_call_arg_locations ; if ( ir -> src1 -> has_struct_or_union_return_value ) has_struct_or_union_return_values [ ir -> src1 -> int_value ] = 1 ; for ( int loc = 0 ; loc < pl -> count ; loc ++ ) { int function_call_register_arg_index = preg_class == PC_INT ? pl -> locations [ loc ] . int_register : pl -> locations [ loc ] . sse_register ; if ( function_call_register_arg_index >= 0 ) { int i = ir -> src1 -> int_value * register_count + function_call_register_arg_index ; arg_values [ i ] = ir -> src2 ; param_indexes [ i ] = ir -> src1 -> function_call_arg_index ; param_locations [ i ] = pl ; } } } if ( ir -> operation == IR_CALL ) { Value * * call_arg = & ( arg_values [ ir -> src1 -> int_value * register_count ] ) ; int has_struct_or_union_return_value = has_struct_or_union_return_values [ ir -> src1 -> int_value ] ; int * param_index = & ( param_indexes [ ir -> src1 -> int_value * register_count ] ) ; FunctionParamLocations * * pls = & ( param_locations [ ir -> src1 -> int_value * register_count ] ) ; Function * called_function = ir -> src1 -> type -> function ; Value * * function_call_values = malloc ( sizeof ( Value * ) * register_count ) ; memset ( function_call_values , 0 , sizeof ( Value * ) * register_count ) ; int i = 0 ; if ( has_struct_or_union_return_value && preg_class == PC_INT ) { call_arg ++ ; param_index ++ ; pls ++ ; i ++ ; } while ( i < register_count && * call_arg ) { call_arg ++ ; param_index ++ ; pls ++ ; i ++ ; } call_arg -- ; param_index -- ; pls -- ; i -- ; for ( ; i >= 0 ; i -- ) { if ( has_struct_or_union_return_value && preg_class == PC_INT && i == 0 ) break ; Type * type ; int pi = * param_index ; if ( pi >= 0 && pi < called_function -> param_count ) { type = called_function -> param_types [ pi ] ; } else type = apply_default_function_call_argument_promotions ( ( * call_arg ) -> type ) ; int function_call_vreg ; Type * function_call_vreg_type ; if ( type -> type == TYPE_STRUCT_OR_UNION ) { FunctionParamLocation * location = lookup_location ( preg_class , i , * pls ) ; function_call_vreg = make_struct_or_union_arg_move_instructions ( function , ir , * call_arg , preg_class , i , location , & arg_register_set ) ; function_call_vreg_type = preg_class == PC_INT ? new_type ( TYPE_LONG ) : new_type ( TYPE_DOUBLE ) ; } else { if ( type -> type == TYPE_ARRAY ) type = decay_array_to_pointer ( type ) ; if ( type -> type == TYPE_ENUM ) type = new_type ( TYPE_INT ) ; function_call_vreg = add_arg_move_to_register ( function , ir , type , * call_arg , preg_class , i , & arg_register_set ) ; function_call_vreg_type = ( * call_arg ) -> type ; } function_call_values [ i ] = new_value ( ) ; function_call_values [ i ] -> type = function_call_vreg_type ; function_call_values [ i ] -> vreg = function_call_vreg ; call_arg -- ; param_index -- ; pls -- ; } add_ir_call_reg_instructions ( ir , function_call_values , register_count ) ; } } }
Insert IR_MOVE instructions before IR_ARG instructions for
 the first 6 single-register args.
Insert IR_MOVE instructions before IR_ARG instructions for the first 6 single - register args .
// Values of the passed argument, i.e. by the caller // param_indexes maps the register indexes to a parameter index, e.g. // foo(int i, long double ld, int j) will produce // param_indexes[0] = 0 // param_indexes[1] = 2 // Set to 1 if the function returns a struct in memory, which reserves rdi for a // pointer to the return address // Allocated registers that hold the argument value // Add the moves backwards so that arg 0 (rsi) is last. // Advance past the first parameter, which holds the pointer to the struct/union return value // Bail if we're doing integers and RDI is reserved for a struct/union // return value.