2
0

CPV486.txt 63 KB

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