IL.ob07 28 KB

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