DIRECTORY
Alloc: TYPE USING [Notifier],
Basics: TYPE USING [BytePair, bytesPerWord],
BcdDefs: TYPE USING [PageSize],
CatchFormat: TYPE USING [EnableItem],
Code: TYPE USING [codeptr, enableList],
CodeDefs:
TYPE
USING [
Base, BYTE, CCIndex, CCItem, CCNull, codeType, EINull,
EnableIndex, LabelCCIndex, TableCodeBytes],
ComData:
TYPE
USING [
catchBytes, catchIndex, codeByteOffsetList, codeOffsetList,
codeSeg, fgTable, globalFrameSize, jumpIndirectList,
linkCount, mtRoot, nBodies, nSigCodes,
stopping, switches],
CompilerUtil: TYPE USING [AcquireStream, NextFilePage, ReleaseStream],
IO:
TYPE
USING [
UnsafeBlock, GetIndex, GetLength, PutChar, SetIndex, SetLength, STREAM, UnsafePutBlock],
Fixup: TYPE USING [JIHandle, JIRec, PCHandle, PCRec],
FOpCodes: TYPE USING [qBLTC, qLCO, qGA, qLA],
Literals: TYPE USING [Base, MSTIndex, STIndex, stType],
LiteralOps: TYPE USING [EnumerateLocalStrings, EnumerateMasterStrings],
Log: TYPE USING [ErrorTree],
OSMiscOps: TYPE USING [FreePages, FreeWords, Pages, Words, pageSize],
P5: TYPE USING [C1W, P5Error],
P5U:
TYPE
USING [
FreeChunk, Out0, Out1, ComputeFrameSize, PushLitVal, RecordConstant,
WordsForString],
PrincOps:
TYPE
USING [
bytesPerPage, wordsPerPage,
AVHeapSize, BytePC, CSegPrefix, EntryVectorItem, EPRange, GlobalOverhead,
MaxFrameSize, PrefixHeader,
zJIB, zJIW, zLIW],
SourceMap: TYPE USING [Loc, nullLoc, Incr, Up, Val],
Stack: TYPE USING [Dump],
Symbols: TYPE USING [Base, BodyInfo, bodyType, CBTIndex, RootBti],
SymbolSegment: TYPE USING [FGTEntry, ObjectStep, SourceStep, Stride];
PutBlock:
PROC [stream:
IO.
STREAM, base:
LONG
POINTER, nw:
CARDINAL] = {
stream.UnsafePutBlock[[base: base, startIndex: 0, count: nw*Basics.bytesPerWord]]};
PutByte:
PROC[stream:
IO.
STREAM, b:
BYTE] =
INLINE {
stream.PutChar[VAL[b]]};
PutWord:
PROC[stream:
IO.
STREAM, w:
WORD] = {
pair: Basics.BytePair = LOOPHOLE[w];
PutByte[stream, pair.high]; PutByte[stream, pair.low]}; -- order is machine dependent
fgt: LONG DESCRIPTOR FOR ARRAY OF FGTEntry;
fgti: INTEGER;
fgtPages: CARDINAL;
LabelPcInfo: TYPE = RECORD [label: LabelCCIndex, pc: Address];
LabelPcSeq:
TYPE =
RECORD [
count: NAT,
data: SEQUENCE max: [0 .. NAT.LAST/LabelPcInfo.SIZE) OF LabelPcInfo];
LabelPcList: TYPE = REF LabelPcSeq;
labelPcList: LabelPcList ← NIL;
SetLabelPc:
PROC [label: LabelCCIndex, pc: Address] =
BEGIN
count: NAT ← IF labelPcList = NIL THEN 0 ELSE labelPcList.count;
FOR i:
NAT
IN [0..count)
DO
IF labelPcList[i].label = label THEN {labelPcList[i].pc ← pc; RETURN};
ENDLOOP;
IF labelPcList =
NIL
OR count = labelPcList.max
THEN {
new: LabelPcList ←
--MPtr.zone.--
NEW[LabelPcSeq[count+20] ←
[count: count, data:]];
FOR j: NAT IN [0..count) DO new[j] ← labelPcList[j] ENDLOOP;
IF labelPcList # NIL THEN --MPtr.zone.--FREE[@labelPcList];
labelPcList ← new};
labelPcList[count] ← [label: label, pc: pc];
labelPcList.count ← count+1;
END;
GetLabelPc:
PROC [label: LabelCCIndex]
RETURNS [Address] =
BEGIN
IF labelPcList = NIL THEN ERROR;
FOR i:
NAT
IN [0..labelPcList.count)
DO
IF labelPcList[i].label = label THEN RETURN [labelPcList[i].pc];
ENDLOOP;
ERROR;
END;
ProcessGlobalStrings:
PUBLIC
PROC [framestart:
CARDINAL]
RETURNS [nextnewframe: CARDINAL] =
BEGIN
firstNewCode, nextNewCode: CARDINAL ← MoveToCodeWord[];
stSize, litSize: CARDINAL;
DoString:
PROC [msti: MSTIndex] =
BEGIN
nw: CARDINAL;
IF stb[msti].info = 0 THEN {stb[msti].local ← TRUE; RETURN};
nw ← P5U.WordsForString[stb[msti].string.length];
stb[msti].info ← nextnewframe;
nextnewframe ← nextnewframe+nw;
IF nextnewframe > PrincOps.MaxFrameSize
THEN
Log.ErrorTree[addressOverflow, [literal[[string[msti]]]]];
stb[msti].codeIndex ← nextNewCode;
nextNewCode ← nextNewCode + nw;
WriteCodeString[@stb[msti].string, nw];
codeByteIndex ← codeByteIndex + nw*Basics.bytesPerWord;
END; -- of doglobal
nextnewframe ← framestart;
LiteralOps.EnumerateMasterStrings[DoString];
litSize ← nextNewCode - firstNewCode; stSize ← nextnewframe - framestart;
IF litSize > 0
THEN
BEGIN
P5U.RecordConstant[firstNewCode, litSize];
IF stSize > 0 THEN BLTStrings[firstNewCode, stSize, framestart, FALSE];
END;
END;
ProcessLocalStrings:
PUBLIC
PROC [framestart:
CARDINAL, first: STIndex]
RETURNS [nextnewframe: CARDINAL] =
BEGIN
nStrings: CARDINAL ← 0;
CountStrings:
PROC [msti: MSTIndex] =
BEGIN
IF stb[msti].local AND stb[msti].codeIndex # 0 THEN nStrings ← nStrings+1;
END;
firstNewCode, nextNewCode: CARDINAL;
firstCode: BOOL ← TRUE;
stSize, i, nw: CARDINAL;
curSize: CARDINAL ← 0;
StringInfo: TYPE = RECORD [offset: CARDINAL, sti: MSTIndex];
star: LONG DESCRIPTOR FOR ARRAY OF StringInfo;
InsertStrings:
PROC [msti: MSTIndex] =
BEGIN
IF stb[msti].local
THEN
BEGIN
co: CARDINAL = stb[msti].codeIndex;
IF co # 0
THEN
BEGIN
FOR i ← curSize, i-1
WHILE i>0
AND co < star[i-1].offset
DO
star[i] ← star[i-1];
ENDLOOP;
star[i] ← [co, msti];
curSize ← curSize+1;
END
ELSE
BEGIN
nw: CARDINAL = P5U.WordsForString[stb[msti].string.length];
stb[msti].info ← nextnewframe;
nextnewframe ← nextnewframe+nw;
IF nextnewframe > PrincOps.MaxFrameSize
THEN
Log.ErrorTree[addressOverflow, [literal[[string[msti]]]]];
IF firstCode
THEN {
firstCode ← FALSE; firstNewCode ← nextNewCode ← MoveToCodeWord[]};
stb[msti].codeIndex ← nextNewCode;
nextNewCode ← nextNewCode + nw;
WriteCodeString[@stb[msti].string, nw];
codeByteIndex ← codeByteIndex + nw*2;
END;
END;
END; -- of InsertStrings
nextnewframe ← framestart;
LiteralOps.EnumerateLocalStrings[first, CountStrings];
IF nStrings # 0
THEN
star ← DESCRIPTOR[OSMiscOps.Words[nStrings*StringInfo.SIZE], nStrings];
LiteralOps.EnumerateLocalStrings[first, InsertStrings];
stSize ← nextnewframe - framestart;
IF stSize > 0
THEN
BEGIN
BLTStrings[firstNewCode, stSize, framestart, TRUE];
P5U.RecordConstant[firstNewCode, stSize];
END;
i ← 0;
WHILE i < nStrings
DO
framestart ← nextnewframe;
nextNewCode ← firstNewCode ← star[i].offset;
WHILE i < nStrings
AND star[i].offset = nextNewCode
DO
nw ← P5U.WordsForString[stb[star[i].sti].string.length];
nextNewCode ← nextNewCode + nw;
stb[star[i].sti].info ← nextnewframe;
nextnewframe ← nextnewframe+nw;
IF nextnewframe > PrincOps.MaxFrameSize
THEN
Log.ErrorTree[addressOverflow, [literal[[string[star[i].sti]]]]];
i ← i+1;
ENDLOOP;
stSize ← nextnewframe - framestart;
BLTStrings[firstNewCode, stSize, framestart, TRUE];
ENDLOOP;
IF nStrings # 0 THEN OSMiscOps.FreeWords[star.BASE];
END;
BLTStrings:
PROC [coffset, length, foffset:
CARDINAL, local:
BOOL] =
BEGIN OPEN FOpCodes;
Stack.Dump[]; -- though I don't see how it could be non-empty now
P5U.Out1[qLCO, coffset];
P5U.PushLitVal[length];
P5U.Out1[IF local THEN qLA ELSE qGA, foffset];
P5U.Out0[qBLTC];
END;
OutputCatchBodies:
PROC =
BEGIN
IF firstCatch # CCNull THEN OutChunks[firstCatch];
MPtr.catchBytes ← codeByteIndex - catchOffset*Basics.bytesPerWord; -- count CEV, etc
END;
OutputCatchTables:
PROC =
BEGIN
maxLevel: CARDINAL = CPtr.enableList.LENGTH-1;
OutEnableLevel:
PROC [i:
CARDINAL] =
BEGIN
n: CARDINAL ← 0;
ei: EnableIndex;
ee: CatchFormat.EnableItem;
lei: EnableIndex = CPtr.enableList[i];
lnei: EnableIndex;
FOR ei ← lei, cb[ei].next
UNTIL ei = EINull
DO
n ← n+1;
ENDLOOP;
WriteCodeWord[n];
FOR ei ← lei, cb[ei].next
UNTIL ei = EINull
DO
ee ← [
start: [cb[ei].startPC], length: cb[ei].bytes,
index: bb[cb[ei].bti].index, alsoNested: FALSE];
IF i < maxLevel
AND (lnei ← CPtr.enableList[i+1]) # EINull
THEN
BEGIN -- look for nexted catch phrases
FOR nei: EnableIndex ← lnei, cb[nei].next
UNTIL nei = EINull
DO
ns: CARDINAL = cb[nei].startPC;
IF ns >= ee.start
THEN {
IF ns < ee.start + ee.length THEN ee.alsoNested ← TRUE;
EXIT};
ENDLOOP;
END;
PutBlock[objectStream, (@ee).LONG, CatchFormat.EnableItem.SIZE];
ENDLOOP;
END;
SortEnableLists[];
WriteCodeWord[catchEntry.LENGTH];
IF catchEntry.
LENGTH # 0
THEN
PutBlock[objectStream, catchEntry.BASE, catchEntry.LENGTH*PrincOps.BytePC.SIZE];
IF CPtr.enableList[0] = EINull THEN WriteCodeWord[0];
FOR l:
CARDINAL
IN [0..maxLevel]
WHILE CPtr.enableList[l] # EINull
DO
OutEnableLevel[l];
ENDLOOP;
END;
SortEnableLists:
PROC = {
FOR l:
CARDINAL
IN [0..CPtr.enableList.
LENGTH)
WHILE CPtr.enableList[l] # EINull
DO
new: EnableIndex ← EINull;
next: EnableIndex;
do simple insertion sort of each list
FOR ei: EnableIndex ← CPtr.enableList[l], next
UNTIL ei = EINull
DO
next ← cb[ei].next;
IF new = EINull OR cb[ei].startPC < cb[new].startPC THEN {cb[ei].next ← new; new ← ei}
ELSE {
prevEi: EnableIndex ← new;
WHILE cb[prevEi].next # EINull
AND cb[cb[prevEi].next].startPC < cb[ei].startPC
DO
prevEi ← cb[prevEi].next;
ENDLOOP;
cb[ei].next ← cb[prevEi].next;
cb[prevEi].next ← ei};
CPtr.enableList[l] ← new;
ENDLOOP;
ENDLOOP};
catchOffset: CARDINAL;
EndCodeFile:
PUBLIC
PROC
RETURNS [nbytes:
CARDINAL] =
BEGIN
maxLevel: CARDINAL = CPtr.enableList.LENGTH-1;
saveindex, catchIndex: StreamIndex;
noCatch: BOOL = (catchEntry.LENGTH = 0);
ctSize: CARDINAL ← 1 + catchEntry.LENGTH*PrincOps.BytePC.SIZE + 1;
prefix: PrincOps.PrefixHeader --CSegPrefix--;
nGfi:
CARDINAL =
(MAX[MPtr.nBodies, MPtr.nSigCodes] + (PrincOps.EPRange-1))/PrincOps.EPRange;
fs: CARDINAL;
IF nGfi NOT IN [1..4] THEN P5.P5Error[833];
IF noCatch THEN {catchOffset ← 0; MPtr.catchBytes ← 0}
ELSE {
lei: EnableIndex;
catchOffset ← MoveToCodeWord[];
catchIndex ← objectStream.GetIndex[];
FOR l:
CARDINAL
IN [0..maxLevel]
WHILE (lei ← CPtr.enableList[l]) # EINull
DO
IF l # 0 THEN ctSize ← ctSize + 1;
FOR ei: EnableIndex ← lei, cb[ei].next
WHILE ei # EINull
DO
ctSize ← ctSize + CatchFormat.EnableItem.SIZE;
ENDLOOP;
ENDLOOP;
codeByteIndex ← codeByteIndex + ctSize*2; -- make room for catch entry, enables
IF objectStream.GetLength[] < codeBase + codeByteIndex
THEN
objectStream.SetLength[codeBase + codeByteIndex];
objectStream.SetIndex[codeBase + codeByteIndex];
OutputCatchBodies[]};
MPtr.mtRoot.code.length ← codeByteIndex;
[] ← MoveToCodeWord[];
saveindex ← objectStream.GetIndex[];
IF ~noCatch
THEN {
objectStream.SetIndex[catchIndex]; codeByteIndex ← catchOffset*2;
OutputCatchTables[]};
MPtr.fgTable ← DESCRIPTOR[fgt.BASE, fgti+1];
MPtr.codeSeg.pages ←
(2*MPtr.mtRoot.code.offset + MPtr.mtRoot.code.length + (2*BcdDefs.PageSize-1))/
(2*BcdDefs.PageSize);
objectStream.SetIndex[codeBase];
fs ← P5U.ComputeFrameSize[MPtr.globalFrameSize];
IF bb[Symbols.RootBti].resident THEN fs ← fs+PrincOps.AVHeapSize;
prefix
--.header-- ← [
globalFsi: fs,
nEntries: MPtr.nBodies,
info: [
available: 0,
stops: MPtr.stopping, ngfi: nGfi, nlinks: MPtr.linkCount]
];
PutBlock[objectStream, (@prefix).LONG, PrincOps.PrefixHeader.SIZE];
PutBlock[
objectStream, entryVector.BASE, entryVector.LENGTH*PrincOps.EntryVectorItem.SIZE];
PutWord[objectStream, catchOffset*2];
OSMiscOps.FreeWords[entryVector.BASE];
OSMiscOps.FreeWords[catchEntry.BASE];
MPtr.mtRoot.framesize ← MPtr.globalFrameSize + PrincOps.GlobalOverhead.SIZE;
MPtr.mtRoot.crossJumped ← MPtr.switches['j];
objectStream.SetIndex[saveindex];
CompilerUtil.ReleaseStream[object]; objectStream ← NIL;
IF labelPcList #
NIL
THEN {
FOR i:
NAT
IN [0..labelPcList.count)
DO
P5U.FreeChunk[labelPcList[i].label, CCItem.label.SIZE];
ENDLOOP;
--MPtr.zone.--FREE[@labelPcList]};
IF MPtr.codeOffsetList #
NIL
THEN {
p: Fixup.PCHandle = MPtr.codeOffsetList.next;
MPtr.codeOffsetList.next ← NIL; MPtr.codeOffsetList ← p};
IF MPtr.codeByteOffsetList #
NIL
THEN {
p: Fixup.PCHandle = MPtr.codeByteOffsetList.next;
MPtr.codeByteOffsetList.next ← NIL; MPtr.codeByteOffsetList ← p};
IF MPtr.jumpIndirectList #
NIL
THEN {
j: Fixup.JIHandle = MPtr.jumpIndirectList.next;
MPtr.jumpIndirectList.next ← NIL; MPtr.jumpIndirectList ← j};
RETURN [MPtr.mtRoot.code.length]
END;