2
0

CPV486.txt 63 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774
  1. MODULE DevCPV486;
  2. (* THIS IS TEXT COPY OF BlackBox 1.6-rc6 Dev/Mod/CPV486.odc *)
  3. (* DO NOT EDIT *)
  4. IMPORT SYSTEM, DevCPM, DevCPT, DevCPE, DevCPH, DevCPL486, DevCPC486;
  5. CONST
  6. processor* = 10; (* for i386 *)
  7. (* object modes *)
  8. Var = 1; VarPar = 2; Con = 3; Fld = 4; Typ = 5; LProc = 6; XProc = 7;
  9. SProc = 8; CProc = 9; IProc = 10; Mod = 11; Head = 12; TProc = 13;
  10. (* item modes for i386 *)
  11. Ind = 14; Abs = 15; Stk = 16; Cond = 17; Reg = 18; DInd = 19;
  12. (* symbol values and ops *)
  13. times = 1; slash = 2; div = 3; mod = 4;
  14. and = 5; plus = 6; minus = 7; or = 8; eql = 9;
  15. neq = 10; lss = 11; leq = 12; gtr = 13; geq = 14;
  16. in = 15; is = 16; ash = 17; msk = 18; len = 19;
  17. conv = 20; abs = 21; cap = 22; odd = 23; not = 33;
  18. (*SYSTEM*)
  19. adr = 24; cc = 25; bit = 26; lsh = 27; rot = 28; val = 29;
  20. min = 34; max = 35; typfn = 36;
  21. thisrecfn = 45; thisarrfn = 46;
  22. shl = 50; shr = 51; lshr = 52; xor = 53;
  23. (* structure forms *)
  24. Undef = 0; Byte = 1; Bool = 2; Char8 = 3; Int8 = 4; Int16 = 5; Int32 = 6;
  25. Real32 = 7; Real64 = 8; Set = 9; String8 = 10; NilTyp = 11; NoTyp = 12;
  26. Pointer = 13; ProcTyp = 14; Comp = 15;
  27. Char16 = 16; String16 = 17; Int64 = 18;
  28. VString16to8 = 29; VString8 = 30; VString16 = 31;
  29. realSet = {Real32, Real64};
  30. (* composite structure forms *)
  31. Basic = 1; Array = 2; DynArr = 3; Record = 4;
  32. (* nodes classes *)
  33. Nvar = 0; Nvarpar = 1; Nfield = 2; Nderef = 3; Nindex = 4; Nguard = 5; Neguard = 6;
  34. Nconst = 7; Ntype = 8; Nproc = 9; Nupto = 10; Nmop = 11; Ndop = 12; Ncall = 13;
  35. Ninittd = 14; Nif = 15; Ncaselse = 16; Ncasedo = 17; Nenter = 18; Nassign = 19;
  36. Nifelse =20; Ncase = 21; Nwhile = 22; Nrepeat = 23; Nloop = 24; Nexit = 25;
  37. Nreturn = 26; Nwith = 27; Ntrap = 28; Ncomp = 30;
  38. Ndrop = 50; Nlabel = 51; Ngoto = 52; Njsr = 53; Nret = 54; Ncmp = 55;
  39. (*function number*)
  40. assign = 0; newfn = 1; incfn = 13; decfn = 14;
  41. inclfn = 15; exclfn = 16; copyfn = 18; assertfn = 32;
  42. (*SYSTEM function number*)
  43. getfn = 24; putfn = 25; getrfn = 26; putrfn = 27; sysnewfn = 30; movefn = 31;
  44. (* COM function number *)
  45. validfn = 40; queryfn = 42;
  46. (* procedure flags (conval.setval) *)
  47. hasBody = 1; isRedef = 2; slNeeded = 3; imVar = 4; isHidden = 29; isGuarded = 30; isCallback = 31;
  48. (* attribute flags (attr.adr, struct.attribute, proc.conval.setval) *)
  49. newAttr = 16; absAttr = 17; limAttr = 18; empAttr = 19; extAttr = 20;
  50. (* case statement flags (conval.setval) *)
  51. useTable = 1; useTree = 2;
  52. (* registers *)
  53. AX = 0; CX = 1; DX = 2; BX = 3; SP = 4; BP = 5; SI = 6; DI = 7; AH = 4; CH = 5; DH = 6; BH = 7;
  54. stk = 31; mem = 30; con = 29; float = 28; high = 27; short = 26; deref = 25; loaded = 24;
  55. wreg = {AX, BX, CX, DX, SI, DI};
  56. (* module visibility of objects *)
  57. internal = 0; external = 1; externalR = 2; inPar = 3; outPar = 4;
  58. (* sysflag *)
  59. untagged = 1; noAlign = 3; align2 = 4; align8 = 6; union = 7;
  60. interface = 10; guarded = 8; noframe = 16;
  61. nilBit = 1; enumBits = 8; new = 1; iid = 2;
  62. stackArray = 120;
  63. (* system trap numbers *)
  64. withTrap = -1; caseTrap = -2; funcTrap = -3; typTrap = -4;
  65. recTrap = -5; ranTrap = -6; inxTrap = -7; copyTrap = -8;
  66. ParOff = 8;
  67. interfaceSize = 16; (* SIZE(Kernel.Interface) *)
  68. addRefFP = 4E27A847H; (* fingerprint of AddRef and Release procedures *)
  69. intHandlerFP = 24B0EAE3H; (* fingerprint of InterfaceTrapHandler *)
  70. numPreIntProc = 2;
  71. VAR
  72. Exit, Return: DevCPL486.Label;
  73. assert, sequential: BOOLEAN;
  74. nesting, actual: INTEGER;
  75. query, addRef, release, release2: DevCPT.Object;
  76. PROCEDURE Init*(opt: SET);
  77. CONST ass = 2;
  78. BEGIN
  79. DevCPL486.Init(opt); DevCPC486.Init(opt);
  80. assert := ass IN opt;
  81. DevCPM.breakpc := MAX(INTEGER);
  82. query := NIL; addRef := NIL; release := NIL; release2 := NIL; DevCPC486.intHandler := NIL;
  83. END Init;
  84. PROCEDURE Close*;
  85. BEGIN
  86. DevCPL486.Close
  87. END Close;
  88. PROCEDURE Align(VAR offset: INTEGER; align: INTEGER);
  89. BEGIN
  90. CASE align OF
  91. 1: (* ok *)
  92. | 2: INC(offset, offset MOD 2)
  93. | 4: INC(offset, (-offset) MOD 4)
  94. | 8: INC(offset, (-offset) MOD 8)
  95. END
  96. END Align;
  97. PROCEDURE NegAlign(VAR offset: INTEGER; align: INTEGER);
  98. BEGIN
  99. CASE align OF
  100. 1: (* ok *)
  101. | 2: DEC(offset, offset MOD 2)
  102. | 4: DEC(offset, offset MOD 4)
  103. | 8: DEC(offset, offset MOD 8)
  104. END
  105. END NegAlign;
  106. PROCEDURE Base(typ: DevCPT.Struct; limit: INTEGER): INTEGER; (* typ.comp # DynArr *)
  107. VAR align: INTEGER;
  108. BEGIN
  109. WHILE typ.comp = Array DO typ := typ.BaseTyp END ;
  110. IF typ.comp = Record THEN
  111. align := typ.align
  112. ELSE
  113. align := typ.size;
  114. END;
  115. IF align > limit THEN RETURN limit ELSE RETURN align END
  116. END Base;
  117. (* -----------------------------------------------------
  118. reference implementation of TypeSize for portable symbol files
  119. mandatory for all non-system structures
  120. PROCEDURE TypeSize (typ: DevCPT.Struct);
  121. VAR f, c: SHORTINT; offset: LONGINT; fld: DevCPT.Object; btyp: DevCPT.Struct;
  122. BEGIN
  123. IF typ.size = -1 THEN
  124. f := typ.form; c := typ.comp; btyp := typ.BaseTyp;
  125. IF c = Record THEN
  126. IF btyp = NIL THEN offset := 0 ELSE TypeSize(btyp); offset := btyp.size END;
  127. fld := typ.link;
  128. WHILE (fld # NIL) & (fld.mode = Fld) DO
  129. btyp := fld.typ; TypeSize(btyp);
  130. IF btyp.size >= 4 THEN INC(offset, (-offset) MOD 4)
  131. ELSIF btyp.size >= 2 THEN INC(offset, offset MOD 2)
  132. END;
  133. fld.adr := offset; INC(offset, btyp.size);
  134. fld := fld.link
  135. END;
  136. IF offset > 2 THEN INC(offset, (-offset) MOD 4) END;
  137. typ.size := offset; typ.align := 4;
  138. typ.n := -1 (* methods not counted yet *)
  139. ELSIF c = Array THEN
  140. TypeSize(btyp);
  141. typ.size := typ.n * btyp.size
  142. ELSIF f = Pointer THEN
  143. typ.size := DevCPM.PointerSize
  144. ELSIF f = ProcTyp THEN
  145. typ.size := DevCPM.ProcSize
  146. ELSE (* c = DynArr *)
  147. TypeSize(btyp);
  148. IF btyp.comp = DynArr THEN typ.size := btyp.size + 4
  149. ELSE typ.size := 8
  150. END
  151. END
  152. END
  153. END TypeSize;
  154. ----------------------------------------------------- *)
  155. PROCEDURE GTypeSize (typ: DevCPT.Struct; guarded: BOOLEAN);
  156. VAR f, c: BYTE; offset, align, falign, alignLimit: INTEGER;
  157. fld: DevCPT.Object; btyp: DevCPT.Struct; name: DevCPT.Name;
  158. BEGIN
  159. IF typ.untagged THEN guarded := TRUE END;
  160. IF typ = DevCPT.undftyp THEN DevCPM.err(58)
  161. ELSIF typ.size = -1 THEN
  162. f := typ.form; c := typ.comp; btyp := typ.BaseTyp;
  163. IF c = Record THEN
  164. IF btyp = NIL THEN offset := 0; align := 1;
  165. ELSE GTypeSize(btyp, guarded); offset := btyp.size; align := btyp.align
  166. END ;
  167. IF typ.sysflag = noAlign THEN alignLimit := 1
  168. ELSIF typ.sysflag = align2 THEN alignLimit := 2
  169. ELSIF typ.sysflag = align8 THEN alignLimit := 8
  170. ELSE alignLimit := 4
  171. END;
  172. fld := typ.link;
  173. WHILE (fld # NIL) & (fld.mode = Fld) DO
  174. btyp := fld.typ; GTypeSize(btyp, guarded);
  175. IF typ.sysflag > 0 THEN falign := Base(btyp, alignLimit)
  176. ELSIF btyp.size >= 4 THEN falign := 4
  177. ELSIF btyp.size >= 2 THEN falign := 2
  178. ELSE falign := 1
  179. END;
  180. IF typ.sysflag = union THEN
  181. fld.adr := 0;
  182. IF btyp.size > offset THEN offset := btyp.size END;
  183. ELSE
  184. Align(offset, falign);
  185. fld.adr := offset;
  186. IF offset <= MAX(INTEGER) - 4 - btyp.size THEN INC(offset, btyp.size)
  187. ELSE offset := 4; DevCPM.Mark(214, typ.txtpos)
  188. END
  189. END;
  190. IF falign > align THEN align := falign END ;
  191. fld := fld.link
  192. END;
  193. (*
  194. IF (typ.sysflag = interface) & (typ.BaseTyp = NIL) THEN
  195. fld := DevCPT.NewObj(); fld.name^ := DevCPM.HdPtrName; fld.mode := Fld;
  196. fld.typ := DevCPT.undftyp; fld.adr := 8;
  197. fld.right := typ.link; typ.link := fld;
  198. fld := DevCPT.NewObj(); fld.name^ := DevCPM.HdPtrName; fld.mode := Fld;
  199. fld.typ := DevCPT.undftyp; fld.adr := 12;
  200. typ.link.link := fld; typ.link.left := fld;
  201. offset := interfaceSize; align := 4
  202. END;
  203. *)
  204. IF typ.sysflag <= 0 THEN align := 4 END;
  205. typ.align := align;
  206. IF (typ.sysflag > 0) OR (offset > 2) THEN Align(offset, align) END;
  207. typ.size := offset;
  208. typ.n := -1 (* methods not counted yet *)
  209. ELSIF c = Array THEN
  210. GTypeSize(btyp, guarded);
  211. IF (btyp.size = 0) OR (typ.n <= MAX(INTEGER) DIV btyp.size) THEN typ.size := typ.n * btyp.size
  212. ELSE typ.size := 4; DevCPM.Mark(214, typ.txtpos)
  213. END
  214. ELSIF f = Pointer THEN
  215. typ.size := DevCPM.PointerSize;
  216. IF guarded & ~typ.untagged THEN DevCPM.Mark(143, typ.txtpos) END
  217. ELSIF f = ProcTyp THEN
  218. typ.size := DevCPM.ProcSize
  219. ELSE (* c = DynArr *)
  220. GTypeSize(btyp, guarded);
  221. IF (typ.sysflag = untagged) OR typ.untagged THEN typ.size := 4
  222. ELSE
  223. IF btyp.comp = DynArr THEN typ.size := btyp.size + 4
  224. ELSE typ.size := 8
  225. END
  226. END
  227. END
  228. END
  229. END GTypeSize;
  230. PROCEDURE TypeSize*(typ: DevCPT.Struct); (* also called from DevCPT.InStruct for arrays *)
  231. BEGIN
  232. GTypeSize(typ, FALSE)
  233. END TypeSize;
  234. PROCEDURE GetComKernel;
  235. VAR name: DevCPT.Name; mod: DevCPT.Object;
  236. BEGIN
  237. IF addRef = NIL THEN
  238. DevCPT.OpenScope(SHORT(SHORT(-DevCPT.nofGmod)), NIL);
  239. DevCPT.topScope.name := DevCPT.NewName("$$");
  240. name := "AddRef"; DevCPT.Insert(name, addRef);
  241. addRef.mode := XProc;
  242. addRef.fprint := addRefFP;
  243. addRef.fpdone := TRUE;
  244. name := "Release"; DevCPT.Insert(name, release);
  245. release.mode := XProc;
  246. release.fprint := addRefFP;
  247. release.fpdone := TRUE;
  248. name := "Release2"; DevCPT.Insert(name, release2);
  249. release2.mode := XProc;
  250. release2.fprint := addRefFP;
  251. release2.fpdone := TRUE;
  252. name := "InterfaceTrapHandler"; DevCPT.Insert(name, DevCPC486.intHandler);
  253. DevCPC486.intHandler.mode := XProc;
  254. DevCPC486.intHandler.fprint := intHandlerFP;
  255. DevCPC486.intHandler.fpdone := TRUE;
  256. DevCPT.GlbMod[DevCPT.nofGmod] := DevCPT.topScope;
  257. INC(DevCPT.nofGmod);
  258. DevCPT.CloseScope;
  259. END
  260. END GetComKernel;
  261. PROCEDURE EnumTProcs(rec: DevCPT.Struct); (* method numbers in declaration order *)
  262. VAR btyp: DevCPT.Struct; obj, redef: DevCPT.Object;
  263. BEGIN
  264. IF rec.n = -1 THEN
  265. rec.n := 0; btyp := rec.BaseTyp;
  266. IF btyp # NIL THEN
  267. EnumTProcs(btyp); rec.n := btyp.n;
  268. END;
  269. obj := rec.strobj.link;
  270. WHILE obj # NIL DO
  271. DevCPT.FindBaseField(obj.name^, rec, redef);
  272. IF redef # NIL THEN obj.num := redef.num (*mthno*);
  273. IF ~(isRedef IN obj.conval.setval) OR (redef.conval.setval * {extAttr, absAttr, empAttr} = {}) THEN
  274. DevCPM.Mark(119, rec.txtpos)
  275. END
  276. ELSE obj.num := rec.n; INC(rec.n)
  277. END ;
  278. IF obj.conval.setval * {hasBody, absAttr, empAttr} = {} THEN DevCPM.Mark(129, obj.adr) END;
  279. obj := obj.nlink
  280. END
  281. END
  282. END EnumTProcs;
  283. PROCEDURE CountTProcs(rec: DevCPT.Struct);
  284. VAR btyp: DevCPT.Struct; comProc: INTEGER; m, rel: DevCPT.Object; name: DevCPT.Name;
  285. PROCEDURE TProcs(obj: DevCPT.Object); (* obj.mnolev = 0, TProcs of base type already counted *)
  286. VAR redef: DevCPT.Object;
  287. BEGIN
  288. IF obj # NIL THEN
  289. TProcs(obj.left);
  290. IF obj.mode = TProc THEN
  291. DevCPT.FindBaseField(obj.name^, rec, redef);
  292. (* obj.adr := 0 *)
  293. IF redef # NIL THEN
  294. obj.num := redef.num (*mthno*);
  295. IF (redef.link # NIL) & (redef.link.typ.sysflag = interface) THEN
  296. obj.num := numPreIntProc + comProc - 1 - obj.num
  297. END;
  298. IF ~(isRedef IN obj.conval.setval) OR (redef.conval.setval * {extAttr, absAttr, empAttr} = {}) THEN
  299. DevCPM.Mark(119, rec.txtpos)
  300. END
  301. ELSE obj.num := rec.n; INC(rec.n)
  302. END ;
  303. IF obj.conval.setval * {hasBody, absAttr, empAttr} = {} THEN DevCPM.Mark(129, obj.adr) END
  304. END ;
  305. TProcs(obj.right)
  306. END
  307. END TProcs;
  308. BEGIN
  309. IF rec.n = -1 THEN
  310. comProc := 0;
  311. IF rec.untagged THEN rec.n := 0 ELSE rec.n := DevCPT.anytyp.n END;
  312. btyp := rec.BaseTyp;
  313. IF btyp # NIL THEN
  314. IF btyp.sysflag = interface THEN
  315. EnumTProcs(btyp); rec.n := btyp.n + numPreIntProc; comProc := btyp.n;
  316. ELSE
  317. CountTProcs(btyp); rec.n := btyp.n
  318. END
  319. END;
  320. WHILE (btyp # NIL) & (btyp # DevCPT.undftyp) & (btyp.sysflag # interface) DO btyp := btyp.BaseTyp END;
  321. IF (btyp # NIL) & (btyp.sysflag = interface) THEN
  322. IF comProc > 0 THEN
  323. name := "QueryInterface"; DevCPT.FindField(name, rec, m);
  324. IF m.link.typ.sysflag = interface THEN
  325. DevCPT.InsertField(name, rec, m); m.mode := TProc; m.typ := rec;
  326. m.conval := DevCPT.NewConst(); m.conval.setval := {isRedef, hasBody, isCallback, extAttr};
  327. m.nlink := query; query := m
  328. END;
  329. name := "AddRef";
  330. DevCPT.InsertField(name, rec, m); m.mode := TProc; m.mnolev := 0;
  331. m.conval := DevCPT.NewConst(); m.conval.setval := {isRedef, hasBody, isCallback, isHidden, extAttr};
  332. GetComKernel; addRef.used := TRUE; m.adr := -1; m.nlink := addRef;
  333. END;
  334. name := "RELEASE";
  335. DevCPT.FindField(name, rec, rel);
  336. IF (rel # NIL) & (rel.link.typ = DevCPT.anyptrtyp) THEN rel := NIL END;
  337. IF (comProc > 0) OR (rel # NIL) THEN
  338. name := "Release";
  339. DevCPT.InsertField(name, rec, m); m.mode := TProc; m.mnolev := 0;
  340. m.conval := DevCPT.NewConst(); m.conval.setval := {isRedef, hasBody, isCallback, isHidden, extAttr};
  341. GetComKernel; m.adr := -1;
  342. IF rel # NIL THEN release2.used := TRUE; m.nlink := release2
  343. ELSE release.used := TRUE; m.nlink := release
  344. END
  345. END
  346. END;
  347. TProcs(rec.link);
  348. END
  349. END CountTProcs;
  350. PROCEDURE ^Parameters(firstPar, proc: DevCPT.Object);
  351. PROCEDURE ^TProcedures(obj: DevCPT.Object);
  352. PROCEDURE TypeAlloc(typ: DevCPT.Struct);
  353. VAR f, c: SHORTINT; fld: DevCPT.Object; btyp: DevCPT.Struct;
  354. BEGIN
  355. IF ~typ.allocated THEN (* not imported, not predefined, not allocated yet *)
  356. typ.allocated := TRUE;
  357. TypeSize(typ);
  358. f := typ.form; c := typ.comp; btyp := typ.BaseTyp;
  359. IF c = Record THEN
  360. IF typ.sysflag = interface THEN
  361. EnumTProcs(typ);
  362. ELSE
  363. CountTProcs(typ)
  364. END;
  365. IF typ.extlev > 14 THEN DevCPM.Mark(233, typ.txtpos) END;
  366. IF btyp # NIL THEN TypeAlloc(btyp) END;
  367. IF ~typ.untagged THEN DevCPE.AllocTypDesc(typ) END;
  368. fld := typ.link;
  369. WHILE (fld # NIL) & (fld.mode = Fld) DO
  370. TypeAlloc(fld.typ); fld := fld.link
  371. END;
  372. TProcedures(typ.link)
  373. ELSIF f = Pointer THEN
  374. IF btyp = DevCPT.undftyp THEN DevCPM.Mark(128, typ.txtpos)
  375. ELSE TypeAlloc(btyp);
  376. END
  377. ELSIF f = ProcTyp THEN
  378. TypeAlloc(btyp);
  379. Parameters(typ.link, NIL)
  380. ELSE (* c IN {Array, DynArr} *)
  381. TypeAlloc(btyp);
  382. IF (btyp.comp = DynArr) & btyp.untagged & ~typ.untagged THEN DevCPM.Mark(225, typ.txtpos) END;
  383. END
  384. END
  385. END TypeAlloc;
  386. PROCEDURE NumOfIntProc (typ: DevCPT.Struct): INTEGER;
  387. BEGIN
  388. WHILE (typ # NIL) & (typ.sysflag # interface) DO typ := typ.BaseTyp END;
  389. IF typ # NIL THEN RETURN typ.n
  390. ELSE RETURN 0
  391. END
  392. END NumOfIntProc;
  393. PROCEDURE Parameters(firstPar, proc: DevCPT.Object);
  394. (* firstPar.mnolev = 0 *)
  395. VAR par: DevCPT.Object; typ: DevCPT.Struct; padr, vadr: INTEGER;
  396. BEGIN
  397. padr := ParOff; par := firstPar;
  398. WHILE par # NIL DO
  399. typ := par.typ; TypeAlloc(typ);
  400. par.adr := padr;
  401. IF (par.mode = VarPar) & (typ.comp # DynArr) THEN
  402. IF (typ.comp = Record) & ~typ.untagged THEN INC(padr, 8)
  403. ELSE INC(padr, 4)
  404. END
  405. ELSE
  406. IF (par.mode = Var) & (typ.comp = DynArr) & typ.untagged THEN DevCPM.err(145) END;
  407. INC(padr, typ.size); Align(padr, 4)
  408. END;
  409. par := par.link
  410. END;
  411. IF proc # NIL THEN
  412. IF proc.mode = XProc THEN
  413. INCL(proc.conval.setval, isCallback)
  414. ELSIF (proc.mode = TProc)
  415. & (proc.num >= numPreIntProc)
  416. & (proc.num < numPreIntProc + NumOfIntProc(proc.link.typ))
  417. THEN
  418. INCL(proc.conval.setval, isCallback);
  419. INCL(proc.conval.setval, isGuarded)
  420. END;
  421. IF proc.sysflag = guarded THEN INCL(proc.conval.setval, isGuarded) END;
  422. IF isGuarded IN proc.conval.setval THEN
  423. GetComKernel; vadr := -24
  424. ELSE
  425. vadr := 0;
  426. IF imVar IN proc.conval.setval THEN DEC(vadr, 4) END;
  427. IF isCallback IN proc.conval.setval THEN DEC(vadr, 8) END
  428. END;
  429. proc.conval.intval := padr; proc.conval.intval2 := vadr;
  430. END
  431. END Parameters;
  432. PROCEDURE Variables(var: DevCPT.Object; VAR varSize: INTEGER);
  433. (* allocates only offsets, regs allocated in DevCPC486.Enter *)
  434. VAR adr: INTEGER; typ: DevCPT.Struct;
  435. BEGIN
  436. adr := varSize;
  437. WHILE var # NIL DO
  438. typ := var.typ; TypeAlloc(typ);
  439. DEC(adr, typ.size); NegAlign(adr, Base(typ, 4));
  440. var.adr := adr;
  441. var := var.link
  442. END;
  443. NegAlign(adr, 4); varSize := adr
  444. END Variables;
  445. PROCEDURE ^Objects(obj: DevCPT.Object);
  446. PROCEDURE Procedure(obj: DevCPT.Object);
  447. (* obj.mnolev = 0 *)
  448. VAR oldPos: INTEGER;
  449. BEGIN
  450. oldPos := DevCPM.errpos; DevCPM.errpos := obj.scope.adr;
  451. TypeAlloc(obj.typ);
  452. Parameters(obj.link, obj);
  453. IF ~(hasBody IN obj.conval.setval) THEN DevCPM.Mark(129, obj.adr) END ;
  454. Variables(obj.scope.scope, obj.conval.intval2); (* local variables *)
  455. Objects(obj.scope.right);
  456. DevCPM.errpos := oldPos
  457. END Procedure;
  458. PROCEDURE TProcedures(obj: DevCPT.Object);
  459. (* obj.mnolev = 0 *)
  460. VAR par: DevCPT.Object; psize: INTEGER;
  461. BEGIN
  462. IF obj # NIL THEN
  463. TProcedures(obj.left);
  464. IF (obj.mode = TProc) & (obj.scope # NIL) THEN
  465. TypeAlloc(obj.typ);
  466. Parameters(obj.link, obj);
  467. Variables(obj.scope.scope, obj.conval.intval2); (* local variables *)
  468. Objects(obj.scope.right);
  469. END ;
  470. TProcedures(obj.right)
  471. END
  472. END TProcedures;
  473. PROCEDURE Objects(obj: DevCPT.Object);
  474. BEGIN
  475. IF obj # NIL THEN
  476. Objects(obj.left);
  477. IF obj.mode IN {Con, Typ, LProc, XProc, CProc, IProc} THEN
  478. IF (obj.mode IN {Con, Typ}) THEN TypeAlloc(obj.typ);
  479. ELSE Procedure(obj)
  480. END
  481. END ;
  482. Objects(obj.right)
  483. END
  484. END Objects;
  485. PROCEDURE Allocate*;
  486. VAR gvarSize: INTEGER; name: DevCPT.Name;
  487. BEGIN
  488. DevCPM.errpos := DevCPT.topScope.adr; (* text position of scope used if error *)
  489. gvarSize := 0;
  490. Variables(DevCPT.topScope.scope, gvarSize); DevCPE.dsize := -gvarSize;
  491. Objects(DevCPT.topScope.right)
  492. END Allocate;
  493. (************************)
  494. PROCEDURE SameExp (n1, n2: DevCPT.Node): BOOLEAN;
  495. BEGIN
  496. WHILE (n1.class = n2.class) & (n1.typ = n2.typ) DO
  497. CASE n1.class OF
  498. | Nvar, Nvarpar, Nproc: RETURN n1.obj = n2.obj
  499. | Nconst: RETURN (n1.typ.form IN {Int8..Int32}) & (n1.conval.intval = n2.conval.intval)
  500. | Nfield: IF n1.obj # n2.obj THEN RETURN FALSE END
  501. | Nderef, Nguard:
  502. | Nindex: IF ~SameExp(n1.right, n2.right) THEN RETURN FALSE END
  503. | Nmop: IF (n1.subcl # n2.subcl) OR (n1.subcl = is) THEN RETURN FALSE END
  504. | Ndop: IF (n1.subcl # n2.subcl) OR ~SameExp(n1.right, n2.right) THEN RETURN FALSE END
  505. ELSE RETURN FALSE
  506. END ;
  507. n1 := n1.left; n2 := n2.left
  508. END;
  509. RETURN FALSE
  510. END SameExp;
  511. PROCEDURE Check (n: DevCPT.Node; VAR used: SET; VAR size: INTEGER);
  512. VAR ux, uy: SET; sx, sy, sf: INTEGER; f: BYTE;
  513. BEGIN
  514. used := {}; size := 0;
  515. WHILE n # NIL DO
  516. IF n.class # Ncomp THEN
  517. Check(n.left, ux, sx);
  518. Check(n.right, uy, sy)
  519. END;
  520. ux := ux + uy; sf := 0;
  521. CASE n.class OF
  522. | Nvar, Nvarpar:
  523. IF (n.class = Nvarpar) OR (n.typ.comp = DynArr) OR
  524. (n.obj.mnolev > 0) &
  525. (DevCPC486.imLevel[n.obj.mnolev] < DevCPC486.imLevel[DevCPL486.level]) THEN sf := 1 END
  526. | Nguard: sf := 2
  527. | Neguard, Nderef: sf := 1
  528. | Nindex:
  529. IF (n.right.class # Nconst) OR (n.left.typ.comp = DynArr) THEN sf := 1 END;
  530. IF sx > 0 THEN INC(sy) END
  531. | Nmop:
  532. CASE n.subcl OF
  533. | is, adr, typfn, minus, abs, cap, val: sf := 1
  534. | bit: sf := 2; INCL(ux, CX)
  535. | conv:
  536. IF n.typ.form = Int64 THEN sf := 2
  537. ELSIF ~(n.typ.form IN realSet) THEN sf := 1;
  538. IF n.left.typ.form IN realSet THEN INCL(ux, AX) END
  539. END
  540. | odd, cc, not:
  541. END
  542. | Ndop:
  543. f := n.left.typ.form;
  544. IF f # Bool THEN
  545. CASE n.subcl OF
  546. | times:
  547. sf := 1;
  548. IF f = Int8 THEN INCL(ux, AX) END
  549. | div, mod:
  550. sf := 3; INCL(ux, AX);
  551. IF f > Int8 THEN INCL(ux, DX) END
  552. | eql..geq:
  553. IF f IN {String8, String16, Comp} THEN ux := ux + {AX, CX, SI, DI}; sf := 4
  554. ELSIF f IN realSet THEN INCL(ux, AX); sf := 1
  555. ELSE sf := 1
  556. END
  557. | ash, lsh, rot:
  558. IF n.right.class = Nconst THEN sf := 1 ELSE sf := 2; INCL(ux, CX) END
  559. | slash, plus, minus, msk, in, bit:
  560. sf := 1
  561. | len:
  562. IF f IN {String8, String16} THEN ux := ux + {AX, CX, DI}; sf := 3
  563. ELSE sf := 1
  564. END
  565. | min, max:
  566. sf := 1;
  567. IF f IN realSet THEN INCL(ux, AX) END
  568. | queryfn:
  569. ux := ux + {CX, SI, DI}; sf := 4
  570. END;
  571. IF sy > sx THEN INC(sx) ELSE INC(sy) END
  572. END
  573. | Nupto:
  574. IF (n.right.class = Nconst) OR (n.left.class = Nconst) THEN sf := 2
  575. ELSE sf := 3
  576. END;
  577. INCL(ux, CX); INC(sx)
  578. | Ncall, Ncomp:
  579. sf := 10; ux := wreg + {float}
  580. | Nfield, Nconst, Nproc, Ntype:
  581. END;
  582. used := used + ux;
  583. IF sx > size THEN size := sx END;
  584. IF sy > size THEN size := sy END;
  585. IF sf > size THEN size := sf END;
  586. n := n.link
  587. END;
  588. IF size > 10 THEN size := 10 END
  589. END Check;
  590. PROCEDURE^ expr (n: DevCPT.Node; VAR x: DevCPL486.Item; hint, stop: SET);
  591. PROCEDURE DualExp (left, right: DevCPT.Node; VAR x, y: DevCPL486.Item; hx, hy, stpx, stpy: SET);
  592. VAR ux, uy: SET; sx, sy: INTEGER;
  593. BEGIN
  594. Check(left, ux, sx); Check(right, uy, sy);
  595. IF sy > sx THEN
  596. expr(right, y, hy + stpy, ux + stpy * {AX, CX});
  597. expr(left, x, hx, stpx);
  598. DevCPC486.Assert(y, hy, stpy)
  599. ELSE
  600. expr(left, x, hx + stpx, uy);
  601. expr(right, y, hy, stpy);
  602. DevCPC486.Assert(x, hx, stpx)
  603. END;
  604. END DualExp;
  605. PROCEDURE IntDOp (n: DevCPT.Node; VAR x: DevCPL486.Item; hint: SET);
  606. VAR y: DevCPL486.Item; rev: BOOLEAN;
  607. BEGIN
  608. DualExp(n.left, n.right, x, y, hint, hint, {stk}, {stk});
  609. IF (x.mode = Reg) & DevCPC486.Fits(x, hint) THEN
  610. DevCPC486.IntDOp(x, y, n.subcl, FALSE)
  611. ELSIF (y.mode = Reg) & DevCPC486.Fits(y, hint) THEN
  612. DevCPC486.IntDOp(y, x, n.subcl, TRUE); x := y
  613. ELSIF x.mode # Reg THEN
  614. DevCPC486.Load(x, hint, {con}); DevCPC486.IntDOp(x, y, n.subcl, FALSE)
  615. ELSIF y.mode # Reg THEN
  616. DevCPC486.Load(y, hint, {con}); DevCPC486.IntDOp(y, x, n.subcl, TRUE); x := y
  617. ELSE
  618. DevCPC486.IntDOp(x, y, n.subcl, FALSE)
  619. END
  620. END IntDOp;
  621. PROCEDURE FloatDOp (n: DevCPT.Node; VAR x: DevCPL486.Item);
  622. VAR y: DevCPL486.Item; ux, uy, uf: SET; sx, sy: INTEGER;
  623. BEGIN
  624. Check(n.left, ux, sx); Check(n.right, uy, sy);
  625. IF (n.subcl = min) OR (n.subcl = max) THEN uf := {AX} ELSE uf := {} END;
  626. IF (sy > sx) OR (sy = sx) & ((n.subcl = mod) OR (n.subcl = ash)) THEN
  627. expr(n.right, x, {}, ux + {mem, stk});
  628. expr(n.left, y, {}, uf);
  629. DevCPC486.FloatDOp(x, y, n.subcl, TRUE)
  630. ELSIF float IN uy THEN (* function calls in both operands *)
  631. expr(n.left, y, {}, uy + {mem});
  632. expr(n.right, x, {}, {mem, stk});
  633. DevCPC486.FloatDOp(x, y, n.subcl, TRUE)
  634. ELSE
  635. expr(n.left, x, {}, uy + {mem, stk});
  636. expr(n.right, y, {}, uf);
  637. DevCPC486.FloatDOp(x, y, n.subcl, FALSE)
  638. END
  639. END FloatDOp;
  640. PROCEDURE design (n: DevCPT.Node; VAR x: DevCPL486.Item; hint, stop: SET);
  641. VAR obj: DevCPT.Object; y: DevCPL486.Item; ux, uy: SET; sx, sy: INTEGER;
  642. BEGIN
  643. CASE n.class OF
  644. Nvar, Nvarpar:
  645. obj := n.obj; x.mode := obj.mode; x.obj := obj; x.scale := 0;
  646. IF obj.typ.comp = DynArr THEN x.mode := VarPar END;
  647. IF obj.mnolev < 0 THEN x.offset := 0; x.tmode := Con
  648. ELSIF x.mode = Var THEN x.offset := obj.adr; x.tmode := Con
  649. ELSE x.offset := 0; x.tmode := VarPar
  650. END
  651. | Nfield:
  652. design(n.left, x, hint, stop); DevCPC486.Field(x, n.obj)
  653. | Nderef:
  654. IF n.subcl # 0 THEN
  655. expr(n.left, x, hint, stop);
  656. IF n.typ.form = String8 THEN x.form := VString8 ELSE x.form := VString16 END
  657. ELSE
  658. expr(n.left, x, hint, stop + {mem} - {loaded}); DevCPC486.DeRef(x)
  659. END
  660. | Nindex:
  661. Check(n.left, ux, sx); Check(n.right, uy, sy);
  662. IF wreg - uy = {} THEN
  663. expr(n.right, y, hint + stop, ux);
  664. design(n.left, x, hint, stop);
  665. IF x.scale # 0 THEN DevCPC486.Index(x, y, {}, {}) ELSE DevCPC486.Index(x, y, hint, stop) END
  666. ELSE
  667. design(n.left, x, hint, stop + uy);
  668. IF x.scale # 0 THEN expr(n.right, y, {}, {}); DevCPC486.Index(x, y, {}, {})
  669. ELSE expr(n.right, y, hint, stop); DevCPC486.Index(x, y, hint, stop)
  670. END
  671. END
  672. | Nguard, Neguard:
  673. IF n.typ.form = Pointer THEN
  674. IF loaded IN stop THEN expr(n.left, x, hint, stop) ELSE expr(n.left, x, hint, stop + {mem}) END
  675. ELSE design(n.left, x, hint, stop)
  676. END;
  677. DevCPC486.TypTest(x, n.typ, TRUE, n.class = Neguard)
  678. | Nproc:
  679. obj := n.obj; x.mode := obj.mode; x.obj := obj;
  680. IF x.mode = TProc THEN x.offset := obj.num; (*mthno*) x.scale := n.subcl (* super *) END
  681. END;
  682. x.typ := n.typ
  683. END design;
  684. PROCEDURE IsAllocDynArr (x: DevCPT.Node): BOOLEAN;
  685. BEGIN
  686. IF (x.typ.comp = DynArr) & ~x.typ.untagged THEN
  687. WHILE x.class = Nindex DO x := x.left END;
  688. IF x.class = Nderef THEN RETURN TRUE END
  689. END;
  690. RETURN FALSE
  691. END IsAllocDynArr;
  692. PROCEDURE StringOp (left, right: DevCPT.Node; VAR x, y: DevCPL486.Item; useLen: BOOLEAN);
  693. VAR ax, ay: DevCPL486.Item; ux: SET; sx: INTEGER;
  694. BEGIN
  695. Check(left, ux, sx);
  696. expr(right, y, wreg - {SI} + ux, {});
  697. ay := y; DevCPC486.GetAdr(ay, wreg - {SI} + ux, {}); DevCPC486.Assert(ay, wreg - {SI}, ux);
  698. IF useLen & IsAllocDynArr(left) THEN (* keep len descriptor *)
  699. design(left, x, wreg - {CX}, {loaded});
  700. DevCPC486.Prepare(x, wreg - {CX} + {deref}, {DI})
  701. ELSE
  702. expr(left, x, wreg - {DI}, {})
  703. END;
  704. ax := x; DevCPC486.GetAdr(ax, {}, wreg - {DI} + {stk, con});
  705. DevCPC486.Load(ay, {}, wreg - {SI} + {con});
  706. DevCPC486.Free(ax); DevCPC486.Free(ay)
  707. END StringOp;
  708. PROCEDURE AdrExpr (n: DevCPT.Node; VAR x: DevCPL486.Item; hint, stop: SET);
  709. BEGIN
  710. IF n.class < Nconst THEN
  711. design(n, x, hint + stop, {loaded}); DevCPC486.Prepare(x, hint + {deref}, stop)
  712. ELSE expr(n, x, hint, stop)
  713. END
  714. END AdrExpr;
  715. (* ---------- interface pointer reference counting ---------- *)
  716. PROCEDURE HandleIPtrs (typ: DevCPT.Struct; VAR x, y: DevCPL486.Item; add, rel, init: BOOLEAN);
  717. PROCEDURE FindPtrs (typ: DevCPT.Struct; adr: INTEGER);
  718. VAR fld: DevCPT.Object; btyp: DevCPT.Struct; i, n: INTEGER;
  719. BEGIN
  720. IF (typ.form = Pointer) & (typ.sysflag = interface) THEN
  721. IF add THEN DevCPC486.IPAddRef(y, adr, TRUE) END;
  722. IF rel THEN DevCPC486.IPRelease(x, adr, TRUE, init) END
  723. ELSIF (typ.comp = Record) & (typ.sysflag # union) THEN
  724. btyp := typ.BaseTyp;
  725. IF btyp # NIL THEN FindPtrs(btyp, adr) END ;
  726. fld := typ.link;
  727. WHILE (fld # NIL) & (fld.mode = Fld) DO
  728. IF (fld.sysflag = interface) & (fld.name^ = DevCPM.HdUtPtrName) THEN
  729. IF add THEN DevCPC486.IPAddRef(y, fld.adr + adr, TRUE) END;
  730. IF rel THEN DevCPC486.IPRelease(x, fld.adr + adr, TRUE, init) END
  731. ELSE FindPtrs(fld.typ, fld.adr + adr)
  732. END;
  733. fld := fld.link
  734. END
  735. ELSIF typ.comp = Array THEN
  736. btyp := typ.BaseTyp; n := typ.n;
  737. WHILE btyp.comp = Array DO n := btyp.n * n; btyp := btyp.BaseTyp END ;
  738. IF DevCPC486.ContainsIPtrs(btyp) THEN
  739. i := 0;
  740. WHILE i < n DO FindPtrs(btyp, adr); INC(adr, btyp.size); INC(i) END
  741. END
  742. ELSIF typ.comp = DynArr THEN
  743. IF DevCPC486.ContainsIPtrs(typ) THEN DevCPM.err(221) END
  744. END
  745. END FindPtrs;
  746. BEGIN
  747. FindPtrs(typ, 0)
  748. END HandleIPtrs;
  749. PROCEDURE CountedPtr (n: DevCPT.Node): BOOLEAN;
  750. BEGIN
  751. RETURN (n.typ.form = Pointer) & (n.typ.sysflag = interface)
  752. & ((n.class = Ncall) OR (n.class = Ncomp) & (n.right.class = Ncall))
  753. END CountedPtr;
  754. PROCEDURE IPAssign (nx, ny: DevCPT.Node; VAR x, y: DevCPL486.Item; ux: SET);
  755. (* nx.typ.form = Pointer & nx.typ.sysflag = interface *)
  756. BEGIN
  757. expr(ny, y, {}, wreg - {SI} + {mem, stk});
  758. IF (ny.class # Nconst) & ~CountedPtr(ny) THEN
  759. DevCPC486.IPAddRef(y, 0, TRUE)
  760. END;
  761. IF nx # NIL THEN
  762. DevCPC486.Assert(y, {}, wreg - {SI} + ux);
  763. expr(nx, x, wreg - {DI}, {loaded});
  764. IF (x.mode = Ind) & (x.reg IN wreg - {SI, DI}) OR (x.scale # 0) THEN
  765. DevCPC486.GetAdr(x, {}, wreg - {DI} + {con});
  766. x.mode := Ind; x.offset := 0; x.scale := 0
  767. END;
  768. DevCPC486.IPRelease(x, 0, TRUE, FALSE);
  769. END
  770. END IPAssign;
  771. PROCEDURE IPStructAssign (typ: DevCPT.Struct);
  772. VAR x, y: DevCPL486.Item;
  773. BEGIN
  774. IF typ.comp = DynArr THEN DevCPM.err(270) END;
  775. (* addresses in SI and DI *)
  776. x.mode := Ind; x.reg := DI; x.offset := 0; x.scale := 0;
  777. y.mode := Ind; y.reg := SI; y.offset := 0; y.scale := 0;
  778. HandleIPtrs(typ, x, y, TRUE, TRUE, FALSE)
  779. END IPStructAssign;
  780. PROCEDURE IPFree (nx: DevCPT.Node; VAR x: DevCPL486.Item);
  781. BEGIN
  782. expr(nx, x, wreg - {DI}, {loaded}); DevCPC486.GetAdr(x, {}, wreg - {DI} + {con});
  783. x.mode := Ind; x.offset := 0; x.scale := 0;
  784. IF nx.typ.form = Comp THEN
  785. HandleIPtrs(nx.typ, x, x, FALSE, TRUE, TRUE)
  786. ELSE (* nx.typ.form = Pointer & nx.typ.sysflag = interface *)
  787. DevCPC486.IPRelease(x, 0, TRUE, TRUE);
  788. END
  789. END IPFree;
  790. (* unchanged val parameters allways counted because of aliasing problems REMOVED! *)
  791. PROCEDURE InitializeIPVars (proc: DevCPT.Object);
  792. VAR x: DevCPL486.Item; obj: DevCPT.Object;
  793. BEGIN
  794. x.mode := Ind; x.reg := BP; x.scale := 0; x.form := Pointer;
  795. obj := proc.link;
  796. WHILE obj # NIL DO
  797. IF (obj.mode = Var) & obj.used THEN (* changed value parameters *)
  798. x.offset := obj.adr;
  799. HandleIPtrs(obj.typ, x, x, TRUE, FALSE, FALSE)
  800. END;
  801. obj := obj.link
  802. END
  803. END InitializeIPVars;
  804. PROCEDURE ReleaseIPVars (proc: DevCPT.Object);
  805. VAR x, ax, dx, si, di: DevCPL486.Item; obj: DevCPT.Object;
  806. BEGIN
  807. obj := proc.link;
  808. WHILE (obj # NIL) & ((obj.mode # Var) OR ~obj.used OR ~DevCPC486.ContainsIPtrs(obj.typ)) DO
  809. obj := obj.link
  810. END;
  811. IF obj = NIL THEN
  812. obj := proc.scope.scope;
  813. WHILE (obj # NIL) & ~DevCPC486.ContainsIPtrs(obj.typ) DO obj := obj.link END;
  814. IF obj = NIL THEN RETURN END
  815. END;
  816. DevCPL486.MakeReg(ax, AX, Int32); DevCPL486.MakeReg(si, SI, Int32);
  817. DevCPL486.MakeReg(dx, DX, Int32); DevCPL486.MakeReg(di, DI, Int32);
  818. IF ~(proc.typ.form IN {Real32, Real64, NoTyp}) THEN DevCPL486.GenMove(ax, si) END;
  819. IF proc.typ.form = Int64 THEN DevCPL486.GenMove(dx, di) END;
  820. x.mode := Ind; x.reg := BP; x.scale := 0; x.form := Pointer;
  821. obj := proc.link;
  822. WHILE obj # NIL DO
  823. IF (obj.mode = Var) & obj.used THEN (* value parameters *)
  824. x.offset := obj.adr;
  825. HandleIPtrs(obj.typ, x, x, FALSE, TRUE, FALSE)
  826. END;
  827. obj := obj.link
  828. END;
  829. obj := proc.scope.scope;
  830. WHILE obj # NIL DO (* local variables *)
  831. IF obj.used THEN
  832. x.offset := obj.adr;
  833. HandleIPtrs(obj.typ, x, x, FALSE, TRUE, FALSE);
  834. END;
  835. obj := obj.link
  836. END;
  837. IF ~(proc.typ.form IN {Real32, Real64, NoTyp}) THEN DevCPL486.GenMove(si, ax) END;
  838. IF proc.typ.form = Int64 THEN DevCPL486.GenMove(di, dx) END
  839. END ReleaseIPVars;
  840. PROCEDURE CompareIntTypes (
  841. typ: DevCPT.Struct; VAR id: DevCPL486.Item; VAR exit: DevCPL486.Label; VAR num: INTEGER
  842. );
  843. VAR x, y: DevCPL486.Item; local: DevCPL486.Label;
  844. BEGIN
  845. local := DevCPL486.NewLbl;
  846. typ := typ.BaseTyp; num := 0;
  847. WHILE (typ # NIL) & (typ # DevCPT.undftyp) DO
  848. IF (typ.sysflag = interface) & (typ.ext # NIL) THEN
  849. IF num > 0 THEN DevCPC486.JumpT(x, local) END;
  850. DevCPC486.GuidFromString(typ.ext, y);
  851. x := id; DevCPC486.GetAdr(x, wreg - {SI}, {mem});
  852. x := y; DevCPC486.GetAdr(x, wreg - {DI}, {});
  853. x := id; DevCPC486.CmpString(x, y, eql, FALSE);
  854. INC(num)
  855. END;
  856. typ := typ.BaseTyp
  857. END;
  858. IF num > 0 THEN DevCPC486.JumpF(x, exit) END;
  859. IF num > 1 THEN DevCPL486.SetLabel(local) END
  860. END CompareIntTypes;
  861. PROCEDURE InstallQueryInterface (typ: DevCPT.Struct; proc: DevCPT.Object);
  862. VAR this, id, int, unk, c: DevCPL486.Item; nil, end: DevCPL486.Label; num: INTEGER;
  863. BEGIN
  864. nil := DevCPL486.NewLbl; end := DevCPL486.NewLbl;
  865. this.mode := Ind; this.reg := BP; this.offset := 8; this.scale := 0; this.form := Pointer; this.typ := DevCPT.anyptrtyp;
  866. id.mode := DInd; id.reg := BP; id.offset := 12; id.scale := 0; id.form := Pointer;
  867. int.mode := DInd; int.reg := BP; int.offset := 16; int.scale := 0; int.form := Pointer;
  868. DevCPC486.GetAdr(int, {}, {AX, CX, SI, DI, mem}); int.mode := Ind; int.offset := 0;
  869. DevCPL486.MakeConst(c, 0, Pointer); DevCPC486.Assign(int, c);
  870. unk.mode := Ind; unk.reg := BP; unk.offset := 8; unk.scale := 0; unk.form := Pointer; unk.typ := DevCPT.punktyp;
  871. DevCPC486.Load(unk, {}, {});
  872. unk.mode := Ind; unk.offset := 8;
  873. DevCPC486.Load(unk, {}, {});
  874. DevCPL486.GenComp(c, unk);
  875. DevCPL486.GenJump(4, nil, TRUE);
  876. DevCPL486.MakeReg(c, int.reg, Pointer);
  877. DevCPL486.GenPush(c);
  878. c.mode := Ind; c.reg := BP; c.offset := 12; c.scale := 0; c.form := Pointer;
  879. DevCPL486.GenPush(c);
  880. DevCPL486.GenPush(unk);
  881. c.mode := Ind; c.reg := unk.reg; c.offset := 0; c.scale := 0; c.form := Pointer;
  882. DevCPL486.GenMove(c, unk);
  883. unk.mode := Ind; unk.offset := 0; unk.scale := 0; unk.form := Pointer;
  884. DevCPL486.GenCall(unk);
  885. DevCPC486.Free(unk);
  886. DevCPL486.GenJump(-1, end, FALSE);
  887. DevCPL486.SetLabel(nil);
  888. DevCPL486.MakeConst(c, 80004002H, Int32); (* E_NOINTERFACE *)
  889. DevCPC486.Result(proc, c);
  890. CompareIntTypes(typ, id, end, num);
  891. IF num > 0 THEN
  892. DevCPC486.Load(this, {}, {});
  893. DevCPC486.Assign(int, this);
  894. DevCPC486.IPAddRef(this, 0, FALSE);
  895. DevCPL486.MakeConst(c, 0, Int32); (* S_OK *)
  896. DevCPC486.Result(proc, c);
  897. END;
  898. DevCPL486.SetLabel(end)
  899. END InstallQueryInterface;
  900. (* -------------------- *)
  901. PROCEDURE ActualPar (n: DevCPT.Node; fp: DevCPT.Object; rec: BOOLEAN; VAR tag: DevCPL486.Item);
  902. VAR ap: DevCPL486.Item; x: DevCPT.Node; niltest: BOOLEAN;
  903. BEGIN
  904. IF n # NIL THEN
  905. ActualPar(n.link, fp.link, FALSE, ap);
  906. niltest := FALSE;
  907. IF fp.mode = VarPar THEN
  908. IF (n.class = Ndop) & ((n.subcl = thisarrfn) OR (n.subcl = thisrecfn)) THEN
  909. expr(n.right, ap, {}, {}); DevCPC486.Push(ap); (* push type/length *)
  910. expr(n.left, ap, {}, {}); DevCPC486.Push(ap); (* push adr *)
  911. RETURN
  912. ELSIF (fp.vis = outPar) & DevCPC486.ContainsIPtrs(fp.typ) & (ap.typ # DevCPT.niltyp) THEN
  913. IPFree(n, ap)
  914. ELSE
  915. x := n;
  916. WHILE (x.class = Nfield) OR (x.class = Nindex) DO x := x.left END;
  917. niltest := x.class = Nderef; (* explicit nil test needed *)
  918. AdrExpr(n, ap, {}, {})
  919. END
  920. ELSIF (n.class = Nmop) & (n.subcl = conv) THEN
  921. IF n.typ.form IN {String8, String16} THEN expr(n, ap, {}, {}); DevCPM.err(265)
  922. ELSIF (DevCPT.Includes(n.typ.form, n.left.typ.form) OR DevCPT.Includes(n.typ.form, fp.typ.form))
  923. & (n.typ.form # Set) & (fp.typ # DevCPT.bytetyp) THEN expr(n.left, ap, {}, {high});
  924. ELSE expr(n, ap, {}, {high});
  925. END
  926. ELSE expr(n, ap, {}, {high});
  927. IF CountedPtr(n) THEN DevCPM.err(270) END
  928. END;
  929. DevCPC486.Param(fp, rec, niltest, ap, tag)
  930. END
  931. END ActualPar;
  932. PROCEDURE Call (n: DevCPT.Node; VAR x: DevCPL486.Item);
  933. VAR tag: DevCPL486.Item; proc: DevCPT.Object; m: BYTE;
  934. BEGIN
  935. IF n.left.class = Nproc THEN
  936. proc := n.left.obj; m := proc.mode;
  937. ELSE proc := NIL; m := 0
  938. END;
  939. IF (m = CProc) & (n.right # NIL) THEN
  940. ActualPar(n.right.link, n.obj.link, FALSE, tag);
  941. expr(n.right, tag, wreg - {AX}, {}); (* tag = first param *)
  942. ELSE
  943. IF proc # NIL THEN DevCPC486.PrepCall(proc) END;
  944. ActualPar(n.right, n.obj, (m = TProc) & (n.left.subcl = 0), tag);
  945. END;
  946. IF proc # NIL THEN design(n.left, x, {}, {}) ELSE expr(n.left, x, {}, {}) END;
  947. DevCPC486.Call(x, tag)
  948. END Call;
  949. PROCEDURE Mem (n: DevCPT.Node; VAR x: DevCPL486.Item; typ: DevCPT.Struct; hint, stop: SET);
  950. VAR offset: INTEGER;
  951. BEGIN
  952. IF (n.class = Ndop) & (n.subcl IN {plus, minus}) & (n.right.class = Nconst) THEN
  953. expr(n.left, x, hint, stop + {mem}); offset := n.right.conval.intval;
  954. IF n.subcl = minus THEN offset := -offset END
  955. ELSE
  956. expr(n, x, hint, stop + {mem}); offset := 0
  957. END;
  958. DevCPC486.Mem(x, offset, typ)
  959. END Mem;
  960. PROCEDURE^ CompStat (n: DevCPT.Node);
  961. PROCEDURE^ CompRelease (n: DevCPT.Node; VAR res: DevCPL486.Item);
  962. PROCEDURE condition (n: DevCPT.Node; VAR x: DevCPL486.Item; VAR false, true: DevCPL486.Label);
  963. VAR local: DevCPL486.Label; y, z: DevCPL486.Item; ux: SET; sx, num: INTEGER; f: BYTE; typ: DevCPT.Struct;
  964. BEGIN
  965. IF n.class = Nmop THEN
  966. CASE n.subcl OF
  967. not: condition(n.left, x, true, false); DevCPC486.Not(x)
  968. | is: IF n.left.typ.form = Pointer THEN expr(n.left, x, {}, {mem})
  969. ELSE design(n.left, x, {}, {})
  970. END;
  971. DevCPC486.TypTest(x, n.obj.typ, FALSE, FALSE)
  972. | odd: expr(n.left, x, {}, {}); DevCPC486.Odd(x)
  973. | cc: expr(n.left, x, {}, {}); x.mode := Cond; x.form := Bool
  974. | val: DevCPM.err(220)
  975. END
  976. ELSIF n.class = Ndop THEN
  977. CASE n.subcl OF
  978. and: local := DevCPL486.NewLbl; condition(n.left, y, false, local);
  979. DevCPC486.JumpF(y, false);
  980. IF local # DevCPL486.NewLbl THEN DevCPL486.SetLabel(local) END;
  981. condition(n.right, x, false, true)
  982. | or: local := DevCPL486.NewLbl; condition(n.left, y, local, true);
  983. DevCPC486.JumpT(y, true);
  984. IF local # DevCPL486.NewLbl THEN DevCPL486.SetLabel(local) END;
  985. condition(n.right, x, false, true)
  986. | eql..geq:
  987. f := n.left.typ.form;
  988. IF f = Int64 THEN DevCPM.err(260)
  989. ELSIF f IN {String8, String16, Comp} THEN
  990. IF (n.left.class = Nmop) & (n.left.subcl = conv) THEN (* converted must be source *)
  991. StringOp(n.right, n.left, x, y, FALSE); DevCPC486.CmpString(x, y, n.subcl, TRUE)
  992. ELSE
  993. StringOp(n.left, n.right, x, y, FALSE); DevCPC486.CmpString(x, y, n.subcl, FALSE)
  994. END
  995. ELSIF f IN {Real32, Real64} THEN FloatDOp(n, x)
  996. ELSE
  997. IF CountedPtr(n.left) OR CountedPtr(n.right) THEN DevCPM.err(270) END;
  998. DualExp(n.left, n.right, x, y, {}, {}, {stk}, {stk});
  999. IF (x.mode = Reg) OR (y.mode = Con) THEN DevCPC486.IntDOp(x, y, n.subcl, FALSE)
  1000. ELSIF (y.mode = Reg) OR (x.mode = Con) THEN DevCPC486.IntDOp(y, x, n.subcl, TRUE); x := y
  1001. ELSE DevCPC486.Load(x, {}, {}); DevCPC486.IntDOp(x, y, n.subcl, FALSE)
  1002. END
  1003. END
  1004. | in: DualExp(n.left, n.right, x, y, {}, {}, {short, mem, stk}, {con, stk});
  1005. DevCPC486.In(x, y)
  1006. | bit: Check(n.left, ux, sx);
  1007. expr(n.right, x, {}, ux + {short});
  1008. Mem(n.left, y, DevCPT.notyp, {}, {});
  1009. DevCPC486.Load(x, {}, {short});
  1010. DevCPC486.In(x, y)
  1011. | queryfn:
  1012. AdrExpr(n.right, x, {}, {CX, SI, DI});
  1013. CompareIntTypes(n.left.typ, x, false, num);
  1014. IF num > 0 THEN
  1015. Check(n.right.link, ux, sx); IPAssign(n.right.link, n.left, x, y, ux); DevCPC486.Assign(x, y);
  1016. x.offset := 1 (* true *)
  1017. ELSE x.offset := 0 (* false *)
  1018. END;
  1019. x.mode := Con; DevCPC486.MakeCond(x)
  1020. END
  1021. ELSIF n.class = Ncomp THEN
  1022. CompStat(n.left); condition(n.right, x, false, true); CompRelease(n.left, x);
  1023. IF x.mode = Stk THEN DevCPL486.GenCode(9DH); (* pop flags *) x.mode := Cond END
  1024. ELSE expr(n, x, {}, {}); DevCPC486.MakeCond(x) (* const, var, or call *)
  1025. END
  1026. END condition;
  1027. PROCEDURE expr(n: DevCPT.Node; VAR x: DevCPL486.Item; hint, stop: SET);
  1028. VAR y, z: DevCPL486.Item; f, g: BYTE; cval: DevCPT.Const; false, true: DevCPL486.Label;
  1029. uy: SET; sy: INTEGER; r: REAL;
  1030. BEGIN
  1031. f := n.typ.form;
  1032. IF (f = Bool) & (n.class IN {Ndop, Nmop}) THEN
  1033. false := DevCPL486.NewLbl; true := DevCPL486.NewLbl;
  1034. condition(n, y, false, true);
  1035. DevCPC486.LoadCond(x, y, false, true, hint, stop + {mem})
  1036. ELSE
  1037. CASE n.class OF
  1038. Nconst:
  1039. IF n.obj = NIL THEN cval := n.conval ELSE cval := n.obj.conval END;
  1040. CASE f OF
  1041. Byte..Int32, NilTyp, Pointer, Char16: DevCPL486.MakeConst(x, cval.intval, f)
  1042. | Int64:
  1043. DevCPL486.MakeConst(x, cval.intval, f);
  1044. DevCPE.GetLongWords(cval, x.scale, x.offset)
  1045. | Set: DevCPL486.MakeConst(x, SYSTEM.VAL(INTEGER, cval.setval), Set)
  1046. | String8, String16, Real32, Real64: DevCPL486.AllocConst(x, cval, f)
  1047. | Comp:
  1048. ASSERT(n.typ = DevCPT.guidtyp);
  1049. IF n.conval # NIL THEN DevCPC486.GuidFromString(n.conval.ext, x)
  1050. ELSE DevCPC486.GuidFromString(n.obj.typ.ext, x)
  1051. END
  1052. END
  1053. | Nupto: (* n.typ = DevCPT.settyp *)
  1054. Check(n.right, uy, sy);
  1055. expr(n.left, x, {}, wreg - {CX} + {high, mem, stk});
  1056. DevCPC486.MakeSet(x, TRUE, FALSE, hint + stop + uy, {});
  1057. DevCPC486.Assert(x, {}, uy);
  1058. expr(n.right, y, {}, wreg - {CX} + {high, mem, stk});
  1059. DevCPC486.MakeSet(y, TRUE, TRUE, hint + stop, {});
  1060. DevCPC486.Load(x, hint + stop, {});
  1061. IF x.mode = Con THEN DevCPC486.IntDOp(y, x, msk, TRUE); x := y
  1062. ELSE DevCPC486.IntDOp(x, y, msk, FALSE)
  1063. END
  1064. | Nmop:
  1065. CASE n.subcl OF
  1066. | bit:
  1067. expr(n.left, x, {}, wreg - {CX} + {high, mem, stk});
  1068. DevCPC486.MakeSet(x, FALSE, FALSE, hint + stop, {})
  1069. | conv:
  1070. IF f IN {String8, String16} THEN
  1071. expr(n.left, x, hint, stop);
  1072. IF f = String8 THEN x.form := VString16to8 END (* SHORT *)
  1073. ELSE
  1074. IF n.left.class = Nconst THEN (* largeint -> longreal *)
  1075. ASSERT((n.left.typ.form = Int64) & (f = Real64));
  1076. DevCPL486.AllocConst(x, n.left.conval, n.left.typ.form);
  1077. ELSE
  1078. expr(n.left, x, hint + stop, {high});
  1079. END;
  1080. DevCPC486.Convert(x, f, -1, hint + stop, {}) (* ??? *)
  1081. END
  1082. | val:
  1083. expr(n.left, x, hint + stop, {high, con}); DevCPC486.Convert(x, f, n.typ.size, hint, stop) (* ??? *)
  1084. | adr:
  1085. IF n.left.class = Ntype THEN
  1086. x.mode := Con; x.offset := 0; x.obj := n.left.obj; x.form := Int32; x.typ := n.left.typ;
  1087. ELSE
  1088. AdrExpr(n.left, x, hint + stop, {});
  1089. END;
  1090. DevCPC486.GetAdr(x, hint + stop, {})
  1091. | typfn:
  1092. IF n.left.class = Ntype THEN
  1093. x.mode := Con; x.offset := 0; x.obj := n.left.obj; x.form := Int32; x.typ := n.left.typ;
  1094. IF x.obj.typ.untagged THEN DevCPM.err(111) END
  1095. ELSE
  1096. expr(n.left, x, hint + stop, {});
  1097. DevCPC486.Tag(x, y); DevCPC486.Free(x); x := y
  1098. END;
  1099. DevCPC486.Load(x, hint + stop, {})
  1100. | minus, abs, cap:
  1101. expr(n.left, x, hint + stop, {mem, stk});
  1102. IF f = Int64 THEN DevCPM.err(260)
  1103. ELSIF f IN realSet THEN DevCPC486.FloatMOp(x, n.subcl)
  1104. ELSE DevCPC486.IntMOp(x, n.subcl)
  1105. END
  1106. END
  1107. | Ndop:
  1108. IF (f IN realSet) & (n.subcl # lsh) & (n.subcl # rot) THEN
  1109. IF (n.subcl = ash) & (n.right.class = Nconst) & (n.right.conval.realval >= 0) THEN
  1110. expr(n.left, x, {}, {mem, stk});
  1111. cval := n.right.conval; sy := SHORT(ENTIER(cval.realval)); cval.realval := 1;
  1112. WHILE sy > 0 DO cval.realval := cval.realval * 2; DEC(sy) END;
  1113. DevCPL486.AllocConst(y, cval, Real32);
  1114. DevCPC486.FloatDOp(x, y, times, FALSE)
  1115. ELSE FloatDOp(n, x)
  1116. END
  1117. ELSIF (f = Int64) OR (n.typ = DevCPT.intrealtyp) THEN DevCPM.err(260); expr(n.left, x, {}, {})
  1118. ELSE
  1119. CASE n.subcl OF
  1120. times:
  1121. IF f = Int8 THEN
  1122. DualExp(n.left, n.right, x, y, {}, {}, wreg - {AX} + {high, mem, stk, con}, {AX, con, stk});
  1123. DevCPC486.IntDOp(x, y, times, FALSE)
  1124. ELSE IntDOp(n, x, hint + stop)
  1125. END
  1126. | div, mod:
  1127. DualExp(n.left, n.right, x, y, {}, {}, wreg - {AX} + {high, mem, stk, con}, {AX, DX, mem, stk});
  1128. DevCPC486.DivMod(x, y, n.subcl = mod)
  1129. | plus:
  1130. IF n.typ.form IN {String8, String16} THEN DevCPM.err(265); expr(n.left, x, {}, {})
  1131. ELSE IntDOp(n, x, hint + stop)
  1132. END
  1133. | slash, minus, msk, min, max:
  1134. IntDOp(n, x, hint + stop)
  1135. | ash, lsh, rot:
  1136. uy := {}; IF n.right.class # Nconst THEN uy := {CX} END;
  1137. DualExp(n^.right, n^.left, y, x, {}, hint + stop, wreg - {CX} + {high, mem, stk}, uy + {con, mem, stk});
  1138. DevCPC486.Shift(x, y, n^.subcl)
  1139. | len:
  1140. IF n.left.typ.form IN {String8, String16} THEN
  1141. expr(n.left, x, wreg - {DI} , {}); DevCPC486.GetAdr(x, {}, wreg - {DI} + {con});
  1142. DevCPC486.StrLen(x, n.left.typ, FALSE)
  1143. ELSE
  1144. design(n.left, x, hint + stop, {}); expr(n.right, y, {}, {}); DevCPC486.Len(x, y)
  1145. END
  1146. END
  1147. END
  1148. | Ncall:
  1149. Call(n, x)
  1150. | Ncomp:
  1151. CompStat(n.left); expr(n.right, x, hint, stop); CompRelease(n.left, x);
  1152. IF x.mode = Stk THEN DevCPC486.Pop(x, x.form, hint, stop) END
  1153. ELSE
  1154. design(n, x, hint + stop, stop * {loaded}); DevCPC486.Prepare(x, hint + stop, {}) (* ??? *)
  1155. END
  1156. END;
  1157. x.typ := n.typ;
  1158. DevCPC486.Assert(x, hint, stop)
  1159. END expr;
  1160. PROCEDURE AddCopy (n: DevCPT.Node; VAR dest, dadr, len: DevCPL486.Item; last: BOOLEAN);
  1161. VAR adr, src: DevCPL486.Item; u: SET; s: INTEGER;
  1162. BEGIN
  1163. Check(n, u, s);
  1164. DevCPC486.Assert(dadr, wreg - {DI}, u + {SI, CX});
  1165. IF len.mode # Con THEN DevCPC486.Assert(len, wreg - {CX}, u + {SI, DI}) END;
  1166. expr(n, src, wreg - {SI}, {});
  1167. adr := src; DevCPC486.GetAdr(adr, {}, wreg - {SI} + {con});
  1168. IF len.mode # Con THEN DevCPC486.Load(len, {}, wreg - {CX} + {con}) END;
  1169. DevCPC486.Load(dadr, {}, wreg - {DI} + {con});
  1170. DevCPC486.AddCopy(dest, src, last)
  1171. END AddCopy;
  1172. PROCEDURE StringCopy (left, right: DevCPT.Node);
  1173. VAR x, y, ax, ay, len: DevCPL486.Item;
  1174. BEGIN
  1175. IF IsAllocDynArr(left) THEN expr(left, x, wreg - {CX}, {DI}) (* keep len descriptor *)
  1176. ELSE expr(left, x, wreg - {DI}, {})
  1177. END;
  1178. ax := x; DevCPC486.GetAdr(ax, {}, wreg - {DI});
  1179. DevCPC486.Free(x); DevCPC486.ArrayLen(x, len, wreg - {CX}, {});
  1180. WHILE right.class = Ndop DO
  1181. ASSERT(right.subcl = plus);
  1182. AddCopy(right.left, x, ax, len, FALSE);
  1183. right := right.right
  1184. END;
  1185. AddCopy(right, x, ax, len, TRUE);
  1186. DevCPC486.Free(len)
  1187. END StringCopy;
  1188. PROCEDURE Checkpc;
  1189. BEGIN
  1190. DevCPE.OutSourceRef(DevCPM.errpos)
  1191. END Checkpc;
  1192. PROCEDURE^ stat (n: DevCPT.Node; VAR end: DevCPL486.Label);
  1193. PROCEDURE CondStat (if, last: DevCPT.Node; VAR hint: INTEGER; VAR else, end: DevCPL486.Label);
  1194. VAR local: DevCPL486.Label; x: DevCPL486.Item; cond, lcond: DevCPT.Node;
  1195. BEGIN
  1196. local := DevCPL486.NewLbl;
  1197. DevCPM.errpos := if.conval.intval; Checkpc; cond := if.left;
  1198. IF (last # NIL) & (cond.class = Ndop) & (cond.subcl >= eql) & (cond.subcl <= geq)
  1199. & (last.class = Ndop) & (last.subcl >= eql) & (last.subcl <= geq)
  1200. & SameExp(cond.left, last.left) & SameExp(cond.right, last.right) THEN (* reuse comparison *)
  1201. DevCPC486.setCC(x, cond.subcl, ODD(hint), hint >= 2)
  1202. ELSIF (last # NIL) & (cond.class = Nmop) & (cond.subcl = is) & (last.class = Nmop) & (last.subcl = is)
  1203. & SameExp(cond.left, last.left) THEN
  1204. DevCPC486.ShortTypTest(x, cond.obj.typ) (* !!! *)
  1205. ELSE condition(cond, x, else, local)
  1206. END;
  1207. hint := x.reg;
  1208. DevCPC486.JumpF(x, else);
  1209. IF local # DevCPL486.NewLbl THEN DevCPL486.SetLabel(local) END;
  1210. stat(if.right, end);
  1211. END CondStat;
  1212. PROCEDURE IfStat (n: DevCPT.Node; withtrap: BOOLEAN; VAR end: DevCPL486.Label);
  1213. VAR else, local: DevCPL486.Label; if, last: DevCPT.Node; hint: INTEGER;
  1214. BEGIN (* n.class = Nifelse *)
  1215. if := n.left; last := NIL;
  1216. WHILE (if # NIL) & ((if.link # NIL) OR (n.right # NIL) OR withtrap) DO
  1217. else := DevCPL486.NewLbl;
  1218. CondStat(if, last, hint, else, end);
  1219. IF sequential THEN DevCPC486.Jump(end) END;
  1220. DevCPL486.SetLabel(else); last := if.left; if := if.link
  1221. END;
  1222. IF n.right # NIL THEN stat(n.right, end)
  1223. ELSIF withtrap THEN DevCPM.errpos := n.conval.intval; Checkpc; DevCPC486.Trap(withTrap); sequential := FALSE
  1224. ELSE CondStat(if, last, hint, end, end)
  1225. END
  1226. END IfStat;
  1227. PROCEDURE CasePart (n: DevCPT.Node; VAR x: DevCPL486.Item; VAR else: DevCPL486.Label; last: BOOLEAN);
  1228. VAR this, higher: DevCPL486.Label; m: DevCPT.Node; low, high: INTEGER;
  1229. BEGIN
  1230. IF n # NIL THEN
  1231. this := SHORT(ENTIER(n.conval.realval));
  1232. IF useTree IN n.conval.setval THEN
  1233. IF n.left # NIL THEN
  1234. IF n.right # NIL THEN
  1235. higher := DevCPL486.NewLbl;
  1236. DevCPC486.CaseJump(x, n.conval.intval, n.conval.intval2, this, higher, TRUE, FALSE);
  1237. CasePart(n.left, x, else, FALSE);
  1238. DevCPL486.SetLabel(higher);
  1239. CasePart(n.right, x, else, last)
  1240. ELSE
  1241. DevCPC486.CaseJump(x, n.conval.intval, n.conval.intval2, this, else, FALSE, FALSE);
  1242. CasePart(n.left, x, else, last);
  1243. END
  1244. ELSE
  1245. DevCPC486.CaseJump(x, n.conval.intval, n.conval.intval2, this, else, FALSE, TRUE);
  1246. IF n.right # NIL THEN CasePart(n.right, x, else, last)
  1247. ELSIF ~last THEN DevCPC486.Jump(else)
  1248. END
  1249. END
  1250. ELSE
  1251. IF useTable IN n.conval.setval THEN
  1252. m := n; WHILE m.left # NIL DO m := m.left END; low := m.conval.intval;
  1253. m := n; WHILE m.right # NIL DO m := m.right END; high := m.conval.intval2;
  1254. DevCPC486.CaseTableJump(x, low, high, else);
  1255. actual := low; last := TRUE
  1256. END;
  1257. CasePart(n.left, x, else, FALSE);
  1258. WHILE actual < n.conval.intval DO
  1259. DevCPL486.GenCaseEntry(else, FALSE); INC(actual)
  1260. END;
  1261. WHILE actual < n.conval.intval2 DO
  1262. DevCPL486.GenCaseEntry(this, FALSE); INC(actual)
  1263. END;
  1264. DevCPL486.GenCaseEntry(this, last & (n.right = NIL)); INC(actual);
  1265. CasePart(n.right, x, else, last)
  1266. END;
  1267. n.conval.realval := this
  1268. END
  1269. END CasePart;
  1270. PROCEDURE CaseStat (n: DevCPT.Node; VAR end: DevCPL486.Label);
  1271. VAR x: DevCPL486.Item; case, lab: DevCPT.Node; low, high, tab: INTEGER; else, this: DevCPL486.Label;
  1272. BEGIN
  1273. expr(n.left, x, {}, {mem, con, short, float, stk}); else := DevCPL486.NewLbl;
  1274. IF (n.right.right # NIL) & (n.right.right.class = Ngoto) THEN (* jump to goto optimization *)
  1275. CasePart(n.right.link, x, else, FALSE); DevCPC486.Free(x);
  1276. n.right.right.right.conval.intval2 := else; sequential := FALSE
  1277. ELSE
  1278. CasePart(n.right.link, x, else, TRUE); DevCPC486.Free(x);
  1279. DevCPL486.SetLabel(else);
  1280. IF n.right.conval.setval # {} THEN stat(n.right.right, end)
  1281. ELSE DevCPC486.Trap(caseTrap); sequential := FALSE
  1282. END
  1283. END;
  1284. case := n.right.left;
  1285. WHILE case # NIL DO (* case.class = Ncasedo *)
  1286. IF sequential THEN DevCPC486.Jump(end) END;
  1287. lab := case.left;
  1288. IF (case.right # NIL) & (case.right.class = Ngoto) THEN (* jump to goto optimization *)
  1289. case.right.right.conval.intval2 := SHORT(ENTIER(lab.conval.realval));
  1290. ASSERT(lab.link = NIL); sequential := FALSE
  1291. ELSE
  1292. WHILE lab # NIL DO
  1293. this := SHORT(ENTIER(lab.conval.realval)); DevCPL486.SetLabel(this); lab := lab.link
  1294. END;
  1295. stat(case.right, end)
  1296. END;
  1297. case := case.link
  1298. END
  1299. END CaseStat;
  1300. PROCEDURE Dim(n: DevCPT.Node; VAR x, nofel: DevCPL486.Item; VAR fact: INTEGER; dimtyp: DevCPT.Struct);
  1301. VAR len: DevCPL486.Item; u: SET; s: INTEGER;
  1302. BEGIN
  1303. Check(n, u, s);
  1304. IF (nofel.mode = Reg) & (nofel.reg IN u) THEN DevCPC486.Push(nofel) END;
  1305. expr(n, len, {}, {mem, short});
  1306. IF nofel.mode = Stk THEN DevCPC486.Pop(nofel, Int32, {}, {}) END;
  1307. IF len.mode = Stk THEN DevCPC486.Pop(len, Int32, {}, {}) END;
  1308. DevCPC486.MulDim(len, nofel, fact, dimtyp);
  1309. IF n.link # NIL THEN
  1310. Dim(n.link, x, nofel, fact, dimtyp.BaseTyp);
  1311. ELSE
  1312. DevCPC486.New(x, nofel, fact)
  1313. END;
  1314. DevCPC486.SetDim(x, len, dimtyp)
  1315. END Dim;
  1316. PROCEDURE CompStat (n: DevCPT.Node);
  1317. VAR x, y, sp, old, len, nofel: DevCPL486.Item; fact: INTEGER; typ: DevCPT.Struct;
  1318. BEGIN
  1319. Checkpc;
  1320. WHILE (n # NIL) & DevCPM.noerr DO
  1321. ASSERT(n.class = Nassign);
  1322. IF n.subcl = assign THEN
  1323. IF n.right.typ.form IN {String8, String16} THEN
  1324. StringCopy(n.left, n.right)
  1325. ELSE
  1326. IF (n.left.typ.sysflag = interface) & ~CountedPtr(n.right) THEN
  1327. IPAssign(NIL, n.right, x, y, {}); (* no Release *)
  1328. ELSE expr(n.right, y, {}, {})
  1329. END;
  1330. expr(n.left, x, {}, {});
  1331. DevCPC486.Assign(x, y)
  1332. END
  1333. ELSE ASSERT(n.subcl = newfn);
  1334. typ := n.left.typ.BaseTyp;
  1335. ASSERT(typ.comp = DynArr);
  1336. ASSERT(n.right.link = NIL);
  1337. expr(n.right, y, {}, wreg - {CX} + {mem, stk});
  1338. DevCPL486.MakeReg(sp, SP, Int32);
  1339. DevCPC486.CopyReg(sp, old, {}, {CX});
  1340. DevCPC486.CopyReg(y, len, {}, {CX});
  1341. IF typ.BaseTyp.form = Char16 THEN
  1342. DevCPL486.MakeConst(x, 2, Int32); DevCPL486.GenMul(x, y, FALSE)
  1343. END;
  1344. DevCPC486.StackAlloc;
  1345. DevCPC486.Free(y);
  1346. expr(n.left, x, {}, {}); DevCPC486.Assign(x, sp);
  1347. DevCPC486.Push(len);
  1348. DevCPC486.Push(old);
  1349. typ.sysflag := stackArray
  1350. END;
  1351. n := n.link
  1352. END
  1353. END CompStat;
  1354. PROCEDURE CompRelease (n: DevCPT.Node; VAR res: DevCPL486.Item);
  1355. VAR x, y, sp: DevCPL486.Item;
  1356. BEGIN
  1357. IF n.link # NIL THEN CompRelease(n.link, res) END;
  1358. ASSERT(n.class = Nassign);
  1359. IF n.subcl = assign THEN
  1360. IF (n.left.typ.form = Pointer) & (n.left.typ.sysflag = interface) THEN
  1361. IF res.mode = Cond THEN
  1362. DevCPL486.GenCode(9CH); (* push flags *)
  1363. res.mode := Stk
  1364. ELSIF res.mode = Reg THEN
  1365. IF res.form < Int16 THEN DevCPC486.Push(res)
  1366. ELSE DevCPC486.Assert(res, {}, {AX, CX, DX})
  1367. END
  1368. END;
  1369. expr(n.left, x, wreg - {DI}, {loaded});
  1370. DevCPC486.IPRelease(x, 0, TRUE, TRUE);
  1371. n.left.obj.used := FALSE
  1372. END
  1373. ELSE ASSERT(n.subcl = newfn);
  1374. DevCPL486.MakeReg(sp, SP, Int32); DevCPL486.GenPop(sp);
  1375. DevCPL486.MakeConst(y, 0, Pointer);
  1376. expr(n.left, x, {}, {}); DevCPC486.Assign(x, y)
  1377. END
  1378. END CompRelease;
  1379. PROCEDURE Assign(n: DevCPT.Node; ux: SET);
  1380. VAR r: DevCPT.Node; f: BYTE; false, true: DevCPL486.Label; x, y, z: DevCPL486.Item; uf, uy: SET; s: INTEGER;
  1381. BEGIN
  1382. r := n.right; f := r.typ.form; uf := {};
  1383. IF (r.class IN {Nmop, Ndop}) THEN
  1384. IF (r.subcl = conv) & (f # Set) &
  1385. (*
  1386. (DevCPT.Includes(f, r.left.typ.form) OR DevCPT.Includes(f, n.left.typ.form)) THEN r := r.left;
  1387. IF ~(f IN realSet) & (r.typ.form IN realSet) & (r.typ # DevCPT.intrealtyp) THEN uf := {AX} END (* entier *)
  1388. *)
  1389. (DevCPT.Includes(f, r.left.typ.form) OR DevCPT.Includes(f, n.left.typ.form)) &
  1390. ((f IN realSet) OR ~(r.left.typ.form IN realSet)) THEN r := r.left
  1391. ELSIF (f IN {Char8..Int32, Set, Char16, String8, String16}) & SameExp(n.left, r.left) THEN
  1392. IF r.class = Ndop THEN
  1393. IF (r.subcl IN {slash, plus, minus, msk}) OR (r.subcl = times) & (f = Set) THEN
  1394. expr(r.right, y, {}, ux); expr(n.left, x, {}, {});
  1395. DevCPC486.Load(y, {}, {}); DevCPC486.IntDOp(x, y, r.subcl, FALSE);
  1396. RETURN
  1397. ELSIF r.subcl IN {ash, lsh, rot} THEN
  1398. expr(r.right, y, wreg - {CX} + {high, mem}, ux); expr(n.left, x, {}, {});
  1399. DevCPC486.Load(y, {}, wreg - {CX} + {high}); DevCPC486.Shift(x, y, r.subcl);
  1400. RETURN
  1401. END
  1402. ELSE
  1403. IF r.subcl IN {minus, abs, cap} THEN
  1404. expr(n.left, x, {}, {}); DevCPC486.IntMOp(x, r.subcl); RETURN
  1405. END
  1406. END
  1407. ELSIF f = Bool THEN
  1408. IF (r.subcl = not) & SameExp(n.left, r.left) THEN
  1409. expr(n.left, x, {}, {}); DevCPC486.IntMOp(x, not); RETURN
  1410. END
  1411. END
  1412. END;
  1413. IF (n.left.typ.sysflag = interface) & (n.left.typ.form = Pointer) THEN IPAssign(n.left, r, x, y, ux)
  1414. ELSE expr(r, y, {high}, ux); expr(n.left, x, {}, uf + {loaded}); (* high ??? *)
  1415. END;
  1416. DevCPC486.Assign(x, y)
  1417. END Assign;
  1418. PROCEDURE stat (n: DevCPT.Node; VAR end: DevCPL486.Label);
  1419. VAR x, y, nofel: DevCPL486.Item; local, next, loop, prevExit: DevCPL486.Label; fact, sx, sz: INTEGER; ux, uz: SET;
  1420. BEGIN
  1421. sequential := TRUE; INC(nesting);
  1422. WHILE (n # NIL) & DevCPM.noerr DO
  1423. IF n.link = NIL THEN next := end ELSE next := DevCPL486.NewLbl END;
  1424. DevCPM.errpos := n.conval.intval; DevCPL486.BegStat;
  1425. CASE n.class OF
  1426. | Ninittd:
  1427. (* done at load-time *)
  1428. | Nassign:
  1429. Checkpc;
  1430. Check(n.left, ux, sx);
  1431. CASE n.subcl OF
  1432. assign:
  1433. IF n.left.typ.form = Comp THEN
  1434. IF (n.right.class = Ndop) & (n.right.typ.form IN {String8, String16}) THEN
  1435. StringCopy(n.left, n.right)
  1436. ELSE
  1437. StringOp(n.left, n.right, x, y, TRUE);
  1438. IF DevCPC486.ContainsIPtrs(n.left.typ) THEN IPStructAssign(n.left.typ) END;
  1439. DevCPC486.Copy(x, y, FALSE)
  1440. END
  1441. ELSE Assign(n, ux)
  1442. END
  1443. | getfn:
  1444. Mem(n.right, y, n.left.typ, {}, ux);
  1445. expr(n.left, x, {}, {loaded});
  1446. DevCPC486.Assign(x, y)
  1447. | putfn:
  1448. expr(n.right, y, {}, ux);
  1449. Mem(n.left, x, n.right.typ, {}, {});
  1450. DevCPC486.Assign(x, y)
  1451. | incfn, decfn:
  1452. expr(n.right, y, {}, ux); expr(n.left, x, {}, {});
  1453. IF n.left.typ.form = Int64 THEN
  1454. DevCPC486.LargeInc(x, y, n.subcl = decfn)
  1455. ELSE
  1456. DevCPC486.Load(y, {}, {}); DevCPC486.IntDOp(x, y, SHORT(SHORT(plus - incfn + n.subcl)), FALSE)
  1457. END
  1458. | inclfn:
  1459. expr(n.right, y, {}, wreg - {CX} + {high, mem, stk}); DevCPC486.MakeSet(y, FALSE, FALSE, ux, {});
  1460. DevCPC486.Assert(y, {}, ux); expr(n.left, x, {}, {});
  1461. DevCPC486.Load(y, {}, {}); DevCPC486.IntDOp(x, y, plus, FALSE)
  1462. | exclfn:
  1463. expr(n.right, y, {}, wreg - {CX} + {high, mem, stk}); DevCPC486.MakeSet(y, FALSE, TRUE, ux, {});
  1464. DevCPC486.Assert(y, {}, ux); expr(n.left, x, {}, {});
  1465. DevCPC486.Load(y, {}, {}); DevCPC486.IntDOp(x, y, times, FALSE)
  1466. | getrfn:
  1467. expr(n.right, y, {}, {});
  1468. IF y.offset < 8 THEN
  1469. DevCPL486.MakeReg(y, y.offset, n.left.typ.form); (* ??? *)
  1470. expr(n.left, x, {}, {loaded}); DevCPC486.Assign(x, y)
  1471. ELSE DevCPM.err(220)
  1472. END
  1473. | putrfn:
  1474. expr(n.left, x, {}, {});
  1475. IF x.offset < 8 THEN
  1476. DevCPL486.MakeReg(x, x.offset, n.right.typ.form); (* ??? *)
  1477. expr(n.right, y, wreg - {x.reg}, {}); DevCPC486.Assign(x, y)
  1478. ELSE DevCPM.err(220)
  1479. END
  1480. | newfn:
  1481. y.typ := n.left.typ;
  1482. IF n.right # NIL THEN
  1483. IF y.typ.BaseTyp.comp = Record THEN
  1484. expr(n.right, nofel, {}, {AX, CX, DX, mem, stk});
  1485. DevCPC486.New(y, nofel, 1);
  1486. ELSE (*open array*)
  1487. nofel.mode := Con; nofel.form := Int32; fact := 1;
  1488. Dim(n.right, y, nofel, fact, y.typ.BaseTyp)
  1489. END
  1490. ELSE
  1491. DevCPL486.MakeConst(nofel, 0, Int32);
  1492. DevCPC486.New(y, nofel, 1);
  1493. END;
  1494. DevCPC486.Assert(y, {}, ux); expr(n.left, x, {}, {loaded}); DevCPC486.Assign(x, y)
  1495. | sysnewfn:
  1496. expr(n.right, y, {}, {mem, short}); DevCPC486.SysNew(y);
  1497. DevCPC486.Assert(y, {}, ux); expr(n.left, x, {}, {}); DevCPC486.Assign(x, y)
  1498. | copyfn:
  1499. StringOp(n.left, n.right, x, y, TRUE);
  1500. DevCPC486.Copy(x, y, TRUE)
  1501. | movefn:
  1502. Check(n.right.link, uz, sz);
  1503. expr(n.right, y, {}, wreg - {SI} + {short} + ux + uz);
  1504. expr(n.left, x, {}, wreg - {DI} + {short} + uz);
  1505. expr(n.right.link, nofel, {}, wreg - {CX} + {mem, stk, short});
  1506. DevCPC486.Load(x, {}, wreg - {DI} + {con});
  1507. DevCPC486.Load(y, {}, wreg - {SI} + {con});
  1508. DevCPC486.SysMove(nofel)
  1509. END;
  1510. sequential := TRUE
  1511. | Ncall:
  1512. Checkpc;
  1513. Call(n, x); sequential := TRUE
  1514. | Nifelse:
  1515. IF (n.subcl # assertfn) OR assert THEN IfStat(n, FALSE, next) END
  1516. | Ncase:
  1517. Checkpc;
  1518. CaseStat(n, next)
  1519. | Nwhile:
  1520. local := DevCPL486.NewLbl;
  1521. IF n.right # NIL THEN DevCPC486.Jump(local) END;
  1522. loop := DevCPL486.NewLbl; DevCPL486.SetLabel(loop);
  1523. stat(n.right, local); DevCPL486.SetLabel(local);
  1524. DevCPM.errpos := n.conval.intval; Checkpc;
  1525. condition(n.left, x, next, loop); DevCPC486.JumpT(x, loop); sequential := TRUE
  1526. | Nrepeat:
  1527. loop := DevCPL486.NewLbl; DevCPL486.SetLabel(loop);
  1528. local := DevCPL486.NewLbl; stat(n.left, local); DevCPL486.SetLabel(local);
  1529. DevCPM.errpos := n.conval.intval; Checkpc;
  1530. condition(n.right, x, loop, next); DevCPC486.JumpF(x, loop); sequential := TRUE
  1531. | Nloop:
  1532. prevExit := Exit; Exit := next;
  1533. loop := DevCPL486.NewLbl; DevCPL486.SetLabel(loop); stat(n.left, loop);
  1534. IF sequential THEN DevCPC486.Jump(loop) END;
  1535. next := Exit; Exit := prevExit; sequential := FALSE
  1536. | Nexit:
  1537. Checkpc;
  1538. DevCPC486.Jump(Exit); sequential := FALSE
  1539. | Nreturn:
  1540. IF n.left # NIL THEN
  1541. Checkpc;
  1542. IF (n.obj.typ.sysflag = interface) & (n.obj.typ.form = Pointer)
  1543. & (n.left.class # Nconst) & ~CountedPtr(n.left) THEN IPAssign(NIL, n.left, y, x, {})
  1544. ELSE expr(n.left, x, wreg - {AX}, {})
  1545. END;
  1546. DevCPC486.Result(n.obj, x)
  1547. END;
  1548. IF (nesting > 1) OR (n.link # NIL) THEN DevCPC486.Jump(Return) END;
  1549. sequential := FALSE
  1550. | Nwith:
  1551. IfStat(n, n.subcl = 0, next)
  1552. | Ntrap:
  1553. Checkpc;
  1554. DevCPC486.Trap(n.right.conval.intval); sequential := TRUE
  1555. | Ncomp:
  1556. CompStat(n.left); stat(n.right, next); x.mode := 0; CompRelease(n.left, x)
  1557. | Ndrop:
  1558. Checkpc;
  1559. expr(n.left, x, {}, {}); DevCPC486.Free(x)
  1560. | Ngoto:
  1561. IF n.left # NIL THEN
  1562. Checkpc;
  1563. condition(n.left, x, next, n.right.conval.intval2);
  1564. DevCPC486.JumpT(x, n.right.conval.intval2)
  1565. ELSE
  1566. DevCPC486.Jump(n.right.conval.intval2);
  1567. sequential := FALSE
  1568. END
  1569. | Njsr:
  1570. DevCPL486.GenJump(-3, n.right.conval.intval2, FALSE) (* call n.right *)
  1571. | Nret:
  1572. DevCPL486.GenReturn(0); sequential := FALSE (* ret 0 *)
  1573. | Nlabel:
  1574. DevCPL486.SetLabel(n.conval.intval2)
  1575. END;
  1576. DevCPC486.CheckReg; DevCPL486.EndStat; n := n.link;
  1577. IF n = NIL THEN end := next
  1578. ELSIF next # DevCPL486.NewLbl THEN DevCPL486.SetLabel(next)
  1579. END
  1580. END;
  1581. DEC(nesting)
  1582. END stat;
  1583. PROCEDURE CheckFpu (n: DevCPT.Node; VAR useFpu: BOOLEAN);
  1584. BEGIN
  1585. WHILE n # NIL DO
  1586. IF n.typ.form IN {Real32, Real64} THEN useFpu := TRUE END;
  1587. CASE n.class OF
  1588. | Ncase:
  1589. CheckFpu(n.left, useFpu); CheckFpu(n.right.left, useFpu); CheckFpu(n.right.right, useFpu)
  1590. | Ncasedo:
  1591. CheckFpu(n.right, useFpu)
  1592. | Ngoto, Ndrop, Nloop, Nreturn, Nmop, Nfield, Nderef, Nguard:
  1593. CheckFpu(n.left, useFpu)
  1594. | Nassign, Ncall, Nifelse, Nif, Nwhile, Nrepeat, Nwith, Ncomp, Ndop, Nupto, Nindex:
  1595. CheckFpu(n.left, useFpu); CheckFpu(n.right, useFpu)
  1596. | Njsr, Nret, Nlabel, Ntrap, Nexit, Ninittd, Ntype, Nproc, Nconst, Nvar, Nvarpar:
  1597. END;
  1598. n := n.link
  1599. END
  1600. END CheckFpu;
  1601. PROCEDURE procs(n: DevCPT.Node);
  1602. VAR proc, obj: DevCPT.Object; i, j: INTEGER; end: DevCPL486.Label;
  1603. ch: SHORTCHAR; name: DevCPT.Name; useFpu: BOOLEAN;
  1604. BEGIN
  1605. INC(DevCPL486.level); nesting := 0;
  1606. WHILE (n # NIL) & DevCPM.noerr DO
  1607. DevCPC486.imLevel[DevCPL486.level] := DevCPC486.imLevel[DevCPL486.level - 1]; proc := n.obj;
  1608. IF imVar IN proc.conval.setval THEN INC(DevCPC486.imLevel[DevCPL486.level]) END;
  1609. procs(n.left);
  1610. DevCPM.errpos := n.conval.intval;
  1611. useFpu := FALSE; CheckFpu(n.right, useFpu);
  1612. DevCPC486.Enter(proc, n.right = NIL, useFpu);
  1613. InitializeIPVars(proc);
  1614. end := DevCPL486.NewLbl; Return := DevCPL486.NewLbl; stat(n.right, end);
  1615. DevCPM.errpos := n.conval.intval2; Checkpc;
  1616. IF sequential OR (end # DevCPL486.NewLbl) THEN
  1617. DevCPL486.SetLabel(end);
  1618. IF (proc.typ # DevCPT.notyp) & (proc.sysflag # noframe) THEN DevCPC486.Trap(funcTrap) END
  1619. END;
  1620. DevCPL486.SetLabel(Return);
  1621. ReleaseIPVars(proc);
  1622. DevCPC486.Exit(proc, n.right = NIL);
  1623. IF proc.mode = TProc THEN
  1624. name := proc.link.typ.strobj.name^$; i := 0;
  1625. WHILE name[i] # 0X DO INC(i) END;
  1626. name[i] := "."; INC(i); j := 0; ch := proc.name[0];
  1627. WHILE (ch # 0X) & (i < LEN(name)-1) DO name[i] := ch; INC(i); INC(j); ch := proc.name[j] END ;
  1628. name[i] := 0X;
  1629. ELSE name := proc.name^$
  1630. END;
  1631. DevCPE.OutRefName(name); DevCPE.OutRefs(proc.scope.right);
  1632. n := n.link
  1633. END;
  1634. DEC(DevCPL486.level)
  1635. END procs;
  1636. PROCEDURE Module*(prog: DevCPT.Node);
  1637. VAR end: DevCPL486.Label; name: DevCPT.Name; obj, p: DevCPT.Object; n: DevCPT.Node;
  1638. aAd, rAd: INTEGER; typ: DevCPT.Struct; useFpu: BOOLEAN;
  1639. BEGIN
  1640. DevCPH.UseReals(prog, {DevCPH.longDop, DevCPH.longMop});
  1641. DevCPM.NewObj(DevCPT.SelfName);
  1642. IF DevCPM.noerr THEN
  1643. DevCPE.OutHeader; n := prog.right;
  1644. WHILE (n # NIL) & (n.class = Ninittd) DO n := n.link END;
  1645. useFpu := FALSE; CheckFpu(n, useFpu);
  1646. DevCPC486.Enter(NIL, n = NIL, useFpu);
  1647. end := DevCPL486.NewLbl; stat(n, end); DevCPL486.SetLabel(end);
  1648. DevCPM.errpos := prog.conval.intval2; Checkpc;
  1649. DevCPC486.Exit(NIL, n = NIL);
  1650. IF prog.link # NIL THEN (* close section *)
  1651. DevCPL486.SetLabel(DevCPE.closeLbl);
  1652. useFpu := FALSE; CheckFpu(prog.link, useFpu);
  1653. DevCPC486.Enter(NIL, FALSE, useFpu);
  1654. end := DevCPL486.NewLbl; stat(prog.link, end); DevCPL486.SetLabel(end);
  1655. DevCPM.errpos := SHORT(ENTIER(prog.conval.realval)); Checkpc;
  1656. DevCPC486.Exit(NIL, FALSE)
  1657. END;
  1658. name := "$$"; DevCPE.OutRefName(name); DevCPE.OutRefs(DevCPT.topScope.right);
  1659. DevCPM.errpos := prog.conval.intval;
  1660. WHILE query # NIL DO
  1661. typ := query.typ; query.typ := DevCPT.int32typ;
  1662. query.conval.intval := 20; (* parameters *)
  1663. query.conval.intval2 := -8; (* saved registers *)
  1664. DevCPC486.Enter(query, FALSE, FALSE);
  1665. InstallQueryInterface(typ, query);
  1666. DevCPC486.Exit(query, FALSE);
  1667. name := "QueryInterface"; DevCPE.OutRefName(name);
  1668. query := query.nlink
  1669. END;
  1670. procs(prog.left);
  1671. DevCPC486.InstallStackAlloc;
  1672. addRef := NIL; release := NIL; release2 := NIL;
  1673. DevCPC486.intHandler := NIL;
  1674. IF DevCPM.noerr THEN DevCPE.OutCode END;
  1675. IF ~DevCPM.noerr THEN DevCPM.DeleteObj END
  1676. END
  1677. END Module;
  1678. END DevCPV486.