IL.ob07 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201
  1. (*
  2. BSD 2-Clause License
  3. Copyright (c) 2018-2023, Anton Krotov
  4. All rights reserved.
  5. *)
  6. MODULE IL;
  7. IMPORT LISTS, SCAN, STRINGS, CHL := CHUNKLISTS, C := COLLECTIONS, TARGETS, PATHS;
  8. CONST
  9. call_stack* = 0;
  10. call_win64* = 1;
  11. call_sysv* = 2;
  12. call_fast1* = 3;
  13. call_fast2* = 4;
  14. begin_loop* = 1; end_loop* = 2;
  15. opJMP* = 0; opLABEL* = 1; opCOPYS* = 2; opGADR* = 3; opCONST* = 4; opLLOAD32* = 5;
  16. opCOPYA* = 6; opCASET* = 7; opMULC* = 8; opMUL* = 9; opDIV* = 10; opMOD* = 11;
  17. opDIVL* = 12; opMODL* = 13; opDIVR* = 14; opMODR* = 15; opUMINUS* = 16;
  18. opADD* = 17; opSUB* = 18; opONERR* = 19; opSUBL* = 20; opADDC* = 21; opSUBR* = 22;
  19. opSAVE* = 23; opSAVEC* = 24; opSAVE8* = 25; opSAVE8C* = 26; (*opCHKBYTE* = 27;*) opDROP* = 28;
  20. opNOT* = 29;
  21. opEQ* = 30; opNE* = opEQ + 1; opLT* = opEQ + 2; opLE* = opEQ + 3; opGT* = opEQ + 4; opGE* = opEQ + 5 (* 35 *);
  22. opEQC* = 36; opNEC* = opEQC + 1; opLTC* = opEQC + 2; opLEC* = opEQC + 3; opGTC* = opEQC + 4; opGEC* = opEQC + 5; (* 41 *)
  23. opEQF* = 42; opNEF* = opEQF + 1; opLTF* = opEQF + 2; opLEF* = opEQF + 3; opGTF* = opEQF + 4; opGEF* = opEQF + 5; (* 47 *)
  24. opEQS* = 48; opNES* = opEQS + 1; opLTS* = opEQS + 2; opLES* = opEQS + 3; opGTS* = opEQS + 4; opGES* = opEQS + 5; (* 53 *)
  25. opEQSW* = 54; opNESW* = opEQSW + 1; opLTSW* = opEQSW + 2; opLESW* = opEQSW + 3; opGTSW* = opEQSW + 4; opGESW* = opEQSW + 5 (* 59 *);
  26. opVLOAD32* = 60; opGLOAD32* = 61;
  27. opJZ* = 62; opJNZ* = 63;
  28. opSAVE32* = 64; opLLOAD8* = 65;
  29. opCONSTF* = 66; opLOADF* = 67; opSAVEF* = 68; opMULF* = 69; opDIVF* = 70; opDIVFI* = 71;
  30. opUMINF* = 72; opSAVEFI* = 73; opSUBFI* = 74; opADDF* = 75; opSUBF* = 76;
  31. opJNZ1* = 77; opJG* = 78;
  32. opINCCB* = 79; opDECCB* = 80; opINCB* = 81; opDECB* = 82;
  33. opCASEL* = 83; opCASER* = 84; opCASELR* = 85;
  34. opPOPSP* = 86;
  35. opWIN64CALL* = 87; opWIN64CALLI* = 88; opWIN64CALLP* = 89; opAND* = 90; opOR* = 91;
  36. opLOAD8* = 92; opLOAD16* = 93; opLOAD32* = 94; opPRECALL* = 95; opRES* = 96; opRESF* = 97;
  37. opPUSHC* = 98; opSWITCH* = 99;
  38. opSBOOL* = 100; opSBOOLC* = 101; opNOP* = 102;
  39. opMULS* = 103; opMULSC* = 104; opDIVS* = 105; opDIVSC* = 106;
  40. opADDS* = 107; opSUBS* = 108; opERR* = 109; opSUBSL* = 110; opADDSC* = 111; opSUBSR* = 112;
  41. opUMINS* = 113; opIN* = 114; opINL* = 115; opINR* = 116;
  42. opRSET* = 117; opRSETL* = 118; opRSETR* = 119; opRSET1* = 120; opLENGTH* = 121;
  43. opLEAVEC* = 122; opCODE* = 123; opALIGN16* = 124;
  44. opINCC* = 125; opINC* = 126; opDEC* = 127;
  45. opINCL* = 128; opEXCL* = 129; opINCLC* = 130; opEXCLC* = 131; opNEW* = 132; opDISP* = 133;
  46. opPACK* = 134; opPACKC* = 135; opUNPK* = 136; opCOPY* = 137; opENTER* = 138; opLEAVE* = 139;
  47. opCALL* = 140; opSAVEP* = 141; opCALLP* = 142; opEQP* = 143; opNEP* = 144; opLEAVER* = 145;
  48. opGET* = 146; opSAVE16* = 147; opABS* = 148; opFABS* = 149; opFLOOR* = 150; opFLT* = 151;
  49. opGETC* = 152; opORD* = 153; opASR* = 154; opLSL* = 155; opROR* = 156;
  50. opASR1* = 157; opLSL1* = 158; opROR1* = 159; opASR2* = 160; opLSL2* = 161; opROR2* = 162;
  51. opPUSHP* = 163; opLADR* = 164; opTYPEGP* = 165; opIS* = 166; opPUSHF* = 167; opVADR* = 168;
  52. opPUSHT* = 169; opTYPEGR* = 170; opISREC* = 171; opCHKIDX* = 172; opPARAM* = 173;
  53. opCHKIDX2* = 174; opLEN* = 175; opROT* = 176; opSAVES* = 177; opSADR* = 178; opLENGTHW* = 179;
  54. (*opCHR* = 180;*) opENDSW* = 181; opLEAVEF* = 182; opCLEANUP* = 183; opMOVE* = 184;
  55. opLSR* = 185; opLSR1* = 186; opLSR2* = 187;
  56. opMIN* = 188; opMINC* = 189; opMAX* = 190; opMAXC* = 191; opSYSVALIGN16* = 192;
  57. opEQB* = 193; opNEB* = 194; opINF* = 195; opWIN64ALIGN16* = 196; opVLOAD8* = 197; opGLOAD8* = 198;
  58. opLLOAD16* = 199; opVLOAD16* = 200; opGLOAD16* = 201;
  59. opLOAD64* = 202; opLLOAD64* = 203; opVLOAD64* = 204; opGLOAD64* = 205; opSAVE64* = 206;
  60. opTYPEGD* = 207; opCALLI* = 208; opPUSHIP* = 209; opSAVEIP* = 210; opEQIP* = 211; opNEIP* = 212;
  61. opSAVE16C* = 213; (*opWCHR* = 214;*) opHANDLER* = 215;
  62. opSYSVCALL* = 216; opSYSVCALLI* = 217; opSYSVCALLP* = 218; opFNAME* = 219; opFASTCALL* = 220;
  63. opSADR_PARAM* = -1; opLOAD64_PARAM* = -2; opLLOAD64_PARAM* = -3; opGLOAD64_PARAM* = -4;
  64. opVADR_PARAM* = -5; opCONST_PARAM* = -6; opGLOAD32_PARAM* = -7; opLLOAD32_PARAM* = -8;
  65. opLOAD32_PARAM* = -9;
  66. opLADR_SAVEC* = -10; opGADR_SAVEC* = -11; opLADR_SAVE* = -12;
  67. opLADR_INCC* = -13; opLADR_INCCB* = -14; opLADR_DECCB* = -15;
  68. opLADR_INC* = -16; opLADR_DEC* = -17; opLADR_INCB* = -18; opLADR_DECB* = -19;
  69. opLADR_INCL* = -20; opLADR_EXCL* = -21; opLADR_INCLC* = -22; opLADR_EXCLC* = -23;
  70. opLADR_UNPK* = -24;
  71. _init *= 0;
  72. _move *= 1;
  73. _strcmpw *= 2;
  74. _exit *= 3;
  75. _set *= 4;
  76. _set1 *= 5;
  77. _lengthw *= 6;
  78. _strcpy *= 7;
  79. _length *= 8;
  80. _divmod *= 9;
  81. _dllentry *= 10;
  82. _sofinit *= 11;
  83. _arrcpy *= 12;
  84. _rot *= 13;
  85. _new *= 14;
  86. _dispose *= 15;
  87. _strcmp *= 16;
  88. _error *= 17;
  89. _is *= 18;
  90. _isrec *= 19;
  91. _guard *= 20;
  92. _guardrec *= 21;
  93. _fmul *= 22;
  94. _fdiv *= 23;
  95. _fdivi *= 24;
  96. _fadd *= 25;
  97. _fsub *= 26;
  98. _fsubi *= 27;
  99. _fcmp *= 28;
  100. _floor *= 29;
  101. _flt *= 30;
  102. _pack *= 31;
  103. _unpk *= 32;
  104. TYPE
  105. COMMAND* = POINTER TO RECORD (LISTS.ITEM)
  106. opcode*: INTEGER;
  107. param1*: INTEGER;
  108. param2*: INTEGER;
  109. param3*: INTEGER;
  110. float*: REAL
  111. END;
  112. FNAMECMD* = POINTER TO RECORD (COMMAND)
  113. fname*: PATHS.PATH
  114. END;
  115. CMDSTACK = POINTER TO RECORD
  116. data: ARRAY 1000 OF COMMAND;
  117. top: INTEGER
  118. END;
  119. EXPORT_PROC* = POINTER TO RECORD (LISTS.ITEM)
  120. label*: INTEGER;
  121. name*: SCAN.IDSTR
  122. END;
  123. IMPORT_LIB* = POINTER TO RECORD (LISTS.ITEM)
  124. name*: SCAN.TEXTSTR;
  125. procs*: LISTS.LIST
  126. END;
  127. IMPORT_PROC* = POINTER TO RECORD (LISTS.ITEM)
  128. label*: INTEGER;
  129. lib*: IMPORT_LIB;
  130. name*: SCAN.TEXTSTR;
  131. count: INTEGER
  132. END;
  133. CODES = RECORD
  134. last: COMMAND;
  135. begcall: CMDSTACK;
  136. endcall: CMDSTACK;
  137. commands*: LISTS.LIST;
  138. export*: LISTS.LIST;
  139. _import*: LISTS.LIST;
  140. types*: CHL.INTLIST;
  141. data*: CHL.BYTELIST;
  142. dmin*: INTEGER;
  143. lcount*: INTEGER;
  144. bss*: INTEGER;
  145. rtl*: ARRAY 33 OF INTEGER;
  146. errlabels*: ARRAY 12 OF INTEGER;
  147. charoffs: ARRAY 256 OF INTEGER;
  148. wcharoffs: ARRAY 65536 OF INTEGER;
  149. wstr: ARRAY 4*1024 OF WCHAR
  150. END;
  151. VAR
  152. codes*: CODES;
  153. CPU: INTEGER;
  154. commands: C.COLLECTION;
  155. PROCEDURE set_dmin* (value: INTEGER);
  156. BEGIN
  157. codes.dmin := value
  158. END set_dmin;
  159. PROCEDURE set_bss* (value: INTEGER);
  160. BEGIN
  161. codes.bss := value
  162. END set_bss;
  163. PROCEDURE set_rtl* (idx, label: INTEGER);
  164. BEGIN
  165. codes.rtl[idx] := label
  166. END set_rtl;
  167. PROCEDURE NewCmd (): COMMAND;
  168. VAR
  169. cmd: COMMAND;
  170. citem: C.ITEM;
  171. BEGIN
  172. citem := C.pop(commands);
  173. IF citem = NIL THEN
  174. NEW(cmd)
  175. ELSE
  176. cmd := citem(COMMAND)
  177. END
  178. RETURN cmd
  179. END NewCmd;
  180. PROCEDURE setlast* (cmd: COMMAND);
  181. BEGIN
  182. codes.last := cmd
  183. END setlast;
  184. PROCEDURE getlast* (): COMMAND;
  185. RETURN codes.last
  186. END getlast;
  187. PROCEDURE PutByte (b: BYTE);
  188. BEGIN
  189. CHL.PushByte(codes.data, b)
  190. END PutByte;
  191. PROCEDURE AlignData (n: INTEGER);
  192. BEGIN
  193. WHILE CHL.Length(codes.data) MOD n # 0 DO
  194. PutByte(0)
  195. END
  196. END AlignData;
  197. PROCEDURE putstr* (s: ARRAY OF CHAR): INTEGER;
  198. VAR
  199. i, n, res: INTEGER;
  200. BEGIN
  201. IF TARGETS.WinLin THEN
  202. AlignData(16)
  203. END;
  204. res := CHL.Length(codes.data);
  205. i := 0;
  206. n := LENGTH(s);
  207. WHILE i < n DO
  208. PutByte(ORD(s[i]));
  209. INC(i)
  210. END;
  211. PutByte(0)
  212. RETURN res
  213. END putstr;
  214. PROCEDURE putstr1* (c: INTEGER): INTEGER;
  215. VAR
  216. res: INTEGER;
  217. BEGIN
  218. IF codes.charoffs[c] = -1 THEN
  219. IF TARGETS.WinLin THEN
  220. AlignData(16)
  221. END;
  222. res := CHL.Length(codes.data);
  223. PutByte(c);
  224. PutByte(0);
  225. codes.charoffs[c] := res
  226. ELSE
  227. res := codes.charoffs[c]
  228. END
  229. RETURN res
  230. END putstr1;
  231. PROCEDURE putstrW* (s: ARRAY OF CHAR): INTEGER;
  232. VAR
  233. i, n, res: INTEGER;
  234. BEGIN
  235. IF TARGETS.WinLin THEN
  236. AlignData(16)
  237. ELSE
  238. AlignData(2)
  239. END;
  240. res := CHL.Length(codes.data);
  241. n := STRINGS.Utf8To16(s, codes.wstr);
  242. i := 0;
  243. WHILE i < n DO
  244. IF TARGETS.LittleEndian THEN
  245. PutByte(ORD(codes.wstr[i]) MOD 256);
  246. PutByte(ORD(codes.wstr[i]) DIV 256)
  247. ELSE
  248. PutByte(ORD(codes.wstr[i]) DIV 256);
  249. PutByte(ORD(codes.wstr[i]) MOD 256)
  250. END;
  251. INC(i)
  252. END;
  253. PutByte(0);
  254. PutByte(0)
  255. RETURN res
  256. END putstrW;
  257. PROCEDURE putstrW1* (c: INTEGER): INTEGER;
  258. VAR
  259. res: INTEGER;
  260. BEGIN
  261. IF codes.wcharoffs[c] = -1 THEN
  262. IF TARGETS.WinLin THEN
  263. AlignData(16)
  264. ELSE
  265. AlignData(2)
  266. END;
  267. res := CHL.Length(codes.data);
  268. IF TARGETS.LittleEndian THEN
  269. PutByte(c MOD 256);
  270. PutByte(c DIV 256)
  271. ELSE
  272. PutByte(c DIV 256);
  273. PutByte(c MOD 256)
  274. END;
  275. PutByte(0);
  276. PutByte(0);
  277. codes.wcharoffs[c] := res
  278. ELSE
  279. res := codes.wcharoffs[c]
  280. END
  281. RETURN res
  282. END putstrW1;
  283. PROCEDURE push (stk: CMDSTACK; cmd: COMMAND);
  284. BEGIN
  285. INC(stk.top);
  286. stk.data[stk.top] := cmd
  287. END push;
  288. PROCEDURE pop (stk: CMDSTACK): COMMAND;
  289. VAR
  290. res: COMMAND;
  291. BEGIN
  292. res := stk.data[stk.top];
  293. DEC(stk.top)
  294. RETURN res
  295. END pop;
  296. PROCEDURE pushBegEnd* (VAR beg, _end: COMMAND);
  297. BEGIN
  298. push(codes.begcall, beg);
  299. push(codes.endcall, _end);
  300. beg := codes.last;
  301. _end := beg.next(COMMAND)
  302. END pushBegEnd;
  303. PROCEDURE popBegEnd* (VAR beg, _end: COMMAND);
  304. BEGIN
  305. beg := pop(codes.begcall);
  306. _end := pop(codes.endcall)
  307. END popBegEnd;
  308. PROCEDURE AddRec* (base: INTEGER);
  309. BEGIN
  310. CHL.PushInt(codes.types, base)
  311. END AddRec;
  312. PROCEDURE insert (cur, nov: COMMAND);
  313. VAR
  314. old_opcode, param2: INTEGER;
  315. PROCEDURE set (cur: COMMAND; opcode, param2: INTEGER);
  316. BEGIN
  317. cur.opcode := opcode;
  318. cur.param1 := cur.param2;
  319. cur.param2 := param2
  320. END set;
  321. BEGIN
  322. IF CPU IN {TARGETS.cpuX86, TARGETS.cpuAMD64, TARGETS.cpuMSP430} THEN
  323. old_opcode := cur.opcode;
  324. param2 := nov.param2;
  325. IF (nov.opcode = opPARAM) & (param2 = 1) THEN
  326. CASE old_opcode OF
  327. |opGLOAD64: cur.opcode := opGLOAD64_PARAM
  328. |opLLOAD64: cur.opcode := opLLOAD64_PARAM
  329. |opLOAD64: cur.opcode := opLOAD64_PARAM
  330. |opGLOAD32: cur.opcode := opGLOAD32_PARAM
  331. |opLLOAD32: cur.opcode := opLLOAD32_PARAM
  332. |opLOAD32: cur.opcode := opLOAD32_PARAM
  333. |opSADR: cur.opcode := opSADR_PARAM
  334. |opVADR: cur.opcode := opVADR_PARAM
  335. |opCONST: cur.opcode := opCONST_PARAM
  336. ELSE
  337. old_opcode := -1
  338. END
  339. ELSIF old_opcode = opLADR THEN
  340. CASE nov.opcode OF
  341. |opSAVEC: set(cur, opLADR_SAVEC, param2)
  342. |opSAVE: cur.opcode := opLADR_SAVE
  343. |opINC: cur.opcode := opLADR_INC
  344. |opDEC: cur.opcode := opLADR_DEC
  345. |opINCB: cur.opcode := opLADR_INCB
  346. |opDECB: cur.opcode := opLADR_DECB
  347. |opINCL: cur.opcode := opLADR_INCL
  348. |opEXCL: cur.opcode := opLADR_EXCL
  349. |opUNPK: cur.opcode := opLADR_UNPK
  350. |opINCC: set(cur, opLADR_INCC, param2)
  351. |opINCCB: set(cur, opLADR_INCCB, param2)
  352. |opDECCB: set(cur, opLADR_DECCB, param2)
  353. |opINCLC: set(cur, opLADR_INCLC, param2)
  354. |opEXCLC: set(cur, opLADR_EXCLC, param2)
  355. ELSE
  356. old_opcode := -1
  357. END
  358. ELSIF (nov.opcode = opSAVEC) & (old_opcode = opGADR) THEN
  359. set(cur, opGADR_SAVEC, param2)
  360. ELSIF (nov.opcode = opMULC) & (old_opcode = opMULC) THEN
  361. cur.param2 := cur.param2 * param2
  362. ELSIF (nov.opcode = opADDC) & (old_opcode = opADDC) THEN
  363. INC(cur.param2, param2)
  364. ELSE
  365. old_opcode := -1
  366. END
  367. ELSIF CPU IN {TARGETS.cpuTHUMB, TARGETS.cpuRVM32I, TARGETS.cpuRVM64I} THEN
  368. old_opcode := cur.opcode;
  369. param2 := nov.param2;
  370. IF (old_opcode = opLADR) & (nov.opcode = opSAVE) THEN
  371. cur.opcode := opLADR_SAVE
  372. ELSIF (old_opcode = opLADR) & (nov.opcode = opINCC) THEN
  373. set(cur, opLADR_INCC, param2)
  374. ELSIF (nov.opcode = opMULC) & (old_opcode = opMULC) THEN
  375. cur.param2 := cur.param2 * param2
  376. ELSIF (nov.opcode = opADDC) & (old_opcode = opADDC) THEN
  377. INC(cur.param2, param2)
  378. ELSE
  379. old_opcode := -1
  380. END
  381. ELSE
  382. old_opcode := -1
  383. END;
  384. IF old_opcode = -1 THEN
  385. LISTS.insert(codes.commands, cur, nov);
  386. codes.last := nov
  387. ELSE
  388. C.push(commands, nov);
  389. codes.last := cur
  390. END
  391. END insert;
  392. PROCEDURE AddCmd* (opcode: INTEGER; param: INTEGER);
  393. VAR
  394. cmd: COMMAND;
  395. BEGIN
  396. cmd := NewCmd();
  397. cmd.opcode := opcode;
  398. cmd.param1 := 0;
  399. cmd.param2 := param;
  400. insert(codes.last, cmd)
  401. END AddCmd;
  402. PROCEDURE AddCmd2* (opcode: INTEGER; param1, param2: INTEGER);
  403. VAR
  404. cmd: COMMAND;
  405. BEGIN
  406. cmd := NewCmd();
  407. cmd.opcode := opcode;
  408. cmd.param1 := param1;
  409. cmd.param2 := param2;
  410. insert(codes.last, cmd)
  411. END AddCmd2;
  412. PROCEDURE Const* (val: INTEGER);
  413. BEGIN
  414. AddCmd(opCONST, val)
  415. END Const;
  416. PROCEDURE StrAdr* (adr: INTEGER);
  417. BEGIN
  418. AddCmd(opSADR, adr)
  419. END StrAdr;
  420. PROCEDURE Param1*;
  421. BEGIN
  422. AddCmd(opPARAM, 1)
  423. END Param1;
  424. PROCEDURE NewLabel* (): INTEGER;
  425. BEGIN
  426. INC(codes.lcount)
  427. RETURN codes.lcount - 1
  428. END NewLabel;
  429. PROCEDURE SetLabel* (label: INTEGER);
  430. BEGIN
  431. AddCmd2(opLABEL, label, 0)
  432. END SetLabel;
  433. PROCEDURE SetErrLabel* (errno: INTEGER);
  434. BEGIN
  435. codes.errlabels[errno] := NewLabel();
  436. SetLabel(codes.errlabels[errno])
  437. END SetErrLabel;
  438. PROCEDURE AddCmd0* (opcode: INTEGER);
  439. BEGIN
  440. AddCmd(opcode, 0)
  441. END AddCmd0;
  442. PROCEDURE delete (cmd: COMMAND);
  443. BEGIN
  444. LISTS.delete(codes.commands, cmd);
  445. C.push(commands, cmd)
  446. END delete;
  447. PROCEDURE delete2* (first, last: LISTS.ITEM);
  448. VAR
  449. cur, next: LISTS.ITEM;
  450. BEGIN
  451. cur := first;
  452. IF first # last THEN
  453. REPEAT
  454. next := cur.next;
  455. LISTS.delete(codes.commands, cur);
  456. C.push(commands, cur);
  457. cur := next
  458. UNTIL cur = last
  459. END;
  460. LISTS.delete(codes.commands, cur);
  461. C.push(commands, cur)
  462. END delete2;
  463. PROCEDURE Jmp* (opcode: INTEGER; label: INTEGER);
  464. VAR
  465. prev: COMMAND;
  466. not: BOOLEAN;
  467. BEGIN
  468. prev := codes.last;
  469. not := prev.opcode = opNOT;
  470. IF not THEN
  471. IF opcode = opJNZ THEN
  472. opcode := opJZ
  473. ELSIF opcode = opJZ THEN
  474. opcode := opJNZ
  475. ELSE
  476. not := FALSE
  477. END
  478. END;
  479. AddCmd2(opcode, label, label);
  480. IF not THEN
  481. delete(prev)
  482. END
  483. END Jmp;
  484. PROCEDURE AndOrOpt* (VAR label: INTEGER);
  485. VAR
  486. cur, prev: COMMAND;
  487. i, op, l: INTEGER;
  488. jz, not: BOOLEAN;
  489. BEGIN
  490. cur := codes.last;
  491. not := cur.opcode = opNOT;
  492. IF not THEN
  493. cur := cur.prev(COMMAND)
  494. END;
  495. IF cur.opcode = opAND THEN
  496. op := opAND
  497. ELSIF cur.opcode = opOR THEN
  498. op := opOR
  499. ELSE
  500. op := -1
  501. END;
  502. cur := codes.last;
  503. IF op # -1 THEN
  504. IF not THEN
  505. IF op = opAND THEN
  506. op := opOR
  507. ELSE (* op = opOR *)
  508. op := opAND
  509. END;
  510. prev := cur.prev(COMMAND);
  511. delete(cur);
  512. cur := prev
  513. END;
  514. FOR i := 1 TO 9 DO
  515. IF i = 8 THEN
  516. l := cur.param1
  517. ELSIF i = 9 THEN
  518. jz := cur.opcode = opJZ
  519. END;
  520. prev := cur.prev(COMMAND);
  521. delete(cur);
  522. cur := prev
  523. END;
  524. setlast(cur);
  525. IF op = opAND THEN
  526. label := l;
  527. jz := ~jz
  528. END;
  529. IF jz THEN
  530. Jmp(opJZ, label)
  531. ELSE
  532. Jmp(opJNZ, label)
  533. END;
  534. IF op = opOR THEN
  535. SetLabel(l)
  536. END
  537. ELSE
  538. Jmp(opJZ, label)
  539. END;
  540. setlast(codes.last)
  541. END AndOrOpt;
  542. PROCEDURE OnError* (line, error: INTEGER);
  543. BEGIN
  544. AddCmd2(opONERR, codes.errlabels[error], line)
  545. END OnError;
  546. PROCEDURE TypeGuard* (op, t: INTEGER; line, error: INTEGER);
  547. VAR
  548. label: INTEGER;
  549. BEGIN
  550. AddCmd(op, t);
  551. label := NewLabel();
  552. Jmp(opJNZ, label);
  553. OnError(line, error);
  554. SetLabel(label)
  555. END TypeGuard;
  556. PROCEDURE TypeCheck* (t: INTEGER);
  557. BEGIN
  558. AddCmd(opIS, t)
  559. END TypeCheck;
  560. PROCEDURE TypeCheckRec* (t: INTEGER);
  561. BEGIN
  562. AddCmd(opISREC, t)
  563. END TypeCheckRec;
  564. PROCEDURE New* (size, typenum: INTEGER);
  565. BEGIN
  566. AddCmd2(opNEW, typenum, size)
  567. END New;
  568. PROCEDURE not*;
  569. VAR
  570. prev: COMMAND;
  571. BEGIN
  572. prev := codes.last;
  573. IF prev.opcode = opNOT THEN
  574. codes.last := prev.prev(COMMAND);
  575. delete(prev)
  576. ELSE
  577. AddCmd0(opNOT)
  578. END
  579. END not;
  580. PROCEDURE _ord*;
  581. BEGIN
  582. IF (codes.last.opcode # opAND) & (codes.last.opcode # opOR) THEN
  583. AddCmd0(opORD)
  584. END
  585. END _ord;
  586. PROCEDURE Enter* (label, params: INTEGER): COMMAND;
  587. VAR
  588. cmd: COMMAND;
  589. BEGIN
  590. cmd := NewCmd();
  591. cmd.opcode := opENTER;
  592. cmd.param1 := label;
  593. cmd.param3 := params;
  594. insert(codes.last, cmd)
  595. RETURN codes.last
  596. END Enter;
  597. PROCEDURE Leave* (result, float: BOOLEAN; locsize, paramsize: INTEGER): COMMAND;
  598. BEGIN
  599. IF result THEN
  600. IF float THEN
  601. AddCmd2(opLEAVEF, locsize, paramsize)
  602. ELSE
  603. AddCmd2(opLEAVER, locsize, paramsize)
  604. END
  605. ELSE
  606. AddCmd2(opLEAVE, locsize, paramsize)
  607. END
  608. RETURN codes.last
  609. END Leave;
  610. PROCEDURE EnterC* (label: INTEGER): COMMAND;
  611. BEGIN
  612. SetLabel(label)
  613. RETURN codes.last
  614. END EnterC;
  615. PROCEDURE LeaveC* (): COMMAND;
  616. BEGIN
  617. AddCmd0(opLEAVEC)
  618. RETURN codes.last
  619. END LeaveC;
  620. PROCEDURE fastcall (VAR callconv: INTEGER);
  621. BEGIN
  622. IF callconv = call_fast1 THEN
  623. AddCmd(opFASTCALL, 1);
  624. callconv := call_stack
  625. ELSIF callconv = call_fast2 THEN
  626. AddCmd(opFASTCALL, 2);
  627. callconv := call_stack
  628. END
  629. END fastcall;
  630. PROCEDURE Call* (proc, callconv, fparams: INTEGER);
  631. BEGIN
  632. fastcall(callconv);
  633. CASE callconv OF
  634. |call_stack: Jmp(opCALL, proc)
  635. |call_win64: Jmp(opWIN64CALL, proc)
  636. |call_sysv: Jmp(opSYSVCALL, proc)
  637. END;
  638. codes.last(COMMAND).param2 := fparams
  639. END Call;
  640. PROCEDURE CallImp* (proc: LISTS.ITEM; callconv, fparams: INTEGER);
  641. BEGIN
  642. fastcall(callconv);
  643. CASE callconv OF
  644. |call_stack: Jmp(opCALLI, proc(IMPORT_PROC).label)
  645. |call_win64: Jmp(opWIN64CALLI, proc(IMPORT_PROC).label)
  646. |call_sysv: Jmp(opSYSVCALLI, proc(IMPORT_PROC).label)
  647. END;
  648. codes.last(COMMAND).param2 := fparams
  649. END CallImp;
  650. PROCEDURE CallP* (callconv, fparams: INTEGER);
  651. BEGIN
  652. fastcall(callconv);
  653. CASE callconv OF
  654. |call_stack: AddCmd0(opCALLP)
  655. |call_win64: AddCmd(opWIN64CALLP, fparams)
  656. |call_sysv: AddCmd(opSYSVCALLP, fparams)
  657. END
  658. END CallP;
  659. PROCEDURE AssignProc* (proc: INTEGER);
  660. BEGIN
  661. Jmp(opSAVEP, proc)
  662. END AssignProc;
  663. PROCEDURE AssignImpProc* (proc: LISTS.ITEM);
  664. BEGIN
  665. Jmp(opSAVEIP, proc(IMPORT_PROC).label)
  666. END AssignImpProc;
  667. PROCEDURE PushProc* (proc: INTEGER);
  668. BEGIN
  669. Jmp(opPUSHP, proc)
  670. END PushProc;
  671. PROCEDURE PushImpProc* (proc: LISTS.ITEM);
  672. BEGIN
  673. Jmp(opPUSHIP, proc(IMPORT_PROC).label)
  674. END PushImpProc;
  675. PROCEDURE ProcCmp* (proc: INTEGER; eq: BOOLEAN);
  676. BEGIN
  677. IF eq THEN
  678. Jmp(opEQP, proc)
  679. ELSE
  680. Jmp(opNEP, proc)
  681. END
  682. END ProcCmp;
  683. PROCEDURE ProcImpCmp* (proc: LISTS.ITEM; eq: BOOLEAN);
  684. BEGIN
  685. IF eq THEN
  686. Jmp(opEQIP, proc(IMPORT_PROC).label)
  687. ELSE
  688. Jmp(opNEIP, proc(IMPORT_PROC).label)
  689. END
  690. END ProcImpCmp;
  691. PROCEDURE load* (size: INTEGER);
  692. VAR
  693. last: COMMAND;
  694. BEGIN
  695. last := codes.last;
  696. CASE size OF
  697. |1:
  698. IF last.opcode = opLADR THEN
  699. last.opcode := opLLOAD8
  700. ELSIF last.opcode = opVADR THEN
  701. last.opcode := opVLOAD8
  702. ELSIF last.opcode = opGADR THEN
  703. last.opcode := opGLOAD8
  704. ELSE
  705. AddCmd0(opLOAD8)
  706. END
  707. |2:
  708. IF last.opcode = opLADR THEN
  709. last.opcode := opLLOAD16
  710. ELSIF last.opcode = opVADR THEN
  711. last.opcode := opVLOAD16
  712. ELSIF last.opcode = opGADR THEN
  713. last.opcode := opGLOAD16
  714. ELSE
  715. AddCmd0(opLOAD16)
  716. END
  717. |4:
  718. IF last.opcode = opLADR THEN
  719. last.opcode := opLLOAD32
  720. ELSIF last.opcode = opVADR THEN
  721. last.opcode := opVLOAD32
  722. ELSIF last.opcode = opGADR THEN
  723. last.opcode := opGLOAD32
  724. ELSE
  725. AddCmd0(opLOAD32)
  726. END
  727. |8:
  728. IF last.opcode = opLADR THEN
  729. last.opcode := opLLOAD64
  730. ELSIF last.opcode = opVADR THEN
  731. last.opcode := opVLOAD64
  732. ELSIF last.opcode = opGADR THEN
  733. last.opcode := opGLOAD64
  734. ELSE
  735. AddCmd0(opLOAD64)
  736. END
  737. END
  738. END load;
  739. PROCEDURE SysPut* (size: INTEGER);
  740. BEGIN
  741. CASE size OF
  742. |1: AddCmd0(opSAVE8)
  743. |2: AddCmd0(opSAVE16)
  744. |4: AddCmd0(opSAVE32)
  745. |8: AddCmd0(opSAVE64)
  746. END
  747. END SysPut;
  748. PROCEDURE savef* (inv: BOOLEAN);
  749. BEGIN
  750. IF inv THEN
  751. AddCmd0(opSAVEFI)
  752. ELSE
  753. AddCmd0(opSAVEF)
  754. END
  755. END savef;
  756. PROCEDURE saves* (offset, length: INTEGER);
  757. BEGIN
  758. AddCmd2(opSAVES, length, offset)
  759. END saves;
  760. PROCEDURE abs* (real: BOOLEAN);
  761. BEGIN
  762. IF real THEN
  763. AddCmd0(opFABS)
  764. ELSE
  765. AddCmd0(opABS)
  766. END
  767. END abs;
  768. PROCEDURE shift_minmax* (op: CHAR);
  769. BEGIN
  770. CASE op OF
  771. |"A": AddCmd0(opASR)
  772. |"L": AddCmd0(opLSL)
  773. |"O": AddCmd0(opROR)
  774. |"R": AddCmd0(opLSR)
  775. |"m": AddCmd0(opMIN)
  776. |"x": AddCmd0(opMAX)
  777. END
  778. END shift_minmax;
  779. PROCEDURE shift_minmax1* (op: CHAR; x: INTEGER);
  780. BEGIN
  781. CASE op OF
  782. |"A": AddCmd(opASR1, x)
  783. |"L": AddCmd(opLSL1, x)
  784. |"O": AddCmd(opROR1, x)
  785. |"R": AddCmd(opLSR1, x)
  786. |"m": AddCmd(opMINC, x)
  787. |"x": AddCmd(opMAXC, x)
  788. END
  789. END shift_minmax1;
  790. PROCEDURE shift_minmax2* (op: CHAR; x: INTEGER);
  791. BEGIN
  792. CASE op OF
  793. |"A": AddCmd(opASR2, x)
  794. |"L": AddCmd(opLSL2, x)
  795. |"O": AddCmd(opROR2, x)
  796. |"R": AddCmd(opLSR2, x)
  797. |"m": AddCmd(opMINC, x)
  798. |"x": AddCmd(opMAXC, x)
  799. END
  800. END shift_minmax2;
  801. PROCEDURE len* (dim: INTEGER);
  802. BEGIN
  803. AddCmd(opLEN, dim)
  804. END len;
  805. PROCEDURE Float* (r: REAL; line, col: INTEGER);
  806. VAR
  807. cmd: COMMAND;
  808. BEGIN
  809. cmd := NewCmd();
  810. cmd.opcode := opCONSTF;
  811. cmd.float := r;
  812. cmd.param1 := line;
  813. cmd.param2 := col;
  814. insert(codes.last, cmd)
  815. END Float;
  816. PROCEDURE drop*;
  817. BEGIN
  818. AddCmd0(opDROP)
  819. END drop;
  820. PROCEDURE _case* (a, b, L, R: INTEGER);
  821. VAR
  822. cmd: COMMAND;
  823. BEGIN
  824. IF a = b THEN
  825. cmd := NewCmd();
  826. cmd.opcode := opCASELR;
  827. cmd.param1 := a;
  828. cmd.param2 := L;
  829. cmd.param3 := R;
  830. insert(codes.last, cmd)
  831. ELSE
  832. AddCmd2(opCASEL, a, L);
  833. AddCmd2(opCASER, b, R)
  834. END
  835. END _case;
  836. PROCEDURE fname* (name: PATHS.PATH);
  837. VAR
  838. cmd: FNAMECMD;
  839. BEGIN
  840. NEW(cmd);
  841. cmd.opcode := opFNAME;
  842. cmd.fname := name;
  843. insert(codes.last, cmd)
  844. END fname;
  845. PROCEDURE AddExp* (label: INTEGER; name: SCAN.IDSTR);
  846. VAR
  847. exp: EXPORT_PROC;
  848. BEGIN
  849. NEW(exp);
  850. exp.label := label;
  851. exp.name := name;
  852. LISTS.push(codes.export, exp)
  853. END AddExp;
  854. PROCEDURE AddImp* (dll, proc: SCAN.TEXTSTR): IMPORT_PROC;
  855. VAR
  856. lib: IMPORT_LIB;
  857. p: IMPORT_PROC;
  858. BEGIN
  859. lib := codes._import.first(IMPORT_LIB);
  860. WHILE (lib # NIL) & (lib.name # dll) DO
  861. lib := lib.next(IMPORT_LIB)
  862. END;
  863. IF lib = NIL THEN
  864. NEW(lib);
  865. lib.name := dll;
  866. lib.procs := LISTS.create(NIL);
  867. LISTS.push(codes._import, lib)
  868. END;
  869. p := lib.procs.first(IMPORT_PROC);
  870. WHILE (p # NIL) & (p.name # proc) DO
  871. p := p.next(IMPORT_PROC)
  872. END;
  873. IF p = NIL THEN
  874. NEW(p);
  875. p.name := proc;
  876. p.label := NewLabel();
  877. p.lib := lib;
  878. p.count := 1;
  879. LISTS.push(lib.procs, p)
  880. ELSE
  881. INC(p.count)
  882. END
  883. RETURN p
  884. END AddImp;
  885. PROCEDURE DelImport* (imp: LISTS.ITEM);
  886. VAR
  887. lib: IMPORT_LIB;
  888. BEGIN
  889. DEC(imp(IMPORT_PROC).count);
  890. IF imp(IMPORT_PROC).count = 0 THEN
  891. lib := imp(IMPORT_PROC).lib;
  892. LISTS.delete(lib.procs, imp);
  893. IF lib.procs.first = NIL THEN
  894. LISTS.delete(codes._import, lib)
  895. END
  896. END
  897. END DelImport;
  898. PROCEDURE init* (pCPU: INTEGER);
  899. VAR
  900. cmd: COMMAND;
  901. i: INTEGER;
  902. BEGIN
  903. commands := C.create();
  904. CPU := pCPU;
  905. NEW(codes.begcall);
  906. codes.begcall.top := -1;
  907. NEW(codes.endcall);
  908. codes.endcall.top := -1;
  909. codes.commands := LISTS.create(NIL);
  910. codes.export := LISTS.create(NIL);
  911. codes._import := LISTS.create(NIL);
  912. codes.types := CHL.CreateIntList();
  913. codes.data := CHL.CreateByteList();
  914. NEW(cmd); cmd.opcode := opNOP; LISTS.push(codes.commands, cmd);
  915. codes.last := cmd;
  916. NEW(cmd); cmd.opcode := opNOP; LISTS.push(codes.commands, cmd);
  917. AddRec(0);
  918. codes.lcount := 0;
  919. FOR i := 0 TO LEN(codes.charoffs) - 1 DO
  920. codes.charoffs[i] := -1
  921. END;
  922. FOR i := 0 TO LEN(codes.wcharoffs) - 1 DO
  923. codes.wcharoffs[i] := -1
  924. END
  925. END init;
  926. END IL.