ir.c
// Load a bit field by loading the entire integer from a struct and bit shifting
Load a bit field by loading the entire integer from a struct and bit shifting
Load a bit field by loading the entire integer from a struct and bit shifting
static void add_load_bit_field(Function *function, Tac *ir) {
    int offset, bit_offset, bit_size;
    determine_bit_field_params(ir->src1, &offset, &bit_offset, &bit_size);
    Value *src1 = dup_value(ir->src1);
    src1->offset = offset;
    src1->bit_field_offset = 0;
    src1->bit_field_size = 0;
    Value *dst = ir->dst;
    Value *loaded_value = dup_value(ir->dst);
    loaded_value->vreg = ++function->vreg_count;
    ir->operation = IR_NOP;
    ir->dst = 0;
    ir->src1 = 0;
    ir->src2 = 0;
    if (src1->is_lvalue && src1->vreg) {
        Value *indirect_src1 = dup_value(src1);
        indirect_src1->type = make_pointer(loaded_value->type);
        indirect_src1->is_lvalue = 0;
        ir = insert_instruction_after_from_operation(ir, IR_INDIRECT, loaded_value, indirect_src1, 0);
    } else
        ir = insert_instruction_after_from_operation(ir, IR_MOVE, loaded_value, src1, 0);
    if (src1->type->is_unsigned) {
        Value *shifted_value;
        if (bit_offset) {
            shifted_value = dup_value(loaded_value);
            shifted_value->vreg = ++function->vreg_count;
            ir = insert_instruction_after_from_operation(ir, IR_BSHR, shifted_value, loaded_value, new_integral_constant(TYPE_INT, bit_offset));
        }
        else
            shifted_value = loaded_value;
        unsigned int mask = (1 << bit_size) - 1;
        ir = insert_instruction_after_from_operation(ir, IR_BAND, dst, shifted_value, new_integral_constant(TYPE_INT, mask));
    }
    else {
        Value *shifted_value;
        int left_shift_offset = 32 - bit_size - bit_offset;
        if (left_shift_offset) {
            shifted_value = dup_value(loaded_value);
            shifted_value->vreg = ++function->vreg_count;
            ir = insert_instruction_after_from_operation(ir, IR_BSHL, shifted_value, loaded_value, new_integral_constant(TYPE_INT, left_shift_offset));
        }
        else
            shifted_value = loaded_value;
        if (32 - bit_size)
            ir = insert_instruction_after_from_operation(ir, IR_ASHR, dst, shifted_value, new_integral_constant(TYPE_INT, 32 - bit_size));
        else
            dst = shifted_value;
    }
}
static void add_load_bit_field ( Function * function , Tac * ir ) { int offset , bit_offset , bit_size ; determine_bit_field_params ( ir -> src1 , & offset , & bit_offset , & bit_size ) ; Value * src1 = dup_value ( ir -> src1 ) ; src1 -> offset = offset ; src1 -> bit_field_offset = 0 ; src1 -> bit_field_size = 0 ; Value * dst = ir -> dst ; Value * loaded_value = dup_value ( ir -> dst ) ; loaded_value -> vreg = ++ function -> vreg_count ; ir -> operation = IR_NOP ; ir -> dst = 0 ; ir -> src1 = 0 ; ir -> src2 = 0 ; if ( src1 -> is_lvalue && src1 -> vreg ) { Value * indirect_src1 = dup_value ( src1 ) ; indirect_src1 -> type = make_pointer ( loaded_value -> type ) ; indirect_src1 -> is_lvalue = 0 ; ir = insert_instruction_after_from_operation ( ir , IR_INDIRECT , loaded_value , indirect_src1 , 0 ) ; } else ir = insert_instruction_after_from_operation ( ir , IR_MOVE , loaded_value , src1 , 0 ) ; if ( src1 -> type -> is_unsigned ) { Value * shifted_value ; if ( bit_offset ) { shifted_value = dup_value ( loaded_value ) ; shifted_value -> vreg = ++ function -> vreg_count ; ir = insert_instruction_after_from_operation ( ir , IR_BSHR , shifted_value , loaded_value , new_integral_constant ( TYPE_INT , bit_offset ) ) ; } else shifted_value = loaded_value ; unsigned int mask = ( 1 << bit_size ) - 1 ; ir = insert_instruction_after_from_operation ( ir , IR_BAND , dst , shifted_value , new_integral_constant ( TYPE_INT , mask ) ) ; } else { Value * shifted_value ; int left_shift_offset = 32 - bit_size - bit_offset ; if ( left_shift_offset ) { shifted_value = dup_value ( loaded_value ) ; shifted_value -> vreg = ++ function -> vreg_count ; ir = insert_instruction_after_from_operation ( ir , IR_BSHL , shifted_value , loaded_value , new_integral_constant ( TYPE_INT , left_shift_offset ) ) ; } else shifted_value = loaded_value ; if ( 32 - bit_size ) ir = insert_instruction_after_from_operation ( ir , IR_ASHR , dst , shifted_value , new_integral_constant ( TYPE_INT , 32 - bit_size ) ) ; else dst = shifted_value ; } }
Load a bit field by loading the entire integer from a struct and bit shifting
Load a bit field by loading the entire integer from a struct and bit shifting
// Make it a pointer and add an indirect instruction // Shift right // Apply mask // Shift left so that the value is at the end of the integer boundary // Sign extend by shifting right