MGen.mod 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624
  1. IMPLEMENTATION MODULE MGen;
  2. IMPORT FileIO, SymTab;
  3. CONST
  4. MaxCode = 8191;
  5. MaxImg = 16383;
  6. MaxGlb = 255;
  7. MaxInit = 255;
  8. MaxLab = 255;
  9. MaxFix = 2047;
  10. MaxLoop = 15;
  11. MaxActDepth = 7;
  12. MaxActN = 63;
  13. (* opcodes, see mc64-spec.md §11 *)
  14. OPdup = 20H; OPswap = 21H;
  15. OPloadGlb = 2DH; OPstoreGlb = 3DH;
  16. OPloadLocal = 2CH; OPstoreLocal = 3CH;
  17. OPloadStk = 2EH;
  18. OPloadIndir0 = 60H; OPstoreIndir0 = 70H;
  19. OPloadOuterN = 11H;
  20. OPloadIndir = 41H; OPstoreIndir = 51H;
  21. OPlocalAddr = 80H; OPglobalAddr = 81H; OPstkAddr = 82H;
  22. OPext = 40H; SUBdrop = 00H;
  23. OPenter = 0D4H; OPprocLeave = 84H; OPfctLeave = 85H;
  24. OPprocCall = 0EDH; OPnestedCall = 0ECH; OPcallFrame = 0EEH;
  25. OPimmB = 8DH; OPimmW = 8EH; OPimm0 = 90H;
  26. OPadd = 0A6H; OPsub = 0A7H; OPumul = 0A8H;
  27. OPudiv = 0A9H; OPumod = 0AAH;
  28. OPaeq0 = 0ABH; OPinc = 0ACH; OPdec = 0ADH;
  29. OPeq = 0A0H; OPne = 0A1H;
  30. OPult = 0A2H; OPugt = 0A3H; OPule = 0A4H; OPuge = 0A5H;
  31. OPilt = 0B2H; OPigt = 0B3H; OPile = 0B4H; OPige = 0B5H;
  32. OPnot = 0B6H;
  33. OPimul = 0B8H; OPidiv = 0B9H;
  34. OPintToLong = 0BDH; OPlongToReal = 0BEH;
  35. OPrCmp = 0D5H; OPrAdd = 0D6H; OPrSub = 0D7H;
  36. OPrMul = 0D8H; OPrDiv = 0D9H;
  37. OPor = 0E6H; OPand = 0E8H;
  38. OPpower2 = 0EAH; OPbitIn = 0E7H;
  39. OPjp = 0E0H; OPjz = 0E1H;
  40. OPsys = 0C3H; OPend = 50H;
  41. (* image layout *)
  42. HeadSize = 64;
  43. DName = 264; DChecksum = 288; DFlags = 292;
  44. DVarCount = 293; DDepCount = 294; DProcs = 296;
  45. DVarSizes = 304;
  46. TYPE
  47. FixRec = RECORD
  48. pos : CARDINAL;
  49. lab : INTEGER;
  50. END;
  51. InitRec = RECORD
  52. idx : CARDINAL;
  53. kind : INTEGER; (* 0 = INTEGER value, 1 = raw 64-bit pattern *)
  54. ival : INTEGER;
  55. bits : LONGCARD;
  56. END;
  57. RealView = RECORD CASE : BOOLEAN OF
  58. | TRUE : r : REAL;
  59. | FALSE : w : LONGCARD;
  60. END;
  61. END;
  62. ActFrame = RECORD
  63. n : CARDINAL;
  64. tmps : ARRAY [0 .. MaxActN] OF INTEGER;
  65. lens : ARRAY [0 .. MaxActN] OF INTEGER;
  66. addrs : ARRAY [0 .. MaxActN] OF INTEGER;
  67. sfxs : ARRAY [0 .. MaxActN] OF BOOLEAN;
  68. idxs : ARRAY [0 .. MaxActN] OF BOOLEAN;
  69. known : BOOLEAN;
  70. nf : CARDINAL;
  71. pn : ARRAY [0 .. 63] OF CHAR;
  72. byNum : BOOLEAN;
  73. num : INTEGER;
  74. END;
  75. VAR
  76. code : ARRAY [0 .. MaxCode] OF CHAR;
  77. nCode : CARDINAL;
  78. img : ARRAY [0 .. MaxImg] OF CHAR;
  79. modName : ARRAY [0 .. 63] OF CHAR;
  80. gNames : ARRAY [0 .. MaxGlb] OF ARRAY [0 .. 63] OF CHAR;
  81. vBase : ARRAY [0 .. MaxGlb] OF CARDINAL;
  82. vSize : ARRAY [0 .. MaxGlb] OF CARDINAL;
  83. nVars : CARDINAL;
  84. nGlb : CARDINAL;
  85. inits : ARRAY [0 .. MaxInit] OF InitRec;
  86. nInit : CARDINAL;
  87. inBody : BOOLEAN;
  88. labs : ARRAY [0 .. MaxLab] OF INTEGER;
  89. nLab : CARDINAL;
  90. fixs : ARRAY [0 .. MaxFix] OF FixRec;
  91. nFix : CARDINAL;
  92. loopSt : ARRAY [0 .. MaxLoop] OF INTEGER;
  93. loopTop : CARDINAL;
  94. noSup : CARDINAL;
  95. noEmit : CARDINAL;
  96. actSt : ARRAY [0 .. MaxActDepth] OF ActFrame;
  97. actTop : CARDINAL;
  98. withTmps : ARRAY [0 .. 7] OF INTEGER;
  99. withTyps : ARRAY [0 .. 7] OF INTEGER;
  100. withTop : CARDINAL;
  101. procAddr : ARRAY [0 .. 64] OF INTEGER;
  102. maxNum : CARDINAL;
  103. mainAddr : CARDINAL;
  104. (* ---------------- byte helpers ---------------- *)
  105. PROCEDURE StrLen (s: ARRAY OF CHAR): CARDINAL;
  106. VAR i : CARDINAL;
  107. BEGIN
  108. i := 0;
  109. WHILE (i < HIGH(s)) & (s[i] # 0C) DO INC(i) END;
  110. RETURN i
  111. END StrLen;
  112. PROCEDURE StrCpy (VAR d: ARRAY OF CHAR; s: ARRAY OF CHAR);
  113. VAR i : CARDINAL;
  114. BEGIN
  115. i := 0;
  116. WHILE (i < HIGH(d)) & (i < HIGH(s)) & (s[i] # 0C) DO
  117. d[i] := s[i]; INC(i)
  118. END;
  119. IF i <= HIGH(d) THEN d[i] := 0C END
  120. END StrCpy;
  121. PROCEDURE EmitByte (b: CARDINAL);
  122. BEGIN
  123. IF noEmit > 0 THEN RETURN END;
  124. IF nCode <= MaxCode THEN
  125. code[nCode] := CHR(b MOD 256); INC(nCode)
  126. END
  127. END EmitByte;
  128. PROCEDURE EmitOp (o: CARDINAL);
  129. BEGIN
  130. EmitByte(o)
  131. END EmitOp;
  132. PROCEDURE EmitOpB (o, b: CARDINAL);
  133. BEGIN
  134. EmitByte(o); EmitByte(b)
  135. END EmitOpB;
  136. PROCEDURE EmitW64 (v: LONGCARD);
  137. VAR j : CARDINAL;
  138. BEGIN
  139. FOR j := 0 TO 7 DO
  140. EmitByte(VAL(CARDINAL, v MOD 256)); v := v DIV 256
  141. END
  142. END EmitW64;
  143. PROCEDURE EmitS64 (rel: INTEGER);
  144. (* Appends a signed 64-bit little-endian offset. *)
  145. VAR mag : CARDINAL;
  146. BEGIN
  147. IF rel >= 0 THEN EmitW64(VAL(LONGCARD, VAL(CARDINAL, rel)))
  148. ELSE
  149. IF rel = -2147483647 - 1 THEN mag := 80000000H
  150. ELSE mag := VAL(CARDINAL, -rel)
  151. END;
  152. EmitW64(0FFFFFFFFFFFFFFFFH - VAL(LONGCARD, mag) + 1H)
  153. END
  154. END EmitS64;
  155. PROCEDURE WriteS64At (off: CARDINAL; rel: INTEGER);
  156. (* Backpatches a signed offset into already-emitted code. *)
  157. VAR mag : CARDINAL;
  158. bits : LONGCARD;
  159. j : CARDINAL;
  160. BEGIN
  161. IF rel >= 0 THEN bits := VAL(LONGCARD, VAL(CARDINAL, rel))
  162. ELSE
  163. IF rel = -2147483647 - 1 THEN mag := 80000000H
  164. ELSE mag := VAL(CARDINAL, -rel)
  165. END;
  166. bits := 0FFFFFFFFFFFFFFFFH - VAL(LONGCARD, mag) + 1H
  167. END;
  168. FOR j := 0 TO 7 DO
  169. code[off + j] := CHR(VAL(CARDINAL, bits MOD 256));
  170. bits := bits DIV 256
  171. END
  172. END WriteS64At;
  173. PROCEDURE FindVar (name: ARRAY OF CHAR): INTEGER;
  174. VAR i : CARDINAL;
  175. BEGIN
  176. i := 0;
  177. WHILE i < nVars DO
  178. IF SymTab.Equal(gNames[i], name) THEN
  179. RETURN VAL(INTEGER, vBase[i])
  180. END;
  181. INC(i)
  182. END;
  183. RETURN -1
  184. END FindVar;
  185. PROCEDURE QualGlob (name: ARRAY OF CHAR; VAR q: ARRAY OF CHAR);
  186. VAR m: SymTab.Name;
  187. i, k: CARDINAL;
  188. BEGIN
  189. IF SymTab.InModule() & (SymTab.SymLev(name) > 0) THEN
  190. SymTab.CurModName(m);
  191. i := 0; k := 0;
  192. WHILE (k < HIGH(q)) & (m[i] # 0C) DO
  193. q[k] := m[i]; INC(k); INC(i)
  194. END;
  195. IF k <= HIGH(q) THEN q[k] := "."; INC(k) END;
  196. i := 0;
  197. WHILE (k < HIGH(q)) & (name[i] # 0C) DO
  198. q[k] := name[i]; INC(k); INC(i)
  199. END;
  200. IF k <= HIGH(q) THEN q[k] := 0C END
  201. ELSE
  202. StrCpy(q, name)
  203. END
  204. END QualGlob;
  205. PROCEDURE AssignSlots (name: ARRAY OF CHAR; n: CARDINAL): INTEGER;
  206. VAR base : CARDINAL;
  207. BEGIN
  208. IF nVars > MaxGlb THEN RETURN -1 END;
  209. IF n = 0 THEN
  210. StrCpy(gNames[nVars], name);
  211. vBase[nVars] := nGlb;
  212. vSize[nVars] := 0;
  213. INC(nVars);
  214. RETURN VAL(INTEGER, nGlb)
  215. END;
  216. IF nGlb + n - 1 > MaxGlb THEN RETURN -1 END;
  217. StrCpy(gNames[nVars], name);
  218. base := nGlb;
  219. vBase[nVars] := base;
  220. vSize[nVars] := n;
  221. INC(nVars);
  222. nGlb := nGlb + n;
  223. RETURN VAL(INTEGER, base)
  224. END AssignSlots;
  225. PROCEDURE AssignSlot (name: ARRAY OF CHAR): INTEGER;
  226. BEGIN
  227. RETURN AssignSlots(name, 1)
  228. END AssignSlot;
  229. (* ---------------- module / data section ---------------- *)
  230. PROCEDURE OpenModule (name: ARRAY OF CHAR);
  231. VAR i : CARDINAL;
  232. dummy : INTEGER;
  233. BEGIN
  234. StrCpy(modName, name);
  235. nCode := 0; nGlb := 0; nVars := 0; nInit := 0;
  236. nLab := 0; nFix := 0; loopTop := 0; noSup := 0; noEmit := 0;
  237. actTop := 0; withTop := 0;
  238. maxNum := 0; mainAddr := 0;
  239. i := 0;
  240. WHILE i <= 64 DO procAddr[i] := -1; INC(i) END;
  241. inBody := FALSE;
  242. i := 0;
  243. WHILE i <= MaxGlb DO gNames[i][0] := 0C; INC(i) END;
  244. (* slots 0..3 belong to the print helper *)
  245. dummy := AssignSlot(""); dummy := AssignSlot("");
  246. dummy := AssignSlot(""); dummy := AssignSlot("")
  247. END OpenModule;
  248. PROCEDURE DeclVar (name: ARRAY OF CHAR);
  249. VAR idx : INTEGER;
  250. BEGIN
  251. idx := AssignSlot(name);
  252. IF idx < 0 THEN RETURN END
  253. END DeclVar;
  254. PROCEDURE DeclVarSized (name: ARRAY OF CHAR; slots: CARDINAL);
  255. VAR idx : INTEGER;
  256. q: ARRAY [0 .. 63] OF CHAR;
  257. BEGIN
  258. QualGlob(name, q);
  259. idx := AssignSlots(q, slots);
  260. IF idx < 0 THEN RETURN END
  261. END DeclVarSized;
  262. PROCEDURE BufInit (idx: INTEGER; kind: INTEGER; ival: INTEGER;
  263. bits: LONGCARD);
  264. BEGIN
  265. IF nInit > MaxInit THEN RETURN END;
  266. inits[nInit].idx := VAL(CARDINAL, idx);
  267. inits[nInit].kind := kind;
  268. inits[nInit].ival := ival;
  269. inits[nInit].bits := bits;
  270. INC(nInit)
  271. END BufInit;
  272. PROCEDURE DeclConst (name: ARRAY OF CHAR; lit: LitStr; t: INTEGER);
  273. VAR idx : INTEGER;
  274. cls : INTEGER;
  275. v : INTEGER;
  276. c : CARDINAL;
  277. b : LONGCARD;
  278. q: ARRAY [0 .. 63] OF CHAR;
  279. BEGIN
  280. QualGlob(name, q);
  281. idx := AssignSlot(q);
  282. IF idx < 0 THEN RETURN END;
  283. cls := SymTab.ClassOf(t);
  284. IF ~IsLit(lit) OR (cls = SymTab.ClStr) THEN
  285. BufInit(idx, 0, 0, 0H); RETURN
  286. END;
  287. IF cls = SymTab.ClReal THEN
  288. IF ParseReal(lit, b) THEN BufInit(idx, 1, 0, b)
  289. ELSE BufInit(idx, 1, 0, 0H)
  290. END
  291. ELSIF SymTab.Equal(lit, "TRUE") THEN BufInit(idx, 0, 1, 0H)
  292. ELSIF SymTab.Equal(lit, "FALSE") THEN BufInit(idx, 0, 0, 0H)
  293. ELSIF ParseInt(lit, v) THEN BufInit(idx, 0, v, 0H)
  294. ELSIF ParseCard(lit, c) THEN
  295. BufInit(idx, 1, 0, VAL(LONGCARD, c))
  296. ELSE BufInit(idx, 0, 0, 0H)
  297. END
  298. END DeclConst;
  299. PROCEDURE DeclConstInt (name: ARRAY OF CHAR; v: INTEGER);
  300. VAR idx : INTEGER;
  301. q: ARRAY [0 .. 63] OF CHAR;
  302. BEGIN
  303. QualGlob(name, q);
  304. idx := AssignSlot(q);
  305. IF idx < 0 THEN RETURN END;
  306. BufInit(idx, 0, v, 0H)
  307. END DeclConstInt;
  308. PROCEDURE PushValue (kind: INTEGER; ival: INTEGER; bits: LONGCARD);
  309. BEGIN
  310. IF kind = 0 THEN PushInt(ival) ELSE PushBits(bits) END
  311. END PushValue;
  312. PROCEDURE BeginBody;
  313. VAR i : CARDINAL;
  314. BEGIN
  315. IF inBody THEN RETURN END;
  316. inBody := TRUE;
  317. mainAddr := nCode;
  318. i := 0;
  319. WHILE i < nInit DO
  320. PushValue(inits[i].kind, inits[i].ival, inits[i].bits);
  321. EmitOpB(OPstoreGlb, inits[i].idx);
  322. INC(i)
  323. END
  324. END BeginBody;
  325. (* ---------------- loads, stores, pushes ---------------- *)
  326. PROCEDURE LoadVar (name: ARRAY OF CHAR);
  327. VAR idx : INTEGER;
  328. q: ARRAY [0 .. 63] OF CHAR;
  329. BEGIN
  330. QualGlob(name, q);
  331. idx := FindVar(q);
  332. IF idx < 0 THEN EmitOp(OPimm0)
  333. ELSE EmitOpB(OPloadGlb, VAL(CARDINAL, idx))
  334. END
  335. END LoadVar;
  336. PROCEDURE StoreVar (name: ARRAY OF CHAR);
  337. VAR idx : INTEGER;
  338. q: ARRAY [0 .. 63] OF CHAR;
  339. BEGIN
  340. QualGlob(name, q);
  341. idx := FindVar(q);
  342. IF idx < 0 THEN EmitOp(OPext); EmitOp(SUBdrop)
  343. ELSE EmitOpB(OPstoreGlb, VAL(CARDINAL, idx))
  344. END
  345. END StoreVar;
  346. PROCEDURE LoadTemp (t: INTEGER);
  347. BEGIN
  348. EmitOpB(OPloadGlb, VAL(CARDINAL, t))
  349. END LoadTemp;
  350. PROCEDURE StoreTemp (t: INTEGER);
  351. BEGIN
  352. EmitOpB(OPstoreGlb, VAL(CARDINAL, t))
  353. END StoreTemp;
  354. PROCEDURE TempGlobal (): INTEGER;
  355. VAR idx : INTEGER;
  356. BEGIN
  357. idx := AssignSlot("");
  358. IF idx < 0 THEN RETURN 4 END;
  359. RETURN idx
  360. END TempGlobal;
  361. (* ---------------- frames and procedures ---------------- *)
  362. PROCEDURE EmitSlotB (op: CARDINAL; sl: INTEGER);
  363. (* Byte operand for a (possibly negative) frame slot. *)
  364. BEGIN
  365. IF sl >= 0 THEN EmitOpB(op, VAL(CARDINAL, sl))
  366. ELSE EmitOpB(op, 256 - VAL(CARDINAL, -sl))
  367. END
  368. END EmitSlotB;
  369. PROCEDURE LoadLocal (sl: INTEGER);
  370. BEGIN
  371. EmitSlotB(OPloadLocal, sl)
  372. END LoadLocal;
  373. PROCEDURE StoreLocal (sl: INTEGER);
  374. BEGIN
  375. EmitSlotB(OPstoreLocal, sl)
  376. END StoreLocal;
  377. PROCEDURE LoadIndir0;
  378. BEGIN
  379. EmitOp(OPloadIndir0)
  380. END LoadIndir0;
  381. PROCEDURE StoreIndir0;
  382. BEGIN
  383. EmitOp(OPstoreIndir0)
  384. END StoreIndir0;
  385. PROCEDURE FrameAddr (sl: INTEGER; np: CARDINAL);
  386. (* Pushes (display-frame(np) + slot*8): 11H np, then the offset. *)
  387. BEGIN
  388. EmitOpB(OPloadOuterN, np);
  389. IF sl >= 0 THEN EmitOpB(OPstkAddr, VAL(CARDINAL, sl))
  390. ELSE
  391. PushInt(sl * 8);
  392. EmitOp(OPadd)
  393. END
  394. END FrameAddr;
  395. PROCEDURE LoadIndir;
  396. BEGIN
  397. EmitOp(OPloadIndir)
  398. END LoadIndir;
  399. PROCEDURE StoreIndir;
  400. BEGIN
  401. EmitOp(OPstoreIndir)
  402. END StoreIndir;
  403. PROCEDURE LocalAddr (sl: INTEGER);
  404. BEGIN
  405. EmitSlotB(OPlocalAddr, sl)
  406. END LocalAddr;
  407. PROCEDURE GlobalAddr (name: ARRAY OF CHAR);
  408. VAR idx : INTEGER;
  409. q: ARRAY [0 .. 63] OF CHAR;
  410. BEGIN
  411. QualGlob(name, q);
  412. idx := FindVar(q);
  413. IF idx < 0 THEN EmitOp(OPimm0)
  414. ELSE EmitOpB(OPglobalAddr, VAL(CARDINAL, idx))
  415. END
  416. END GlobalAddr;
  417. PROCEDURE PushAddr (name: ARRAY OF CHAR);
  418. (* VAR-actual address: slot contents for VAR params, slot address
  419. for plain variables; display-aware. *)
  420. VAR k, d, D, sl : INTEGER;
  421. np : CARDINAL;
  422. BEGIN
  423. k := SymTab.SymKind(name);
  424. d := SymTab.SymDepth(name);
  425. D := SymTab.CurDepth();
  426. sl := SymTab.SymSlot(name);
  427. IF (k # SymTab.KindVar) & (k # SymTab.KindParam)
  428. & (k # SymTab.KindVarPar) THEN
  429. EmitOp(OPimm0); RETURN
  430. END;
  431. IF (k = SymTab.KindVarPar)
  432. OR ((k = SymTab.KindParam)
  433. & SymTab.IsOpen(SymTab.SymType(name))) THEN
  434. IF D = d THEN LoadLocal(sl)
  435. ELSE
  436. np := VAL(CARDINAL, D - 1 - d);
  437. FrameAddr(sl, np);
  438. LoadIndir
  439. END
  440. ELSE
  441. IF d = 0 THEN GlobalAddr(name)
  442. ELSIF D = d THEN LocalAddr(sl)
  443. ELSE
  444. np := VAL(CARDINAL, D - 1 - d);
  445. FrameAddr(sl, np)
  446. END
  447. END
  448. END PushAddr;
  449. PROCEDURE StoreSetup (name: ARRAY OF CHAR);
  450. (* Early address for indirect stores; call before the value code. *)
  451. VAR k, d, D, sl : INTEGER;
  452. np : CARDINAL;
  453. BEGIN
  454. k := SymTab.SymKind(name);
  455. IF (k # SymTab.KindVar) & (k # SymTab.KindParam)
  456. & (k # SymTab.KindVarPar) THEN
  457. RETURN
  458. END;
  459. d := SymTab.SymDepth(name);
  460. D := SymTab.CurDepth();
  461. sl := SymTab.SymSlot(name);
  462. IF k = SymTab.KindVarPar THEN
  463. IF D = d THEN LoadLocal(sl)
  464. ELSE
  465. np := VAL(CARDINAL, D - 1 - d);
  466. FrameAddr(sl, np);
  467. LoadIndir
  468. END
  469. ELSIF (d # 0) & (D # d) THEN
  470. np := VAL(CARDINAL, D - 1 - d);
  471. FrameAddr(sl, np)
  472. END
  473. END StoreSetup;
  474. PROCEDURE StoreFinish (name: ARRAY OF CHAR);
  475. (* Completes the store; call after the value code. *)
  476. VAR k, d, D, sl : INTEGER;
  477. BEGIN
  478. k := SymTab.SymKind(name);
  479. IF (k # SymTab.KindVar) & (k # SymTab.KindParam)
  480. & (k # SymTab.KindVarPar) THEN
  481. RETURN
  482. END;
  483. d := SymTab.SymDepth(name);
  484. D := SymTab.CurDepth();
  485. sl := SymTab.SymSlot(name);
  486. IF d = 0 THEN StoreVar(name)
  487. ELSIF D = d THEN
  488. IF k = SymTab.KindVarPar THEN StoreIndir0
  489. ELSE StoreLocal(sl)
  490. END
  491. ELSE
  492. IF k = SymTab.KindVarPar THEN StoreIndir0
  493. ELSE StoreIndir
  494. END
  495. END
  496. END StoreFinish;
  497. PROCEDURE PushVar (name: ARRAY OF CHAR);
  498. (* Frame-aware value load (see PushAddr for the address twin). *)
  499. VAR k, d, D, sl : INTEGER;
  500. np : CARDINAL;
  501. BEGIN
  502. k := SymTab.SymKind(name);
  503. d := SymTab.SymDepth(name);
  504. D := SymTab.CurDepth();
  505. sl := SymTab.SymSlot(name);
  506. IF (k # SymTab.KindVar) & (k # SymTab.KindParam)
  507. & (k # SymTab.KindVarPar) THEN
  508. EmitOp(OPimm0); RETURN
  509. END;
  510. IF d = 0 THEN LoadVar(name)
  511. ELSIF D = d THEN
  512. IF k = SymTab.KindVarPar THEN
  513. LoadLocal(sl); LoadIndir0
  514. ELSE LoadLocal(sl)
  515. END
  516. ELSE
  517. np := VAL(CARDINAL, D - 1 - d);
  518. FrameAddr(sl, np);
  519. LoadIndir;
  520. IF k = SymTab.KindVarPar THEN LoadIndir0 END
  521. END
  522. END PushVar;
  523. PROCEDURE ProcEntry (num: INTEGER; nLoc: CARDINAL);
  524. VAR k : CARDINAL;
  525. BEGIN
  526. IF (num >= 0) & (num <= 64) THEN
  527. procAddr[num] := VAL(INTEGER, nCode);
  528. IF VAL(CARDINAL, num) > maxNum THEN
  529. maxNum := VAL(CARDINAL, num)
  530. END
  531. END;
  532. IF nLoc > 255 THEN k := 255 ELSE k := nLoc END;
  533. EmitOpB(OPenter, 255 - k)
  534. END ProcEntry;
  535. PROCEDURE CallProc (num: INTEGER);
  536. BEGIN
  537. EmitOpB(OPprocCall, VAL(CARDINAL, num))
  538. END CallProc;
  539. PROCEDURE CallNested (num: INTEGER);
  540. BEGIN
  541. EmitOpB(OPnestedCall, VAL(CARDINAL, num))
  542. END CallNested;
  543. PROCEDURE CallDisplay (num: INTEGER; np: CARDINAL);
  544. BEGIN
  545. EmitOpB(OPloadOuterN, np);
  546. EmitOpB(OPcallFrame, VAL(CARDINAL, num))
  547. END CallDisplay;
  548. PROCEDURE Leave (nPar: CARDINAL; func: BOOLEAN);
  549. BEGIN
  550. IF nPar > 255 THEN nPar := 255 END;
  551. IF func THEN EmitOpB(OPfctLeave, nPar)
  552. ELSE EmitOpB(OPprocLeave, nPar)
  553. END
  554. END Leave;
  555. (* ---------------- actual parameters ---------------- *)
  556. PROCEDURE ActFrameIdx (): CARDINAL;
  557. (* Active frame, capped (nesting past the cap reuses the top). *)
  558. BEGIN
  559. IF actTop = 0 THEN RETURN 0 END;
  560. IF actTop - 1 > MaxActDepth THEN RETURN MaxActDepth END;
  561. RETURN actTop - 1
  562. END ActFrameIdx;
  563. PROCEDURE ActIsVarNext (): BOOLEAN;
  564. VAR fr, i: CARDINAL;
  565. BEGIN
  566. IF actTop = 0 THEN RETURN FALSE END;
  567. fr := ActFrameIdx();
  568. IF ~actSt[fr].known THEN RETURN FALSE END;
  569. i := actSt[fr].n;
  570. IF i >= actSt[fr].nf THEN RETURN FALSE END;
  571. RETURN SymTab.ParamIsVar(actSt[fr].pn, i)
  572. END ActIsVarNext;
  573. PROCEDURE NoteSfx (b: BOOLEAN);
  574. VAR fr, i: CARDINAL;
  575. BEGIN
  576. IF actTop = 0 THEN RETURN END;
  577. fr := ActFrameIdx();
  578. i := actSt[fr].n;
  579. IF i <= MaxActN THEN actSt[fr].sfxs[i] := b END
  580. END NoteSfx;
  581. PROCEDURE NoteIdx (b: BOOLEAN);
  582. VAR fr, i: CARDINAL;
  583. BEGIN
  584. IF actTop = 0 THEN RETURN END;
  585. fr := ActFrameIdx();
  586. i := actSt[fr].n;
  587. IF i <= MaxActN THEN actSt[fr].idxs[i] := b END
  588. END NoteIdx;
  589. PROCEDURE ActBegin (pn: ARRAY OF CHAR);
  590. VAR fr : CARDINAL;
  591. k : CARDINAL;
  592. BEGIN
  593. fr := actTop;
  594. IF fr > MaxActDepth THEN fr := MaxActDepth
  595. ELSE INC(actTop)
  596. END;
  597. StrCpy(actSt[fr].pn, pn);
  598. actSt[fr].n := 0;
  599. k := 0;
  600. WHILE k <= MaxActN DO
  601. actSt[fr].lens[k] := -1;
  602. actSt[fr].addrs[k] := -1;
  603. actSt[fr].sfxs[k] := FALSE;
  604. actSt[fr].idxs[k] := TRUE;
  605. INC(k)
  606. END;
  607. actSt[fr].known := SymTab.Lookup(pn)
  608. & (SymTab.SymKind(pn) = SymTab.KindProc);
  609. IF actSt[fr].known THEN actSt[fr].nf := SymTab.ProcNPar(pn)
  610. ELSE actSt[fr].nf := 0
  611. END;
  612. actSt[fr].byNum := FALSE;
  613. actSt[fr].num := -1
  614. END ActBegin;
  615. PROCEDURE ActBeginNum (num: INTEGER);
  616. (* Actuals for a procedure known by number (exported module procs,
  617. whose names vanish with the module body scope). *)
  618. VAR fr : CARDINAL;
  619. k : CARDINAL;
  620. BEGIN
  621. fr := actTop;
  622. IF fr > MaxActDepth THEN fr := MaxActDepth
  623. ELSE INC(actTop)
  624. END;
  625. actSt[fr].pn[0] := 0C;
  626. actSt[fr].n := 0;
  627. k := 0;
  628. WHILE k <= MaxActN DO
  629. actSt[fr].lens[k] := -1;
  630. actSt[fr].addrs[k] := -1;
  631. actSt[fr].sfxs[k] := FALSE;
  632. actSt[fr].idxs[k] := TRUE;
  633. INC(k)
  634. END;
  635. actSt[fr].known := SymTab.ProcValid(num);
  636. IF actSt[fr].known THEN actSt[fr].nf := SymTab.ProcNParByNum(num)
  637. ELSE actSt[fr].nf := 0
  638. END;
  639. actSt[fr].byNum := TRUE;
  640. actSt[fr].num := num
  641. END ActBeginNum;
  642. PROCEDURE ActFormalType (fr, i: CARDINAL): INTEGER;
  643. (* i-th formal type of the frame's callee, by number or by name. *)
  644. BEGIN
  645. IF actSt[fr].byNum THEN
  646. RETURN SymTab.ParamTypeByNum(actSt[fr].num, i)
  647. ELSE
  648. RETURN SymTab.ParamType(actSt[fr].pn, i)
  649. END
  650. END ActFormalType;
  651. PROCEDURE ActFormalIsVar (fr, i: CARDINAL): BOOLEAN;
  652. BEGIN
  653. IF actSt[fr].byNum THEN
  654. RETURN SymTab.ParamIsVarByNum(actSt[fr].num, i)
  655. ELSE
  656. RETURN SymTab.ParamIsVar(actSt[fr].pn, i)
  657. END
  658. END ActFormalIsVar;
  659. PROCEDURE StashAddr;
  660. (* Duplicates the address on top of stack into a per-actual temp of
  661. the current call frame (for VAR actuals with tails: a[i], p^,
  662. fields). The ATG calls this at the Fact tail, when the address is
  663. complete but not yet loaded. Recorded as -1 when unused. *)
  664. VAR fr, i : CARDINAL;
  665. tmp : INTEGER;
  666. BEGIN
  667. IF actTop = 0 THEN RETURN END;
  668. fr := ActFrameIdx();
  669. i := actSt[fr].n;
  670. IF i > MaxActN THEN RETURN END;
  671. tmp := TempGlobal();
  672. actSt[fr].addrs[i] := tmp;
  673. EmitOp(OPdup);
  674. StoreTemp(tmp)
  675. END StashAddr;
  676. PROCEDURE ClrStash;
  677. (* Invalidates the stashed address of the current actual: a
  678. value-combining operator followed, so the address no longer
  679. denotes the actual. Conservative no-op outside calls. *)
  680. VAR fr, i : CARDINAL;
  681. BEGIN
  682. IF actTop = 0 THEN RETURN END;
  683. fr := ActFrameIdx();
  684. i := actSt[fr].n;
  685. IF i <= MaxActN THEN actSt[fr].addrs[i] := -1 END
  686. END ClrStash;
  687. PROCEDURE ActValue (t: INTEGER; v: BOOLEAN;
  688. vn: ARRAY OF CHAR): INTEGER;
  689. VAR fr : CARDINAL;
  690. i : CARDINAL;
  691. ftyp : INTEGER;
  692. fv : BOOLEAN;
  693. err : INTEGER;
  694. BEGIN
  695. err := 0;
  696. fr := ActFrameIdx();
  697. i := actSt[fr].n;
  698. IF i > MaxActN THEN
  699. EmitOp(OPext); EmitOp(SUBdrop);
  700. actSt[fr].n := i + 1;
  701. RETURN 1
  702. END;
  703. IF actSt[fr].known & (i < actSt[fr].nf) THEN
  704. ftyp := ActFormalType(fr, i);
  705. fv := ActFormalIsVar(fr, i);
  706. IF SymTab.IsOpen(ftyp) THEN
  707. IF (t = SymTab.InvalidType)
  708. OR SymTab.IsOpen(t)
  709. OR (SymTab.ClassOf(t) # SymTab.ClArray) THEN
  710. err := 1
  711. ELSIF ~SymTab.SameType(SymTab.ArrayElem(t),
  712. SymTab.ArrayElem(ftyp)) THEN
  713. err := 1
  714. ELSIF fv & ~v & (actSt[fr].addrs[i] < 0) THEN
  715. err := 1
  716. END;
  717. IF (t # SymTab.InvalidType)
  718. & (SymTab.ClassOf(t) = SymTab.ClArray)
  719. & ~SymTab.IsOpen(t) THEN
  720. PushInt(VAL(INTEGER, SymTab.ArrayLen(t)))
  721. ELSE
  722. PushInt(0)
  723. END;
  724. actSt[fr].lens[i] := TempGlobal();
  725. StoreTemp(actSt[fr].lens[i]);
  726. IF fv THEN
  727. IF (err = 0) & (actSt[fr].addrs[i] >= 0) THEN
  728. (* tailed array actual: its address is already on top *)
  729. ELSE
  730. EmitOp(OPext); EmitOp(SUBdrop);
  731. PushAddr(vn)
  732. END
  733. END
  734. ELSIF fv THEN
  735. IF actSt[fr].addrs[i] >= 0 THEN
  736. IF (t # SymTab.InvalidType)
  737. & ((SymTab.ClassOf(t) = SymTab.ClArray)
  738. OR (SymTab.ClassOf(t) = SymTab.ClRecord)) THEN
  739. (* tailed composite actual: address already on top *)
  740. ELSIF SymTab.SameType(t, ftyp) THEN
  741. EmitOp(OPext); EmitOp(SUBdrop);
  742. LoadTemp(actSt[fr].addrs[i])
  743. ELSE
  744. err := 1;
  745. EmitOp(OPext); EmitOp(SUBdrop);
  746. PushAddr(vn)
  747. END
  748. ELSE
  749. IF ~v THEN err := 1
  750. ELSIF ~SymTab.SameType(t, ftyp) THEN err := 1
  751. END;
  752. EmitOp(OPext); EmitOp(SUBdrop);
  753. PushAddr(vn)
  754. END
  755. ELSE
  756. IF ~SymTab.Assignable(t, ftyp) THEN err := 1
  757. ELSIF SymTab.IsIntFamily(t)
  758. & (SymTab.ClassOf(ftyp) = SymTab.ClReal) THEN
  759. IntToReal
  760. END
  761. END
  762. END;
  763. actSt[fr].tmps[i] := TempGlobal();
  764. StoreTemp(actSt[fr].tmps[i]);
  765. actSt[fr].n := i + 1;
  766. RETURN err
  767. END ActValue;
  768. PROCEDURE ActEnd (pn: ARRAY OF CHAR; sfx, inExpr: BOOLEAN): INTEGER;
  769. VAR fr : CARDINAL;
  770. i : CARDINAL;
  771. n, num, F, d : INTEGER;
  772. BEGIN
  773. fr := ActFrameIdx();
  774. IF actTop > 0 THEN DEC(actTop) END;
  775. n := VAL(INTEGER, actSt[fr].n);
  776. IF ~SymTab.Lookup(pn) THEN
  777. IF inExpr THEN EmitOp(OPimm0) END;
  778. RETURN 0
  779. END;
  780. IF (SymTab.SymKind(pn) # SymTab.KindProc)
  781. OR sfx
  782. OR (n # VAL(INTEGER, SymTab.ProcNPar(pn))) THEN
  783. IF inExpr THEN EmitOp(OPimm0) END;
  784. RETURN 1
  785. END;
  786. IF inExpr & (SymTab.ProcRet(pn) = SymTab.InvalidType) THEN
  787. EmitOp(OPimm0);
  788. RETURN 1
  789. END;
  790. i := actSt[fr].n;
  791. WHILE i > 0 DO
  792. DEC(i);
  793. IF i <= MaxActN THEN
  794. IF (actSt[fr].lens[i] >= 0)
  795. & SymTab.IsOpen(SymTab.ParamType(pn, i)) THEN
  796. LoadTemp(actSt[fr].lens[i]);
  797. LoadTemp(actSt[fr].tmps[i])
  798. ELSE
  799. LoadTemp(actSt[fr].tmps[i])
  800. END
  801. END
  802. END;
  803. num := SymTab.ProcNum(pn);
  804. F := SymTab.CurDepth();
  805. d := SymTab.SymDepth(pn);
  806. IF d = 0 THEN CallProc(num)
  807. ELSIF F = d THEN CallNested(num)
  808. ELSE CallDisplay(num, VAL(CARDINAL, F - 1 - d))
  809. END;
  810. IF ~inExpr & (SymTab.ProcRet(pn) # SymTab.InvalidType) THEN
  811. EmitOp(OPext); EmitOp(SUBdrop)
  812. END;
  813. RETURN 0
  814. END ActEnd;
  815. PROCEDURE ActEndNum (num: INTEGER; inExpr: BOOLEAN): INTEGER;
  816. (* Ends a by-number call (module procedures are always global-level,
  817. so a plain global call is correct; the M. prefix is qualification,
  818. not a tail, hence no sfx check). *)
  819. VAR fr : CARDINAL;
  820. i : CARDINAL;
  821. n : INTEGER;
  822. BEGIN
  823. fr := ActFrameIdx();
  824. IF actTop > 0 THEN DEC(actTop) END;
  825. n := VAL(INTEGER, actSt[fr].n);
  826. IF ~SymTab.ProcValid(num)
  827. OR (n # VAL(INTEGER, SymTab.ProcNParByNum(num))) THEN
  828. IF inExpr THEN EmitOp(OPimm0) END;
  829. RETURN 1
  830. END;
  831. IF inExpr & (SymTab.ProcRetByNum(num) = SymTab.InvalidType) THEN
  832. EmitOp(OPimm0);
  833. RETURN 1
  834. END;
  835. i := actSt[fr].n;
  836. WHILE i > 0 DO
  837. DEC(i);
  838. IF i <= MaxActN THEN
  839. IF (actSt[fr].lens[i] >= 0)
  840. & SymTab.IsOpen(SymTab.ParamTypeByNum(num, i)) THEN
  841. LoadTemp(actSt[fr].lens[i]);
  842. LoadTemp(actSt[fr].tmps[i])
  843. ELSE
  844. LoadTemp(actSt[fr].tmps[i])
  845. END
  846. END
  847. END;
  848. CallProc(num);
  849. IF ~inExpr & (SymTab.ProcRetByNum(num) # SymTab.InvalidType) THEN
  850. EmitOp(OPext); EmitOp(SUBdrop)
  851. END;
  852. RETURN 0
  853. END ActEndNum;
  854. PROCEDURE EmitMag (c: CARDINAL);
  855. BEGIN
  856. IF c <= 255 THEN EmitOpB(OPimmB, c)
  857. ELSE EmitOp(OPimmW); EmitW64(VAL(LONGCARD, c))
  858. END
  859. END EmitMag;
  860. PROCEDURE PushInt (v: INTEGER);
  861. VAR mag : CARDINAL;
  862. BEGIN
  863. IF (v >= 0) & (v <= 15) THEN EmitOp(OPimm0 + VAL(CARDINAL, v))
  864. ELSIF v < 0 THEN
  865. IF v = -2147483647 - 1 THEN mag := 80000000H
  866. ELSE mag := VAL(CARDINAL, -v)
  867. END;
  868. EmitOp(OPimm0); EmitMag(mag); EmitOp(OPsub)
  869. ELSE EmitMag(VAL(CARDINAL, v))
  870. END
  871. END PushInt;
  872. PROCEDURE PushBits (b: LONGCARD);
  873. BEGIN
  874. EmitOp(OPimmW); EmitW64(b)
  875. END PushBits;
  876. (* ---------------- literal parsing ---------------- *)
  877. PROCEDURE DigVal (ch: CHAR): INTEGER;
  878. BEGIN
  879. IF (ch >= "0") & (ch <= "9") THEN RETURN ORD(ch) - ORD("0") END;
  880. IF (ch >= "A") & (ch <= "F") THEN RETURN ORD(ch) - ORD("A") + 10 END;
  881. IF (ch >= "a") & (ch <= "f") THEN RETURN ORD(ch) - ORD("a") + 10 END;
  882. RETURN -1
  883. END DigVal;
  884. PROCEDURE ParseCard (s: ARRAY OF CHAR; VAR v: CARDINAL): BOOLEAN;
  885. VAR i, n : CARDINAL;
  886. hex : BOOLEAN;
  887. d : INTEGER;
  888. acc : LONGCARD;
  889. BEGIN
  890. v := 0;
  891. n := StrLen(s);
  892. IF n = 0 THEN RETURN FALSE END;
  893. hex := (s[n - 1] = "H") OR (s[n - 1] = "h");
  894. IF hex THEN DEC(n) END;
  895. IF n = 0 THEN RETURN FALSE END;
  896. acc := 0H; i := 0;
  897. WHILE i < n DO
  898. d := DigVal(s[i]);
  899. IF hex THEN
  900. IF d < 0 THEN RETURN FALSE END;
  901. acc := acc * 16 + VAL(LONGCARD, VAL(CARDINAL, d))
  902. ELSE
  903. IF (d < 0) OR (d > 9) THEN RETURN FALSE END;
  904. acc := acc * 10 + VAL(LONGCARD, VAL(CARDINAL, d))
  905. END;
  906. IF acc > 0FFFFFFFFH THEN RETURN FALSE END;
  907. INC(i)
  908. END;
  909. v := VAL(CARDINAL, acc);
  910. RETURN TRUE
  911. END ParseCard;
  912. PROCEDURE ParseInt (s: ARRAY OF CHAR; VAR v: INTEGER): BOOLEAN;
  913. VAR i : CARDINAL;
  914. neg : BOOLEAN;
  915. t : ARRAY [0 .. 63] OF CHAR;
  916. c : CARDINAL;
  917. lim : LONGCARD;
  918. BEGIN
  919. v := 0;
  920. IF (StrLen(s) = 0) THEN RETURN FALSE END;
  921. neg := s[0] = "-";
  922. IF neg THEN
  923. i := 1;
  924. WHILE s[i] # 0C DO
  925. IF i - 1 > HIGH(t) THEN RETURN FALSE END;
  926. t[i - 1] := s[i]; INC(i)
  927. END;
  928. IF i - 1 > HIGH(t) THEN RETURN FALSE END;
  929. t[i - 1] := 0C
  930. ELSE StrCpy(t, s)
  931. END;
  932. IF ~ParseCard(t, c) THEN RETURN FALSE END;
  933. IF neg THEN lim := 80000000H ELSE lim := 7FFFFFFFH END;
  934. IF VAL(LONGCARD, c) > lim THEN RETURN FALSE END;
  935. IF neg THEN
  936. IF VAL(LONGCARD, c) = 80000000H THEN v := -2147483647 - 1
  937. ELSE v := -VAL(INTEGER, c)
  938. END
  939. ELSE v := VAL(INTEGER, c)
  940. END;
  941. RETURN TRUE
  942. END ParseInt;
  943. PROCEDURE ParseReal (s: ARRAY OF CHAR; VAR b: LONGCARD): BOOLEAN;
  944. VAR i : CARDINAL;
  945. neg, esign : BOOLEAN;
  946. m, scale : REAL;
  947. e, d : CARDINAL;
  948. rv : RealView;
  949. BEGIN
  950. b := 0H;
  951. i := 0; neg := FALSE;
  952. IF s[0] = "-" THEN neg := TRUE; INC(i) END;
  953. IF (s[i] < "0") OR (s[i] > "9") THEN RETURN FALSE END;
  954. m := 0.0;
  955. WHILE (s[i] >= "0") & (s[i] <= "9") DO
  956. m := m * 10.0 + VAL(REAL, VAL(CARDINAL, ORD(s[i]) - ORD("0")));
  957. INC(i)
  958. END;
  959. IF s[i] = "." THEN
  960. INC(i);
  961. IF (s[i] < "0") OR (s[i] > "9") THEN RETURN FALSE END;
  962. scale := 10.0;
  963. WHILE (s[i] >= "0") & (s[i] <= "9") DO
  964. m := m + VAL(REAL, VAL(CARDINAL, ORD(s[i]) - ORD("0"))) / scale;
  965. scale := scale * 10.0;
  966. INC(i)
  967. END
  968. END;
  969. IF (s[i] = "E") OR (s[i] = "e") THEN
  970. INC(i); esign := FALSE;
  971. IF s[i] = "+" THEN INC(i)
  972. ELSIF s[i] = "-" THEN esign := TRUE; INC(i)
  973. END;
  974. IF (s[i] < "0") OR (s[i] > "9") THEN RETURN FALSE END;
  975. e := 0;
  976. WHILE (s[i] >= "0") & (s[i] <= "9") DO
  977. d := VAL(CARDINAL, ORD(s[i]) - ORD("0"));
  978. IF e <= 9999 THEN e := e * 10 + d END;
  979. INC(i)
  980. END;
  981. WHILE e > 0 DO
  982. IF esign THEN m := m / 10.0 ELSE m := m * 10.0 END;
  983. DEC(e)
  984. END
  985. END;
  986. IF s[i] # 0C THEN RETURN FALSE END;
  987. IF neg THEN m := -m END;
  988. rv.r := m;
  989. b := rv.w;
  990. RETURN TRUE
  991. END ParseReal;
  992. PROCEDURE CharOrd (s: ARRAY OF CHAR): INTEGER;
  993. BEGIN
  994. IF StrLen(s) >= 2 THEN RETURN ORD(s[1]) END;
  995. RETURN 0
  996. END CharOrd;
  997. PROCEDURE NegFold (a: ARRAY OF CHAR; VAR q: LitStr);
  998. (* Safe for a and q being the same variable. *)
  999. VAR tmp : LitStr;
  1000. i, j : CARDINAL;
  1001. BEGIN
  1002. StrCpy(tmp, a);
  1003. IF StrLen(tmp) = 0 THEN StrCpy(q, ""); RETURN END;
  1004. IF tmp[0] = "-" THEN
  1005. i := 1; j := 0;
  1006. WHILE (tmp[i] # 0C) & (j < HIGH(q)) DO
  1007. q[j] := tmp[i]; INC(i); INC(j)
  1008. END;
  1009. IF j <= HIGH(q) THEN q[j] := 0C END
  1010. ELSE
  1011. StrCpy(q, "-");
  1012. i := 0; j := StrLen(q);
  1013. WHILE (tmp[i] # 0C) & (j < HIGH(q)) DO
  1014. q[j] := tmp[i]; INC(i); INC(j)
  1015. END;
  1016. IF j <= HIGH(q) THEN q[j] := 0C END
  1017. END
  1018. END NegFold;
  1019. PROCEDURE IsLit (s: ARRAY OF CHAR): BOOLEAN;
  1020. BEGIN
  1021. RETURN StrLen(s) > 0
  1022. END IsLit;
  1023. (* ---------------- operators ---------------- *)
  1024. PROCEDURE Add;
  1025. BEGIN EmitOp(OPadd) END Add;
  1026. PROCEDURE Sub;
  1027. BEGIN EmitOp(OPsub) END Sub;
  1028. PROCEDURE MulU;
  1029. BEGIN EmitOp(OPumul) END MulU;
  1030. PROCEDURE DivU;
  1031. BEGIN EmitOp(OPudiv) END DivU;
  1032. PROCEDURE ModU;
  1033. BEGIN EmitOp(OPumod) END ModU;
  1034. PROCEDURE MulI;
  1035. BEGIN EmitOp(OPimul) END MulI;
  1036. PROCEDURE DivI;
  1037. BEGIN EmitOp(OPidiv) END DivI;
  1038. PROCEDURE ModI (t: INTEGER);
  1039. (* [a b] -> a MOD b (truncation) via temp t. *)
  1040. BEGIN
  1041. StoreTemp(t);
  1042. EmitOp(OPdup);
  1043. LoadTemp(t);
  1044. EmitOp(OPidiv);
  1045. LoadTemp(t);
  1046. EmitOp(OPimul);
  1047. EmitOp(OPsub)
  1048. END ModI;
  1049. PROCEDURE RealAdd;
  1050. BEGIN EmitOp(OPrAdd) END RealAdd;
  1051. PROCEDURE RealSub;
  1052. BEGIN EmitOp(OPrSub) END RealSub;
  1053. PROCEDURE RealMul;
  1054. BEGIN EmitOp(OPrMul) END RealMul;
  1055. PROCEDURE RealDiv;
  1056. BEGIN EmitOp(OPrDiv) END RealDiv;
  1057. PROCEDURE And;
  1058. BEGIN EmitOp(OPand) END And;
  1059. PROCEDURE Or;
  1060. BEGIN EmitOp(OPor) END Or;
  1061. PROCEDURE Not;
  1062. BEGIN EmitOp(OPnot) END Not;
  1063. PROCEDURE Power2;
  1064. BEGIN EmitOp(OPpower2) END Power2;
  1065. PROCEDURE FieldMask;
  1066. BEGIN EmitOp(OPext); EmitOp(04H) END FieldMask;
  1067. PROCEDURE BitIn;
  1068. BEGIN EmitOp(OPbitIn) END BitIn;
  1069. PROCEDURE Eq;
  1070. BEGIN EmitOp(OPeq) END Eq;
  1071. PROCEDURE Neq;
  1072. BEGIN EmitOp(OPne) END Neq;
  1073. PROCEDURE ULt;
  1074. BEGIN EmitOp(OPult) END ULt;
  1075. PROCEDURE ULe;
  1076. BEGIN EmitOp(OPule) END ULe;
  1077. PROCEDURE UGt;
  1078. BEGIN EmitOp(OPugt) END UGt;
  1079. PROCEDURE UGe;
  1080. BEGIN EmitOp(OPuge) END UGe;
  1081. PROCEDURE ILt;
  1082. BEGIN EmitOp(OPilt) END ILt;
  1083. PROCEDURE ILe;
  1084. BEGIN EmitOp(OPile) END ILe;
  1085. PROCEDURE IGt;
  1086. BEGIN EmitOp(OPigt) END IGt;
  1087. PROCEDURE IGe;
  1088. BEGIN EmitOp(OPige) END IGe;
  1089. PROCEDURE RealEq;
  1090. (* [r1 r2] -> (r1 = r2): cmp, or, not. *)
  1091. BEGIN EmitOp(OPrCmp); EmitOp(OPor); EmitOp(OPnot) END RealEq;
  1092. PROCEDURE RealNe;
  1093. (* [r1 r2] -> (r1 # r2): cmp, or. *)
  1094. BEGIN EmitOp(OPrCmp); EmitOp(OPor) END RealNe;
  1095. PROCEDURE RealLt;
  1096. (* [gt lt] -> lt: swap, drop. *)
  1097. BEGIN EmitOp(OPswap); EmitOp(OPext); EmitOp(SUBdrop) END RealLt;
  1098. PROCEDURE RealLe;
  1099. (* [gt lt] -> NOT gt: drop, not. *)
  1100. BEGIN EmitOp(OPext); EmitOp(SUBdrop); EmitOp(OPnot) END RealLe;
  1101. PROCEDURE RealGt;
  1102. (* [gt lt] -> gt: drop. *)
  1103. BEGIN EmitOp(OPext); EmitOp(SUBdrop) END RealGt;
  1104. PROCEDURE RealGe;
  1105. (* [gt lt] -> NOT lt: swap, drop, not. *)
  1106. BEGIN
  1107. EmitOp(OPswap); EmitOp(OPext); EmitOp(SUBdrop); EmitOp(OPnot)
  1108. END RealGe;
  1109. PROCEDURE NegInt;
  1110. BEGIN EmitOp(OPimm0); EmitOp(OPswap); EmitOp(OPsub) END NegInt;
  1111. PROCEDURE NegReal;
  1112. BEGIN
  1113. EmitOp(OPimmW); EmitW64(0H);
  1114. EmitOp(OPswap); EmitOp(OPrSub)
  1115. END NegReal;
  1116. PROCEDURE IntToReal;
  1117. BEGIN EmitOp(OPintToLong); EmitOp(OPlongToReal) END IntToReal;
  1118. PROCEDURE Dup;
  1119. BEGIN EmitOp(OPdup) END Dup;
  1120. PROCEDURE Drop;
  1121. BEGIN EmitOp(OPext); EmitOp(SUBdrop) END Drop;
  1122. PROCEDURE Swap;
  1123. BEGIN EmitOp(OPswap) END Swap;
  1124. (* ---------------- composites ---------------- *)
  1125. PROCEDURE IdxScale (lo: INTEGER; elemBytes: CARDINAL);
  1126. BEGIN
  1127. PushInt(lo);
  1128. EmitOp(OPsub);
  1129. PushInt(VAL(INTEGER, elemBytes));
  1130. EmitOp(OPumul);
  1131. EmitOp(OPadd)
  1132. END IdxScale;
  1133. PROCEDURE FieldAdd (offSlots: CARDINAL);
  1134. BEGIN
  1135. IF offSlots = 0 THEN RETURN END;
  1136. PushInt(VAL(INTEGER, offSlots * 8));
  1137. EmitOp(OPadd)
  1138. END FieldAdd;
  1139. PROCEDURE CopyBlock;
  1140. BEGIN EmitOp(30H) END CopyBlock;
  1141. PROCEDURE LoadByte;
  1142. BEGIN
  1143. PushInt(0);
  1144. EmitOp(0DH)
  1145. END LoadByte;
  1146. PROCEDURE StoreByte;
  1147. BEGIN
  1148. PushInt(0);
  1149. EmitOp(OPswap);
  1150. EmitOp(1DH)
  1151. END StoreByte;
  1152. PROCEDURE PushBytes (n: CARDINAL);
  1153. BEGIN PushInt(VAL(INTEGER, n)) END PushBytes;
  1154. PROCEDURE AllocOp;
  1155. BEGIN EmitOp(OPext); EmitOp(05H) END AllocOp;
  1156. PROCEDURE DeallocOp;
  1157. BEGIN EmitOp(OPext); EmitOp(06H) END DeallocOp;
  1158. PROCEDURE BitXor;
  1159. BEGIN EmitOp(0E9H) END BitXor;
  1160. PROCEDURE StrLenOf (s: ARRAY OF CHAR): CARDINAL;
  1161. VAR n: CARDINAL;
  1162. BEGIN
  1163. n := StrLen(s);
  1164. IF n < 2 THEN RETURN 0 END;
  1165. RETURN n - 2
  1166. END StrLenOf;
  1167. PROCEDURE EmitString (s: ARRAY OF CHAR);
  1168. VAR len, i: CARDINAL;
  1169. BEGIN
  1170. len := StrLenOf(s);
  1171. IF len + 1 > 255 THEN
  1172. PushInt(0); RETURN
  1173. END;
  1174. EmitOp(8CH);
  1175. EmitByte(len + 1);
  1176. i := 1;
  1177. WHILE i <= len DO
  1178. EmitByte(ORD(s[i])); INC(i)
  1179. END;
  1180. EmitByte(0)
  1181. END EmitString;
  1182. PROCEDURE StrComp;
  1183. BEGIN EmitOp(0C4H) END StrComp;
  1184. (* ---------------- WITH ---------------- *)
  1185. PROCEDURE WithEnter (typ: INTEGER);
  1186. VAR tmp: INTEGER;
  1187. BEGIN
  1188. tmp := TempGlobal();
  1189. StoreTemp(tmp);
  1190. IF withTop <= 7 THEN
  1191. withTmps[withTop] := tmp;
  1192. withTyps[withTop] := typ;
  1193. INC(withTop)
  1194. END
  1195. END WithEnter;
  1196. PROCEDURE WithExit;
  1197. BEGIN
  1198. IF withTop > 0 THEN DEC(withTop) END
  1199. END WithExit;
  1200. PROCEDURE WithDepth (): CARDINAL;
  1201. BEGIN RETURN withTop END WithDepth;
  1202. PROCEDURE WithAddr (name: ARRAY OF CHAR);
  1203. VAR i: CARDINAL;
  1204. off: INTEGER;
  1205. found: BOOLEAN;
  1206. BEGIN
  1207. found := FALSE;
  1208. i := withTop;
  1209. WHILE (i > 0) & ~found DO
  1210. DEC(i);
  1211. IF SymTab.FieldExists(withTyps[i], name) THEN
  1212. off := SymTab.FieldOffset(withTyps[i], name);
  1213. LoadTemp(withTmps[i]);
  1214. IF off > 0 THEN
  1215. PushInt(VAL(INTEGER, VAL(CARDINAL, off) * 8));
  1216. EmitOp(OPadd)
  1217. ELSIF off < 0 THEN
  1218. PushInt(0)
  1219. END;
  1220. found := TRUE
  1221. END
  1222. END;
  1223. IF ~found THEN PushInt(0) END
  1224. END WithAddr;
  1225. PROCEDURE PrintNum (): CARDINAL;
  1226. BEGIN RETURN maxNum + 1 END PrintNum;
  1227. PROCEDURE CallPrint;
  1228. BEGIN
  1229. EmitOpB(OPprocCall, maxNum + 1);
  1230. EmitOp(OPext); EmitOp(SUBdrop)
  1231. END CallPrint;
  1232. PROCEDURE SysCall;
  1233. BEGIN EmitOp(OPsys) END SysCall;
  1234. (* ---------------- control flow ---------------- *)
  1235. PROCEDURE NewLabel (): INTEGER;
  1236. BEGIN
  1237. IF nLab > MaxLab THEN RETURN 0 END;
  1238. labs[nLab] := -1;
  1239. INC(nLab);
  1240. RETURN VAL(INTEGER, nLab - 1)
  1241. END NewLabel;
  1242. PROCEDURE DefLabel (id: INTEGER);
  1243. VAR i : CARDINAL;
  1244. rel : INTEGER;
  1245. BEGIN
  1246. IF (id < 0) OR (id >= VAL(INTEGER, nLab)) THEN RETURN END;
  1247. labs[id] := VAL(INTEGER, nCode);
  1248. i := 0;
  1249. WHILE i < nFix DO
  1250. IF fixs[i].lab = id THEN
  1251. rel := labs[id] - VAL(INTEGER, fixs[i].pos + 9);
  1252. WriteS64At(fixs[i].pos + 1, rel);
  1253. fixs[i].lab := -1
  1254. END;
  1255. INC(i)
  1256. END
  1257. END DefLabel;
  1258. PROCEDURE Jump (op: CARDINAL; id: INTEGER);
  1259. VAR pos : CARDINAL;
  1260. j : CARDINAL;
  1261. BEGIN
  1262. pos := nCode;
  1263. EmitOp(op);
  1264. IF (id >= 0) & (id < VAL(INTEGER, nLab)) & (labs[id] >= 0) THEN
  1265. EmitS64(labs[id] - VAL(INTEGER, pos + 9))
  1266. ELSE
  1267. FOR j := 0 TO 7 DO EmitByte(0) END;
  1268. IF (nFix <= MaxFix) & (id >= 0) & (id < VAL(INTEGER, nLab)) THEN
  1269. fixs[nFix].pos := pos; fixs[nFix].lab := id; INC(nFix)
  1270. END
  1271. END
  1272. END Jump;
  1273. PROCEDURE Jmp (id: INTEGER);
  1274. BEGIN
  1275. Jump(OPjp, id)
  1276. END Jmp;
  1277. PROCEDURE Jz (id: INTEGER);
  1278. BEGIN
  1279. Jump(OPjz, id)
  1280. END Jz;
  1281. PROCEDURE PushLoop (exit: INTEGER);
  1282. BEGIN
  1283. IF loopTop <= MaxLoop THEN
  1284. loopSt[loopTop] := exit; INC(loopTop)
  1285. END
  1286. END PushLoop;
  1287. PROCEDURE PopLoop;
  1288. BEGIN
  1289. IF loopTop > 0 THEN DEC(loopTop) END
  1290. END PopLoop;
  1291. PROCEDURE TopLoop (VAR exit: INTEGER): BOOLEAN;
  1292. BEGIN
  1293. IF loopTop = 0 THEN RETURN FALSE END;
  1294. exit := loopSt[loopTop - 1];
  1295. RETURN TRUE
  1296. END TopLoop;
  1297. PROCEDURE NoSupEnter;
  1298. BEGIN
  1299. INC(noSup)
  1300. END NoSupEnter;
  1301. PROCEDURE NoSupExit;
  1302. BEGIN
  1303. IF noSup > 0 THEN DEC(noSup) END
  1304. END NoSupExit;
  1305. PROCEDURE NoSup (): BOOLEAN;
  1306. BEGIN
  1307. RETURN noSup > 0
  1308. END NoSup;
  1309. PROCEDURE CopyName (s: ARRAY OF CHAR; VAR d: ARRAY OF CHAR);
  1310. VAR i : CARDINAL;
  1311. BEGIN
  1312. i := 0;
  1313. WHILE (i < HIGH(d)) & (i < HIGH(s)) & (s[i] # 0C) DO
  1314. d[i] := s[i]; INC(i)
  1315. END;
  1316. IF i <= HIGH(d) THEN d[i] := 0C END
  1317. END CopyName;
  1318. PROCEDURE NoEmitEnter;
  1319. BEGIN
  1320. INC(noEmit)
  1321. END NoEmitEnter;
  1322. PROCEDURE NoEmitExit;
  1323. BEGIN
  1324. IF noEmit > 0 THEN DEC(noEmit) END
  1325. END NoEmitExit;
  1326. (* ---------------- image assembly ---------------- *)
  1327. PROCEDURE Put32At (off: CARDINAL; v: CARDINAL);
  1328. BEGIN
  1329. img[off] := CHR(v MOD 256);
  1330. img[off + 1] := CHR((v DIV 256) MOD 256);
  1331. img[off + 2] := CHR((v DIV 65536) MOD 256);
  1332. img[off + 3] := CHR(v DIV 16777216)
  1333. END Put32At;
  1334. PROCEDURE Put64At (off: CARDINAL; v: LONGCARD);
  1335. VAR j : CARDINAL;
  1336. BEGIN
  1337. FOR j := 0 TO 7 DO
  1338. img[off + j] := CHR(VAL(CARDINAL, v MOD 256));
  1339. v := v DIV 256
  1340. END
  1341. END Put64At;
  1342. PROCEDURE EmitPrint;
  1343. (* proc1: prints the CARDINAL parameter as decimal + CRLF.
  1344. Uses global temps 0..3 (buffer, count, index, char). *)
  1345. VAR l1, l2 : INTEGER;
  1346. BEGIN
  1347. EmitOpB(OPenter, 250);
  1348. EmitOpB(OPimmB, 16); EmitOp(0D2H); EmitOpB(OPstoreGlb, 0);
  1349. EmitOp(OPimm0); EmitOp(OPimm0);
  1350. EmitOpB(OPstoreGlb, 1); EmitOpB(OPstoreGlb, 2);
  1351. EmitOp(03H);
  1352. l1 := NewLabel(); DefLabel(l1);
  1353. EmitOpB(OPloadGlb, 1); EmitOp(OPinc); EmitOpB(OPstoreGlb, 1);
  1354. EmitOp(OPdup); EmitOpB(OPimmB, 10); EmitOp(OPumod);
  1355. EmitOp(OPswap); EmitOpB(OPimmB, 10); EmitOp(OPudiv);
  1356. EmitOp(OPdup); EmitOp(OPaeq0);
  1357. Jz(l1);
  1358. EmitOp(OPext); EmitOp(SUBdrop);
  1359. l2 := NewLabel(); DefLabel(l2);
  1360. EmitOpB(OPimmB, 48); EmitOp(OPadd); EmitOpB(OPstoreGlb, 3);
  1361. EmitOpB(OPloadGlb, 0); EmitOpB(OPloadGlb, 2); EmitOp(OPadd);
  1362. EmitOp(OPimm0); EmitOpB(OPloadGlb, 3); EmitOp(1DH);
  1363. EmitOpB(OPloadGlb, 2); EmitOp(OPinc); EmitOpB(OPstoreGlb, 2);
  1364. EmitOpB(OPloadGlb, 1); EmitOp(OPdec); EmitOpB(OPstoreGlb, 1);
  1365. EmitOpB(OPloadGlb, 1); EmitOp(OPaeq0);
  1366. Jz(l2);
  1367. EmitOpB(OPloadGlb, 0); EmitOpB(OPloadGlb, 2); EmitOp(OPadd);
  1368. EmitOp(OPimm0); EmitOp(OPimm0); EmitOp(1DH);
  1369. EmitOpB(OPloadGlb, 0);
  1370. EmitOpB(OPimmB, 1); EmitOp(OPsys);
  1371. EmitOpB(OPimmB, 3); EmitOp(0D2H);
  1372. EmitOp(OPdup); EmitOp(OPimm0); EmitOpB(OPimmB, 13); EmitOp(1DH);
  1373. EmitOp(OPdup); EmitOpB(OPimmB, 1); EmitOpB(OPimmB, 10); EmitOp(1DH);
  1374. EmitOp(OPdup); EmitOpB(OPimmB, 2); EmitOp(OPimm0); EmitOp(1DH);
  1375. EmitOpB(OPimmB, 1); EmitOp(OPsys);
  1376. EmitOpB(OPfctLeave, 0)
  1377. END EmitPrint;
  1378. PROCEDURE PutS64At (off, addr, slot: CARDINAL);
  1379. (* Procedure-table cell: signed (addr - slot). *)
  1380. VAR mag : LONGCARD;
  1381. bits : LONGCARD;
  1382. j : CARDINAL;
  1383. BEGIN
  1384. IF addr >= slot THEN bits := VAL(LONGCARD, addr - slot)
  1385. ELSE
  1386. mag := VAL(LONGCARD, slot - addr);
  1387. bits := 0FFFFFFFFFFFFFFFFH - mag + 1H
  1388. END;
  1389. FOR j := 0 TO 7 DO
  1390. img[off + j] := CHR(VAL(CARDINAL, bits MOD 256));
  1391. bits := bits DIV 256
  1392. END
  1393. END PutS64At;
  1394. PROCEDURE EndModule;
  1395. VAR i : CARDINAL;
  1396. codeOff, p1, pt, prNum, tabBytes : CARDINAL;
  1397. k : CARDINAL;
  1398. addr : CARDINAL;
  1399. exitIdx : INTEGER;
  1400. sum : CARDINAL;
  1401. fname : ARRAY [0 .. 127] OF CHAR;
  1402. f : FileIO.File;
  1403. ch : CHAR;
  1404. BEGIN
  1405. IF ~inBody THEN mainAddr := nCode END;
  1406. prNum := maxNum + 1;
  1407. (* epilogue: print ExitCode when the convention applies *)
  1408. exitIdx := -1;
  1409. IF SymTab.Lookup("ExitCode")
  1410. & (SymTab.SymKind("ExitCode") = SymTab.KindVar)
  1411. & SymTab.IsIntFamily(SymTab.SymType("ExitCode")) THEN
  1412. exitIdx := FindVar("ExitCode")
  1413. END;
  1414. IF exitIdx >= 0 THEN
  1415. EmitOpB(OPloadGlb, VAL(CARDINAL, exitIdx));
  1416. EmitOpB(OPprocCall, prNum);
  1417. EmitOp(OPext); EmitOp(SUBdrop)
  1418. END;
  1419. EmitOp(OPend);
  1420. p1 := nCode;
  1421. EmitPrint;
  1422. (* assemble the image *)
  1423. i := 0;
  1424. WHILE i <= MaxImg DO img[i] := 0C; INC(i) END;
  1425. img[0] := "M"; img[1] := "C"; img[2] := "6"; img[3] := "4";
  1426. i := 0;
  1427. WHILE (i < 16) & (modName[i] # 0C) DO
  1428. img[HeadSize + DName + i] := modName[i]; INC(i)
  1429. END;
  1430. img[HeadSize + DFlags] := CHR(4);
  1431. img[HeadSize + DVarCount] := CHR(nVars MOD 256);
  1432. img[HeadSize + DDepCount] := 0C;
  1433. codeOff := DVarSizes + nVars * 8;
  1434. i := 0;
  1435. WHILE i < nCode DO
  1436. img[HeadSize + codeOff + i] := code[i]; INC(i)
  1437. END;
  1438. pt := codeOff + nCode;
  1439. tabBytes := (maxNum + 2) * 8;
  1440. Put64At(HeadSize + DProcs, VAL(LONGCARD, pt));
  1441. k := 0;
  1442. WHILE k <= maxNum + 1 DO
  1443. IF k = 0 THEN addr := codeOff + mainAddr
  1444. ELSIF k <= maxNum THEN
  1445. IF procAddr[k] < 0 THEN addr := pt + k * 8
  1446. ELSE addr := VAL(CARDINAL, procAddr[k]) + codeOff
  1447. END
  1448. ELSE addr := codeOff + p1
  1449. END;
  1450. PutS64At(HeadSize + pt + k * 8, addr, pt + k * 8);
  1451. INC(k)
  1452. END;
  1453. i := 0;
  1454. WHILE i < nVars DO
  1455. Put64At(HeadSize + DVarSizes + i * 8,
  1456. VAL(LONGCARD, vSize[i] * 8));
  1457. INC(i)
  1458. END;
  1459. sum := 0;
  1460. i := HeadSize;
  1461. WHILE i < HeadSize + pt + tabBytes DO
  1462. IF ~((i >= 352) & (i <= 355)) THEN
  1463. sum := sum + ORD(img[i])
  1464. END;
  1465. INC(i)
  1466. END;
  1467. Put32At(HeadSize + DChecksum, sum);
  1468. fname[0] := 0C;
  1469. StrCpy(fname, modName);
  1470. i := StrLen(fname);
  1471. fname[i] := "."; fname[i + 1] := "M"; fname[i + 2] := "C";
  1472. fname[i + 3] := "4"; fname[i + 4] := 0C;
  1473. FileIO.Open(f, fname, TRUE);
  1474. IF FileIO.Okay THEN
  1475. i := 0;
  1476. WHILE i < HeadSize + pt + tabBytes DO
  1477. ch := img[i];
  1478. FileIO.Write(f, ch);
  1479. INC(i)
  1480. END;
  1481. FileIO.Close(f)
  1482. END
  1483. END EndModule;
  1484. BEGIN
  1485. nCode := 0; nGlb := 0; nVars := 0; nInit := 0;
  1486. nLab := 0; nFix := 0; loopTop := 0; noSup := 0; noEmit := 0;
  1487. actTop := 0; withTop := 0;
  1488. maxNum := 0; mainAddr := 0;
  1489. inBody := FALSE;
  1490. modName[0] := 0C
  1491. END MGen.