functions.c
// Move struct or union of size <= 32 into rax/rdx or xmm0/xmm1
Move struct or union of size <= 32 into rax/rdx or xmm0/xmm1
Move struct or union of size < = 32 into rax / rdx or xmm0 / xmm1
static void add_function_return_moves_for_struct_or_union(Function *function, Tac *ir, char *identifier) {
    FunctionParamAllocation *fpa = init_function_param_allocaton(identifier);
    add_function_param_to_allocation(fpa, ir->src1->type);
    FunctionParamLocations *fpl = &(fpa->params[0]);
    Value **function_call_values = malloc(sizeof(Value *) * 2);
    memset(function_call_values, 0, sizeof(Value *) * 2);
    if (fpl->locations[0].stack_offset != -1) {
        ir->operation = IR_NOP;
        Value *src1 = dup_value(ir->src1);
        src1->type = make_pointer_to_void();
        Value *dst = dup_value(function->return_value_pointer);
        dst->is_lvalue = 1;
        int size = get_type_size(ir->src1->type);
        ir = add_memory_copy(function, ir, dst, src1, size);
        dst = new_value();
        dst->type = make_pointer_to_void();
        dst->live_range_preg = LIVE_RANGE_PREG_RAX_INDEX;
        dst->type = make_pointer_to_void();
        dst->vreg = ++function->vreg_count;
        ir = insert_instruction_after_from_operation(ir, IR_MOVE, dst, function->return_value_pointer, 0);
        ir = insert_instruction_after_from_operation(ir, IR_RETURN, 0, 0, 0);
    }
    else {
        for (int loc = fpl->count - 1; loc >= 0; loc--) {
            FunctionParamLocation *location = &(fpl->locations[loc]);
            int preg_class = (location->int_register != -1) ? PC_INT : PC_SSE;
            int register_index = (preg_class == PC_INT) ? location->int_register : location->sse_register;
            Value *param = ir->src1;
            int vreg = make_struct_or_union_arg_move_instructions(function, ir, param, preg_class, register_index, location, &function_return_value_register_set);
            function_call_values[loc] = new_value();
            function_call_values[loc]->type = preg_class == PC_INT ? new_type(TYPE_LONG) : new_type(TYPE_DOUBLE);
            function_call_values[loc]->vreg = vreg;
        }
        add_ir_call_reg_instructions(ir, function_call_values, 2);
    }
}
static void add_function_return_moves_for_struct_or_union ( Function * function , Tac * ir , char * identifier ) { FunctionParamAllocation * fpa = init_function_param_allocaton ( identifier ) ; add_function_param_to_allocation ( fpa , ir -> src1 -> type ) ; FunctionParamLocations * fpl = & ( fpa -> params [ 0 ] ) ; Value * * function_call_values = malloc ( sizeof ( Value * ) * 2 ) ; memset ( function_call_values , 0 , sizeof ( Value * ) * 2 ) ; if ( fpl -> locations [ 0 ] . stack_offset != -1 ) { ir -> operation = IR_NOP ; Value * src1 = dup_value ( ir -> src1 ) ; src1 -> type = make_pointer_to_void ( ) ; Value * dst = dup_value ( function -> return_value_pointer ) ; dst -> is_lvalue = 1 ; int size = get_type_size ( ir -> src1 -> type ) ; ir = add_memory_copy ( function , ir , dst , src1 , size ) ; dst = new_value ( ) ; dst -> type = make_pointer_to_void ( ) ; dst -> live_range_preg = LIVE_RANGE_PREG_RAX_INDEX ; dst -> type = make_pointer_to_void ( ) ; dst -> vreg = ++ function -> vreg_count ; ir = insert_instruction_after_from_operation ( ir , IR_MOVE , dst , function -> return_value_pointer , 0 ) ; ir = insert_instruction_after_from_operation ( ir , IR_RETURN , 0 , 0 , 0 ) ; } else { for ( int loc = fpl -> count - 1 ; loc >= 0 ; loc -- ) { FunctionParamLocation * location = & ( fpl -> locations [ loc ] ) ; int preg_class = ( location -> int_register != -1 ) ? PC_INT : PC_SSE ; int register_index = ( preg_class == PC_INT ) ? location -> int_register : location -> sse_register ; Value * param = ir -> src1 ; int vreg = make_struct_or_union_arg_move_instructions ( function , ir , param , preg_class , register_index , location , & function_return_value_register_set ) ; function_call_values [ loc ] = new_value ( ) ; function_call_values [ loc ] -> type = preg_class == PC_INT ? new_type ( TYPE_LONG ) : new_type ( TYPE_DOUBLE ) ; function_call_values [ loc ] -> vreg = vreg ; } add_ir_call_reg_instructions ( ir , function_call_values , 2 ) ; } }
Move struct or union of size <= 32 into rax/rdx or xmm0/xmm1
Move struct or union of size < = 32 into rax / rdx or xmm0 / xmm1
// Determine registers // Move data into memory // Convert src1 to be a pointer to void // Add move of the target pointer to rax // Move the data into registers // Add instructions to ensure the values stay in the registers