Browse Source

Minor change to bit_field assignment rules

gingerBill 6 years ago
parent
commit
a46a1f5f34
4 changed files with 44 additions and 17 deletions
  1. 1 1
      src/check_stmt.cpp
  2. 36 12
      src/ir.cpp
  3. 7 3
      src/ir_print.cpp
  4. 0 1
      src/types.cpp

+ 1 - 1
src/check_stmt.cpp

@@ -264,7 +264,7 @@ Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, Operand *rhs)
 						}
 						}
 
 
 						BigInt imax = big_int_make_u64(imax_);
 						BigInt imax = big_int_make_u64(imax_);
-						if (big_int_cmp(&i, &imax) >= 0) {
+						if (big_int_cmp(&i, &imax) <= 0) {
 							return rhs->type;
 							return rhs->type;
 						}
 						}
 					}
 					}

+ 36 - 12
src/ir.cpp

@@ -186,7 +186,7 @@ gbAllocator ir_allocator(void) {
 	})                                                                \
 	})                                                                \
 	IR_INSTR_KIND(ZeroInit, struct { irValue *address; })             \
 	IR_INSTR_KIND(ZeroInit, struct { irValue *address; })             \
 	IR_INSTR_KIND(Store,    struct { irValue *address, *value; bool is_volatile; }) \
 	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(AtomicFence, struct { BuiltinProcId id; })          \
 	IR_INSTR_KIND(AtomicStore, struct {                               \
 	IR_INSTR_KIND(AtomicStore, struct {                               \
 		irValue *address, *value;                                     \
 		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);
 void     ir_emit_zero_init      (irProcedure *p, irValue *address, Ast *expr);
 irValue *ir_emit_comment        (irProcedure *p, String text);
 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_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);
 void     ir_emit_jump           (irProcedure *proc, irBlock *block);
 irValue *ir_emit_conv           (irProcedure *proc, irValue *value, Type *t);
 irValue *ir_emit_conv           (irProcedure *proc, irValue *value, Type *t);
 irValue *ir_type_info           (irProcedure *proc, Type *type);
 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));
 	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);
 	GB_ASSERT(address != nullptr);
 	Type *t = type_deref(ir_type(address));
 	Type *t = type_deref(ir_type(address));
 	// if (is_type_boolean(t)) {
 	// if (is_type_boolean(t)) {
 		// return ir_emit(p, ir_instr_load_bool(p, address));
 		// return ir_emit(p, ir_instr_load_bool(p, address));
 	// }
 	// }
 	if (address) address->uses += 1;
 	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) {
 irValue *ir_emit_select(irProcedure *p, irValue *cond, irValue *t, irValue *f) {
 	if (cond) cond->uses += 1;
 	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 offset = bft->BitField.offsets[value_index];
 		i32 size_in_bits = bft->BitField.fields[value_index]->type->BitFieldValue.bits;
 		i32 size_in_bits = bft->BitField.fields[value_index]->type->BitFieldValue.bits;
 
 
+
 		i32 byte_index = offset / 8;
 		i32 byte_index = offset / 8;
 		i32 bit_inset = offset % 8;
 		i32 bit_inset = offset % 8;
 
 
@@ -3349,6 +3352,9 @@ void ir_addr_store(irProcedure *proc, irAddr const &addr, irValue *value) {
 			return;
 			return;
 		}
 		}
 
 
+		gb_printf_err("bit_field_size, %d %d %d\n", size_in_bits, byte_index, bit_inset);
+
+
 		Type *int_type = nullptr;
 		Type *int_type = nullptr;
 		switch (size_in_bytes) {
 		switch (size_in_bytes) {
 		case 1:  int_type = t_u8;   break;
 		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);
 				v = ir_emit_arith(proc, Token_Shr, v, shift_amount, int_type);
 			}
 			}
 			irValue *ptr = ir_emit_conv(proc, bytes, alloc_type_pointer(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);
 			ir_emit_store(proc, ptr, v, true);
 			return;
 			return;
 		}
 		}
 
 
+		GB_ASSERT(0 < bit_inset && bit_inset < 8);
 
 
 		// First byte
 		// 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);
 			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_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
 		// Remaining bytes
-		{
+		if (bit_inset+size_in_bits > 8) {
 			irValue *shift_amount = ir_const_int(bit_inset);
 			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 *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);
 			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);
 			ir_emit_store(proc, ptr, v, true);
-			return;
 		}
 		}
+		return;
 	} else if (addr.kind == irAddr_Context) {
 	} else if (addr.kind == irAddr_Context) {
 		irValue *old = ir_emit_load(proc, ir_find_or_generate_context_ptr(proc));
 		irValue *old = ir_emit_load(proc, ir_find_or_generate_context_ptr(proc));
 		irValue *next = ir_add_local_generated(proc, t_context, true);
 		irValue *next = ir_add_local_generated(proc, t_context, true);

+ 7 - 3
src/ir_print.cpp

@@ -558,9 +558,9 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t, bool in_struct) {
 	case Type_BitField: {
 	case Type_BitField: {
 		i64 align = type_align_of(t);
 		i64 align = type_align_of(t);
 		i64 size  = type_size_of(t);
 		i64 size  = type_size_of(t);
-		ir_write_byte(f, '{');
+		ir_write_string(f, str_lit("<{"));
 		ir_print_alignment_prefix_hack(f, align);
 		ir_print_alignment_prefix_hack(f, align);
-		ir_fprintf(f, ", [%lld x i8]}", size);
+		ir_fprintf(f, ", [%lld x i8]}>", size);
 		break;
 		break;
 	}
 	}
 
 
@@ -1190,7 +1190,11 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
 		ir_print_type(f, m, type);
 		ir_print_type(f, m, type);
 		ir_write_str_lit(f, "* ");
 		ir_write_str_lit(f, "* ");
 		ir_print_value(f, m, instr->Load.address, type);
 		ir_print_value(f, m, instr->Load.address, type);
-		ir_fprintf(f, ", align %lld", type_align_of(type));
+		if (instr->Load.custom_align > 0) {
+			ir_fprintf(f, ", align %lld", instr->Load.custom_align);
+		} else {
+			ir_fprintf(f, ", align %lld", type_align_of(type));
+		}
 		ir_print_debug_location(f, m, value);
 		ir_print_debug_location(f, m, value);
 		break;
 		break;
 	}
 	}

+ 0 - 1
src/types.cpp

@@ -2953,7 +2953,6 @@ gbString write_type_to_string(gbString str, Type *type) {
 			Entity *f = type->BitField.fields[i];
 			Entity *f = type->BitField.fields[i];
 			GB_ASSERT(f->kind == Entity_Variable);
 			GB_ASSERT(f->kind == Entity_Variable);
 			GB_ASSERT(f->type != nullptr && f->type->kind == Type_BitFieldValue);
 			GB_ASSERT(f->type != nullptr && f->type->kind == Type_BitFieldValue);
-			str = gb_string_append_rune(str, '{');
 			if (i > 0) {
 			if (i > 0) {
 				str = gb_string_appendc(str, ", ");
 				str = gb_string_appendc(str, ", ");
 			}
 			}