DIRECTORY
Alloc: TYPE USING [Notifier],
CatchFormat: TYPE USING [cExit],
Code: TYPE USING [caseCVState, catchcount, CodeNotImplemented, curctxlvl],
CodeDefs:
TYPE
USING [
Base, BYTE, codeType, JumpType, LabelCCIndex, LabelCCNull,
LabelInfoRecord, LabelInfoIndex, LabelInfoNull, Lexeme, NamedLabelInfoIndex,
NullLex, VarComponent, VarIndex, wordlength],
FOpCodes:
TYPE
USING [
qBLTEL, qBLTECL, qDCMP, qUDCMP, qFCOMP, qLI, qLP, qIOR, qREC, qRET],
Literals: TYPE USING [Base, LTIndex, ltType],
P5:
TYPE
USING [
Exp, FreeHeapLex, GenAnonLex, LogHeapFree, PushLex, PushRhs,
StatementTree, TypeRel],
P5L:
TYPE
USING [
EasilyLoadable, FieldOfVar, InCode, LoadAddress, LoadBoth, LoadComponent,
LoadVar, MakeComponent, ReusableCopies, VarAlignment, VarForLex, Words],
P5S: TYPE USING [],
P5U:
TYPE
USING [
FreeChunk, GetChunk, InsertLabel, LabelAlloc, Out0, Out1, OutJump,
PushLitVal, TreeLiteral, TreeLiteralValue],
PrincOps: TYPE USING [localbase],
Stack: TYPE USING [Decr, Dump, Incr, Require],
Symbols: TYPE USING [HTIndex],
Tree: TYPE USING [Base, Index, Link, NodeName, Null, treeType],
TreeOps: TYPE USING [GetHash, GetNode, ScanList];
VarVarComp:
PROC [
r1, r2: VarIndex, n: Tree.NodeName, real, signed: BOOL,
hLex1, hLex2: Lexeme.se, label: LabelCCIndex,
commutable: BOOL←FALSE] =
BEGIN
wSize: CARDINAL;
bSize, bd1, bd2: [0..wordlength);
nw: CARDINAL;
FreeHeapNodes:
PROC =
BEGIN
IF hLex1 # NullLex THEN P5.FreeHeapLex[hLex1];
IF hLex2 # NullLex THEN P5.FreeHeapLex[hLex2];
hLex1 ← hLex2 ← NullLex;
END;
[wSize: wSize, bSize: bSize, bd: bd1] ← P5L.VarAlignment[r1, load];
[bd: bd2] ← P5L.VarAlignment[r2, load];
nw ← P5L.Words[wSize, bSize]; -- r1 and r2 are same size if > 1
IF nw > 1 AND bd1 # bd2 THEN SIGNAL CPtr.CodeNotImplemented;
IF nw <= 2
THEN
BEGIN
c1: VarComponent ← P5L.MakeComponent[r1];
c2: VarComponent ← P5L.MakeComponent[r2];
BEGIN
IF n = relE
OR n = relN
THEN
WITH c2
SELECT
FROM
const =>
IF wSize = 2
AND bSize = 0
AND ~real
AND d1 = 0
AND d2 = 0
THEN
BEGIN
P5L.LoadComponent[c1];
P5U.Out0[FOpCodes.qIOR];
GO TO double;
END;
ENDCASE;
P5L.LoadBoth[@c1, @c2, (n = relE OR n = relN) AND commutable];
IF nw = 2
THEN
BEGIN
P5U.Out0[
IF real
THEN FOpCodes.qFCOMP
ELSE IF signed THEN FOpCodes.qDCMP ELSE FOpCodes.qUDCMP];
GO TO double;
END;
FreeHeapNodes[];
EXITS
double => {FreeHeapNodes[]; P5U.Out1[FOpCodes.qLI, 0]};
END;
P5U.OutJump[IF signed OR nw = 2 THEN JumpNN[n] ELSE UJumpNN[n], label];
END
ELSE
BEGIN -- multiword quantities, n = relE or relN
IF bSize = 0
THEN
BEGIN
code: BOOL ← FALSE;
IF P5L.InCode[r2] THEN {tr: VarIndex = r2; r2 ← r1; r1 ← tr};
IF P5L.InCode[r1] THEN code ← TRUE;
IF ~P5L.LoadAddress[r: r1, codeOk:
TRUE]
AND ~code
THEN
P5U.Out0[FOpCodes.qLP];
P5U.Out1[FOpCodes.qLI, nw];
IF ~P5L.LoadAddress[r: r2, codeOk: FALSE] THEN P5U.Out0[FOpCodes.qLP];
P5U.Out0[IF code THEN FOpCodes.qBLTECL ELSE FOpCodes.qBLTEL];
Stack.Incr[1];
FreeHeapNodes[];
P5U.Out1[FOpCodes.qLI, 0];
P5U.OutJump[IF n # relE THEN JumpE ELSE JumpN, label]
END
ELSE
BEGIN -- do in two pieces
r1a, r1b: VarIndex;
r2a, r2b: VarIndex;
firstEq, secondComp: LabelCCIndex;
[first: r1b, next: r1a] ← P5L.ReusableCopies[r1, load, FALSE];
[first: r2b, next: r2a] ← P5L.ReusableCopies[r2, load, FALSE];
IF bd1 # 0
THEN
BEGIN
P5L.FieldOfVar[r: r1b, bSize: bSize];
P5L.FieldOfVar[r: r1a, bd: bSize, wSize: wSize];
P5L.FieldOfVar[r: r2b, bSize: bSize];
P5L.FieldOfVar[r: r2a, bd: bSize, wSize: wSize];
END
ELSE
BEGIN
P5L.FieldOfVar[r: r1b, wSize: wSize];
P5L.FieldOfVar[r: r1a, wd: wSize, bSize: bSize];
P5L.FieldOfVar[r: r2b, wSize: wSize];
P5L.FieldOfVar[r: r2a, wd: wSize, bSize: bSize];
END;
secondComp ← P5U.LabelAlloc[];
IF n = relN THEN firstEq ← label
ELSE firstEq ← P5U.LabelAlloc[];
VarVarComp[r1b, r2b, relE, real, signed, NullLex, NullLex, secondComp];
FreeHeapNodes[]; -- this looks awful here, but Final sorts it all out
P5U.OutJump[Jump, firstEq];
P5U.InsertLabel[secondComp];
VarVarComp[r1a, r2a, n, real, signed, hLex1, hLex2, label];
IF n # relN THEN P5U.InsertLabel[firstEq];
END;
END;
END;
FlowIn:
PROC [t: Tree.Link, tf:
BOOL, label: LabelCCIndex] =
BEGIN -- generates code for IN expression in flow context
node: Tree.Index = TreeOps.GetNode[t];
t1: Tree.Link = tb[node].son[1];
subNode: Tree.Index = TreeOps.GetNode[tb[node].son[2]]; -- interval node
n: Tree.NodeName = tb[subNode].name;
real: BOOL = tb[subNode].attr1;
double: BOOL = real OR tb[subNode].attr2;
signed: BOOL = tb[subNode].attr3;
tLow: Tree.Link = tb[subNode].son[1];
tUp: Tree.Link = tb[subNode].son[2];
jumpNN:
POINTER
TO
PACKED
ARRAY Tree.NodeName[relE..relLE]
OF JumpType ←
IF double OR signed THEN @JumpNN ELSE @UJumpNN;
r1: VarIndex;
hLex: Lexeme.se ← NullLex;
IF real
THEN
IF t = Tree.Null
AND CPtr.caseCVState = singleLoaded
THEN
Stack.Require[1]
ELSE Stack.Dump[];
r1 ← P5L.VarForLex[P5.Exp[t1 ! P5.LogHeapFree =>
IF calltree = t1 THEN RESUME [TRUE, hLex ← P5.GenAnonLex[1]]
ELSE RESUME [FALSE, NullLex]]];
IF ~real
AND Zero[tLow]
AND (~signed
OR Constant[tUp])
AND (n = intCO
OR n = intCC)
THEN
BEGIN
P5L.LoadVar[r1];
IF hLex # NullLex THEN {P5.FreeHeapLex[hLex]; hLex ← NullLex};
P5.PushRhs[tUp ! P5.LogHeapFree =>
IF calltree = tUp THEN RESUME [TRUE, hLex ← P5.GenAnonLex[1]]
ELSE RESUME [FALSE, NullLex]];
IF double
THEN
{P5U.Out0[FOpCodes.qUDCMP]; P5U.PushLitVal[0]; jumpNN ← @JumpNN}
ELSE jumpNN ← @UJumpNN;
IF hLex # NullLex THEN {P5.FreeHeapLex[hLex]; hLex ← NullLex};
SELECT n
FROM
intCO => P5U.OutJump[IF tf THEN jumpNN[relL] ELSE jumpNN[relGE], label];
intCC => P5U.OutJump[IF tf THEN jumpNN[relLE] ELSE jumpNN[relG], label];
ENDCASE;
END
ELSE
BEGIN
fail: LabelCCIndex = P5U.LabelAlloc[];
OutDComp:
PROC =
BEGIN
P5U.Out0[
IF real
THEN FOpCodes.qFCOMP
ELSE IF signed THEN FOpCodes.qDCMP ELSE FOpCodes.qUDCMP];
P5U.PushLitVal[0];
END;
var1: VarComponent ← P5L.MakeComponent[r1];
IF double THEN var1 ← P5L.EasilyLoadable[var1, load];
P5L.LoadComponent[var1];
IF hLex # NullLex THEN {P5.FreeHeapLex[hLex]; hLex ← NullLex};
P5.PushRhs[tLow ! P5.LogHeapFree =>
IF calltree = tLow THEN RESUME [TRUE, hLex ← P5.GenAnonLex[1]]
ELSE RESUME [FALSE, NullLex]];
IF double THEN OutDComp[];
IF hLex # NullLex THEN {P5.FreeHeapLex[hLex]; hLex ← NullLex};
SELECT n
FROM
intOO,intOC => P5U.OutJump[jumpNN[relLE], IF tf THEN fail ELSE label];
intCO,intCC => P5U.OutJump[jumpNN[relL], IF tf THEN fail ELSE label];
ENDCASE;
IF double THEN P5L.LoadComponent[var1]
ELSE P5U.Out0[FOpCodes.qREC];
P5.PushRhs[tUp ! P5.LogHeapFree =>
IF calltree = tUp THEN RESUME [TRUE, hLex ← P5.GenAnonLex[1]]
ELSE RESUME [FALSE, NullLex]];
IF double THEN OutDComp[];
IF hLex # NullLex THEN P5.FreeHeapLex[hLex];
SELECT n
FROM
intOO,intCO => P5U.OutJump[IF tf THEN jumpNN[relL] ELSE jumpNN[relGE], label];
intOC,intCC => P5U.OutJump[IF tf THEN jumpNN[relLE] ELSE jumpNN[relG], label];
ENDCASE;
P5U.InsertLabel[fail];
END;
END;
Constant:
PROC [t: Tree.Link]
RETURNS [
BOOL] =
BEGIN
RETURN [
WITH t
SELECT
FROM
literal => TRUE,
subtree => tb[index].name = mwconst,
ENDCASE => FALSE]
END;