diff options
| author | gingerBill <bill@gingerbill.org> | 2019-05-04 13:02:15 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2019-05-04 13:02:15 +0100 |
| commit | a46a1f5f34d281ecede1b446fea7be8834496da5 (patch) | |
| tree | badacc472ce50c6ee0fda26fdee4e6b521af0455 /src/ir.cpp | |
| parent | 40135cbc667b5991e00ff7d9fc2d638f94b9fb9b (diff) | |
Minor change to bit_field assignment rules
Diffstat (limited to 'src/ir.cpp')
| -rw-r--r-- | src/ir.cpp | 48 |
1 files changed, 36 insertions, 12 deletions
diff --git a/src/ir.cpp b/src/ir.cpp index 315810d80..08960efab 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -186,7 +186,7 @@ gbAllocator ir_allocator(void) { }) \ IR_INSTR_KIND(ZeroInit, struct { irValue *address; }) \ IR_INSTR_KIND(Store, struct { irValue *address, *value; bool is_volatile; }) \ - IR_INSTR_KIND(Load, struct { Type *type; irValue *address; }) \ + IR_INSTR_KIND(Load, struct { Type *type; irValue *address; i64 custom_align; }) \ IR_INSTR_KIND(AtomicFence, struct { BuiltinProcId id; }) \ IR_INSTR_KIND(AtomicStore, struct { \ irValue *address, *value; \ @@ -848,7 +848,7 @@ void ir_module_add_value (irModule *m, Entity *e, irValue *v); void ir_emit_zero_init (irProcedure *p, irValue *address, Ast *expr); irValue *ir_emit_comment (irProcedure *p, String text); irValue *ir_emit_store (irProcedure *p, irValue *address, irValue *value, bool is_volatile=false); -irValue *ir_emit_load (irProcedure *p, irValue *address); +irValue *ir_emit_load (irProcedure *p, irValue *address, i64 custom_align=0); void ir_emit_jump (irProcedure *proc, irBlock *block); irValue *ir_emit_conv (irProcedure *proc, irValue *value, Type *t); irValue *ir_type_info (irProcedure *proc, Type *type); @@ -2793,14 +2793,16 @@ irValue *ir_emit_store(irProcedure *p, irValue *address, irValue *value, bool is } return ir_emit(p, ir_instr_store(p, address, value, is_volatile)); } -irValue *ir_emit_load(irProcedure *p, irValue *address) { +irValue *ir_emit_load(irProcedure *p, irValue *address, i64 custom_align) { GB_ASSERT(address != nullptr); Type *t = type_deref(ir_type(address)); // if (is_type_boolean(t)) { // return ir_emit(p, ir_instr_load_bool(p, address)); // } if (address) address->uses += 1; - return ir_emit(p, ir_instr_load(p, address)); + auto instr = ir_instr_load(p, address); + instr->Instr.Load.custom_align = custom_align; + return ir_emit(p, instr); } irValue *ir_emit_select(irProcedure *p, irValue *cond, irValue *t, irValue *f) { if (cond) cond->uses += 1; @@ -3340,6 +3342,7 @@ void ir_addr_store(irProcedure *proc, irAddr const &addr, irValue *value) { i32 offset = bft->BitField.offsets[value_index]; i32 size_in_bits = bft->BitField.fields[value_index]->type->BitFieldValue.bits; + i32 byte_index = offset / 8; i32 bit_inset = offset % 8; @@ -3349,6 +3352,9 @@ void ir_addr_store(irProcedure *proc, irAddr const &addr, irValue *value) { return; } + gb_printf_err("bit_field_size, %d %d %d\n", size_in_bits, byte_index, bit_inset); + + Type *int_type = nullptr; switch (size_in_bytes) { case 1: int_type = t_u8; break; @@ -3373,32 +3379,50 @@ void ir_addr_store(irProcedure *proc, irAddr const &addr, irValue *value) { v = ir_emit_arith(proc, Token_Shr, v, shift_amount, int_type); } irValue *ptr = ir_emit_conv(proc, bytes, alloc_type_pointer(int_type)); - v = ir_emit_arith(proc, Token_Or, ir_emit_load(proc, ptr), v, int_type); + + irValue *sv = ir_emit_load(proc, ptr, 1); + // NOTE(bill): Zero out the lower bits that need to be stored to + sv = ir_emit_arith(proc, Token_Shr, sv, ir_const_int(size_in_bits), int_type); + sv = ir_emit_arith(proc, Token_Shl, sv, ir_const_int(size_in_bits), int_type); + + v = ir_emit_arith(proc, Token_Or, sv, v, int_type); ir_emit_store(proc, ptr, v, true); return; } + GB_ASSERT(0 < bit_inset && bit_inset < 8); // First byte { - i32 sa = 8 - bit_inset; - irValue *shift_amount = ir_const_int(sa); + irValue *shift_amount = ir_const_int(bit_inset); + irValue *v = ir_emit_conv(proc, value, t_u8); v = ir_emit_arith(proc, Token_Shl, v, shift_amount, int_type); - v = ir_emit_arith(proc, Token_Or, ir_emit_load(proc, bytes), v, int_type); - ir_emit_store(proc, bytes, v, true); + irValue *sv = ir_emit_load(proc, bytes, 1); + // NOTE(bill): Zero out the upper bits that need to be stored to + sv = ir_emit_arith(proc, Token_Shl, sv, ir_const_int(bit_inset), int_type); + sv = ir_emit_arith(proc, Token_Shr, sv, ir_const_int(bit_inset), int_type); + + v = ir_emit_arith(proc, Token_Or, sv, v, int_type); + ir_emit_store(proc, bytes, v, true); } // Remaining bytes - { + if (bit_inset+size_in_bits > 8) { irValue *shift_amount = ir_const_int(bit_inset); irValue *ptr = ir_emit_conv(proc, ir_emit_ptr_offset(proc, bytes, v_one), alloc_type_pointer(int_type)); irValue *v = ir_emit_arith(proc, Token_Shr, value, shift_amount, int_type); - v = ir_emit_arith(proc, Token_Or, ir_emit_load(proc, ptr), v, int_type); + + irValue *sv = ir_emit_load(proc, ptr, 1); + // NOTE(bill): Zero out the lower bits that need to be stored to + sv = ir_emit_arith(proc, Token_Shr, sv, ir_const_int(size_in_bits-bit_inset), int_type); + sv = ir_emit_arith(proc, Token_Shl, sv, ir_const_int(size_in_bits-bit_inset), int_type); + + v = ir_emit_arith(proc, Token_Or, sv, v, int_type); ir_emit_store(proc, ptr, v, true); - return; } + return; } else if (addr.kind == irAddr_Context) { irValue *old = ir_emit_load(proc, ir_find_or_generate_context_ptr(proc)); irValue *next = ir_add_local_generated(proc, t_context, true); |