aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2018-12-02 19:27:42 +0000
committergingerBill <bill@gingerbill.org>2018-12-02 19:27:42 +0000
commit17b0e3a1a1017a3f2afc8fd47fc7451d65eb33cd (patch)
treef028923c2bb40dbcc7b22eb1327b0446fe28686e /src
parent28583bfff88ff1378a0e71030701071dcfd37462 (diff)
Fix bit sets with custom endian underlying type
Diffstat (limited to 'src')
-rw-r--r--src/ir.cpp9
-rw-r--r--src/ir_print.cpp8
-rw-r--r--src/types.cpp12
3 files changed, 20 insertions, 9 deletions
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<<cast(u64)(v-lower);
}
+ if (is_type_different_to_arch_endianness(type)) {
+ i64 size = type_size_of(type);
+ switch (size) {
+ case 2: bits = cast(u64)gb_endian_swap16(cast(u16)bits); break;
+ case 4: bits = cast(u64)gb_endian_swap32(cast(u32)bits); break;
+ case 8: bits = cast(u64)gb_endian_swap64(cast(u64)bits); break;
+ }
+ }
ir_write_u64(f, bits);
} else {
ir_write_str_lit(f, "zeroinitializer");
diff --git a/src/types.cpp b/src/types.cpp
index b2dca25bd..09fdce3f1 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -500,7 +500,7 @@ i64 type_align_of (Type *t);
i64 type_offset_of (Type *t, i32 index);
gbString type_to_string (Type *type);
void init_map_internal_types(Type *type);
-
+Type * bit_set_to_int(Type *t);
Type *base_type(Type *t) {
@@ -1037,7 +1037,7 @@ bool is_type_integer_endian_big(Type *t) {
}
return build_context.endian_kind == TargetEndian_Big;
} else if (t->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;
}