<<>> <> <> <> <> <> <> <<>> DIRECTORY Alloc USING [AddNotify, Base, BaseSeq, DropNotify, Notifier], Basics USING [LowHalf], BasicTime USING [Now], CardTab USING [Create, Ref, Store], CompilerUtil USING [], ConstArith USING [ToInt], ConvertUnsafe USING [ToRope, SubString, SubStringToRope], IntCodeDefs USING [BlockNode, ByteSequence, CaseList, Label, LabelNode, LambdaKind, LambdaNode, Location, LocationRep, MesaSelector, ModuleNode, Node, NodeList, NodeRep, RefLitKind, SourceNode, Var, VariableFlags, VarList], IntCodeGen USING [CodeGenerator, GetCodeGenerator], IntCodeStuff USING [NodeContains], IntCodeTwig USING [BaseModel, DoModule, LambdaModel], IntCodeUtils USING [MapNode, Visitor, zone], IO USING [PutChar, PutF1, PutFR, PutRope, RopeFromROS, ROS, STREAM], List USING [CompareProc, UniqueSort], LiteralOps USING [StringValue], Literals USING [Base, STIndex, stType], MimBodyCorrect USING [FixBodies], MimCommandUtil USING [GetRootName, SetExtension], MimCode USING [BitCount, CodeList, StoreOptions], MimData USING [bodyIndex, idATOM, idTEXT, mainCtx, nSigCodes, objectVersion, source, switches, table, textIndex, worstAlignment], MimosaLog USING [ErrorRope], MimP5 USING [DeclList, Exp, ExpList, StatementList, StatementTree, VarForSei, VisibalContextArray, WrapSource, WrapSourceBlock], MimP5Install USING [GenInstallationProc], MimP5S USING [ComAssign, ExtendValue, Temporize, WillEvalToConst], MimP5U USING [Address, AllocLabel, AppendNodeList, ApplyOp, Assign, BitsForOperand, BitsForType, CgenUtilInit, CreateTemp, Declare, Deref, ExtractList, InsertLabel, Jump, LabelAddress, MakeArgList, MakeArgList2, MakeBlock, MakeComposite, MakeConstCard, MakeGoTo, MakeNodeList, MakeNodeList2, MakeReturn, MakeTemp, MakeVarList, MaybeBlock, MesaOpNode, MoreCode, NewCodeList, NextVar, OperandType, PadArgList, ProcessSafens, TakeField, TakeFieldVar, TreeLiteralValue, TypeForTree], MimSysOps USING [Close, Open], MobDefs USING [Link, ModuleIndex], ParseIntCode USING [ToStream], Rope USING [Concat, FromProc, ROPE], SourceMap USING [Loc, nullLoc, Up], SymbolOps USING [DecodeLink, EncodeBitAddr, EncodeInt, EnumerateBodies, MakeCtxSe, NameForSe, NextSe, own, ParentBti, RCType, SetCtxLevel, SubStringForName, TransferTypes, XferMode], Symbols USING [Base, bodyType, BTIndex, BTNull, CBTIndex, CBTNull, ContextLevel, CSEIndex, CSENull, CTXIndex, CTXNull, ctxType, HTNull, ISEIndex, ISENull, lG, lL, Name, nullType, RecordSEIndex, RecordSENull, RootBti, SEIndex, SENull, seType, SpecialVarKind, Type, typeANY, VariableFlags], TargetConversions USING [NewWriter, PutCard, PutChar, Writer, WriterContents], Target: TYPE MachineParms USING [bitsPerAU, bitsPerByte, bitsPerChar, bitsPerLongWord, bitsPerRef, bitsPerSignal, bitsPerStringBound, bitsPerWord], Tree USING [Base, Index, Link, LinkRep, Map, NodePtr, NodeName, Null, treeType], TreeOps USING [GetTag, OpName, SearchList, UpdateLeaves]; MimDriver: PROGRAM IMPORTS Alloc, Basics, BasicTime, CardTab, ConstArith, ConvertUnsafe, IntCodeGen, IntCodeStuff, IntCodeTwig, IntCodeUtils, IO, List, LiteralOps, MimBodyCorrect, MimCommandUtil, MimData, MimosaLog, MimP5, MimP5Install, MimP5S, MimP5U, MimSysOps, ParseIntCode, Rope, SourceMap, SymbolOps, TargetConversions, TreeOps EXPORTS CompilerUtil, MimCode, MimP5, MimP5S = { OPEN IntCodeDefs, MimCode, Target; <> enableTypesFile: BOOL ¬ FALSE; enableIntCodeTransforms: BOOL ¬ TRUE; collectConstants: BOOL ¬ TRUE; minCollectibleWords: NAT ¬ 4; noCollectConstAssigns: BOOL ¬ TRUE; maxMemoBits: INT ¬ LAST[INT]; <> minMemoBits: INT ¬ 3*LONG[bitsPerLongWord]+1; <> <> LORA: TYPE = LIST OF REF ANY; ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; BTIndex: TYPE = Symbols.BTIndex; CBTIndex: TYPE = Symbols.CBTIndex; CTXIndex: TYPE = Symbols.CTXIndex; CTXNull: CTXIndex = Symbols.CTXNull; CSEIndex: TYPE = Symbols.CSEIndex; CSENull: CSEIndex = Symbols.CSENull; ISEIndex: TYPE = Symbols.ISEIndex; ISENull: ISEIndex = Symbols.ISENull; RecordSEIndex: TYPE = Symbols.RecordSEIndex; RecordSENull: RecordSEIndex = Symbols.RecordSENull; Type: TYPE = Symbols.Type; nullType: Type = Symbols.nullType; typeANY: Type = Symbols.typeANY; bytesPerWord: NAT = Target.bitsPerWord / Target.bitsPerByte; bitsPerPtr: NAT = Target.bitsPerRef; bitsPerWord: NAT = Target.bitsPerWord; bitsPerProcDesc: NAT = bitsPerPtr*2; <> curctxlvl: PUBLIC Symbols.ContextLevel ¬ Symbols.lG; bodyRetLabel, bodyComRetLabel: PUBLIC Label ¬ NIL; bodyInRecord, bodyOutRecord: PUBLIC Symbols.RecordSEIndex ¬ RecordSENull; mainBody: PUBLIC BOOL ¬ FALSE; tailJumpOK: PUBLIC BOOL ¬ FALSE; caseCV: PUBLIC Node ¬ NIL; caseType: PUBLIC Symbols.Type ¬ nullType; fileLoc, inlineFileLoc: PUBLIC SourceMap.Loc ¬ SourceMap.nullLoc; catchcount: PUBLIC CARDINAL ¬ 0; catchoutrecord: PUBLIC Symbols.RecordSEIndex ¬ RecordSENull; tempcontext: PUBLIC Symbols.CTXIndex ¬ CTXNull; xtracting: PUBLIC BOOL ¬ FALSE; xtractNode: PUBLIC Node ¬ NIL; xtractsei: PUBLIC Symbols.ISEIndex ¬ ISENull; nC0, nC1: PUBLIC Node ¬ NIL; <> trueNode, falseNode: PUBLIC Node ¬ NIL; <> CodeNotImplemented: PUBLIC SIGNAL = CODE; CodePassInconsistency: PUBLIC SIGNAL = CODE; <> myBaseSeq: REF Alloc.BaseSeq ¬ NIL; tb: Tree.Base; -- tree base (local copy) seb: Symbols.Base; -- semantic entry base (local copy) ctxb: Symbols.Base; -- context entry base (local copy) bb: Symbols.Base; -- body entry base (local copy) stb: Literals.Base; -- string base (local copy) DriverNotify: Alloc.Notifier = { <> myBaseSeq ¬ base; seb ¬ base[Symbols.seType]; ctxb ¬ base[Symbols.ctxType]; bb ¬ base[Symbols.bodyType]; stb ¬ base[Literals.stType]; tb ¬ base[Tree.treeType]; FOR i: NAT IN [0..notifiers) DO notifier: Alloc.Notifier ¬ notifierArray[i]; notifier[base]; ENDLOOP; }; z: PUBLIC ZONE ¬ IntCodeUtils.zone; notifiers: NAT ¬ 0; notifierArray: REF NotifierArray ¬ z.NEW[NotifierArray ¬ ALL[NIL]]; NotifierArray: TYPE = ARRAY [0..32) OF Alloc.Notifier; <> inInline: PUBLIC BOOL ¬ FALSE; localProcCodeList: CodeList ¬ NIL; substState: REF SubstState ¬ NIL; SubstState: TYPE = RECORD [ cl: CodeList ¬ NIL, prefixCL: CodeList ¬ NIL, postfixCL: CodeList ¬ NIL, resultType: Type ¬ nullType, resultVar: Var ¬ NIL, exitLabel: IntCodeDefs.Label ¬ NIL, lock: Tree.Link ¬ Tree.Null, lastResult: Node ¬ NIL, lastResultExpr: Node ¬ NIL, lastResultGoTo: Node ¬ NIL, nResults: INT ¬ 0 ]; mLock: Tree.Link ¬ Tree.Null; signalsVar: Var ¬ NIL; procDescRoot: REF ProcDescEntry ¬ NIL; ProcDescEntry: TYPE = RECORD [ rest: REF ProcDescEntry ¬ NIL, -- the next sibling (if any) parent: REF ProcDescEntry ¬ NIL, -- the parent (if any) child: REF ProcDescEntry ¬ NIL, -- the first child (if any) name: ROPE ¬ NIL, -- the name of the proc label: Label ¬ NIL, -- the label for the proc used: BOOL ¬ FALSE, -- TRUE if used as a proc desc bti: CBTIndex ¬ Symbols.CBTNull, -- the bti for the proc indirectEntry: Node ¬ NIL, -- the indirect entry point directEntry: Node ¬ NIL, -- the direct entry point body: Var ¬ NIL -- the variable for the proc desc body ]; maxBti: CBTIndex ¬ Symbols.RootBti; <> modNode: ModuleNode ¬ NIL; modVarsTail: VarList ¬ NIL; <> maxGlobalVarId: INT ¬ 0; <> <<>> ModuleIndex: TYPE = MobDefs.ModuleIndex; linkToVarSeq: LinkVarSeq ¬ NIL; LinkVarSeq: TYPE = REF LinkVarSeqRep; LinkVarSeqRep: TYPE = RECORD [ length: ModuleIndex, entries: SEQUENCE max: ModuleIndex OF Var ]; linkOverhead: NAT ¬ 4; <> <<(This needs to be parameterized)>> extraLinkDeref: BOOL ¬ FALSE; <> <<(This needs to be parameterized)>> <> P5module: PUBLIC PROC = { <> moduleNode: Node = Module[]; nodeList: NodeList ¬ MimP5U.MakeNodeList[moduleNode]; root: ROPE ¬ MimCommandUtil.GetRootName[MimData.source.locator]; id: Symbols.Name ¬ seb[bb[Symbols.RootBti].id].hash; ss: ConvertUnsafe.SubString = SymbolOps.SubStringForName[SymbolOps.own, id]; moduleName: ROPE ¬ ConvertUnsafe.SubStringToRope[ss]; namesFileName: ROPE ¬ MimCommandUtil.SetExtension[root, "names"]; nameStream: STREAM ¬ NIL; err: ROPE ¬ NIL; cg: IntCodeGen.CodeGenerator ¬ NIL; cgd: REF ¬ NIL; [cg: cg, data: cgd] ¬ IntCodeGen.GetCodeGenerator[]; IF MimData.switches['m] THEN cg ¬ NIL; IF MimData.switches['i] THEN { <> [nameStream, err, ] ¬ MimSysOps.Open[namesFileName, $write]; IF err # NIL THEN {MimosaLog.ErrorRope[other, err]; RETURN}; IO.PutF1[nameStream, "-- %g \n", [rope[namesFileName]] ]; }; MimP5Install.GenInstallationProc[ FindProcDesc[Symbols.RootBti].name, bb[Symbols.RootBti].type, NARROW[modNode]]; IF enableIntCodeTransforms THEN { <> model: IntCodeTwig.BaseModel ¬ IntCodeTwig.DoModule[modNode, MimData.switches]; lambda: IntCodeTwig.LambdaModel ¬ model.first; nodeList ¬ MimP5U.MakeNodeList[model.module]; RewriteSymbols[model]; <> WHILE lambda # NIL DO next: IntCodeTwig.LambdaModel ¬ lambda.next; lambda­ ¬ []; -- clobber the fields to the ground state lambda ¬ next; ENDLOOP; model­ ¬ []; -- clobber the base model }; { cr: ROPE ¬ IO.PutFR["file: %g, module: %g, compiled at: %g", [rope[root]], [rope[moduleName]], [time[BasicTime.Now[]]]]; cn: Node ¬ z.NEW[NodeRep.comment ¬ [bits: 0, details: comment[cr]]]; modNode.procs ¬ MimP5U.MakeNodeList[cn, modNode.procs]; }; MimBodyCorrect.FixBodies[modNode.procs]; <> IF MimData.switches['i] THEN { <> tName: ROPE ¬ MimCommandUtil.SetExtension[root, "icd"]; st: STREAM ¬ NIL; [st, err, ] ¬ MimSysOps.Open[tName, $write]; IF err # NIL THEN {MimosaLog.ErrorRope[other, err]; RETURN}; ParseIntCode.ToStream[st, nodeList]; [] ¬ MimSysOps.Close[st]; }; IF nameStream # NIL OR cg # NIL THEN { <> head: LORA ¬ NIL; tail: LORA ¬ NIL; inner: IntCodeUtils.Visitor = TRUSTED { <<[node: IntCodeDefs.Node] RETURNS [IntCodeDefs.Node]>> add: BOOL ¬ FALSE; WITH node SELECT FROM var: Var => add ¬ var.flags[named]; labelNode: LabelNode => WITH labelNode.label.node SELECT FROM lambda: LambdaNode => add ¬ TRUE; ENDCASE; ENDCASE; IF add THEN { new: LORA ¬ LIST[node]; IF tail = NIL THEN head ¬ new ELSE tail.rest ¬ new; tail ¬ new; }; IntCodeUtils.MapNode[node, inner]; RETURN [node]; }; compare: List.CompareProc = TRUSTED { delta: INT; WITH ref1 SELECT FROM var1: Var => WITH ref2 SELECT FROM var2: Var => delta ¬ var1.id - var2.id; labelNode2: LabelNode => RETURN [greater]; ENDCASE; labelNode1: LabelNode => WITH ref2 SELECT FROM var2: Var => RETURN [less]; labelNode2: LabelNode => delta ¬ labelNode1.label.id - labelNode2.label.id; ENDCASE; ENDCASE; SELECT delta FROM < 0 => RETURN [less]; > 0 => RETURN [greater]; ENDCASE => RETURN [equal]; }; table: CardTab.Ref ¬ NIL; IntCodeUtils.MapNode[modNode, inner]; head ¬ List.UniqueSort[head, compare]; IF nameStream # NIL THEN { <> FOR each: LORA ¬ head, each.rest WHILE each # NIL DO WITH each.first SELECT FROM var: Var => IF var.flags[named] THEN { sei: Symbols.ISEIndex; index: Tree.LinkRep ¬ LOOPHOLE[var.id]; index.tag ¬ VAL[0]; IO.PutF1[nameStream, "\n %g: ", [integer[LOOPHOLE[index]]] ]; index.tag ¬ symbol; sei ¬ LOOPHOLE[index]; PrintSei[nameStream, sei]; }; labelNode: LabelNode => IF labelNode.label.id IN [0..100000) THEN { bti: Symbols.BTIndex = LOOPHOLE[labelNode.label.id]; IO.PutF1[nameStream, "\n %%%g: ", [integer[LOOPHOLE[bti]]] ]; WITH b: bb[bti] SELECT FROM Callable => PrintSei[nameStream, b.id]; ENDCASE => IO.PutRope[nameStream, "??"]; }; ENDCASE; ENDLOOP; IO.PutRope[nameStream, "\n\n"]; [] ¬ MimSysOps.Close[nameStream]; }; IF cg # NIL THEN { <> msg: ROPE ¬ NIL; namesTable: CardTab.Ref ¬ CardTab.Create[]; labelsTable: CardTab.Ref ¬ CardTab.Create[]; FOR each: LORA ¬ head, each.rest WHILE each # NIL DO WITH each.first SELECT FROM var: Var => IF var.flags[named] THEN { sei: Symbols.ISEIndex; index: Tree.LinkRep ¬ LOOPHOLE[var.id]; index.tag ¬ symbol; sei ¬ LOOPHOLE[index]; [] ¬ CardTab.Store[namesTable, LOOPHOLE[var.id, CARD], RopeForSei[sei]]; }; labelNode: LabelNode => IF labelNode.label.id IN [0..100000) THEN { bti: Symbols.BTIndex = LOOPHOLE[labelNode.label.id]; WITH b: bb[bti] SELECT FROM Callable => [] ¬ CardTab.Store[labelsTable, LOOPHOLE[bti, CARD], RopeForSei[b.id]]; ENDCASE; }; ENDCASE; ENDLOOP; msg ¬ cg[ fileName: root, moduleName: moduleName, versionStamp: IO.PutFR["[%g,%g]", [cardinal[MimData.objectVersion[0]]], [cardinal[MimData.objectVersion[1]]] ], root: modNode, names: namesTable, labels: labelsTable, data: cgd, switches: MimData.switches]; IF msg # NIL THEN MimosaLog.ErrorRope[other, msg]; }; }; <> z.FREE[@linkToVarSeq]; (MimData.table).DropNotify[DriverNotify]; myBaseSeq ¬ NIL; caseCV ¬ NIL; xtractNode ¬ NIL; mLock ¬ Tree.Null; signalsVar ¬ NIL; ClearProcDesc[procDescRoot]; procDescRoot ¬ NIL; MimP5U.CgenUtilInit[NIL]; IntCodeUtils.MapNode[modNode, ClearNodes]; modNode ¬ NIL; modVarsTail ¬ NIL; }; <> RegisterNotifier: PUBLIC PROC [notifier: Alloc.Notifier] = { notifierArray[notifiers] ¬ notifier; notifiers ¬ notifiers + 1; IF myBaseSeq # NIL THEN notifier[myBaseSeq]; }; <> visibleContext: PUBLIC REF MimP5.VisibalContextArray ¬ NIL; MakeGlobal: PUBLIC PROC [bits: INT, type: Type ¬ typeANY] RETURNS [v: Var, sei: ISEIndex] = { oldTempCtx: Symbols.CTXIndex ¬ tempcontext; new: VarList; tempcontext ¬ MimData.mainCtx; [v, sei] ¬ MimP5U.CreateTemp[bits: bits, type: type]; new ¬ MimP5U.MakeVarList[v]; SELECT TRUE FROM modVarsTail # NIL => modVarsTail.rest ¬ new; modNode.vars = NIL => modNode.vars ¬ new; ENDCASE => ERROR; modVarsTail ¬ new; tempcontext ¬ oldTempCtx; RETURN [v, sei]; }; <<>> P5Error: PUBLIC PROC [n: CARDINAL] = { ERROR CodePassError[n]; }; ProcDescForBti: PUBLIC PROC [bti: CBTIndex, body: BOOL] RETURNS [Node] = { new: REF ProcDescEntry ¬ FindProcDesc[bti]; node: Node ¬ new.body; new.used ¬ TRUE; IF node = NIL THEN ERROR; IF NOT body THEN node ¬ MimP5U.Address[node]; <> RETURN [node]; }; ProcLabelForBti: PUBLIC PROC [bti: CBTIndex, direct: BOOL] RETURNS [Node] = { new: REF ProcDescEntry ¬ FindProcDesc[bti]; node: Node ¬ IF direct THEN new.directEntry ELSE new.indirectEntry; new.used ¬ TRUE; RETURN [node]; }; SignalForSei: PUBLIC PROC [sei: ISEIndex] RETURNS [Node] = { SELECT SymbolOps.XferMode[SymbolOps.own, seb[sei].idType] FROM signal, error => { link: MobDefs.Link = SymbolOps.DecodeLink[seb[sei].idValue]; index: NAT = link.offset; IF link.modIndex = 0 THEN { <> sel: IntCodeDefs.MesaSelector = SELECT index FROM 0 => unnamedError, 1 => unwindError, 2 => abortedError, 3 => uncaughtError, 4 => boundsError, ENDCASE => ERROR; RETURN [MimP5U.MesaOpNode[op: sel, bits: bitsPerSignal]]; }; RETURN [MimP5U.Address[MimP5U.TakeField[ signalsVar, index*bitsPerWord, bitsPerWord]]]; }; ENDCASE => ERROR; }; <<>> VarForInterface: PUBLIC PROC [mod: MobDefs.ModuleIndex] RETURNS [Var] = { <> oldLen: ModuleIndex ¬ IF linkToVarSeq = NIL THEN 0 ELSE linkToVarSeq.length; linkVar: Var ¬ NIL; IF oldLen <= mod THEN { newLen: ModuleIndex = MIN[MAX[mod+1, oldLen + oldLen/2 + 1], ModuleIndex.LAST]; newSeq: LinkVarSeq ¬ z.NEW[LinkVarSeqRep[newLen]]; newSeq.length ¬ mod+1; IF linkToVarSeq # NIL THEN { FOR i: ModuleIndex IN [0..oldLen) DO newSeq[i] ¬ linkToVarSeq[i]; linkToVarSeq[i] ¬ NIL; ENDLOOP; z.FREE[@linkToVarSeq]; }; linkToVarSeq ¬ newSeq; }; linkVar ¬ linkToVarSeq[mod]; IF linkVar = NIL THEN <> linkToVarSeq[mod] ¬ linkVar ¬ MakeGlobal[bitsPerPtr].v; RETURN [linkVar]; }; VarForLink: PUBLIC PROC [link: MobDefs.Link, bits: INT] RETURNS [v: Var] = { <> offset: CARD = Target.bitsPerRef * (link.offset + linkOverhead); linkVar: Var ¬ VarForInterface[link.modIndex]; v ¬ MimP5U.TakeFieldVar[ MimP5U.Deref[linkVar, offset+bits, MimData.worstAlignment], offset, bits]; }; <> Lock: PUBLIC PROC [node: Tree.Index] RETURNS [n: Node ¬ NIL] = { saveLock: Tree.Link = mLock; cl: CodeList ¬ MimP5U.NewCodeList[]; mLock ¬ tb[node].son[2]; substState.lock ¬ mLock; SetLock[cl, mLock]; n ¬ MimP5U.MaybeBlock[cl, MimP5.StatementTree[tb[node].son[1]]]; mLock ¬ saveLock; }; <<>> Result: PUBLIC PROC [node: Tree.Index] RETURNS [Node ¬ NIL] = { <> cl: CodeList ¬ MimP5U.NewCodeList[]; resultVar: Var ¬ substState.resultVar; <> <> substState.lastResultExpr ¬ NIL; substState.nResults ¬ substState.nResults + 1; IF resultVar # NIL THEN { returnOfAnotherCall: BOOL ¬ tb[node].attr3; t1: Tree.Link ¬ tb[node].son[1]; dstType: Type = substState.resultType; result: Node ¬ NIL; IF returnOfAnotherCall THEN result ¬ MimP5.Exp[t1] ELSE { list: NodeList ¬ MimP5.ExpList[t1, TRUE].head; IF list.rest = NIL THEN result ¬ list.first ELSE result ¬ MimP5U.MakeComposite[list]; <> }; IF result # NIL AND result.bits # resultVar.bits THEN { <> lbits: INT ¬ resultVar.bits; rbits: INT ¬ result.bits; SELECT lbits FROM < rbits => { <> start: INT ¬ IF rbits <= bitsPerWord THEN rbits-lbits ELSE 0; result ¬ MimP5U.TakeField[result, start, lbits]; }; > rbits => { <> srcType: Type = SELECT TreeOps.OpName[t1] FROM none, list => dstType, ENDCASE => MimP5U.OperandType[t1]; result ¬ MimP5S.ExtendValue[result, dstType, srcType, lbits]; }; ENDCASE; }; substState.lastResultExpr ¬ result; MimP5U.MoreCode[cl, MimP5U.Assign[lhs: resultVar, rhs: result]]; }; IF substState.exitLabel = NIL THEN <> substState.exitLabel ¬ MimP5U.AllocLabel[]; IF substState.lastResultGoTo = NIL THEN substState.lastResultGoTo ¬ MimP5U.MakeGoTo[substState.exitLabel]; substState.lastResult ¬ MimP5U.MaybeBlock[cl, substState.lastResultGoTo]; RETURN [substState.lastResult]; }; Resume: PUBLIC PROC [node: Tree.Index] RETURNS [Node ¬ NIL] = { <> returnOfAnotherCall: BOOL ¬ tb[node].attr3; retvals: NodeList; t1: Tree.Link ¬ tb[node].son[1]; totalBits: BitCount ¬ MimP5U.BitsForType[catchoutrecord]; IF returnOfAnotherCall THEN retvals ¬ MimP5U.MakeNodeList[MimP5.Exp[t1]] ELSE retvals ¬ MimP5.ExpList[t1, TRUE].head; RETURN [MimP5U.ApplyOp[oper: MimP5U.MesaOpNode[resume], args: MimP5U.PadArgList[retvals]]]; }; Return: PUBLIC PROC [node: Tree.Index] RETURNS [l: Node] = { <> cl: CodeList ¬ MimP5U.NewCodeList[]; monitored: BOOL ¬ tb[node].attr1; <> returnOfAnotherCall: BOOL ¬ tb[node].attr3; retvals: NodeList; t1: Tree.Link ¬ tb[node].son[1]; safend: Tree.Link ¬ t1; totalBits: BitCount ¬ MimP5U.BitsForType[bodyOutRecord]; IF (Basics.LowHalf[totalBits] MOD bitsPerWord) # 0 THEN ERROR; <> IF CommonRet[t1] THEN { <> outCtx: CTXIndex = IF bodyOutRecord = CSENull THEN CTXNull ELSE seb[bodyOutRecord].fieldCtx; IF substState.exitLabel # NIL THEN { <> MimP5U.Jump[cl, substState.exitLabel]; RETURN [MimP5U.MakeBlock[cl]]; }; IF monitored THEN LocalReleaseLock[cl, mLock]; RETURN [MimP5U.MaybeBlock[cl, MimP5U.MakeReturn[NodesForCtx[outCtx]]]]; }; IF monitored THEN safend ¬ MimP5U.ProcessSafens[cl: cl, t: t1]; <> IF returnOfAnotherCall THEN retvals ¬ MimP5U.MakeNodeList[MimP5.Exp[safend]] ELSE retvals ¬ MimP5.ExpList[safend, TRUE].head; IF substState.exitLabel # NIL THEN { <> IF ListNeedsTemp[retvals] THEN MakeListNice[cl, retvals]; IF bodyOutRecord # RecordSENull THEN { <> ctx: Symbols.CTXIndex = seb[bodyOutRecord].fieldCtx; sei: ISEIndex ¬ MimP5U.NextVar[ctxb[ctx].seList]; UNTIL sei = ISENull DO var: Var ¬ MimP5.VarForSei[sei]; src: Node ¬ retvals.first; IF returnOfAnotherCall THEN { retvals.first ¬ MimP5U.TakeField[src, var.bits, src.bits-var.bits]; src ¬ MimP5U.TakeField[src, 0, var.bits]; } ELSE retvals ¬ retvals.rest; MimP5U.MoreCode[cl, MimP5U.Assign[var, src]]; sei ¬ MimP5U.NextVar[SymbolOps.NextSe[SymbolOps.own, sei]]; ENDLOOP; }; MimP5U.Jump[cl, substState.exitLabel]; RETURN [MimP5U.MakeBlock[cl]]; }; IF monitored THEN { <> IF ListNeedsTemp[retvals] THEN MakeListNice[cl, retvals]; LocalReleaseLock[cl, mLock]; }; l ¬ MimP5U.MaybeBlock[cl, MimP5U.MakeReturn[retvals]]; }; RetWithError: PUBLIC PROC [node: Tree.Index] RETURNS [Node] = { <> <<>> <> <> cl: CodeList ¬ MimP5U.NewCodeList[]; psei: CSEIndex = MimP5U.OperandType[tb[node].son[1]]; sig: Node ¬ MimP5.Exp[tb[node].son[1]]; t2: Tree.Link ¬ tb[node].son[2]; monitored: BOOL ¬ tb[node].attr1; exitLabel: Label ¬ MimP5U.AllocLabel[]; sigTemp: Var ¬ NIL; argsList: NodeList ¬ NIL; argsTemp: Var ¬ NIL; prefixCL: CodeList ¬ substState.prefixCL; postfixCL: CodeList ¬ substState.postfixCL; <> IF prefixCL = NIL THEN <> prefixCL ¬ substState.prefixCL ¬ MimP5U.NewCodeList[]; IF postfixCL = NIL THEN <> postfixCL ¬ substState.postfixCL ¬ MimP5U.NewCodeList[]; <> t2 ¬ MimP5U.ProcessSafens[cl: cl, t: t2]; <> sigTemp ¬ MimP5U.MakeTemp[prefixCL, sig.bits].var; MimP5U.MoreCode[cl, MimP5U.Assign[sigTemp, sig]]; <> argsList ¬ MimP5.ExpList[t2, TRUE].head; IF argsList # NIL THEN { argsVar: Var ¬ MimP5U.MakeComposite[MimP5U.PadArgList[argsList]]; argsTemp ¬ MimP5U.MakeTemp[prefixCL, argsVar.bits].var; MimP5U.MoreCode[cl, MimP5U.Assign[argsTemp, argsVar]]; }; IF monitored THEN LocalReleaseLock[cl, mLock]; <> <> MimP5U.Jump[cl, exitLabel]; <> MimP5U.InsertLabel[postfixCL, exitLabel]; MimP5U.MoreCode[postfixCL, MimP5.WrapSource[ node: MimP5U.ApplyOp[ oper: MimP5U.MesaOpNode[error], args: IF argsTemp = NIL THEN MimP5U.MakeArgList[sigTemp] ELSE MimP5U.MakeArgList2[sigTemp, argsTemp]], loc: LOOPHOLE[tb[node].info, SourceMap.Loc] ] ]; RETURN [MimP5U.MakeBlock[cl]]; }; MakeString: PUBLIC PROC [t: Tree.Link] RETURNS [Node] = { WITH e: t SELECT TreeOps.GetTag[t] FROM string => { sti: Literals.STIndex ¬ e.index; string: LONG STRING ¬ LiteralOps.StringValue[sti]; local: BOOL ¬ FALSE; DO WITH s: stb[sti] SELECT FROM heap => { kind: IntCodeDefs.RefLitKind ¬ rope; SELECT s.type FROM MimData.idATOM => kind ¬ atom; MimData.idTEXT => kind ¬ refText; ENDCASE => kind ¬ rope; RETURN [z.NEW[NodeRep.const.refLiteral ¬ [ bits: bitsPerPtr, details: const[data: refLiteral[ litKind: kind, contents: ConvertUnsafe.ToRope[string]]]]]]; }; copy => {sti ¬ s.link; local ¬ TRUE}; <> master => { align: NAT ¬ Target.bitsPerWord; nchars: INT ¬ string.length; extras: NAT ¬ bytesPerWord - (nchars MOD bytesPerWord); bits: INT ¬ (nchars+extras)*bitsPerChar + 2*bitsPerStringBound; init: Node ¬ z.NEW[NodeRep.const.bytes ¬ [ bits: bits, details: const[bytes[align, RopeHoldingStringRep[string]]]]]; IF local THEN <> init ¬ MimP5U.MakeTemp[cl: localProcCodeList, bits: bits, init: init].var; RETURN [MimP5U.Address[init]]; }; ENDCASE => ERROR; ENDLOOP; }; ENDCASE => ERROR; }; RopeHoldingStringRep: PROC [string: LONG STRING] RETURNS [ByteSequence] = { nchars: CARDINAL ¬ string.length; writer: TargetConversions.Writer ¬ TargetConversions.NewWriter[]; extras: NAT ¬ bytesPerWord - (nchars MOD bytesPerWord); TargetConversions.PutCard[writer, nchars, bitsPerStringBound]; TargetConversions.PutCard[writer, nchars+extras, bitsPerStringBound]; FOR i: CARDINAL IN [0..nchars) DO TargetConversions.PutChar[writer, string[i]]; ENDLOOP; THROUGH [0..extras) DO TargetConversions.PutChar[writer, 0C]; ENDLOOP; <> RETURN [TargetConversions.WriterContents[writer]]; }; StringInit: PUBLIC PROC [node: Tree.Index] RETURNS [Node] = { <> cl: CodeList ¬ substState.cl; nchars: INT = ConstArith.ToInt[MimP5U.TreeLiteralValue[tb[node].son[2]]]; bits: INT ¬ bitsPerChar*nchars + bitsPerStringBound*2; bodyVar: Var ¬ IF mainBody THEN MakeGlobal[bits].v ELSE MimP5U.MakeTemp[cl, bits].var; field: Var ¬ MimP5U.TakeFieldVar[bodyVar, 0, bitsPerStringBound*2]; list: NodeList ¬ MimP5U.MakeNodeList2[ MimP5U.MakeConstCard[0, bitsPerStringBound], -- length MimP5U.MakeConstCard[nchars, bitsPerStringBound] -- max length ]; init: Node ¬ MimP5U.MakeComposite[list, bitsPerStringBound*2]; MimP5U.MoreCode[cl, MimP5U.Assign[lhs: field, rhs: init]]; RETURN [MimP5U.ApplyOp[ MimP5U.MesaOpNode[addr], MimP5U.MakeNodeList[bodyVar], bitsPerPtr]]; }; Subst: PUBLIC PROC [node: Tree.Index, resultType: Type] RETURNS [result: Node ¬ NIL] = { oldInInline: BOOL = inInline; oldSubstState: SubstState = substState­; declCL: CodeList ¬ MimP5U.NewCodeList[]; cl: CodeList ¬ MimP5U.NewCodeList[]; bits: INT = MimP5U.BitsForType[resultType]; resultVar: Var = IF resultType = nullType THEN NIL ELSE MimP5U.MakeTemp[declCL, bits].var; argType: RecordSEIndex = SymbolOps.TransferTypes[SymbolOps.own, MimP5U.OperandType[tb[node].son[1]]].typeIn; stmtList: Tree.Link = tb[node].son[2]; inInline ¬ TRUE; substState­ ¬ [resultType: resultType, resultVar: resultVar, cl: cl]; { stmtNode: Node ¬ MimP5.StatementTree[stmtList]; IF substState.lastResultGoTo # NIL THEN IF NOT IntCodeStuff.NodeContains[stmtNode, substState.lastResultGoTo] THEN substState.exitLabel ¬ NIL; WITH stmtNode SELECT FROM block: BlockNode => MimP5U.AppendNodeList[cl, block.nodes]; <> ENDCASE => MimP5U.MoreCode[cl, stmtNode]; IF substState.exitLabel # NIL THEN <> MimP5U.InsertLabel[cl, substState.exitLabel]; IF substState.lock # Tree.Null THEN <> LocalReleaseLock[cl, substState.lock]; IF substState.postfixCL # NIL THEN <> cl ¬ ApplyPrefixAndPostfix[MimP5U.ExtractList[cl]]; IF resultType # nullType THEN { <> list: NodeList ¬ MimP5U.ExtractList[cl]; IF list # NIL AND list.rest = NIL THEN <> WITH StripSource[list.first] SELECT FROM assign: REF NodeRep.assign => <> IF assign.lhs = resultVar THEN { <> result ¬ assign.rhs; GO TO simple; }; ENDCASE; MimP5U.AppendNodeList[declCL, list]; cl ¬ declCL; MimP5U.MoreCode[cl, resultVar]; }; result ¬ MimP5U.MakeBlock[cl, bits]; EXITS simple => {}; }; inInline ¬ oldInInline; substState­ ¬ oldSubstState; RETURN [result]; }; PushContext: PUBLIC PROC [label: Label, cl: CodeList, inner: PROC] = { saveCaseCV: Node = caseCV; saveCaseType: Symbols.Type = caseType; oldInInline: BOOL = inInline; oldProcCodeList: CodeList = localProcCodeList; oldSubstState: SubstState = substState­; enclosingContext: Label ¬ visibleContext[curctxlvl]; curctxlvl ¬ curctxlvl + 1; catchcount ¬ catchcount + 1; visibleContext[curctxlvl] ¬ label; substState­ ¬ [resultType: nullType, resultVar: NIL, cl: cl]; localProcCodeList ¬ cl; inner[]; catchcount ¬ catchcount - 1; curctxlvl ¬ curctxlvl - 1; inInline ¬ oldInInline; substState­ ¬ oldSubstState; localProcCodeList ¬ oldProcCodeList; caseCV ¬ saveCaseCV; caseType ¬ saveCaseType; }; <> ApplyPrefixAndPostfix: PROC [list: NodeList] RETURNS [CodeList] = { <> prefixCL: CodeList = substState.prefixCL; postfixCL: CodeList = substState.postfixCL; afterLabel: Label = MimP5U.AllocLabel[]; MimP5U.AppendNodeList[prefixCL, list]; <> MimP5U.Jump[prefixCL, afterLabel]; <> MimP5U.AppendNodeList[prefixCL, MimP5U.ExtractList[postfixCL]]; <> MimP5U.InsertLabel[prefixCL, afterLabel]; <> substState.prefixCL ¬ NIL; substState.postfixCL ¬ NIL; RETURN [prefixCL]; }; BlockTail: PROC [node: Node] RETURNS [NodeList] = { nodes: NodeList ¬ NIL; WITH node SELECT FROM block: BlockNode => nodes ¬ block.nodes; source: SourceNode => nodes ¬ source.nodes; ENDCASE => RETURN [NIL]; WHILE nodes # NIL DO next: NodeList ¬ nodes.rest; IF next = NIL THEN WITH nodes.first SELECT FROM block: BlockNode => next ¬ block.nodes; source: SourceNode => next ¬ source.nodes; ENDCASE => RETURN [nodes]; nodes ¬ next; ENDLOOP; RETURN [NIL]; }; CodePassError: ERROR [n: CARDINAL] = CODE; CollectConstants: PROC [cl: CodeList] = { EachBody: PROC [bti: Symbols.BTIndex] RETURNS [stop: BOOL ¬ FALSE] = { <> const: BOOL ¬ TRUE; inAssign: BOOL ¬ FALSE; Mapper: Tree.Map = { <<[t: Tree.Link] RETURNS [v: Tree.Link]>> v ¬ t; WITH e: t SELECT TreeOps.GetTag[t] FROM subtree => IF t # Tree.Null THEN { node: Tree.Index = e.index; name: Tree.NodeName = tb[e.index].name; oldConst: BOOL ¬ const; needsMap: BOOL ¬ FALSE; const ¬ TRUE; SELECT name FROM mwconst, construct, rowcons, all, union, cast, pad, lengthen, shorten => { <> const ¬ MimP5S.WillEvalToConst[t, TRUE]; IF const THEN { bits: INT ¬ MimP5U.BitsForOperand[t]; IF inAssign AND noCollectConstAssigns THEN GO TO noCollect; IF bits < minMemoBits OR bits > maxMemoBits THEN GO TO noCollect; <> FOR each: ConstList ¬ constListHead, each.rest WHILE each # NIL DO IF each.bits # bits THEN LOOP; IF each.name # name THEN LOOP; IF TreeSame[t, each.tree] THEN { <> v ¬ each.var; each.uses¬ each.uses + 1; const ¬ oldConst; GO TO done; }; ENDLOOP; { <> node: Node ¬ MimP5.Exp[t]; lcl: CodeList = MimP5U.NewCodeList[]; type: Type ¬ MimP5U.TypeForTree[t]; temp: Var; sei: ISEIndex; [temp, sei] ¬ MakeGlobal[bits, MimP5U.TypeForTree[t]]; v ¬ [symbol[sei]]; constListHead ¬ z.NEW[ConstEntry ¬ [ rest: constListHead, var: v, bits: bits, uses: 1, name: name, tree: t ]]; node ¬ MimP5S.ComAssign[v, t, [ init: TRUE, counted: SymbolOps.RCType[SymbolOps.own, type] # none, skipZeros: TRUE]]; MimP5U.MoreCode[lcl, node]; MimP5U.MoreCode[cl, MimP5U.MakeBlock[lcl]]; seb[sei].immutable ¬ TRUE; seb[sei].idDecl ¬ 2; <> }; const ¬ oldConst; GO TO done; }; }; ENDCASE; SELECT name FROM assign, assignx => { <> inAssign ¬ FALSE; tb[node].son[1] ¬ Mapper[tb[node].son[1]]; inAssign ¬ TRUE; tb[node].son[2] ¬ Mapper[tb[node].son[2]]; inAssign ¬ FALSE; }; decl => { <> init: Tree.Link = tb[node].son[3]; IF init # Tree.Null THEN { inAssign ¬ TRUE; tb[node].son[3] ¬ Mapper[tb[node].son[3]]; inAssign ¬ FALSE; }; }; new => { <> inAssign ¬ FALSE; tb[node].son[1] ¬ Mapper[tb[node].son[1]]; tb[node].son[2] ¬ Mapper[tb[node].son[2]]; inAssign ¬ TRUE; tb[node].son[3] ¬ Mapper[tb[node].son[3]]; inAssign ¬ FALSE; }; construct, rowcons => { <> tb[node].son[2] ¬ Mapper[tb[node].son[2]]; }; all, union, cast, pad, list, lengthen, shorten => { <> [] ¬ TreeOps.UpdateLeaves[e, Mapper]; }; ENDCASE => { <> inAssign ¬ FALSE; [] ¬ TreeOps.UpdateLeaves[e, Mapper]; }; GO TO noCollect; EXITS done => {}; noCollect => const ¬ FALSE; }; symbol => { const ¬ FALSE; FOR each: ConstList ¬ constListHead, each.rest WHILE each # NIL DO IF v = t THEN {const ¬ TRUE; EXIT}; ENDLOOP; }; ENDCASE; }; WITH body: bb[bti] SELECT FROM Callable => IF ~body.inline AND body.hints.pad = 0 THEN WITH bi: bb[bti].info SELECT FROM Internal => { bodyNode: Tree.Index ¬ bi.bodyTree; [] ¬ TreeOps.UpdateLeaves[[subtree[bodyNode]], Mapper]; }; ENDCASE; ENDCASE; }; TreeSame: PROC [t1, t2: Tree.Link] RETURNS [BOOL] = { IF t1 = t2 THEN RETURN [TRUE]; WITH e1: t1 SELECT TreeOps.GetTag[t1] FROM subtree => { tp1: Tree.NodePtr = @tb[e1.index]; WITH e2: t2 SELECT TreeOps.GetTag[t2] FROM subtree => { tp2: Tree.NodePtr = @tb[e2.index]; SELECT TRUE FROM tp1.name # tp2.name => {}; tp1.nSons # tp2.nSons => {}; tp1.info # tp2.info => {}; tp1.subInfo # tp2.subInfo => {}; tp1.attr1 # tp2.attr1 => {}; tp1.attr2 # tp2.attr2 => {}; tp1.attr3 # tp2.attr3 => {}; ENDCASE => { FOR i: NAT IN [1..tp1.nSons] DO IF NOT TreeSame[tp1.son[i], tp2.son[i]] THEN RETURN [FALSE]; ENDLOOP; RETURN [TRUE]; }; }; ENDCASE; }; ENDCASE; RETURN [FALSE]; }; ConstList: TYPE = REF ConstEntry; ConstEntry: TYPE = RECORD [ rest: ConstList, var: Tree.Link, bits: INT, uses: INT, name: Tree.NodeName, tree: Tree.Link]; constListHead: ConstList ¬ NIL; [] ¬ SymbolOps.EnumerateBodies[SymbolOps.own, Symbols.RootBti, EachBody]; WHILE constListHead # NIL DO next: ConstList ¬ constListHead.rest; z.FREE[@constListHead]; constListHead ¬ next; ENDLOOP; }; CommonRet: PROC [t: Tree.Link] RETURNS [common: BOOL ¬ TRUE] = { <> sei: ISEIndex; Item: PROC [t: Tree.Link] RETURNS [BOOL] = { WITH t SELECT TreeOps.GetTag[t] FROM symbol => common ¬ (sei = index); literal, subtree => common ¬ FALSE; ENDCASE; IF sei # ISENull THEN sei ¬ MimP5U.NextVar[SymbolOps.NextSe[SymbolOps.own, sei]]; RETURN [~common] }; IF t = Tree.Null THEN RETURN; IF bodyOutRecord # CSENull THEN sei ¬ MimP5U.NextVar[ctxb[seb[bodyOutRecord].fieldCtx].seList] ELSE RETURN [FALSE]; TreeOps.SearchList[t, Item]; }; FindProcDesc: PROC [bti: CBTIndex] RETURNS [new: REF ProcDescEntry ¬ NIL] = { <> SELECT bb[bti].kind FROM Outer => { < descriptor is in global frame)>> new ¬ procDescRoot; }; Inner => { <> pBti: Symbols.BTIndex ¬ bti; DO pBti ¬ SymbolOps.ParentBti[SymbolOps.own, pBti]; WITH body: bb[pBti] SELECT FROM Callable => IF NOT body.inline AND body.hints.pad = 0 THEN { new ¬ MakeProcDesc[pBti].child; EXIT; }; ENDCASE; ENDLOOP; }; ENDCASE => ERROR; <> WHILE new # NIL DO IF new.bti = bti THEN RETURN; new ¬ new.rest; ENDLOOP; }; GetFormals: PROC [irecord: RecordSEIndex] RETURNS [VarList] = { IF irecord = CSENull THEN RETURN [NIL]; RETURN [VarsForCtx[seb[irecord].fieldCtx]]; }; IsVarInCtx: PROC [sei: ISEIndex, ctx: CTXIndex] RETURNS [BOOL] = { IF ctx # CTXNull THEN { each: ISEIndex ¬ MimP5U.NextVar[ctxb[ctx].seList]; WHILE each # ISENull DO IF sei = each THEN RETURN [TRUE]; each ¬ MimP5U.NextVar[SymbolOps.NextSe[SymbolOps.own, each]]; ENDLOOP; }; RETURN [FALSE]; }; ListNeedsTemp: PROC [nodeList: NodeList] RETURNS [BOOL] = { FOR each: NodeList ¬ nodeList, each.rest WHILE each # NIL DO IF NeedsTemp[each.first] THEN RETURN [TRUE]; ENDLOOP; RETURN [FALSE]; }; LocalReleaseLock: PROC [cl: CodeList, lock: Tree.Link] = { node: Node = MimP5.Exp[lock]; rel: Node = MimP5U.ApplyOp[ oper: MimP5U.MesaOpNode[monitorExit], args: MimP5U.MakeArgList[MimP5U.Address[node]], bits: 0]; MimP5U.MoreCode[cl, rel]; }; MakeListNice: PROC [cl: CodeList, nodeList: NodeList] = { FOR each: NodeList ¬ nodeList, each.rest WHILE each # NIL DO n: Node = each.first; IF NeedsTemp[n] THEN each.first ¬ MimP5S.Temporize[cl, n]; ENDLOOP; }; MakeProcDesc: PROC [bti: BTIndex] RETURNS [new: REF ProcDescEntry ¬ NIL] = { <> parent: REF ProcDescEntry ¬ NIL; IF bti = Symbols.BTNull THEN ERROR; WITH body: bb[bti] SELECT FROM Callable => { IF body.inline THEN ERROR; SELECT body.kind FROM Outer => < descriptor is in global frame)>> new ¬ procDescRoot; Inner => { < descriptor is in local frame)>> pBti: Symbols.BTIndex ¬ bti; DO pBti ¬ SymbolOps.ParentBti[SymbolOps.own, pBti]; WITH bb[pBti] SELECT FROM Callable => { parent ¬ MakeProcDesc[pBti]; new ¬ parent.child; EXIT; }; ENDCASE; ENDLOOP; }; ENDCASE => ERROR; <> }; ENDCASE => ERROR; <> WHILE new # NIL DO IF new.bti = bti THEN RETURN; new ¬ new.rest; ENDLOOP; IF new = NIL THEN { <> label: Label = MimP5U.AllocLabel[id: LOOPHOLE[bti]]; directEntry: Node ¬ MimP5U.LabelAddress[label, TRUE]; indirectEntry: Node ¬ MimP5U.LabelAddress[label, FALSE]; new ¬ z.NEW[ProcDescEntry ¬ [ bti: LOOPHOLE[bti], parent: parent, directEntry: directEntry, indirectEntry: indirectEntry, label: label]]; WITH b: bb[bti] SELECT FROM Callable => { out: STREAM ¬ IO.ROS[]; PrintSei[out, b.id]; new.name ¬ IO.RopeFromROS[out]; IF LOOPHOLE[bti, CARD] > LOOPHOLE[maxBti, CARD] THEN { <> maxBti ¬ LOOPHOLE[bti]; }; }; ENDCASE; IF parent = NIL THEN { < descriptor is in global frame)>> new.rest ¬ procDescRoot; procDescRoot ¬ new; } ELSE { <> new.rest ¬ parent.child; parent.child ¬ new; }; }; }; Module: PROC RETURNS [Node] = { <
> bodies: CodeList ¬ MimP5U.NewCodeList[]; Body1: PROC [bti: Symbols.BTIndex] RETURNS [stop: BOOL ¬ FALSE] = { <> WITH body: bb[bti] SELECT FROM Callable => IF ~body.inline AND body.hints.pad = 0 THEN [] ¬ MakeProcDesc[bti]; ENDCASE; }; Body2: PROC [bti: Symbols.BTIndex] RETURNS [stop: BOOL ¬ FALSE] = { <> WITH body: bb[bti] SELECT FROM Callable => IF ~body.inline AND body.hints.pad = 0 THEN MimP5U.MoreCode[bodies, ProcBody[LOOPHOLE[bti]]]; ENDCASE; }; (MimData.table).AddNotify[DriverNotify]; maxBti ¬ Symbols.RootBti; procDescRoot ¬ NIL; linkToVarSeq ¬ NIL; inInline ¬ FALSE; visibleContext ¬ z.NEW[MimP5.VisibalContextArray ¬ ALL[NIL]]; substState ¬ z.NEW[SubstState ¬ []]; { modNode ¬ z.NEW[module NodeRep ¬ [details: module[vars: VarsForCtx[MimData.mainCtx], procs: NIL]]]; <> maxGlobalVarId ¬ 0; FOR each: VarList ¬ modNode.vars, each.rest WHILE each # NIL DO id: INT ¬ each.first.id; IF id > maxGlobalVarId THEN maxGlobalVarId ¬ id; ENDLOOP; modVarsTail ¬ modNode.vars; IF modVarsTail # NIL THEN WHILE modVarsTail.rest # NIL DO modVarsTail ¬ modVarsTail.rest; ENDLOOP; bodyInRecord ¬ bodyOutRecord ¬ RecordSENull; MimP5U.CgenUtilInit[MimData.table]; inlineFileLoc ¬ SourceMap.nullLoc; xtracting ¬ FALSE; caseCV ¬ NIL; catchoutrecord ¬ RecordSENull; [] ¬ SymbolOps.EnumerateBodies[SymbolOps.own, Symbols.RootBti, Body1]; IF MimData.nSigCodes # 0 THEN signalsVar ¬ MakeGlobal[MimData.nSigCodes*bitsPerWord].v; [] ¬ SymbolOps.EnumerateBodies[SymbolOps.own, Symbols.RootBti, Body2]; modNode.procs ¬ bodies.head; }; z.FREE[@visibleContext]; z.FREE[@substState]; RETURN [modNode] }; NeedsTemp: PROC [node: Node] RETURNS [BOOL] = { <> n: Node ¬ node; WHILE n # NIL DO list: NodeList ¬ NIL; WITH n SELECT FROM v: REF NodeRep.var => { IF v.flags[constant] THEN EXIT; WITH v.location SELECT FROM local: REF LocationRep.localVar => RETURN [FALSE]; dummy: REF LocationRep.dummy => RETURN [FALSE]; field: REF LocationRep.field => {n ¬ field.base; LOOP}; indexed: REF LocationRep.indexed => IF NeedsTemp[indexed.base] THEN RETURN [TRUE] ELSE {n ¬ indexed.index; LOOP}; comp: REF LocationRep.composite => list ¬ comp.parts; ENDCASE; RETURN [TRUE]; }; c: REF NodeRep.const => EXIT; block: REF NodeRep.block => list ¬ block.nodes; decl: REF NodeRep.decl => {n ¬ decl.init; LOOP}; assign: REF NodeRep.assign => IF NeedsTemp[assign.lhs] THEN RETURN [TRUE] ELSE {n ¬ assign.rhs; LOOP}; cond: REF NodeRep.cond => { FOR each: CaseList ¬ cond.cases, each.rest WHILE each # NIL DO IF ListNeedsTemp[each.tests] THEN RETURN [TRUE]; IF NeedsTemp[each.body] THEN RETURN [TRUE]; ENDLOOP; RETURN [FALSE]; }; label: REF NodeRep.label => {n ¬ label.label.node; LOOP}; apply: REF NodeRep.apply => { WITH apply.proc SELECT FROM oper: REF NodeRep.oper => SELECT oper.oper.kind FROM arith, boolean, convert, check, compare, mesa, cedar => { <> IF apply.handler # NIL THEN RETURN [TRUE]; list ¬ apply.args; }; ENDCASE => RETURN [TRUE]; ENDCASE => RETURN [TRUE]; }; source: REF NodeRep.source => list ¬ source.nodes; ENDCASE => RETURN [TRUE]; WHILE list # NIL DO IF NeedsTemp[list.first] THEN RETURN [TRUE]; list ¬ list.rest; IF list = NIL THEN RETURN [FALSE]; ENDLOOP; EXIT; ENDLOOP; RETURN [FALSE]; }; NodesForCtx: PROC [ctx: CTXIndex] RETURNS [vl: NodeList ¬ NIL] = { IF ctx # CTXNull THEN { tail: NodeList ¬ NIL; sei: ISEIndex ¬ MimP5U.NextVar[ctxb[ctx].seList]; UNTIL sei = ISENull DO var: Var ¬ MimP5.VarForSei[sei]; this: NodeList ¬ MimP5U.MakeNodeList[var]; IF tail = NIL THEN vl ¬ this ELSE tail.rest ¬ this; tail ¬ this; sei ¬ MimP5U.NextVar[SymbolOps.NextSe[SymbolOps.own, sei]]; ENDLOOP; }; }; PrintSei: PROC [st: STREAM, sei: Symbols.ISEIndex] = TRUSTED { name: Symbols.Name = SymbolOps.NameForSe[SymbolOps.own, sei]; s: ConvertUnsafe.SubString ¬ SymbolOps.SubStringForName[SymbolOps.own, name]; FOR i: CARDINAL IN [s.offset..s.offset+s.length) DO IO.PutChar[st, s.base[i]]; ENDLOOP; }; RopeForSei: PROC [sei: Symbols.ISEIndex] RETURNS [ROPE] = TRUSTED { name: Symbols.Name = SymbolOps.NameForSe[SymbolOps.own, sei]; s: ConvertUnsafe.SubString ¬ SymbolOps.SubStringForName[SymbolOps.own, name]; i: CARDINAL ¬ s.offset; eachChar: SAFE PROC RETURNS [c: CHAR] = TRUSTED { c ¬ s.base[i]; i ¬ i + 1; }; RETURN [Rope.FromProc[len: s.length, p: eachChar]]; }; ProcBody: PROC [bti: Symbols.CBTIndex] RETURNS [Node] = { <> oldSubstState: SubstState ¬ substState­; oldLocalProcList: CodeList ¬ localProcCodeList; cl: CodeList ¬ MimP5U.NewCodeList[]; desc: REF ProcDescEntry ¬ FindProcDesc[bti]; procLabel: Label ¬ desc.label; lambda: LambdaNode ¬ NIL; enclosingContext: Label ¬ NIL; substState­ ¬ [cl: cl, prefixCL: NIL, postfixCL: NIL]; localProcCodeList ¬ cl; mainBody ¬ (bti = Symbols.RootBti); MimData.bodyIndex ¬ bti; MimData.textIndex ¬ SourceMap.Up[bb[bti].sourceIndex]; WITH bi: bb[bti].info SELECT FROM Internal => { bodyNode: Tree.Index ¬ bi.bodyTree; kind: IntCodeDefs.LambdaKind ¬ outer; curctxlvl ¬ bb[bti].level; FOR pd: REF ProcDescEntry ¬ desc, pd.parent WHILE pd # NIL DO <> pBti: CBTIndex = pd.bti; level: Symbols.ContextLevel ¬ bb[pBti].level; visibleContext[level] ¬ pd.label; ENDLOOP; IF curctxlvl >= Symbols.lL THEN { enclosingContext ¬ visibleContext[curctxlvl.PRED]; IF curctxlvl > Symbols.lL THEN kind ¬ inner; }; IF mainBody THEN kind ¬ init; <> [bodyInRecord, bodyOutRecord] ¬ SymbolOps.TransferTypes[SymbolOps.own, bb[bti].ioType]; fileLoc ¬ SourceMap.Up[bb[bti].sourceIndex]; tailJumpOK ¬ TRUE; SymbolOps.SetCtxLevel[tempcontext, curctxlvl]; lambda ¬ z.NEW[NodeRep.lambda ¬ [details: lambda[ parent: enclosingContext, kind: kind, descBody: NIL, bitsOut: MimP5U.BitsForType[bodyOutRecord], formalArgs: GetFormals[bodyInRecord], body: NIL]]]; <> <> substState.resultType ¬ bodyOutRecord; IF bodyOutRecord # RecordSENull THEN { <> ctx: Symbols.CTXIndex = seb[bodyOutRecord].fieldCtx; sei: ISEIndex ¬ MimP5U.NextVar[ctxb[ctx].seList]; IF MimP5U.BitsForType[bodyOutRecord] > bitsPerWord THEN { substState.exitLabel ¬ MimP5U.AllocLabel[]; }; UNTIL sei = ISENull DO MimP5U.Declare[cl: cl, var: MimP5.VarForSei[sei]]; sei ¬ MimP5U.NextVar[SymbolOps.NextSe[SymbolOps.own, sei]]; ENDLOOP; }; <> IF bti = Symbols.RootBti THEN { <> FOR each: REF ProcDescEntry ¬ procDescRoot, each.rest WHILE each # NIL DO <> bodyVar: Var ¬ MakeGlobal[bitsPerProcDesc].v; WITH bodyVar.location SELECT FROM glob: REF LocationRep.globalVar => bb[each.bti].frameOffset ¬ glob.id / Target.bitsPerAU; ENDCASE => ERROR; each.body ¬ bodyVar; bodyVar.flags[constant] ¬ TRUE; ENDLOOP; <> IF collectConstants THEN CollectConstants[cl]; }; FOR each: REF ProcDescEntry ¬ desc.child, each.rest WHILE each # NIL DO <> init: Node ¬ MimP5U.MakeComposite[ MimP5U.MakeNodeList2[each.indirectEntry, MimP5U.MakeConstCard[1]], bitsPerProcDesc]; each.body ¬ MimP5S.Temporize[cl, init]; ENDLOOP; <> mLock ¬ Tree.Null; IF bb[bti].entry THEN { IF substState.exitLabel # NIL THEN substState.exitLabel ¬ MimP5U.AllocLabel[]; mLock ¬ tb[bodyNode].son[4]; SetLock[cl, mLock]; }; <> MimP5.DeclList[cl, tb[bodyNode].son[2]]; MimP5.StatementList[cl, tb[bodyNode].son[3]]; IF substState.exitLabel # NIL THEN { <> MimP5U.InsertLabel[cl, substState.exitLabel]; IF mLock # Tree.Null THEN LocalReleaseLock[cl, mLock]; IF bodyOutRecord # RecordSENull THEN { ctx: Symbols.CTXIndex = seb[bodyOutRecord].fieldCtx; sei: ISEIndex ¬ MimP5U.NextVar[ctxb[ctx].seList]; head: NodeList ¬ NIL; tail: NodeList ¬ NIL; UNTIL sei = ISENull DO new: NodeList ¬ MimP5U.MakeArgList[MimP5.VarForSei[sei]]; IF tail = NIL THEN head ¬ new ELSE tail.rest ¬ new; tail ¬ new; sei ¬ MimP5U.NextVar[SymbolOps.NextSe[SymbolOps.own, sei]]; ENDLOOP; MimP5U.MoreCode[cl, MimP5U.MakeReturn[head]]; }; }; }; ENDCASE; lambda.body ¬ MimP5U.MakeNodeList[MimP5.WrapSourceBlock[cl, bti, FALSE]]; <> IF substState.postfixCL # NIL THEN <> lambda.body ¬ MimP5U.ExtractList[ApplyPrefixAndPostfix[lambda.body]]; <> lambda.body ¬ MimP5U.MakeNodeList[ z.NEW[NodeRep.comment ¬ [details: comment[Rope.Concat[desc.name, ":"]]]], lambda.body]; IF desc.parent # NIL THEN lambda.descBody ¬ desc.body; procLabel.node ¬ lambda; substState­ ¬ oldSubstState; localProcCodeList ¬ oldLocalProcList; RETURN [z.NEW[NodeRep.label ¬ [details: label[procLabel]]]]; }; SetLock: PROC [cl: CodeList, lock: Tree.Link] = { node: Node ¬ MimP5.Exp[lock]; set: Node = MimP5U.ApplyOp[ oper: MimP5U.MesaOpNode[monitorEntry], args: MimP5U.MakeArgList[MimP5U.Address[node]], bits: 0]; MimP5U.MoreCode[cl, set]; }; StripExtraDecl: PROC [node: Node] RETURNS [Node] = { <> <<{decl V; V _ E; V}>> <> WITH StripSource[node] SELECT FROM block: REF NodeRep.block => { list: NodeList ¬ block.nodes; IF list # NIL THEN WITH StripSource[list.first] SELECT FROM decl: REF NodeRep.decl => IF decl.init = NIL THEN { r1: NodeList ¬ list.rest; IF r1 # NIL THEN { var: Var ¬ decl.var; IF var # NIL AND NOT var.flags[named] THEN { <> n2: Node ¬ StripSource[r1.first]; WITH StripSource[r1.first] SELECT FROM assign: REF NodeRep.assign => IF assign.lhs = var THEN { <> r2: NodeList ¬ r1.rest; IF r2 # NIL AND r2.rest = NIL THEN WITH StripSource[r2.first] SELECT FROM rvar: Var => IF rvar = var THEN <> RETURN [assign.rhs]; ENDCASE; }; ENDCASE; }; }; }; ENDCASE; }; ENDCASE; RETURN [node]; }; StripSource: PROC [node: Node] RETURNS [Node] = { DO WITH node SELECT FROM source: SourceNode => { nodes: NodeList ¬ source.nodes; IF nodes # NIL AND nodes.rest = NIL THEN {node ¬ nodes.first; LOOP}; }; ENDCASE; RETURN [node]; ENDLOOP; }; ClearProcDesc: PROC [pd: REF ProcDescEntry] = { WHILE pd # NIL DO next: REF ProcDescEntry ¬ pd.rest; ClearProcDesc[pd.child]; pd­ ¬ []; pd ¬ next; ENDLOOP; }; ClearNodes: IntCodeUtils.Visitor = CHECKED { <<[node: IntCodeDefs.Node] RETURNS [IntCodeDefs.Node]>> IF node # NIL THEN IntCodeUtils.MapNode[node, ClearNodes]; RETURN [NIL]; }; VarsForCtx: PROC [ctx: CTXIndex] RETURNS [vl: VarList ¬ NIL] = { IF ctx # CTXNull THEN { tail: VarList ¬ NIL; sei: ISEIndex ¬ MimP5U.NextVar[ctxb[ctx].seList]; UNTIL sei = ISENull DO var: Var ¬ MimP5.VarForSei[sei]; this: VarList ¬ MimP5U.MakeVarList[var]; IF tail = NIL THEN vl ¬ this ELSE tail.rest ¬ this; tail ¬ this; sei ¬ MimP5U.NextVar[SymbolOps.NextSe[SymbolOps.own, sei]]; ENDLOOP; }; }; <> RewriteSymbols: PROC [baseModel: IntCodeTwig.BaseModel] = { <> <<>> <> modNode: ModuleNode = NARROW[baseModel.module]; FOR each: VarList ¬ modNode.vars, each.rest WHILE each # NIL DO var: Var ¬ each.first; IF var # NIL THEN WITH var.location SELECT FROM glob: REF LocationRep.globalVar => { id: INT ¬ var.id; IF id > 0 AND id <= maxGlobalVarId THEN { <> sei: Symbols.SEIndex ¬ Symbols.SENull + id; WITH se: seb[sei] SELECT FROM id => IF se.idCtx = MimData.mainCtx THEN <> se.idValue ¬ SymbolOps.EncodeBitAddr[[glob.id]]; ENDCASE; CopyVarFlags[var]; }; }; ENDCASE; ENDLOOP; <> FOR lambda: IntCodeTwig.LambdaModel ¬ baseModel.first, lambda.next WHILE lambda # NIL DO label: Label = lambda.label; IF label # NIL AND LOOPHOLE[label.id, CARD] <= LOOPHOLE[maxBti, CARD] THEN { bti: CBTIndex = LOOPHOLE[label.id]; MakeSpecialVar: PROC [var: Var, kind: Symbols.SpecialVarKind] = { IF var # NIL THEN WITH var.location SELECT FROM local: REF LocationRep.localVar => { bits: INT ¬ var.bits; sei: ISEIndex ¬ SymbolOps.MakeCtxSe[Symbols.HTNull, Symbols.CTXNull]; ctx: CTXIndex = bb[bti].localCtx; WITH se: seb[sei] SELECT FROM linked => se.link ¬ ctxb[ctx].seList; ENDCASE => ERROR; seb[sei].idInfo ¬ SymbolOps.EncodeInt[bits]; seb[sei].idType ¬ typeANY; seb[sei].special ¬ kind; var.id ¬ LOOPHOLE[sei - Symbols.ISENull]; <> ctxb[ctx].seList ¬ sei; <> }; ENDCASE; }; MakeSpecialVar[lambda.frameExtension, frameExtension]; MakeSpecialVar[lambda.globalLink, globalLink]; MakeSpecialVar[lambda.staticLink, staticLink]; MakeSpecialVar[lambda.memoryLink, memoryLink]; MakeSpecialVar[lambda.returnVar, returnLink]; }; [] ¬ CopyFlags[lambda.lambda]; ENDLOOP; }; CopyFlags: IntCodeUtils.Visitor = TRUSTED { WITH node SELECT FROM decl: REF NodeRep.decl => CopyVarFlags[decl.var]; lambda: REF NodeRep.lambda => FOR each: VarList ¬ lambda.formalArgs, each.rest WHILE each # NIL DO CopyVarFlags[each.first]; ENDLOOP; ENDCASE; IntCodeUtils.MapNode[node, CopyFlags]; RETURN [node]; }; CopyVarFlags: PROC [var: Var] = { IF var # NIL THEN { <> flags: IntCodeDefs.VariableFlags = var.flags; IF flags[named] THEN { sei: ISEIndex = Symbols.ISENull + CARD[var.id]; new: Symbols.VariableFlags ¬ seb[sei].flags; IF flags[upLevel] THEN { <> offset: INT ¬ 0; new.upLevel ¬ new.valid ¬ TRUE; WITH var.location SELECT FROM field: REF LocationRep.field => offset ¬ field.start; ENDCASE; seb[sei].idValue ¬ SymbolOps.EncodeBitAddr[[offset]]; }; IF flags[addressed] THEN new.addressed ¬ new.valid ¬ TRUE; IF flags[assigned] THEN new.assigned ¬ new.valid ¬ TRUE; IF flags[used] THEN new.used ¬ new.valid ¬ TRUE; IF flags[constant] THEN seb[sei].immutable ¬ TRUE; seb[sei].flags ¬ new; }; }; }; }.