|
|
@@ -211,6 +211,8 @@ TYPE
|
|
|
isVar : BOOLEAN ; (* a VAR parameter: the slot holds an address *)
|
|
|
level : CARDINAL ;
|
|
|
local : BOOLEAN ;
|
|
|
+ parent : CARDINAL ; (* lexical parent procedure, 0 at top level *)
|
|
|
+ staticOff : CARDINAL ; (* nested proc's hidden static-link local *)
|
|
|
resvar : CARDINAL ;
|
|
|
goPos : CARDINAL ;
|
|
|
defnd : BOOLEAN ;
|
|
|
@@ -440,6 +442,8 @@ VAR
|
|
|
txerrPos : CARDINAL ;
|
|
|
|
|
|
lexnest : CARDINAL ;
|
|
|
+ curProc : CARDINAL ; (* symbol of the procedure body being compiled *)
|
|
|
+ curStaticOff : CARDINAL ; (* its hidden static-link slot, 0 if none *)
|
|
|
curIsFunc : BOOLEAN ;
|
|
|
resultVar : CARDINAL ;
|
|
|
resultIsReal : BOOLEAN ; (* the CURRENT function returns TReal *)
|
|
|
@@ -1324,6 +1328,55 @@ BEGIN
|
|
|
END
|
|
|
END EmBpDisp ;
|
|
|
|
|
|
+PROCEDURE EmBxDisp (off, regf : CARDINAL) ;
|
|
|
+(* The [BX+disp] twin of EmBpDisp. A nested procedure reaches an enclosing
|
|
|
+ frame through the static link in BX; the displacement rules are identical
|
|
|
+ except for the rm field (111 for BX instead of 110 for BP). *)
|
|
|
+BEGIN
|
|
|
+ IF off <= 127 THEN
|
|
|
+ Ebyte (VAL (BYTE, 40H + regf * 8 + 7H)) ; Ebyte (VAL (BYTE, off))
|
|
|
+ ELSE
|
|
|
+ Ebyte (VAL (BYTE, 80H + regf * 8 + 7H)) ; Eword (off)
|
|
|
+ END
|
|
|
+END EmBxDisp ;
|
|
|
+
|
|
|
+PROCEDURE EmMovBxBp () ;
|
|
|
+BEGIN Ebyte (89H) ; Ebyte (0EBH) END EmMovBxBp ; (* MOV BX,BP *)
|
|
|
+
|
|
|
+PROCEDURE EmMovDxBp () ;
|
|
|
+BEGIN Ebyte (89H) ; Ebyte (0EAH) END EmMovDxBp ; (* MOV DX,BP *)
|
|
|
+
|
|
|
+PROCEDURE EmMovDxBx () ;
|
|
|
+BEGIN Ebyte (89H) ; Ebyte (0DAH) END EmMovDxBx ; (* MOV DX,BX *)
|
|
|
+
|
|
|
+PROCEDURE EmMovAxDx () ;
|
|
|
+BEGIN Ebyte (89H) ; Ebyte (0D0H) END EmMovAxDx ; (* MOV AX,DX *)
|
|
|
+
|
|
|
+PROCEDURE EmLdBxBx (off : CARDINAL) ;
|
|
|
+(* BX := [BX+off] - one step up the static-link chain. *)
|
|
|
+BEGIN Ebyte (8BH) ; EmBxDisp (off, 3) END EmLdBxBx ;
|
|
|
+
|
|
|
+PROCEDURE EmLoadVarBx (off, nbytes : CARDINAL) ;
|
|
|
+BEGIN
|
|
|
+ IF nbytes = 1 THEN
|
|
|
+ Ebyte (8AH) ; EmBxDisp (off, 0)
|
|
|
+ ELSE
|
|
|
+ Ebyte (8BH) ; EmBxDisp (off, 0)
|
|
|
+ END
|
|
|
+END EmLoadVarBx ;
|
|
|
+
|
|
|
+PROCEDURE EmStoreVarBx (off, nbytes : CARDINAL) ;
|
|
|
+BEGIN
|
|
|
+ IF nbytes = 1 THEN
|
|
|
+ Ebyte (88H) ; EmBxDisp (off, 0)
|
|
|
+ ELSE
|
|
|
+ Ebyte (89H) ; EmBxDisp (off, 0)
|
|
|
+ END
|
|
|
+END EmStoreVarBx ;
|
|
|
+
|
|
|
+PROCEDURE EmLeaDiBx (off : CARDINAL) ;
|
|
|
+BEGIN Ebyte (8DH) ; EmBxDisp (off, 7) END EmLeaDiBx ;
|
|
|
+
|
|
|
PROCEDURE EmLoadVar (local : BOOLEAN ; off, nbytes : CARDINAL) ;
|
|
|
(* A local is [BP+off] and `off' is already a frame displacement, so it needs
|
|
|
no bias. A global is [off] with a DIRECT displacement, i.e. an absolute
|
|
|
@@ -1405,6 +1458,117 @@ BEGIN
|
|
|
END
|
|
|
END EmLeaDi ;
|
|
|
|
|
|
+PROCEDURE EmMovBxAx () ;
|
|
|
+BEGIN Ebyte (89H) ; Ebyte (0C3H) END EmMovBxAx ; (* MOV BX,AX *)
|
|
|
+
|
|
|
+PROCEDURE EmitFrameBase (level : CARDINAL) ;
|
|
|
+(* Leave BX pointing at the frame for lexical scope `level', pushing the old
|
|
|
+ BX. The current frame is at `lexnest'; each step follows the hidden
|
|
|
+ static link stored by the enclosing procedure. The caller must POP BX
|
|
|
+ after the access. *)
|
|
|
+VAR p, k : CARDINAL ;
|
|
|
+BEGIN
|
|
|
+ EmPushBx () ;
|
|
|
+ EmMovBxBp () ;
|
|
|
+ p := curProc ;
|
|
|
+ k := lexnest ;
|
|
|
+ WHILE k > level DO
|
|
|
+ EmLdBxBx (symtab [p].staticOff) ;
|
|
|
+ p := symtab [p].parent ;
|
|
|
+ DEC (k)
|
|
|
+ END
|
|
|
+END EmitFrameBase ;
|
|
|
+
|
|
|
+PROCEDURE IsOuterLocal (idx : CARDINAL) : BOOLEAN ;
|
|
|
+BEGIN
|
|
|
+ RETURN symtab [idx].local AND (symtab [idx].level < lexnest)
|
|
|
+END IsOuterLocal ;
|
|
|
+
|
|
|
+PROCEDURE LoadSymVar (idx, off, nbytes : CARDINAL) ;
|
|
|
+BEGIN
|
|
|
+ IF IsOuterLocal (idx) THEN
|
|
|
+ EmitFrameBase (symtab [idx].level) ;
|
|
|
+ EmLoadVarBx (off, nbytes) ;
|
|
|
+ EmPopBx ()
|
|
|
+ ELSE
|
|
|
+ EmLoadVar (symtab [idx].local, off, nbytes)
|
|
|
+ END
|
|
|
+END LoadSymVar ;
|
|
|
+
|
|
|
+PROCEDURE StoreSymVar (idx, off, nbytes : CARDINAL) ;
|
|
|
+BEGIN
|
|
|
+ IF IsOuterLocal (idx) THEN
|
|
|
+ EmitFrameBase (symtab [idx].level) ;
|
|
|
+ EmStoreVarBx (off, nbytes) ;
|
|
|
+ EmPopBx ()
|
|
|
+ ELSE
|
|
|
+ EmStoreVar (symtab [idx].local, off, nbytes)
|
|
|
+ END
|
|
|
+END StoreSymVar ;
|
|
|
+
|
|
|
+PROCEDURE EmPushSymAddr (idx, off : CARDINAL) ;
|
|
|
+BEGIN
|
|
|
+ IF IsOuterLocal (idx) THEN
|
|
|
+ EmitFrameBase (symtab [idx].level) ;
|
|
|
+ Ebyte (8DH) ; EmBxDisp (off, 0) ; (* LEA AX,[BX+off] *)
|
|
|
+ EmPopBx () ; (* restore BX before pushing AX *)
|
|
|
+ EmPushAx ()
|
|
|
+ ELSE
|
|
|
+ EmPushVarAddr (symtab [idx].local, off)
|
|
|
+ END
|
|
|
+END EmPushSymAddr ;
|
|
|
+
|
|
|
+PROCEDURE LeaDiSym (idx, off : CARDINAL) ;
|
|
|
+BEGIN
|
|
|
+ IF IsOuterLocal (idx) THEN
|
|
|
+ EmitFrameBase (symtab [idx].level) ;
|
|
|
+ EmLeaDiBx (off) ;
|
|
|
+ EmPopBx ()
|
|
|
+ ELSE
|
|
|
+ EmLeaDi (symtab [idx].local, off)
|
|
|
+ END
|
|
|
+END LeaDiSym ;
|
|
|
+
|
|
|
+PROCEDURE EmLoadVarIndSym (idx, nbytes : CARDINAL) ;
|
|
|
+(* AX := the value reached through a VAR parameter's address slot. *)
|
|
|
+BEGIN
|
|
|
+ LoadSymVar (idx, symtab [idx].off, 2) ;
|
|
|
+ EmMovBxAx () ;
|
|
|
+ IF nbytes = 1 THEN
|
|
|
+ Ebyte (8AH) ; Ebyte (07H) ;
|
|
|
+ EmMovAh0 ()
|
|
|
+ ELSE
|
|
|
+ Ebyte (8BH) ; Ebyte (07H)
|
|
|
+ END
|
|
|
+END EmLoadVarIndSym ;
|
|
|
+
|
|
|
+PROCEDURE StoreVarIndPrepSym (idx : CARDINAL) ;
|
|
|
+(* DI := the address held by a VAR parameter's slot, then PUSH DI. *)
|
|
|
+BEGIN
|
|
|
+ LoadSymVar (idx, symtab [idx].off, 2) ;
|
|
|
+ EmMovDiAx () ;
|
|
|
+ EmPushDi ()
|
|
|
+END StoreVarIndPrepSym ;
|
|
|
+
|
|
|
+PROCEDURE EmitStaticLink (idx : CARDINAL) ;
|
|
|
+(* Pass the lexical parent frame in DX before a call to a nested procedure.
|
|
|
+ The callee saves it in its hidden static-link local. A top-level procedure
|
|
|
+ has no parent frame and gets nothing. *)
|
|
|
+VAR level : CARDINAL ;
|
|
|
+BEGIN
|
|
|
+ level := symtab [idx].level ;
|
|
|
+ IF level = 0 THEN
|
|
|
+ RETURN
|
|
|
+ END ;
|
|
|
+ IF level = lexnest THEN
|
|
|
+ EmMovDxBp ()
|
|
|
+ ELSE
|
|
|
+ EmitFrameBase (level) ;
|
|
|
+ EmMovDxBx () ;
|
|
|
+ EmPopBx ()
|
|
|
+ END
|
|
|
+END EmitStaticLink ;
|
|
|
+
|
|
|
PROCEDURE EmAddDiAx () ;
|
|
|
BEGIN Ebyte (01H) ; Ebyte (0C7H) END EmAddDiAx ; (* 01 C7: DI := DI + AX *)
|
|
|
|
|
|
@@ -1800,6 +1964,8 @@ BEGIN
|
|
|
e.isVar := FALSE ;
|
|
|
e.level := lexnest ;
|
|
|
e.local := local ;
|
|
|
+ e.parent := 0 ;
|
|
|
+ e.staticOff := 0 ;
|
|
|
e.resvar := 0 ;
|
|
|
e.goPos := 0 ;
|
|
|
e.defnd := FALSE ;
|
|
|
@@ -2478,7 +2644,7 @@ BEGIN
|
|
|
r.kind := 2 ;
|
|
|
RETURN
|
|
|
END ;
|
|
|
- EmLoadVarInd (symtab [r.idx].off, VarSize (r)) ;
|
|
|
+ EmLoadVarIndSym (r.idx, VarSize (r)) ;
|
|
|
r.kind := 2 ;
|
|
|
RETURN
|
|
|
END ;
|
|
|
@@ -2492,9 +2658,7 @@ BEGIN
|
|
|
IF (r.cls = TChar) AND (symtab [r.idx].cls = TString) THEN
|
|
|
emsz := 1
|
|
|
END ;
|
|
|
- EmLoadVar (symtab [r.idx].local,
|
|
|
- (symtab [r.idx].off + r.boff) MOD 10000H,
|
|
|
- emsz) ;
|
|
|
+ LoadSymVar (r.idx, (symtab [r.idx].off + r.boff) MOD 10000H, emsz) ;
|
|
|
IF emsz = 1 THEN
|
|
|
EmMovAh0 ()
|
|
|
END ;
|
|
|
@@ -2529,7 +2693,7 @@ BEGIN
|
|
|
metadata, exactly as in ParseVar. *)
|
|
|
DropCh (GetCh ()) ;
|
|
|
p := symtab [r.idx].elem ;
|
|
|
- EmLoadVar (symtab [r.idx].local, symtab [r.idx].off, 2) ;
|
|
|
+ LoadSymVar (r.idx, symtab [r.idx].off, 2) ;
|
|
|
EmMovDiAx () ;
|
|
|
r.idx := p ;
|
|
|
r.kind := 5 ;
|
|
|
@@ -2604,7 +2768,7 @@ BEGIN
|
|
|
both constant and variable indices, so LoadAtom and
|
|
|
Assignment see the same kind-5 character address they do
|
|
|
for an ordinary string. *)
|
|
|
- EmLoadVar (TRUE, symtab [r.idx].off, 2) ;
|
|
|
+ LoadSymVar (r.idx, symtab [r.idx].off, 2) ;
|
|
|
EmMovDiAx () ;
|
|
|
IF t.kind = 0 THEN
|
|
|
EmAddDiImm ((r.boff + W16 (t.imm)) MOD 10000H)
|
|
|
@@ -2632,8 +2796,7 @@ BEGIN
|
|
|
lets a later LoadAtom read [DI] and a later assignment PUSH
|
|
|
DI across its right-hand side. *)
|
|
|
LoadAtom (t) ;
|
|
|
- EmLeaDi (symtab [r.idx].local,
|
|
|
- (symtab [r.idx].off + r.boff) MOD 10000H) ;
|
|
|
+ LeaDiSym (r.idx, (symtab [r.idx].off + r.boff) MOD 10000H) ;
|
|
|
EmAddDiAx () ;
|
|
|
r.kind := 5
|
|
|
END ;
|
|
|
@@ -2745,8 +2908,7 @@ BEGIN
|
|
|
END ;
|
|
|
r.kind := 5
|
|
|
ELSIF haveVar THEN
|
|
|
- EmLeaDi (symtab [r.idx].local,
|
|
|
- (symtab [r.idx].off + r.boff
|
|
|
+ LeaDiSym (r.idx, (symtab [r.idx].off + r.boff
|
|
|
+ W16 (coff)) MOD 10000H) ;
|
|
|
EmAddDiAx () ;
|
|
|
r.kind := 5
|
|
|
@@ -2788,7 +2950,7 @@ BEGIN
|
|
|
metadata from the symbol, not from the expression. *)
|
|
|
DropCh (GetCh ()) ;
|
|
|
p := symtab [idx].elem ;
|
|
|
- EmLoadVar (symtab [idx].local, symtab [idx].off, 2) ;
|
|
|
+ LoadSymVar (idx, symtab [idx].off, 2) ;
|
|
|
EmMovDiAx () ;
|
|
|
r.idx := p ;
|
|
|
r.kind := 5 ;
|
|
|
@@ -3127,8 +3289,7 @@ BEGIN
|
|
|
IF r.kind = 5 THEN
|
|
|
EmPushDi ()
|
|
|
ELSIF r.kind = 1 THEN
|
|
|
- EmPushVarAddr (symtab [r.idx].local,
|
|
|
- (symtab [r.idx].off + r.boff) MOD 10000H)
|
|
|
+ EmPushSymAddr (r.idx, (symtab [r.idx].off + r.boff) MOD 10000H)
|
|
|
ELSIF (r.kind = 7) OR (r.kind = 8) THEN
|
|
|
EmPushVarAddr (FALSE, r.setoff)
|
|
|
ELSE
|
|
|
@@ -3259,12 +3420,11 @@ BEGIN
|
|
|
IF r.boff # 0 THEN
|
|
|
Err (ENoLib)
|
|
|
ELSE
|
|
|
- EmLoadVar (TRUE, symtab [r.idx].off, 2) ;
|
|
|
+ LoadSymVar (r.idx, symtab [r.idx].off, 2) ;
|
|
|
EmPushAx ()
|
|
|
END
|
|
|
ELSE
|
|
|
- EmPushVarAddr (symtab [r.idx].local,
|
|
|
- (symtab [r.idx].off + r.boff) MOD 10000H)
|
|
|
+ EmPushSymAddr (r.idx, (symtab [r.idx].off + r.boff) MOD 10000H)
|
|
|
END
|
|
|
ELSIF r.kind = 3 THEN
|
|
|
EmPushVarAddr (FALSE, EmStrBlob (r)) (* the literal travels inline *)
|
|
|
@@ -3281,11 +3441,10 @@ BEGIN
|
|
|
EmPushDi ()
|
|
|
ELSIF r.kind = 1 THEN
|
|
|
IF symtab [r.idx].isVar THEN
|
|
|
- EmLoadVar (TRUE, symtab [r.idx].off, 2) ;
|
|
|
+ LoadSymVar (r.idx, symtab [r.idx].off, 2) ;
|
|
|
EmPushAx ()
|
|
|
ELSE
|
|
|
- EmPushVarAddr (symtab [r.idx].local,
|
|
|
- (symtab [r.idx].off + r.boff) MOD 10000H)
|
|
|
+ EmPushSymAddr (r.idx, (symtab [r.idx].off + r.boff) MOD 10000H)
|
|
|
END
|
|
|
ELSE
|
|
|
Err (ENoLib)
|
|
|
@@ -3571,8 +3730,7 @@ BEGIN
|
|
|
IF right.kind = 5 THEN
|
|
|
EmLdAlDiOff (bidx)
|
|
|
ELSIF right.kind = 1 THEN
|
|
|
- EmLoadVar (symtab [right.idx].local,
|
|
|
- (right.setoff + right.boff + bidx) MOD 10000H, 1)
|
|
|
+ LoadSymVar (right.idx, (right.setoff + right.boff + bidx) MOD 10000H, 1)
|
|
|
ELSE
|
|
|
Err (ENoLib) ;
|
|
|
RETURN
|
|
|
@@ -4379,8 +4537,7 @@ BEGIN
|
|
|
IF OK () THEN
|
|
|
IF (r.kind = 1) AND
|
|
|
((r.cls = TText) OR (r.cls = TFile)) THEN
|
|
|
- EmPushVarAddr (symtab [r.idx].local,
|
|
|
- (symtab [r.idx].off + r.boff) MOD 10000H) ;
|
|
|
+ EmPushSymAddr (r.idx, (symtab [r.idx].off + r.boff) MOD 10000H) ;
|
|
|
DropC (EmCall (TU_FileEof)) ;
|
|
|
EmAddSp (2) ;
|
|
|
r.kind := 2 ;
|
|
|
@@ -4618,11 +4775,10 @@ BEGIN
|
|
|
IF r.boff # 0 THEN
|
|
|
Err (ENoLib)
|
|
|
ELSE
|
|
|
- EmLoadVarInd (symtab [r.idx].off, 1)
|
|
|
+ EmLoadVarIndSym (r.idx, 1)
|
|
|
END
|
|
|
ELSIF r.kind = 1 THEN
|
|
|
- EmLoadVar (symtab [r.idx].local,
|
|
|
- (symtab [r.idx].off + r.boff) MOD 10000H, 1)
|
|
|
+ LoadSymVar (r.idx, (symtab [r.idx].off + r.boff) MOD 10000H, 1)
|
|
|
ELSIF r.kind = 3 THEN
|
|
|
EmLoadVar (FALSE, EmStrBlob (r), 1)
|
|
|
ELSE
|
|
|
@@ -4684,6 +4840,7 @@ PROCEDURE EmCallMost (idx, cleanup : CARDINAL) ;
|
|
|
larger than a word. *)
|
|
|
VAR p : CARDINAL ;
|
|
|
BEGIN
|
|
|
+ EmitStaticLink (idx) ;
|
|
|
IF symtab [idx].defnd THEN
|
|
|
DropC (EmCall (symtab [idx].goPos))
|
|
|
ELSE
|
|
|
@@ -4742,11 +4899,10 @@ BEGIN
|
|
|
Err (ENoLib) ;
|
|
|
EXIT
|
|
|
END ;
|
|
|
- EmLoadVar (TRUE, symtab [arg.idx].off, 2) ;
|
|
|
+ LoadSymVar (arg.idx, symtab [arg.idx].off, 2) ;
|
|
|
EmPushAx ()
|
|
|
ELSE
|
|
|
- EmPushVarAddr (symtab [arg.idx].local,
|
|
|
- (symtab [arg.idx].off + arg.boff) MOD 10000H)
|
|
|
+ EmPushSymAddr (arg.idx, (symtab [arg.idx].off + arg.boff) MOD 10000H)
|
|
|
END
|
|
|
ELSIF slot > 2 THEN
|
|
|
(* A STRING VALUE parameter: push its whole slot, copied.
|
|
|
@@ -4822,11 +4978,10 @@ BEGIN
|
|
|
Err (ENoLib) ;
|
|
|
EXIT
|
|
|
END ;
|
|
|
- EmLoadVar (TRUE, symtab [arg.idx].off, 2) ;
|
|
|
+ LoadSymVar (arg.idx, symtab [arg.idx].off, 2) ;
|
|
|
EmPushAx ()
|
|
|
ELSE
|
|
|
- EmPushVarAddr (symtab [arg.idx].local,
|
|
|
- (symtab [arg.idx].off + arg.boff) MOD 10000H)
|
|
|
+ EmPushSymAddr (arg.idx, (symtab [arg.idx].off + arg.boff) MOD 10000H)
|
|
|
END
|
|
|
ELSIF slot > 2 THEN
|
|
|
(* see ParseCallArgs: push the whole string slot *)
|
|
|
@@ -5061,7 +5216,7 @@ BEGIN
|
|
|
END ;
|
|
|
IF (src.kind = 0) AND (src.cls # TString) AND (src.cls # TSet) THEN
|
|
|
IntToMbf (src.imm, rbuf) ;
|
|
|
- EmLoadVar (TRUE, symtab [r.idx].off, 2) ;
|
|
|
+ LoadSymVar (r.idx, symtab [r.idx].off, 2) ;
|
|
|
EmMovDiAx () ;
|
|
|
k := 0 ;
|
|
|
WHILE k < 6 DO
|
|
|
@@ -5073,16 +5228,15 @@ BEGIN
|
|
|
IF (src.cls = TReal) AND ((src.kind = 1) OR (src.kind = 5)) THEN
|
|
|
(* Destination pointer first, then the source address; pop SI
|
|
|
(source), DI (destination), and copy six bytes. *)
|
|
|
- EmLoadVar (TRUE, symtab [r.idx].off, 2) ;
|
|
|
+ LoadSymVar (r.idx, symtab [r.idx].off, 2) ;
|
|
|
EmPushAx () ;
|
|
|
IF src.kind = 5 THEN
|
|
|
EmPushDi ()
|
|
|
ELSIF symtab [src.idx].isVar THEN
|
|
|
- EmLoadVar (TRUE, symtab [src.idx].off, 2) ;
|
|
|
+ LoadSymVar (src.idx, symtab [src.idx].off, 2) ;
|
|
|
EmPushAx ()
|
|
|
ELSE
|
|
|
- EmPushVarAddr (symtab [src.idx].local,
|
|
|
- (symtab [src.idx].off + src.boff) MOD 10000H)
|
|
|
+ EmPushSymAddr (src.idx, (symtab [src.idx].off + src.boff) MOD 10000H)
|
|
|
END ;
|
|
|
EmPopSi () ;
|
|
|
EmPopDi () ;
|
|
|
@@ -5115,8 +5269,7 @@ BEGIN
|
|
|
k := 0 ;
|
|
|
WHILE k < 6 DO
|
|
|
EmMovAxi (ORD (rbuf [k])) ;
|
|
|
- EmStoreVar (symtab [r.idx].local,
|
|
|
- (symtab [r.idx].off + r.boff + k) MOD 10000H, 1) ;
|
|
|
+ StoreSymVar (r.idx, (symtab [r.idx].off + r.boff + k) MOD 10000H, 1) ;
|
|
|
INC (k)
|
|
|
END
|
|
|
ELSE
|
|
|
@@ -5130,8 +5283,7 @@ BEGIN
|
|
|
k := 0 ;
|
|
|
WHILE k < 6 DO
|
|
|
EmLdAlSi () ;
|
|
|
- EmStoreVar (symtab [r.idx].local,
|
|
|
- (symtab [r.idx].off + r.boff + k) MOD 10000H, 1) ;
|
|
|
+ StoreSymVar (r.idx, (symtab [r.idx].off + r.boff + k) MOD 10000H, 1) ;
|
|
|
EmIncSi () ;
|
|
|
INC (k)
|
|
|
END ;
|
|
|
@@ -5145,18 +5297,15 @@ BEGIN
|
|
|
END ;
|
|
|
k := 0 ;
|
|
|
WHILE k < 6 DO
|
|
|
- EmLoadVar (symtab [src.idx].local,
|
|
|
- (symtab [src.idx].off + src.boff + k) MOD 10000H, 1) ;
|
|
|
+ LoadSymVar (src.idx, (symtab [src.idx].off + src.boff + k) MOD 10000H, 1) ;
|
|
|
EmStDiAlOff (k) ;
|
|
|
INC (k)
|
|
|
END
|
|
|
ELSIF r.kind = 1 THEN
|
|
|
k := 0 ;
|
|
|
WHILE k < 6 DO
|
|
|
- EmLoadVar (symtab [src.idx].local,
|
|
|
- (symtab [src.idx].off + src.boff + k) MOD 10000H, 1) ;
|
|
|
- EmStoreVar (symtab [r.idx].local,
|
|
|
- (symtab [r.idx].off + r.boff + k) MOD 10000H, 1) ;
|
|
|
+ LoadSymVar (src.idx, (symtab [src.idx].off + src.boff + k) MOD 10000H, 1) ;
|
|
|
+ StoreSymVar (r.idx, (symtab [r.idx].off + r.boff + k) MOD 10000H, 1) ;
|
|
|
INC (k)
|
|
|
END
|
|
|
ELSE
|
|
|
@@ -5193,8 +5342,7 @@ BEGIN
|
|
|
RETURN
|
|
|
END ;
|
|
|
IF r.kind = 1 THEN
|
|
|
- EmPushVarAddr (symtab [r.idx].local,
|
|
|
- (symtab [r.idx].off + r.boff) MOD 10000H)
|
|
|
+ EmPushSymAddr (r.idx, (symtab [r.idx].off + r.boff) MOD 10000H)
|
|
|
ELSIF r.kind # 5 THEN
|
|
|
Err (ENoLib) ;
|
|
|
RETURN
|
|
|
@@ -5223,8 +5371,7 @@ BEGIN
|
|
|
k := 0 ;
|
|
|
WHILE k < r.setsize DO
|
|
|
EmMovAxi (ORD (sbuf [k])) ;
|
|
|
- EmStoreVar (symtab [r.idx].local,
|
|
|
- (symtab [r.idx].off + r.boff + k) MOD 10000H, 1) ;
|
|
|
+ StoreSymVar (r.idx, (symtab [r.idx].off + r.boff + k) MOD 10000H, 1) ;
|
|
|
INC (k)
|
|
|
END
|
|
|
ELSE
|
|
|
@@ -5254,8 +5401,7 @@ BEGIN
|
|
|
INC (k)
|
|
|
END
|
|
|
ELSIF src.kind = 1 THEN
|
|
|
- EmPushVarAddr (symtab [src.idx].local,
|
|
|
- (symtab [src.idx].off + src.boff) MOD 10000H) ;
|
|
|
+ EmPushSymAddr (src.idx, (symtab [src.idx].off + src.boff) MOD 10000H) ;
|
|
|
EmPushDi () ; (* destination = the field *)
|
|
|
EmMovCxi (n) ; (* strstore's limit *)
|
|
|
DropC (EmCall (TU_StrStore)) ;
|
|
|
@@ -5281,7 +5427,7 @@ BEGIN
|
|
|
RETURN
|
|
|
END ;
|
|
|
EmPushStrAddr (src) ;
|
|
|
- EmLoadVar (TRUE, symtab [r.idx].off, 2) ;
|
|
|
+ LoadSymVar (r.idx, symtab [r.idx].off, 2) ;
|
|
|
EmPushAx () ;
|
|
|
EmMovCxi ((VarSize (r) - 1) MOD 10000H) ;
|
|
|
DropC (EmCall (TU_StrStore)) ;
|
|
|
@@ -5296,7 +5442,7 @@ BEGIN
|
|
|
Err (ENoLib) ;
|
|
|
RETURN
|
|
|
END ;
|
|
|
- EmStoreVarIndPrep (symtab [r.idx].off) ;
|
|
|
+ StoreVarIndPrepSym (r.idx) ;
|
|
|
ParseExpr (src) ;
|
|
|
LoadAtom (src) ;
|
|
|
EmPopDi () ;
|
|
|
@@ -5320,18 +5466,14 @@ BEGIN
|
|
|
`EXY := FactorCh' before Val. *)
|
|
|
IF src.kind = 0 THEN
|
|
|
EmMovAxi (1) ;
|
|
|
- EmStoreVar (symtab [r.idx].local,
|
|
|
- (symtab [r.idx].off + r.boff) MOD 10000H, 1) ;
|
|
|
+ StoreSymVar (r.idx, (symtab [r.idx].off + r.boff) MOD 10000H, 1) ;
|
|
|
EmMovAxi (W16 (src.imm)) ;
|
|
|
- EmStoreVar (symtab [r.idx].local,
|
|
|
- (symtab [r.idx].off + r.boff + 1) MOD 10000H, 1)
|
|
|
+ StoreSymVar (r.idx, (symtab [r.idx].off + r.boff + 1) MOD 10000H, 1)
|
|
|
ELSE
|
|
|
LoadAtom (src) ;
|
|
|
- EmStoreVar (symtab [r.idx].local,
|
|
|
- (symtab [r.idx].off + r.boff + 1) MOD 10000H, 1) ;
|
|
|
+ StoreSymVar (r.idx, (symtab [r.idx].off + r.boff + 1) MOD 10000H, 1) ;
|
|
|
EmMovAxi (1) ;
|
|
|
- EmStoreVar (symtab [r.idx].local,
|
|
|
- (symtab [r.idx].off + r.boff) MOD 10000H, 1)
|
|
|
+ StoreSymVar (r.idx, (symtab [r.idx].off + r.boff) MOD 10000H, 1)
|
|
|
END ;
|
|
|
RETURN
|
|
|
END ;
|
|
|
@@ -5349,8 +5491,7 @@ BEGIN
|
|
|
destination at [BP+4] - the caller pops both, and the limit is a
|
|
|
full MOV CX,imm16 because this runtime reads it in CX outright. *)
|
|
|
IF src.kind = 1 THEN
|
|
|
- EmPushVarAddr (symtab [src.idx].local,
|
|
|
- (symtab [src.idx].off + src.boff) MOD 10000H)
|
|
|
+ EmPushSymAddr (src.idx, (symtab [src.idx].off + src.boff) MOD 10000H)
|
|
|
ELSIF src.kind = 5 THEN
|
|
|
(* A string element reached through DI, including a pointer
|
|
|
dereference: Buffer^[i]. Its address is already in DI. *)
|
|
|
@@ -5359,8 +5500,7 @@ BEGIN
|
|
|
Err (ENoLib) ; (* a computed string is not a value *)
|
|
|
RETURN
|
|
|
END ;
|
|
|
- EmPushVarAddr (symtab [r.idx].local,
|
|
|
- (symtab [r.idx].off + r.boff) MOD 10000H) ;
|
|
|
+ EmPushSymAddr (r.idx, (symtab [r.idx].off + r.boff) MOD 10000H) ;
|
|
|
EmMovCxi ((VarSize (r) - 1) MOD 10000H) ;
|
|
|
DropC (EmCall (TU_StrStore)) ;
|
|
|
EmAddSp (4) ;
|
|
|
@@ -5371,13 +5511,11 @@ BEGIN
|
|
|
n := VarSize (r) - 1
|
|
|
END ;
|
|
|
EmMovAxi (n) ;
|
|
|
- EmStoreVar (symtab [r.idx].local,
|
|
|
- (symtab [r.idx].off + r.boff) MOD 10000H, 1) ;
|
|
|
+ StoreSymVar (r.idx, (symtab [r.idx].off + r.boff) MOD 10000H, 1) ;
|
|
|
k := 0 ;
|
|
|
WHILE k < n DO
|
|
|
EmMovAxi (ORD (strPool [strOff [src.strx] + k])) ;
|
|
|
- EmStoreVar (symtab [r.idx].local,
|
|
|
- (symtab [r.idx].off + r.boff + 1 + k) MOD 10000H, 1) ;
|
|
|
+ StoreSymVar (r.idx, (symtab [r.idx].off + r.boff + 1 + k) MOD 10000H, 1) ;
|
|
|
INC (k)
|
|
|
END ;
|
|
|
RETURN
|
|
|
@@ -5411,9 +5549,7 @@ BEGIN
|
|
|
END ;
|
|
|
ParseExpr (src) ;
|
|
|
LoadAtom (src) ;
|
|
|
- EmStoreVar (symtab [r.idx].local,
|
|
|
- (symtab [r.idx].off + r.boff) MOD 10000H,
|
|
|
- VarSize (r))
|
|
|
+ StoreSymVar (r.idx, (symtab [r.idx].off + r.boff) MOD 10000H, VarSize (r))
|
|
|
END Assignment ;
|
|
|
|
|
|
PROCEDURE Compound () ;
|
|
|
@@ -5557,8 +5693,7 @@ BEGIN
|
|
|
p := symtab [arg.idx].elem ;
|
|
|
EmMovAxi (symtab [p].size) ;
|
|
|
EmPushAx () ; (* size -> [BP+6] *)
|
|
|
- EmPushVarAddr (symtab [arg.idx].local,
|
|
|
- (symtab [arg.idx].off + arg.boff) MOD 10000H) ;
|
|
|
+ EmPushSymAddr (arg.idx, (symtab [arg.idx].off + arg.boff) MOD 10000H) ;
|
|
|
DropC (EmCall (TU_HeapNew)) ;
|
|
|
EmAddSp (4)
|
|
|
ELSIF OK () THEN
|
|
|
@@ -5749,10 +5884,8 @@ BEGIN
|
|
|
IF OK () AND (dummy.kind = 1) AND (dummy.cls = TScalar)
|
|
|
AND (VarSize (dummy) = 2) AND (errV.kind = 1)
|
|
|
AND (errV.cls = TScalar) AND (VarSize (errV) = 2) THEN
|
|
|
- EmPushVarAddr (symtab [errV.idx].local,
|
|
|
- (symtab [errV.idx].off + errV.boff) MOD 10000H) ;
|
|
|
- EmPushVarAddr (symtab [dummy.idx].local,
|
|
|
- (symtab [dummy.idx].off + dummy.boff) MOD 10000H) ;
|
|
|
+ EmPushSymAddr (errV.idx, (symtab [errV.idx].off + errV.boff) MOD 10000H) ;
|
|
|
+ EmPushSymAddr (dummy.idx, (symtab [dummy.idx].off + dummy.boff) MOD 10000H) ;
|
|
|
EmPushStrAddr (arg) ;
|
|
|
DropC (EmCall (TU_ValInt)) ;
|
|
|
EmAddSp (6)
|
|
|
@@ -5760,8 +5893,7 @@ BEGIN
|
|
|
((dummy.kind = 1) OR (dummy.kind = 5)) AND
|
|
|
(errV.kind = 1) AND (errV.cls = TScalar) AND (VarSize (errV) = 2)
|
|
|
THEN
|
|
|
- EmPushVarAddr (symtab [errV.idx].local,
|
|
|
- (symtab [errV.idx].off + errV.boff) MOD 10000H) ;
|
|
|
+ EmPushSymAddr (errV.idx, (symtab [errV.idx].off + errV.boff) MOD 10000H) ;
|
|
|
EmPushRealAddr (dummy) ;
|
|
|
EmPushStrAddr (arg) ;
|
|
|
DropC (EmCall (TU_ValReal)) ;
|
|
|
@@ -5819,8 +5951,7 @@ BEGIN
|
|
|
IF arg.kind = 5 THEN
|
|
|
EmPushDi ()
|
|
|
ELSE
|
|
|
- EmPushVarAddr (symtab [arg.idx].local,
|
|
|
- (symtab [arg.idx].off + arg.boff) MOD 10000H)
|
|
|
+ EmPushSymAddr (arg.idx, (symtab [arg.idx].off + arg.boff) MOD 10000H)
|
|
|
END ;
|
|
|
IF MatchDelim (':') THEN
|
|
|
ParseExpr (dummy) ;
|
|
|
@@ -5888,8 +6019,7 @@ BEGIN
|
|
|
IF OK () THEN
|
|
|
IF dummy.cls = TString THEN
|
|
|
EmPushStrAddr (dummy) ;
|
|
|
- EmPushVarAddr (symtab [arg.idx].local,
|
|
|
- (symtab [arg.idx].off + arg.boff) MOD 10000H) ;
|
|
|
+ EmPushSymAddr (arg.idx, (symtab [arg.idx].off + arg.boff) MOD 10000H) ;
|
|
|
DropC (EmCall (TU_FileAssign)) ;
|
|
|
EmAddSp (4)
|
|
|
ELSE
|
|
|
@@ -5911,8 +6041,7 @@ BEGIN
|
|
|
IF OK () THEN
|
|
|
IF (arg.kind = 1) AND
|
|
|
((arg.cls = TFile) OR (arg.cls = TText) OR (arg.cls = TUntyp)) THEN
|
|
|
- EmPushVarAddr (symtab [arg.idx].local,
|
|
|
- (symtab [arg.idx].off + arg.boff) MOD 10000H) ;
|
|
|
+ EmPushSymAddr (arg.idx, (symtab [arg.idx].off + arg.boff) MOD 10000H) ;
|
|
|
IF which = BI_Reset THEN
|
|
|
DropC (EmCall (TU_FileReset))
|
|
|
ELSIF which = BI_Rewrite THEN
|
|
|
@@ -5992,8 +6121,7 @@ BEGIN
|
|
|
EmMovAxi ((VarSize (dummy) - 1) MOD 10000H) ;
|
|
|
EmPushAx () ;
|
|
|
EmPushStrAddr (dummy) ;
|
|
|
- EmPushVarAddr (symtab [arg.idx].local,
|
|
|
- (symtab [arg.idx].off + arg.boff) MOD 10000H) ;
|
|
|
+ EmPushSymAddr (arg.idx, (symtab [arg.idx].off + arg.boff) MOD 10000H) ;
|
|
|
DropC (EmCall (TU_FileReadln)) ;
|
|
|
EmAddSp (6)
|
|
|
ELSIF OK () THEN
|
|
|
@@ -6123,11 +6251,10 @@ BEGIN
|
|
|
Err (ENoLib) ;
|
|
|
RETURN
|
|
|
END ;
|
|
|
- EmLoadVar (TRUE, symtab [arg.idx].off, 2) ;
|
|
|
+ LoadSymVar (arg.idx, symtab [arg.idx].off, 2) ;
|
|
|
EmPushAx ()
|
|
|
ELSE
|
|
|
- EmPushVarAddr (symtab [arg.idx].local,
|
|
|
- (symtab [arg.idx].off + arg.boff) MOD 10000H)
|
|
|
+ EmPushSymAddr (arg.idx, (symtab [arg.idx].off + arg.boff) MOD 10000H)
|
|
|
END ;
|
|
|
IF acls = TString THEN
|
|
|
(* readln(s)/read(s) of a string variable: TPSRC8 prdstr
|
|
|
@@ -6219,11 +6346,10 @@ BEGIN
|
|
|
ELSIF symtab [arg.idx].isVar THEN
|
|
|
(* VAR string: the slot holds the address of the
|
|
|
caller's characters; push that, not the slot. *)
|
|
|
- EmLoadVar (TRUE, symtab [arg.idx].off, 2) ;
|
|
|
+ LoadSymVar (arg.idx, symtab [arg.idx].off, 2) ;
|
|
|
EmPushAx ()
|
|
|
ELSE
|
|
|
- EmPushVarAddr (symtab [arg.idx].local,
|
|
|
- (symtab [arg.idx].off + arg.boff) MOD 10000H)
|
|
|
+ EmPushSymAddr (arg.idx, (symtab [arg.idx].off + arg.boff) MOD 10000H)
|
|
|
END ;
|
|
|
ent := TU_WrStr
|
|
|
ELSE
|
|
|
@@ -6239,8 +6365,7 @@ BEGIN
|
|
|
IF arg.kind = 5 THEN
|
|
|
EmPushDi ()
|
|
|
ELSE
|
|
|
- EmPushVarAddr (symtab [arg.idx].local,
|
|
|
- (symtab [arg.idx].off + arg.boff) MOD 10000H)
|
|
|
+ EmPushSymAddr (arg.idx, (symtab [arg.idx].off + arg.boff) MOD 10000H)
|
|
|
END ;
|
|
|
IF MatchDelim (':') THEN
|
|
|
ParseExpr (dummy) ;
|
|
|
@@ -6492,8 +6617,7 @@ BEGIN
|
|
|
END ;
|
|
|
ParseExpr (src) ;
|
|
|
LoadAtom (src) ;
|
|
|
- EmStoreVar (symtab [idx].local, symtab [idx].off,
|
|
|
- symtab [idx].size) ;
|
|
|
+ StoreSymVar (idx, symtab [idx].off, symtab [idx].size) ;
|
|
|
IF NOT MatchKey (tok) THEN
|
|
|
Err (ESimpType) ;
|
|
|
RETURN
|
|
|
@@ -6528,8 +6652,7 @@ BEGIN
|
|
|
8086, so EmMovCxSp is POP CX ; PUSH CX, an observational no-op that
|
|
|
leaves the bound in place. *)
|
|
|
EmMovCxSp () ;
|
|
|
- EmLoadVar (symtab [idx].local, symtab [idx].off,
|
|
|
- symtab [idx].size) ;
|
|
|
+ LoadSymVar (idx, symtab [idx].off, symtab [idx].size) ;
|
|
|
EmCmpAxCx () ;
|
|
|
IF dow THEN
|
|
|
zj := EmJcc (8CH, 0) (* JL -> done *)
|
|
|
@@ -6552,15 +6675,13 @@ BEGIN
|
|
|
A WHILE nested inside the FOR saves and restores its own range and
|
|
|
leaves this one intact. *)
|
|
|
(* step *)
|
|
|
- EmLoadVar (symtab [idx].local, symtab [idx].off,
|
|
|
- symtab [idx].size) ;
|
|
|
+ LoadSymVar (idx, symtab [idx].off, symtab [idx].size) ;
|
|
|
IF dow THEN
|
|
|
EmDecAx ()
|
|
|
ELSE
|
|
|
EmIncAx ()
|
|
|
END ;
|
|
|
- EmStoreVar (symtab [idx].local, symtab [idx].off,
|
|
|
- symtab [idx].size) ;
|
|
|
+ StoreSymVar (idx, symtab [idx].off, symtab [idx].size) ;
|
|
|
DropC (EmJmpNear (L1)) ;
|
|
|
SetPatTgt (zj, pc) ; (* done: *)
|
|
|
(* A WHILE loop here, not a FOR over the exit range. The range is
|
|
|
@@ -7553,7 +7674,7 @@ BEGIN
|
|
|
INC (k)
|
|
|
END
|
|
|
ELSE
|
|
|
- EmLoadVar (TRUE, symtab [resultVar].off, symtab [resultVar].size)
|
|
|
+ LoadSymVar (resultVar, symtab [resultVar].off, symtab [resultVar].size)
|
|
|
END
|
|
|
END
|
|
|
END
|
|
|
@@ -7593,6 +7714,7 @@ VAR nm : ARRAY [0..MaxName] OF CHAR ;
|
|
|
isFunc, groupVar : BOOLEAN ;
|
|
|
saveNest, saveLoc, saveRes, saveF : CARDINAL ;
|
|
|
saveLB, savePO, saveRP : CARDINAL ;
|
|
|
+ saveProc, saveStatic, staticOff : CARDINAL ;
|
|
|
saveR : BOOLEAN ;
|
|
|
realResult : BOOLEAN ;
|
|
|
reusedFwd : BOOLEAN ;
|
|
|
@@ -7619,6 +7741,10 @@ BEGIN
|
|
|
IF isFunc THEN
|
|
|
symtab [old].tag := KFunc
|
|
|
END ;
|
|
|
+ saveProc := curProc ;
|
|
|
+ saveStatic := curStaticOff ;
|
|
|
+ symtab [old].parent := curProc ;
|
|
|
+ curProc := old ;
|
|
|
saveNest := lexnest ;
|
|
|
saveLoc := locFree ;
|
|
|
saveRes := resultVar ;
|
|
|
@@ -7820,20 +7946,44 @@ BEGIN
|
|
|
curIsFunc := (saveF # 0) ;
|
|
|
locBytes := saveLB ;
|
|
|
parmOff := savePO ;
|
|
|
+ curProc := saveProc ;
|
|
|
+ curStaticOff := saveStatic ;
|
|
|
RETURN
|
|
|
END ;
|
|
|
- (* body *)
|
|
|
+ (* A procedure declared inside another one receives its lexical parent's
|
|
|
+ frame in DX. Reserve a hidden local for it before ordinary locals, so
|
|
|
+ nested code can walk the static chain. Top-level procedures have no
|
|
|
+ parent frame and no slot. *)
|
|
|
+ IF symtab [old].level > 0 THEN
|
|
|
+ staticOff := (locFree - 1) MOD 10000H ;
|
|
|
+ locFree := (locFree - 2) MOD 10000H ;
|
|
|
+ locBytes := locBytes + 2 ;
|
|
|
+ symtab [old].staticOff := staticOff ;
|
|
|
+ curStaticOff := staticOff
|
|
|
+ ELSE
|
|
|
+ staticOff := 0 ;
|
|
|
+ curStaticOff := 0
|
|
|
+ END ;
|
|
|
+ (* Body. Nested procedures are emitted BEFORE the enclosing procedure's
|
|
|
+ prologue: otherwise execution entering the outer procedure falls straight
|
|
|
+ through the nested bodies. The outer entry point is therefore set only
|
|
|
+ after DefPart has emitted them. *)
|
|
|
+ DefPart () ; (* nested declarations; stops at BEGIN *)
|
|
|
symtab [old].goPos := pc ;
|
|
|
symtab [old].defnd := TRUE ;
|
|
|
EmPushBp () ;
|
|
|
EmMovBpSp () ;
|
|
|
+ IF symtab [old].level > 0 THEN
|
|
|
+ (* The caller passed the parent frame in DX. *)
|
|
|
+ EmMovAxDx () ;
|
|
|
+ EmStoreVar (TRUE, staticOff, 2)
|
|
|
+ END ;
|
|
|
IF resultIsReal THEN
|
|
|
(* The caller put the six-byte result destination in DI. Save it
|
|
|
before declarations/body can reuse DI. *)
|
|
|
EmMovAxDi () ;
|
|
|
EmStoreVar (TRUE, resultPtrOff, 2)
|
|
|
END ;
|
|
|
- DefPart () ; (* nested declarations; stops at BEGIN *)
|
|
|
IF locBytes > 0 THEN
|
|
|
EmSubSp (locBytes)
|
|
|
END ;
|
|
|
@@ -7864,7 +8014,9 @@ BEGIN
|
|
|
resultPtrOff := saveRP ;
|
|
|
curIsFunc := (saveF # 0) ;
|
|
|
locBytes := saveLB ;
|
|
|
- parmOff := savePO
|
|
|
+ parmOff := savePO ;
|
|
|
+ curProc := saveProc ;
|
|
|
+ curStaticOff := saveStatic
|
|
|
END ProcFunc ;
|
|
|
|
|
|
PROCEDURE DefType () ;
|
|
|
@@ -8163,6 +8315,8 @@ BEGIN
|
|
|
brkN := 0 ;
|
|
|
caseN := 0 ;
|
|
|
lexnest := 0 ;
|
|
|
+ curProc := 0 ;
|
|
|
+ curStaticOff := 0 ;
|
|
|
curIsFunc := FALSE ;
|
|
|
resultVar := 0 ;
|
|
|
resultIsReal := FALSE ;
|