Initial support for constants with long long types.

Currently, the actual values they can have are still constrained to the 32-bit range. Also, there are some bits of functionality (e.g. for initializers) that are not implemented yet.
This commit is contained in:
Stephen Heumann 2021-02-03 23:11:23 -06:00
parent 714b417261
commit 793f0a57cc
9 changed files with 157 additions and 30 deletions

View File

@ -114,7 +114,7 @@ type
{Misc.} {Misc.}
{-----} {-----}
long = record lsw,msw: integer; end; {for extracting words from longints} long = record lsw,msw: integer; end; {for extracting words from longints}
longlong = record low32,high32: longint; end; {64-bit integer representation} longlong = record lo,hi: longint; end; {64-bit integer representation}
cString = packed array [1..256] of char; {null terminated string} cString = packed array [1..256] of char; {null terminated string}
cStringPtr = ^cString; cStringPtr = ^cString;
@ -167,7 +167,8 @@ type
tokenEnum = ( {enumeration of the tokens} tokenEnum = ( {enumeration of the tokens}
ident, {identifiers} ident, {identifiers}
{constants} {constants}
intconst,uintconst,longconst,ulongconst,doubleconst, intconst,uintconst,longconst,ulongconst,longlongconst,
ulonglongconst,doubleconst,
stringconst, stringconst,
{reserved words} {reserved words}
_Alignassy,_Alignofsy,_Atomicsy,_Boolsy,_Complexsy, _Alignassy,_Alignofsy,_Atomicsy,_Boolsy,_Complexsy,
@ -208,7 +209,7 @@ type
tokenSet = set of tokenEnum; tokenSet = set of tokenEnum;
tokenClass = (reservedWord,reservedSymbol,identifier,intConstant,longConstant, tokenClass = (reservedWord,reservedSymbol,identifier,intConstant,longConstant,
doubleConstant,stringConstant,macroParameter); longlongConstant,doubleConstant,stringConstant,macroParameter);
identPtr = ^identRecord; {^ to a symbol table entry} identPtr = ^identRecord; {^ to a symbol table entry}
tokenType = record {a token} tokenType = record {a token}
kind: tokenEnum; {kind of token} kind: tokenEnum; {kind of token}
@ -220,6 +221,7 @@ type
symbolPtr: identPtr); symbolPtr: identPtr);
intConstant : (ival: integer); intConstant : (ival: integer);
longConstant : (lval: longint); longConstant : (lval: longint);
longlongConstant: (qval: longlong);
doubleConstant: (rval: double); doubleConstant: (rval: double);
stringConstant: (sval: longstringPtr; stringConstant: (sval: longstringPtr;
ispstring: boolean); ispstring: boolean);
@ -487,6 +489,7 @@ var
{------------------} {------------------}
doDispose: boolean; {dispose of the expression tree as we go?} doDispose: boolean; {dispose of the expression tree as we go?}
realExpressionValue: double; {value of the last real constant expression} realExpressionValue: double; {value of the last real constant expression}
longlongExpressionValue: longlong; {value of the last long long constant expression}
expressionValue: longint; {value of the last constant expression} expressionValue: longint; {value of the last constant expression}
expressionType: typePtr; {the type of the expression} expressionType: typePtr; {the type of the expression}
initializerTree: tokenPtr; {for non-constant initializers} initializerTree: tokenPtr; {for non-constant initializers}

29
CGI.pas
View File

@ -575,6 +575,14 @@ procedure GenLdcLong (lval: longint);
{ lval - value to load } { lval - value to load }
procedure GenLdcQuad (qval: longlong);
{ load a long long constant }
{ }
{ parameters: }
{ qval - value to load }
procedure GenLdcReal (rval: double); procedure GenLdcReal (rval: double);
{ load a real constant } { load a real constant }
@ -1238,6 +1246,27 @@ if codeGeneration then begin
end; {GenLdcLong} end; {GenLdcLong}
procedure GenLdcQuad {qval: longlong};
{ load a long long constant }
{ }
{ parameters: }
{ qval - value to load }
var
lcode: icptr; {local copy of code}
begin {GenLdcQuad}
if codeGeneration then begin
lcode := code;
lcode^.optype := cgQuad;
lcode^.qval.lo := qval.lo;
lcode^.qval.hi := qval.hi;
Gen0(pc_ldc);
end; {if}
end; {GenLdcQuad}
procedure GenTool {fop: pcodes; fp1, fp2: integer; dispatcher: longint}; procedure GenTool {fop: pcodes; fp1, fp2: integer; dispatcher: longint};
{ generate a tool call } { generate a tool call }

