(* Copyright (C) 1992, Digital Equipment Corporation *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* File: NilChkExpr.m3 *) (* Last Modified On Tue Jun 30 11:51:14 PDT 1992 By kalsow *) (* Modified On Thu Nov 29 03:28:30 1990 By muller *) MODULE NilChkExpr; IMPORT Expr, ExprRep, Type, Emit, AddressExpr, Temp, MBuf; IMPORT Target, RefType, Host; TYPE P = ExprRep.Ta BRANDED "NilChkExpr.P" OBJECT offset : INTEGER; OVERRIDES typeOf := TypeOf; check := Check; compile := Compile; evaluate := Fold; fprint := FPrinter; write := ExprRep.NoWriter; isEqual := ExprRep.EqCheckA; getBounds := Bounder; isWritable := ExprRep.IsNever; isDesignator := ExprRep.IsNever; isZeroes := ExprRep.IsNever; note_write := NoteWrites; genLiteral := ExprRep.NoLiteral; END; PROCEDURE New (a: Expr.T): Expr.T = VAR p: P; BEGIN IF (NOT Host.doNilChk) OR (TYPECODE (a) = TYPECODE (P)) THEN RETURN a END; p := NEW (P); ExprRep.Init (p); p.origin := a.origin; p.a := a; p.offset := LAST (INTEGER); RETURN p; END New; PROCEDURE SetOffset (a: Expr.T; offset: INTEGER) = BEGIN TYPECASE a OF | NULL => (* skip *) | P(p) => p.offset := MIN (p.offset, offset); ELSE (* skip *) END; END SetOffset; PROCEDURE TypeOf (p: P): Type.T = BEGIN RETURN Expr.TypeOf (p.a) END TypeOf; PROCEDURE Check (p: P; VAR cs: Expr.CheckState) = VAR target: Type.T; BEGIN Expr.TypeCheck (p.a, cs); p.type := Expr.TypeOf (p.a); IF p.offset = LAST (INTEGER) THEN IF RefType.Split (p.type, target) THEN p.offset := Type.Size (target); END; END; END Check; PROCEDURE Compile (p: P): Temp.T = CONST EasyCheck = Target.FIRSTREADABLEADDR * Target.CHARSIZE; VAR t1, t2: Temp.T; BEGIN t1 := Expr.Compile (p.a); IF (p.offset < 0) OR (EasyCheck <= p.offset) THEN t2 := Temp.Alloc (p); Emit.OpTT ("_NILCHECKB (@ = @);\n", t2, t1); Temp.Free (t1); t1 := t2; END; RETURN t1; END Compile; (************************************************************************* PROCEDURE Compile (p: P): Temp.T = CONST EasyCheck = 1024 * Target.CHARSIZE; CONST Fmt = ARRAY BOOLEAN OF TEXT { "_NILCHECKB (@ = @);\n", "_NILCHECKA (@ = @);\n" }; VAR t1, t2: Temp.T; BEGIN t1 := Expr.Compile (p.a); t2 := Temp.Alloc (p); Emit.OpTT (Fmt[p.offset < EasyCheck], t2, t1); Temp.Free (t1); RETURN t2; END Compile; **************************************************************************) PROCEDURE Fold (p: P): Expr.T = VAR e: Expr.T; i: INTEGER; BEGIN e := Expr.ConstValue (p.a); IF (e = NIL) THEN RETURN NIL END; IF NOT AddressExpr.Split (e, i) THEN RETURN NIL END; IF (i = 0) THEN RETURN NIL END; RETURN e; END Fold; PROCEDURE NoteWrites (p: P) = BEGIN Expr.NoteWrite (p.a); END NoteWrites; PROCEDURE Bounder (p: P; VAR min, max: INTEGER) = BEGIN Expr.GetBounds (p.a, min, max); END Bounder; PROCEDURE FPrinter (p: P; map: Type.FPMap; wr: MBuf.T) = BEGIN MBuf.PutText (wr, "CHKN "); Expr.Fingerprint (p.a, map, wr); END FPrinter; BEGIN END NilChkExpr.