From 17b0e3a1a1017a3f2afc8fd47fc7451d65eb33cd Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 2 Dec 2018 19:27:42 +0000 Subject: [PATCH] Fix bit sets with custom endian underlying type --- core/fmt/fmt.odin | 40 ++++++++++++++++++++++++++++++++++++---- src/ir.cpp | 9 ++++----- src/ir_print.cpp | 8 ++++++++ src/types.cpp | 12 ++++++++---- 4 files changed, 56 insertions(+), 13 deletions(-) diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index 202a65ebb..229e72fc3 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -834,6 +834,25 @@ enum_value_to_u64 :: proc(ev: runtime.Type_Info_Enum_Value) -> u64 { } fmt_bit_set :: proc(fi: ^Fmt_Info, v: any, name: string = "") { + is_bit_set_different_endian_to_platform :: proc(ti: ^runtime.Type_Info, ) -> bool { + if ti == nil { + return false; + } + ti = runtime.type_info_base(ti); + switch info in ti.variant { + case runtime.Type_Info_Integer: + using runtime.Type_Info_Endianness; + switch info.endianness { + case Platform: return false; + case Little: return ODIN_ENDIAN != "little"; + case Big: return ODIN_ENDIAN != "big"; + } + } + return false; + } + + byte_swap :: bits.byte_swap; + type_info := type_info_of(v.id); switch info in type_info.variant { case runtime.Type_Info_Named: @@ -845,12 +864,25 @@ fmt_bit_set :: proc(fi: ^Fmt_Info, v: any, name: string = "") { bits: u64; bit_size := u64(8*type_info.size); + do_byte_swap := is_bit_set_different_endian_to_platform(info.underlying); + switch bit_size { case 0: bits = 0; - case 8: bits = u64( (^u8)(v.data)^); - case 16: bits = u64((^u16)(v.data)^); - case 32: bits = u64((^u32)(v.data)^); - case 64: bits = u64((^u64)(v.data)^); + case 8: + x := (^u8)(v.data)^; + bits = u64(x); + case 16: + x := (^u16)(v.data)^; + if do_byte_swap do x = byte_swap(x); + bits = u64(x); + case 32: + x := (^u32)(v.data)^; + if do_byte_swap do x = byte_swap(x); + bits = u64(x); + case 64: + x := (^u64)(v.data)^; + if do_byte_swap do x = byte_swap(x); + bits = u64(x); case: panic("unknown bit_size size"); } diff --git a/src/ir.cpp b/src/ir.cpp index 49482b7ea..bf595251e 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -6250,13 +6250,13 @@ irValue *ir_build_expr_internal(irProcedure *proc, Ast *expr) { Type *key_type = rt->BitSet.elem; GB_ASSERT(are_types_identical(ir_type(left), key_type)); + Type *it = bit_set_to_int(rt); - left = ir_emit_conv(proc, left, it); irValue *lower = ir_value_constant(it, exact_value_i64(rt->BitSet.lower)); - irValue *key = ir_emit_arith(proc, Token_Sub, left, lower, it); - irValue *bit = ir_emit_arith(proc, Token_Shl, v_one, key, it); - + irValue *key = ir_emit_arith(proc, Token_Sub, left, lower, ir_type(left)); + irValue *bit = ir_emit_arith(proc, Token_Shl, v_one, key, ir_type(left)); + bit = ir_emit_conv(proc, bit, it); irValue *old_value = ir_emit_bitcast(proc, right, it); irValue *new_value = ir_emit_arith(proc, Token_And, old_value, bit, it); @@ -7228,7 +7228,6 @@ irAddr ir_build_addr(irProcedure *proc, Ast *expr) { } case Type_BitSet: { - i64 sz = type_size_of(type); if (cl->elems.count > 0 && sz > 0) { ir_emit_store(proc, v, ir_add_module_constant(proc->module, type, exact_value_compound(expr))); diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 298e722e2..2536679d0 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -890,6 +890,14 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type * i64 lower = type->BitSet.lower; bits |= 1ull<kind == Type_BitSet) { - return is_type_integer_endian_big(t->BitSet.elem); + return is_type_integer_endian_big(bit_set_to_int(t)); } else { GB_PANIC("Unsupported type: %s", type_to_string); } @@ -1054,7 +1054,7 @@ bool is_type_integer_endian_little(Type *t) { } return build_context.endian_kind == TargetEndian_Little; } else if (t->kind == Type_BitSet) { - return is_type_integer_endian_little(t->BitSet.elem); + return is_type_integer_endian_little(bit_set_to_int(t)); } else { GB_PANIC("Unsupported type: %s", type_to_string); } @@ -1074,7 +1074,7 @@ bool is_type_different_to_arch_endianness(Type *t) { Type *integer_endian_type_to_platform_type(Type *t) { t = core_type(t); if (t->kind == Type_BitSet) { - t = core_type(t->BitSet.elem); + t = bit_set_to_int(t); } GB_ASSERT(t->kind == Type_Basic); @@ -2919,6 +2919,10 @@ gbString write_type_to_string(gbString str, Type *type) { case Type_BitSet: str = gb_string_appendc(str, "bit_set["); str = write_type_to_string(str, type->BitSet.elem); + if (type->BitSet.underlying != nullptr) { + str = gb_string_appendc(str, "; "); + str = write_type_to_string(str, type->BitSet.underlying); + } str = gb_string_appendc(str, "]"); break; }