View File

@ -167,8 +167,8 @@ else if (op1 <> nil) and (op2 <> nil) then
if op1^.lval = op2^.lval then if op1^.lval = op2^.lval then
CodesMatch := true; CodesMatch := true;
cgQuad, cgUQuad: cgQuad, cgUQuad:
if op1^.qval.low32 = op2^.qval.low32 then if op1^.qval.lo = op2^.qval.lo then
if op1^.qval.high32 = op2^.qval.high32 then if op1^.qval.hi = op2^.qval.hi then
CodesMatch := true; CodesMatch := true;
cgReal, cgDouble, cgComp, cgExtended: cgReal, cgDouble, cgComp, cgExtended:
if op1^.rval = op2^.rval then if op1^.rval = op2^.rval then

View File

@ -2810,6 +2810,8 @@ var
if opType^.baseType in [cgByte,cgWord,cgUByte,cgUWord,cgLong,cgULong] then if opType^.baseType in [cgByte,cgWord,cgUByte,cgUWord,cgLong,cgULong] then
if ((divisor.class = intConstant) and (divisor.ival = 0)) if ((divisor.class = intConstant) and (divisor.ival = 0))
or ((divisor.class = longConstant) and (divisor.lval = 0)) or ((divisor.class = longConstant) and (divisor.lval = 0))
or ((divisor.class = longlongConstant)
and (divisor.qval.lo = 0) and (divisor.qval.hi = 0))
or ((divisor.class = doubleConstant) and (divisor.rval = 0.0)) then or ((divisor.class = doubleConstant) and (divisor.rval = 0.0)) then
Error(129); Error(129);
end; {CheckDivByZero} end; {CheckDivByZero}
@ -2831,6 +2833,12 @@ var
shiftCount := shiftCountTok.ival shiftCount := shiftCountTok.ival
else if shiftCountTok.class = longConstant then else if shiftCountTok.class = longConstant then
shiftCount := shiftCountTok.lval shiftCount := shiftCountTok.lval
else if shiftCountTok.class = longlongConstant then begin
if shiftCountTok.qval.hi = 0 then
shiftCount := shiftCountTok.qval.lo
else
shiftCount := -1;
end {else if}
else else
shiftCount := 0; shiftCount := 0;
@ -2911,6 +2919,18 @@ case tree^.token.kind of
lastconst := tree^.token.lval; lastconst := tree^.token.lval;
end; {case longConst} end; {case longConst}
longlongConst,ulonglongConst: begin
GenLdcQuad(tree^.token.qval);
if tree^.token.kind = longlongConst then
expressionType := longlongPtr
else
expressionType := ulonglongPtr;
if (tree^.token.qval.hi = 0) and (tree^.token.qval.lo >= 0) then begin
lastwasconst := true;
lastconst := tree^.token.qval.lo;
end; {if}
end; {case longlongConst}
doubleConst: begin doubleConst: begin
GenLdcReal(tree^.token.rval); GenLdcReal(tree^.token.rval);
expressionType := doublePtr; expressionType := doublePtr;
@ -3920,6 +3940,18 @@ else begin {record the expression for an initialize
expressionType := ulongPtr; expressionType := ulongPtr;
isConstant := true; isConstant := true;
end {else if} end {else if}
else if tree^.token.kind = longlongconst then begin
longlongExpressionValue.lo := tree^.token.qval.lo;
longlongExpressionValue.hi := tree^.token.qval.hi;
expressionType := longLongPtr;
isConstant := true;
end {else if}
else if tree^.token.kind = ulonglongconst then begin
longlongExpressionValue.lo := tree^.token.qval.lo;
longlongExpressionValue.hi := tree^.token.qval.hi;
expressionType := ulongLongPtr;
isConstant := true;
end {else if}
else if tree^.token.kind = doubleconst then begin else if tree^.token.kind = doubleconst then begin
realExpressionValue := tree^.token.rval; realExpressionValue := tree^.token.rval;
expressionType := extendedPtr; expressionType := extendedPtr;
@ -3955,8 +3987,8 @@ procedure InitExpression;
{ initialize the expression handler } { initialize the expression handler }
begin {InitExpression} begin {InitExpression}
startTerm := [ident,intconst,uintconst,longconst,ulongconst,doubleconst, startTerm := [ident,intconst,uintconst,longconst,ulongconst,longlongconst,
stringconst,_Genericsy]; ulonglongconst,doubleconst,stringconst,_Genericsy];
startExpression:= startTerm + startExpression:= startTerm +
[lparench,asteriskch,andch,plusch,minusch,excch,tildech,sizeofsy, [lparench,asteriskch,andch,plusch,minusch,excch,tildech,sizeofsy,
plusplusop,minusminusop,typedef,_Alignofsy]; plusplusop,minusminusop,typedef,_Alignofsy];

View File

@ -4986,6 +4986,13 @@ procedure GenTree {op: icptr};
GenNative(m_pea, immediate, long(op^.lval).lsw, nil, 0); GenNative(m_pea, immediate, long(op^.lval).lsw, nil, 0);
end; end;
cgQuad,cgUQuad: begin
GenNative(m_pea, immediate, long(op^.qval.hi).msw, nil, 0);
GenNative(m_pea, immediate, long(op^.qval.hi).lsw, nil, 0);
GenNative(m_pea, immediate, long(op^.qval.lo).msw, nil, 0);
GenNative(m_pea, immediate, long(op^.qval.lo).lsw, nil, 0);
end;
otherwise: otherwise:
Error(cge1); Error(cge1);
end; {case} end; {case}

View File

@ -18,7 +18,7 @@ uses CCommon, MM, Scanner, Symbol, CGI;
{$segment 'SCANNER'} {$segment 'SCANNER'}
const const
symFileVersion = 9; {version number of .sym file format} symFileVersion = 10; {version number of .sym file format}
var var
inhibitHeader: boolean; {should .sym includes be blocked?} inhibitHeader: boolean; {should .sym includes be blocked?}
@ -711,6 +711,10 @@ procedure EndInclude {chPtr: ptr};
identifier: WriteString(token.name); identifier: WriteString(token.name);
intConstant: WriteWord(token.ival); intConstant: WriteWord(token.ival);
longConstant: WriteLong(token.lval); longConstant: WriteLong(token.lval);
longlongConstant: begin
WriteLong(token.qval.lo);
WriteLong(token.qval.hi);
end;
doubleConstant: WriteDouble(token.rval); doubleConstant: WriteDouble(token.rval);
stringConstant: begin stringConstant: begin
WriteLongString(token.sval); WriteLongString(token.sval);
@ -1331,6 +1335,10 @@ var
identifier: token.name := ReadString; identifier: token.name := ReadString;
intConstant: token.ival := ReadWord; intConstant: token.ival := ReadWord;
longConstant: token.lval := ReadLong; longConstant: token.lval := ReadLong;
longlongConstant: begin
token.qval.lo := ReadLong;
token.qval.hi := ReadLong;
end;
doubleConstant: token.rval := ReadDouble; doubleConstant: token.rval := ReadDouble;
stringConstant: begin stringConstant: begin
token.sval := ReadLongString; token.sval := ReadLongString;

View File

@ -1846,6 +1846,8 @@ var
size := rtree^.token.ival size := rtree^.token.ival
else if rtree^.token.kind in [longconst,ulongconst] then else if rtree^.token.kind in [longconst,ulongconst] then
size := rtree^.token.lval size := rtree^.token.lval
else if rtree^.token.kind in [longlongconst,ulonglongconst] then
size := rtree^.token.qval.lo
else begin else begin
Error(18); Error(18);
errorFound := true; errorFound := true;
@ -2056,11 +2058,13 @@ var
operator := tree^.token.kind; operator := tree^.token.kind;
while operator in [plusch,minusch] do begin while operator in [plusch,minusch] do begin
with tree^.right^.token do with tree^.right^.token do
if kind in [intConst,longConst] then begin if kind in [intConst,longConst,longlongConst] then begin
if kind = intConst then if kind = intConst then
offSet2 := ival offSet2 := ival
else else if kind = longConst then
offset2 := lval; offset2 := lval
else {if kind = longlongConst then}
offset2 := qval.lo;
if operator = plusch then if operator = plusch then
offset := offset + offset2 offset := offset + offset2
else else
@ -4179,12 +4183,19 @@ var
{do assignment conversions} {do assignment conversions}
while tree^.token.kind = castoper do while tree^.token.kind = castoper do
tree := tree^.left; tree := tree^.left;
isConstant := tree^.token.class in [intConstant,longConstant]; isConstant :=
tree^.token.class in [intConstant,longConstant,longlongConstant];
if isConstant then if isConstant then
if tree^.token.class = intConstant then if tree^.token.class = intConstant then
val := tree^.token.ival val := tree^.token.ival
else else if tree^.token.class = longConstant then
val := tree^.token.lval; val := tree^.token.lval
else {if tree^.token.class = longlongConstant then} begin
if (tree^.token.qval.hi = 0) and (tree^.token.qval.lo >= 0) then
val := tree^.token.qval.lo
else
isConstant := false;
end; {else}
{ if isConstant then { if isConstant then
if tree^.token.class = intConstant then if tree^.token.class = intConstant then

View File

@ -272,6 +272,7 @@ var
lintErrors: set of 1..maxLint; {lint error codes} lintErrors: set of 1..maxLint; {lint error codes}
spaceStr: string[2]; {string ' ' (used in stringization)} spaceStr: string[2]; {string ' ' (used in stringization)}
quoteStr: string[2]; {string '"' (used in stringization)} quoteStr: string[2]; {string '"' (used in stringization)}
numericConstants: set of tokenClass; {token classes for numeric constants}
{-- External procedures; see expression evaluator for notes ----} {-- External procedures; see expression evaluator for notes ----}
@ -742,6 +743,9 @@ case token.kind of
longConst, longConst,
ulongConst: write(token.lval:1); ulongConst: write(token.lval:1);
longlongConst,
ulonglongConst: write('0x...'); {TODO implement}
doubleConst: write(token.rval:1); doubleConst: write(token.rval:1);
@ -1043,7 +1047,7 @@ if class1 in [identifier,reservedWord] then begin
str2 := tk2.name str2 := tk2.name
else if class2 = reservedWord then else if class2 = reservedWord then
str2 := @reservedWords[kind2] str2 := @reservedWords[kind2]
else if class2 in [intConstant,longConstant,doubleConstant] then else if class2 in numericConstants then
str2 := tk2.numString str2 := tk2.numString
else begin else begin
Error(63); Error(63);
@ -1067,8 +1071,8 @@ if class1 in [identifier,reservedWord] then begin
goto 1; goto 1;
end {class1 in [identifier,reservedWord]} end {class1 in [identifier,reservedWord]}
else if class1 in [intConstant,longConstant,doubleConstant] then begin else if class1 in numericConstants then begin
if class2 in [intConstant,longConstant,doubleConstant] then if class2 in numericConstants then
str2 := tk2.numString str2 := tk2.numString
else if class2 = identifier then else if class2 = identifier then
str2 := tk2.name str2 := tk2.name
@ -1086,7 +1090,7 @@ else if class1 in [intConstant,longConstant,doubleConstant] then begin
tk1 := token; tk1 := token;
token := lt; token := lt;
goto 1; goto 1;
end {else if class1 in [intConstant,longConstant,doubleConstant]} end {else if class1 in numericConstants}
else if class1 = stringConstant then begin else if class1 = stringConstant then begin
if class2 = stringConstant then begin if class2 = stringConstant then begin
@ -1106,7 +1110,7 @@ else if class1 = stringConstant then begin
end {else if} end {else if}
else if kind1 = dotch then begin else if kind1 = dotch then begin
if class2 in [intConstant,longConstant,doubleConstant] then begin if class2 in numericConstants then begin
workString := concat(tk1.numString^, tk2.numString^); workString := concat(tk1.numString^, tk2.numString^);
lt := token; lt := token;
DoNumber(true); DoNumber(true);
@ -1114,7 +1118,7 @@ else if kind1 = dotch then begin
token := lt; token := lt;
goto 1; goto 1;
end; {if} end; {if}
end {else if class1 in [intConstant,longConstant,doubleConstant]} end {else if class1 in numericConstants}
else if kind1 = poundch then begin else if kind1 = poundch then begin
if kind2 = poundch then begin if kind2 = poundch then begin
@ -1846,7 +1850,7 @@ else begin
new(tempString); new(tempString);
tempString^[0] := chr(0); tempString^[0] := chr(0);
while while
(token.class in [reservedWord,intconstant,longconstant,doubleconstant]) (token.class in ([reservedWord] + numericConstants))
or (token.kind in [dotch,ident]) do begin or (token.kind in [dotch,ident]) do begin
if token.kind = ident then if token.kind = ident then
tempString^ := concat(tempString^, token.name^) tempString^ := concat(tempString^, token.name^)
@ -1854,7 +1858,7 @@ else begin
tempString^ := concat(tempString^, '.') tempString^ := concat(tempString^, '.')
else if token.class = reservedWord then else if token.class = reservedWord then
tempString^ := concat(tempString^, reservedWords[token.kind]) tempString^ := concat(tempString^, reservedWords[token.kind])
else {if token.class in [intconst,longconst,doubleconst] then} else {if token.class in numericConstants then}
tempString^ := concat(tempString^, token.numstring^); tempString^ := concat(tempString^, token.numstring^);
NextToken; NextToken;
end; {while} end; {while}
@ -2317,6 +2321,10 @@ var
longConstant: longConstant:
if tk1^.token.lval <> tk2^.token.lval then if tk1^.token.lval <> tk2^.token.lval then
goto 3; goto 3;
longlongConstant:
if (tk1^.token.qval.lo <> tk2^.token.qval.lo) or
(tk1^.token.qval.hi <> tk2^.token.qval.hi) then
goto 3;
doubleConstant: doubleConstant:
if tk1^.token.rval <> tk2^.token.rval then if tk1^.token.rval <> tk2^.token.rval then
goto 3; goto 3;
@ -3145,12 +3153,14 @@ var
isBin: boolean; {is the value a binary number?} isBin: boolean; {is the value a binary number?}
isHex: boolean; {is the value a hex number?} isHex: boolean; {is the value a hex number?}
isLong: boolean; {is the value a long number?} isLong: boolean; {is the value a long number?}
isLongLong: boolean; {is the value a long long number?}
isReal: boolean; {is the value a real number?} isReal: boolean; {is the value a real number?}
numIndex: 0..maxLine; {index into workString} numIndex: 0..maxLine; {index into workString}
sp: stringPtr; {for saving identifier names} sp: stringPtr; {for saving identifier names}
stringIndex: 0..maxLine; {length of the number string} stringIndex: 0..maxLine; {length of the number string}
unsigned: boolean; {is the number unsigned?} unsigned: boolean; {is the number unsigned?}
val: integer; {value of a digit} val: integer; {value of a digit}
c1: char; {saved copy of last character}
numString: pString; {characters in the number} numString: pString; {characters in the number}
@ -3217,6 +3227,7 @@ isBin := false; {assume it's not binary}
isHex := false; {assume it's not hex} isHex := false; {assume it's not hex}
isReal := false; {assume it's an integer} isReal := false; {assume it's an integer}
isLong := false; {assume a short integer} isLong := false; {assume a short integer}
isLongLong := false;
unsigned := false; {assume signed numbers} unsigned := false; {assume signed numbers}
stringIndex := 0; {no digits so far...} stringIndex := 0; {no digits so far...}
if scanWork then begin {set up the scanner} if scanWork then begin {set up the scanner}
@ -3276,11 +3287,17 @@ if c2 in ['e','E'] then begin {handle an exponent}
end; {if} end; {if}
1: 1:
while c2 in ['l','u','L','U'] do {check for long or unsigned} while c2 in ['l','u','L','U'] do {check for long or unsigned}
if c2 in ['l','L'] then begin if c2 in ['l','L'] then begin
NextChar; if isLong or isLongLong then
if isLong then
FlagError(156); FlagError(156);
isLong := true; c1 := c2;
NextChar;
if c2 = c1 then begin
NextChar;
isLongLong := true;
end {if}
else
isLong := true;
end {if} end {if}
else {if c2 in ['u','U'] then} begin else {if c2 in ['u','U'] then} begin
NextChar; NextChar;
@ -3293,6 +3310,8 @@ while c2 in ['l','u','L','U'] do {check for long or unsigned}
if c2 in ['f','F'] then begin {allow F designator on reals} if c2 in ['f','F'] then begin {allow F designator on reals}
if unsigned then if unsigned then
FlagError(91); FlagError(91);
if isLongLong then
FlagError(156);
if not isReal then begin if not isReal then begin
FlagError(100); FlagError(100);
isReal := true; isReal := true;
@ -3395,7 +3414,17 @@ else begin {hex, octal, & binary}
end; {else} end; {else}
if long(token.lval).msw <> 0 then if long(token.lval).msw <> 0 then
isLong := true; isLong := true;
if isLong then begin if isLongLong then begin
{TODO support actual long long range}
token.qval.lo := token.lval;
token.qval.hi := 0;
if unsigned then
token.kind := ulonglongConst
else
token.kind := longlongConst;
token.class := longlongConstant;
end {if}
else if isLong then begin
if unsigned or (token.lval & $80000000 <> 0) then if unsigned or (token.lval & $80000000 <> 0) then
token.kind := ulongConst token.kind := ulongConst
else else
@ -3718,6 +3747,8 @@ lintErrors := [51,104,105,110,124,125,128,129,130,147,151,152,153,154,155];
spaceStr := ' '; {strings used in stringization} spaceStr := ' '; {strings used in stringization}
quoteStr := '"'; quoteStr := '"';
{set of classes for numeric constants}
numericConstants := [intConstant,longConstant,longlongConstant,doubleConstant];
new(mp); {__LINE__} new(mp); {__LINE__}
mp^.name := @'__LINE__'; mp^.name := @'__LINE__';
@ -3877,7 +3908,7 @@ repeat
intConstant : token.ival := -token.ival; intConstant : token.ival := -token.ival;
longConstant : token.lval := -token.lval; longConstant : token.lval := -token.lval;
doubleConstant: token.rval := -token.rval; doubleConstant: token.rval := -token.rval;
otherwise: ; longlongConstant,otherwise: Error(108);
end; {case} end; {case}
end {if} end {if}
else else

View File

@ -284,7 +284,8 @@ charKinds start character set
charSym start single character symbols charSym start single character symbols
enum ident,0 identifiers enum ident,0 identifiers
! constants ! constants
enum (intconst,uintconst,longconst,ulongconst,doubleconst) enum (intconst,uintconst,longconst,ulongconst,longlongconst)
enum (ulonglongconst,doubleconst)
enum stringconst enum stringconst
! reserved words ! reserved words
enum (_Alignassy,_Alignofsy,_Atomicsy,_Boolsy,_Complexsy) enum (_Alignassy,_Alignofsy,_Atomicsy,_Boolsy,_Complexsy)
@ -356,6 +357,8 @@ icp start in-coming priority for expression
dc i1'200' uintconst dc i1'200' uintconst
dc i1'200' longconst dc i1'200' longconst
dc i1'200' ulongconst dc i1'200' ulongconst
dc i1'200' longlongconst
dc i1'200' ulonglongconst
dc i1'200' doubleconst dc i1'200' doubleconst
dc i1'200' stringconst dc i1'200' stringconst
dc i1'200' _Alignassy dc i1'200' _Alignassy
@ -521,6 +524,8 @@ isp start in stack priority for expression
dc i1'0' uintconst dc i1'0' uintconst
dc i1'0' longconst dc i1'0' longconst
dc i1'0' ulongconst dc i1'0' ulongconst
dc i1'0' longlongconst
dc i1'0' ulonglongconst
dc i1'0' doubleconst dc i1'0' doubleconst
dc i1'0' stringconst dc i1'0' stringconst
dc i1'0' _Alignassy dc i1'0' _Alignassy
@ -893,7 +898,8 @@ wordHash start reserved word hash table
enum ident,0 identifiers enum ident,0 identifiers
! constants ! constants
enum (intconst,uintconst,longconst,ulongconst,doubleconst) enum (intconst,uintconst,longconst,ulongconst,longlongconst)
enum (ulonglongconst,doubleconst)
enum stringconst enum stringconst
! reserved words ! reserved words
enum (_Alignassy,_Alignofsy,_Atomicsy,_Boolsy,_Complexsy) enum (_Alignassy,_Alignofsy,_Atomicsy,_Boolsy,_Complexsy)