Rework bit-field initialization.

This generally simplifies things, and always generates individual initializer records for each explicit initialization of a bit-field (which was previously done for automatic initialization, but not static).

This should work correctly for automatic initialization, but needs corresponding code changes in GenSymbols for static initialization.
This commit is contained in:
Stephen Heumann 2022-11-28 18:49:49 -06:00
parent adfa7c04c1
commit a3c4eeb8f6

View File

@ -1854,8 +1854,6 @@ procedure Initializer (var variable: identPtr);
{ variable - ptr to the identifier begin initialized } { variable - ptr to the identifier begin initialized }
var var
bitcount: integer; {# if bits initialized}
bitvalue: longint; {bit field initializer value}
disp: longint; {disp within overall object being initialized} disp: longint; {disp within overall object being initialized}
done: boolean; {for loop termination} done: boolean; {for loop termination}
errorFound: boolean; {used to remove bad initializations} errorFound: boolean; {used to remove bad initializations}
@ -1882,46 +1880,6 @@ var
end; {InsertInitializerRecord} end; {InsertInitializerRecord}
procedure InitializeBitField;
{ If bit fields have been initialized, fill them in }
{ }
{ Inputs: }
{ bitcount - # of bits initialized }
{ bitvalue - value of initializer }
var
iPtr: initializerPtr; {for creating an initializer entry}
begin {InitializeBitField}
if bitcount <> 0 then begin {skip if there has been no initializer}
{ writeln('InitializeBitField; bitcount = ', bitcount:1); {debug}
{create the initializer entry}
iPtr := pointer(Malloc(sizeof(initializerRecord)));
iPtr^.isConstant := isConstant;
iPtr^.count := 1;
iPtr^.bitdisp := 0;
iPtr^.bitsize := 0;
iPtr^.iVal := bitvalue;
if bitcount <= 8 then
iPtr^.basetype := cgUByte
else if bitcount <= 24 then
iPtr^.basetype := cgUWord
else
iPtr^.basetype := cgULong;
InsertInitializerRecord(iPtr, TypeSize(iPtr^.basetype));
if bitcount in [17..24] then begin {3-byte bitfield: split into two parts}
iPtr^.iVal := bitvalue & $0000FFFF;
bitcount := bitcount - 16;
bitvalue := bitvalue >> 16;
InitializeBitField;
end;
bitcount := 0; {reset the bit field values}
bitvalue := 0;
end; {if}
end; {InitializeBitField}
procedure GetInitializerValue (tp: typePtr; bitsize,bitdisp: integer); procedure GetInitializerValue (tp: typePtr; bitsize,bitdisp: integer);
{ get the value of an initializer from a single expression } { get the value of an initializer from a single expression }
@ -1931,10 +1889,9 @@ var
{ bitsize - size of bit field (0 for non-bit fields) } { bitsize - size of bit field (0 for non-bit fields) }
{ bitdisp - disp of bit field; unused if bitsize = 0 } { bitdisp - disp of bit field; unused if bitsize = 0 }
label 1,2,3; label 1,2;
var var
bitmask: longint; {used to add a value to a bit field}
bKind: baseTypeEnum; {type of constant} bKind: baseTypeEnum; {type of constant}
etype: typePtr; {expression type} etype: typePtr; {expression type}
i: integer; {loop variable} i: integer; {loop variable}
@ -1943,6 +1900,7 @@ var
kind: tokenEnum; {kind of constant} kind: tokenEnum; {kind of constant}
offset, offset2: longint; {integer offset from a pointer} offset, offset2: longint; {integer offset from a pointer}
operator: tokenEnum; {operator for constant pointers} operator: tokenEnum; {operator for constant pointers}
size: longint; {size of item being initialized}
tKind: typeKind; {type of constant} tKind: typeKind; {type of constant}
tree: tokenPtr; {for evaluating pointer constants} tree: tokenPtr; {for evaluating pointer constants}
@ -2056,31 +2014,30 @@ var
Expression(autoInitializerExpression, [commach,rparench,rbracech]) Expression(autoInitializerExpression, [commach,rparench,rbracech])
else else
Expression(initializerExpression, [commach,rparench,rbracech]); Expression(initializerExpression, [commach,rparench,rbracech]);
if bitsize = 0 then begin iPtr := pointer(Malloc(sizeof(initializerRecord)));
iPtr := pointer(Malloc(sizeof(initializerRecord))); if bitsize <> 0 then
InsertInitializerRecord(iPtr, tp^.size); size := (bitdisp + bitsize + 7) div 8
iPtr^.isConstant := isConstant; else
iPtr^.count := 1; size := tp^.size;
iPtr^.bitdisp := 0; InsertInitializerRecord(iPtr, size);
iPtr^.bitsize := 0; iPtr^.isConstant := isConstant;
end; {if} iPtr^.count := 1;
iPtr^.bitdisp := bitdisp;
iPtr^.bitsize := bitsize;
etype := expressionType; etype := expressionType;
AssignmentConversion(tp, expressionType, isConstant, expressionValue, AssignmentConversion(tp, expressionType, isConstant, expressionValue,
false, false); false, false);
if variable^.storage = external then if variable^.storage = external then
variable^.storage := global; variable^.storage := global;
if isConstant and (variable^.storage in [external,global,private]) then begin if isConstant and (variable^.storage in [external,global,private]) then begin
if bitsize = 0 then begin if etype^.baseType in [cgQuad,cgUQuad] then begin
if etype^.baseType in [cgQuad,cgUQuad] then begin iPtr^.qVal := llExpressionValue;
iPtr^.qVal := llExpressionValue; end {if}
end {if} else begin
else begin iPtr^.qval.hi := 0;
iPtr^.qval.hi := 0; iPtr^.iVal := expressionValue;
iPtr^.iVal := expressionValue; end; {else}
end; {else} iPtr^.basetype := tp^.baseType;
iPtr^.basetype := tp^.baseType;
InitializeBitField;
end; {if}
case tp^.kind of case tp^.kind of
scalarType: begin scalarType: begin
@ -2099,7 +2056,7 @@ var
iPtr^.qVal.hi := -1 iPtr^.qVal.hi := -1
else else
iPtr^.qVal.hi := 0; iPtr^.qVal.hi := 0;
goto 3; goto 2;
end; {if} end; {if}
if bKind in [cgReal,cgDouble,cgComp,cgExtended] then begin if bKind in [cgReal,cgDouble,cgComp,cgExtended] then begin
if etype^.baseType in [cgByte..cgULong] then if etype^.baseType in [cgByte..cgULong] then
@ -2107,26 +2064,10 @@ var
else if etype^.baseType in else if etype^.baseType in
[cgReal,cgDouble,cgComp,cgExtended] then [cgReal,cgDouble,cgComp,cgExtended] then
iPtr^.rval := realExpressionValue; iPtr^.rval := realExpressionValue;
goto 3; goto 2;
end; {if} end; {if}
Error(47); Error(47);
errorFound := true; errorFound := true;
goto 2;
3: if bitsize <> 0 then begin
{set up a bit field value}
if bitdisp < bitcount then
InitializeBitField;
bitmask := 0;
for i := 1 to bitsize do
bitmask := (bitmask << 1) | 1;
bitmask := bitmask & expressionValue;
for i := 1 to bitdisp do
bitmask := bitmask << 1;
bitvalue := bitvalue | bitmask;
bitcount := bitcount + bitsize;
end; {if}
end; end;
arrayType: begin arrayType: begin
@ -2330,14 +2271,6 @@ var
end; {if} end; {if}
{handle auto variables} {handle auto variables}
if bitsize <> 0 then begin
iPtr := pointer(Malloc(sizeof(initializerRecord)));
InsertInitializerRecord(iPtr, 0); {TODO should size be 0?}
iPtr^.isConstant := isConstant;
iPtr^.count := 1;
iPtr^.bitdisp := bitdisp;
iPtr^.bitsize := bitsize;
end; {if}
if variable^.storage in [external,global,private] then begin if variable^.storage in [external,global,private] then begin
Error(41); Error(41);
errorFound := true; errorFound := true;
@ -2345,8 +2278,6 @@ var
iPtr^.isConstant := false; iPtr^.isConstant := false;
iPtr^.iTree := initializerTree; iPtr^.iTree := initializerTree;
iPtr^.iType := tp; iPtr^.iType := tp;
iPtr^.bitdisp := bitdisp;
iPtr^.bitsize := bitsize;
end; {else} end; {else}
1: 1:
end; {GetInitializerValue} end; {GetInitializerValue}
@ -2369,7 +2300,8 @@ var
label 1,2; label 1,2;
var var
bitCount: integer; {# of bits in a union} bfp: identPtr; {pointer to bit-field in field list}
bfsize: integer; {number of bytes used by bit-field}
braces: boolean; {is the initializer inclosed in braces?} braces: boolean; {is the initializer inclosed in braces?}
count,maxCount: longint; {for tracking the size of an initializer} count,maxCount: longint; {for tracking the size of an initializer}
ep: tokenPtr; {for forming string expression} ep: tokenPtr; {for forming string expression}
@ -2403,8 +2335,6 @@ var
ip: identPtr; {pointer to next field in a structure} ip: identPtr; {pointer to next field in a structure}
begin {Fill} begin {Fill}
{ writeln('Fill tp^.kind = ', ord(tp^.kind):1, '; count = ', count:1); {debug}
InitializeBitField; {if needed, do the bit field}
if tp^.kind = arrayType then if tp^.kind = arrayType then
{fill an array} {fill an array}
@ -2671,7 +2601,6 @@ var
else if kind in [structType, unionType] then begin else if kind in [structType, unionType] then begin
if braces or (not main) then begin if braces or (not main) then begin
ip := tp^.fieldList; ip := tp^.fieldList;
bitCount := 0;
maxDisp := disp; maxDisp := disp;
lSuppressMacroExpansions := suppressMacroExpansions; lSuppressMacroExpansions := suppressMacroExpansions;
while true do begin while true do begin
@ -2722,24 +2651,25 @@ var
end; {if} end; {if}
if (ip = nil) or (ip^.itype^.size = 0) then if (ip = nil) or (ip^.itype^.size = 0) then
goto 2; goto 2;
{TODO zero padding in bitfields}
if ip^.bitSize = 0 then
if bitCount > 0 then begin
InitializeBitField;
bitCount := 0;
end; {if}
disp := startingDisp + ip^.disp; disp := startingDisp + ip^.disp;
if ip^.bitsize <> 0 then begin {zero out padding bits in bitfields}
bfp := ip;
while (bfp^.next <> nil) and (bfp^.next^.disp = bfp^.disp)
and (bfp^.next^.bitsize <> 0) do
bfp := bfp^.next;
bfsize := (bfp^.bitdisp + bfp^.bitsize + 7) div 8;
if disp + bfsize > maxDisp then
if (bfp <> ip) or (ip^.bitdisp <> 0)
or (ip^.bitsize mod 8 <> 0) then begin
Fill(bfsize, charPtr);
maxDisp := disp;
disp := startingDisp + ip^.disp;
end; {if}
end; {if}
InitializeTerm(ip^.itype, ip^.bitsize, ip^.bitdisp, false, InitializeTerm(ip^.itype, ip^.bitsize, ip^.bitdisp, false,
hasNestedDesignator, setNoFill or hasNestedDesignator); hasNestedDesignator, setNoFill or hasNestedDesignator);
if ip^.bitSize <> 0 then begin
bitCount := bitCount + ip^.bitSize;
if bitCount > maxBitField then begin
bitCount := ip^.bitSize;
end; {if}
end; {if}
if disp > maxDisp then if disp > maxDisp then
maxDisp := disp; maxDisp := disp;
{ writeln('Initializer: ', ip^.bitsize:10, ip^.bitdisp:10, bitCount:10); {debug}
if kind = unionType then if kind = unionType then
ip := nil ip := nil
else begin else begin
@ -2755,12 +2685,7 @@ var
else if token.kind <> rbracech then else if token.kind <> rbracech then
ip := nil; ip := nil;
end; {while} end; {while}
2: if bitCount > 0 then begin 2: if not noFill then begin
InitializeBitField;
bitCount := (bitCount+7) div 8;
bitCount := 0;
end; {if}
if not noFill then begin
disp := startingDisp + tp^.size; disp := startingDisp + tp^.size;
if disp > maxDisp then begin {if there weren't enough initializers...} if disp > maxDisp then begin {if there weren't enough initializers...}
fillSize := disp - maxDisp; fillSize := disp - maxDisp;
@ -2800,8 +2725,6 @@ var
end; {InitializeTerm} end; {InitializeTerm}
begin {Initializer} begin {Initializer}
bitcount := 0; {set up for bit fields}
bitvalue := 0;
disp := 0; {start at beginning of the object} disp := 0; {start at beginning of the object}
errorFound := false; {no errors found so far} errorFound := false; {no errors found so far}
skipComma := false; skipComma := false;