MODULE DevCPV486; (* THIS IS TEXT COPY OF BlackBox 1.6-rc6 Dev/Mod/CPV486.odc *) (* DO NOT EDIT *) IMPORT SYSTEM, DevCPM, DevCPT, DevCPE, DevCPH, DevCPL486, DevCPC486; CONST processor* = 10; (* for i386 *) (* object modes *) Var = 1; VarPar = 2; Con = 3; Fld = 4; Typ = 5; LProc = 6; XProc = 7; SProc = 8; CProc = 9; IProc = 10; Mod = 11; Head = 12; TProc = 13; (* item modes for i386 *) Ind = 14; Abs = 15; Stk = 16; Cond = 17; Reg = 18; DInd = 19; (* symbol values and ops *) times = 1; slash = 2; div = 3; mod = 4; and = 5; plus = 6; minus = 7; or = 8; eql = 9; neq = 10; lss = 11; leq = 12; gtr = 13; geq = 14; in = 15; is = 16; ash = 17; msk = 18; len = 19; conv = 20; abs = 21; cap = 22; odd = 23; not = 33; (*SYSTEM*) adr = 24; cc = 25; bit = 26; lsh = 27; rot = 28; val = 29; min = 34; max = 35; typfn = 36; thisrecfn = 45; thisarrfn = 46; shl = 50; shr = 51; lshr = 52; xor = 53; (* structure forms *) Undef = 0; Byte = 1; Bool = 2; Char8 = 3; Int8 = 4; Int16 = 5; Int32 = 6; Real32 = 7; Real64 = 8; Set = 9; String8 = 10; NilTyp = 11; NoTyp = 12; Pointer = 13; ProcTyp = 14; Comp = 15; Char16 = 16; String16 = 17; Int64 = 18; VString16to8 = 29; VString8 = 30; VString16 = 31; realSet = {Real32, Real64}; (* composite structure forms *) Basic = 1; Array = 2; DynArr = 3; Record = 4; (* nodes classes *) Nvar = 0; Nvarpar = 1; Nfield = 2; Nderef = 3; Nindex = 4; Nguard = 5; Neguard = 6; Nconst = 7; Ntype = 8; Nproc = 9; Nupto = 10; Nmop = 11; Ndop = 12; Ncall = 13; Ninittd = 14; Nif = 15; Ncaselse = 16; Ncasedo = 17; Nenter = 18; Nassign = 19; Nifelse =20; Ncase = 21; Nwhile = 22; Nrepeat = 23; Nloop = 24; Nexit = 25; Nreturn = 26; Nwith = 27; Ntrap = 28; Ncomp = 30; Ndrop = 50; Nlabel = 51; Ngoto = 52; Njsr = 53; Nret = 54; Ncmp = 55; (*function number*) assign = 0; newfn = 1; incfn = 13; decfn = 14; inclfn = 15; exclfn = 16; copyfn = 18; assertfn = 32; (*SYSTEM function number*) getfn = 24; putfn = 25; getrfn = 26; putrfn = 27; sysnewfn = 30; movefn = 31; (* COM function number *) validfn = 40; queryfn = 42; (* procedure flags (conval.setval) *) hasBody = 1; isRedef = 2; slNeeded = 3; imVar = 4; isHidden = 29; isGuarded = 30; isCallback = 31; (* attribute flags (attr.adr, struct.attribute, proc.conval.setval) *) newAttr = 16; absAttr = 17; limAttr = 18; empAttr = 19; extAttr = 20; (* case statement flags (conval.setval) *) useTable = 1; useTree = 2; (* registers *) AX = 0; CX = 1; DX = 2; BX = 3; SP = 4; BP = 5; SI = 6; DI = 7; AH = 4; CH = 5; DH = 6; BH = 7; stk = 31; mem = 30; con = 29; float = 28; high = 27; short = 26; deref = 25; loaded = 24; wreg = {AX, BX, CX, DX, SI, DI}; (* module visibility of objects *) internal = 0; external = 1; externalR = 2; inPar = 3; outPar = 4; (* sysflag *) untagged = 1; noAlign = 3; align2 = 4; align8 = 6; union = 7; interface = 10; guarded = 8; noframe = 16; nilBit = 1; enumBits = 8; new = 1; iid = 2; stackArray = 120; (* system trap numbers *) withTrap = -1; caseTrap = -2; funcTrap = -3; typTrap = -4; recTrap = -5; ranTrap = -6; inxTrap = -7; copyTrap = -8; ParOff = 8; interfaceSize = 16; (* SIZE(Kernel.Interface) *) addRefFP = 4E27A847H; (* fingerprint of AddRef and Release procedures *) intHandlerFP = 24B0EAE3H; (* fingerprint of InterfaceTrapHandler *) numPreIntProc = 2; VAR Exit, Return: DevCPL486.Label; assert, sequential: BOOLEAN; nesting, actual: INTEGER; query, addRef, release, release2: DevCPT.Object; PROCEDURE Init*(opt: SET); CONST ass = 2; BEGIN DevCPL486.Init(opt); DevCPC486.Init(opt); assert := ass IN opt; DevCPM.breakpc := MAX(INTEGER); query := NIL; addRef := NIL; release := NIL; release2 := NIL; DevCPC486.intHandler := NIL; END Init; PROCEDURE Close*; BEGIN DevCPL486.Close END Close; PROCEDURE Align(VAR offset: INTEGER; align: INTEGER); BEGIN CASE align OF 1: (* ok *) | 2: INC(offset, offset MOD 2) | 4: INC(offset, (-offset) MOD 4) | 8: INC(offset, (-offset) MOD 8) END END Align; PROCEDURE NegAlign(VAR offset: INTEGER; align: INTEGER); BEGIN CASE align OF 1: (* ok *) | 2: DEC(offset, offset MOD 2) | 4: DEC(offset, offset MOD 4) | 8: DEC(offset, offset MOD 8) END END NegAlign; PROCEDURE Base(typ: DevCPT.Struct; limit: INTEGER): INTEGER; (* typ.comp # DynArr *) VAR align: INTEGER; BEGIN WHILE typ.comp = Array DO typ := typ.BaseTyp END ; IF typ.comp = Record THEN align := typ.align ELSE align := typ.size; END; IF align > limit THEN RETURN limit ELSE RETURN align END END Base; (* ----------------------------------------------------- reference implementation of TypeSize for portable symbol files mandatory for all non-system structures PROCEDURE TypeSize (typ: DevCPT.Struct); VAR f, c: SHORTINT; offset: LONGINT; fld: DevCPT.Object; btyp: DevCPT.Struct; BEGIN IF typ.size = -1 THEN f := typ.form; c := typ.comp; btyp := typ.BaseTyp; IF c = Record THEN IF btyp = NIL THEN offset := 0 ELSE TypeSize(btyp); offset := btyp.size END; fld := typ.link; WHILE (fld # NIL) & (fld.mode = Fld) DO btyp := fld.typ; TypeSize(btyp); IF btyp.size >= 4 THEN INC(offset, (-offset) MOD 4) ELSIF btyp.size >= 2 THEN INC(offset, offset MOD 2) END; fld.adr := offset; INC(offset, btyp.size); fld := fld.link END; IF offset > 2 THEN INC(offset, (-offset) MOD 4) END; typ.size := offset; typ.align := 4; typ.n := -1 (* methods not counted yet *) ELSIF c = Array THEN TypeSize(btyp); typ.size := typ.n * btyp.size ELSIF f = Pointer THEN typ.size := DevCPM.PointerSize ELSIF f = ProcTyp THEN typ.size := DevCPM.ProcSize ELSE (* c = DynArr *) TypeSize(btyp); IF btyp.comp = DynArr THEN typ.size := btyp.size + 4 ELSE typ.size := 8 END END END END TypeSize; ----------------------------------------------------- *) PROCEDURE GTypeSize (typ: DevCPT.Struct; guarded: BOOLEAN); VAR f, c: BYTE; offset, align, falign, alignLimit: INTEGER; fld: DevCPT.Object; btyp: DevCPT.Struct; name: DevCPT.Name; BEGIN IF typ.untagged THEN guarded := TRUE END; IF typ = DevCPT.undftyp THEN DevCPM.err(58) ELSIF typ.size = -1 THEN f := typ.form; c := typ.comp; btyp := typ.BaseTyp; IF c = Record THEN IF btyp = NIL THEN offset := 0; align := 1; ELSE GTypeSize(btyp, guarded); offset := btyp.size; align := btyp.align END ; IF typ.sysflag = noAlign THEN alignLimit := 1 ELSIF typ.sysflag = align2 THEN alignLimit := 2 ELSIF typ.sysflag = align8 THEN alignLimit := 8 ELSE alignLimit := 4 END; fld := typ.link; WHILE (fld # NIL) & (fld.mode = Fld) DO btyp := fld.typ; GTypeSize(btyp, guarded); IF typ.sysflag > 0 THEN falign := Base(btyp, alignLimit) ELSIF btyp.size >= 4 THEN falign := 4 ELSIF btyp.size >= 2 THEN falign := 2 ELSE falign := 1 END; IF typ.sysflag = union THEN fld.adr := 0; IF btyp.size > offset THEN offset := btyp.size END; ELSE Align(offset, falign); fld.adr := offset; IF offset <= MAX(INTEGER) - 4 - btyp.size THEN INC(offset, btyp.size) ELSE offset := 4; DevCPM.Mark(214, typ.txtpos) END END; IF falign > align THEN align := falign END ; fld := fld.link END; (* IF (typ.sysflag = interface) & (typ.BaseTyp = NIL) THEN fld := DevCPT.NewObj(); fld.name^ := DevCPM.HdPtrName; fld.mode := Fld; fld.typ := DevCPT.undftyp; fld.adr := 8; fld.right := typ.link; typ.link := fld; fld := DevCPT.NewObj(); fld.name^ := DevCPM.HdPtrName; fld.mode := Fld; fld.typ := DevCPT.undftyp; fld.adr := 12; typ.link.link := fld; typ.link.left := fld; offset := interfaceSize; align := 4 END; *) IF typ.sysflag <= 0 THEN align := 4 END; typ.align := align; IF (typ.sysflag > 0) OR (offset > 2) THEN Align(offset, align) END; typ.size := offset; typ.n := -1 (* methods not counted yet *) ELSIF c = Array THEN GTypeSize(btyp, guarded); IF (btyp.size = 0) OR (typ.n <= MAX(INTEGER) DIV btyp.size) THEN typ.size := typ.n * btyp.size ELSE typ.size := 4; DevCPM.Mark(214, typ.txtpos) END ELSIF f = Pointer THEN typ.size := DevCPM.PointerSize; IF guarded & ~typ.untagged THEN DevCPM.Mark(143, typ.txtpos) END ELSIF f = ProcTyp THEN typ.size := DevCPM.ProcSize ELSE (* c = DynArr *) GTypeSize(btyp, guarded); IF (typ.sysflag = untagged) OR typ.untagged THEN typ.size := 4 ELSE IF btyp.comp = DynArr THEN typ.size := btyp.size + 4 ELSE typ.size := 8 END END END END END GTypeSize; PROCEDURE TypeSize*(typ: DevCPT.Struct); (* also called from DevCPT.InStruct for arrays *) BEGIN GTypeSize(typ, FALSE) END TypeSize; PROCEDURE GetComKernel; VAR name: DevCPT.Name; mod: DevCPT.Object; BEGIN IF addRef = NIL THEN DevCPT.OpenScope(SHORT(SHORT(-DevCPT.nofGmod)), NIL); DevCPT.topScope.name := DevCPT.NewName("$$"); name := "AddRef"; DevCPT.Insert(name, addRef); addRef.mode := XProc; addRef.fprint := addRefFP; addRef.fpdone := TRUE; name := "Release"; DevCPT.Insert(name, release); release.mode := XProc; release.fprint := addRefFP; release.fpdone := TRUE; name := "Release2"; DevCPT.Insert(name, release2); release2.mode := XProc; release2.fprint := addRefFP; release2.fpdone := TRUE; name := "InterfaceTrapHandler"; DevCPT.Insert(name, DevCPC486.intHandler); DevCPC486.intHandler.mode := XProc; DevCPC486.intHandler.fprint := intHandlerFP; DevCPC486.intHandler.fpdone := TRUE; DevCPT.GlbMod[DevCPT.nofGmod] := DevCPT.topScope; INC(DevCPT.nofGmod); DevCPT.CloseScope; END END GetComKernel; PROCEDURE EnumTProcs(rec: DevCPT.Struct); (* method numbers in declaration order *) VAR btyp: DevCPT.Struct; obj, redef: DevCPT.Object; BEGIN IF rec.n = -1 THEN rec.n := 0; btyp := rec.BaseTyp; IF btyp # NIL THEN EnumTProcs(btyp); rec.n := btyp.n; END; obj := rec.strobj.link; WHILE obj # NIL DO DevCPT.FindBaseField(obj.name^, rec, redef); IF redef # NIL THEN obj.num := redef.num (*mthno*); IF ~(isRedef IN obj.conval.setval) OR (redef.conval.setval * {extAttr, absAttr, empAttr} = {}) THEN DevCPM.Mark(119, rec.txtpos) END ELSE obj.num := rec.n; INC(rec.n) END ; IF obj.conval.setval * {hasBody, absAttr, empAttr} = {} THEN DevCPM.Mark(129, obj.adr) END; obj := obj.nlink END END END EnumTProcs; PROCEDURE CountTProcs(rec: DevCPT.Struct); VAR btyp: DevCPT.Struct; comProc: INTEGER; m, rel: DevCPT.Object; name: DevCPT.Name; PROCEDURE TProcs(obj: DevCPT.Object); (* obj.mnolev = 0, TProcs of base type already counted *) VAR redef: DevCPT.Object; BEGIN IF obj # NIL THEN TProcs(obj.left); IF obj.mode = TProc THEN DevCPT.FindBaseField(obj.name^, rec, redef); (* obj.adr := 0 *) IF redef # NIL THEN obj.num := redef.num (*mthno*); IF (redef.link # NIL) & (redef.link.typ.sysflag = interface) THEN obj.num := numPreIntProc + comProc - 1 - obj.num END; IF ~(isRedef IN obj.conval.setval) OR (redef.conval.setval * {extAttr, absAttr, empAttr} = {}) THEN DevCPM.Mark(119, rec.txtpos) END ELSE obj.num := rec.n; INC(rec.n) END ; IF obj.conval.setval * {hasBody, absAttr, empAttr} = {} THEN DevCPM.Mark(129, obj.adr) END END ; TProcs(obj.right) END END TProcs; BEGIN IF rec.n = -1 THEN comProc := 0; IF rec.untagged THEN rec.n := 0 ELSE rec.n := DevCPT.anytyp.n END; btyp := rec.BaseTyp; IF btyp # NIL THEN IF btyp.sysflag = interface THEN EnumTProcs(btyp); rec.n := btyp.n + numPreIntProc; comProc := btyp.n; ELSE CountTProcs(btyp); rec.n := btyp.n END END; WHILE (btyp # NIL) & (btyp # DevCPT.undftyp) & (btyp.sysflag # interface) DO btyp := btyp.BaseTyp END; IF (btyp # NIL) & (btyp.sysflag = interface) THEN IF comProc > 0 THEN name := "QueryInterface"; DevCPT.FindField(name, rec, m); IF m.link.typ.sysflag = interface THEN DevCPT.InsertField(name, rec, m); m.mode := TProc; m.typ := rec; m.conval := DevCPT.NewConst(); m.conval.setval := {isRedef, hasBody, isCallback, extAttr}; m.nlink := query; query := m END; name := "AddRef"; DevCPT.InsertField(name, rec, m); m.mode := TProc; m.mnolev := 0; m.conval := DevCPT.NewConst(); m.conval.setval := {isRedef, hasBody, isCallback, isHidden, extAttr}; GetComKernel; addRef.used := TRUE; m.adr := -1; m.nlink := addRef; END; name := "RELEASE"; DevCPT.FindField(name, rec, rel); IF (rel # NIL) & (rel.link.typ = DevCPT.anyptrtyp) THEN rel := NIL END; IF (comProc > 0) OR (rel # NIL) THEN name := "Release"; DevCPT.InsertField(name, rec, m); m.mode := TProc; m.mnolev := 0; m.conval := DevCPT.NewConst(); m.conval.setval := {isRedef, hasBody, isCallback, isHidden, extAttr}; GetComKernel; m.adr := -1; IF rel # NIL THEN release2.used := TRUE; m.nlink := release2 ELSE release.used := TRUE; m.nlink := release END END END; TProcs(rec.link); END END CountTProcs; PROCEDURE ^Parameters(firstPar, proc: DevCPT.Object); PROCEDURE ^TProcedures(obj: DevCPT.Object); PROCEDURE TypeAlloc(typ: DevCPT.Struct); VAR f, c: SHORTINT; fld: DevCPT.Object; btyp: DevCPT.Struct; BEGIN IF ~typ.allocated THEN (* not imported, not predefined, not allocated yet *) typ.allocated := TRUE; TypeSize(typ); f := typ.form; c := typ.comp; btyp := typ.BaseTyp; IF c = Record THEN IF typ.sysflag = interface THEN EnumTProcs(typ); ELSE CountTProcs(typ) END; IF typ.extlev > 14 THEN DevCPM.Mark(233, typ.txtpos) END; IF btyp # NIL THEN TypeAlloc(btyp) END; IF ~typ.untagged THEN DevCPE.AllocTypDesc(typ) END; fld := typ.link; WHILE (fld # NIL) & (fld.mode = Fld) DO TypeAlloc(fld.typ); fld := fld.link END; TProcedures(typ.link) ELSIF f = Pointer THEN IF btyp = DevCPT.undftyp THEN DevCPM.Mark(128, typ.txtpos) ELSE TypeAlloc(btyp); END ELSIF f = ProcTyp THEN TypeAlloc(btyp); Parameters(typ.link, NIL) ELSE (* c IN {Array, DynArr} *) TypeAlloc(btyp); IF (btyp.comp = DynArr) & btyp.untagged & ~typ.untagged THEN DevCPM.Mark(225, typ.txtpos) END; END END END TypeAlloc; PROCEDURE NumOfIntProc (typ: DevCPT.Struct): INTEGER; BEGIN WHILE (typ # NIL) & (typ.sysflag # interface) DO typ := typ.BaseTyp END; IF typ # NIL THEN RETURN typ.n ELSE RETURN 0 END END NumOfIntProc; PROCEDURE Parameters(firstPar, proc: DevCPT.Object); (* firstPar.mnolev = 0 *) VAR par: DevCPT.Object; typ: DevCPT.Struct; padr, vadr: INTEGER; BEGIN padr := ParOff; par := firstPar; WHILE par # NIL DO typ := par.typ; TypeAlloc(typ); par.adr := padr; IF (par.mode = VarPar) & (typ.comp # DynArr) THEN IF (typ.comp = Record) & ~typ.untagged THEN INC(padr, 8) ELSE INC(padr, 4) END ELSE IF (par.mode = Var) & (typ.comp = DynArr) & typ.untagged THEN DevCPM.err(145) END; INC(padr, typ.size); Align(padr, 4) END; par := par.link END; IF proc # NIL THEN IF proc.mode = XProc THEN INCL(proc.conval.setval, isCallback) ELSIF (proc.mode = TProc) & (proc.num >= numPreIntProc) & (proc.num < numPreIntProc + NumOfIntProc(proc.link.typ)) THEN INCL(proc.conval.setval, isCallback); INCL(proc.conval.setval, isGuarded) END; IF proc.sysflag = guarded THEN INCL(proc.conval.setval, isGuarded) END; IF isGuarded IN proc.conval.setval THEN GetComKernel; vadr := -24 ELSE vadr := 0; IF imVar IN proc.conval.setval THEN DEC(vadr, 4) END; IF isCallback IN proc.conval.setval THEN DEC(vadr, 8) END END; proc.conval.intval := padr; proc.conval.intval2 := vadr; END END Parameters; PROCEDURE Variables(var: DevCPT.Object; VAR varSize: INTEGER); (* allocates only offsets, regs allocated in DevCPC486.Enter *) VAR adr: INTEGER; typ: DevCPT.Struct; BEGIN adr := varSize; WHILE var # NIL DO typ := var.typ; TypeAlloc(typ); DEC(adr, typ.size); NegAlign(adr, Base(typ, 4)); var.adr := adr; var := var.link END; NegAlign(adr, 4); varSize := adr END Variables; PROCEDURE ^Objects(obj: DevCPT.Object); PROCEDURE Procedure(obj: DevCPT.Object); (* obj.mnolev = 0 *) VAR oldPos: INTEGER; BEGIN oldPos := DevCPM.errpos; DevCPM.errpos := obj.scope.adr; TypeAlloc(obj.typ); Parameters(obj.link, obj); IF ~(hasBody IN obj.conval.setval) THEN DevCPM.Mark(129, obj.adr) END ; Variables(obj.scope.scope, obj.conval.intval2); (* local variables *) Objects(obj.scope.right); DevCPM.errpos := oldPos END Procedure; PROCEDURE TProcedures(obj: DevCPT.Object); (* obj.mnolev = 0 *) VAR par: DevCPT.Object; psize: INTEGER; BEGIN IF obj # NIL THEN TProcedures(obj.left); IF (obj.mode = TProc) & (obj.scope # NIL) THEN TypeAlloc(obj.typ); Parameters(obj.link, obj); Variables(obj.scope.scope, obj.conval.intval2); (* local variables *) Objects(obj.scope.right); END ; TProcedures(obj.right) END END TProcedures; PROCEDURE Objects(obj: DevCPT.Object); BEGIN IF obj # NIL THEN Objects(obj.left); IF obj.mode IN {Con, Typ, LProc, XProc, CProc, IProc} THEN IF (obj.mode IN {Con, Typ}) THEN TypeAlloc(obj.typ); ELSE Procedure(obj) END END ; Objects(obj.right) END END Objects; PROCEDURE Allocate*; VAR gvarSize: INTEGER; name: DevCPT.Name; BEGIN DevCPM.errpos := DevCPT.topScope.adr; (* text position of scope used if error *) gvarSize := 0; Variables(DevCPT.topScope.scope, gvarSize); DevCPE.dsize := -gvarSize; Objects(DevCPT.topScope.right) END Allocate; (************************) PROCEDURE SameExp (n1, n2: DevCPT.Node): BOOLEAN; BEGIN WHILE (n1.class = n2.class) & (n1.typ = n2.typ) DO CASE n1.class OF | Nvar, Nvarpar, Nproc: RETURN n1.obj = n2.obj | Nconst: RETURN (n1.typ.form IN {Int8..Int32}) & (n1.conval.intval = n2.conval.intval) | Nfield: IF n1.obj # n2.obj THEN RETURN FALSE END | Nderef, Nguard: | Nindex: IF ~SameExp(n1.right, n2.right) THEN RETURN FALSE END | Nmop: IF (n1.subcl # n2.subcl) OR (n1.subcl = is) THEN RETURN FALSE END | Ndop: IF (n1.subcl # n2.subcl) OR ~SameExp(n1.right, n2.right) THEN RETURN FALSE END ELSE RETURN FALSE END ; n1 := n1.left; n2 := n2.left END; RETURN FALSE END SameExp; PROCEDURE Check (n: DevCPT.Node; VAR used: SET; VAR size: INTEGER); VAR ux, uy: SET; sx, sy, sf: INTEGER; f: BYTE; BEGIN used := {}; size := 0; WHILE n # NIL DO IF n.class # Ncomp THEN Check(n.left, ux, sx); Check(n.right, uy, sy) END; ux := ux + uy; sf := 0; CASE n.class OF | Nvar, Nvarpar: IF (n.class = Nvarpar) OR (n.typ.comp = DynArr) OR (n.obj.mnolev > 0) & (DevCPC486.imLevel[n.obj.mnolev] < DevCPC486.imLevel[DevCPL486.level]) THEN sf := 1 END | Nguard: sf := 2 | Neguard, Nderef: sf := 1 | Nindex: IF (n.right.class # Nconst) OR (n.left.typ.comp = DynArr) THEN sf := 1 END; IF sx > 0 THEN INC(sy) END | Nmop: CASE n.subcl OF | is, adr, typfn, minus, abs, cap, val: sf := 1 | bit: sf := 2; INCL(ux, CX) | conv: IF n.typ.form = Int64 THEN sf := 2 ELSIF ~(n.typ.form IN realSet) THEN sf := 1; IF n.left.typ.form IN realSet THEN INCL(ux, AX) END END | odd, cc, not: END | Ndop: f := n.left.typ.form; IF f # Bool THEN CASE n.subcl OF | times: sf := 1; IF f = Int8 THEN INCL(ux, AX) END | div, mod: sf := 3; INCL(ux, AX); IF f > Int8 THEN INCL(ux, DX) END | eql..geq: IF f IN {String8, String16, Comp} THEN ux := ux + {AX, CX, SI, DI}; sf := 4 ELSIF f IN realSet THEN INCL(ux, AX); sf := 1 ELSE sf := 1 END | ash, lsh, rot: IF n.right.class = Nconst THEN sf := 1 ELSE sf := 2; INCL(ux, CX) END | slash, plus, minus, msk, in, bit: sf := 1 | len: IF f IN {String8, String16} THEN ux := ux + {AX, CX, DI}; sf := 3 ELSE sf := 1 END | min, max: sf := 1; IF f IN realSet THEN INCL(ux, AX) END | queryfn: ux := ux + {CX, SI, DI}; sf := 4 END; IF sy > sx THEN INC(sx) ELSE INC(sy) END END | Nupto: IF (n.right.class = Nconst) OR (n.left.class = Nconst) THEN sf := 2 ELSE sf := 3 END; INCL(ux, CX); INC(sx) | Ncall, Ncomp: sf := 10; ux := wreg + {float} | Nfield, Nconst, Nproc, Ntype: END; used := used + ux; IF sx > size THEN size := sx END; IF sy > size THEN size := sy END; IF sf > size THEN size := sf END; n := n.link END; IF size > 10 THEN size := 10 END END Check; PROCEDURE^ expr (n: DevCPT.Node; VAR x: DevCPL486.Item; hint, stop: SET); PROCEDURE DualExp (left, right: DevCPT.Node; VAR x, y: DevCPL486.Item; hx, hy, stpx, stpy: SET); VAR ux, uy: SET; sx, sy: INTEGER; BEGIN Check(left, ux, sx); Check(right, uy, sy); IF sy > sx THEN expr(right, y, hy + stpy, ux + stpy * {AX, CX}); expr(left, x, hx, stpx); DevCPC486.Assert(y, hy, stpy) ELSE expr(left, x, hx + stpx, uy); expr(right, y, hy, stpy); DevCPC486.Assert(x, hx, stpx) END; END DualExp; PROCEDURE IntDOp (n: DevCPT.Node; VAR x: DevCPL486.Item; hint: SET); VAR y: DevCPL486.Item; rev: BOOLEAN; BEGIN DualExp(n.left, n.right, x, y, hint, hint, {stk}, {stk}); IF (x.mode = Reg) & DevCPC486.Fits(x, hint) THEN DevCPC486.IntDOp(x, y, n.subcl, FALSE) ELSIF (y.mode = Reg) & DevCPC486.Fits(y, hint) THEN DevCPC486.IntDOp(y, x, n.subcl, TRUE); x := y ELSIF x.mode # Reg THEN DevCPC486.Load(x, hint, {con}); DevCPC486.IntDOp(x, y, n.subcl, FALSE) ELSIF y.mode # Reg THEN DevCPC486.Load(y, hint, {con}); DevCPC486.IntDOp(y, x, n.subcl, TRUE); x := y ELSE DevCPC486.IntDOp(x, y, n.subcl, FALSE) END END IntDOp; PROCEDURE FloatDOp (n: DevCPT.Node; VAR x: DevCPL486.Item); VAR y: DevCPL486.Item; ux, uy, uf: SET; sx, sy: INTEGER; BEGIN Check(n.left, ux, sx); Check(n.right, uy, sy); IF (n.subcl = min) OR (n.subcl = max) THEN uf := {AX} ELSE uf := {} END; IF (sy > sx) OR (sy = sx) & ((n.subcl = mod) OR (n.subcl = ash)) THEN expr(n.right, x, {}, ux + {mem, stk}); expr(n.left, y, {}, uf); DevCPC486.FloatDOp(x, y, n.subcl, TRUE) ELSIF float IN uy THEN (* function calls in both operands *) expr(n.left, y, {}, uy + {mem}); expr(n.right, x, {}, {mem, stk}); DevCPC486.FloatDOp(x, y, n.subcl, TRUE) ELSE expr(n.left, x, {}, uy + {mem, stk}); expr(n.right, y, {}, uf); DevCPC486.FloatDOp(x, y, n.subcl, FALSE) END END FloatDOp; PROCEDURE design (n: DevCPT.Node; VAR x: DevCPL486.Item; hint, stop: SET); VAR obj: DevCPT.Object; y: DevCPL486.Item; ux, uy: SET; sx, sy: INTEGER; BEGIN CASE n.class OF Nvar, Nvarpar: obj := n.obj; x.mode := obj.mode; x.obj := obj; x.scale := 0; IF obj.typ.comp = DynArr THEN x.mode := VarPar END; IF obj.mnolev < 0 THEN x.offset := 0; x.tmode := Con ELSIF x.mode = Var THEN x.offset := obj.adr; x.tmode := Con ELSE x.offset := 0; x.tmode := VarPar END | Nfield: design(n.left, x, hint, stop); DevCPC486.Field(x, n.obj) | Nderef: IF n.subcl # 0 THEN expr(n.left, x, hint, stop); IF n.typ.form = String8 THEN x.form := VString8 ELSE x.form := VString16 END ELSE expr(n.left, x, hint, stop + {mem} - {loaded}); DevCPC486.DeRef(x) END | Nindex: Check(n.left, ux, sx); Check(n.right, uy, sy); IF wreg - uy = {} THEN expr(n.right, y, hint + stop, ux); design(n.left, x, hint, stop); IF x.scale # 0 THEN DevCPC486.Index(x, y, {}, {}) ELSE DevCPC486.Index(x, y, hint, stop) END ELSE design(n.left, x, hint, stop + uy); IF x.scale # 0 THEN expr(n.right, y, {}, {}); DevCPC486.Index(x, y, {}, {}) ELSE expr(n.right, y, hint, stop); DevCPC486.Index(x, y, hint, stop) END END | Nguard, Neguard: IF n.typ.form = Pointer THEN IF loaded IN stop THEN expr(n.left, x, hint, stop) ELSE expr(n.left, x, hint, stop + {mem}) END ELSE design(n.left, x, hint, stop) END; DevCPC486.TypTest(x, n.typ, TRUE, n.class = Neguard) | Nproc: obj := n.obj; x.mode := obj.mode; x.obj := obj; IF x.mode = TProc THEN x.offset := obj.num; (*mthno*) x.scale := n.subcl (* super *) END END; x.typ := n.typ END design; PROCEDURE IsAllocDynArr (x: DevCPT.Node): BOOLEAN; BEGIN IF (x.typ.comp = DynArr) & ~x.typ.untagged THEN WHILE x.class = Nindex DO x := x.left END; IF x.class = Nderef THEN RETURN TRUE END END; RETURN FALSE END IsAllocDynArr; PROCEDURE StringOp (left, right: DevCPT.Node; VAR x, y: DevCPL486.Item; useLen: BOOLEAN); VAR ax, ay: DevCPL486.Item; ux: SET; sx: INTEGER; BEGIN Check(left, ux, sx); expr(right, y, wreg - {SI} + ux, {}); ay := y; DevCPC486.GetAdr(ay, wreg - {SI} + ux, {}); DevCPC486.Assert(ay, wreg - {SI}, ux); IF useLen & IsAllocDynArr(left) THEN (* keep len descriptor *) design(left, x, wreg - {CX}, {loaded}); DevCPC486.Prepare(x, wreg - {CX} + {deref}, {DI}) ELSE expr(left, x, wreg - {DI}, {}) END; ax := x; DevCPC486.GetAdr(ax, {}, wreg - {DI} + {stk, con}); DevCPC486.Load(ay, {}, wreg - {SI} + {con}); DevCPC486.Free(ax); DevCPC486.Free(ay) END StringOp; PROCEDURE AdrExpr (n: DevCPT.Node; VAR x: DevCPL486.Item; hint, stop: SET); BEGIN IF n.class < Nconst THEN design(n, x, hint + stop, {loaded}); DevCPC486.Prepare(x, hint + {deref}, stop) ELSE expr(n, x, hint, stop) END END AdrExpr; (* ---------- interface pointer reference counting ---------- *) PROCEDURE HandleIPtrs (typ: DevCPT.Struct; VAR x, y: DevCPL486.Item; add, rel, init: BOOLEAN); PROCEDURE FindPtrs (typ: DevCPT.Struct; adr: INTEGER); VAR fld: DevCPT.Object; btyp: DevCPT.Struct; i, n: INTEGER; BEGIN IF (typ.form = Pointer) & (typ.sysflag = interface) THEN IF add THEN DevCPC486.IPAddRef(y, adr, TRUE) END; IF rel THEN DevCPC486.IPRelease(x, adr, TRUE, init) END ELSIF (typ.comp = Record) & (typ.sysflag # union) THEN btyp := typ.BaseTyp; IF btyp # NIL THEN FindPtrs(btyp, adr) END ; fld := typ.link; WHILE (fld # NIL) & (fld.mode = Fld) DO IF (fld.sysflag = interface) & (fld.name^ = DevCPM.HdUtPtrName) THEN IF add THEN DevCPC486.IPAddRef(y, fld.adr + adr, TRUE) END; IF rel THEN DevCPC486.IPRelease(x, fld.adr + adr, TRUE, init) END ELSE FindPtrs(fld.typ, fld.adr + adr) END; fld := fld.link END ELSIF typ.comp = Array THEN btyp := typ.BaseTyp; n := typ.n; WHILE btyp.comp = Array DO n := btyp.n * n; btyp := btyp.BaseTyp END ; IF DevCPC486.ContainsIPtrs(btyp) THEN i := 0; WHILE i < n DO FindPtrs(btyp, adr); INC(adr, btyp.size); INC(i) END END ELSIF typ.comp = DynArr THEN IF DevCPC486.ContainsIPtrs(typ) THEN DevCPM.err(221) END END END FindPtrs; BEGIN FindPtrs(typ, 0) END HandleIPtrs; PROCEDURE CountedPtr (n: DevCPT.Node): BOOLEAN; BEGIN RETURN (n.typ.form = Pointer) & (n.typ.sysflag = interface) & ((n.class = Ncall) OR (n.class = Ncomp) & (n.right.class = Ncall)) END CountedPtr; PROCEDURE IPAssign (nx, ny: DevCPT.Node; VAR x, y: DevCPL486.Item; ux: SET); (* nx.typ.form = Pointer & nx.typ.sysflag = interface *) BEGIN expr(ny, y, {}, wreg - {SI} + {mem, stk}); IF (ny.class # Nconst) & ~CountedPtr(ny) THEN DevCPC486.IPAddRef(y, 0, TRUE) END; IF nx # NIL THEN DevCPC486.Assert(y, {}, wreg - {SI} + ux); expr(nx, x, wreg - {DI}, {loaded}); IF (x.mode = Ind) & (x.reg IN wreg - {SI, DI}) OR (x.scale # 0) THEN DevCPC486.GetAdr(x, {}, wreg - {DI} + {con}); x.mode := Ind; x.offset := 0; x.scale := 0 END; DevCPC486.IPRelease(x, 0, TRUE, FALSE); END END IPAssign; PROCEDURE IPStructAssign (typ: DevCPT.Struct); VAR x, y: DevCPL486.Item; BEGIN IF typ.comp = DynArr THEN DevCPM.err(270) END; (* addresses in SI and DI *) x.mode := Ind; x.reg := DI; x.offset := 0; x.scale := 0; y.mode := Ind; y.reg := SI; y.offset := 0; y.scale := 0; HandleIPtrs(typ, x, y, TRUE, TRUE, FALSE) END IPStructAssign; PROCEDURE IPFree (nx: DevCPT.Node; VAR x: DevCPL486.Item); BEGIN expr(nx, x, wreg - {DI}, {loaded}); DevCPC486.GetAdr(x, {}, wreg - {DI} + {con}); x.mode := Ind; x.offset := 0; x.scale := 0; IF nx.typ.form = Comp THEN HandleIPtrs(nx.typ, x, x, FALSE, TRUE, TRUE) ELSE (* nx.typ.form = Pointer & nx.typ.sysflag = interface *) DevCPC486.IPRelease(x, 0, TRUE, TRUE); END END IPFree; (* unchanged val parameters allways counted because of aliasing problems REMOVED! *) PROCEDURE InitializeIPVars (proc: DevCPT.Object); VAR x: DevCPL486.Item; obj: DevCPT.Object; BEGIN x.mode := Ind; x.reg := BP; x.scale := 0; x.form := Pointer; obj := proc.link; WHILE obj # NIL DO IF (obj.mode = Var) & obj.used THEN (* changed value parameters *) x.offset := obj.adr; HandleIPtrs(obj.typ, x, x, TRUE, FALSE, FALSE) END; obj := obj.link END END InitializeIPVars; PROCEDURE ReleaseIPVars (proc: DevCPT.Object); VAR x, ax, dx, si, di: DevCPL486.Item; obj: DevCPT.Object; BEGIN obj := proc.link; WHILE (obj # NIL) & ((obj.mode # Var) OR ~obj.used OR ~DevCPC486.ContainsIPtrs(obj.typ)) DO obj := obj.link END; IF obj = NIL THEN obj := proc.scope.scope; WHILE (obj # NIL) & ~DevCPC486.ContainsIPtrs(obj.typ) DO obj := obj.link END; IF obj = NIL THEN RETURN END END; DevCPL486.MakeReg(ax, AX, Int32); DevCPL486.MakeReg(si, SI, Int32); DevCPL486.MakeReg(dx, DX, Int32); DevCPL486.MakeReg(di, DI, Int32); IF ~(proc.typ.form IN {Real32, Real64, NoTyp}) THEN DevCPL486.GenMove(ax, si) END; IF proc.typ.form = Int64 THEN DevCPL486.GenMove(dx, di) END; x.mode := Ind; x.reg := BP; x.scale := 0; x.form := Pointer; obj := proc.link; WHILE obj # NIL DO IF (obj.mode = Var) & obj.used THEN (* value parameters *) x.offset := obj.adr; HandleIPtrs(obj.typ, x, x, FALSE, TRUE, FALSE) END; obj := obj.link END; obj := proc.scope.scope; WHILE obj # NIL DO (* local variables *) IF obj.used THEN x.offset := obj.adr; HandleIPtrs(obj.typ, x, x, FALSE, TRUE, FALSE); END; obj := obj.link END; IF ~(proc.typ.form IN {Real32, Real64, NoTyp}) THEN DevCPL486.GenMove(si, ax) END; IF proc.typ.form = Int64 THEN DevCPL486.GenMove(di, dx) END END ReleaseIPVars; PROCEDURE CompareIntTypes ( typ: DevCPT.Struct; VAR id: DevCPL486.Item; VAR exit: DevCPL486.Label; VAR num: INTEGER ); VAR x, y: DevCPL486.Item; local: DevCPL486.Label; BEGIN local := DevCPL486.NewLbl; typ := typ.BaseTyp; num := 0; WHILE (typ # NIL) & (typ # DevCPT.undftyp) DO IF (typ.sysflag = interface) & (typ.ext # NIL) THEN IF num > 0 THEN DevCPC486.JumpT(x, local) END; DevCPC486.GuidFromString(typ.ext, y); x := id; DevCPC486.GetAdr(x, wreg - {SI}, {mem}); x := y; DevCPC486.GetAdr(x, wreg - {DI}, {}); x := id; DevCPC486.CmpString(x, y, eql, FALSE); INC(num) END; typ := typ.BaseTyp END; IF num > 0 THEN DevCPC486.JumpF(x, exit) END; IF num > 1 THEN DevCPL486.SetLabel(local) END END CompareIntTypes; PROCEDURE InstallQueryInterface (typ: DevCPT.Struct; proc: DevCPT.Object); VAR this, id, int, unk, c: DevCPL486.Item; nil, end: DevCPL486.Label; num: INTEGER; BEGIN nil := DevCPL486.NewLbl; end := DevCPL486.NewLbl; this.mode := Ind; this.reg := BP; this.offset := 8; this.scale := 0; this.form := Pointer; this.typ := DevCPT.anyptrtyp; id.mode := DInd; id.reg := BP; id.offset := 12; id.scale := 0; id.form := Pointer; int.mode := DInd; int.reg := BP; int.offset := 16; int.scale := 0; int.form := Pointer; DevCPC486.GetAdr(int, {}, {AX, CX, SI, DI, mem}); int.mode := Ind; int.offset := 0; DevCPL486.MakeConst(c, 0, Pointer); DevCPC486.Assign(int, c); unk.mode := Ind; unk.reg := BP; unk.offset := 8; unk.scale := 0; unk.form := Pointer; unk.typ := DevCPT.punktyp; DevCPC486.Load(unk, {}, {}); unk.mode := Ind; unk.offset := 8; DevCPC486.Load(unk, {}, {}); DevCPL486.GenComp(c, unk); DevCPL486.GenJump(4, nil, TRUE); DevCPL486.MakeReg(c, int.reg, Pointer); DevCPL486.GenPush(c); c.mode := Ind; c.reg := BP; c.offset := 12; c.scale := 0; c.form := Pointer; DevCPL486.GenPush(c); DevCPL486.GenPush(unk); c.mode := Ind; c.reg := unk.reg; c.offset := 0; c.scale := 0; c.form := Pointer; DevCPL486.GenMove(c, unk); unk.mode := Ind; unk.offset := 0; unk.scale := 0; unk.form := Pointer; DevCPL486.GenCall(unk); DevCPC486.Free(unk); DevCPL486.GenJump(-1, end, FALSE); DevCPL486.SetLabel(nil); DevCPL486.MakeConst(c, 80004002H, Int32); (* E_NOINTERFACE *) DevCPC486.Result(proc, c); CompareIntTypes(typ, id, end, num); IF num > 0 THEN DevCPC486.Load(this, {}, {}); DevCPC486.Assign(int, this); DevCPC486.IPAddRef(this, 0, FALSE); DevCPL486.MakeConst(c, 0, Int32); (* S_OK *) DevCPC486.Result(proc, c); END; DevCPL486.SetLabel(end) END InstallQueryInterface; (* -------------------- *) PROCEDURE ActualPar (n: DevCPT.Node; fp: DevCPT.Object; rec: BOOLEAN; VAR tag: DevCPL486.Item); VAR ap: DevCPL486.Item; x: DevCPT.Node; niltest: BOOLEAN; BEGIN IF n # NIL THEN ActualPar(n.link, fp.link, FALSE, ap); niltest := FALSE; IF fp.mode = VarPar THEN IF (n.class = Ndop) & ((n.subcl = thisarrfn) OR (n.subcl = thisrecfn)) THEN expr(n.right, ap, {}, {}); DevCPC486.Push(ap); (* push type/length *) expr(n.left, ap, {}, {}); DevCPC486.Push(ap); (* push adr *) RETURN ELSIF (fp.vis = outPar) & DevCPC486.ContainsIPtrs(fp.typ) & (ap.typ # DevCPT.niltyp) THEN IPFree(n, ap) ELSE x := n; WHILE (x.class = Nfield) OR (x.class = Nindex) DO x := x.left END; niltest := x.class = Nderef; (* explicit nil test needed *) AdrExpr(n, ap, {}, {}) END ELSIF (n.class = Nmop) & (n.subcl = conv) THEN IF n.typ.form IN {String8, String16} THEN expr(n, ap, {}, {}); DevCPM.err(265) ELSIF (DevCPT.Includes(n.typ.form, n.left.typ.form) OR DevCPT.Includes(n.typ.form, fp.typ.form)) & (n.typ.form # Set) & (fp.typ # DevCPT.bytetyp) THEN expr(n.left, ap, {}, {high}); ELSE expr(n, ap, {}, {high}); END ELSE expr(n, ap, {}, {high}); IF CountedPtr(n) THEN DevCPM.err(270) END END; DevCPC486.Param(fp, rec, niltest, ap, tag) END END ActualPar; PROCEDURE Call (n: DevCPT.Node; VAR x: DevCPL486.Item); VAR tag: DevCPL486.Item; proc: DevCPT.Object; m: BYTE; BEGIN IF n.left.class = Nproc THEN proc := n.left.obj; m := proc.mode; ELSE proc := NIL; m := 0 END; IF (m = CProc) & (n.right # NIL) THEN ActualPar(n.right.link, n.obj.link, FALSE, tag); expr(n.right, tag, wreg - {AX}, {}); (* tag = first param *) ELSE IF proc # NIL THEN DevCPC486.PrepCall(proc) END; ActualPar(n.right, n.obj, (m = TProc) & (n.left.subcl = 0), tag); END; IF proc # NIL THEN design(n.left, x, {}, {}) ELSE expr(n.left, x, {}, {}) END; DevCPC486.Call(x, tag) END Call; PROCEDURE Mem (n: DevCPT.Node; VAR x: DevCPL486.Item; typ: DevCPT.Struct; hint, stop: SET); VAR offset: INTEGER; BEGIN IF (n.class = Ndop) & (n.subcl IN {plus, minus}) & (n.right.class = Nconst) THEN expr(n.left, x, hint, stop + {mem}); offset := n.right.conval.intval; IF n.subcl = minus THEN offset := -offset END ELSE expr(n, x, hint, stop + {mem}); offset := 0 END; DevCPC486.Mem(x, offset, typ) END Mem; PROCEDURE^ CompStat (n: DevCPT.Node); PROCEDURE^ CompRelease (n: DevCPT.Node; VAR res: DevCPL486.Item); PROCEDURE condition (n: DevCPT.Node; VAR x: DevCPL486.Item; VAR false, true: DevCPL486.Label); VAR local: DevCPL486.Label; y, z: DevCPL486.Item; ux: SET; sx, num: INTEGER; f: BYTE; typ: DevCPT.Struct; BEGIN IF n.class = Nmop THEN CASE n.subcl OF not: condition(n.left, x, true, false); DevCPC486.Not(x) | is: IF n.left.typ.form = Pointer THEN expr(n.left, x, {}, {mem}) ELSE design(n.left, x, {}, {}) END; DevCPC486.TypTest(x, n.obj.typ, FALSE, FALSE) | odd: expr(n.left, x, {}, {}); DevCPC486.Odd(x) | cc: expr(n.left, x, {}, {}); x.mode := Cond; x.form := Bool | val: DevCPM.err(220) END ELSIF n.class = Ndop THEN CASE n.subcl OF and: local := DevCPL486.NewLbl; condition(n.left, y, false, local); DevCPC486.JumpF(y, false); IF local # DevCPL486.NewLbl THEN DevCPL486.SetLabel(local) END; condition(n.right, x, false, true) | or: local := DevCPL486.NewLbl; condition(n.left, y, local, true); DevCPC486.JumpT(y, true); IF local # DevCPL486.NewLbl THEN DevCPL486.SetLabel(local) END; condition(n.right, x, false, true) | eql..geq: f := n.left.typ.form; IF f = Int64 THEN DevCPM.err(260) ELSIF f IN {String8, String16, Comp} THEN IF (n.left.class = Nmop) & (n.left.subcl = conv) THEN (* converted must be source *) StringOp(n.right, n.left, x, y, FALSE); DevCPC486.CmpString(x, y, n.subcl, TRUE) ELSE StringOp(n.left, n.right, x, y, FALSE); DevCPC486.CmpString(x, y, n.subcl, FALSE) END ELSIF f IN {Real32, Real64} THEN FloatDOp(n, x) ELSE IF CountedPtr(n.left) OR CountedPtr(n.right) THEN DevCPM.err(270) END; DualExp(n.left, n.right, x, y, {}, {}, {stk}, {stk}); IF (x.mode = Reg) OR (y.mode = Con) THEN DevCPC486.IntDOp(x, y, n.subcl, FALSE) ELSIF (y.mode = Reg) OR (x.mode = Con) THEN DevCPC486.IntDOp(y, x, n.subcl, TRUE); x := y ELSE DevCPC486.Load(x, {}, {}); DevCPC486.IntDOp(x, y, n.subcl, FALSE) END END | in: DualExp(n.left, n.right, x, y, {}, {}, {short, mem, stk}, {con, stk}); DevCPC486.In(x, y) | bit: Check(n.left, ux, sx); expr(n.right, x, {}, ux + {short}); Mem(n.left, y, DevCPT.notyp, {}, {}); DevCPC486.Load(x, {}, {short}); DevCPC486.In(x, y) | queryfn: AdrExpr(n.right, x, {}, {CX, SI, DI}); CompareIntTypes(n.left.typ, x, false, num); IF num > 0 THEN Check(n.right.link, ux, sx); IPAssign(n.right.link, n.left, x, y, ux); DevCPC486.Assign(x, y); x.offset := 1 (* true *) ELSE x.offset := 0 (* false *) END; x.mode := Con; DevCPC486.MakeCond(x) END ELSIF n.class = Ncomp THEN CompStat(n.left); condition(n.right, x, false, true); CompRelease(n.left, x); IF x.mode = Stk THEN DevCPL486.GenCode(9DH); (* pop flags *) x.mode := Cond END ELSE expr(n, x, {}, {}); DevCPC486.MakeCond(x) (* const, var, or call *) END END condition; PROCEDURE expr(n: DevCPT.Node; VAR x: DevCPL486.Item; hint, stop: SET); VAR y, z: DevCPL486.Item; f, g: BYTE; cval: DevCPT.Const; false, true: DevCPL486.Label; uy: SET; sy: INTEGER; r: REAL; BEGIN f := n.typ.form; IF (f = Bool) & (n.class IN {Ndop, Nmop}) THEN false := DevCPL486.NewLbl; true := DevCPL486.NewLbl; condition(n, y, false, true); DevCPC486.LoadCond(x, y, false, true, hint, stop + {mem}) ELSE CASE n.class OF Nconst: IF n.obj = NIL THEN cval := n.conval ELSE cval := n.obj.conval END; CASE f OF Byte..Int32, NilTyp, Pointer, Char16: DevCPL486.MakeConst(x, cval.intval, f) | Int64: DevCPL486.MakeConst(x, cval.intval, f); DevCPE.GetLongWords(cval, x.scale, x.offset) | Set: DevCPL486.MakeConst(x, SYSTEM.VAL(INTEGER, cval.setval), Set) | String8, String16, Real32, Real64: DevCPL486.AllocConst(x, cval, f) | Comp: ASSERT(n.typ = DevCPT.guidtyp); IF n.conval # NIL THEN DevCPC486.GuidFromString(n.conval.ext, x) ELSE DevCPC486.GuidFromString(n.obj.typ.ext, x) END END | Nupto: (* n.typ = DevCPT.settyp *) Check(n.right, uy, sy); expr(n.left, x, {}, wreg - {CX} + {high, mem, stk}); DevCPC486.MakeSet(x, TRUE, FALSE, hint + stop + uy, {}); DevCPC486.Assert(x, {}, uy); expr(n.right, y, {}, wreg - {CX} + {high, mem, stk}); DevCPC486.MakeSet(y, TRUE, TRUE, hint + stop, {}); DevCPC486.Load(x, hint + stop, {}); IF x.mode = Con THEN DevCPC486.IntDOp(y, x, msk, TRUE); x := y ELSE DevCPC486.IntDOp(x, y, msk, FALSE) END | Nmop: CASE n.subcl OF | bit: expr(n.left, x, {}, wreg - {CX} + {high, mem, stk}); DevCPC486.MakeSet(x, FALSE, FALSE, hint + stop, {}) | conv: IF f IN {String8, String16} THEN expr(n.left, x, hint, stop); IF f = String8 THEN x.form := VString16to8 END (* SHORT *) ELSE IF n.left.class = Nconst THEN (* largeint -> longreal *) ASSERT((n.left.typ.form = Int64) & (f = Real64)); DevCPL486.AllocConst(x, n.left.conval, n.left.typ.form); ELSE expr(n.left, x, hint + stop, {high}); END; DevCPC486.Convert(x, f, -1, hint + stop, {}) (* ??? *) END | val: expr(n.left, x, hint + stop, {high, con}); DevCPC486.Convert(x, f, n.typ.size, hint, stop) (* ??? *) | adr: IF n.left.class = Ntype THEN x.mode := Con; x.offset := 0; x.obj := n.left.obj; x.form := Int32; x.typ := n.left.typ; ELSE AdrExpr(n.left, x, hint + stop, {}); END; DevCPC486.GetAdr(x, hint + stop, {}) | typfn: IF n.left.class = Ntype THEN x.mode := Con; x.offset := 0; x.obj := n.left.obj; x.form := Int32; x.typ := n.left.typ; IF x.obj.typ.untagged THEN DevCPM.err(111) END ELSE expr(n.left, x, hint + stop, {}); DevCPC486.Tag(x, y); DevCPC486.Free(x); x := y END; DevCPC486.Load(x, hint + stop, {}) | minus, abs, cap: expr(n.left, x, hint + stop, {mem, stk}); IF f = Int64 THEN DevCPM.err(260) ELSIF f IN realSet THEN DevCPC486.FloatMOp(x, n.subcl) ELSE DevCPC486.IntMOp(x, n.subcl) END END | Ndop: IF (f IN realSet) & (n.subcl # lsh) & (n.subcl # rot) THEN IF (n.subcl = ash) & (n.right.class = Nconst) & (n.right.conval.realval >= 0) THEN expr(n.left, x, {}, {mem, stk}); cval := n.right.conval; sy := SHORT(ENTIER(cval.realval)); cval.realval := 1; WHILE sy > 0 DO cval.realval := cval.realval * 2; DEC(sy) END; DevCPL486.AllocConst(y, cval, Real32); DevCPC486.FloatDOp(x, y, times, FALSE) ELSE FloatDOp(n, x) END ELSIF (f = Int64) OR (n.typ = DevCPT.intrealtyp) THEN DevCPM.err(260); expr(n.left, x, {}, {}) ELSE CASE n.subcl OF times: IF f = Int8 THEN DualExp(n.left, n.right, x, y, {}, {}, wreg - {AX} + {high, mem, stk, con}, {AX, con, stk}); DevCPC486.IntDOp(x, y, times, FALSE) ELSE IntDOp(n, x, hint + stop) END | div, mod: DualExp(n.left, n.right, x, y, {}, {}, wreg - {AX} + {high, mem, stk, con}, {AX, DX, mem, stk}); DevCPC486.DivMod(x, y, n.subcl = mod) | plus: IF n.typ.form IN {String8, String16} THEN DevCPM.err(265); expr(n.left, x, {}, {}) ELSE IntDOp(n, x, hint + stop) END | slash, minus, msk, min, max: IntDOp(n, x, hint + stop) | ash, lsh, rot: uy := {}; IF n.right.class # Nconst THEN uy := {CX} END; DualExp(n^.right, n^.left, y, x, {}, hint + stop, wreg - {CX} + {high, mem, stk}, uy + {con, mem, stk}); DevCPC486.Shift(x, y, n^.subcl) | len: IF n.left.typ.form IN {String8, String16} THEN expr(n.left, x, wreg - {DI} , {}); DevCPC486.GetAdr(x, {}, wreg - {DI} + {con}); DevCPC486.StrLen(x, n.left.typ, FALSE) ELSE design(n.left, x, hint + stop, {}); expr(n.right, y, {}, {}); DevCPC486.Len(x, y) END END END | Ncall: Call(n, x) | Ncomp: CompStat(n.left); expr(n.right, x, hint, stop); CompRelease(n.left, x); IF x.mode = Stk THEN DevCPC486.Pop(x, x.form, hint, stop) END ELSE design(n, x, hint + stop, stop * {loaded}); DevCPC486.Prepare(x, hint + stop, {}) (* ??? *) END END; x.typ := n.typ; DevCPC486.Assert(x, hint, stop) END expr; PROCEDURE AddCopy (n: DevCPT.Node; VAR dest, dadr, len: DevCPL486.Item; last: BOOLEAN); VAR adr, src: DevCPL486.Item; u: SET; s: INTEGER; BEGIN Check(n, u, s); DevCPC486.Assert(dadr, wreg - {DI}, u + {SI, CX}); IF len.mode # Con THEN DevCPC486.Assert(len, wreg - {CX}, u + {SI, DI}) END; expr(n, src, wreg - {SI}, {}); adr := src; DevCPC486.GetAdr(adr, {}, wreg - {SI} + {con}); IF len.mode # Con THEN DevCPC486.Load(len, {}, wreg - {CX} + {con}) END; DevCPC486.Load(dadr, {}, wreg - {DI} + {con}); DevCPC486.AddCopy(dest, src, last) END AddCopy; PROCEDURE StringCopy (left, right: DevCPT.Node); VAR x, y, ax, ay, len: DevCPL486.Item; BEGIN IF IsAllocDynArr(left) THEN expr(left, x, wreg - {CX}, {DI}) (* keep len descriptor *) ELSE expr(left, x, wreg - {DI}, {}) END; ax := x; DevCPC486.GetAdr(ax, {}, wreg - {DI}); DevCPC486.Free(x); DevCPC486.ArrayLen(x, len, wreg - {CX}, {}); WHILE right.class = Ndop DO ASSERT(right.subcl = plus); AddCopy(right.left, x, ax, len, FALSE); right := right.right END; AddCopy(right, x, ax, len, TRUE); DevCPC486.Free(len) END StringCopy; PROCEDURE Checkpc; BEGIN DevCPE.OutSourceRef(DevCPM.errpos) END Checkpc; PROCEDURE^ stat (n: DevCPT.Node; VAR end: DevCPL486.Label); PROCEDURE CondStat (if, last: DevCPT.Node; VAR hint: INTEGER; VAR else, end: DevCPL486.Label); VAR local: DevCPL486.Label; x: DevCPL486.Item; cond, lcond: DevCPT.Node; BEGIN local := DevCPL486.NewLbl; DevCPM.errpos := if.conval.intval; Checkpc; cond := if.left; IF (last # NIL) & (cond.class = Ndop) & (cond.subcl >= eql) & (cond.subcl <= geq) & (last.class = Ndop) & (last.subcl >= eql) & (last.subcl <= geq) & SameExp(cond.left, last.left) & SameExp(cond.right, last.right) THEN (* reuse comparison *) DevCPC486.setCC(x, cond.subcl, ODD(hint), hint >= 2) ELSIF (last # NIL) & (cond.class = Nmop) & (cond.subcl = is) & (last.class = Nmop) & (last.subcl = is) & SameExp(cond.left, last.left) THEN DevCPC486.ShortTypTest(x, cond.obj.typ) (* !!! *) ELSE condition(cond, x, else, local) END; hint := x.reg; DevCPC486.JumpF(x, else); IF local # DevCPL486.NewLbl THEN DevCPL486.SetLabel(local) END; stat(if.right, end); END CondStat; PROCEDURE IfStat (n: DevCPT.Node; withtrap: BOOLEAN; VAR end: DevCPL486.Label); VAR else, local: DevCPL486.Label; if, last: DevCPT.Node; hint: INTEGER; BEGIN (* n.class = Nifelse *) if := n.left; last := NIL; WHILE (if # NIL) & ((if.link # NIL) OR (n.right # NIL) OR withtrap) DO else := DevCPL486.NewLbl; CondStat(if, last, hint, else, end); IF sequential THEN DevCPC486.Jump(end) END; DevCPL486.SetLabel(else); last := if.left; if := if.link END; IF n.right # NIL THEN stat(n.right, end) ELSIF withtrap THEN DevCPM.errpos := n.conval.intval; Checkpc; DevCPC486.Trap(withTrap); sequential := FALSE ELSE CondStat(if, last, hint, end, end) END END IfStat; PROCEDURE CasePart (n: DevCPT.Node; VAR x: DevCPL486.Item; VAR else: DevCPL486.Label; last: BOOLEAN); VAR this, higher: DevCPL486.Label; m: DevCPT.Node; low, high: INTEGER; BEGIN IF n # NIL THEN this := SHORT(ENTIER(n.conval.realval)); IF useTree IN n.conval.setval THEN IF n.left # NIL THEN IF n.right # NIL THEN higher := DevCPL486.NewLbl; DevCPC486.CaseJump(x, n.conval.intval, n.conval.intval2, this, higher, TRUE, FALSE); CasePart(n.left, x, else, FALSE); DevCPL486.SetLabel(higher); CasePart(n.right, x, else, last) ELSE DevCPC486.CaseJump(x, n.conval.intval, n.conval.intval2, this, else, FALSE, FALSE); CasePart(n.left, x, else, last); END ELSE DevCPC486.CaseJump(x, n.conval.intval, n.conval.intval2, this, else, FALSE, TRUE); IF n.right # NIL THEN CasePart(n.right, x, else, last) ELSIF ~last THEN DevCPC486.Jump(else) END END ELSE IF useTable IN n.conval.setval THEN m := n; WHILE m.left # NIL DO m := m.left END; low := m.conval.intval; m := n; WHILE m.right # NIL DO m := m.right END; high := m.conval.intval2; DevCPC486.CaseTableJump(x, low, high, else); actual := low; last := TRUE END; CasePart(n.left, x, else, FALSE); WHILE actual < n.conval.intval DO DevCPL486.GenCaseEntry(else, FALSE); INC(actual) END; WHILE actual < n.conval.intval2 DO DevCPL486.GenCaseEntry(this, FALSE); INC(actual) END; DevCPL486.GenCaseEntry(this, last & (n.right = NIL)); INC(actual); CasePart(n.right, x, else, last) END; n.conval.realval := this END END CasePart; PROCEDURE CaseStat (n: DevCPT.Node; VAR end: DevCPL486.Label); VAR x: DevCPL486.Item; case, lab: DevCPT.Node; low, high, tab: INTEGER; else, this: DevCPL486.Label; BEGIN expr(n.left, x, {}, {mem, con, short, float, stk}); else := DevCPL486.NewLbl; IF (n.right.right # NIL) & (n.right.right.class = Ngoto) THEN (* jump to goto optimization *) CasePart(n.right.link, x, else, FALSE); DevCPC486.Free(x); n.right.right.right.conval.intval2 := else; sequential := FALSE ELSE CasePart(n.right.link, x, else, TRUE); DevCPC486.Free(x); DevCPL486.SetLabel(else); IF n.right.conval.setval # {} THEN stat(n.right.right, end) ELSE DevCPC486.Trap(caseTrap); sequential := FALSE END END; case := n.right.left; WHILE case # NIL DO (* case.class = Ncasedo *) IF sequential THEN DevCPC486.Jump(end) END; lab := case.left; IF (case.right # NIL) & (case.right.class = Ngoto) THEN (* jump to goto optimization *) case.right.right.conval.intval2 := SHORT(ENTIER(lab.conval.realval)); ASSERT(lab.link = NIL); sequential := FALSE ELSE WHILE lab # NIL DO this := SHORT(ENTIER(lab.conval.realval)); DevCPL486.SetLabel(this); lab := lab.link END; stat(case.right, end) END; case := case.link END END CaseStat; PROCEDURE Dim(n: DevCPT.Node; VAR x, nofel: DevCPL486.Item; VAR fact: INTEGER; dimtyp: DevCPT.Struct); VAR len: DevCPL486.Item; u: SET; s: INTEGER; BEGIN Check(n, u, s); IF (nofel.mode = Reg) & (nofel.reg IN u) THEN DevCPC486.Push(nofel) END; expr(n, len, {}, {mem, short}); IF nofel.mode = Stk THEN DevCPC486.Pop(nofel, Int32, {}, {}) END; IF len.mode = Stk THEN DevCPC486.Pop(len, Int32, {}, {}) END; DevCPC486.MulDim(len, nofel, fact, dimtyp); IF n.link # NIL THEN Dim(n.link, x, nofel, fact, dimtyp.BaseTyp); ELSE DevCPC486.New(x, nofel, fact) END; DevCPC486.SetDim(x, len, dimtyp) END Dim; PROCEDURE CompStat (n: DevCPT.Node); VAR x, y, sp, old, len, nofel: DevCPL486.Item; fact: INTEGER; typ: DevCPT.Struct; BEGIN Checkpc; WHILE (n # NIL) & DevCPM.noerr DO ASSERT(n.class = Nassign); IF n.subcl = assign THEN IF n.right.typ.form IN {String8, String16} THEN StringCopy(n.left, n.right) ELSE IF (n.left.typ.sysflag = interface) & ~CountedPtr(n.right) THEN IPAssign(NIL, n.right, x, y, {}); (* no Release *) ELSE expr(n.right, y, {}, {}) END; expr(n.left, x, {}, {}); DevCPC486.Assign(x, y) END ELSE ASSERT(n.subcl = newfn); typ := n.left.typ.BaseTyp; ASSERT(typ.comp = DynArr); ASSERT(n.right.link = NIL); expr(n.right, y, {}, wreg - {CX} + {mem, stk}); DevCPL486.MakeReg(sp, SP, Int32); DevCPC486.CopyReg(sp, old, {}, {CX}); DevCPC486.CopyReg(y, len, {}, {CX}); IF typ.BaseTyp.form = Char16 THEN DevCPL486.MakeConst(x, 2, Int32); DevCPL486.GenMul(x, y, FALSE) END; DevCPC486.StackAlloc; DevCPC486.Free(y); expr(n.left, x, {}, {}); DevCPC486.Assign(x, sp); DevCPC486.Push(len); DevCPC486.Push(old); typ.sysflag := stackArray END; n := n.link END END CompStat; PROCEDURE CompRelease (n: DevCPT.Node; VAR res: DevCPL486.Item); VAR x, y, sp: DevCPL486.Item; BEGIN IF n.link # NIL THEN CompRelease(n.link, res) END; ASSERT(n.class = Nassign); IF n.subcl = assign THEN IF (n.left.typ.form = Pointer) & (n.left.typ.sysflag = interface) THEN IF res.mode = Cond THEN DevCPL486.GenCode(9CH); (* push flags *) res.mode := Stk ELSIF res.mode = Reg THEN IF res.form < Int16 THEN DevCPC486.Push(res) ELSE DevCPC486.Assert(res, {}, {AX, CX, DX}) END END; expr(n.left, x, wreg - {DI}, {loaded}); DevCPC486.IPRelease(x, 0, TRUE, TRUE); n.left.obj.used := FALSE END ELSE ASSERT(n.subcl = newfn); DevCPL486.MakeReg(sp, SP, Int32); DevCPL486.GenPop(sp); DevCPL486.MakeConst(y, 0, Pointer); expr(n.left, x, {}, {}); DevCPC486.Assign(x, y) END END CompRelease; PROCEDURE Assign(n: DevCPT.Node; ux: SET); VAR r: DevCPT.Node; f: BYTE; false, true: DevCPL486.Label; x, y, z: DevCPL486.Item; uf, uy: SET; s: INTEGER; BEGIN r := n.right; f := r.typ.form; uf := {}; IF (r.class IN {Nmop, Ndop}) THEN IF (r.subcl = conv) & (f # Set) & (* (DevCPT.Includes(f, r.left.typ.form) OR DevCPT.Includes(f, n.left.typ.form)) THEN r := r.left; IF ~(f IN realSet) & (r.typ.form IN realSet) & (r.typ # DevCPT.intrealtyp) THEN uf := {AX} END (* entier *) *) (DevCPT.Includes(f, r.left.typ.form) OR DevCPT.Includes(f, n.left.typ.form)) & ((f IN realSet) OR ~(r.left.typ.form IN realSet)) THEN r := r.left ELSIF (f IN {Char8..Int32, Set, Char16, String8, String16}) & SameExp(n.left, r.left) THEN IF r.class = Ndop THEN IF (r.subcl IN {slash, plus, minus, msk}) OR (r.subcl = times) & (f = Set) THEN expr(r.right, y, {}, ux); expr(n.left, x, {}, {}); DevCPC486.Load(y, {}, {}); DevCPC486.IntDOp(x, y, r.subcl, FALSE); RETURN ELSIF r.subcl IN {ash, lsh, rot} THEN expr(r.right, y, wreg - {CX} + {high, mem}, ux); expr(n.left, x, {}, {}); DevCPC486.Load(y, {}, wreg - {CX} + {high}); DevCPC486.Shift(x, y, r.subcl); RETURN END ELSE IF r.subcl IN {minus, abs, cap} THEN expr(n.left, x, {}, {}); DevCPC486.IntMOp(x, r.subcl); RETURN END END ELSIF f = Bool THEN IF (r.subcl = not) & SameExp(n.left, r.left) THEN expr(n.left, x, {}, {}); DevCPC486.IntMOp(x, not); RETURN END END END; IF (n.left.typ.sysflag = interface) & (n.left.typ.form = Pointer) THEN IPAssign(n.left, r, x, y, ux) ELSE expr(r, y, {high}, ux); expr(n.left, x, {}, uf + {loaded}); (* high ??? *) END; DevCPC486.Assign(x, y) END Assign; PROCEDURE stat (n: DevCPT.Node; VAR end: DevCPL486.Label); VAR x, y, nofel: DevCPL486.Item; local, next, loop, prevExit: DevCPL486.Label; fact, sx, sz: INTEGER; ux, uz: SET; BEGIN sequential := TRUE; INC(nesting); WHILE (n # NIL) & DevCPM.noerr DO IF n.link = NIL THEN next := end ELSE next := DevCPL486.NewLbl END; DevCPM.errpos := n.conval.intval; DevCPL486.BegStat; CASE n.class OF | Ninittd: (* done at load-time *) | Nassign: Checkpc; Check(n.left, ux, sx); CASE n.subcl OF assign: IF n.left.typ.form = Comp THEN IF (n.right.class = Ndop) & (n.right.typ.form IN {String8, String16}) THEN StringCopy(n.left, n.right) ELSE StringOp(n.left, n.right, x, y, TRUE); IF DevCPC486.ContainsIPtrs(n.left.typ) THEN IPStructAssign(n.left.typ) END; DevCPC486.Copy(x, y, FALSE) END ELSE Assign(n, ux) END | getfn: Mem(n.right, y, n.left.typ, {}, ux); expr(n.left, x, {}, {loaded}); DevCPC486.Assign(x, y) | putfn: expr(n.right, y, {}, ux); Mem(n.left, x, n.right.typ, {}, {}); DevCPC486.Assign(x, y) | incfn, decfn: expr(n.right, y, {}, ux); expr(n.left, x, {}, {}); IF n.left.typ.form = Int64 THEN DevCPC486.LargeInc(x, y, n.subcl = decfn) ELSE DevCPC486.Load(y, {}, {}); DevCPC486.IntDOp(x, y, SHORT(SHORT(plus - incfn + n.subcl)), FALSE) END | inclfn: expr(n.right, y, {}, wreg - {CX} + {high, mem, stk}); DevCPC486.MakeSet(y, FALSE, FALSE, ux, {}); DevCPC486.Assert(y, {}, ux); expr(n.left, x, {}, {}); DevCPC486.Load(y, {}, {}); DevCPC486.IntDOp(x, y, plus, FALSE) | exclfn: expr(n.right, y, {}, wreg - {CX} + {high, mem, stk}); DevCPC486.MakeSet(y, FALSE, TRUE, ux, {}); DevCPC486.Assert(y, {}, ux); expr(n.left, x, {}, {}); DevCPC486.Load(y, {}, {}); DevCPC486.IntDOp(x, y, times, FALSE) | getrfn: expr(n.right, y, {}, {}); IF y.offset < 8 THEN DevCPL486.MakeReg(y, y.offset, n.left.typ.form); (* ??? *) expr(n.left, x, {}, {loaded}); DevCPC486.Assign(x, y) ELSE DevCPM.err(220) END | putrfn: expr(n.left, x, {}, {}); IF x.offset < 8 THEN DevCPL486.MakeReg(x, x.offset, n.right.typ.form); (* ??? *) expr(n.right, y, wreg - {x.reg}, {}); DevCPC486.Assign(x, y) ELSE DevCPM.err(220) END | newfn: y.typ := n.left.typ; IF n.right # NIL THEN IF y.typ.BaseTyp.comp = Record THEN expr(n.right, nofel, {}, {AX, CX, DX, mem, stk}); DevCPC486.New(y, nofel, 1); ELSE (*open array*) nofel.mode := Con; nofel.form := Int32; fact := 1; Dim(n.right, y, nofel, fact, y.typ.BaseTyp) END ELSE DevCPL486.MakeConst(nofel, 0, Int32); DevCPC486.New(y, nofel, 1); END; DevCPC486.Assert(y, {}, ux); expr(n.left, x, {}, {loaded}); DevCPC486.Assign(x, y) | sysnewfn: expr(n.right, y, {}, {mem, short}); DevCPC486.SysNew(y); DevCPC486.Assert(y, {}, ux); expr(n.left, x, {}, {}); DevCPC486.Assign(x, y) | copyfn: StringOp(n.left, n.right, x, y, TRUE); DevCPC486.Copy(x, y, TRUE) | movefn: Check(n.right.link, uz, sz); expr(n.right, y, {}, wreg - {SI} + {short} + ux + uz); expr(n.left, x, {}, wreg - {DI} + {short} + uz); expr(n.right.link, nofel, {}, wreg - {CX} + {mem, stk, short}); DevCPC486.Load(x, {}, wreg - {DI} + {con}); DevCPC486.Load(y, {}, wreg - {SI} + {con}); DevCPC486.SysMove(nofel) END; sequential := TRUE | Ncall: Checkpc; Call(n, x); sequential := TRUE | Nifelse: IF (n.subcl # assertfn) OR assert THEN IfStat(n, FALSE, next) END | Ncase: Checkpc; CaseStat(n, next) | Nwhile: local := DevCPL486.NewLbl; IF n.right # NIL THEN DevCPC486.Jump(local) END; loop := DevCPL486.NewLbl; DevCPL486.SetLabel(loop); stat(n.right, local); DevCPL486.SetLabel(local); DevCPM.errpos := n.conval.intval; Checkpc; condition(n.left, x, next, loop); DevCPC486.JumpT(x, loop); sequential := TRUE | Nrepeat: loop := DevCPL486.NewLbl; DevCPL486.SetLabel(loop); local := DevCPL486.NewLbl; stat(n.left, local); DevCPL486.SetLabel(local); DevCPM.errpos := n.conval.intval; Checkpc; condition(n.right, x, loop, next); DevCPC486.JumpF(x, loop); sequential := TRUE | Nloop: prevExit := Exit; Exit := next; loop := DevCPL486.NewLbl; DevCPL486.SetLabel(loop); stat(n.left, loop); IF sequential THEN DevCPC486.Jump(loop) END; next := Exit; Exit := prevExit; sequential := FALSE | Nexit: Checkpc; DevCPC486.Jump(Exit); sequential := FALSE | Nreturn: IF n.left # NIL THEN Checkpc; IF (n.obj.typ.sysflag = interface) & (n.obj.typ.form = Pointer) & (n.left.class # Nconst) & ~CountedPtr(n.left) THEN IPAssign(NIL, n.left, y, x, {}) ELSE expr(n.left, x, wreg - {AX}, {}) END; DevCPC486.Result(n.obj, x) END; IF (nesting > 1) OR (n.link # NIL) THEN DevCPC486.Jump(Return) END; sequential := FALSE | Nwith: IfStat(n, n.subcl = 0, next) | Ntrap: Checkpc; DevCPC486.Trap(n.right.conval.intval); sequential := TRUE | Ncomp: CompStat(n.left); stat(n.right, next); x.mode := 0; CompRelease(n.left, x) | Ndrop: Checkpc; expr(n.left, x, {}, {}); DevCPC486.Free(x) | Ngoto: IF n.left # NIL THEN Checkpc; condition(n.left, x, next, n.right.conval.intval2); DevCPC486.JumpT(x, n.right.conval.intval2) ELSE DevCPC486.Jump(n.right.conval.intval2); sequential := FALSE END | Njsr: DevCPL486.GenJump(-3, n.right.conval.intval2, FALSE) (* call n.right *) | Nret: DevCPL486.GenReturn(0); sequential := FALSE (* ret 0 *) | Nlabel: DevCPL486.SetLabel(n.conval.intval2) END; DevCPC486.CheckReg; DevCPL486.EndStat; n := n.link; IF n = NIL THEN end := next ELSIF next # DevCPL486.NewLbl THEN DevCPL486.SetLabel(next) END END; DEC(nesting) END stat; PROCEDURE CheckFpu (n: DevCPT.Node; VAR useFpu: BOOLEAN); BEGIN WHILE n # NIL DO IF n.typ.form IN {Real32, Real64} THEN useFpu := TRUE END; CASE n.class OF | Ncase: CheckFpu(n.left, useFpu); CheckFpu(n.right.left, useFpu); CheckFpu(n.right.right, useFpu) | Ncasedo: CheckFpu(n.right, useFpu) | Ngoto, Ndrop, Nloop, Nreturn, Nmop, Nfield, Nderef, Nguard: CheckFpu(n.left, useFpu) | Nassign, Ncall, Nifelse, Nif, Nwhile, Nrepeat, Nwith, Ncomp, Ndop, Nupto, Nindex: CheckFpu(n.left, useFpu); CheckFpu(n.right, useFpu) | Njsr, Nret, Nlabel, Ntrap, Nexit, Ninittd, Ntype, Nproc, Nconst, Nvar, Nvarpar: END; n := n.link END END CheckFpu; PROCEDURE procs(n: DevCPT.Node); VAR proc, obj: DevCPT.Object; i, j: INTEGER; end: DevCPL486.Label; ch: SHORTCHAR; name: DevCPT.Name; useFpu: BOOLEAN; BEGIN INC(DevCPL486.level); nesting := 0; WHILE (n # NIL) & DevCPM.noerr DO DevCPC486.imLevel[DevCPL486.level] := DevCPC486.imLevel[DevCPL486.level - 1]; proc := n.obj; IF imVar IN proc.conval.setval THEN INC(DevCPC486.imLevel[DevCPL486.level]) END; procs(n.left); DevCPM.errpos := n.conval.intval; useFpu := FALSE; CheckFpu(n.right, useFpu); DevCPC486.Enter(proc, n.right = NIL, useFpu); InitializeIPVars(proc); end := DevCPL486.NewLbl; Return := DevCPL486.NewLbl; stat(n.right, end); DevCPM.errpos := n.conval.intval2; Checkpc; IF sequential OR (end # DevCPL486.NewLbl) THEN DevCPL486.SetLabel(end); IF (proc.typ # DevCPT.notyp) & (proc.sysflag # noframe) THEN DevCPC486.Trap(funcTrap) END END; DevCPL486.SetLabel(Return); ReleaseIPVars(proc); DevCPC486.Exit(proc, n.right = NIL); IF proc.mode = TProc THEN name := proc.link.typ.strobj.name^$; i := 0; WHILE name[i] # 0X DO INC(i) END; name[i] := "."; INC(i); j := 0; ch := proc.name[0]; WHILE (ch # 0X) & (i < LEN(name)-1) DO name[i] := ch; INC(i); INC(j); ch := proc.name[j] END ; name[i] := 0X; ELSE name := proc.name^$ END; DevCPE.OutRefName(name); DevCPE.OutRefs(proc.scope.right); n := n.link END; DEC(DevCPL486.level) END procs; PROCEDURE Module*(prog: DevCPT.Node); VAR end: DevCPL486.Label; name: DevCPT.Name; obj, p: DevCPT.Object; n: DevCPT.Node; aAd, rAd: INTEGER; typ: DevCPT.Struct; useFpu: BOOLEAN; BEGIN DevCPH.UseReals(prog, {DevCPH.longDop, DevCPH.longMop}); DevCPM.NewObj(DevCPT.SelfName); IF DevCPM.noerr THEN DevCPE.OutHeader; n := prog.right; WHILE (n # NIL) & (n.class = Ninittd) DO n := n.link END; useFpu := FALSE; CheckFpu(n, useFpu); DevCPC486.Enter(NIL, n = NIL, useFpu); end := DevCPL486.NewLbl; stat(n, end); DevCPL486.SetLabel(end); DevCPM.errpos := prog.conval.intval2; Checkpc; DevCPC486.Exit(NIL, n = NIL); IF prog.link # NIL THEN (* close section *) DevCPL486.SetLabel(DevCPE.closeLbl); useFpu := FALSE; CheckFpu(prog.link, useFpu); DevCPC486.Enter(NIL, FALSE, useFpu); end := DevCPL486.NewLbl; stat(prog.link, end); DevCPL486.SetLabel(end); DevCPM.errpos := SHORT(ENTIER(prog.conval.realval)); Checkpc; DevCPC486.Exit(NIL, FALSE) END; name := "$$"; DevCPE.OutRefName(name); DevCPE.OutRefs(DevCPT.topScope.right); DevCPM.errpos := prog.conval.intval; WHILE query # NIL DO typ := query.typ; query.typ := DevCPT.int32typ; query.conval.intval := 20; (* parameters *) query.conval.intval2 := -8; (* saved registers *) DevCPC486.Enter(query, FALSE, FALSE); InstallQueryInterface(typ, query); DevCPC486.Exit(query, FALSE); name := "QueryInterface"; DevCPE.OutRefName(name); query := query.nlink END; procs(prog.left); DevCPC486.InstallStackAlloc; addRef := NIL; release := NIL; release2 := NIL; DevCPC486.intHandler := NIL; IF DevCPM.noerr THEN DevCPE.OutCode END; IF ~DevCPM.noerr THEN DevCPM.DeleteObj END END END Module; END DevCPV486.