ref: a5a475be2a9d72c7e60bcc6f5b013ca655384d7a
parent: f65b0ec2cd01428bba712d7008329c60b0cfad60
author: Arusekk <floss@arusekk.pl>
date: Sat May 24 12:26:49 EDT 2025
cc: initialization of bitfields
This patch adds support for static (vector) initialization of
structs that contains bitfields. The original compiler only
supports dynamic initialization.
Initialization of automatic variables just works,
and is converted to dynamic initialization (assignment).
Static variables only work with no labels, so {1, 2} works,
while { .a = 1, .b = 2 } does not.
The initialization is deferred until the next distinct
bitfield offset or the end of structure.
Implementing the labels would require extra effort,
probably sorting the initializer by the offsets,
or finding all corresponding bitfields sharing an offset
{ .a_sub1 = 1, .b_sub1 = 1, .a_sub2 = 1 }.
Co-authored-by: Jonas Amoson <jonas.amoson@hv.se>
--- a/sys/src/cmd/cc/com.c
+++ b/sys/src/cmd/cc/com.c
@@ -81,6 +81,12 @@
diag(n, "unknown op in type complex: %O", n->op);
goto bad;
+ case OBIT:
+ if(tcom(l))
+ goto bad;
+ n->addable = l->addable;
+ break;
+
case ODOTDOT:
/*
* tcom has already been called on this subtree
--- a/sys/src/cmd/cc/dcl.c
+++ b/sys/src/cmd/cc/dcl.c
@@ -286,7 +286,9 @@
{Node *a, *l, *r, nod;
Type *t1;
- long e, w, so, mw;
+ long e, w, so, mw, bitoff;
+ static Node *bitagg;
+ static Type *bitaggt;
a = peekinit();
if(a == Z)
@@ -326,8 +328,6 @@
if(a == Z)
return Z;
- if(t->nbits)
- diag(Z, "cannot initialize bitfields");
if(s->class == CAUTO) {l = new(ONAME, Z, Z);
l->sym = s;
@@ -337,6 +337,10 @@
l->etype = s->type->etype;
l->xoffset = s->offset + o;
l->class = s->class;
+ if(t->nbits) {+ l = new(OBIT, l, Z);
+ l->type = t;
+ }
l = new(OASI, l, a);
return l;
@@ -370,8 +374,21 @@
}
if(vconst(a) == 0)
return Z;
+
+ if(t->nbits) {+ if(bitagg == Z)
+ bitagg = a;
+ a->vconst = (a->vconst & ((1ULL<<t->nbits) - 1)) << t->shift;
+ a->vconst = bitagg->vconst = a->vconst | bitagg->vconst;
+ return Z;
+ }
+
goto gext;
}
+ if(t->nbits) {+ diag(a, "initializer is not a constant: %s", s->name);
+ return Z;
+ }
if(t->etype == TIND) {if(a->op == OCAST)
warn(a, "CAST in initialization ignored");
@@ -491,6 +508,7 @@
return Z;
}
l = Z;
+ bitoff = -1;
again:
for(t1 = t->link; t1 != T; t1 = t1->down) {@@ -501,6 +519,15 @@
continue;
nextinit();
}
+ if(t1->nbits && (bitoff != t1->offset || !bitagg)) {+ if(a->op == OELEM && bitoff != -1)
+ diag(a, "named bitfield static initializers not supported %F", a);
+ if(bitagg)
+ gextern(s, bitagg, o+bitaggt->offset, bitaggt->width);
+ bitagg = Z;
+ bitaggt = t1;
+ bitoff = t1->offset;
+ }
r = init1(s, t1, o+t1->offset, 1);
l = newlist(l, r);
a = peekinit();
@@ -511,6 +538,11 @@
}
if(a && a->op == OELEM)
diag(a, "structure element not found %F", a);
+ if(bitoff != -1) {+ if(bitagg)
+ gextern(s, bitagg, o+bitaggt->offset, bitaggt->width);
+ bitagg = Z;
+ }
return l;
}
}
--
⑨