DIRECTORY BasicTime, C2CAccess, C2CAddressing, C2CAddressingOps, C2CBasics, C2CDefs, C2CEmit, C2CEnables, C2CCodeUtils, C2CIntCodeUtils, C2CPreprocessing, C2CMain, C2CMode, C2CGlobalFrame, C2CNames, C2CRunTime, C2CStateUtils, C2CSourcePositions, C2CTarget, C2CTypes, Convert, IntCodeDefs, IntCodeStuff, IntCodeUtils, IO, Process, RefText, Rope, SymTab; C2CMainImpl: CEDAR PROGRAM IMPORTS BasicTime, C2CAccess, C2CAddressingOps, C2CBasics, C2CEmit, C2CCodeUtils, C2CEnables, C2CGlobalFrame, C2CIntCodeUtils, C2CNames, C2CMain, C2CMode, C2CPreprocessing, C2CRunTime, C2CSourcePositions, C2CStateUtils, C2CTarget, C2CTypes, Convert, IntCodeUtils, IntCodeStuff, IO, Process, RefText, Rope, SymTab EXPORTS C2CMain = BEGIN OPEN IntCodeDefs, C2CBasics, C2CDefs, C2CMain, C2CMode; ROPE: TYPE = Rope.ROPE; declMode: Mode ~ SetExpr[NIL, TRUE]; skipMode: Mode ~ DSetBaseSize[SetAModeNC[Like[rhs: TRUE, stat: TRUE], skip], 0]; stringPieceMaxLength: INT = C2CTarget.RoundUpCharsToWords[200]; myKeyForFirstProc: REF INT ¬ NEW[INT]; --unique myKeyForModuleEncountered: REF INT ¬ NEW[INT]; --unique myKeyForFormalReturn: REF INT ¬ NEW[INT]; --unique myKeyForReturnBits: REF INT ¬ NEW[INT]; --unique Cat2: PROC [c1, c2: Code] RETURNS [c: Code] = { IF c2=NIL THEN RETURN [c1]; IF c1=NIL THEN RETURN [c2]; RETURN [C2CEmit.Cat[c1, c2]] }; GenNodeList: PROC [nodeList: IntCodeDefs.NodeList, mode: Mode, outsideTemporaryDecl: BOOL ¬ FALSE, mayOmmitLastEnablePop: BOOL ¬ FALSE] RETURNS [cc: CodeCont] = { count: INT ¬ 0; rqMode: Mode ¬ mode; useMode: Mode; skipMode: Mode ¬ SetAMode[mode, skip]; saveDeclC: Code ¬ NIL; lastNode, needComma, makesRealCode, adressable, makeTemporaryDecl: BOOL ¬ FALSE; FOR nodes: IntCodeDefs.NodeList ¬ nodeList, nodes.rest WHILE nodes#NIL DO wasDead: BOOL ¬ FALSE; cc1: CodeCont; useMode ¬ skipMode; lastNode ¬ FALSE; IF cc.sc#NIL THEN wasDead ¬ C2CEmit.GetIsDead[cc.sc]; IF wasDead AND ~C2CIntCodeUtils.HasLabel[nodes.first] THEN { cc.sc ¬ C2CEmit.CatRemark[cc.sc, "c2c skipped dead code"]; cc.sc ¬ C2CEmit.Cat[cc.sc, C2CEmit.line]; count ¬ 0; C2CEmit.SetDead[cc.sc]; LOOP }; makesRealCode ¬ C2CIntCodeUtils.NodeHasCode[nodes.first]; IF makesRealCode THEN IF ~C2CIntCodeUtils.AnyNodeHasCode[nodes.rest] THEN { useMode ¬ rqMode; lastNode ¬ TRUE; }; makeTemporaryDecl ¬ GetAMode[useMode]=skip; IF makeTemporaryDecl AND outsideTemporaryDecl AND nodeList.rest=NIL THEN makeTemporaryDecl ¬ FALSE; IF makesRealCode AND makeTemporaryDecl THEN { saveDeclC ¬ C2CEmit.CollectCode[temporaryDeclarations]; }; IF mayOmmitLastEnablePop AND nodes.rest=NIL AND nodes.first#NIL AND ISTYPE[nodes.first, EnableNode] THEN cc1 ¬ GenEnableNode[enableNode: NARROW[nodes.first], mode: useMode, skipPost: TRUE] ELSE cc1 ¬ GenNode[node: nodes.first, mode: useMode]; IF makesRealCode AND makeTemporaryDecl THEN { declC: Code ¬ C2CEmit.CollectCode[temporaryDeclarations]; IF declC#NIL THEN { dead: BOOL ¬ C2CEmit.GetIsDead[cc1.sc]; cc1.sc ¬ C2CEmit.Cat[enterBlock, declC, cc1.sc, exitBlock]; IF dead THEN C2CEmit.SetDead[cc1.sc]; }; IF saveDeclC#NIL THEN C2CEmit.AppendCode[temporaryDeclarations, saveDeclC]; }; cc.sc ¬ Cat2[cc.sc, cc1.sc]; IF (count¬count+1) > 5 AND cc1.sc#NIL AND nodes.rest#NIL THEN { dead: BOOL ¬ C2CEmit.GetIsDead[cc.sc]; cc.sc ¬ C2CEmit.Cat[cc.sc, C2CEmit.line]; count ¬ 0; IF dead THEN C2CEmit.SetDead[cc.sc]; }; IF cc1.ec#NIL THEN { IF ~makesRealCode THEN { cc.sc ¬ C2CEmit.Cat[cc.sc, cc1.ec, ";\n"]; IF wasDead THEN C2CEmit.SetDead[cc.sc]; } ELSE IF ~lastNode OR GetAMode[rqMode]=skip THEN cc.sc ¬ C2CEmit.Cat[cc.sc, "(void) ", cc1.ec, ";\n"] ELSE { IF count>5 THEN {count ¬ 0; cc1.ec ¬ C2CEmit.Cat[cc1.ec, C2CEmit.line]}; cc.ec ¬ cc1.ec; } }; ENDLOOP; FreeMode[skipMode]; }; GenNode: PUBLIC PROC [node: Node, mode: Mode] RETURNS [cc: CodeCont] = { Process.CheckForAbort[]; IF node = nullNode THEN { RETURN }; WITH node SELECT FROM varNode: Var => { cc ¬ GenVarNode[varNode: varNode, mode: mode]; }; constNode: ConstNode => { cc ¬ GenConstNode[constNode: constNode, mode: mode]; }; blockNode: BlockNode => { cc ¬ GenBlockNode[blockNode: blockNode, mode: mode]; }; declNode: DeclNode => { cc.sc ¬ GenDeclNode[declNode: declNode, mode: mode]; }; enableNode: EnableNode => { cc ¬ GenEnableNode[enableNode: enableNode, mode: mode]; }; assignNode: AssignNode => { cc ¬ GenAssignNode[assignNode: assignNode, mode: mode]; }; condNode: CondNode => { cc ¬ GenCondNode[condNode: condNode, mode: mode]; }; labelNode: LabelNode => { cc ¬ GenLabelNode[labelNode: labelNode, mode: mode]; }; gotoNode: GotoNode => { cc.sc ¬ GenGotoNode[gotoNode: gotoNode, mode: mode]; }; applyNode: ApplyNode => { cc ¬ GenApplyNode[applyNode: applyNode, mode: mode]; }; lambdaNode: LambdaNode => { cc.sc ¬ GenLambdaNode[lambdaNode: lambdaNode, mode: mode]; }; returnNode: ReturnNode => { cc ¬ GenReturnNode[returnNode: returnNode, mode: mode]; }; operNode: OperNode => { cc ¬ GenNakedOperNode[operNode: operNode, mode: mode]; }; machineCodeNode: MachineCodeNode => { CantHappenCedar; --only allowed in context of applyNode }; moduleNode: ModuleNode => { GenModuleNode[moduleNode: moduleNode, mode: mode]; }; sourceNode: SourceNode => { cc ¬ GenSourceNode[sourceNode: sourceNode, mode: mode]; }; commentNode: CommentNode => { cc.sc ¬ GenCommentNode[commentNode: commentNode, mode: mode]; }; ENDCASE => CaseMissing; }; AssBitAddrOfId: PROC [name: ROPE, mode: Mode, bitOffset: INT ¬ 0] RETURNS [sc: Code] = { ac: C2CAddressing.AddressContainer ¬ GetAddrContainer[mode]; IF ~GetAMode[mode]=assBitAddr THEN CantHappen; sc ¬ C2CEmit.Cat[ C2CEmit.Cat[ac.words, " = (word) &", name, "; "], C2CEmit.Cat[ac.bits, " = ", C2CCodeUtils.ConstI[bitOffset], ";\n"] ]; }; AssAddrOfId: PROC [r: ROPE, mode: Mode] RETURNS [sc: Code] = { template: ROPE ¬ GetTemplate[mode]; IF ~GetAMode[mode]=assAddr THEN CantHappen; sc ¬ C2CEmit.Cat[template, " = &", r, ";\n"]; }; ConstVal: PROC [w: Word] RETURNS [ROPE] = { i: INT ¬ IntCodeUtils.WordToInt[w]; IF i<0 AND i>-2001 THEN RETURN [ IO.PutFR1[" (word) %g", IO.int[i]] ] ELSE RETURN [ Convert.RopeFromCard[IntCodeUtils.WordToCard[w]] ]; }; globalSmallConstantsTable: IntCodeUtils.IdTab; ResetGlobalSmallConstantsTable: PROC [] = { globalSmallConstantsTable ¬ IntCodeUtils.NewIdTab[] }; DeclareWordConstant: PROC [w: Word] RETURNS [name: ROPE] = { table: IntCodeUtils.IdTab ~ globalSmallConstantsTable; WITH IntCodeUtils.Fetch[table, IntCodeUtils.WordToInt[w]] SELECT FROM r: ROPE => name ¬ r; ENDCASE => { c: Code; name ¬ C2CNames.InternalName["const"]; c ¬ C2CEmit.Cat["static ", C2CTarget.word, " ", name]; c ¬ C2CEmit.Cat[c, " = ", ConstVal[w], ";\n"]; C2CEmit.AppendCode[moduleDeclarations, c]; [] ¬ IntCodeUtils.Store[table, IntCodeUtils.WordToInt[w], name]; }; }; StringTableEntryRec: TYPE = RECORD [ name: ROPE ¬ NIL, --name of template with string [if template is already generated] count: INT ¬ 1 --how often this string is used ]; CountUsageOfStrings: PROC [] = { stringTable: SymTab.Ref ~ SymTab.Create[]; FindConstants: IntCodeUtils.Visitor = { WITH node SELECT FROM bytes: BytesConstNode => WITH SymTab.Fetch[stringTable, bytes.bytes].val SELECT FROM entry: REF StringTableEntryRec => entry.count ¬ entry.count+1; ENDCASE => [] ¬ SymTab.Store[stringTable, bytes.bytes, NEW[StringTableEntryRec]]; ENDCASE => {}; IntCodeUtils.MapNode[node, FindConstants]; RETURN [node]; }; [] ¬ FindConstants[C2CBasics.rootNode]; C2CBasics.PutProp[$stringTable, stringTable] }; DefineStringCopy: PUBLIC PROC [length: INT, bytes: ROPE] RETURNS [name: ROPE] = { type: ROPE ¬ C2CTypes.DefineType[MAX[length*8, C2CTarget.bitsPerWord]]; start: INT ¬ 0; decl: Code; name ¬ C2CNames.InternalName["const"]; decl ¬ C2CEmit.Cat["static ", type, " ", name, ";\n"]; C2CEmit.AppendCode[moduleDeclarations, decl]; WHILE length>0 DO chunkSize: INT ¬ MIN[length, stringPieceMaxLength]; dest: ROPE ¬ IF start=0 THEN Rope.Concat["&", name] ELSE IO.PutFR["( (int) &%g + %g)", IO.rope[name], IO.int[start]]; c: Code ¬ C2CRunTime.MoveBytesDisjoint[ src: C2CEmit.IdentCode[C2CCodeUtils.CString[Rope.Substr[base: bytes, start: start, len: chunkSize]]], dst: C2CEmit.IdentCode[dest], nBytes: chunkSize ]; C2CEmit.AppendCode[moduleInitializations, C2CEmit.Cat[c, ";\n"]]; length ¬ length-chunkSize; start ¬ start+chunkSize; ENDLOOP; }; DefineStringStruct: PUBLIC PROC [length: INT, bytes: ROPE] RETURNS [name: ROPE] = { First: PROC [] RETURNS [val: CARD ¬ 0] = { leng: INT ¬ Rope.Length[bytes]; IF ~C2CTarget.consecutiveStringsAllocedAdj THEN NotYetImpl; IF BITS[CARD] RETURN [tab]; ENDCASE => { tab: SymTab.Ref ~ SymTab.Create[case: FALSE]; C2CBasics.PutProp[key, tab]; RETURN [tab] }; }; ConvertSingleRealLiterals: PROC [contents: ByteSequence] RETURNS [ROPE] = { RETURN [contents]; }; ConvertDoubleRealLiterals: PROC [contents: ByteSequence] RETURNS [ROPE] = { RETURN [contents]; }; literalsDirectCast: BOOL ¬ TRUE; MakeTemplate: PROC [bits: INT, type: ROPE, lit: ROPE] RETURNS [name: ROPE] = { IF literalsDirectCast THEN { name ¬ C2CNames.InternalName["fc"]; C2CEmit.AppendCode[macroDeclarations, "static "]; C2CEmit.AppendCode[macroDeclarations, C2CEmit.Cat[type, name, " = ", lit, ";\n"]]; } ELSE { assign: Code; ptrType: ROPE ¬ C2CTypes.DefinePtrType[bits]; fname: ROPE ¬ C2CNames.InternalName["ff"]; C2CEmit.AppendCode[macroDeclarations, "static "]; C2CEmit.AppendCode[macroDeclarations, C2CEmit.Cat[type, fname, " = ", lit, ";\n"]]; name ¬ C2CStateUtils.DeclareVariable[macroDeclarations, bits, "fc"]; assign ¬ C2CEmit.Cat[" = *(", ptrType, ")&", fname]; C2CEmit.AppendCode[moduleInitializations, C2CEmit.Cat[name, assign, ";\n"]]; }; }; SingleFloatLiteral: PROC [contents: ByteSequence] RETURNS [cc: CodeCont¬[]] = { template: ROPE; tab: SymTab.Ref ~ GetSymTab[$SingleRealLiterals]; lit: ROPE ~ ConvertSingleRealLiterals[contents]; WITH SymTab.Fetch[tab, lit].val SELECT FROM r: ROPE => template ¬ r; ENDCASE => { template ¬ MakeTemplate[C2CTarget.bitsPerWord, "float ", lit]; [] ¬ SymTab.Store[tab, lit, template]; }; IF literalsDirectCast THEN { cc.ec ¬ C2CEmit.Deref[ c: C2CEmit.IdentCode[Rope.Concat["&", template]], pointeeBits: C2CTarget.bitsPerWord ] } ELSE cc.ec ¬ C2CEmit.IdentCode[template]; }; DoubleFloatLiteral: PROC [contents: ByteSequence] RETURNS [cc: CodeCont¬[]] = { template: ROPE; tab: SymTab.Ref ~ GetSymTab[$DRealLiterals]; lit: ROPE ¬ ConvertDoubleRealLiterals[contents]; WITH SymTab.Fetch[tab, lit].val SELECT FROM r: ROPE => template ¬ r; ENDCASE => { template ¬ MakeTemplate[C2CTarget.bitsPerDoubleWord, "double ", lit]; [] ¬ SymTab.Store[tab, lit, template]; }; IF literalsDirectCast THEN { cc.ec ¬ C2CEmit.Deref[ c: C2CEmit.IdentCode[Rope.Concat["&", template]], pointeeBits: C2CTarget.bitsPerDoubleWord ] } ELSE cc.ec ¬ C2CEmit.IdentCode[template]; }; GenConstNode: PUBLIC PROC [constNode: ConstNode, mode: Mode] RETURNS [cc: CodeCont] = { am: C2CAddressing.AddressMode ¬ GetAMode[mode]; IF am=skip THEN CantHappen; WITH constNode SELECT FROM wordConst: WordConstNode => { SELECT am FROM plain => {cc.ec ¬ C2CEmit.IdentCode[DeclareWordConstant[wordConst.word]]}; value, maskNShift => { cc.ec ¬ C2CEmit.Cat[ConstVal[wordConst.word]]; cc.ec ¬ C2CEmit.SetPrecedence[cc.ec, primaryPrecedence]; }; assUnits => { c: Code ¬ C2CEmit.RopeCode[ConstVal[wordConst.word]]; c ¬ C2CEmit.SetPrecedence[c, unaryPrecedence]; cc.sc ¬ C2CAddressingOps.CodeToAssUnits[c, mode]; }; assBitAddr => { template: ROPE ¬ DeclareWordConstant[wordConst.word]; cc.sc ¬ AssBitAddrOfId[template, mode, C2CTarget.bitsPerWord-constNode.bits]; }; getBitAddr => { template: ROPE ¬ DeclareWordConstant[wordConst.word]; cc.ec ¬ C2CEmit.TakeAddr[C2CEmit.IdentCode[template]]; IF constNode.bits CantHappen; ENDCASE => CaseMissing; }; bytes: BytesConstNode => { name: ROPE; stringTable: SymTab.Ref ~ NARROW[C2CBasics.GetProp[$stringTable]]; entry: REF StringTableEntryRec ~ NARROW[SymTab.Fetch[stringTable, bytes.bytes].val]; length: INT ¬ IF constNode.bits#0 THEN (constNode.bits+7)/8 ELSE Rope.Length[bytes.bytes]; IF entry=NIL THEN CantHappen; IF entry.name#NIL THEN name ¬ entry.name ELSE { IF entry.count<=1 AND bytes.align<=8 AND Rope.Length[bytes.bytes]<=stringPieceMaxLength THEN SELECT am FROM plain => { cc.ec ¬ C2CEmit.IdentCode[C2CCodeUtils.CString[bytes.bytes]]; cc.ec ¬ C2CEmit.SetIsAddress[cc.ec]; RETURN; }; getAddr => { cc.ec ¬ C2CEmit.IdentCode[C2CCodeUtils.CString[bytes.bytes]]; RETURN; }; ENDCASE => {}; IF C2CTarget.bitsPerWord<=C2CTarget.bestAlignment AND C2CTarget.consecutiveStringsAllocedAdj THEN { name ¬ DefineStringStruct[length, bytes.bytes]; } ELSE { name ¬ DefineStringCopy[length, bytes.bytes]; }; entry.name ¬ name; }; SELECT am FROM plain, maskNShift, value => cc.ec ¬ C2CEmit.Deref[C2CEmit.TakeAddr[C2CEmit.IdentCode[name], TRUE], constNode.bits]; getAddr => cc.ec ¬ C2CEmit.TakeAddr[C2CEmit.IdentCode[name], TRUE]; assBitAddr => cc.sc ¬ AssBitAddrOfId[name, mode, 0]; assAddr => cc.sc ¬ AssAddrOfId[name, mode]; assUnits => NotYetImpl; skip => CantHappen; ENDCASE => CaseMissing; }; refLit: RefLiteralConstNode => CantHappen; --resolved in front end numLiteral: REF NodeRep.const.numLiteral => { SELECT numLiteral.class.kind FROM real => SELECT TRUE FROM numLiteral.class.precision=C2CTarget.bitsPerWord => cc ¬ SingleFloatLiteral[numLiteral.contents]; numLiteral.class.precision=C2CTarget.bitsPerDoubleWord => cc ¬ DoubleFloatLiteral[numLiteral.contents]; ENDCASE => CantHappen; ENDCASE => CantHappen; SELECT am FROM plain, value => {}; ENDCASE => cc ¬ C2CAddressingOps.ModizeArithCode[cc, mode, numLiteral.class.precision]; }; ENDCASE => CaseMissing; }; enterBlock: ROPE ¬ Rope.Flatten[Rope.Concat["{", C2CEmit.nestNLine]]; exitBlock: ROPE ¬ Rope.Flatten[Rope.Concat["};", C2CEmit.unNestNLine]]; GenBlockNode: PUBLIC PROC [blockNode: BlockNode, mode: Mode] RETURNS [cc: CodeCont] = { saveBlockDecl, saveTempDecl: Code ¬ NIL; allowsDecls: BOOL ¬ IF blockNode.bits#0 THEN FALSE ELSE SELECT GetAMode[mode] FROM skip, assBitAddr, assAddr, assUnits, assBits => TRUE, ENDCASE => FALSE; IF allowsDecls THEN { saveBlockDecl ¬ C2CEmit.CollectCode[blockDeclarations]; saveTempDecl ¬ C2CEmit.CollectCode[temporaryDeclarations]; } ELSE { s: INT ¬ BaseSize[mode]; IF s>0 AND s RETURN [TRUE]; ENDCASE => RETURN [FALSE]; }; GenVarNodeInDeclaration: PROC [var: Var, init: Node¬NIL, mode: Mode, global: BOOL ¬ FALSE] RETURNS [initC: Code¬NIL] = { GenInit: PROC [init: Node, var: Var, declPreC: Code, initInDeclAllowed: BOOL] RETURNS [declC, initC: Code¬NIL] = { GenAssign: --IntCodeTwigImpl-- PROC [lhs: Var, rhs: Node] RETURNS [AssignNode] = { lhs.flags[assigned] ¬ TRUE; RETURN [IntCodeUtils.zone.NEW[NodeRep.assign ¬ [0, assign[lhs: lhs, rhs: rhs]]]]; }; declC ¬ declPreC; IF init#NIL THEN { IF var.bits#init.bits THEN CantHappen; IF initInDeclAllowed AND var.bits=C2CTarget.bitsPerWord AND C2CPreprocessing.MayBeDeclaredAsPtr[var] THEN { cc1: CodeCont ¬ GenNode[init, UseValue[init.bits]]; IF cc1.sc#NIL THEN CantHappen; cc1.ec ¬ C2CEmit.MinPrecedence[cc1.ec, unaryPrecedence]; declC ¬ C2CEmit.Cat[declC, " = ", C2CTarget.wordPtrCast, cc1.ec]; } ELSE IF initInDeclAllowed AND C2CIntCodeUtils.IsSimpleConst[init].is THEN { cc1: CodeCont ¬ GenNode[init, UseValue[init.bits]]; IF cc1.sc#NIL THEN CantHappen; declC ¬ C2CEmit.Cat[declC, " = ", cc1.ec]; } ELSE { cc1: CodeCont; assign: AssignNode; assign ¬ GenAssign[lhs: var, rhs: init]; cc1 ¬ GenAssignNode[assignNode: assign, mode: skipMode]; initC ¬ cc1.sc; IF cc1.ec#NIL THEN CantHappen; }; }; }; PeekSpecialNames: PROC [] RETURNS [proposedName: ROPE¬NIL] = { IF init#NIL AND var.bits=C2CTarget.bitsPerWord THEN WITH init SELECT FROM app: ApplyNode => WITH app.proc SELECT FROM oper: OperNode => WITH oper.oper SELECT FROM mesa: MesaOper => SELECT mesa.mesa FROM alloc => RETURN ["lf"]; ENDCASE => {}; ENDCASE => {}; ENDCASE => {}; oper: OperNode => WITH oper.oper SELECT FROM mesa: MesaOper => SELECT mesa.mesa FROM globalFrame => RETURN ["gf"]; ENDCASE => {}; ENDCASE => {}; ENDCASE => {} }; name: ROPE; hasDecl: BOOL ¬ FALSE; declC: Code ¬ NIL; sz: INT ¬ C2CTarget.TemporaryBits[var.bits]; type: ROPE ¬ C2CTypes.DefineType[sz]; proposedName: ROPE ¬ "var"; IF var.bits=C2CTarget.bitsPerWord AND C2CPreprocessing.MayBeDeclaredAsPtr[var] THEN type ¬ C2CTarget.wordPtr; IF var.flags[frequent] AND ISTYPE[var.location, LocalVarLocation] AND var.bits=C2CTarget.bitsPerWord THEN { type ¬ Rope.Concat["register ", type]; proposedName ¬ PeekSpecialNames[].proposedName; }; name ¬ C2CNames.VarName[id: var.id, class: proposedName]; WITH var.location SELECT FROM localVarLocation: LocalVarLocation => { IF global THEN CantHappenCedar; hasDecl ¬ TRUE; declC ¬ C2CEmit.Cat[type, " ", name]; IF localVarLocation.parent=nullLabel OR C2CBasics.labelWithLambda=NIL THEN CantHappen; IF localVarLocation.parent.id#C2CBasics.labelWithLambda.label.id THEN CantHappen; [declC, initC] ¬ GenInit[init: init, var: var, declPreC: declC, initInDeclAllowed: TRUE]; declC ¬ C2CEmit.Cat[declC, ";\n"]; IF var.bits#sz THEN C2CBasics.Report[Rope.Cat["Warning: declares local variable ", name, " with funny size; This is benign if c2c doesn't crash on usage\n"]]; }; globalVarLocation: GlobalVarLocation => { IF ~global THEN CantHappenCedar; hasDecl ¬ TRUE; declC ¬ C2CEmit.Cat["static ", type, " ", name]; [declC, initC] ¬ GenInit[init: init, var: var, declPreC: declC, initInDeclAllowed: TRUE]; declC ¬ C2CEmit.Cat[declC, ";\n"]; IF var.bits#sz THEN C2CBasics.Report[Rope.Cat["Warning: declares global variable ", name, " with funny size; This is benign if c2c doesn't crash on usage\n"]]; }; fieldLocation: FieldLocation => { declC ¬ C2CEmit.CatRemark[declC, Rope.Cat["declaration of ", name, " skipped"]]; IF init#NIL THEN [declC, initC] ¬ GenInit[init: init, var: var, declPreC: declC, initInDeclAllowed: FALSE]; declC ¬ C2CEmit.Cat[declC, "\n"]; }; systemLocation: SystemLocation => CantHappenCedar; registerLocation: RegisterLocation => CantHappenCedar; linkLocation: LinkLocation => CantHappenCedar; stackLocation: StackLocation => CantHappenCedar; derefLocation: DerefLocation => CantHappenCedar; indexedLocation: IndexedLocation => CantHappenCedar; upLevelLocation: UpLevelLocation => CantHappenCedar; compositeLocation: CompositeLocation => CantHappenCedar; escapeLocation: EscapeLocation => CantHappenCedar; dummyLocation: DummyLocation => CantHappenCedar; ENDCASE => CaseMissing; IF declC#NIL THEN { IF global THEN C2CEmit.AppendCode[procedureDeclarations, declC] ELSE C2CEmit.AppendCode[blockDeclarations, declC]; }; }; GenDeclNode: PUBLIC PROC [declNode: DeclNode, mode: Mode] RETURNS [code: Code¬NIL] = { code ¬ GenVarNodeInDeclaration[var: declNode.var, init: declNode.init, mode: mode]; }; LastNode: PROC [nodeList: IntCodeDefs.NodeList] RETURNS [node: IntCodeDefs.Node ¬ NIL] = { WHILE nodeList#NIL DO node ¬ nodeList.first; nodeList ¬ nodeList.rest ENDLOOP }; GenEnableNode: PROC [enableNode: EnableNode, mode: Mode, skipPost: BOOL ¬ FALSE] RETURNS [cc: CodeCont] = { nest: BOOL ¬ enableNode.handle#NIL; sc, preCode, postCode: Code; innerIsLive: BOOL ¬ IntCodeStuff.IsLive[LastNode[enableNode.scope]]; [sc, preCode, postCode] ¬ GenHandlerNode[handler: enableNode.handle, mode: mode, innerIsLive: innerIsLive]; IF skipPost THEN postCode ¬ NIL; IF nest THEN C2CEnables.IncEnableNesting[]; cc ¬ GenNodeList[nodeList: enableNode.scope, mode: mode, outsideTemporaryDecl: FALSE]; cc.sc ¬ C2CEmit.Cat[sc, preCode, cc.sc, postCode]; IF cc.ec#NIL THEN CantHappen; IF nest THEN C2CEnables.DecEnableNesting[]; }; GenCondNode: PUBLIC PROC [condNode: CondNode, mode: Mode] RETURNS [cc: CodeCont] = { CondNodeIsSimpleEnoughForExpr: PROC [] RETURNS [b: BOOL ¬ FALSE] = { IF condNode.bits>bitsPerWord OR condNode.bits=0 THEN RETURN [FALSE] ELSE { reqAMode: C2CAddressing.AddressMode ¬ GetAMode[mode]; SELECT reqAMode FROM value, plain => { RETURN [~C2CIntCodeUtils.StatementCode[condNode]] }; skip, assUnits, assBits, assBitAddr => RETURN [FALSE]; ENDCASE => CaseMissing; }; }; GenOrNodeList: PROC [nodeList: IntCodeDefs.NodeList] RETURNS [cc: CodeCont, thenLabel: ROPE¬NIL] = { NeedsStatementCode: PROC [nodeList: IntCodeDefs.NodeList] RETURNS [BOOL¬FALSE] = { FOR nl: NodeList ¬ nodeList, nl.rest WHILE nl#NIL DO IF C2CIntCodeUtils.StatementCode[nl.first] THEN RETURN [TRUE]; ENDLOOP }; isFirst: BOOL ¬ TRUE; FOR nl: NodeList ¬ nodeList, nl.rest WHILE nl#NIL DO cc1: CodeCont; hackBool: BOOL ¬ C2CIntCodeUtils.IsFieldVar[nl.first]; IF hackBool THEN C2CBasics.PushContext[[$BoolBitHackOk, NIL, NIL]]; cc1 ¬ C2CAddressingOps.LoadArithNode[node: nl.first]; IF hackBool THEN C2CBasics.PopContext[]; IF cc1.sc#NIL THEN cc.sc ¬ Cat2[cc.sc, cc1.sc]; IF isFirst THEN cc.ec ¬ cc1.ec ELSE cc.ec ¬ C2CEmit.BinOp[cc.ec, " || ", cc1.ec, logicalOrPrecedence]; isFirst ¬ FALSE; IF NeedsStatementCode[nl.rest] THEN { IF thenLabel=NIL THEN thenLabel ¬ C2CNames.InternalName["then0"]; cc.ec ¬ C2CEmit.MinPrecedence[cc.ec, allwaysPutParanthesisPrecedence]; cc.sc ¬ C2CEmit.Cat[cc.sc, "if ", cc.ec]; cc.sc ¬ C2CEmit.Cat[cc.sc, " { goto ", thenLabel, ";};\n"]; cc.ec ¬ NIL; isFirst ¬ TRUE; }; ENDLOOP; cc.ec ¬ C2CEmit.MinPrecedence[cc.ec, logicalOrPrecedence]; }; ExprCond: PROC [] = { count: INT ¬ 0; --we count open parantheses code: Code ¬ C2CEmit.RopeCode[]; FOR cases: IntCodeDefs.CaseList ¬ condNode.cases, cases.rest WHILE cases#NIL DO IF cases.tests=NIL THEN { elsecc: CodeCont; IF cases.rest#NIL THEN CantHappen; elsecc ¬ C2CAddressingOps.LoadArithNode[node: cases.body]; elsecc.ec ¬ C2CEmit.MinPrecedence[elsecc.ec, questionColonPrecedence]; IF elsecc.sc#NIL THEN CantHappen; code ¬ C2CEmit.Cat[code, elsecc.ec]; } ELSE { testcc, bodycc: CodeCont; thenLabel: ROPE ¬ NIL; [testcc, thenLabel] ¬ GenOrNodeList[nodeList: cases.tests]; IF thenLabel#NIL THEN CantHappen; IF C2CEmit.NonWhiteSpace[testcc.sc] THEN CantHappen; --shouldn't have used Expr testcc.ec ¬ C2CEmit.MinPrecedence[testcc.ec, parenPrecedence]; bodycc ¬ C2CAddressingOps.LoadArithNode[node: cases.body]; IF C2CEmit.NonWhiteSpace[bodycc.sc] THEN CantHappen; --shouldn't have used Expr bodycc.ec ¬ C2CEmit.MinPrecedence[bodycc.ec, questionColonPrecedence]; code ¬ C2CEmit.Cat[code, " ( ", testcc.ec]; count ¬ count+1; code ¬ C2CEmit.Cat[code, " ? ", bodycc.ec, " : "]; } ENDLOOP; IF count=0 THEN CantHappen; WHILE count>0 DO code ¬ C2CEmit.Cat[code, " ) "]; count ¬ count-1; ENDLOOP; code ¬ C2CEmit.SetPrecedence[code, parenPrecedence]; cc.ec ¬ code; }; CanSwitchStatementBeUsed: PROC RETURNS [switchVar: Var ¬ NIL] = { branchTab: IntCodeUtils.IdTab ¬ IntCodeUtils.NewIdTab[]; branches: INT ¬ 0; CheckOneTest: PROC [n: Node] RETURNS [switch: BOOL ¬ TRUE] = { IF n.bits#1 THEN RETURN [FALSE]; WITH n SELECT FROM apply: ApplyNode => { isConst: BOOL; constVal: CARD; IF apply.handler#NIL THEN RETURN [FALSE]; IF apply.args=NIL OR apply.args.rest=NIL OR apply.args.rest.rest#NIL THEN RETURN [FALSE]; WITH apply.proc SELECT FROM oper: OperNode => WITH oper.oper SELECT FROM compare: CompareOper => { IF compare.class.precision>C2CTarget.bitsPerWord THEN RETURN [FALSE]; IF compare.sense#eq THEN RETURN [FALSE]; SELECT compare.class.kind FROM signed, unsigned => {}; ENDCASE => RETURN [FALSE] }; ENDCASE => RETURN [FALSE]; ENDCASE => RETURN [FALSE]; [isConst, constVal] ¬ C2CIntCodeUtils.IsSimpleConst[apply.args.rest.first]; IF ~isConst THEN RETURN [FALSE]; IF IntCodeUtils.Insert[branchTab, LOOPHOLE[constVal], $x]#IntCodeUtils.NullValue THEN RETURN [FALSE]; WITH apply.args.first SELECT FROM var: Var => { IF switchVar#NIL THEN { IF switchVar.id#var.id THEN RETURN [FALSE]; } ELSE { IF var.bits>C2CTarget.bitsPerWord THEN RETURN [FALSE]; switchVar ¬ var; }; }; ENDCASE => RETURN [FALSE]; }; ENDCASE => RETURN [FALSE]; }; FOR cases: IntCodeDefs.CaseList ¬ condNode.cases, cases.rest WHILE cases#NIL DO IF cases.tests#NIL THEN { FOR nl: NodeList ¬ cases.tests, nl.rest WHILE nl#NIL DO switch: BOOL ¬ CheckOneTest[nl.first]; branches ¬ branches+1; IF ~switch THEN RETURN [NIL]; ENDLOOP; }; ENDLOOP; IF branches<3 THEN RETURN [NIL]; }; StatementCondWithSwitch: PROC [switchVar: Var] = { noneAlive: BOOL ¬ TRUE; hadDefault: BOOL ¬ FALSE; cc1: CodeCont ¬ C2CAddressingOps.LoadArithNode[node: switchVar]; cc.sc ¬ Cat2[cc.sc, cc1.sc]; cc.sc ¬ C2CEmit.Cat[cc.sc, "switch (", cc1.ec, ") {", C2CEmit.nestNLine]; FOR cases: IntCodeDefs.CaseList ¬ condNode.cases, cases.rest WHILE cases#NIL DO IF cases.tests=NIL THEN { cc.sc ¬ C2CEmit.Cat[cc.sc, "default: "]; hadDefault ¬ TRUE } ELSE { FOR nl: NodeList ¬ cases.tests, nl.rest WHILE nl#NIL DO WITH nl.first SELECT FROM apply: ApplyNode => { val: CARD ¬ C2CIntCodeUtils.IsSimpleConst[apply.args.rest.first].val; cc.sc ¬ C2CEmit.Cat[cc.sc, IO.PutFR1["case %g: ", IO.card[val]]]; }; ENDCASE => ERROR; ENDLOOP }; cc.sc ¬ C2CEmit.Cat[cc.sc, C2CEmit.nestNLine]; cc1 ¬ GenNode[node: cases.body, mode: mode]; cc.sc ¬ Cat2[cc.sc, cc1.sc]; IF cc1.ec#NIL THEN CantHappen; IF C2CEmit.GetIsDead[cc.sc] THEN cc.sc ¬ C2CEmit.Cat[cc.sc, C2CEmit.unNestNLine] ELSE { cc.sc ¬ C2CEmit.Cat[cc.sc, "break;", C2CEmit.unNestNLine]; noneAlive ¬ FALSE; }; ENDLOOP; cc.sc ¬ C2CEmit.Cat[cc.sc, "};", C2CEmit.unNestNLine]; IF noneAlive AND hadDefault THEN C2CEmit.SetDead[cc.sc]; }; StatementCondWithIfs: PROC [] = { cc1: CodeCont; isFirst: BOOL ¬ TRUE; elseBrackets: INT ¬ 0; allDead: BOOL ¬ condNode.cases#NIL; ifBracket: BOOL ¬ FALSE; FOR cases: IntCodeDefs.CaseList ¬ condNode.cases, cases.rest WHILE cases#NIL DO hasAnElse: BOOL ¬ cases.rest#NIL; ifBracket ¬ FALSE; IF ~isFirst THEN { elseBrackets ¬ elseBrackets+1; cc.sc ¬ C2CEmit.Cat[cc.sc, "else {", C2CEmit.nestNLine]; }; IF cases.tests#NIL THEN { testcc: CodeCont; thenLabel: ROPE ¬ NIL; [testcc, thenLabel] ¬ GenOrNodeList[nodeList: cases.tests]; cc.sc ¬ Cat2[cc.sc, testcc.sc]; testcc.ec ¬ C2CEmit.MinPrecedence[testcc.ec, allwaysPutParanthesisPrecedence]; ifBracket ¬ TRUE; cc.sc ¬ C2CEmit.Cat[cc.sc, "if ", testcc.ec, " {", C2CEmit.nestNLine]; IF thenLabel#NIL THEN cc.sc ¬ C2CEmit.Cat[cc.sc, thenLabel, ": ;\n"]; }; cc1 ¬ GenNode[node: cases.body, mode: mode]; IF allDead AND ~C2CEmit.GetIsDead[cc1.sc] THEN allDead ¬ FALSE; cc.sc ¬ C2CEmit.Cat[cc.sc, cc1.sc]; IF cc1.ec#NIL THEN CantHappen; IF ifBracket THEN { cc.sc ¬ C2CEmit.Cat[cc.sc, "}", (IF hasAnElse THEN NIL ELSE ";"), C2CEmit.unNestNLine ]; }; isFirst ¬ FALSE; ENDLOOP; FOR i: INT IN [0..elseBrackets) DO cc.sc ¬ C2CEmit.Cat[cc.sc, "};", C2CEmit.unNestNLine]; ENDLOOP; IF allDead AND ~ifBracket THEN C2CEmit.SetDead[cc.sc]; }; LongStatementCondWithIfs: PROC [] = { cc1: CodeCont; elseBrackets: INT ¬ 0; endLabel: ROPE ¬ C2CNames.InternalName["endif0"]; needsEndLabel: BOOL ¬ FALSE; allDead: BOOL ¬ condNode.cases#NIL; isIf: BOOL ¬ FALSE; FOR cases: IntCodeDefs.CaseList ¬ condNode.cases, cases.rest WHILE cases#NIL DO isIf ¬ FALSE; IF cases.tests#NIL THEN { testcc: CodeCont; thenLabel: ROPE ¬ NIL; [testcc, thenLabel] ¬ GenOrNodeList[nodeList: cases.tests]; cc.sc ¬ Cat2[cc.sc, testcc.sc]; testcc.ec ¬ C2CEmit.MinPrecedence[testcc.ec, allwaysPutParanthesisPrecedence]; isIf ¬ TRUE; cc.sc ¬ C2CEmit.Cat[cc.sc, "if ", testcc.ec, " {", C2CEmit.nestNLine]; IF thenLabel#NIL THEN cc.sc ¬ C2CEmit.Cat[cc.sc, thenLabel, ": ;\n"]; }; cc1 ¬ GenNode[node: cases.body, mode: mode]; IF allDead AND ~C2CEmit.GetIsDead[cc1.sc] THEN allDead ¬ FALSE; cc.sc ¬ C2CEmit.Cat[cc.sc, cc1.sc]; IF cc1.ec#NIL THEN CantHappen; IF ~C2CEmit.GetIsDead[cc.sc] THEN { cc.sc ¬ C2CEmit.Cat[cc.sc, "goto ", endLabel, ";\n"]; allDead ¬ FALSE; needsEndLabel ¬ TRUE; }; IF isIf THEN cc.sc ¬ C2CEmit.Cat[cc.sc, "};", C2CEmit.unNestNLine]; ENDLOOP; IF needsEndLabel THEN cc.sc ¬ C2CEmit.Cat[cc.sc, endLabel, ": ;\n"]; IF allDead AND ~isIf THEN C2CEmit.SetDead[cc.sc]; }; IsLongCond: PROC [condList: IntCodeDefs.CaseList] RETURNS [BOOL¬FALSE] = { cnt: INT ¬ 0; FOR l: IntCodeDefs.CaseList ¬ condList, l.rest WHILE l#NIL DO IF (cnt ¬ cnt+1)>=4 THEN RETURN [TRUE] ENDLOOP }; StatementCond: PROC [] = { switchVar: Var ¬ CanSwitchStatementBeUsed[]; SELECT TRUE FROM switchVar#NIL => StatementCondWithSwitch[switchVar]; IsLongCond[condNode.cases] => LongStatementCondWithIfs[] ENDCASE => StatementCondWithIfs[]; }; aMode: C2CAddressing.AddressMode ¬ GetAMode[mode]; IF LHSMode[mode] THEN NotYetImpl; SELECT aMode FROM skip, assUnits, assBits, assBitAddr, assAddr => StatementCond[]; value, maskNShift, plain => { IF CondNodeIsSimpleEnoughForExpr[] THEN ExprCond[] ELSE { bits: INT ¬ C2CTarget.TemporaryBits[condNode.bits]; tempName: ROPE ¬ C2CStateUtils.DeclareVariable[temporaryDeclarations, bits, "tc"]; cc ¬ GenNode[condNode, SetAssUnits[mode, tempName, bits]]; IF cc.ec#NIL THEN CantHappen; cc.ec ¬ C2CEmit.IdentCode[tempName]; } }; getAddr => { IF CondNodeIsSimpleEnoughForExpr[] THEN ExprCond[] ELSE { tempName: ROPE ¬ C2CStateUtils.DeclareVariable[temporaryDeclarations, C2CTarget.bitsPerWord, "tcp"]; cc ¬ GenNode[condNode, SetAssAddr[mode, tempName]]; IF cc.ec#NIL THEN CantHappen; cc.ec ¬ C2CEmit.IdentCode[tempName]; } }; ENDCASE => CaseMissing; }; GenLabelNode: PUBLIC PROC [labelNode: LabelNode, mode: Mode] RETURNS [cc: CodeCont] = { WITH labelNode.label.node SELECT FROM labeledLambda: LambdaNode => { outerLambda: LabelNode ¬ C2CBasics.labelWithLambda; C2CBasics.labelWithLambda ¬ labelNode; GenLambdaNodeWithLabels[labeledLambda, labelNode, mode]; C2CBasics.labelWithLambda ¬ outerLambda; }; ENDCASE => { IF labelNode.label.id#nullLogicalId THEN cc.sc ¬ C2CEmit.Cat[C2CNames.LabName[id: labelNode.label.id, class: "lab"], ": ;\n"]; IF labelNode.label.node#NIL THEN { cc1: CodeCont ¬ C2CMain.GenNode[node: labelNode.label.node, mode: mode]; cc.sc ¬ Cat2[cc.sc, cc1.sc]; IF cc1.ec#NIL THEN CantHappen; }; }; }; GenGotoNode: PUBLIC PROC [gotoNode: GotoNode, mode: Mode] RETURNS [code: Code¬NIL] = { name: ROPE; SELECT GetAMode[mode] FROM skip => {}; ENDCASE => CantHappen; name ¬ C2CNames.LabName[gotoNode.dest.id, "lab"]; code ¬ C2CEmit.Cat["goto ", name, ";\n"]; FOR i: INT IN [0..C2CEnables.PopsForJump[gotoNode.dest.id]) DO code ¬ C2CEmit.Cat[C2CRunTime.PopHandler[], ";\n", code]; ENDLOOP; C2CEmit.SetDead[code]; }; GenLambdaNode: PUBLIC PROC [lambdaNode: LambdaNode, mode: Mode] RETURNS [code: Code¬NIL] = { CantHappenCedar; }; GenLambdaNodeWithLabels: PUBLIC PROC [lambdaNode: LambdaNode, labelNode: LabelNode, mode: Mode] = { myFlags: Mode ¬ mode; RVar: TYPE = RECORD [r: ROPE, var: Var]; addressTab: IntCodeUtils.IdTab ¬ IntCodeUtils.NewIdTab[]; GenFormalList: PROC [varList: VarList] RETURNS [param: Code¬NIL] = { IF ExpMode[mode] THEN CantHappen; FOR list: VarList ¬ varList, list.rest WHILE list#NIL DO var: Var ¬ list.first; name: ROPE ¬ C2CNames.VarName[id: var.id, class: "formal"]; IF var.location#nullLocation THEN { WITH var.location SELECT FROM locLoc: LocalVarLocation => IF locLoc.parent.id#C2CBasics.labelWithLambda.label.id THEN CantHappen; ENDCASE => CantHappen; }; IF var.bits<=C2CTarget.maxBitsForValueParams THEN { param ¬ C2CEmit.Cat[param, name] } ELSE { ptrName: ROPE ¬ C2CNames.InternalName[Rope.Concat["P", name]]; param ¬ C2CEmit.Cat[param, ptrName]; [] ¬ IntCodeUtils.Store[addressTab, var.id, ptrName]; }; IF list.rest#NIL THEN param ¬ C2CEmit.Cat[param, ", "]; ENDLOOP; }; FormalsDecl: PROC [varList: VarList] RETURNS [code: Code¬NIL] = { FOR list: VarList ¬ varList, list.rest WHILE list#NIL DO var: Var ¬ list.first; val: IntCodeUtils.Value ¬ IntCodeUtils.Fetch[addressTab, var.id]; cc1: Code; IF val=IntCodeUtils.NullValue THEN { cc1 ¬ GenVarNodeInDeclaration[var: var, init: NIL, mode: declMode, global: FALSE] } ELSE { pType: ROPE ¬ C2CTypes.DefinePtrType[var.bits]; cc1 ¬ C2CEmit.Cat[pType, " ", NARROW[val, ROPE], ";"]; }; code ¬ C2CEmit.Cat[code, cc1, C2CEmit.line]; ENDLOOP; }; DeclareNMoveLargeFormals: PROC [varList: VarList] RETURNS [code: Code¬NIL] = { FOR list: VarList ¬ varList, list.rest WHILE list#NIL DO var: Var ¬ list.first; val: IntCodeUtils.Value ¬ IntCodeUtils.Fetch[addressTab, var.id]; IF val=IntCodeUtils.NullValue THEN NULL ELSE { addrName: ROPE ¬ NARROW[val]; usedName: ROPE ¬ C2CNames.VarName[id: var.id, class: "formal"]; decl: Code ¬ GenVarNodeInDeclaration[var: var, init: NIL, mode: declMode, global: FALSE]; C2CEmit.AppendCode[procedureDeclarations, C2CEmit.Cat[decl, C2CEmit.line]]; code ¬ C2CEmit.Cat[ code, C2CRunTime.MoveWordsDisjoint[ src: C2CEmit.IdentCode[addrName], dst: C2CEmit.Cat["&", usedName], nWords: C2CTarget.BitsToWords[var.bits] --rounds up same as template ], ";\n" ]; }; ENDLOOP; }; cc1: CodeCont; procName: ROPE; staticOrExtern: ROPE ¬ IF C2CNames.IsExtern[labelNode.label.id] THEN "extern " ELSE "static "; param, headCode, mainCode, total: Code; formalReturnName: ROPE; formalReturnType: ROPE ¬ IF (lambdaNode.bitsOut>0) AND (lambdaNode.bitsOut<=C2CTarget.bitsPerWord) THEN "word " ELSE "void "; formalArgs: VarList ~ lambdaNode.formalArgs; myFlags ¬ SetExpr[myFlags, FALSE]; IF GetProp[myKeyForModuleEncountered]=NIL THEN CantHappen; PutProp[myKeyForReturnBits, NEW[INT¬lambdaNode.bitsOut]]; IF GetProp[myKeyForFirstProc]=NIL THEN { procName ¬ C2CNames.LabName[id: labelNode.label.id, class: "Installation"]; PutProp[myKeyForFirstProc, procName]; } ELSE { procName ¬ C2CNames.LabName[id: labelNode.label.id, class: "Proc"]; }; C2CEmit.AppendCode[moduleDeclarationsP, C2CEmit.Cat[staticOrExtern, formalReturnType, procName, "();\n"]]; headCode ¬ C2CEmit.Cat[C2CEmit.twoLines, staticOrExtern, formalReturnType, procName, "("]; IF lambdaNode.bitsOut>C2CTarget.bitsPerWord THEN { formalReturnName ¬ C2CNames.InternalName["formalReturn"]; PutProp[myKeyForFormalReturn, formalReturnName]; headCode ¬ C2CEmit.Cat[headCode, formalReturnName]; IF formalArgs#NIL THEN headCode ¬ C2CEmit.Cat[headCode, ", "]; }; param ¬ GenFormalList[varList: formalArgs]; headCode ¬ C2CEmit.Cat[headCode, param, ")", C2CEmit.nestNLine]; headCode ¬ C2CEmit.Cat[headCode, FormalsDecl[varList: formalArgs]]; IF lambdaNode.bitsOut>C2CTarget.bitsPerWord THEN { headCode ¬ C2CEmit.Cat[headCode, "word ", formalReturnName, "[];", C2CEmit.line]; }; headCode ¬ C2CEmit.Cat[ headCode, C2CEmit.CollectCode[procedureDeclarations], C2CEmit.CollectCode[blockDeclarations], C2CEmit.CollectCode[temporaryDeclarations] ]; headCode ¬ C2CEmit.Cat[headCode, C2CEmit.line, "{", C2CEmit.line]; mainCode ¬ DeclareNMoveLargeFormals[formalArgs]; cc1 ¬ GenNodeList[nodeList: lambdaNode.body, mode: myFlags, outsideTemporaryDecl: TRUE, mayOmmitLastEnablePop: lambdaNode.bitsOut>0]; IF cc1.ec#NIL THEN CantHappen; mainCode ¬ C2CEmit.Cat[ C2CEmit.CollectCode[procedureDeclarations], C2CEmit.CollectCode[blockDeclarations], C2CEmit.CollectCode[temporaryDeclarations], mainCode, cc1.sc ]; mainCode ¬ C2CEmit.Cat[mainCode, "}", C2CEmit.unNest, C2CEmit.twoLines]; PutProp[myKeyForFormalReturn, NIL]; PutProp[myKeyForReturnBits, NIL]; total ¬ C2CEmit.Cat[ headCode, C2CEmit.CollectCode[procedureDeclarations], C2CEmit.CollectCode[blockDeclarations], C2CEmit.CollectCode[temporaryDeclarations], mainCode ]; C2CEmit.AppendCode[moduleContents, total]; FreeMode[myFlags]; }; GenReturnNode: PUBLIC PROC [returnNode: ReturnNode, mode: Mode] RETURNS [cc: CodeCont] = { cc1: CodeCont; returnBits: INT; pops: INT ¬ C2CEnables.PopsForReturns[]; myMode: Mode ¬ SetExpr[mode, TRUE]; skipMode: Mode ¬ SetAMode[myMode, skip]; DoPops: PROC [] RETURNS [c: Code¬NIL] = { FOR i: INT IN [0..pops) DO c ¬ C2CEmit.Cat[c, C2CRunTime.PopHandler[], ";\n"]; ENDLOOP; }; WITH GetProp[myKeyForReturnBits] SELECT FROM i: REF INT => returnBits ¬ i­; ENDCASE => CantHappen; IF returnBits=0 THEN { FOR nodes: NodeList ¬ returnNode.rets, nodes.rest WHILE nodes#NIL DO IF nodes.first.bits#0 THEN CantHappen; cc1 ¬ GenNode[nodes.first, skipMode]; cc.sc ¬ Cat2[cc.sc, cc1.sc]; IF cc1.ec#NIL THEN CantHappen; ENDLOOP; cc.sc ¬ C2CEmit.Cat[cc.sc, DoPops[], "return;\n"] } ELSE IF returnBits<=C2CTarget.bitsPerWord THEN { retVal: Code ¬ NIL; mustUseTemporary: BOOL ¬ FALSE; IF pops#0 AND returnBits#0 THEN { retVal ¬ C2CEmit.IdentCode[C2CStateUtils.DeclareVariable[procedureDeclarations, C2CTarget.bitsPerWord, "temp"]]; mustUseTemporary ¬ TRUE; }; FOR nodes: NodeList ¬ returnNode.rets, nodes.rest WHILE nodes#NIL DO node: Node ¬ nodes.first; IF node.bits=0 THEN { cc1 ¬ GenNode[node, skipMode]; cc.sc ¬ Cat2[cc.sc, cc1.sc]; IF cc1.ec#NIL THEN CantHappen; } ELSE { m: Mode ¬ UseValue[node.bits, myMode]; IF node.bits#returnBits THEN CantHappen; cc1 ¬ GenNode[node, m]; FreeMode[m]; cc.sc ¬ Cat2[cc.sc, cc1.sc]; IF nodes.rest#NIL THEN { IF ~mustUseTemporary THEN { retVal ¬ C2CEmit.IdentCode[C2CStateUtils.DeclareVariable[procedureDeclarations, C2CTarget.bitsPerWord, "temp"]]; mustUseTemporary ¬ TRUE; }; }; IF mustUseTemporary THEN { cc1.ec ¬ C2CEmit.MinPrecedence[cc1.ec, assignPrecedence]; cc.sc ¬ C2CEmit.Cat[cc.sc, C2CEmit.CopyC[retVal], " = ", cc1.ec, ";\n"]; } ELSE retVal ¬ cc1.ec; }; ENDLOOP; cc.sc ¬ C2CEmit.Cat[cc.sc, DoPops[], "return(", retVal, ");\n"]; } ELSE { i: INT ¬ 0; FOR nodes: NodeList ¬ returnNode.rets, nodes.rest WHILE nodes#NIL DO nodeMode: Mode; node: Node ¬ nodes.first; IF (node.bits MOD C2CTarget.bitsPerWord)#0 THEN CantHappen; IF node.bits=0 THEN nodeMode ¬ SetAMode[myMode, skip] ELSE nodeMode ¬ UseValue[node.bits, myMode]; cc1 ¬ GenNode[node, nodeMode]; cc.sc ¬ Cat2[cc.sc, cc1.sc]; IF node.bits=0 THEN { IF cc1.ec#NIL THEN CantHappen; } ELSE { formalReturn: ROPE ¬ NARROW[GetProp[myKeyForFormalReturn]]; cc.sc ¬ C2CEmit.Cat[ cc.sc, IO.PutFR["%g[%g] = ", IO.rope[formalReturn], IO.int[i]], cc1.ec, ";\n" ]; i ¬ i+1; }; FreeMode[nodeMode]; ENDLOOP; cc.sc ¬ C2CEmit.Cat[cc.sc, DoPops[], "return;\n"]; }; C2CEmit.SetDead[cc.sc]; FreeMode[skipMode]; FreeMode[myMode]; }; GenGlobalFrame: PROC [] RETURNS [code: Code] = { name: ROPE ¬ C2CGlobalFrame.GlobalFrameName[]; code ¬ C2CEmit.Cat["&", name]; code ¬ C2CEmit.SetPrecedence[code, unaryPrecedence]; }; GenNakedOperNode: PROC [operNode: OperNode, mode: Mode] RETURNS [cc: CodeCont] = { NakedMesaOp: PROC [mesaOper: MesaOper, mode: Mode] RETURNS [cc: CodeCont] = { SELECT mesaOper.mesa FROM globalFrame => cc.ec ¬ GenGlobalFrame[]; unnamedError => cc.ec ¬ C2CEmit.IdentCode[C2CRunTime.nakedUnnamedError]; unwindError => cc.ec ¬ C2CEmit.IdentCode[C2CRunTime.nakedUnwindError]; abortedError => cc.ec ¬ C2CEmit.IdentCode[C2CRunTime.nakedAbortedError]; uncaughtError => cc.ec ¬ C2CEmit.IdentCode[C2CRunTime.nakedUncaughtError]; boundsError => cc.ec ¬ C2CEmit.IdentCode[C2CRunTime.nakedBoundsError]; narrowFault => cc.ec ¬ C2CEmit.IdentCode[C2CRunTime.nakedNarrowFault]; addr, all, equal, notEqual, nilck, alloc, free, fork, join, monitorEntry, monitorExit, notify, broadcast, wait, signal, error, unwind, resume, reject, copyGlobal, startGlobal, restartGlobal, stopGlobal, checkInit => CantHappenCedar; ENDCASE => CaseMissing; }; NakedCedarOp: PROC [cedarOper: CedarOper, mode: Mode] RETURNS [cc: CodeCont] = { SELECT cedarOper.cedar FROM procCheck => { NotYetImpl; --cedar oper proc check }; ENDCASE => CaseMissing; --mesa oper }; NakedCodeOp: PROC [codeOper: CodeOper, mode: Mode] RETURNS [cc: CodeCont] = { name: ROPE; label: Label ¬ codeOper.label; cast: ROPE ¬ C2CTypes.DefineFTypeCast[]; IF codeOper.offset#0 THEN CantHappenCedar; name ¬ C2CNames.LabName[codeOper.label.id, "Proc"]; cc.ec ¬ C2CEmit.Cat[" ((word) ", cast, name, ") "]; }; WITH operNode.oper SELECT FROM mesaOp: MesaOper => cc ¬ NakedMesaOp[mesaOp, mode]; cedarOp: CedarOper => cc ¬ NakedCedarOp[cedarOp, mode]; codeOp: CodeOper => cc ¬ NakedCodeOp[codeOp, mode]; ENDCASE => CantHappenCedar; }; GenModuleNode: PROC [moduleNode: ModuleNode, mode: Mode] = { cc1: CodeCont; gFrameCode: Code; IF GetProp[myKeyForModuleEncountered]#NIL THEN CantHappenCedar; PutProp[myKeyForModuleEncountered, $yes]; gFrameCode ¬ C2CGlobalFrame.GlobalFrameDeclarationCode[moduleNode]; C2CEmit.AppendCode[globalFrameDeclaration, gFrameCode]; C2CEmit.AppendCode[moduleContents, C2CEmit.CollectCode[procedureDeclarations]]; C2CEmit.AppendCode[moduleContents, C2CEmit.CollectCode[blockDeclarations]]; C2CEmit.AppendCode[moduleContents, C2CEmit.CollectCode[temporaryDeclarations]]; cc1 ¬ GenNodeList[nodeList: moduleNode.procs, mode: SetExpr[mode, FALSE], outsideTemporaryDecl: TRUE]; IF cc1.ec#NIL THEN CantHappen; C2CEmit.AppendCode[moduleContents, C2CEmit.CollectCode[procedureDeclarations]]; C2CEmit.AppendCode[moduleContents, C2CEmit.CollectCode[blockDeclarations]]; C2CEmit.AppendCode[moduleContents, C2CEmit.CollectCode[temporaryDeclarations]]; C2CEmit.AppendCode[moduleContents, cc1.sc]; }; sourceEnterMacro: ROPE ¬ C2CNames.Reserve["SOURCE"]; sourceProgName: ROPE ¬ C2CNames.Reserve["progName"]; enterFormat: ROPE ¬ Rope.Flatten[Rope.Concat[C2CEmit.noIndent, "%g(%g, %g)\n"]]; temporarySourcePos: REF TEXT ¬ RefText.New[11]; sourceStuffInitialized: BOOL ¬ FALSE; sourceAsMacro: BOOL ¬ FALSE; sourceInFile: BOOL ¬ FALSE; ResetSourceStuff: PROC [] = { sourceStuffInitialized ¬ FALSE }; InitSourceStuff: PROC [] = { sourceStuffInitialized ¬ TRUE; sourceAsMacro ¬ C2CAccess.params.generateSourceMacros; IF sourceAsMacro THEN { enterMacro: ROPE ¬ Rope.Concat["#define ", sourceEnterMacro]; IF C2CAccess.params.generateDBXStyleSourceMacros THEN enterMacro ¬ Rope.Cat[enterMacro, "(p, l)# 123/**/p/**/00 """, C2CNames.ProgramName[], ".mesa"" /* l */\n"] ELSE enterMacro ¬ Rope.Concat[enterMacro, "(p, l) /* source p, l */\n"]; C2CEmit.AppendCode[macroDeclarations, enterMacro]; sourceAsMacro ¬ TRUE; }; sourceInFile ¬ C2CAccess.params.generateLineNumberStream; IF sourceInFile THEN { temporarySourcePos.length ¬ 10; temporarySourcePos[0] ¬ C2CEmit.breakChar; }; }; DefineSourceEnter: PROC [] RETURNS [name: ROPE] = INLINE { name ¬ sourceEnterMacro; }; GenSourceNode: PUBLIC PROC [sourceNode: SourceNode, mode: Mode] RETURNS [cc: CodeCont] = { whiteSpace: BOOL; IF ~sourceStuffInitialized THEN InitSourceStuff[]; cc ¬ GenNodeList[nodeList: sourceNode.nodes, mode: mode, outsideTemporaryDecl: FALSE]; IF sourceNode.source=IntCodeDefs.nullSourceRange THEN RETURN; IF sourceNode.source.file#0 THEN RETURN; --file change! IF cc.ec#NIL OR cc.xbc#NIL THEN RETURN; --position would not be exact, better ommit whiteSpace ¬ ~C2CEmit.NonWhiteSpace[cc.sc]; IF whiteSpace THEN RETURN; --I fear those positions might be duplicated and cause problems IF sourceNode.source.chars=0 THEN RETURN; --Just to avoid problems BEGIN wasDead: BOOL ¬ C2CEmit.GetIsDead[cc.sc]; outerSourcePosition: IntCodeDefs.SourceNode ¬ C2CSourcePositions.currentSourceNode; C2CSourcePositions.currentSourceNode ¬ sourceNode; IF outerSourcePosition#NIL AND outerSourcePosition.source = sourceNode.source THEN RETURN; --avoid identical ranges; at least where direct and easy IF sourceAsMacro THEN { enter: Rope.ROPE ¬ IO.PutFR[enterFormat, [rope[DefineSourceEnter[]]], [integer[sourceNode.source.start]], [integer[sourceNode.source.chars]]]; cc.sc ¬ C2CEmit.Cat[enter, cc.sc]; }; IF sourceInFile THEN { enter, exit: Rope.ROPE ¬ NIL; start: INT ¬ sourceNode.source.start; chars: INT ¬ sourceNode.source.chars; temporarySourcePos[2] ¬ 0C + start / 100000000B MOD 256; temporarySourcePos[3] ¬ 0C + start / 200000B MOD 256; temporarySourcePos[4] ¬ 0C + start / 256 MOD 256; temporarySourcePos[5] ¬ 0C + start MOD 256; temporarySourcePos[6] ¬ 0C + chars / 100000000B MOD 256; temporarySourcePos[7] ¬ 0C + chars / 200000B MOD 256; temporarySourcePos[8] ¬ 0C + chars / 256 MOD 256; temporarySourcePos[9] ¬ 0C + chars MOD 256; temporarySourcePos[1] ¬ '#; enter ¬ Rope.FromRefText[temporarySourcePos]; temporarySourcePos[1] ¬ '%; exit ¬ Rope.FromRefText[temporarySourcePos]; cc.sc ¬ C2CEmit.Cat[enter, cc.sc, exit]; }; IF whiteSpace THEN cc.sc ¬ C2CEmit.SetWhiteSpace[cc.sc]; IF wasDead THEN C2CEmit.SetDead[cc.sc]; C2CSourcePositions.currentSourceNode ¬ outerSourcePosition; END; }; GenCommentNode: PUBLIC PROC [commentNode: CommentNode, mode: Mode] RETURNS [code: Code¬NIL] = { code ¬ C2CEmit.Cat[C2CEmit.CComment[commentNode.bytes]]; IF ~ExpMode[mode] THEN { code ¬ C2CEmit.Cat[C2CEmit.line, code, C2CEmit.line]; }; code ¬ C2CEmit.SetWhiteSpace[code]; }; magic: Rope.ROPE ¬ "/* Generated with C2C (Cedar To C)*/\n"; copyright: Rope.ROPE ¬ Rope.Flatten[IO.PutFR1["/* Copyright (C) %g by Xerox Corporation. All rights reserved. */\n", IO.int[BasicTime.Unpack[BasicTime.Now[]].year]]]; UseReferenceCounting: PROC [] RETURNS [use: BOOL] = { RETURN [C2CAccess.params.supportReferenceCounting] }; C2CRoot: PUBLIC PROC [] RETURNS [code: Code] = { GenMain: PROC [node: Node] = { maincc: CodeCont; progName: ROPE ¬ C2CNames.ProgramName[]; firtProcName: ROPE; moduleInitCode, mainCode: Code ¬ NIL; C2CEmit.AppendCode[moduleHeader, magic]; C2CEmit.AppendCode[moduleHeader, copyright]; C2CEmit.AppendCode[moduleHeader, IO.PutFR1["/* time: %g */\n", IO.time[]]]; C2CEmit.AppendCode[moduleHeader, Rope.Cat["/* C2C version: ", C2CBasics.c2cVersion, " */\n"] ]; IF ~UseReferenceCounting[] THEN { C2CEmit.AppendCode[moduleHeader, "/* ref-counting: off */\n"]; }; BEGIN header: Rope.ROPE ¬ IO.PutFR["file: %g, module: %g", [rope[C2CAccess.params.fileName]], [rope[C2CAccess.params.moduleName]]]; C2CEmit.AppendCode[moduleHeader, C2CEmit.Cat[C2CEmit.CComment[header], "\n"]]; END; FOR rl: LIST OF Rope.ROPE ¬ C2CAccess.params.commentLines, rl.rest WHILE rl#NIL DO C2CEmit.AppendCode[moduleHeader, C2CEmit.Cat[C2CEmit.CComment[rl.first], "\n"]]; ENDLOOP; C2CEmit.AppendCode[typeDeclarations, C2CTarget.definitions]; C2CRunTime.IncludeInstallationSupport[]; C2CRunTime.IncludeCedarExtra[]; maincc ¬ GenNode[node, skipMode]; IF maincc.ec#NIL THEN CantHappen; WITH GetProp[myKeyForFirstProc] SELECT FROM r: ROPE => firtProcName ¬ r; ENDCASE => ERROR CantHappen; moduleInitCode ¬ C2CEmit.Cat[ Rope.Cat["extern void ", C2CRunTime.install, "_", progName], Rope.Concat["() {", C2CEmit.nestNLine], C2CEmit.CollectCode[moduleInitializations], Rope.Cat[C2CEmit.line, firtProcName, "();\n}", C2CEmit.unNestNLine], ]; C2CEmit.AppendCode[moduleContents, maincc.sc]; C2CEmit.AppendCode[moduleContents, moduleInitCode]; OuterInstallation[progName]; }; moduleHC, moduleDC, moduleDCP, typeDC, macroDC, procsC, userTypesC, globalFrameC: Code; C2CPreprocessing.EliminateSideEffectsOfErrors[]; CountUsageOfStrings[]; GenMain[C2CBasics.rootNode]; BEGIN --version processing; versionDeclC: Code; prefix: ROPE ¬ Rope.Concat["@", "(#)"];--prevent finding string in compiler source itself version: ROPE ¬ C2CAccess.params.versionStamp; moduleName: ROPE ¬ C2CAccess.params.moduleName; IF version#NIL THEN { versionVar: ROPE ¬ C2CNames.TryName["versionStamp"]; versionDeclC ¬ C2CEmit.Cat["static char ", versionVar, "[] = ", C2CCodeUtils.CString[IO.PutFR["%gmob_version %g %g", IO.rope[prefix], IO.rope[version], IO.rope[moduleName]]], ";\n"]; } ELSE { versionVar: ROPE ¬ C2CNames.TryName["c2cTime"]; versionDeclC ¬ C2CEmit.Cat["static char ", versionVar, "[] = ", C2CCodeUtils.CString[IO.PutFR["%gc2c_time [%g] %g", IO.rope[prefix], IO.time[], IO.rope[moduleName]]], ";\n"]; }; C2CEmit.AppendCode[moduleHeader, versionDeclC]; END; moduleHC ¬ C2CEmit.CollectCode[moduleHeader, TRUE]; typeDC ¬ C2CEmit.CollectCode[typeDeclarations, TRUE]; macroDC ¬ C2CEmit.CollectCode[macroDeclarations, TRUE]; moduleDCP ¬ C2CEmit.CollectCode[moduleDeclarationsP, TRUE]; moduleDC ¬ C2CEmit.CollectCode[moduleDeclarations, TRUE]; procsC ¬ C2CEmit.CollectCode[moduleContents, TRUE]; userTypesC ¬ C2CEmit.CollectCode[userTypeDeclaration, TRUE]; globalFrameC ¬ C2CEmit.CollectCode[globalFrameDeclaration, TRUE]; code ¬ C2CEmit.Cat[moduleHC, C2CEmit.line, typeDC, C2CEmit.line]; code ¬ C2CEmit.Cat[code, macroDC, C2CEmit.line, moduleDCP, C2CEmit.line]; code ¬ C2CEmit.Cat[code, moduleDC, C2CEmit.line, globalFrameC, C2CEmit.line]; code ¬ C2CEmit.Cat[code, userTypesC, C2CEmit.line, procsC, C2CEmit.line]; C2CBasics.Report[]; }; OuterInstallation: PROC [progName: ROPE] = { st: IO.STREAM ¬ IO.ROS[]; pre: ROPE ¬ C2CTarget.runtimePrefix; gf: ROPE ¬ C2CGlobalFrame.GlobalFrameName[]; C: PROC [r1, r2, r3: ROPE¬NIL] = { IO.PutRope[st, r1]; IO.PutRope[st, r2]; IO.PutRope[st, r3]; }; C["extern void ", pre, "run_"]; C[progName, "() { ", pre]; C["Start(&", gf, "); }\n"]; C2CEmit.AppendCode[moduleContents, C2CEmit.RopeCode[IO.RopeFromROS[st]]]; }; C2CBasics.CallbackWhenC2CIsCalled[ResetGlobalSmallConstantsTable]; C2CBasics.CallbackWhenC2CIsCalled[ResetSourceStuff]; END. Ž C2CMainImpl.mesa Copyright Ó 1987, 1988, 1989, 1990, 1991, 1992, 1993 by Xerox Corporation. All rights reserved. Christian Jacobi, 1987 Christian Jacobi, January 25, 1993 7:14 pm PST Russ Atkinson (RRA) January 14, 1988 6:15:51 pm PST JKF May 25, 1990 9:25:06 am PDT Willie-s, September 24, 1991 6:12 pm PDT Michael Plass, September 27, 1991 1:46 pm PDT --"statement" nodes --outsideTemporaryDecl: Set FALSE in doubt --given an identifier, returns statement-code assigning the bit address into a template --bitOffset bits from left --given an identifier, returns statement-code assigning the address into a template --assumes precedence high enough --declares an word constant and returns its name --right adjusted in word Generate a constant but only assign the value at run time. Because C strings do not fullfill eventuel alignment conditions. --split large string into small pieces to prevent blowing up the C compiler --for alignments not bigger than single word input parameter has Cedar syntax for floating point literal return parameter has C syntax for floating point literal input parameter has Cedar syntax for double precision floating point literal return parameter has C syntax for double precision floating point literal --check whether we already have this string --nice'n easy string literals --branch independent of actual alignment condition so we can allways reuse template --addr cast and deref so we get the canonical type --actually called from inside decl node, block node --and from module node --it may and we do declare it as pointer, so it is put into an address register... --initialize right in declaration --no casting: const is simple --make separate statement for initialization --rely on preprocessing for eliminating "frequent" if troubles would arise nodeList applied in context of if statement only [so position of boolean bit canm be ignored] --last case SIZE PROBLEM elsecc _ GenNode[node: cases.body, mode: mode]; --other case SIZE PROBLEM bodycc _ GenNode[node: cases.body, mode: mode]; --returns switchVar#NIL if a switch statement can be used --check operation --check constant --check variable --possibly machine dependent: not every C allows unsigned switch statements --Label for a procedure. --Ordinary label --Unlabeled lambda node! How do we get here, and what can we do about it? -- I guess I could make up labels and call GenLambdaNodeWithLabels. --contains names of pointers for indirectly passed things --generates the list naming the formals --generates the list declaring the named formals --generates declaration for formals which are copied; including code Hint: there are return nodes with 0 size! these nodes need to be executed before the return --returnBits>C2CTarget.bitsPerWord --Mostly oper nodes are applied, and as such are handled inside GenApplyNode. --Should always be applied: --The mesa language does not have the primitives to use as value --the other operators are not allowed to be naked sourceExitMacro: ROPE _ C2CNames.Reserve["SOURCEPOP"]; --Not used Find out whether the ref counting primitives ought to be used. Sorry, we put the burden inside here instead of C2CRuntime because that allows ommiting the typecodes. ÊDÀ•NewlineDelimiter –(cedarcode) style™šœ™Icodešœ ÏeœU™`Kšœ™K™.K™3K™K™(K™-K˜šÏk ˜ Kšœ ˜ Kšœ ˜ Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ ˜ Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ Kšœ ˜ Kšœ˜Kšœ˜Kšœ ˜ Kšœ ˜ Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšžœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜——šÏn œžœž˜Kšžœžœ ˜¸Kšžœ ˜—šž˜Kšžœ3˜7K˜—Kšžœžœžœ˜Kšœžœžœ˜$Kšœ3žœžœ ˜PKšœžœ&˜?K˜Kš œžœžœžœžœÏc˜/Kš œžœžœžœžœ ˜7Kš œžœžœžœžœ ˜2Kš œžœžœžœžœ ˜0K˜šŸœžœžœ˜/Kšžœžœžœžœ˜Kšžœžœžœžœ˜Kšžœ˜Kšœ˜—K˜š Ÿ œžœDž œžœžœžœ˜¢Kš ™Kš *™*Kšœžœ˜Kšœ˜Kšœ˜Kšœ&˜&Kšœžœ˜KšœCžœžœ˜Pšžœ4žœžœž˜IKšœ žœžœ˜Kšœ˜Kšœ˜Kšœ žœ˜Kšžœžœžœ$˜5šžœ žœ(žœ˜J–1.2 in tabStopsš S™SJ–1.2 in tabStopsš  ™ Kšœ žœ˜#Kšžœžœ ˜+Kšœ-˜-Kšœ˜—K˜šŸœžœ žœžœ˜+K–1.2 in tabStopsšœžœ˜#šžœžœ ˜Kšžœžœžœžœ ˜3Kšžœžœ6˜A—K˜—K˜šœ.˜.šŸœžœ˜+Kšœ3˜3Kšœ˜——K˜šŸœžœ žœžœ˜K–1.2 in tabStopsšžœ0žœ˜Q——Kšžœ˜—Kšœ*˜*Kšžœ˜K˜—Kšœ'˜'Kšœ,˜,Kšœ˜—K˜šŸœžœžœ žœ žœžœžœ˜QK–1.2 in tabStopsšœ:™:K–1.2 in tabStopsšœ@™@K–1.2 in tabStopsšœžœžœ#˜GK–1.2 in tabStopsšœžœ˜K–1.2 in tabStopsšœ ˜ K–1.2 in tabStopsšœ&˜&K–1.2 in tabStopsšœ6˜6K–1.2 in tabStopsšœ-˜-K–1.2 in tabStopsš K™K–1.2 in tabStopsšžœ ž˜K–1.2 in tabStopsšœ žœžœ˜3–1.2 in tabStopsšœžœ˜ –1.2 in tabStopsšžœ ˜ K–1.2 in tabStopsšžœ˜K–1.2 in tabStopsšžœžœžœ žœ ˜A——–1.2 in tabStopsšœ'˜'K–1.2 in tabStopsšœe˜eK–1.2 in tabStopsšœ˜K–1.2 in tabStopsšœ˜K–1.2 in tabStopsšœ˜—K–1.2 in tabStopsšœA˜AK–1.2 in tabStopsšœ˜K–1.2 in tabStopsšœ˜K–1.2 in tabStopsšžœ˜—K˜—K˜šŸœžœžœ žœ žœžœžœ˜SKš ,™,šŸœžœžœžœ˜*Kšœžœ˜Kšžœ)žœ ˜;Kšžœžœžœžœ ˜4š žœžœžœ%žœ  ˜?Kšœ˜Kšžœžœ žœ ˜PKšžœ˜—K˜—Kšœ žœ˜Kšœžœ!˜,Kšœžœ˜ Kšœ'˜'Kšœ'žœ˜;šžœ(žœ˜0Kšœžœ%žœ žœ˜TKšœ˜—šžœžœžœ˜+KšœžœL˜VKš œžœDžœžœ-žœ žœžœ˜¸K˜—šžœ˜Kšœ žœ˜Kšœžœ"˜,Kšœ,˜,šžœž˜Kšœ žœžœ%˜;Kš œžœžœžœžœ˜hKšœ˜Kšœ˜Kšžœ˜—Kš œ'žœžœ žœžœ˜|Kšœ'˜'šžœž˜Kšœ žœžœ%˜;Kš œžœžœ žœ(žœ˜iKšœžœžœžœ˜IKšœ#˜#Kšžœ˜—Kšœžœžœžœ˜UKšœ˜—KšœA˜AK˜—K˜šŸ œžœžœžœ˜4šžœžœž˜'Kšœžœ˜ šžœ˜ Kšœ&žœ˜-Kšœ˜Kšžœ˜ Kšœ˜——Kšœ˜K˜—šŸœžœžœžœ˜KKšœ;™;Kšœ8™8Kšžœ ˜Kšœ˜K˜—šŸœžœžœžœ˜KKšœL™LKšœI™IKšžœ ˜Kšœ˜K˜—Kšœžœžœ˜ K˜šŸ œžœžœžœžœžœžœ˜Nšžœ˜šžœ˜Kšœ#˜#Kšœ1˜1KšœR˜RK˜—šžœ˜Kšœ ˜ Kšœ žœ ˜-Kšœžœ˜*Kšœ1˜1KšœS˜SKšœD˜DKšœ4˜4KšœL˜LK˜——K˜K˜—šŸœžœžœ˜OKšœ žœ˜Kšœ1˜1Kšœžœ'˜0šžœžœž˜+Kšœžœ˜šžœ˜ Kšœ>˜>Kšœ&˜&Kšœ˜——šžœ˜šžœ˜šœ˜Kšœ1˜1Kšœ"˜"Kšœ˜—K˜—Kšžœ%˜)—Kšœ˜K˜—šŸœžœžœ˜OKšœ žœ˜Kšœ,˜,Kšœžœ'˜0šžœžœž˜+Kšœžœ˜šžœ˜ KšœE˜EKšœ&˜&Kšœ˜——šžœ˜šžœ˜šœ˜Kšœ1˜1Kšœ(˜(Kšœ˜—K˜—Kšžœ%˜)—K˜—K˜šŸ œžœžœ$žœ˜WKšœ/˜/Kšžœ žœ ˜–1.2 in tabStopsšžœ žœž˜–1.2 in tabStopsšœ˜–1.2 in tabStopsšžœž˜K–1.2 in tabStopsšœK˜K–1.2 in tabStops˜K–1.2 in tabStopsšœ.˜.K–1.2 in tabStopsšœ8˜8K–1.2 in tabStopsšœ˜—–1.2 in tabStopsšœ ˜ K–1.2 in tabStopsšœ5˜5K–1.2 in tabStopsšœ.˜.K–1.2 in tabStopsšœ1˜1K–1.2 in tabStopsšœ˜—–1.2 in tabStopsšœ˜K–1.2 in tabStopsšœ žœ'˜5K–1.2 in tabStopsšœM˜MK–1.2 in tabStops˜—–1.2 in tabStopsšœ˜K–1.2 in tabStopsšœ žœ'˜5K–1.2 in tabStopsšœ6˜6–1.2 in tabStopsšžœ&žœ˜.K–1.2 in tabStopsšœC˜CK–1.2 in tabStops˜—K–1.2 in tabStops˜—K–1.2 in tabStopsšœ&˜&K–1.2 in tabStopsšžœ˜—K–1.2 in tabStopsšœ˜—–1.2 in tabStopsšœ˜K–1.2 in tabStopsšœžœ˜ K–1.2 in tabStopsšœžœ"˜BK–1.2 in tabStopsšœžœžœ-˜T–1.2 in tabStopsšœžœžœ˜"K–1.2 in tabStopsšžœ˜K–1.2 in tabStopsšžœ˜—K–1.2 in tabStopsšžœžœžœ ˜J–1.2 in tabStopsš +™+K–1.2 in tabStopsšžœ žœžœ˜(–1.2 in tabStopsšžœ˜K–1.2 in tabStopsš ™–1.2 in tabStopsšžœžœžœ0ž˜\–1.2 in tabStopsšžœž˜–1.2 in tabStopsšœ ˜ K–1.2 in tabStopsšœ=˜=K–1.2 in tabStopsšœ$˜$K–1.2 in tabStopsšžœ˜K–1.2 in tabStopsšœ˜—–1.2 in tabStopsšœ ˜ K–1.2 in tabStopsšœ=˜=K–1.2 in tabStopsšžœ˜K–1.2 in tabStopsšœ˜—K–1.2 in tabStopsšžœ˜——K–1.2 in tabStopsšœT™T–1.2 in tabStopsšžœ0žœ(˜]–1.2 in tabStopsšžœ˜K–1.2 in tabStopsšœ/˜/K–1.2 in tabStops˜—–1.2 in tabStopsšžœ˜K–1.2 in tabStopsšœ-˜-K–1.2 in tabStops˜——K–1.2 in tabStopsšœ˜K–1.2 in tabStops˜—–1.2 in tabStopsšžœž˜–1.2 in tabStops˜K–1.2 in tabStopsšœ2™2K–1.2 in tabStopsšœ@žœ˜W—K–1.2 in tabStopsšœ=žœ˜CK–1.2 in tabStopsšœ4˜4K–1.2 in tabStopsšœ+˜+K–1.2 in tabStopsšœ˜K–1.2 in tabStopsšœ˜K–1.2 in tabStopsšžœ˜—K–1.2 in tabStopsšœ˜—K–1.2 in tabStopsšœ+ ˜B–1.2 in tabStopsšœ žœ˜-–1.2 in tabStopsšžœž˜!–1.2 in tabStopsšœžœžœž˜K–1.2 in tabStopsšœa˜aK–1.2 in tabStopsšœg˜gK–1.2 in tabStopsšžœ˜—K–1.2 in tabStopsšžœ˜—–1.2 in tabStopsšžœž˜K–1.2 in tabStopsšœ˜K–1.2 in tabStopsšžœP˜W—K–1.2 in tabStopsšœ˜—K–1.2 in tabStopsšžœ˜—K˜Iimp˜—Kšœ žœ5˜EKšœ žœ8˜GK˜šŸ œžœžœ$žœ˜WK–1.0 in tabStopsšœ$žœ˜(–1.0 in tabStopsšœ žœ˜šžœ˜Kšžœž˜ šžœžœž˜Kšœ0žœ˜6Kšžœžœ˜———šžœ ˜šžœ˜Kšœ7˜7Kšœ:˜:Kšœ˜—šžœ˜Kšœžœ˜Kšžœžœžœ*˜JKšœ˜——K–1.0 in tabStopsšœ[˜[–1.0 in tabStopsšžœ žœ˜K–1.0 in tabStopsšœ6˜6K–1.0 in tabStopsšœ:˜:–1.0 in tabStopsš žœžœžœžœžœ˜#K–1.0 in tabStopsšœ žœ žœžœ˜8K–1.0 in tabStopsšœB˜BK–1.0 in tabStopsšžœ žœ˜'K–1.0 in tabStops˜—K–1.0 in tabStopsšœ5˜5K–1.0 in tabStopsšœ8˜8K–1.0 in tabStops˜—K˜K˜—šŸ œžœžœžœ˜GKš žœ žœžœžœžœ˜%šžœžœž˜!Kšœ#žœžœ˜1Kšžœžœžœ˜—Kšœ˜K˜—šŸœžœžœžœžœžœžœ˜xKš 4™4Kš ™š Ÿœžœ;žœžœžœ˜ršŸ œ œžœžœ˜RKšœžœ˜Kšžœžœ4˜QK˜—Kšœ˜šžœžœžœ˜Kšžœžœ ˜&šžœžœ žœ*žœ˜kKš R™RKšœ3˜3Kšžœžœžœ ˜Kšœ8˜8KšœA˜AK˜—šžœžœžœ(žœ˜KKš !™!Kš ™Kšœ3˜3Kšžœžœžœ ˜Kšœ*˜*Kšœ˜—šžœ˜Kš ,™,Kšœ˜Kšœ˜Kšœ(˜(Kšœ8˜8Kšœ˜Kšžœžœžœ ˜Kšœ˜—K˜—K˜—š Ÿœžœžœžœžœ˜>šžœžœžœ ž˜3šžœžœž˜˜šžœ žœž˜˜šžœ žœž˜šœ˜šžœ ž˜Kšœ žœ˜Kšžœ˜——Kšžœ˜——Kšžœ˜——˜šžœ žœž˜šœ˜šžœ ž˜Kšœžœ˜Kšžœ˜——Kšžœ˜——Kšžœ˜ ——K˜—Kšœžœ˜ Kšœ žœžœ˜Kšœžœ˜Kšœžœ%˜,Kšœžœ˜%Kšœžœ ˜šžœ žœ*ž˜SKšœ˜—š žœžœžœ!žœ žœ˜kKš J™JKšœ&˜&Kšœ/˜/K˜—Kšœ9˜9šžœžœž˜šœ'˜'Kšžœžœ˜Kšœ žœ˜Kšœ%˜%Kšžœ#žœžœžœ ˜VKšžœ?žœ ˜QKšœSžœ˜YKšœ"˜"šžœ žœ˜KšœŠ˜Š—Kšœ˜—šœ)˜)Kšžœ žœ˜ Kšœ žœ˜Kšœ0˜0KšœSžœ˜YKšœ"˜"šžœ žœ˜Kšœ‹˜‹—Kšœ˜—šœ!˜!KšœP˜Pšžœžœžœ˜KšœSžœ˜Z—Kšœ!˜!K˜—Kšœ2˜2Kšœ6˜6Kšœ.˜.Kšœ0˜0Kšœ0˜0Kšœ4˜4Kšœ4˜4Kšœ8˜8Kšœ2˜2Kšœ0˜0Kšžœ˜—šžœžœžœ˜šžœ˜ Kšžœ1˜5Kšžœ.˜2—K˜—K˜—K˜š Ÿ œžœžœ"žœ žœ˜VKšœS˜SKšœ˜K˜—šŸœžœ"žœžœ˜Zšžœ žœž˜Kšœ˜Kšœ˜Kšžœ˜—K˜—K˜K˜š Ÿ œžœ0žœžœžœ˜kKšœžœžœ˜$K˜Kšœ žœ3˜DKšœk˜kKšžœ žœ žœ˜ Kšžœžœ˜+KšœOžœ˜VKšœ2˜2Kšžœžœžœ ˜Kšžœžœ˜+˜K˜——K˜šŸ œžœžœ"žœ˜TK˜šŸœžœžœž œ˜DKš žœžœžœžœžœ˜Cšžœ˜Kšœ5˜5šžœ ž˜šœ˜Kšžœ+˜1Kšœ˜—Kšœ'žœžœ˜6Kšžœ˜—K˜—K˜—K˜šŸ œžœ"žœžœ˜dKšœ]™]šŸœžœ"žœž œ˜Ršžœ"žœžœž˜4Kšžœ)žœžœžœ˜>Kšž˜—K˜—Kšœ žœžœ˜šžœ"žœžœž˜4Kšœ˜Kšœ žœ(˜6Kšžœ žœ(žœžœ˜CKšœ5˜5Kšžœ žœ˜(Kšžœžœžœ˜/šžœ ˜ Kšžœ˜KšžœC˜G—Kšœ žœ˜šžœžœ˜%Kšžœ žœžœ,˜AKšœF˜FKšœ)˜)Kšœ;˜;Kšœžœ˜ Kšœ žœ˜Kšœ˜—Kšžœ˜—Kšœ:˜:Kšœ˜—K˜šŸœžœ˜Kšœžœ ˜+Kšœ ˜ šžœ:žœžœž˜Ošžœ žœžœ˜Kš  ™ Kšœ˜Kšžœ žœžœ ˜"šœ:˜:Kšœ<™<—KšœF˜FKšžœ žœžœ ˜!Kšœ$˜$K˜—šžœ˜Kš  ™ Kšœ%žœžœ˜0Kšœ;˜;Kšžœ žœžœ ˜!Kšžœ"žœ  Ðbc˜OKšœ>˜>šœ:˜:Kšžœžœ0™<—Kšžœ"žœ  ¡˜OKšœF˜FKšœ<˜Kšžœ žœžœžœ˜ šžœžœž˜šœ˜Kšœ žœ žœ˜Kš ™Kš žœžœžœžœžœ˜)Kšžœ žœžœžœžœžœžœžœžœ˜Yšžœ žœž˜šœ˜šžœ žœž˜šœ˜Kšžœ/žœžœžœ˜EKšžœžœžœžœ˜(šžœž˜Kšœ˜Kšžœžœžœ˜—Kšœ˜—Kšžœžœžœ˜——Kšžœžœžœ˜—Kš ™KšœK˜KKšžœ žœžœžœ˜ Kš žœ žœ'žœžœžœ˜eKš ™šžœžœž˜!šœ ˜ šžœ žœ˜šžœ˜Kšžœžœžœžœ˜+K˜—šžœ˜Kšžœ žœžœžœ˜6Kšœ˜K˜——K˜—Kšžœžœžœ˜—K˜—Kšžœžœžœ˜—K˜—šžœ:žœžœž˜Ošžœ žœžœ˜šžœ%žœžœž˜7Kšœžœ˜&Kšœ˜Kšžœ žœžœžœ˜Kšž˜—K˜—Kšžœ˜—Kšžœ žœžœžœ˜ Kšœ˜—K˜šŸœžœ˜2Kšœ žœžœ˜Kšœ žœžœ˜Kšœ@˜@Kšœ˜KšœI˜Išžœ:žœžœž˜Ošžœ žœ˜šžœ˜Kšœ)˜)Kšœ ž˜Kšœ˜—šžœ˜šžœ%žœžœž˜7šžœ žœž˜šœ˜KšœM™MKšœžœ<˜EKšœžœžœ ˜AK˜—Kšžœžœ˜—Kšž˜—K˜——Kšœ.˜.Kšœ,˜,Kšœžœžœžœ ˜;šžœ˜Kšžœ0˜4šžœ˜Kšœ:˜:Kšœ žœ˜Kšœ˜——Kšžœ˜—Kšœ6˜6Kšžœ žœ žœ˜8Kšœ˜—K˜šŸœžœ˜!Kšœ˜Kšœ žœžœ˜Kšœžœ˜Kšœ žœžœ˜#Kšœ žœžœ˜šžœ:žœžœž˜OKšœ žœžœ˜!Kšœ žœ˜šžœ žœ˜Kšœ˜Kšœ8˜8K˜—šžœ žœ˜šžœ˜Kšœžœžœ˜(Kšœ;˜;Kšœ˜KšœN˜NKšœ žœ˜KšœF˜Fšžœ žœž˜Kšœ/˜/—Kšœ˜——Kšœ,˜,Kšžœ žœžœ žœ˜?Kšœ#˜#Kšžœžœžœ ˜šžœ žœ˜šœ ˜ Kš œžœ žœžœžœ˜!Kšœ˜Kšœ˜—K˜—Kšœ žœ˜Kšžœ˜—šžœžœžœž˜"Kšœ6˜6Kšžœ˜—Kšžœ žœ žœ˜6K˜K˜—šŸœžœ˜%Kšœ˜Kšœžœ˜Kšœ žœ#˜1Kšœžœžœ˜Kšœ žœžœ˜#Kšœžœžœ˜šžœ:žœžœž˜OKšœžœ˜ šžœ žœžœ˜Kšœžœžœ˜(Kšœ;˜;Kšœ˜KšœN˜NKšœžœ˜ KšœF˜Fšžœ žœž˜Kšœ/˜/—Kšœ˜—Kšœ,˜,Kšžœ žœžœ žœ˜?Kšœ#˜#Kšžœžœžœ ˜šžœžœ˜#Kšœ5˜5Kšœ žœ˜Kšœžœ˜Kšœ˜—šžœžœ˜ Kšœ6˜6—Kšžœ˜—Kšžœžœ/˜DKšžœ žœžœ˜1K˜—K˜šŸ œžœ"žœž œ˜JKšœžœ˜ šžœ,žœžœž˜=Kšžœžœžœžœ˜&Kšž˜—K˜K˜—šŸ œžœ˜Kšœ,˜,šžœžœž˜Kšœ žœ'˜4Kšœ9˜9Kšžœ˜"—K˜—K˜Kšœ2˜2Kšžœžœ ˜!šžœž˜Kšœ@˜@˜Kšžœ!žœ ˜2šžœ˜Kšœžœ*˜3Kšœ žœD˜RKšœ:˜:Kšžœžœžœ ˜Kšœ$˜$K˜—Kšœ˜—šœ ˜ Kšžœ!žœ ˜2šžœ˜Kšœ žœV˜dKšœ3˜3Kšžœžœžœ ˜Kšœ$˜$K˜—Kšœ˜—Kšžœ˜—Kšœ˜K˜—šŸ œžœžœ$žœ˜Wšžœžœž˜%˜Kš ™Kšœ3˜3Kšœ&˜&Kšœ8˜8Kšœ(˜(K˜—šžœ˜ Kš ™šžœ"ž˜(KšœU˜U—šžœžœžœ˜"KšœH˜HKšœ˜Kšžœžœžœ ˜K˜—K˜——K˜—K˜š Ÿ œžœžœ"žœ žœ˜VKšœžœ˜ šžœž˜Kšœ ˜ Kšžœ˜—Kšœ1˜1Kšœ)˜)šžœžœžœ/ž˜>Kšœ9˜9Kšžœ˜—Kšœ˜K˜—K˜š Ÿ œžœžœ&žœ žœ˜\Kš J™JKš C™CKšœ˜K˜—K˜šŸœžœžœ?˜cKšœ˜Kšœžœžœžœ ˜(šœ9˜9Kš 9™9—K˜šŸ œžœžœžœ˜DKš '™'Kšžœžœ ˜!šžœ$žœžœž˜8Kšœ˜Kšœžœ2˜<šžœžœ˜#šžœžœž˜šœ˜Kšžœ5žœ ˜G—Kšžœ˜—Kšœ˜—šžœ+˜-šžœ˜Kšœ ˜ Kšœ˜—šžœ˜Kšœ žœ1˜>Kšœ$˜$Kšœ5˜5K˜——Kšžœ žœžœ"˜7Kšžœ˜—K˜—K˜šŸ œžœžœ žœ˜AKš 0™0šžœ$žœžœž˜8Kšœ˜KšœA˜AKšœ ˜ šžœ˜šžœ˜Kšœ.žœžœ˜QK˜—šžœ˜Kšœžœ$˜/Kšœžœžœ˜6K˜——Kšœ,˜,Kšžœ˜—K˜—K˜šŸœžœžœ žœ˜NKš D™Dšžœ$žœžœž˜8Kšœ˜KšœA˜AKšžœžœž˜'šžœ˜Kšœ žœžœ˜Kšœ žœ1˜?Kšœ5žœžœ˜YKšœK˜Kšœ˜Kšœ˜šœ˜Kšœ"˜"Kšœ!˜!Kšœ( ˜DKšœ˜—K˜Kšœ˜—K˜—Kšžœ˜—K˜—K˜Kšœ˜Kšœ žœ˜Kš œžœžœ'žœ žœ ˜^Kšœ(˜(Kšœžœ˜šœžœ˜Kšžœžœ-žœ žœ ˜d—Kšœ,˜,Kšœžœ˜"Kšžœ$žœžœ ˜:Kšœžœžœ˜9šžœžœ˜"šžœ˜KšœK˜KKšœ%˜%K˜—šžœ˜KšœD˜DK˜——Kšœj˜jKšœZ˜Zšžœ*žœ˜2Kšœ9˜9Kšœ0˜0Kšœ3˜3Kšžœ žœžœ(˜>Kšœ˜—Kšœ+˜+Kšœ@˜@KšœC˜Cšžœ*žœ˜2KšœQ˜QKšœ˜—šœ˜Kšœ ˜ Kšœ,˜,Kšœ'˜'Kšœ+˜+Kšœ˜—KšœB˜BKšœ0˜0KšœRžœ/˜…Kšžœžœžœ ˜šœ˜Kšœ,˜,Kšœ(˜(Kšœ,˜,Kšœ ˜ Kšœ˜Kšœ˜—KšœH˜HKšœžœ˜#Kšœžœ˜!šœ˜Kšœ ˜ Kšœ,˜,Kšœ(˜(Kšœ,˜,Kšœ˜Kšœ˜—Kšœ*˜*Kšœ˜K˜K˜—šŸ œžœžœ&žœ˜ZKšœ[™[Kšœ˜Kšœ žœ˜Kšœžœ˜(Kšœžœ˜#Kšœ(˜(šŸœžœžœ žœ˜)šžœžœžœ ž˜Kšœ3˜3Kšžœ˜—Kšœ˜—šžœžœž˜,Kšœžœžœ˜Kšžœ˜—šžœžœ˜šžœ/žœžœž˜DKšžœžœ ˜&Kšœ%˜%Kšœ˜Kšžœžœžœ ˜Kšžœ˜—Kšœ1˜1K˜—šžœžœ#žœ˜0Kšœžœ˜Kšœžœžœ˜šžœžœžœ˜!Kšœp˜pKšœžœ˜K˜—šžœ/žœžœž˜DKšœ˜šžœ žœ˜Kšœ˜Kšœ˜Kšžœžœžœ ˜K˜—šžœ˜Kšœ&˜&Kšžœžœ ˜(Kšœ$˜$Kšœ˜šžœ žœžœ˜šžœžœ˜Kšœp˜pKšœžœ˜K˜—K˜—šžœ˜šžœ˜Kšœ9˜9KšœH˜HK˜—Kšžœ˜—K˜—Kšžœ˜—Kšœ@˜@K˜—šžœ˜Jš "™"Kšœžœ˜ šžœ/žœžœž˜DKšœ˜Kšœ˜Kšžœ žœžœ ˜<šžœ ˜Kšžœ$˜(Kšžœ*˜.—Kšœ˜Kšœ˜šžœ ˜šžœ˜Kšžœžœžœ ˜K˜—šžœ˜Kšœžœžœ ˜;šœ˜Kšœ˜Kšžœžœžœ ˜8Kšœ˜Kšœ˜Kšœ˜—Kšœ˜K˜——Kšœ˜Kšžœ˜—Kšœ2˜2K˜—Kšœ˜Kšœ˜Kšœ˜K˜K˜—šŸœžœžœ˜0Kšœžœ$˜.Kšœ˜Kšœ4˜4Kšœ˜—K˜šŸœžœ"žœ˜RJš O™OK˜šŸ œžœ"žœ˜Mšžœž˜Kšœ(˜(KšœH˜HKšœF˜FKšœH˜HKšœJ˜JKšœF˜FKšœF˜Fšœè˜èKš ™Kš @™@—Kšžœ˜—K˜—K˜šŸ œžœ$žœ˜Pšžœž˜šœ˜Kšœ  ˜#K˜—Kšžœ  ˜$—K˜—K˜šŸ œžœ"žœ˜NKšœžœ˜ Kšœ˜Kšœžœ˜(Kšžœžœ˜*Kšœ3˜3Kšœ3˜3K˜—K˜šžœžœž˜Kšœ3˜3Kšœ7˜7Kšœ3˜3Jš 1™1Kšžœ˜—K˜K˜—K˜šŸ œžœ*˜=Kšœ ˜ Kšžœ$žœžœ˜?Kšœ)˜)KšœC˜CKšœ7˜7KšœO˜OKšœK˜KKšœO˜OKšœBžœžœ˜fKšžœžœžœ ˜KšœO˜OKšœK˜KKšœO˜OKšœ+˜+K˜K˜—Kšœžœ˜4Kšœžœ,™AKšœžœ ˜4Kšœ žœ?˜PK˜Kšœžœžœ˜/Kšœžœžœ˜%Kšœžœžœ˜šœžœžœ˜šŸœžœ˜Kšœž˜Kšœ˜—šŸœžœ˜Kšœžœ˜Kšœ6˜6šžœžœ˜Kšœ žœ-˜=šžœ.˜0Kšžœl˜pKšžœD˜H—Kšœ2˜2Kšœžœ˜Kšœ˜—Kšœ9˜9šžœžœ˜Kšœ˜Kšœ*˜*Kšœ˜—K˜—š Ÿœžœžœžœžœ˜:Kšœ˜K˜——K˜K˜šŸ œžœžœ&žœ˜ZKšœ ž˜Kšžœžœ˜2KšœOžœ˜VKšžœ/žœžœ˜=Kšžœžœžœ ˜7Kš žœžœžœžœžœžœ +˜TKšœ+˜+Kšžœ žœžœ ?˜ZKšžœžœžœ ˜Bšž˜Kšœ žœ˜)KšœS˜SKšœ2˜2Kš žœžœžœ0žœžœ 8˜“šžœžœ˜Kšœ žœžœy˜ŽKšœ"˜"K˜—šžœžœ˜Kšœžœžœ˜Kšœžœ˜&Kšœžœ˜&Kšœ$Ïf œžœ˜:Kšœ$¢ œžœ˜:Kšœ$¢ œžœ˜:Kšœ$¢ œžœ˜:Kšœ#¢ œžœ˜9Kšœ#¢ œžœ˜9Kšœ#¢ œžœ˜9Kšœ"¢ œžœ˜8Kšœ˜Kšœ-˜-Kšœ˜Kšœ,˜,Kšœ(˜(K˜—Kšžœ žœ&˜8Kšžœ žœ˜'Kšœ;˜;Kšžœ˜—Kšœ˜K˜—K˜š Ÿœžœžœ(žœ žœ˜_Kšœ8˜8šžœžœ˜Kšœ5˜5K˜—Kšœ#˜#K˜—L˜L˜Kšœ žœ,˜™>K™gKšžœ-˜3Lšœ˜—K˜šŸœžœžœžœ˜0K˜šŸœžœ˜Kšœ˜Kšœ žœ˜(Kšœžœ˜Kšœ!žœ˜%Kšœ(˜(Kšœ,˜,Kšœ!žœžœ ˜Kšœ!˜!Kšœ;˜;Kšœ˜—šžœžœ˜!Kšœ>˜>Kšœ˜—šž˜Kšœ žœžœg˜}KšœN˜NKšžœ˜—š žœžœžœžœ*žœžœž˜RKšœP˜PKšžœ˜—Kšœ<˜