CPV486.txt 63 KB

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