mirror of
https://github.com/byteworksinc/ORCA-C.git
synced 2024-05-29 04:41:27 +00:00
Support switch statements using long long expressions.
This commit is contained in:
parent
5268f37261
commit
cf463ff155
|
@ -496,6 +496,7 @@ var
|
||||||
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}
|
||||||
isConstant: boolean; {is the initializer expression constant?}
|
isConstant: boolean; {is the initializer expression constant?}
|
||||||
|
expressionIsLongLong: boolean; {is the last constant expression long long?}
|
||||||
|
|
||||||
{type specifier results}
|
{type specifier results}
|
||||||
{----------------------}
|
{----------------------}
|
||||||
|
|
|
@ -216,6 +216,11 @@ function UsualUnaryConversions: baseTypeEnum;
|
||||||
{ outputs: }
|
{ outputs: }
|
||||||
{ expressionType - set to result type }
|
{ expressionType - set to result type }
|
||||||
|
|
||||||
|
procedure GetLLExpressionValue (var val: longlong);
|
||||||
|
|
||||||
|
{ get the value of the last integer constant expression as a }
|
||||||
|
{ long long (whether it had long long type or not). }
|
||||||
|
|
||||||
{---------------------------------------------------------------}
|
{---------------------------------------------------------------}
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
@ -4264,6 +4269,7 @@ else begin {record the expression for an initialize
|
||||||
isConstant := false;
|
isConstant := false;
|
||||||
llExpressionValue.lo := 0;
|
llExpressionValue.lo := 0;
|
||||||
llExpressionValue.hi := 0;
|
llExpressionValue.hi := 0;
|
||||||
|
expressionIsLongLong := false;
|
||||||
if errorFound then begin
|
if errorFound then begin
|
||||||
DisposeTree(initializerTree);
|
DisposeTree(initializerTree);
|
||||||
initializerTree := nil;
|
initializerTree := nil;
|
||||||
|
@ -4321,6 +4327,7 @@ else begin {record the expression for an initialize
|
||||||
end {else if}
|
end {else if}
|
||||||
else if tree^.token.kind = longlongconst then begin
|
else if tree^.token.kind = longlongconst then begin
|
||||||
llExpressionValue := tree^.token.qval;
|
llExpressionValue := tree^.token.qval;
|
||||||
|
expressionIsLongLong := true;
|
||||||
if ((llExpressionValue.hi = 0) and (llExpressionValue.lo >= 0))
|
if ((llExpressionValue.hi = 0) and (llExpressionValue.lo >= 0))
|
||||||
or ((llExpressionValue.hi = -1) and (llExpressionValue.lo < 0)) then
|
or ((llExpressionValue.hi = -1) and (llExpressionValue.lo < 0)) then
|
||||||
expressionValue := llExpressionValue.lo
|
expressionValue := llExpressionValue.lo
|
||||||
|
@ -4333,6 +4340,7 @@ else begin {record the expression for an initialize
|
||||||
end {else if}
|
end {else if}
|
||||||
else if tree^.token.kind = ulonglongconst then begin
|
else if tree^.token.kind = ulonglongconst then begin
|
||||||
llExpressionValue := tree^.token.qval;
|
llExpressionValue := tree^.token.qval;
|
||||||
|
expressionIsLongLong := true;
|
||||||
if llExpressionValue.hi = 0 then
|
if llExpressionValue.hi = 0 then
|
||||||
expressionValue := llExpressionValue.lo
|
expressionValue := llExpressionValue.lo
|
||||||
else
|
else
|
||||||
|
@ -4370,6 +4378,25 @@ else begin {record the expression for an initialize
|
||||||
end; {Expression}
|
end; {Expression}
|
||||||
|
|
||||||
|
|
||||||
|
procedure GetLLExpressionValue {var val: longlong};
|
||||||
|
|
||||||
|
{ get the value of the last integer constant expression as a }
|
||||||
|
{ long long (whether it had long long type or not). }
|
||||||
|
|
||||||
|
begin {GetLLExpressionValue}
|
||||||
|
if expressionIsLongLong then
|
||||||
|
val := llExpressionValue
|
||||||
|
else begin
|
||||||
|
val.lo := expressionValue;
|
||||||
|
val.hi := 0;
|
||||||
|
if expressionValue < 0 then
|
||||||
|
if expressionType^.kind = scalarType then
|
||||||
|
if expressionType^.baseType in [cgByte,cgWord,cgLong] then
|
||||||
|
val.hi := -1;
|
||||||
|
end;
|
||||||
|
end; {GetLLExpressionValue}
|
||||||
|
|
||||||
|
|
||||||
procedure InitExpression;
|
procedure InitExpression;
|
||||||
|
|
||||||
{ initialize the expression handler }
|
{ initialize the expression handler }
|
||||||
|
|
79
Parser.pas
79
Parser.pas
|
@ -98,7 +98,7 @@ type
|
||||||
switchRecord = record
|
switchRecord = record
|
||||||
next,last: switchPtr; {doubly linked list (for inserts)}
|
next,last: switchPtr; {doubly linked list (for inserts)}
|
||||||
lab: integer; {label to branch to}
|
lab: integer; {label to branch to}
|
||||||
val: longint; {switch value}
|
val: longlong; {switch value}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{token stack}
|
{token stack}
|
||||||
|
@ -139,7 +139,6 @@ type
|
||||||
);
|
);
|
||||||
switchSt: (
|
switchSt: (
|
||||||
maxVal: longint; {max switch value}
|
maxVal: longint; {max switch value}
|
||||||
isLong: boolean; {do long switch?}
|
|
||||||
ln: integer; {temp var number}
|
ln: integer; {temp var number}
|
||||||
size: integer; {temp var size}
|
size: integer; {temp var size}
|
||||||
labelCount: integer; {# of switch labels}
|
labelCount: integer; {# of switch labels}
|
||||||
|
@ -188,6 +187,12 @@ var
|
||||||
declarationSpecifiersElement: tokenSet;
|
declarationSpecifiersElement: tokenSet;
|
||||||
structDeclarationStart: tokenSet;
|
structDeclarationStart: tokenSet;
|
||||||
|
|
||||||
|
{-- External procedures ----------------------------------------}
|
||||||
|
|
||||||
|
function slt64(a,b: longlong): boolean; extern;
|
||||||
|
|
||||||
|
function sgt64(a,b: longlong): boolean; extern;
|
||||||
|
|
||||||
{-- Parser Utility Procedures ----------------------------------}
|
{-- Parser Utility Procedures ----------------------------------}
|
||||||
|
|
||||||
procedure Match {kind: tokenEnum; err: integer};
|
procedure Match {kind: tokenEnum; err: integer};
|
||||||
|
@ -454,38 +459,52 @@ var
|
||||||
var
|
var
|
||||||
stPtr: statementPtr; {switch record for this case label}
|
stPtr: statementPtr; {switch record for this case label}
|
||||||
swPtr,swPtr2: switchPtr; {work pointers for inserting new entry}
|
swPtr,swPtr2: switchPtr; {work pointers for inserting new entry}
|
||||||
val: integer; {case label value}
|
val: longlong; {case label value}
|
||||||
|
|
||||||
begin {CaseStatement}
|
begin {CaseStatement}
|
||||||
while token.kind = casesy do begin
|
while token.kind = casesy do begin
|
||||||
NextToken; {skip the 'case' token}
|
NextToken; {skip the 'case' token}
|
||||||
stPtr := GetSwitchRecord; {get the proper switch record}
|
stPtr := GetSwitchRecord; {get the proper switch record}
|
||||||
Expression(arrayExpression, [colonch]); {evaluate the branch condition}
|
Expression(arrayExpression, [colonch]); {evaluate the branch condition}
|
||||||
val := long(expressionValue).lsw;
|
GetLLExpressionValue(val);
|
||||||
if val <> expressionValue then
|
if stPtr^.size = cgLongSize then begin {convert out-of-range values}
|
||||||
if not stPtr^.isLong then
|
if val.lo < 0 then
|
||||||
expressionValue := val; {convert out-of-range value to (U)Word}
|
val.hi := -1
|
||||||
|
else
|
||||||
|
val.hi := 0;
|
||||||
|
end {if}
|
||||||
|
else if stPtr^.size = cgWordSize then begin
|
||||||
|
if long(val.lo).lsw < 0 then begin
|
||||||
|
val.hi := -1;
|
||||||
|
val.lo := val.lo | $FFFF0000;
|
||||||
|
end {if}
|
||||||
|
else begin
|
||||||
|
val.hi := 0;
|
||||||
|
val.lo := val.lo & $0000FFFF;
|
||||||
|
end; {else}
|
||||||
|
end; {else if}
|
||||||
if stPtr = nil then
|
if stPtr = nil then
|
||||||
Error(72)
|
Error(72)
|
||||||
else begin
|
else begin
|
||||||
new(swPtr2); {create the new label table entry}
|
new(swPtr2); {create the new label table entry}
|
||||||
swPtr2^.lab := GenLabel;
|
swPtr2^.lab := GenLabel;
|
||||||
Gen1(dc_lab, swPtr2^.lab);
|
Gen1(dc_lab, swPtr2^.lab);
|
||||||
swPtr2^.val := expressionValue;
|
swPtr2^.val := val;
|
||||||
swPtr := stPtr^.switchList;
|
swPtr := stPtr^.switchList;
|
||||||
|
if val.lo > stPtr^.maxVal then
|
||||||
|
stPtr^.maxVal := val.lo;
|
||||||
if swPtr = nil then begin {enter it in the table}
|
if swPtr = nil then begin {enter it in the table}
|
||||||
swPtr2^.last := nil;
|
swPtr2^.last := nil;
|
||||||
swPtr2^.next := nil;
|
swPtr2^.next := nil;
|
||||||
stPtr^.switchList := swPtr2;
|
stPtr^.switchList := swPtr2;
|
||||||
stPtr^.maxVal := expressionValue;
|
|
||||||
stPtr^.labelCount := 1;
|
stPtr^.labelCount := 1;
|
||||||
end {if}
|
end {if}
|
||||||
else begin
|
else begin
|
||||||
while (swPtr^.next <> nil) and (swPtr^.val < expressionValue) do
|
while (swPtr^.next <> nil) and slt64(swPtr^.val, val) do
|
||||||
swPtr := swPtr^.next;
|
swPtr := swPtr^.next;
|
||||||
if swPtr^.val = expressionValue then
|
if (swPtr^.val.lo = val.lo) and (swPtr^.val.hi = val.hi) then
|
||||||
Error(73)
|
Error(73)
|
||||||
else if swPtr^.val > expressionValue then begin
|
else if sgt64(swPtr^.val, val) then begin
|
||||||
swPtr2^.next := swPtr;
|
swPtr2^.next := swPtr;
|
||||||
if swPtr^.last = nil then
|
if swPtr^.last = nil then
|
||||||
stPtr^.switchList := swPtr2
|
stPtr^.switchList := swPtr2
|
||||||
|
@ -498,7 +517,6 @@ var
|
||||||
swPtr2^.next := nil;
|
swPtr2^.next := nil;
|
||||||
swPtr2^.last := swPtr;
|
swPtr2^.last := swPtr;
|
||||||
swPtr^.next := swPtr2;
|
swPtr^.next := swPtr2;
|
||||||
stPtr^.maxVal := expressionValue;
|
|
||||||
end; {else}
|
end; {else}
|
||||||
stPtr^.labelCount := stPtr^.labelCount + 1;
|
stPtr^.labelCount := stPtr^.labelCount + 1;
|
||||||
end; {else}
|
end; {else}
|
||||||
|
@ -798,7 +816,6 @@ var
|
||||||
statementList := stPtr;
|
statementList := stPtr;
|
||||||
stPtr^.kind := switchSt;
|
stPtr^.kind := switchSt;
|
||||||
stPtr^.maxVal := -maxint4;
|
stPtr^.maxVal := -maxint4;
|
||||||
stPtr^.isLong := false;
|
|
||||||
stPtr^.labelCount := 0;
|
stPtr^.labelCount := 0;
|
||||||
stPtr^.switchLab := GenLabel;
|
stPtr^.switchLab := GenLabel;
|
||||||
stPtr^.switchExit := GenLabel;
|
stPtr^.switchExit := GenLabel;
|
||||||
|
@ -815,14 +832,17 @@ var
|
||||||
case tp^.kind of
|
case tp^.kind of
|
||||||
|
|
||||||
scalarType:
|
scalarType:
|
||||||
if tp^.baseType in [cgLong,cgULong] then begin
|
if tp^.baseType in [cgQuad,cgUQuad] then begin
|
||||||
stPtr^.isLong := true;
|
stPtr^.size := cgQuadSize;
|
||||||
|
stPtr^.ln := GetTemp(cgQuadSize);
|
||||||
|
Gen2t(pc_str, stPtr^.ln, 0, cgQuad);
|
||||||
|
end {if}
|
||||||
|
else if tp^.baseType in [cgLong,cgULong] then begin
|
||||||
stPtr^.size := cgLongSize;
|
stPtr^.size := cgLongSize;
|
||||||
stPtr^.ln := GetTemp(cgLongSize);
|
stPtr^.ln := GetTemp(cgLongSize);
|
||||||
Gen2t(pc_str, stPtr^.ln, 0, cgLong);
|
Gen2t(pc_str, stPtr^.ln, 0, cgLong);
|
||||||
end {if}
|
end {if}
|
||||||
else if tp^.baseType in [cgByte,cgUByte,cgWord,cgUWord] then begin
|
else if tp^.baseType in [cgByte,cgUByte,cgWord,cgUWord] then begin
|
||||||
stPtr^.isLong := false;
|
|
||||||
stPtr^.size := cgWordSize;
|
stPtr^.size := cgWordSize;
|
||||||
stPtr^.ln := GetTemp(cgWordSize);
|
stPtr^.ln := GetTemp(cgWordSize);
|
||||||
Gen2t(pc_str, stPtr^.ln, 0, cgWord);
|
Gen2t(pc_str, stPtr^.ln, 0, cgWord);
|
||||||
|
@ -831,7 +851,6 @@ var
|
||||||
Error(71);
|
Error(71);
|
||||||
|
|
||||||
enumType: begin
|
enumType: begin
|
||||||
stPtr^.isLong := false;
|
|
||||||
stPtr^.size := cgWordSize;
|
stPtr^.size := cgWordSize;
|
||||||
stPtr^.ln := GetTemp(cgWordSize);
|
stPtr^.ln := GetTemp(cgWordSize);
|
||||||
Gen2t(pc_str, stPtr^.ln, 0, cgWord);
|
Gen2t(pc_str, stPtr^.ln, 0, cgWord);
|
||||||
|
@ -1075,13 +1094,15 @@ var
|
||||||
{-------------------------------}
|
{-------------------------------}
|
||||||
exitLab: integer; {label at the end of the jump table}
|
exitLab: integer; {label at the end of the jump table}
|
||||||
isLong: boolean; {is the case expression long?}
|
isLong: boolean; {is the case expression long?}
|
||||||
|
isLongLong: boolean; {is the case expression long long?}
|
||||||
swPtr,swPtr2: switchPtr; {switch label table list}
|
swPtr,swPtr2: switchPtr; {switch label table list}
|
||||||
|
|
||||||
begin {EndSwitchStatement}
|
begin {EndSwitchStatement}
|
||||||
if c99Scope then PopTable;
|
if c99Scope then PopTable;
|
||||||
stPtr := statementList; {get the statement record}
|
stPtr := statementList; {get the statement record}
|
||||||
exitLab := stPtr^.switchExit; {get the exit label}
|
exitLab := stPtr^.switchExit; {get the exit label}
|
||||||
isLong := stPtr^.isLong; {get the long flag}
|
isLong := stPtr^.size = cgLongSize; {get the long flag}
|
||||||
|
isLongLong := stPtr^.size = cgQuadSize; {get the long long flag}
|
||||||
swPtr := stPtr^.switchList; {Skip further generation if there were}
|
swPtr := stPtr^.switchList; {Skip further generation if there were}
|
||||||
if swPtr <> nil then begin { no labels. }
|
if swPtr <> nil then begin { no labels. }
|
||||||
default := stPtr^.switchDefault; {get a default label}
|
default := stPtr^.switchDefault; {get a default label}
|
||||||
|
@ -1089,21 +1110,25 @@ if swPtr <> nil then begin { no labels. }
|
||||||
default := exitLab;
|
default := exitLab;
|
||||||
Gen1(pc_ujp, exitLab); {branch past the indexed jump}
|
Gen1(pc_ujp, exitLab); {branch past the indexed jump}
|
||||||
Gen1(dc_lab, stPtr^.switchLab); {create the label for the xjp table}
|
Gen1(dc_lab, stPtr^.switchLab); {create the label for the xjp table}
|
||||||
if isLong then {decide on a base type}
|
if isLongLong then {decide on a base type}
|
||||||
|
ltp := cgQuad
|
||||||
|
else if isLong then
|
||||||
ltp := cgLong
|
ltp := cgLong
|
||||||
else
|
else
|
||||||
ltp := cgWord;
|
ltp := cgWord;
|
||||||
if stPtr^.isLong
|
if isLong or isLongLong
|
||||||
or (((stPtr^.maxVal-swPtr^.val) div stPtr^.labelCount) > sparse) then
|
or (((stPtr^.maxVal-swPtr^.val.lo) div stPtr^.labelCount) > sparse) then
|
||||||
begin
|
begin
|
||||||
|
|
||||||
{Long expressions and sparse switch statements are handled as a }
|
{Long expressions and sparse switch statements are handled as a }
|
||||||
{series of if-goto tests. }
|
{series of if-goto tests. }
|
||||||
while swPtr <> nil do begin {generate the compares}
|
while swPtr <> nil do begin {generate the compares}
|
||||||
if isLong then
|
if isLongLong then
|
||||||
GenLdcLong(swPtr^.val)
|
GenLdcQuad(swPtr^.val)
|
||||||
|
else if isLong then
|
||||||
|
GenLdcLong(swPtr^.val.lo)
|
||||||
else
|
else
|
||||||
Gen1t(pc_ldc, long(swPtr^.val).lsw, cgWord);
|
Gen1t(pc_ldc, long(swPtr^.val.lo).lsw, cgWord);
|
||||||
Gen2t(pc_lod, stPtr^.ln, 0, ltp);
|
Gen2t(pc_lod, stPtr^.ln, 0, ltp);
|
||||||
Gen0t(pc_equ, ltp);
|
Gen0t(pc_equ, ltp);
|
||||||
Gen1(pc_tjp, swPtr^.lab);
|
Gen1(pc_tjp, swPtr^.lab);
|
||||||
|
@ -1116,12 +1141,12 @@ if swPtr <> nil then begin { no labels. }
|
||||||
else begin
|
else begin
|
||||||
|
|
||||||
{compact word switch statements are handled with xjp}
|
{compact word switch statements are handled with xjp}
|
||||||
minVal := long(swPtr^.val).lsw; {record the min label value}
|
minVal := long(swPtr^.val.lo).lsw; {record the min label value}
|
||||||
Gen2t(pc_lod, stPtr^.ln, 0, ltp); {get the value}
|
Gen2t(pc_lod, stPtr^.ln, 0, ltp); {get the value}
|
||||||
Gen1t(pc_dec, minVal, cgWord); {adjust the range}
|
Gen1t(pc_dec, minVal, cgWord); {adjust the range}
|
||||||
Gen1(pc_xjp, ord(stPtr^.maxVal-minVal+1)); {do the indexed jump}
|
Gen1(pc_xjp, ord(stPtr^.maxVal-minVal+1)); {do the indexed jump}
|
||||||
while swPtr <> nil do begin {generate the jump table}
|
while swPtr <> nil do begin {generate the jump table}
|
||||||
while minVal < swPtr^.val do begin
|
while minVal < swPtr^.val.lo do begin
|
||||||
Gen1(pc_add, default);
|
Gen1(pc_add, default);
|
||||||
minVal := minVal+1;
|
minVal := minVal+1;
|
||||||
end; {while}
|
end; {while}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user