IL.ob07 28 KB

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