(* Copyright (C) 1992, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* File: Inc.m3 *) (* Last Modified On Tue Jun 30 08:59:00 PDT 1992 By kalsow *) (* Modified On Tue Apr 2 03:47:06 1991 By muller *) MODULE Inc; IMPORT CallExpr, Expr, Type, Procedure, Dec, Emit, Void, Temp, Target; IMPORT IntegerExpr, Addr, Host, Frame, Fault; VAR Z: CallExpr.MethodList; PROCEDURE Check (<*UNUSED*> proc: Expr.T; VAR args: Expr.List; <*UNUSED*> VAR cs: Expr.CheckState): Type.T = BEGIN Dec.DoCheck ("INC", args); RETURN Void.T; END Check; PROCEDURE Compile (<*UNUSED*> proc: Expr.T; args: Expr.List): Temp.T = VAR t1, t2: Temp.T; bmin, bmax, imin, imax: INTEGER; inc: Expr.T; check: [0..4] := 0; block: INTEGER; BEGIN IF (NUMBER (args^) > 1) THEN inc := args[1]; ELSE inc := IntegerExpr.New (1); END; Expr.GetBounds (args[0], bmin, bmax); Expr.GetBounds (inc, imin, imax); IF Host.doRangeChk THEN IF (bmin # Target.MININT) AND (imin < 0) THEN INC (check) END; IF (bmax # Target.MAXINT) AND (imax > 0) THEN INC (check, 2) END; END; IF Type.IsSubtype (Expr.TypeOf (args[0]), Addr.T) THEN check := 4; END; t1 := Expr.CompileLValue (args[0]); t2 := Expr.Compile (inc); CASE check OF | 0 => (* no range checking *) Emit.OpTT ("@ += @;\n", t1, t2); | 1 => (* check lower bound only *) Frame.PushBlock (block, 1); Emit.Op ("register int _r;\n"); Emit.OpTT ("_r = @ + @;\n", t1, t2); Emit.OpI ("if (_r < @) ", bmin); Fault.Range (); Emit.OpT ("@ = _r;\n", t1); Frame.PopBlock (block); | 2 => (* check upper bound only *) Frame.PushBlock (block, 1); Emit.Op ("register int _r;\n"); Emit.OpTT ("_r = @ + @;\n", t1, t2); Emit.OpI ("if (@ < _r) ", bmax); Fault.Range (); Emit.OpT ("@ = _r;\n", t1); Frame.PopBlock (block); | 3 => (* check both bounds *) Frame.PushBlock (block, 1); Emit.Op ("register int _r;\n"); Emit.OpTT ("_r = @ + @;\n", t1, t2); Emit.OpII ("if ((_r < @) || (@ < _r)) ", bmin, bmax); Fault.Range (); Emit.OpT ("@ = _r;\n", t1); Frame.PopBlock (block); | 4 => (* address *) Emit.OpTT ("*((char**)&@) += @;\n", t1, t2); END; Expr.NoteWrite (args[0]); Temp.Free (t2); Temp.Free (t1); RETURN t1; (*DUMMY*) END Compile; PROCEDURE Initialize () = BEGIN Z := CallExpr.NewMethodList (1, 2, FALSE, FALSE, Void.T, NIL, Check, Compile, CallExpr.NoValue, CallExpr.IsNever, (* writable *) CallExpr.IsNever, (* designator *) CallExpr.NotWritable (* noteWriter *)); Procedure.Define ("INC", Z, TRUE); END Initialize; BEGIN END Inc.