<<>> <> <> <> <> <> DIRECTORY C2CAddressing, C2CAddressingOps, C2CBasics, C2CDefs, C2CEmit, C2CIntCodeUtils, C2CCodeUtils, C2CMain, C2CMode, C2CStateUtils, C2CTarget, C2CTypes, IntCodeDefs, Convert, Rope; C2CAddressingOpsImpl: CEDAR MONITOR IMPORTS C2CBasics, C2CCodeUtils, C2CEmit, C2CIntCodeUtils, C2CMain, C2CMode, C2CStateUtils, C2CTarget, C2CTypes, Convert, Rope EXPORTS C2CAddressingOps = BEGIN OPEN IntCodeDefs, C2CBasics, C2CDefs, C2CMain, C2CMode; ROPE: TYPE = Rope.ROPE; LoadArithNode: PUBLIC PROC [node: IntCodeDefs.Node] RETURNS [cc: CodeCont] = { hasLab: BOOL ¬ C2CIntCodeUtils.StatementJumps[node: node]; bits: INT ¬ node.bits; mode: Mode ¬ C2CMode.UseValue[bits]; IF bits>INT[C2CTarget.bitsPerDoubleWord] OR bits<=0 THEN C2CBasics.FatalError["bad size expression"]; IF ~hasLab THEN { done: BOOL ¬ FALSE; IF node.bits=1 THEN { [done, cc] ¬ TrySpecialLoadBool[node]; }; IF NOT done THEN cc ¬ GenNode[node, mode]; } ELSE { sz: INT ¬ C2CTarget.TemporaryBits[bits]; tempName: ROPE ¬ C2CStateUtils.DeclareVariable[temporaryDeclarations, sz]; m1: Mode ¬ SetAssUnits[mode, tempName, sz]; cc ¬ GenNode[node, m1]; cc.ec ¬ C2CEmit.IdentCode[tempName]; C2CMode.FreeMode[m1]; }; IF cc.ec=NIL THEN CantHappen; C2CMode.FreeMode[mode]; }; TrySpecialLoadBool: PROC [node: IntCodeDefs.Node] RETURNS [done: BOOL ¬ FALSE, cc: CodeCont ¬ [NIL, NIL, NIL]] = { <<--just try, maybe we fetch just a sign bit...>> IF node.bits#1 THEN RETURN; WITH node SELECT FROM var: Var => { WITH var.location SELECT FROM field: FieldLocation => IF field.start MOD 8 = 0 THEN { WITH field.base SELECT FROM bvar: Var => { <<--Special checks in pointer case, (usage of alignment info!)>> IF ISTYPE[bvar.location, DerefLocation] THEN { TryPtr: PROC [bits: INT, type: ROPE] = { IF field.start MOD bits = 0 THEN { WITH bvar.location SELECT FROM deref: DerefLocation => IF deref.align>=bits THEN { cc ¬ LoadArithNode[deref.addr]; cc.ec ¬ C2CEmit.MinPrecedence[cc.ec, unaryPrecedence]; cc.ec ¬ C2CEmit.Cat["(", type, "*)", cc.ec]; IF field.start>0 THEN cc.ec ¬ C2CEmit.Cat["(", cc.ec, " + ", C2CCodeUtils.ConstI[field.start/bits], ")"]; cc.ec ¬ C2CEmit.Cat["*", cc.ec, "<0"]; cc.ec ¬ C2CEmit.SetPrecedence[cc.ec, orderPrecedence]; done ¬ TRUE; RETURN }; ENDCASE; }; }; TryPtr[C2CTarget.bitsPerWord, C2CTarget.signedWord]; IF NOT done AND C2CTarget.hasHalfWords THEN TryPtr[C2CTarget.bitsPerHalfWord, C2CTarget.signedHalf]; RETURN; }; <<--non pointer case>> IF field.start MOD C2CTarget.bitsPerWord = 0 AND C2CIntCodeUtils.SizeIsProvableOk[bvar] AND bvar.bits>=field.start+C2CTarget.bitsPerWord THEN { n: Node ¬ NEW[VarRep ¬ var­]; n.bits ¬ C2CTarget.bitsPerWord; cc ¬ LoadArithNode[n]; cc.ec ¬ C2CEmit.MinPrecedence[cc.ec, unaryPrecedence]; cc.ec ¬ C2CEmit.Cat["(int)", cc.ec, "<0"]; cc.ec ¬ C2CEmit.SetPrecedence[cc.ec, orderPrecedence]; done ¬ TRUE; RETURN }; }; ENDCASE; }; ENDCASE; }; ENDCASE; }; ModizeArithCode: PUBLIC PROC [incc: CodeCont, mode: Mode, bits: INT ¬ 0] RETURNS [cc: CodeCont] = { AssCast: PROC [] RETURNS [ROPE] = { type: ROPE ¬ C2CTypes.DefineType[bits]; RETURN [Rope.Cat[" = (", type, ") "]]; }; am: C2CAddressing.AddressMode ¬ GetAMode[mode]; IF bits<1 THEN { SELECT am FROM skip, getAddr, getBitAddr, assBitAddr => {}; ENDCASE => NotYetImpl; }; cc ¬ incc; IF cc.xbc#NIL THEN NotYetImpl; IF cc.ec#NIL THEN cc.ec ¬ C2CEmit.MinPrecedence[cc.ec, unaryPrecedence] ELSE IF am#skip THEN NotYetImpl; SELECT am FROM skip => { IF cc.ec#NIL THEN cc.sc ¬ C2CEmit.Cat[cc.sc, "(void) ", cc.ec, ";\n"]; cc.ec ¬ NIL; }; value, plain, maskNShift => {}; assAddr => { cont: ROPE ¬ GetTemplate[mode]; IF C2CEmit.GetAddressable[cc.ec] THEN cc.sc ¬ C2CEmit.Cat[cc.sc, cont, " = ", C2CEmit.TakeAddr[cc.ec], ";\n"] ELSE CantHappen; cc.ec ¬ NIL; }; getAddr => { IF C2CEmit.GetAddressable[cc.ec] THEN cc.ec ¬ C2CEmit.TakeAddr[cc.ec, TRUE] ELSE CantHappen; }; getBitAddr => { <<--convert from right adjusted value mode to left adjusted getBitAddr mode>> unitSz: INT ¬ C2CTarget.TemporaryBits[bits]; cc.xbc ¬ NIL; IF C2CEmit.GetAddressable[cc.ec] THEN { cc.ec ¬ C2CEmit.TakeAddr[cc.ec]; } ELSE { template: ROPE ¬ C2CStateUtils.DeclareVariable[temporaryDeclarations, unitSz]; preC: Code ¬ C2CEmit.Cat[template, AssCast[], cc.ec, ",\n"]; cc.ec ¬ C2CEmit.Cat[preC, " &", template]; cc.ec ¬ C2CEmit.ParentizeAndLn[cc.ec]; }; IF bits> cc.xbc ¬ C2CCodeUtils.ConstI[unitSz-bits]; --allways positive }; }; assBitAddr => { <<--convert from right adjusted value mode to left adjusted getBitAddr mode>> unitSz: INT ¬ C2CTarget.TemporaryBits[bits]; bitOff: INT ¬ unitSz-bits; ac: C2CAddressing.AddressContainer ¬ GetAddrContainer[mode]; IF ~C2CEmit.GetAddressable[cc.ec] THEN { template: ROPE ¬ C2CStateUtils.DeclareVariable[temporaryDeclarations, unitSz]; cc.sc ¬ C2CEmit.Cat[cc.sc, template, AssCast[], cc.ec, ";\n"]; cc.ec ¬ C2CEmit.IdentCode[template]; }; cc.sc ¬ C2CEmit.Cat[cc.sc, ac.words, " = ", C2CEmit.TakeAddr[cc.ec], "; "]; cc.sc ¬ C2CEmit.Cat[cc.sc, ac.bits, " = ", Convert.RopeFromInt[bitOff], ";\n"]; cc.ec ¬ NIL; }; assUnits => { cc.sc ¬ C2CEmit.Cat[cc.sc, CodeToAssUnits[cc.ec, mode]]; cc.ec ¬ NIL; }; ENDCASE => NotYetImpl; }; CodeToAssUnits: PUBLIC PROC [ec: Code, mode: Mode] RETURNS [sc: Code] = { <<--ec expression code to be assigned to container stored with mode>> <<--mode must have AssUnits addressing mode>> <<--ec must have a size which allows simple assignment>> template: ROPE ¬ GetTemplate[mode]; am: C2CAddressing.AddressMode ¬ GetAMode[mode]; csz: INT ¬ ContainerSize[mode]; IF am#assUnits OR csz<=0 THEN CantHappen; IF csz<=C2CTarget.bitsPerWord THEN { ec ¬ C2CEmit.PreventCastingToWord[ec]; ec ¬ C2CEmit.MinPrecedence[ec, unaryPrecedence]; ec ¬ C2CEmit.Cat[" (", C2CTypes.DefineType[csz], ") ", ec]; ec ¬ C2CEmit.SetPrecedence[ec, unaryPrecedence]; }; ec ¬ C2CEmit.MinPrecedence[ec, assignPrecedence]; sc ¬ C2CEmit.Cat[template, " = ", ec, ";\n"]; }; END.