DIRECTORY Alloc USING [Base, Notifier], IntCodeDefs USING [ApplyNode, ArithClass, ArithSelector, BlockNode, CaseList, CaseListRep, Comparator, Handler, HandlerRep, Label, LambdaNode, Node, NodeList, NodeRep, nullFileId, SourceNode, Var, VarList], MimCode USING [BitAddress, BitCount, caseCV, caseType, catchoutrecord, CodeList, CodeNotImplemented, curctxlvl, fileLoc, inlineFileLoc, LabelInfo, nC1, RegisterNotifier, StoreOptions, z], MimData USING [checks, idCARDINAL, idINTEGER, idUNWIND, switches, textIndex, worstAlignment], MimosaLog USING [Error, WarningSei], MimP5 USING [BindStmtExp, CaseStmtExp, Clarify, Exp, ExpList, GetLabelMark, inInline, LabelCreate, LabelList, MakeExitLabel, Normalize, PushContext, SysError, VarForSei, visibleContext], MimP5S USING [Assign, Call, CatchMark, ComAssign, Continue, ExtendValue, Exit, Extract, Free, GoTo, Join, LabelStmt, Lock, Loop, Restart, Result, Resume, Retry, Return, RetWithError, SigErr, SplitArith, Start, Stop, Subst, Unlock, WillEvalToConst], MimP5Stuff USING [GetCard, IsCard], MimP5U USING [Address, AllocLabel, ApplyOp, ArithClassForTree, ArithClassForType, Assign, BinaryArithOp, BitsForType, BoolTest, BoundsCheck, CJump, Declare, Deref, Extend, ExtractList, FnField, FormalVar, InsertLabel, Jump, MakeArgList, MakeArgList2, MakeBlock, MakeCaseList, MakeConstCard, MakeConstInt, MakeGoTo, MakeNodeList, MakeTemp, MakeVarList, MesaOpNode, MoreCode, NewCodeList, NextVar, NodeIf, OperandType, TakeField, TakeFieldVar, WordsForSei], SourceMap USING [Loc, nullLoc, Up, Val], SourceMarks USING [GetProps], SymbolOps USING [CtxLevel, NextSe, own, SetCtxLevel, TransferTypes], Symbols USING [Base, bodyType, BTIndex, BTNull, ContextLevel, CSEIndex, CSENull, CTXIndex, CTXNull, ctxType, ISEIndex, ISENull, RecordSEIndex, RecordSENull, SEIndex, seType, Type], Target: TYPE MachineParms USING [bitsPerProc, bitsPerRef, bitsPerWord], Tree USING [Base, Index, Link, Node, NodeName, Null, Scan, treeType], TreeOps USING [GetNode, GetSe, GetTag, NthSon, OpName, ScanList]; MimStmt: PROGRAM IMPORTS MimCode, MimData, MimosaLog, MimP5, MimP5S, MimP5Stuff, MimP5U, SourceMap, SourceMarks, SymbolOps, TreeOps EXPORTS MimP5 = { OPEN IntCodeDefs, MimCode, Target; bitsPerPtr: NAT = Target.bitsPerRef; bitsPerSignal: NAT = Target.bitsPerProc; SourceSeen: SIGNAL [index: SourceMap.Loc] = CODE; sourceBreak: SourceMap.Loc ฌ SourceMap.nullLoc; SuspiciousLength: SIGNAL = CODE; SEIndex: TYPE = Symbols.SEIndex; ISEIndex: TYPE = Symbols.ISEIndex; ISENull: ISEIndex = Symbols.ISENull; CSEIndex: TYPE = Symbols.CSEIndex; CSENull: CSEIndex = Symbols.CSENull; RecordSEIndex: TYPE = Symbols.RecordSEIndex; RecordSENull: RecordSEIndex = Symbols.RecordSENull; BTIndex: TYPE = Symbols.BTIndex; BTNull: BTIndex = Symbols.BTNull; DeclList: PUBLIC PROC [cl: CodeList, t: Tree.Link] = { PreId: Tree.Scan = { sei: ISEIndex = TreeOps.GetSe[t]; IF NOT seb[sei].constant THEN seb[sei].idDecl ฌ 1; }; PreDecl: Tree.Scan = { SELECT TreeOps.OpName[t] FROM decl => TreeOps.ScanList[TreeOps.NthSon[t, 1], PreId]; list => TreeOps.ScanList[t, PreDecl]; ENDCASE; }; OneDecl: Tree.Scan = { IF t # Tree.Null THEN SELECT TreeOps.OpName[t] FROM decl => DeclItem[cl, TreeOps.GetNode[t]]; typedecl => NULL; procinit, signalinit => {}; list => TreeOps.ScanList[t, OneDecl]; ENDCASE => MimP5U.MoreCode[cl, StatementTree[t]]; }; TreeOps.ScanList[t, PreDecl]; TreeOps.ScanList[t, OneDecl]; }; StatementList: PUBLIC PROC [cl: CodeList, t: Tree.Link] = { OneStmt: Tree.Scan = { new: Node; WITH e: t SELECT TreeOps.GetTag[t] FROM subtree => IF tb[e.index].name = decl THEN {DeclItem[cl, e.index]; RETURN}; ENDCASE; new ฌ StatementTree[t]; IF new # NIL THEN MimP5U.MoreCode[cl, new]; }; TreeOps.ScanList[t, OneStmt]; }; StatementTree: PUBLIC PROC [t: Tree.Link] RETURNS [l: Node ฌ NIL] = { saveIndex: SourceMap.Loc = MimData.textIndex; recentStmt ฌ t; IF t # Tree.Null THEN { ENABLE MimCode.CodeNotImplemented => IF ~MimData.switches['d] THEN GO TO unimplemented; WITH t SELECT TreeOps.GetTag[t] FROM subtree => { fIndex: SourceMap.Loc ฌ MimCode.inlineFileLoc; node: Tree.Index ฌ index; tp: LONG POINTER TO Tree.Node = @tb[node]; IF tp.free THEN ERROR; IF fIndex = SourceMap.nullLoc THEN fIndex ฌ LOOPHOLE[tp.info, SourceMap.Loc]; IF fIndex # SourceMap.nullLoc THEN SELECT tp.name FROM list, block, null => fIndex ฌ SourceMap.nullLoc; ENDCASE => { MimCode.fileLoc ฌ MimData.textIndex ฌ fIndex; }; IF fIndex = sourceBreak AND fIndex # SourceMap.nullLoc THEN SIGNAL SourceSeen[fIndex]; SELECT tp.name FROM list => { cl: CodeList ฌ MimP5U.NewCodeList[]; StatementList[cl, t]; l ฌ MimP5U.MakeBlock[cl]; }; block => { cl: CodeList ฌ MimP5U.NewCodeList[]; bti: BTIndex = LOOPHOLE[tb[node].info, BTIndex]; hasDecls: BOOL ฌ FALSE; DeclList[cl, tb[node].son[1]]; IF cl.head # NIL THEN hasDecls ฌ TRUE; StatementList[cl, tb[node].son[2]]; IF bti # BTNull THEN l ฌ WrapSourceBlock[cl, bti, hasDecls] ELSE l ฌ MimP5U.MakeBlock[cl]; }; start => l ฌ MimP5S.Start[node]; restart => l ฌ MimP5S.Restart[node]; stop => l ฌ MimP5S.Stop[node]; dst, lst, lste, lstf => GO TO unimplemented; portcall => GO TO unimplemented; syscall => GO TO unimplemented; call => l ฌ MimP5S.Call[node]; signal => l ฌ MimP5S.SigErr[node: node, error: FALSE, stmt: TRUE]; error => l ฌ MimP5S.SigErr[node: node, error: TRUE, stmt: TRUE]; syserror => l ฌ MimP5.SysError[]; label => l ฌ MimP5S.LabelStmt[node]; assign => l ฌ MimP5S.Assign[node]; extract => l ฌ MimP5S.Extract[node]; if => { son2: Tree.Link = tp.son[2]; son3: Tree.Link = tp.son[3]; test: Node = MimP5.Exp[tp.son[1]]; SELECT MimP5U.BoolTest[test] FROM true => l ฌ StatementTree[son2]; false => l ฌ StatementTree[son3]; ENDCASE => l ฌ MimP5U.NodeIf[test, StatementTree[son2], StatementTree[son3]]; }; case => lฌ MimP5.CaseStmtExp[node, FALSE]; bind => l ฌ MimP5.BindStmtExp[node, FALSE]; do => l ฌ DoStmt[node]; exit => l ฌ MimP5S.Exit[]; loop => l ฌ MimP5S.Loop[]; retry => l ฌ MimP5S.Retry[]; continue => l ฌ MimP5S.Continue[]; goto => l ฌ MimP5S.GoTo[node]; catchmark => l ฌ MimP5S.CatchMark[node]; return => l ฌ MimP5S.Return[node]; resume => l ฌ MimP5S.Resume[node]; reject => l ฌ MimP5U.MakeGoTo[catchEndLabel]; result => l ฌ MimP5S.Result[node]; open => l ฌ StatementTree[tp.son[2]]; enable => { handler: Handler ฌ SCatchPhrase[tb[node].son[1]]; cl: CodeList ฌ MimP5U.NewCodeList[]; range: NodeList; StatementList[cl, tb[node].son[2]]; range ฌ MimP5U.ExtractList[cl]; l ฌ z.NEW[NodeRep.enable ฌ [details: enable[handle: handler, scope: range]]]; }; checked => l ฌ StatementTree[tp.son[1]]; wait => { monitor: Node ฌ MimP5U.Address[MimP5.Exp[tb[node].son[1]]]; condition: Node ฌ MimP5U.Address[MimP5.Exp[tb[node].son[2]]]; apply: ApplyNode ฌ NARROW[MimP5U.ApplyOp[ oper: MimP5U.MesaOpNode[wait], args: MimP5U.MakeArgList2[monitor, condition]]]; IF tb[node].nSons > 2 THEN apply.handler ฌ SCatchPhrase[tb[node].son[3]]; l ฌ apply; }; notify => { condition: Node ฌ MimP5U.Address[MimP5.Exp[tb[node].son[1]]]; args: NodeList ฌ MimP5U.MakeArgList[condition]; l ฌ MimP5U.ApplyOp[oper: MimP5U.MesaOpNode[notify], args: args, bits: 0]; }; broadcast => { condition: Node ฌ MimP5U.Address[MimP5.Exp[tb[node].son[1]]]; args: NodeList ฌ MimP5U.MakeArgList[condition]; l ฌ MimP5U.ApplyOp[oper: MimP5U.MesaOpNode[broadcast], args: args, bits: 0]; }; join => l ฌ MimP5S.Join[node]; unlock => l ฌ MimP5S.Unlock[node]; lock => l ฌ MimP5S.Lock[node]; subst => l ฌ MimP5S.Subst[node]; free => l ฌ MimP5S.Free[node]; xerror => l ฌ MimP5S.RetWithError[node]; null => {}; ENDCASE => GO TO unimplemented; IF fIndex # SourceMap.nullLoc THEN l ฌ WrapSource[l, fIndex]; }; ENDCASE; EXITS unimplemented => MimosaLog.Error[unimplemented]; }; MimData.textIndex ฌ saveIndex; }; DeclItem: PROC [cl: CodeList, node: Tree.Index] = { initVal: Node ฌ NIL; initTree: Tree.Link ฌ tb[node].son[3]; first: BOOL ฌ TRUE; OneId: Tree.Scan = { sei: ISEIndex ฌ TreeOps.GetSe[t]; IF NOT seb[sei].constant THEN { type: Symbols.Type = seb[sei].idType; var: Var = MimP5.VarForSei[sei]; varBits: INT = var.bits; IF initTree = Tree.Null THEN { nt: CSEIndex = MimP5.Normalize[type]; typeBits: INT = MimP5U.BitsForType[nt]; offset: INT = typeBits MOD bitsPerWord; IF typeBits < varBits AND offset # 0 THEN { WITH se: seb[nt] SELECT FROM record, array => { options: MimCode.StoreOptions = [init: TRUE]; lastWord: Var = MimP5U.TakeFieldVar[var, typeBits-offset, bitsPerWord]; zero: Node = MimP5U.MakeConstCard[0]; MimP5U.Declare[cl, var]; seb[sei].idDecl ฌ 0; MimP5U.MoreCode[cl, MimP5U.Assign[lhs: lastWord, rhs: zero]]; IF MimData.checks['p] THEN MimosaLog.WarningSei[paddedField, sei]; first ฌ FALSE; RETURN; }; ENDCASE; }; }; IF first THEN { first ฌ FALSE; IF initTree # Tree.Null THEN { initType: Symbols.Type = MimP5U.OperandType[initTree]; padded: BOOL ฌ FALSE; t: Tree.Link ฌ initTree; DO SELECT TreeOps.OpName[t] FROM pad => {t ฌ TreeOps.NthSon[t, 1]; padded ฌ TRUE}; cast => t ฌ TreeOps.NthSon[t, 1]; ENDCASE => EXIT; ENDLOOP; IF padded AND varBits > bitsPerWord THEN { options: MimCode.StoreOptions = [init: TRUE]; MimP5U.Declare[cl, var]; seb[sei].idDecl ฌ 0; MimP5U.MoreCode[cl, MimP5S.ComAssign[t1: [symbol[sei]], t2: initTree, options: options]]; initVal ฌ var; RETURN; }; initVal ฌ MimP5.Exp[t]; IF initVal # NIL AND initVal.bits < varBits THEN initVal ฌ MimP5S.ExtendValue[ node: initVal, dstType: type, srcType: initType, bits: var.bits]; }; }; seb[sei].idDecl ฌ 0; MimP5U.Declare[cl: cl, var: var, init: initVal]; IF initVal # NIL AND initVal.kind # const THEN initVal ฌ var; }; }; fIndex: SourceMap.Loc ฌ MimCode.inlineFileLoc; oldCL: CodeList ฌ cl; IF fIndex = SourceMap.nullLoc THEN fIndex ฌ LOOPHOLE[tb[node].info, SourceMap.Loc]; IF fIndex # SourceMap.nullLoc AND NOT MimP5.inInline THEN { pos: INT = SourceMap.Val[fIndex]; IF pos >= 0 THEN { IF fIndex = sourceBreak THEN SIGNAL SourceSeen[fIndex]; MimCode.fileLoc ฌ MimData.textIndex ฌ fIndex; cl ฌ MimP5U.NewCodeList[]; TreeOps.ScanList[tb[node].son[1], OneId]; MimP5U.MoreCode[oldCL, WrapList[MimP5U.ExtractList[cl], fIndex]]; RETURN; }; }; TreeOps.ScanList[tb[node].son[1], OneId]; }; DoStmt: PROC [rootNode: Tree.Index] RETURNS [l: Node] = { preBodyTest: Tree.Link = tb[rootNode].son[2]; exitsCode: Tree.Link = tb[rootNode].son[5]; finishingCode: Tree.Link = tb[rootNode].son[6]; finLabel: Label = MimP5U.AllocLabel[]; endLabel: Label ฌ NIL; loopLabel: Label ฌ NIL; labelMark: LabelInfo = MimP5.GetLabelMark[]; cl: CodeList = MimP5U.NewCodeList[]; body: Node ฌ NIL; TestAndBody: PROC = { IF preBodyTest # Tree.Null THEN { case: CaseList ฌ MimP5U.MakeCaseList[ MimP5U.MakeNodeList[MimP5.Exp[preBodyTest]], NIL, MimP5U.MakeCaseList[NIL, MimP5U.MakeGoTo[finLabel]]]; cond: Node ฌ z.NEW[NodeRep.cond ฌ [details: cond[case]]]; MimP5U.MoreCode[cl, cond]; }; body ฌ StatementTree[tb[rootNode].son[4]]; MimP5U.MoreCode[cl, body]; }; [exit: endLabel, loop: loopLabel] ฌ MimP5.MakeExitLabel[]; TreeOps.ScanList[exitsCode, MimP5.LabelCreate]; IF tb[rootNode].son[1] = Tree.Null THEN { MimP5U.InsertLabel[cl, loopLabel]; TestAndBody[]; MimP5U.Jump[cl, loopLabel]; } ELSE { topLabel: Label = MimP5U.AllocLabel[]; node: Tree.Index = TreeOps.GetNode[tb[rootNode].son[1]]; son1: Tree.Link = tb[node].son[1]; son2: Tree.Link = tb[node].son[2]; bti: BTIndex = LOOPHOLE[tb[node].info, BTIndex]; options: MimCode.StoreOptions = []; name: Tree.NodeName = tb[node].name; IF bti # BTNull THEN EnterBlock[cl, bti]; SELECT name FROM forseq => { forSeqUpdateCode: Tree.Link = tb[node].son[3]; indexType: Symbols.Type = MimP5U.OperandType[son1]; ac: ArithClass = MimP5U.ArithClassForType[indexType]; indexVar: Var = MimP5.VarForSei[TreeOps.GetSe[son1]]; indexVar.flags[frequent] ฌ ac.kind < real; IF bti # BTNull THEN MimP5U.Declare[cl, indexVar, NIL]; IF son2 # Tree.Null THEN MimP5U.MoreCode[cl, MimP5S.ComAssign[son1, son2, options]]; MimP5U.InsertLabel[cl, topLabel]; TestAndBody[]; IF loopLabel.used THEN MimP5U.InsertLabel[cl, loopLabel]; IF forSeqUpdateCode # Tree.Null THEN MimP5U.MoreCode[cl, MimP5S.ComAssign[son1, forSeqUpdateCode, options]]; MimP5U.Jump[cl, topLabel, TRUE]; }; upthru, downthru => { upLoop: BOOL ฌ tb[node].name = upthru; cvBound: Node ฌ NIL; knownNonEmpty: BOOL = tb[node].attr1; subNode: Tree.Index = TreeOps.GetNode[son2]; indexTree: Tree.Link ฌ son1; indexVar: Var ฌ NIL; intervalKind: Tree.NodeName ฌ tb[subNode].name; loSon: Tree.Link ฌ tb[subNode].son[1]; loVal: Node ฌ MimP5.Exp[loSon]; hiSon: Tree.Link ฌ tb[subNode].son[2]; hiVal: Node ฌ MimP5.Exp[hiSon]; ac: ArithClass ฌ MimP5U.ArithClassForTree[subNode]; gac: ArithClass ฌ ac; bias: Node ฌ NIL; indexType: Symbols.Type ฌ IF ac.kind = signed THEN MimData.idINTEGER ELSE MimData.idCARDINAL; groundType: Symbols.Type ฌ indexType; IncrOp: PROC [val: Node, incr: Node, op: ArithSelector] RETURNS [Node] = { thisClass: ArithClass ฌ ac; bits: INT = MAX[thisClass.precision, val.bits, incr.bits]; thisClass.precision ฌ bits; IF val.bits < bits THEN val ฌ MimP5U.Extend[val, bits, groundType]; IF incr.bits < bits THEN incr ฌ MimP5U.Extend[incr, bits, groundType]; IF bits = bitsPerWord THEN { valCard: CARD; incrCard: CARD; const: Node ฌ NIL; [val, valCard] ฌ MimP5S.SplitArith[val]; [incr, incrCard] ฌ MimP5S.SplitArith[incr]; IF incrCard # 0 THEN SELECT op FROM add => valCard ฌ valCard + incrCard; sub => valCard ฌ valCard - incrCard; ENDCASE => ERROR; const ฌ MimP5U.MakeConstCard[valCard]; SELECT TRUE FROM val = NIL => { IF incr = NIL THEN RETURN [const]; IF valCard = 0 THEN RETURN [incr]; val ฌ const; }; incr = NIL => { IF valCard = 0 THEN RETURN [val]; op ฌ add; incr ฌ const; IF valCard > CARD[LAST[INT]] THEN { incr ฌ MimP5U.MakeConstInt[-LOOPHOLE[valCard, INT]]; op ฌ sub; }; }; valCard = 0 => {}; ENDCASE => val ฌ MimP5U.BinaryArithOp[add, thisClass, val, const] }; RETURN [MimP5U.BinaryArithOp[op, thisClass, val, incr]]; }; AssignIncr: PROC [val: Node, incr: Node, op: ArithSelector] = { var: Var = NARROW[val]; MimP5U.MoreCode[cl, MimP5U.Assign[var, IncrOp[val, MimCode.nC1, op]]]; }; Bump: PROC [val: Node, incr: Node, op: ArithSelector] RETURNS [Node] = { new: Node = IncrOp[val, MimCode.nC1, op]; WITH val SELECT FROM var: Var => MimP5U.MoreCode[cl, MimP5U.Assign[var, new]]; ENDCASE => val ฌ new; RETURN [val]; }; FrequentTemp: PROC [val: Node, son: Tree.Link, forceTemp: BOOL] RETURNS [Node] = { IF indexVar # NIL AND indexVar.bits > val.bits THEN { ac.precision ฌ indexVar.bits; val ฌ MimP5S.ExtendValue[ node: val, dstType: indexType, srcType: MimP5U.OperandType[son], bits: indexVar.bits]; }; IF forceTemp AND bias = NIL AND indexVar # NIL AND bti # BTNull THEN { MimP5U.Declare[cl, indexVar, val]; val ฌ indexVar; indexVar ฌ NIL; RETURN [val]; }; IF forceTemp OR NOT MimP5S.WillEvalToConst[son] THEN { sei: ISEIndex; tv: Var; [tv, sei] ฌ MimP5U.MakeTemp[cl, val.bits, val, indexType]; tv.flags[frequent] ฌ TRUE; val ฌ tv; }; RETURN [val]; }; IF tb[node].nSons > 2 THEN { son3: Tree.Link = tb[node].son[3]; IF son3 # Tree.Null THEN cvBound ฌ MimP5.Exp[son3]; }; WITH s1: indexTree SELECT TreeOps.GetTag[indexTree] FROM symbol => { indexType ฌ MimP5U.OperandType[indexTree]; groundType ฌ MimP5.Normalize[indexType]; indexVar ฌ MimP5.VarForSei[s1.index]; indexVar.flags[frequent] ฌ TRUE; { ut: CSEIndex = MimP5.Clarify[indexType]; WITH se: seb[ut] SELECT FROM subrange => IF se.biased THEN IF se.origin # 0 THEN bias ฌ MimP5U.MakeConstInt[-se.origin]; ENDCASE; }; }; ENDCASE; gac ฌ MimP5U.ArithClassForType[groundType]; IF gac.precision < bitsPerWord THEN gac.precision ฌ bitsPerWord; IF MimP5Stuff.IsCard[loVal] THEN SELECT intervalKind FROM intOC, intOO => { lb: CARD = MimP5Stuff.GetCard[loVal]; IF lb # CARD[INT.LAST] AND lb # CARD.LAST THEN { loVal ฌ IncrOp[loVal, MimCode.nC1, add]; intervalKind ฌ IF intervalKind = intOC THEN intCC ELSE intCO; }; }; ENDCASE; IF MimP5Stuff.IsCard[hiVal] THEN SELECT intervalKind FROM intCO, intOO => { lb: CARD = MimP5Stuff.GetCard[hiVal]; IF lb # 0 AND lb # CARD[INT.LAST]+1 THEN { hiVal ฌ IncrOp[hiVal, MimCode.nC1, sub]; intervalKind ฌ IF intervalKind = intCO THEN intCC ELSE intOC; }; }; ENDCASE; loVal ฌ FrequentTemp[loVal, loSon, name = upthru]; hiVal ฌ FrequentTemp[hiVal, hiSon, name = downthru]; IF NOT knownNonEmpty THEN { tst: Comparator ฌ IF intervalKind = intCC THEN gt ELSE ge; MimP5U.CJump[cl: cl, test: tst, ac: gac, op1: loVal, op2: hiVal, target: finLabel]; }; SELECT intervalKind FROM intOC => IF name = upthru THEN { loVal ฌ Bump[loVal, MimCode.nC1, add]; intervalKind ฌ intCC; }; intCO => IF name # upthru THEN { hiVal ฌ Bump[hiVal, MimCode.nC1, sub]; intervalKind ฌ intCC; }; intOO => { IF name = upthru THEN {loVal ฌ Bump[loVal, MimCode.nC1, add]; intervalKind ฌ intCO} ELSE {hiVal ฌ Bump[hiVal, MimCode.nC1, sub]; intervalKind ฌ intOC}; IF NOT knownNonEmpty THEN MimP5U.CJump[cl: cl, test: eq, op1: loVal, op2: hiVal, ac: gac, target: finLabel, backwards: FALSE]; }; ENDCASE; MimP5U.InsertLabel[cl, topLabel]; { localControl: Var = NARROW[IF name = upthru THEN loVal ELSE hiVal]; limit: Node = IF name = upthru THEN hiVal ELSE loVal; op: ArithSelector = IF name = upthru THEN add ELSE sub; closedLimit: BOOL ฌ FALSE; SELECT intervalKind FROM intCC => closedLimit ฌ TRUE; intCO => IF name # upthru THEN closedLimit ฌ TRUE; intOC => IF name = upthru THEN closedLimit ฌ TRUE; ENDCASE => ERROR; IF indexVar # NIL THEN { newVal: Node ฌ localControl; newType: Symbols.Type ฌ MimP5U.OperandType[IF name = upthru THEN loSon ELSE hiSon]; IF newVal.bits < indexVar.bits THEN newVal ฌ MimP5U.Extend[newVal, indexVar.bits, newType]; IF cvBound # NIL THEN newVal ฌ MimP5U.BoundsCheck[newVal, cvBound]; IF bias # NIL THEN newVal ฌ IncrOp[newVal, bias, add]; IF bti # BTNull THEN MimP5U.Declare[cl, indexVar, newVal] ELSE MimP5U.MoreCode[cl, MimP5U.Assign[indexVar, newVal]]; }; TestAndBody[]; IF loopLabel.used THEN MimP5U.InsertLabel[cl, loopLabel]; IF bti = BTNull AND indexVar # NIL THEN { temp: Node ฌ IF bias = NIL THEN indexVar ELSE IncrOp[indexVar, bias, sub]; IF temp.bits < localControl.bits THEN temp ฌ MimP5U.Extend[temp, indexVar.bits, groundType]; MimP5U.MoreCode[cl, MimP5U.Assign[localControl, temp]]; }; IF closedLimit THEN MimP5U.CJump[cl: cl, test: ge, op1: loVal, op2: hiVal, ac: ac, target: finLabel, backwards: FALSE]; AssignIncr[localControl, MimCode.nC1, op]; IF closedLimit THEN MimP5U.Jump[cl, topLabel, TRUE] ELSE MimP5U.CJump[cl: cl, test: lt, op1: loVal, op2: hiVal, ac: ac, target: topLabel, backwards: TRUE]; IF exitsCode # Tree.Null OR finishingCode # Tree.Null THEN MimP5U.Jump[cl, finLabel, FALSE]; }; }; ENDCASE; }; MimP5.LabelList[cl, exitsCode, endLabel, labelMark]; IF finLabel.used THEN { MimP5U.InsertLabel[cl, finLabel]; IF finishingCode # Tree.Null THEN MimP5U.MoreCode[cl, StatementTree[finishingCode]]; }; IF endLabel.used THEN MimP5U.InsertLabel[cl, endLabel]; RETURN [MimP5U.MakeBlock[cl]]; }; SCatchPhrase: PUBLIC PROC [t: Tree.Link] RETURNS [Handler] = { handler: Handler ฌ NIL; IF t # Tree.Null THEN { insider: PROC = { CatchArm: PROC [t: Tree.Link] = { node: Tree.Index ฌ TreeOps.GetNode[t]; -- t is an item tests: NodeList ฌ MimP5.ExpList[tb[node].son[1], FALSE].head; body: Node ฌ CatchItem[node: node, argPtr: argPtr]; arm: CaseList ฌ z.NEW[CaseListRep ฌ [tests: tests, body: body, rest: NIL]]; IF armTail = NIL THEN armHead ฌ arm ELSE armTail.rest ฌ arm; armTail ฌ arm; }; node: Tree.Index = TreeOps.GetNode[t]; armHead, armTail: CaseList ฌ NIL; regsPtr: Var ฌ MimP5U.FormalVar[bitsPerPtr]; except: Var ฌ MimP5U.FormalVar[bitsPerSignal]; rtnPtr: Var ฌ MimP5U.FormalVar[bitsPerPtr]; argPtr: Var ฌ MimP5U.FormalVar[bitsPerPtr]; formals: VarList ฌ MimP5U.MakeVarList[regsPtr, MimP5U.MakeVarList[except, MimP5U.MakeVarList[rtnPtr, MimP5U.MakeVarList[argPtr]]]]; lambda: LambdaNode ฌ z.NEW[NodeRep.lambda ฌ [details: lambda[ parent: enclosingContext, kind: catch, bitsOut: 0, formalArgs: formals, body: NIL]]]; -- will fill in body field soon catchEndLabel ฌ MimP5U.AllocLabel[]; MimCode.caseCV ฌ except; MimCode.caseType ฌ seb[MimData.idUNWIND].idType; TreeOps.ScanList[tb[node].son[1], CatchArm]; IF tb[node].son[2] # Tree.Null THEN { ec: Node ฌ StatementTree[tb[node].son[2]]; other: CaseList ฌ z.NEW[CaseListRep ฌ [tests: NIL, body: ec, rest: NIL]]; IF armHead = NIL THEN armHead ฌ other ELSE armTail.rest ฌ other; }; MimP5U.MoreCode[cl, z.NEW[NodeRep.cond ฌ [details: cond[armHead]]]]; MimP5U.InsertLabel[cl, catchEndLabel]; MimP5U.MoreCode[cl, MimP5U.ApplyOp[MimP5U.MesaOpNode[reject], NIL]]; lambda.body ฌ MimP5U.ExtractList[cl]; catchLabel.node ฌ lambda; handler ฌ z.NEW[HandlerRep ฌ [ context: NIL, proc: z.NEW[NodeRep.label ฌ [details: label[catchLabel]]]]]; }; cl: CodeList ฌ MimP5U.NewCodeList[]; enclosingContext: Label ฌ MimP5.visibleContext[MimCode.curctxlvl]; catchLabel: Label ฌ MimP5U.AllocLabel[]; oldCatchEnd: Label ฌ catchEndLabel; MimP5.PushContext[catchLabel, cl, insider]; catchEndLabel ฌ oldCatchEnd; }; RETURN [handler]; }; CatchItem: PROC [node: Tree.Index, argPtr: Node] RETURNS [Node] = { inCtx, outCtx: Symbols.CTXIndex ฌ Symbols.CTXNull; saveCatchOutRecord: RecordSEIndex = MimCode.catchoutrecord; saveInCtxLevel, saveOutCtxLevel: Symbols.ContextLevel; body: Node ฌ NIL; bodyStmts: NodeList ฌ NIL; cl: CodeList ฌ MimP5U.NewCodeList[]; tSei: CSEIndex = MimP5.Clarify[LOOPHOLE[tb[node].info, SEIndex]]; IF tSei = Symbols.CSENull THEN MimCode.catchoutrecord ฌ RecordSENull ELSE { inRecord, outRecord: RecordSEIndex; [inRecord, outRecord] ฌ SymbolOps.TransferTypes[SymbolOps.own, tSei]; MimCode.catchoutrecord ฌ outRecord; IF inRecord # RecordSENull THEN { inCtx ฌ seb[inRecord].fieldCtx; saveInCtxLevel ฌ SymbolOps.CtxLevel[SymbolOps.own, inCtx]; SymbolOps.SetCtxLevel[inCtx, MimCode.curctxlvl]; GetSignalParams[cl, argPtr, inRecord]; }; IF outRecord # RecordSENull THEN { ctx: Symbols.CTXIndex ฌ outCtx ฌ seb[outRecord].fieldCtx; sei: ISEIndex ฌ MimP5U.NextVar[ctxb[ctx].seList]; saveOutCtxLevel ฌ SymbolOps.CtxLevel[SymbolOps.own, ctx]; SymbolOps.SetCtxLevel[outCtx, MimCode.curctxlvl]; UNTIL sei = ISENull DO MimP5U.Declare[cl, MimP5.VarForSei[sei]]; sei ฌ MimP5U.NextVar[SymbolOps.NextSe[SymbolOps.own, sei]]; ENDLOOP; }; }; body ฌ StatementTree[tb[node].son[2]]; WITH body SELECT FROM block: BlockNode => bodyStmts ฌ block.nodes; ENDCASE => bodyStmts ฌ MimP5U.MakeNodeList[body]; IF cl.tail = NIL THEN cl.head ฌ bodyStmts ELSE cl.tail.rest ฌ bodyStmts; MimCode.catchoutrecord ฌ saveCatchOutRecord; IF inCtx # Symbols.CTXNull THEN SymbolOps.SetCtxLevel[inCtx, saveInCtxLevel]; IF outCtx # Symbols.CTXNull THEN SymbolOps.SetCtxLevel[outCtx, saveOutCtxLevel]; RETURN [MimP5U.MakeBlock[cl]]; }; GetSignalParams: PROC [cl: CodeList, argPtr: Node, irecord: RecordSEIndex] = { IF irecord # CSENull THEN { nParms: INT ฌ MimP5U.WordsForSei[irecord]; IF nParms # 0 THEN { totalBits: BitCount ฌ MimP5U.BitsForType[irecord]; args: Node ฌ MimP5U.Deref[n: argPtr, bits: totalBits, align: MimData.worstAlignment]; sei: ISEIndex ฌ MimP5U.NextVar[ctxb[seb[irecord].fieldCtx].seList]; UNTIL sei = ISENull DO offset: BitAddress; size: BitCount; var: Var = MimP5.VarForSei[sei]; init: Node ฌ NIL; [offset, size] ฌ MimP5U.FnField[sei]; init ฌ MimP5U.TakeField[args, offset, size]; MimP5U.Declare[cl: cl, var: var, init: init]; sei ฌ MimP5U.NextVar[SymbolOps.NextSe[SymbolOps.own, sei]]; ENDLOOP; }; }; }; EnterBlock: PROC [cl: CodeList, bti: BTIndex] = { fIndex: SourceMap.Loc ฌ MimCode.inlineFileLoc; IF fIndex = SourceMap.nullLoc THEN fIndex ฌ SourceMap.Up[bb[bti].sourceIndex]; IF fIndex # SourceMap.nullLoc THEN MimP5U.MoreCode[cl, WrapSource[NIL, fIndex]]; }; ReplaceNode: PROC [sn: SourceNode] = { start: INT ฌ sn.source.start; IF sn.nodes # NIL THEN { end: INT ฌ SourceMarks.GetProps[start].endPos; IF end > start THEN sn.source.chars ฌ end-start; }; }; WrapSource: PUBLIC PROC [node: Node, loc: SourceMap.Loc] RETURNS [Node] = { IF MimP5.inInline AND NOT MimData.switches['h] THEN RETURN [node]; IF loc # SourceMap.nullLoc THEN { pos: INT = SourceMap.Val[loc]; IF pos >= 0 THEN { bits: INT ฌ IF node = NIL THEN 0 ELSE node.bits; node ฌ WrapList[IF node = NIL THEN NIL ELSE MimP5U.MakeNodeList[node], loc]; node.bits ฌ bits; }; }; RETURN [node]; }; WrapList: PROC [list: NodeList, loc: SourceMap.Loc] RETURNS [SourceNode] = { pos: INT ฌ SourceMap.Val[loc]; sn: SourceNode ฌ z.NEW[NodeRep.source ฌ [ bits: 0, details: source[ source: [start: pos, chars: 0, file: nullFileId], nodes: list]]]; ReplaceNode[sn]; RETURN [sn]; }; WrapSourceBlock: PUBLIC PROC [cl: CodeList, bti: BTIndex, hasDecls: BOOL] RETURNS [Node] = { startPos: INT ฌ -1; fIndex: SourceMap.Loc ฌ MimCode.inlineFileLoc; sn: SourceNode ฌ NIL; IF MimP5.inInline AND NOT MimData.switches['h] THEN RETURN [MimP5U.MakeBlock[cl]]; IF fIndex = SourceMap.nullLoc THEN fIndex ฌ SourceMap.Up[bb[bti].sourceIndex]; IF fIndex # SourceMap.nullLoc THEN startPos ฌ SourceMap.Val[fIndex]; IF startPos < 0 THEN RETURN [MimP5U.MakeBlock[cl]]; sn ฌ WrapList[IF hasDecls THEN MimP5U.MakeNodeList[MimP5U.MakeBlock[cl]] ELSE MimP5U.ExtractList[cl], fIndex]; ReplaceNode[sn]; RETURN [sn]; }; tb: Tree.Base ฌ NIL; -- tree base (local copy) seb: Symbols.Base ฌ NIL; -- semantic entry base (local copy) ctxb: Symbols.Base ฌ NIL; -- context entry base (local copy) bb: Symbols.Base ฌ NIL; -- body base (local copy) StatementNotify: Alloc.Notifier = { seb ฌ base[Symbols.seType]; ctxb ฌ base[Symbols.ctxType]; bb ฌ base[Symbols.bodyType]; tb ฌ base[Tree.treeType]; }; catchEndLabel: Label ฌ NIL; recentStmt: PUBLIC Tree.Link; -- for debugging MimCode.RegisterNotifier[StatementNotify]; }. v MimStmt.mesa Copyright ำ 1985, 1986, 1987, 1988, 1989, 1990, 1991 by Xerox Corporation. All rights reserved. Sweet, June 2, 1986 1:06:04 am PDT Satterthwaite, December 30, 1985 11:51:18 am PST Russ Atkinson (RRA) March 6, 1991 4:26 pm PST imported definitions procedures maybe some statements, too generates code for Mesa statements Remember to extract all fields before calling anything that could cause relocation! info is not a valid file index For debugging down to the statement level generates code for multiple statements, no new scope generates code for multiple statements, new scope generates code for an IF statement Nest this statement in a source node This variable could use some zeros to make values kosher just in case some yurk assigns to things element by element. The use wants to know about this! There is an initialization value For error & warning tracking For debugging down to the statement level generates code for all the loop statments now the pre-body test (if any) set up for EXIT clause ignore the opens (tb[rootNode].son3) or some better test of locally declared indexVar? There is an initial value for the control variable now (update and) test the control variable We need to update the variable New style, here to handle the various kinds of intervals, as well as trying to handle increments & decrements Try to combine constants Not wide enough, so convert it This control variable is used for the low (or high) bound The low value needs a temporary RRA: See Pass4S.ForClause for details. The loop variable is already a variable Make intervalKind more closed (it's OK to do so) Make intervalKind more closed (it's OK to do so) Force loVal & hiVal into variables if necessary Initial test for the empty interval (use ground type for comparison!) Take care! This test normally should be performed BEFORE adjusting for the intervalKind, since doing it after can give erroneous results around 0 for unsigned numbers. Make sure that the starting value is correct. If both ends are open the first test was not sufficient, so there is an additional test. It is unlikely that either end was constant. Update to the index variable We got the bound from some funny place that needs to be large enough Must bounds check the assignment to the control variable The control variable is kept biased now (update and) test the lo & hi variables Increment the controlling variables and test. If we have a closed limit, then we test for completion before the variables are incremented. If we have an open limit, we increment the variables before the test. Fix for AR 1502. Sigh, we have to assign the indexVar back to either the loVal or the hiVal to ensure that any possible alteration to the indexVar in the body gets reflected back into the test. This should be done better! Must extend to fit the temporary Test before increment Loop to top after increment Test after increment now the labelled EXITs (if any) finally the FINISHED clause (if any) main subr for catchphrases and ENABLEs Formal parameters The ANY catch phrase has no test generate code for a CATCH item The output record bases & notifier called by allocator whenever table area is repacked ส“•NewlineDelimiter –(cedarcode) style™head™ Icodešœ ฯeœU™`Lšฯy"™"Lšž0™0L™-L˜šฯk ˜ LšœŸœ˜Lšœ Ÿœฝ˜ฮLšœŸœฎ˜ปLšœŸœP˜]Lšœ Ÿœ˜$LšœŸœฏ˜บLšœŸœ์˜๘Lšœ Ÿœ˜#LšœŸœป˜วLšœ Ÿœ˜(Lšœ Ÿœ ˜Lšœ Ÿœ5˜DLšœŸœง˜ดLšœŸœŸœ(˜GLšœŸœ;˜ELšœŸœ4˜A——šฯnœŸ˜LšŸœl˜sLšŸœ ˜LšŸœ˜"L˜Lšœ Ÿœ˜$LšœŸœ˜(L˜Lš  œŸœŸœ˜1L˜/L˜Lš œŸœŸœ˜ L˜—™L˜Lšœ Ÿœ˜ Lšœ Ÿœ˜"L˜$Lšœ Ÿœ˜"L˜$LšœŸœ˜,L˜3Lšœ Ÿœ˜ L˜!L˜—™ L™š œŸœŸœ!˜6L™š œ˜L˜!LšŸœŸœŸœ˜2L˜—š œ˜šŸœŸœ˜Lšœ6˜6Lšœ%˜%LšŸœ˜—L˜—š œ˜šŸœŸ˜šŸœŸœ˜L˜)Lšœ Ÿœ˜L˜L˜%LšŸœ*˜1——L˜—L˜L˜L˜L˜—š  œŸœŸœ!˜;š œ˜L˜ šŸœŸœŸ˜'Lšœ ŸœŸœŸœ˜KLšŸœ˜—L˜LšŸœŸœŸœ˜+L˜—L˜L˜—L˜š   œŸœŸœŸœ Ÿœ˜EL™"L˜-L˜šŸœŸœ˜šŸœ˜$LšŸœŸœŸœŸœ˜2—šŸœŸœŸ˜$˜ L˜.L˜šœŸœŸœŸœ˜*L™S—LšŸœ ŸœŸœ˜šŸœŸ˜"Lšœ Ÿœ˜*—šŸœŸ˜"šŸœ Ÿ˜˜L™LšœŸœ˜—šŸœ˜ L˜-L˜———šŸœŸœŸ˜;L™)LšŸœ˜—šŸœ Ÿ˜˜ L™4L˜$L˜L˜L˜—˜ L™1L˜$LšœŸœ˜0Lšœ ŸœŸœ˜L˜LšŸœ ŸœŸœ Ÿœ˜&L˜#šŸœ ˜LšŸœ'˜+LšŸœ˜—L˜—L˜ L˜$L˜LšœŸœŸœ˜,Lšœ ŸœŸœ˜ Lšœ ŸœŸœ˜L˜Lšœ/ŸœŸœ˜BLšœ.ŸœŸœ˜@L˜!L˜$L˜"L˜$˜LšœŸœ ™"L˜L˜L˜"šŸœŸ˜!L˜ L˜!šŸœ˜ L˜B——L˜—Lšœ#Ÿœ˜*Lšœ$Ÿœ˜+L˜L˜L˜L˜L˜"L˜L˜(L˜"L˜"Lšœ-˜-L˜"L˜%˜ L˜1L˜$L˜L˜#L˜LšœŸœD˜ML˜—L˜(˜ Lšœ;˜;Lšœ=˜=LšœŸœ`˜yšŸœŸ˜Lšœ.˜.—L˜ L˜—˜ Lšœ=˜=Lšœ/˜/LšœI˜IL˜—˜Lšœ=˜=Lšœ/˜/LšœL˜LL˜—L˜L˜"L˜L˜ L˜L˜(L˜ LšŸœŸœŸœ˜—šŸœŸœ˜=L™$—L˜—LšŸœ˜—šŸ˜L˜0—L˜—L˜L˜L˜—š œŸœ%˜3LšœŸœ˜L˜&LšœŸœŸœ˜š œ˜L˜!šŸœŸœŸœ˜L˜%L˜ Lšœ Ÿœ ˜šŸœŸœ˜Lšœ%˜%Lšœ Ÿœ˜'LšœŸœ Ÿœ ˜'šŸœŸœ Ÿœ˜+L™ušŸœ ŸœŸ˜˜Lšœ'Ÿœ˜-LšœG˜GLšœ%˜%Lšœ˜Lšœ˜Lšœ=˜=šŸœŸ˜L™!Lšœ'˜'—LšœŸœ˜LšŸœ˜L˜—LšŸœ˜—L˜—L˜—šŸœŸœ˜LšœŸœ˜šŸœŸœ˜L™ Lšœ6˜6LšœŸœŸœ˜Lšœ˜šŸ˜šŸœŸ˜Lšœ+Ÿœ˜1Lšœ!˜!LšŸœŸœ˜—LšŸœ˜—šŸœŸœŸœ˜*Lšœ'Ÿœ˜-Lšœ˜Lšœ˜LšœY˜YLšœ˜LšŸœ˜L˜—Lšœ˜šŸœ ŸœŸœŸ˜0Lšœ_˜_—L˜—L˜—Lšœ˜L˜0LšŸœ ŸœŸœŸœ˜=L˜—L˜—L˜.L˜šŸœŸ˜"Lšœ Ÿœ˜0—šŸœŸœŸœŸœ˜;L™LšœŸœ˜!šŸœ Ÿœ˜šŸœŸœŸœ˜7L™)—Lšœ-˜-L˜L˜)LšœA˜ALšŸœ˜L˜—L˜—L˜)L˜L˜—š œŸœŸœ˜9L™)Lšœ-˜-Lšœ+˜+Lšœ/˜/L˜&LšœŸœ˜LšœŸœ˜Lšœ,˜,L˜$Lšœ Ÿœ˜š  œŸœ˜L™šŸœŸœ˜!LšœSŸœŸœ˜LšœŸœ'˜9L˜L˜—L˜*L˜L˜—L˜L™L˜L˜:Lšœ/˜/L˜šŸœ ˜"šŸœ˜Lšœ"˜"Lšœ˜Lšœ˜L˜—šŸœ˜L™$L˜&L˜8L˜"L˜"LšœŸœ˜0Lšœ#˜#Lšœ$˜$L˜LšŸœŸœ˜)šŸœŸ˜˜ Lšœ.˜.Lšœ3˜3Lšœ5˜5Lšœ5˜5L˜Lšœ*˜*L˜šŸœŸœŸœ˜7L™1—šŸœŸ˜L™2Lšœ;˜;—L˜Lšœ!˜!Lšœ˜L˜L™*LšŸœŸœ#˜9šŸœŸ˜$L™LšœG˜G—LšœŸœ˜ L˜—˜L™mLšœŸœ˜&LšœŸœ˜LšœŸœ˜%L˜,Lšœ˜LšœŸœ˜L˜/Lšœ&˜&Lšœ˜Lšœ&˜&Lšœ˜Lšœ3˜3Lšœ˜Lšœ Ÿœ˜LšœŸœŸœŸœ˜]Lšœ%˜%š œŸœ,Ÿœ ˜JLšœ˜LšœŸœŸœ+˜:Lšœ˜LšŸœŸœ,˜CLšŸœŸœ.˜FšŸœŸœ˜L™Lšœ Ÿœ˜Lšœ Ÿœ˜LšœŸœ˜Lšœ(˜(Lšœ+˜+šŸœŸ˜šŸœŸ˜Lšœ$˜$Lšœ$˜$LšŸœŸœ˜——Lšœ&˜&šŸœŸœŸ˜šœŸœ˜LšŸœŸœŸœŸœ ˜"LšŸœ ŸœŸœ˜"Lšœ ˜ L˜—šœŸœ˜LšŸœ ŸœŸœ˜!L˜ Lšœ ˜ š Ÿœ ŸœŸœŸœŸœ˜#LšœŸœ Ÿœ˜4L˜ L˜—L˜—Lšœ˜LšŸœ:˜A—L˜—LšŸœ2˜8L˜—š  œŸœ/˜?Lšœ Ÿœ˜LšœF˜FL˜—š œŸœ,Ÿœ ˜HLšœ)˜)šŸœŸœŸ˜Lšœ9˜9LšŸœ˜—LšŸœ˜ L˜—š  œŸœ(ŸœŸœ ˜RšŸœ ŸœŸœŸœ˜5L™Lšœ˜šœ˜Lšœ ˜ Lšœ˜Lšœ!˜!Lšœ˜—L˜—šŸœ ŸœŸœŸœ ŸœŸœŸœ˜FL™9Lšœ"˜"Lšœ˜Lšœ Ÿœ˜LšŸœ˜ L˜—šŸœ ŸœŸœŸœ˜6L™L˜Lšœ˜Lšœ:˜:LšœŸœ˜Lšœ ˜ L˜—LšŸœ˜ L˜—šŸœŸœ˜LšŸœ#™&L˜"LšŸœŸœ˜3L˜—šŸœŸœŸ˜8˜ L™'Lšœ*˜*Lšœ(˜(L˜%LšœŸœ˜ ˜Lšœ(˜(šŸœ ŸœŸ˜šœ Ÿœ Ÿ˜LšŸœŸœ(˜=—LšŸœ˜—L˜—L˜—LšŸœ˜—L˜Lšœ+˜+LšŸœŸœ˜@L˜šŸœŸœŸœŸ˜9šœ˜LšœŸœ˜%šŸœŸœŸœŸœŸœŸœŸœŸœ˜0L™0Lšœ(˜(LšœŸœŸœŸœ˜=L˜—L˜—LšŸœ˜—šŸœŸœŸœŸ˜9šœ˜LšœŸœ˜%š ŸœŸœŸœŸœŸœŸœ˜*L™0Lšœ(˜(LšœŸœŸœŸœ˜=L˜—L˜—LšŸœ˜L˜—Lšœ/™/Lšœ2˜2Lšœ4˜4L˜šŸœŸœŸœ˜L™EL™จLšœŸœŸœŸœ˜:LšœS˜SL˜—L˜L™-šŸœŸ˜šœ ŸœŸœ˜ Lšœ&˜&Lšœ˜L˜—šœ ŸœŸœ˜ Lšœ&˜&Lšœ˜L˜—šœ ˜ L™†šŸœ˜LšŸœ>˜BLšŸœ?˜C—šŸœŸœŸ˜Lšœ]Ÿœ˜d—Lšœ˜—LšŸœ˜L˜—L˜!L˜˜Lš œŸœŸœŸœŸœ˜CLšœŸœŸœŸœ˜5LšœŸœŸœŸœ˜7Lšœ ŸœŸœ˜šŸœŸ˜LšœŸœ˜Lšœ ŸœŸœŸœ˜2Lšœ ŸœŸœŸœ˜2LšŸœŸœ˜—L˜šŸœ ŸœŸœ˜L™Lšœ˜Lšœ+ŸœŸœŸœ˜SšŸœŸ˜#L™DLšœ7˜7—šŸœ ŸœŸ˜L™8Lšœ-˜-—šŸœŸœŸ˜L™#Lšœ#˜#—šŸœ ˜LšŸœ%˜)LšŸœ6˜:—L˜L˜—Lšœ˜L˜L™+LšŸœŸœ#˜9L˜L™าšŸœŸœ ŸœŸœ˜)L™฿Lš œ ŸœŸœŸœ Ÿœ˜JšŸœŸ˜%L™ Lšœ6˜6—Lšœ7˜7L˜—šŸœ Ÿ˜L™Lšœ\Ÿœ˜c—Lšœ*˜*šŸœ ˜šŸœŸœ˜$L™—šŸœ]Ÿœ˜gL™——šŸœŸœŸ˜:LšœŸœ˜!—L˜—L˜—LšŸœ˜—L˜L˜——L™L˜Lšœ4˜4L˜L™$L˜šŸœŸœ˜Lšœ!˜!LšŸœŸœ3˜TL˜—L˜LšŸœŸœ"˜7LšŸœ˜L˜L˜—š  œŸœŸœŸœ˜>L™&LšœŸœ˜šŸœŸœ˜šœ Ÿœ˜š œŸœ˜!Lšœ'ฯc˜6Lšœ1Ÿœ˜=L˜3LšœŸœ0Ÿœ˜KLšŸœ ŸœŸœŸœ˜Ÿœ˜DL˜Lšœ%˜%L˜Lšœ ŸœŸœ Ÿœ1˜iL˜—L˜$L˜BLšœ(˜(Lšœ#˜#Lšœ+˜+Lšœ˜L˜—LšŸœ ˜L˜L˜—š  œŸœ"Ÿœ ˜CL™L˜2L˜;L˜6Lšœ Ÿœ˜LšœŸœ˜L˜$LšœŸœ˜AšŸœ˜LšŸœ&˜*šŸœ˜L˜#L˜EL˜#šŸœŸœ˜!L˜L˜:L˜0L˜&L˜—šŸœŸœ˜"L™L˜9L˜1L˜9L˜1šŸœŸ˜L˜)L˜;LšŸœ˜—L˜—L˜——L˜&šŸœŸœŸ˜L˜,LšŸœ*˜1—LšŸœ ŸœŸœŸœ˜HL˜,LšŸœŸœ.˜MLšŸœŸœ0˜PLšŸœ˜L˜L˜—š œŸœ9˜NšŸœŸœ˜LšœŸœ˜*šŸœ Ÿœ˜L˜2LšœU˜UL˜CšŸœŸ˜L˜L˜L˜ Lšœ Ÿœ˜L˜%L˜,L˜-L˜;LšŸœ˜—L˜—L˜—L˜L˜—š  œŸœ!˜1L˜.šŸœŸ˜"L˜+—šŸœŸ˜"LšœŸœ ˜-—L˜L˜—š  œŸœ˜&LšœŸœ˜šŸœ ŸœŸœ˜LšœŸœ&˜.LšŸœ Ÿœ˜0L˜—L˜L˜—š  œŸœŸœ"Ÿœ ˜KLš ŸœŸœŸœŸœŸœ˜BšŸœŸœ˜!LšœŸœ˜šŸœ Ÿœ˜Lš œŸœŸœŸœŸœŸœ ˜0Lš œŸœŸœŸœŸœŸœ!˜LLšœ˜Lšœ˜—L˜—LšŸœ˜L˜L˜—š œŸœ&Ÿœ˜LLšœŸœ˜šœŸœ˜)Lšœ˜˜Lšœ1˜1Lšœ˜——L˜LšŸœ˜ L˜L˜—š  œŸœŸœ(ŸœŸœ ˜\Lšœ Ÿœ˜L˜.LšœŸœ˜šŸœŸœŸœŸ˜3LšŸœ˜—šŸœŸ˜"L˜+—šŸœŸ˜"L˜!—LšŸœŸœŸœ˜3LšœŸœ Ÿœ+Ÿœ!˜nL˜LšŸœ˜ L˜L˜——™L˜LšœŸœก˜/LšœŸœก#˜=LšœŸœก"˜