aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2024-06-05 15:43:15 +0100
committergingerBill <bill@gingerbill.org>2024-06-05 15:43:15 +0100
commitcbabcb0907e6430571c14d21fcb09c150275d99b (patch)
treecd1f5601d46eb4dee27d4c39973fda80a0104769 /src
parentc406bbb6e3c05118b97c3ee30d6a2efc4c4b870f (diff)
Fix #3682
Diffstat (limited to 'src')
-rw-r--r--src/check_expr.cpp7
-rw-r--r--src/llvm_backend_expr.cpp20
-rw-r--r--src/types.cpp9
3 files changed, 34 insertions, 2 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 0830f65bd..d2d01deda 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -8866,6 +8866,10 @@ gb_internal void check_compound_literal_field_values(CheckerContext *c, Slice<As
case Type_Array:
ft = bt->Array.elem;
break;
+ case Type_BitField:
+ is_constant = false;
+ ft = bt->BitField.fields[index]->type;
+ break;
default:
GB_PANIC("invalid type: %s", type_to_string(ft));
break;
@@ -8892,6 +8896,9 @@ gb_internal void check_compound_literal_field_values(CheckerContext *c, Slice<As
case Type_Array:
nested_ft = bt->Array.elem;
break;
+ case Type_BitField:
+ nested_ft = bt->BitField.fields[index]->type;
+ break;
default:
GB_PANIC("invalid type %s", type_to_string(nested_ft));
break;
diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp
index c12489598..7772ba930 100644
--- a/src/llvm_backend_expr.cpp
+++ b/src/llvm_backend_expr.cpp
@@ -4533,10 +4533,26 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
if (lb_is_nested_possibly_constant(type, sel, elem)) {
continue;
}
- lbValue dst = lb_emit_deep_field_gep(p, comp_lit_ptr, sel);
field_expr = lb_build_expr(p, elem);
field_expr = lb_emit_conv(p, field_expr, sel.entity->type);
- lb_emit_store(p, dst, field_expr);
+ if (sel.is_bit_field) {
+ Selection sub_sel = trim_selection(sel);
+ lbValue trimmed_dst = lb_emit_deep_field_gep(p, comp_lit_ptr, sub_sel);
+ Type *bf = base_type(type_deref(trimmed_dst.type));
+ if (is_type_pointer(bf)) {
+ trimmed_dst = lb_emit_load(p, trimmed_dst);
+ bf = base_type(type_deref(trimmed_dst.type));
+ }
+ GB_ASSERT(bf->kind == Type_BitField);
+
+ isize idx = sel.index[sel.index.count-1];
+ lbAddr dst = lb_addr_bit_field(trimmed_dst, bf->BitField.fields[idx]->type, bf->BitField.bit_offsets[idx], bf->BitField.bit_sizes[idx]);
+ lb_addr_store(p, dst, field_expr);
+
+ } else {
+ lbValue dst = lb_emit_deep_field_gep(p, comp_lit_ptr, sel);
+ lb_emit_store(p, dst, field_expr);
+ }
continue;
}
diff --git a/src/types.cpp b/src/types.cpp
index e568d2af2..618e5bd8a 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -457,6 +457,15 @@ gb_internal Selection sub_selection(Selection const &sel, isize offset) {
return res;
}
+gb_internal Selection trim_selection(Selection const &sel) {
+ Selection res = {};
+ res.index.data = sel.index.data;
+ res.index.count = gb_max(sel.index.count - 1, 0);
+ res.index.capacity = res.index.count;
+ return res;
+}
+
+
gb_global Type basic_types[] = {
{Type_Basic, {Basic_Invalid, 0, 0, STR_LIT("invalid type")}},