functions.c
// Load an 8-byte into an integer register. In the best case, a single move instruction
// is produced. In the worst case, 3 load instructions with 3 bit shifts & 3 bitwise ors.
// Try sizes in order of 8, 4, 2, 1.
// The code produced:
// size = 1     load char
// size = 2     load short
// size = 3     load short, load char, shift char, or char
// size = 4     load int
// size = 5     load int, load char, shift char, or char
// size = 6     load int, load short, shift short, or short
// size = 7     load int, load short, shift short, or short, load char, shift char, or char
// size = 8     load long
Load an 8-byte into an integer register. In the best case, a single move instruction
is produced. In the worst case, 3 load instructions with 3 bit shifts & 3 bitwise ors.
Try sizes in order of 8, 4, 2, 1.
Load an 8 - byte into an integer register . In the best case a single move instruction is produced . In the worst case 3 load instructions with 3 bit shifts & 3 bitwise ors . Try sizes in order of 8 4 2 1 .
static int make_int_struct_or_union_arg_move_instructions(
    Function *function, Tac *ir, Value *param, int preg_class, int register_index,
    FunctionParamLocation *pl, RegisterSet *register_set) {
    Value *result_register = new_value();
    result_register->type = new_type(TYPE_LONG);
    result_register->type->is_unsigned = 1;
    result_register->vreg = ++function->vreg_count;
    if (debug_function_arg_mapping) printf("Adding arg move from struct to integer register_index=%d register size=%d\n", register_index, pl->stru_size);
    int lvalue_in_register = param->is_lvalue && param->vreg;
    int temp_loaded = 0;
    int size = pl->stru_size;
    int offset = 0;
    for (int i = 3; i >= 0; i--) {
        int size_unit = 1 << i;
        if (size_unit > size) continue;
        if (!temp_loaded) {
            Type *type = new_type(TYPE_CHAR + i);
            type->is_unsigned = 1;
            load_struct_scalar_into_temp(function, ir, param, pl, type, result_register, offset);
            temp_loaded = 1;
        }
        else {
            Value *loaded_value = make_long_temp(function);
            Value *temp2 = dup_value(param);
            temp2->type = new_type(TYPE_CHAR + i);
            temp2->type->is_unsigned = 1;
            temp2->offset += pl->stru_offset + offset;
            insert_instruction_from_operation(ir, lvalue_in_register ? IR_INDIRECT : IR_MOVE, loaded_value, temp2, 0, 1);
            Value *shifted_value;
            if (offset) {
                shifted_value = make_long_temp(function);
                insert_instruction_from_operation(ir, IR_BSHL, shifted_value, loaded_value, new_integral_constant(TYPE_LONG, offset * 8), 1);
            }
            else
                shifted_value = loaded_value;
            Value *orred_value = make_long_temp(function);
            insert_instruction_from_operation(ir, IR_BOR, orred_value, shifted_value, result_register, 1);
            result_register = orred_value;
        }
        size -= size_unit;
        offset += size_unit;
        if (size == 0) break;
    }
    return add_arg_move_to_register(function, ir, new_type(TYPE_LONG), result_register, preg_class, register_index, register_set);
}
static int make_int_struct_or_union_arg_move_instructions ( Function * function , Tac * ir , Value * param , int preg_class , int register_index , FunctionParamLocation * pl , RegisterSet * register_set ) { Value * result_register = new_value ( ) ; result_register -> type = new_type ( TYPE_LONG ) ; result_register -> type -> is_unsigned = 1 ; result_register -> vreg = ++ function -> vreg_count ; if ( debug_function_arg_mapping ) printf ( " \n " , register_index , pl -> stru_size ) ; int lvalue_in_register = param -> is_lvalue && param -> vreg ; int temp_loaded = 0 ; int size = pl -> stru_size ; int offset = 0 ; for ( int i = 3 ; i >= 0 ; i -- ) { int size_unit = 1 << i ; if ( size_unit > size ) continue ; if ( ! temp_loaded ) { Type * type = new_type ( TYPE_CHAR + i ) ; type -> is_unsigned = 1 ; load_struct_scalar_into_temp ( function , ir , param , pl , type , result_register , offset ) ; temp_loaded = 1 ; } else { Value * loaded_value = make_long_temp ( function ) ; Value * temp2 = dup_value ( param ) ; temp2 -> type = new_type ( TYPE_CHAR + i ) ; temp2 -> type -> is_unsigned = 1 ; temp2 -> offset += pl -> stru_offset + offset ; insert_instruction_from_operation ( ir , lvalue_in_register ? IR_INDIRECT : IR_MOVE , loaded_value , temp2 , 0 , 1 ) ; Value * shifted_value ; if ( offset ) { shifted_value = make_long_temp ( function ) ; insert_instruction_from_operation ( ir , IR_BSHL , shifted_value , loaded_value , new_integral_constant ( TYPE_LONG , offset * 8 ) , 1 ) ; } else shifted_value = loaded_value ; Value * orred_value = make_long_temp ( function ) ; insert_instruction_from_operation ( ir , IR_BOR , orred_value , shifted_value , result_register , 1 ) ; result_register = orred_value ; } size -= size_unit ; offset += size_unit ; if ( size == 0 ) break ; } return add_arg_move_to_register ( function , ir , new_type ( TYPE_LONG ) , result_register , preg_class , register_index , register_set ) ; }
Load an 8-byte into an integer register.
Load an 8 - byte into an integer register .
// Make the shift register // Load value // Shift loaded value // Bitwise or shifted_value and put result in result_register