<<>> <> <> <> <> DIRECTORY C2CAccess, C2CBasics, C2CTarget, C2CIntCodeUtils, IntCodeDefs, IntCodeUtils; C2CIntCodeUtilsImpl: CEDAR PROGRAM IMPORTS C2CAccess, C2CBasics, C2CIntCodeUtils, IntCodeUtils EXPORTS C2CIntCodeUtils = BEGIN OPEN IntCodeDefs; CountNodes: PUBLIC PROC [nodes: IntCodeDefs.NodeList] RETURNS [cnt: INT ¬ 0] = { WHILE nodes#NIL DO cnt ¬ cnt+1; nodes ¬ nodes.rest; ENDLOOP; }; AnyNodeHasCode: PUBLIC PROC [nodes: IntCodeDefs.NodeList] RETURNS [BOOL ¬ FALSE] = { FOR nl: NodeList ¬ nodes, nl.rest WHILE nl#NIL DO IF NodeHasCode[nl.first] THEN RETURN [TRUE]; ENDLOOP; }; NodeHasCode: PUBLIC PROC [node: IntCodeDefs.Node] RETURNS [BOOL] = { IF node=NIL THEN RETURN [FALSE]; WITH node SELECT FROM sourceNode: SourceNode => RETURN [AnyNodeHasCode[sourceNode.nodes]]; commentNode: CommentNode => RETURN [FALSE]; ENDCASE => RETURN [TRUE]; }; LastNodeWithCode: PUBLIC PROC [nodes: IntCodeDefs.NodeList] RETURNS [node: IntCodeDefs.Node ¬ NIL] = { FOR nodesLeft: IntCodeDefs.NodeList ¬ nodes, nodesLeft.rest WHILE nodesLeft#NIL DO IF NodeHasCode[nodesLeft.first] THEN node ¬ nodesLeft.first ENDLOOP }; CheckArgCount: PUBLIC PROC [args: IntCodeDefs.NodeList, n: INT] = { WHILE args#NIL DO IF n<=0 THEN C2CBasics.CantHappen; args ¬ args.rest; n ¬ n-1; ENDLOOP; IF n#0 THEN C2CBasics.CantHappen; }; IsSimpleConst: PUBLIC PROC [node: IntCodeDefs.Node] RETURNS [is: BOOL ¬ FALSE, val: CARD ¬ 0] = { IF node#NIL AND node.bits<=bitsPerWord THEN WITH node SELECT FROM constNode: ConstNode => WITH constNode SELECT FROM wordConst: WordConstNode => { RETURN [TRUE, IntCodeUtils.WordToCard[wordConst.word]]; }; ENDCASE; var: Var => WITH var.location SELECT FROM dummy: DummyLocation => RETURN [TRUE, 0]; ENDCASE; ENDCASE; }; <<>> IsFieldVar: PUBLIC PROC [node: IntCodeDefs.Node] RETURNS [is: BOOL ¬ FALSE] = { WITH node SELECT FROM var: Var => WITH var.location SELECT FROM field: FieldLocation => RETURN [TRUE]; ENDCASE => NULL; ENDCASE => NULL; }; GenConst: PUBLIC PROC [value: INT, bits: INT] RETURNS [ConstNode] = { RETURN [IntCodeUtils.zone.NEW[NodeRep.const.word ¬ [bits, const[word[IntCodeUtils.IntToWord[value]]]]]]; }; keyForMaxVariableId: REF INT ~ NEW[INT]; --unique NewVariableId: PUBLIC PROC [] RETURNS [id: VariableId] = { MaxVariableId: PROC [node: Node] RETURNS [maxVariableId: INT ¬ nullVariableId] = { <<--returns the maximal value used as an VariableId recursively down this node>> VisitVariableIds: IntCodeUtils.Visitor = { WITH node SELECT FROM var: Var => maxVariableId ¬ MAX[maxVariableId, var.id]; ENDCASE => {}; IntCodeUtils.MapNode[node, VisitVariableIds]; RETURN [node]; }; [] ¬ VisitVariableIds[node]; }; WITH C2CBasics.GetProp[keyForMaxVariableId] SELECT FROM ri: REF INT => id ¬ ri­ ¬ ri­+1 ENDCASE => { id ¬ MaxVariableId[C2CBasics.rootNode]; id ¬ ((id/100000)+1) * 100000; C2CBasics.PutProp[keyForMaxVariableId, NEW[INT ¬ id]] }; }; UseTemporaryIfReused: PUBLIC PROC [arg: Node, addr: BOOL ¬ FALSE] RETURNS [BOOL ¬ TRUE] = { SimpleReUse: PROC [arg: Node] RETURNS [BOOL ¬ TRUE] = { <<--returns TRUE only for constants and very simple variables>> WITH arg SELECT FROM const: ConstNode => RETURN [TRUE]; var: Var => { IF var.location=nullLocation THEN RETURN [TRUE]; WITH var.location SELECT FROM globLoc: GlobalVarLocation => RETURN [TRUE]; locLoc: LocalVarLocation => RETURN [TRUE]; ENDCASE => RETURN [FALSE]; }; ENDCASE => RETURN [FALSE]; }; IF ~IntCodeUtils.SideEffectFree[node: arg, noSignals: TRUE] THEN RETURN [TRUE]; <<--eventual alternative: could consider trap on first deref NOT a sideeffect in case addr=TRUE>> WITH arg SELECT FROM apply: ApplyNode => { WITH apply.proc SELECT FROM oper: OperNode => WITH oper.oper SELECT FROM arithOp: ArithOper => SELECT arithOp.select FROM add, sub => { C2CIntCodeUtils.CheckArgCount[apply.args, 2]; IF SimpleReUse[apply.args.first] AND SimpleReUse[apply.args.rest.first] THEN RETURN [FALSE] }; ENDCASE; ENDCASE; ENDCASE; RETURN [TRUE]; }; const: ConstNode => RETURN [FALSE]; var: Var => { IF var.location=nullLocation THEN RETURN [FALSE]; WITH var.location SELECT FROM globLoc: GlobalVarLocation => RETURN [FALSE]; locLoc: LocalVarLocation => RETURN [FALSE]; derefLoc: DerefLocation => { <<--on Sunos4 compiler for Sparc I have found that the compiler might optimize away a temporary but wont optimize away multiple dereferences >> IF ~addr THEN RETURN [TRUE]; IF SimpleReUse[derefLoc.addr] THEN RETURN [FALSE]; RETURN [TRUE]; } ENDCASE => RETURN [TRUE]; }; ENDCASE => RETURN [TRUE]; }; UsingTemporaryWhichGeneratesStatementCode: PUBLIC PROC [arg: Node] RETURNS [BOOL ¬ FALSE] = { <> WITH arg SELECT FROM apply: ApplyNode => WITH apply.proc SELECT FROM oper: OperNode => { IF ~C2CAccess.params.supportInlineFloatingPoint THEN RETURN [FALSE]; WITH oper.oper SELECT FROM arithOp: ArithOper => IF arithOp.class.kind=real THEN { SELECT arithOp.select FROM min, max, abs => RETURN [TRUE] ENDCASE => {}; }; ENDCASE => {}; }; machineCode: MachineCodeNode => {}; ENDCASE => RETURN [TRUE]; ENDCASE => {}; }; StatementCode: PUBLIC PROC [node: Node] RETURNS [hasLabel: BOOL ¬ FALSE] = { <<--Checks whether node contains a label, goto, need for temporary, strong in tree. >> <<--To detect statement code which is not ok in conditional expressions >> <<--This is the stronger test >> Visit: IntCodeUtils.Visitor = { IF hasLabel THEN RETURN [node]; IF UsingTemporaryWhichGeneratesStatementCode[node] THEN { hasLabel ¬ TRUE; RETURN [node]; }; <