|
@@ -1200,6 +1200,23 @@ PROCEDURE UserLabel (name: ARRAY OF CHAR; VAR q: QbeGen.QVal);
|
|
|
END
|
|
END
|
|
|
END UserLabel;
|
|
END UserLabel;
|
|
|
|
|
|
|
|
|
|
+PROCEDURE CheckSub (t: SymTab.TypeIndex; q: ARRAY OF CHAR);
|
|
|
|
|
+(* ISO range check: trap when a value is assigned to a subrange outside
|
|
|
|
|
+ its bounds. Only 32-bit-or-smaller ordinal bases; LONGINT subranges
|
|
|
|
|
+ are left unchecked for now. *)
|
|
|
|
|
+ VAR lo, hi, c: INTEGER; ql, qlo, qhi: QbeGen.QVal;
|
|
|
|
|
+ BEGIN
|
|
|
|
|
+ IF (t # SymTab.InvalidType) AND SymTab.SubBounds(t, lo, hi) THEN
|
|
|
|
|
+ c := SymTab.ClassOf(t);
|
|
|
|
|
+ IF (c # SymTab.ClLong) AND (c # SymTab.ClInvalid) THEN
|
|
|
|
|
+ QbeGen.WidenIndex(q, ql);
|
|
|
|
|
+ QbeGen.IntStr(lo, qlo);
|
|
|
|
|
+ QbeGen.IntStr(hi, qhi);
|
|
|
|
|
+ QbeGen.CheckRange(ql, qlo, qhi)
|
|
|
|
|
+ END
|
|
|
|
|
+ END
|
|
|
|
|
+ END CheckSub;
|
|
|
|
|
+
|
|
|
PROCEDURE LowerCall (n: AST.Node; VAR t: SymTab.TypeIndex;
|
|
PROCEDURE LowerCall (n: AST.Node; VAR t: SymTab.TypeIndex;
|
|
|
VAR q: QbeGen.QVal; want: BOOLEAN);
|
|
VAR q: QbeGen.QVal; want: BOOLEAN);
|
|
|
VAR nm, pn, cqn: SymTab.Name; i, ai: CARDINAL; at, ft, res: SymTab.TypeIndex;
|
|
VAR nm, pn, cqn: SymTab.Name; i, ai: CARDINAL; at, ft, res: SymTab.TypeIndex;
|
|
@@ -1308,6 +1325,7 @@ PROCEDURE LowerCall (n: AST.Node; VAR t: SymTab.TypeIndex;
|
|
|
(* ISO: empty string actual for a CHAR formal is 0 *)
|
|
(* ISO: empty string actual for a CHAR formal is 0 *)
|
|
|
QbeGen.CopyOp("0", qe); at := SymTab.CharType()
|
|
QbeGen.CopyOp("0", qe); at := SymTab.CharType()
|
|
|
END;
|
|
END;
|
|
|
|
|
+ IF (NOT va) AND (NOT isV) THEN CheckSub(ft, qe) END;
|
|
|
IF va THEN
|
|
IF va THEN
|
|
|
(* permissive C variadic argument *)
|
|
(* permissive C variadic argument *)
|
|
|
QbeGen.CArgAdd(qe, at, qa, cl)
|
|
QbeGen.CArgAdd(qe, at, qa, cl)
|
|
@@ -1607,6 +1625,7 @@ PROCEDURE LowerBuiltinStmt (n: AST.Node; nm: SymTab.Name);
|
|
|
IF isInc THEN QbeGen.Op3("add", qn2, qv, qstep, FALSE)
|
|
IF isInc THEN QbeGen.Op3("add", qn2, qv, qstep, FALSE)
|
|
|
ELSE QbeGen.Op3("sub", qn2, qv, qstep, FALSE)
|
|
ELSE QbeGen.Op3("sub", qn2, qv, qstep, FALSE)
|
|
|
END;
|
|
END;
|
|
|
|
|
+ CheckSub(dt, qn2);
|
|
|
IF sfx OR (dk = SymTab.KindField) THEN QbeGen.ElemStore(qd, qn2, dt)
|
|
IF sfx OR (dk = SymTab.KindField) THEN QbeGen.ElemStore(qd, qn2, dt)
|
|
|
ELSIF SymTab.IsSmallInt(dt) THEN
|
|
ELSIF SymTab.IsSmallInt(dt) THEN
|
|
|
QbeGen.StoreShortVar(qn, SymTab.SmallIntBytes(dt), qn2)
|
|
QbeGen.StoreShortVar(qn, SymTab.SmallIntBytes(dt), qn2)
|
|
@@ -2295,6 +2314,7 @@ PROCEDURE LowerStmt (seq: AST.Node);
|
|
|
(* ISO: the empty string assigned to CHAR is the terminator *)
|
|
(* ISO: the empty string assigned to CHAR is the terminator *)
|
|
|
QbeGen.CopyOp("0", qe); et := SymTab.CharType()
|
|
QbeGen.CopyOp("0", qe); et := SymTab.CharType()
|
|
|
END;
|
|
END;
|
|
|
|
|
+ CheckSub(dt, qe);
|
|
|
isR := (dt # SymTab.InvalidType) AND (SymTab.ClassOf(dt) = SymTab.ClReal);
|
|
isR := (dt # SymTab.InvalidType) AND (SymTab.ClassOf(dt) = SymTab.ClReal);
|
|
|
conv := isR AND SymTab.IsIntFamily(et);
|
|
conv := isR AND SymTab.IsIntFamily(et);
|
|
|
wconv := (dt # SymTab.InvalidType) AND SymTab.IsLongFamily(dt)
|
|
wconv := (dt # SymTab.InvalidType) AND SymTab.IsLongFamily(dt)
|
|
@@ -2392,6 +2412,8 @@ PROCEDURE LowerStmt (seq: AST.Node);
|
|
|
IF SymTab.IsEmptyStr(t2) THEN
|
|
IF SymTab.IsEmptyStr(t2) THEN
|
|
|
QbeGen.CopyOp("0", qhi); t2 := SymTab.CharType()
|
|
QbeGen.CopyOp("0", qhi); t2 := SymTab.CharType()
|
|
|
END;
|
|
END;
|
|
|
|
|
+ CheckSub(SymTab.SymType(lv), qlo);
|
|
|
|
|
+ CheckSub(SymTab.SymType(lv), qhi);
|
|
|
(* optional BY step: a constant, default +1; its sign also
|
|
(* optional BY step: a constant, default +1; its sign also
|
|
|
selects the termination comparison *)
|
|
selects the termination comparison *)
|
|
|
step := 1;
|
|
step := 1;
|
|
@@ -2453,6 +2475,9 @@ PROCEDURE LowerStmt (seq: AST.Node);
|
|
|
QbeGen.EmitRet(q, FALSE)
|
|
QbeGen.EmitRet(q, FALSE)
|
|
|
ELSE
|
|
ELSE
|
|
|
LowerExpr(AST.Child(seq, 0), t, q);
|
|
LowerExpr(AST.Child(seq, 0), t, q);
|
|
|
|
|
+ IF (emitProc >= 0) AND (emitProc < VAL(INTEGER, nProcs)) THEN
|
|
|
|
|
+ CheckSub(procRes[emitProc], q)
|
|
|
|
|
+ END;
|
|
|
IF SymTab.IsEmptyStr(t)
|
|
IF SymTab.IsEmptyStr(t)
|
|
|
AND (emitProc >= 0) AND (emitProc < VAL(INTEGER, nProcs))
|
|
AND (emitProc >= 0) AND (emitProc < VAL(INTEGER, nProcs))
|
|
|
AND (SymTab.ClassOf(procRes[emitProc]) = SymTab.ClChar) THEN
|
|
AND (SymTab.ClassOf(procRes[emitProc]) = SymTab.ClChar) THEN
|