| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201 |
- (*
- BSD 2-Clause License
- Copyright (c) 2018-2023, Anton Krotov
- All rights reserved.
- *)
- MODULE IL;
- IMPORT LISTS, SCAN, STRINGS, CHL := CHUNKLISTS, C := COLLECTIONS, TARGETS, PATHS;
- CONST
- call_stack* = 0;
- call_win64* = 1;
- call_sysv* = 2;
- call_fast1* = 3;
- call_fast2* = 4;
- begin_loop* = 1; end_loop* = 2;
- opJMP* = 0; opLABEL* = 1; opCOPYS* = 2; opGADR* = 3; opCONST* = 4; opLLOAD32* = 5;
- opCOPYA* = 6; opCASET* = 7; opMULC* = 8; opMUL* = 9; opDIV* = 10; opMOD* = 11;
- opDIVL* = 12; opMODL* = 13; opDIVR* = 14; opMODR* = 15; opUMINUS* = 16;
- opADD* = 17; opSUB* = 18; opONERR* = 19; opSUBL* = 20; opADDC* = 21; opSUBR* = 22;
- opSAVE* = 23; opSAVEC* = 24; opSAVE8* = 25; opSAVE8C* = 26; (*opCHKBYTE* = 27;*) opDROP* = 28;
- opNOT* = 29;
- opEQ* = 30; opNE* = opEQ + 1; opLT* = opEQ + 2; opLE* = opEQ + 3; opGT* = opEQ + 4; opGE* = opEQ + 5 (* 35 *);
- opEQC* = 36; opNEC* = opEQC + 1; opLTC* = opEQC + 2; opLEC* = opEQC + 3; opGTC* = opEQC + 4; opGEC* = opEQC + 5; (* 41 *)
- opEQF* = 42; opNEF* = opEQF + 1; opLTF* = opEQF + 2; opLEF* = opEQF + 3; opGTF* = opEQF + 4; opGEF* = opEQF + 5; (* 47 *)
- opEQS* = 48; opNES* = opEQS + 1; opLTS* = opEQS + 2; opLES* = opEQS + 3; opGTS* = opEQS + 4; opGES* = opEQS + 5; (* 53 *)
- opEQSW* = 54; opNESW* = opEQSW + 1; opLTSW* = opEQSW + 2; opLESW* = opEQSW + 3; opGTSW* = opEQSW + 4; opGESW* = opEQSW + 5 (* 59 *);
- opVLOAD32* = 60; opGLOAD32* = 61;
- opJZ* = 62; opJNZ* = 63;
- opSAVE32* = 64; opLLOAD8* = 65;
- opCONSTF* = 66; opLOADF* = 67; opSAVEF* = 68; opMULF* = 69; opDIVF* = 70; opDIVFI* = 71;
- opUMINF* = 72; opSAVEFI* = 73; opSUBFI* = 74; opADDF* = 75; opSUBF* = 76;
- opJNZ1* = 77; opJG* = 78;
- opINCCB* = 79; opDECCB* = 80; opINCB* = 81; opDECB* = 82;
- opCASEL* = 83; opCASER* = 84; opCASELR* = 85;
- opPOPSP* = 86;
- opWIN64CALL* = 87; opWIN64CALLI* = 88; opWIN64CALLP* = 89; opAND* = 90; opOR* = 91;
- opLOAD8* = 92; opLOAD16* = 93; opLOAD32* = 94; opPRECALL* = 95; opRES* = 96; opRESF* = 97;
- opPUSHC* = 98; opSWITCH* = 99;
- opSBOOL* = 100; opSBOOLC* = 101; opNOP* = 102;
- opMULS* = 103; opMULSC* = 104; opDIVS* = 105; opDIVSC* = 106;
- opADDS* = 107; opSUBS* = 108; opERR* = 109; opSUBSL* = 110; opADDSC* = 111; opSUBSR* = 112;
- opUMINS* = 113; opIN* = 114; opINL* = 115; opINR* = 116;
- opRSET* = 117; opRSETL* = 118; opRSETR* = 119; opRSET1* = 120; opLENGTH* = 121;
- opLEAVEC* = 122; opCODE* = 123; opALIGN16* = 124;
- opINCC* = 125; opINC* = 126; opDEC* = 127;
- opINCL* = 128; opEXCL* = 129; opINCLC* = 130; opEXCLC* = 131; opNEW* = 132; opDISP* = 133;
- opPACK* = 134; opPACKC* = 135; opUNPK* = 136; opCOPY* = 137; opENTER* = 138; opLEAVE* = 139;
- opCALL* = 140; opSAVEP* = 141; opCALLP* = 142; opEQP* = 143; opNEP* = 144; opLEAVER* = 145;
- opGET* = 146; opSAVE16* = 147; opABS* = 148; opFABS* = 149; opFLOOR* = 150; opFLT* = 151;
- opGETC* = 152; opORD* = 153; opASR* = 154; opLSL* = 155; opROR* = 156;
- opASR1* = 157; opLSL1* = 158; opROR1* = 159; opASR2* = 160; opLSL2* = 161; opROR2* = 162;
- opPUSHP* = 163; opLADR* = 164; opTYPEGP* = 165; opIS* = 166; opPUSHF* = 167; opVADR* = 168;
- opPUSHT* = 169; opTYPEGR* = 170; opISREC* = 171; opCHKIDX* = 172; opPARAM* = 173;
- opCHKIDX2* = 174; opLEN* = 175; opROT* = 176; opSAVES* = 177; opSADR* = 178; opLENGTHW* = 179;
- (*opCHR* = 180;*) opENDSW* = 181; opLEAVEF* = 182; opCLEANUP* = 183; opMOVE* = 184;
- opLSR* = 185; opLSR1* = 186; opLSR2* = 187;
- opMIN* = 188; opMINC* = 189; opMAX* = 190; opMAXC* = 191; opSYSVALIGN16* = 192;
- opEQB* = 193; opNEB* = 194; opINF* = 195; opWIN64ALIGN16* = 196; opVLOAD8* = 197; opGLOAD8* = 198;
- opLLOAD16* = 199; opVLOAD16* = 200; opGLOAD16* = 201;
- opLOAD64* = 202; opLLOAD64* = 203; opVLOAD64* = 204; opGLOAD64* = 205; opSAVE64* = 206;
- opTYPEGD* = 207; opCALLI* = 208; opPUSHIP* = 209; opSAVEIP* = 210; opEQIP* = 211; opNEIP* = 212;
- opSAVE16C* = 213; (*opWCHR* = 214;*) opHANDLER* = 215;
- opSYSVCALL* = 216; opSYSVCALLI* = 217; opSYSVCALLP* = 218; opFNAME* = 219; opFASTCALL* = 220;
- opSADR_PARAM* = -1; opLOAD64_PARAM* = -2; opLLOAD64_PARAM* = -3; opGLOAD64_PARAM* = -4;
- opVADR_PARAM* = -5; opCONST_PARAM* = -6; opGLOAD32_PARAM* = -7; opLLOAD32_PARAM* = -8;
- opLOAD32_PARAM* = -9;
- opLADR_SAVEC* = -10; opGADR_SAVEC* = -11; opLADR_SAVE* = -12;
- opLADR_INCC* = -13; opLADR_INCCB* = -14; opLADR_DECCB* = -15;
- opLADR_INC* = -16; opLADR_DEC* = -17; opLADR_INCB* = -18; opLADR_DECB* = -19;
- opLADR_INCL* = -20; opLADR_EXCL* = -21; opLADR_INCLC* = -22; opLADR_EXCLC* = -23;
- opLADR_UNPK* = -24;
- _init *= 0;
- _move *= 1;
- _strcmpw *= 2;
- _exit *= 3;
- _set *= 4;
- _set1 *= 5;
- _lengthw *= 6;
- _strcpy *= 7;
- _length *= 8;
- _divmod *= 9;
- _dllentry *= 10;
- _sofinit *= 11;
- _arrcpy *= 12;
- _rot *= 13;
- _new *= 14;
- _dispose *= 15;
- _strcmp *= 16;
- _error *= 17;
- _is *= 18;
- _isrec *= 19;
- _guard *= 20;
- _guardrec *= 21;
- _fmul *= 22;
- _fdiv *= 23;
- _fdivi *= 24;
- _fadd *= 25;
- _fsub *= 26;
- _fsubi *= 27;
- _fcmp *= 28;
- _floor *= 29;
- _flt *= 30;
- _pack *= 31;
- _unpk *= 32;
- TYPE
- COMMAND* = POINTER TO RECORD (LISTS.ITEM)
- opcode*: INTEGER;
- param1*: INTEGER;
- param2*: INTEGER;
- param3*: INTEGER;
- float*: REAL
- END;
- FNAMECMD* = POINTER TO RECORD (COMMAND)
- fname*: PATHS.PATH
- END;
- CMDSTACK = POINTER TO RECORD
- data: ARRAY 1000 OF COMMAND;
- top: INTEGER
- END;
- EXPORT_PROC* = POINTER TO RECORD (LISTS.ITEM)
- label*: INTEGER;
- name*: SCAN.IDSTR
- END;
- IMPORT_LIB* = POINTER TO RECORD (LISTS.ITEM)
- name*: SCAN.TEXTSTR;
- procs*: LISTS.LIST
- END;
- IMPORT_PROC* = POINTER TO RECORD (LISTS.ITEM)
- label*: INTEGER;
- lib*: IMPORT_LIB;
- name*: SCAN.TEXTSTR;
- count: INTEGER
- END;
- CODES = RECORD
- last: COMMAND;
- begcall: CMDSTACK;
- endcall: CMDSTACK;
- commands*: LISTS.LIST;
- export*: LISTS.LIST;
- _import*: LISTS.LIST;
- types*: CHL.INTLIST;
- data*: CHL.BYTELIST;
- dmin*: INTEGER;
- lcount*: INTEGER;
- bss*: INTEGER;
- rtl*: ARRAY 33 OF INTEGER;
- errlabels*: ARRAY 12 OF INTEGER;
- charoffs: ARRAY 256 OF INTEGER;
- wcharoffs: ARRAY 65536 OF INTEGER;
- wstr: ARRAY 4*1024 OF WCHAR
- END;
- VAR
- codes*: CODES;
- CPU: INTEGER;
- commands: C.COLLECTION;
- PROCEDURE set_dmin* (value: INTEGER);
- BEGIN
- codes.dmin := value
- END set_dmin;
- PROCEDURE set_bss* (value: INTEGER);
- BEGIN
- codes.bss := value
- END set_bss;
- PROCEDURE set_rtl* (idx, label: INTEGER);
- BEGIN
- codes.rtl[idx] := label
- END set_rtl;
- PROCEDURE NewCmd (): COMMAND;
- VAR
- cmd: COMMAND;
- citem: C.ITEM;
- BEGIN
- citem := C.pop(commands);
- IF citem = NIL THEN
- NEW(cmd)
- ELSE
- cmd := citem(COMMAND)
- END
- RETURN cmd
- END NewCmd;
- PROCEDURE setlast* (cmd: COMMAND);
- BEGIN
- codes.last := cmd
- END setlast;
- PROCEDURE getlast* (): COMMAND;
- RETURN codes.last
- END getlast;
- PROCEDURE PutByte (b: BYTE);
- BEGIN
- CHL.PushByte(codes.data, b)
- END PutByte;
- PROCEDURE AlignData (n: INTEGER);
- BEGIN
- WHILE CHL.Length(codes.data) MOD n # 0 DO
- PutByte(0)
- END
- END AlignData;
- PROCEDURE putstr* (s: ARRAY OF CHAR): INTEGER;
- VAR
- i, n, res: INTEGER;
- BEGIN
- IF TARGETS.WinLin THEN
- AlignData(16)
- END;
- res := CHL.Length(codes.data);
- i := 0;
- n := LENGTH(s);
- WHILE i < n DO
- PutByte(ORD(s[i]));
- INC(i)
- END;
- PutByte(0)
- RETURN res
- END putstr;
- PROCEDURE putstr1* (c: INTEGER): INTEGER;
- VAR
- res: INTEGER;
- BEGIN
- IF codes.charoffs[c] = -1 THEN
- IF TARGETS.WinLin THEN
- AlignData(16)
- END;
- res := CHL.Length(codes.data);
- PutByte(c);
- PutByte(0);
- codes.charoffs[c] := res
- ELSE
- res := codes.charoffs[c]
- END
- RETURN res
- END putstr1;
- PROCEDURE putstrW* (s: ARRAY OF CHAR): INTEGER;
- VAR
- i, n, res: INTEGER;
- BEGIN
- IF TARGETS.WinLin THEN
- AlignData(16)
- ELSE
- AlignData(2)
- END;
- res := CHL.Length(codes.data);
- n := STRINGS.Utf8To16(s, codes.wstr);
- i := 0;
- WHILE i < n DO
- IF TARGETS.LittleEndian THEN
- PutByte(ORD(codes.wstr[i]) MOD 256);
- PutByte(ORD(codes.wstr[i]) DIV 256)
- ELSE
- PutByte(ORD(codes.wstr[i]) DIV 256);
- PutByte(ORD(codes.wstr[i]) MOD 256)
- END;
- INC(i)
- END;
- PutByte(0);
- PutByte(0)
- RETURN res
- END putstrW;
- PROCEDURE putstrW1* (c: INTEGER): INTEGER;
- VAR
- res: INTEGER;
- BEGIN
- IF codes.wcharoffs[c] = -1 THEN
- IF TARGETS.WinLin THEN
- AlignData(16)
- ELSE
- AlignData(2)
- END;
- res := CHL.Length(codes.data);
- IF TARGETS.LittleEndian THEN
- PutByte(c MOD 256);
- PutByte(c DIV 256)
- ELSE
- PutByte(c DIV 256);
- PutByte(c MOD 256)
- END;
- PutByte(0);
- PutByte(0);
- codes.wcharoffs[c] := res
- ELSE
- res := codes.wcharoffs[c]
- END
- RETURN res
- END putstrW1;
- PROCEDURE push (stk: CMDSTACK; cmd: COMMAND);
- BEGIN
- INC(stk.top);
- stk.data[stk.top] := cmd
- END push;
- PROCEDURE pop (stk: CMDSTACK): COMMAND;
- VAR
- res: COMMAND;
- BEGIN
- res := stk.data[stk.top];
- DEC(stk.top)
- RETURN res
- END pop;
- PROCEDURE pushBegEnd* (VAR beg, _end: COMMAND);
- BEGIN
- push(codes.begcall, beg);
- push(codes.endcall, _end);
- beg := codes.last;
- _end := beg.next(COMMAND)
- END pushBegEnd;
- PROCEDURE popBegEnd* (VAR beg, _end: COMMAND);
- BEGIN
- beg := pop(codes.begcall);
- _end := pop(codes.endcall)
- END popBegEnd;
- PROCEDURE AddRec* (base: INTEGER);
- BEGIN
- CHL.PushInt(codes.types, base)
- END AddRec;
- PROCEDURE insert (cur, nov: COMMAND);
- VAR
- old_opcode, param2: INTEGER;
- PROCEDURE set (cur: COMMAND; opcode, param2: INTEGER);
- BEGIN
- cur.opcode := opcode;
- cur.param1 := cur.param2;
- cur.param2 := param2
- END set;
- BEGIN
- IF CPU IN {TARGETS.cpuX86, TARGETS.cpuAMD64, TARGETS.cpuMSP430} THEN
- old_opcode := cur.opcode;
- param2 := nov.param2;
- IF (nov.opcode = opPARAM) & (param2 = 1) THEN
- CASE old_opcode OF
- |opGLOAD64: cur.opcode := opGLOAD64_PARAM
- |opLLOAD64: cur.opcode := opLLOAD64_PARAM
- |opLOAD64: cur.opcode := opLOAD64_PARAM
- |opGLOAD32: cur.opcode := opGLOAD32_PARAM
- |opLLOAD32: cur.opcode := opLLOAD32_PARAM
- |opLOAD32: cur.opcode := opLOAD32_PARAM
- |opSADR: cur.opcode := opSADR_PARAM
- |opVADR: cur.opcode := opVADR_PARAM
- |opCONST: cur.opcode := opCONST_PARAM
- ELSE
- old_opcode := -1
- END
- ELSIF old_opcode = opLADR THEN
- CASE nov.opcode OF
- |opSAVEC: set(cur, opLADR_SAVEC, param2)
- |opSAVE: cur.opcode := opLADR_SAVE
- |opINC: cur.opcode := opLADR_INC
- |opDEC: cur.opcode := opLADR_DEC
- |opINCB: cur.opcode := opLADR_INCB
- |opDECB: cur.opcode := opLADR_DECB
- |opINCL: cur.opcode := opLADR_INCL
- |opEXCL: cur.opcode := opLADR_EXCL
- |opUNPK: cur.opcode := opLADR_UNPK
- |opINCC: set(cur, opLADR_INCC, param2)
- |opINCCB: set(cur, opLADR_INCCB, param2)
- |opDECCB: set(cur, opLADR_DECCB, param2)
- |opINCLC: set(cur, opLADR_INCLC, param2)
- |opEXCLC: set(cur, opLADR_EXCLC, param2)
- ELSE
- old_opcode := -1
- END
- ELSIF (nov.opcode = opSAVEC) & (old_opcode = opGADR) THEN
- set(cur, opGADR_SAVEC, param2)
- ELSIF (nov.opcode = opMULC) & (old_opcode = opMULC) THEN
- cur.param2 := cur.param2 * param2
- ELSIF (nov.opcode = opADDC) & (old_opcode = opADDC) THEN
- INC(cur.param2, param2)
- ELSE
- old_opcode := -1
- END
- ELSIF CPU IN {TARGETS.cpuTHUMB, TARGETS.cpuRVM32I, TARGETS.cpuRVM64I} THEN
- old_opcode := cur.opcode;
- param2 := nov.param2;
- IF (old_opcode = opLADR) & (nov.opcode = opSAVE) THEN
- cur.opcode := opLADR_SAVE
- ELSIF (old_opcode = opLADR) & (nov.opcode = opINCC) THEN
- set(cur, opLADR_INCC, param2)
- ELSIF (nov.opcode = opMULC) & (old_opcode = opMULC) THEN
- cur.param2 := cur.param2 * param2
- ELSIF (nov.opcode = opADDC) & (old_opcode = opADDC) THEN
- INC(cur.param2, param2)
- ELSE
- old_opcode := -1
- END
- ELSE
- old_opcode := -1
- END;
- IF old_opcode = -1 THEN
- LISTS.insert(codes.commands, cur, nov);
- codes.last := nov
- ELSE
- C.push(commands, nov);
- codes.last := cur
- END
- END insert;
- PROCEDURE AddCmd* (opcode: INTEGER; param: INTEGER);
- VAR
- cmd: COMMAND;
- BEGIN
- cmd := NewCmd();
- cmd.opcode := opcode;
- cmd.param1 := 0;
- cmd.param2 := param;
- insert(codes.last, cmd)
- END AddCmd;
- PROCEDURE AddCmd2* (opcode: INTEGER; param1, param2: INTEGER);
- VAR
- cmd: COMMAND;
- BEGIN
- cmd := NewCmd();
- cmd.opcode := opcode;
- cmd.param1 := param1;
- cmd.param2 := param2;
- insert(codes.last, cmd)
- END AddCmd2;
- PROCEDURE Const* (val: INTEGER);
- BEGIN
- AddCmd(opCONST, val)
- END Const;
- PROCEDURE StrAdr* (adr: INTEGER);
- BEGIN
- AddCmd(opSADR, adr)
- END StrAdr;
- PROCEDURE Param1*;
- BEGIN
- AddCmd(opPARAM, 1)
- END Param1;
- PROCEDURE NewLabel* (): INTEGER;
- BEGIN
- INC(codes.lcount)
- RETURN codes.lcount - 1
- END NewLabel;
- PROCEDURE SetLabel* (label: INTEGER);
- BEGIN
- AddCmd2(opLABEL, label, 0)
- END SetLabel;
- PROCEDURE SetErrLabel* (errno: INTEGER);
- BEGIN
- codes.errlabels[errno] := NewLabel();
- SetLabel(codes.errlabels[errno])
- END SetErrLabel;
- PROCEDURE AddCmd0* (opcode: INTEGER);
- BEGIN
- AddCmd(opcode, 0)
- END AddCmd0;
- PROCEDURE delete (cmd: COMMAND);
- BEGIN
- LISTS.delete(codes.commands, cmd);
- C.push(commands, cmd)
- END delete;
- PROCEDURE delete2* (first, last: LISTS.ITEM);
- VAR
- cur, next: LISTS.ITEM;
- BEGIN
- cur := first;
- IF first # last THEN
- REPEAT
- next := cur.next;
- LISTS.delete(codes.commands, cur);
- C.push(commands, cur);
- cur := next
- UNTIL cur = last
- END;
- LISTS.delete(codes.commands, cur);
- C.push(commands, cur)
- END delete2;
- PROCEDURE Jmp* (opcode: INTEGER; label: INTEGER);
- VAR
- prev: COMMAND;
- not: BOOLEAN;
- BEGIN
- prev := codes.last;
- not := prev.opcode = opNOT;
- IF not THEN
- IF opcode = opJNZ THEN
- opcode := opJZ
- ELSIF opcode = opJZ THEN
- opcode := opJNZ
- ELSE
- not := FALSE
- END
- END;
- AddCmd2(opcode, label, label);
- IF not THEN
- delete(prev)
- END
- END Jmp;
- PROCEDURE AndOrOpt* (VAR label: INTEGER);
- VAR
- cur, prev: COMMAND;
- i, op, l: INTEGER;
- jz, not: BOOLEAN;
- BEGIN
- cur := codes.last;
- not := cur.opcode = opNOT;
- IF not THEN
- cur := cur.prev(COMMAND)
- END;
- IF cur.opcode = opAND THEN
- op := opAND
- ELSIF cur.opcode = opOR THEN
- op := opOR
- ELSE
- op := -1
- END;
- cur := codes.last;
- IF op # -1 THEN
- IF not THEN
- IF op = opAND THEN
- op := opOR
- ELSE (* op = opOR *)
- op := opAND
- END;
- prev := cur.prev(COMMAND);
- delete(cur);
- cur := prev
- END;
- FOR i := 1 TO 9 DO
- IF i = 8 THEN
- l := cur.param1
- ELSIF i = 9 THEN
- jz := cur.opcode = opJZ
- END;
- prev := cur.prev(COMMAND);
- delete(cur);
- cur := prev
- END;
- setlast(cur);
- IF op = opAND THEN
- label := l;
- jz := ~jz
- END;
- IF jz THEN
- Jmp(opJZ, label)
- ELSE
- Jmp(opJNZ, label)
- END;
- IF op = opOR THEN
- SetLabel(l)
- END
- ELSE
- Jmp(opJZ, label)
- END;
- setlast(codes.last)
- END AndOrOpt;
- PROCEDURE OnError* (line, error: INTEGER);
- BEGIN
- AddCmd2(opONERR, codes.errlabels[error], line)
- END OnError;
- PROCEDURE TypeGuard* (op, t: INTEGER; line, error: INTEGER);
- VAR
- label: INTEGER;
- BEGIN
- AddCmd(op, t);
- label := NewLabel();
- Jmp(opJNZ, label);
- OnError(line, error);
- SetLabel(label)
- END TypeGuard;
- PROCEDURE TypeCheck* (t: INTEGER);
- BEGIN
- AddCmd(opIS, t)
- END TypeCheck;
- PROCEDURE TypeCheckRec* (t: INTEGER);
- BEGIN
- AddCmd(opISREC, t)
- END TypeCheckRec;
- PROCEDURE New* (size, typenum: INTEGER);
- BEGIN
- AddCmd2(opNEW, typenum, size)
- END New;
- PROCEDURE not*;
- VAR
- prev: COMMAND;
- BEGIN
- prev := codes.last;
- IF prev.opcode = opNOT THEN
- codes.last := prev.prev(COMMAND);
- delete(prev)
- ELSE
- AddCmd0(opNOT)
- END
- END not;
- PROCEDURE _ord*;
- BEGIN
- IF (codes.last.opcode # opAND) & (codes.last.opcode # opOR) THEN
- AddCmd0(opORD)
- END
- END _ord;
- PROCEDURE Enter* (label, params: INTEGER): COMMAND;
- VAR
- cmd: COMMAND;
- BEGIN
- cmd := NewCmd();
- cmd.opcode := opENTER;
- cmd.param1 := label;
- cmd.param3 := params;
- insert(codes.last, cmd)
- RETURN codes.last
- END Enter;
- PROCEDURE Leave* (result, float: BOOLEAN; locsize, paramsize: INTEGER): COMMAND;
- BEGIN
- IF result THEN
- IF float THEN
- AddCmd2(opLEAVEF, locsize, paramsize)
- ELSE
- AddCmd2(opLEAVER, locsize, paramsize)
- END
- ELSE
- AddCmd2(opLEAVE, locsize, paramsize)
- END
- RETURN codes.last
- END Leave;
- PROCEDURE EnterC* (label: INTEGER): COMMAND;
- BEGIN
- SetLabel(label)
- RETURN codes.last
- END EnterC;
- PROCEDURE LeaveC* (): COMMAND;
- BEGIN
- AddCmd0(opLEAVEC)
- RETURN codes.last
- END LeaveC;
- PROCEDURE fastcall (VAR callconv: INTEGER);
- BEGIN
- IF callconv = call_fast1 THEN
- AddCmd(opFASTCALL, 1);
- callconv := call_stack
- ELSIF callconv = call_fast2 THEN
- AddCmd(opFASTCALL, 2);
- callconv := call_stack
- END
- END fastcall;
- PROCEDURE Call* (proc, callconv, fparams: INTEGER);
- BEGIN
- fastcall(callconv);
- CASE callconv OF
- |call_stack: Jmp(opCALL, proc)
- |call_win64: Jmp(opWIN64CALL, proc)
- |call_sysv: Jmp(opSYSVCALL, proc)
- END;
- codes.last(COMMAND).param2 := fparams
- END Call;
- PROCEDURE CallImp* (proc: LISTS.ITEM; callconv, fparams: INTEGER);
- BEGIN
- fastcall(callconv);
- CASE callconv OF
- |call_stack: Jmp(opCALLI, proc(IMPORT_PROC).label)
- |call_win64: Jmp(opWIN64CALLI, proc(IMPORT_PROC).label)
- |call_sysv: Jmp(opSYSVCALLI, proc(IMPORT_PROC).label)
- END;
- codes.last(COMMAND).param2 := fparams
- END CallImp;
- PROCEDURE CallP* (callconv, fparams: INTEGER);
- BEGIN
- fastcall(callconv);
- CASE callconv OF
- |call_stack: AddCmd0(opCALLP)
- |call_win64: AddCmd(opWIN64CALLP, fparams)
- |call_sysv: AddCmd(opSYSVCALLP, fparams)
- END
- END CallP;
- PROCEDURE AssignProc* (proc: INTEGER);
- BEGIN
- Jmp(opSAVEP, proc)
- END AssignProc;
- PROCEDURE AssignImpProc* (proc: LISTS.ITEM);
- BEGIN
- Jmp(opSAVEIP, proc(IMPORT_PROC).label)
- END AssignImpProc;
- PROCEDURE PushProc* (proc: INTEGER);
- BEGIN
- Jmp(opPUSHP, proc)
- END PushProc;
- PROCEDURE PushImpProc* (proc: LISTS.ITEM);
- BEGIN
- Jmp(opPUSHIP, proc(IMPORT_PROC).label)
- END PushImpProc;
- PROCEDURE ProcCmp* (proc: INTEGER; eq: BOOLEAN);
- BEGIN
- IF eq THEN
- Jmp(opEQP, proc)
- ELSE
- Jmp(opNEP, proc)
- END
- END ProcCmp;
- PROCEDURE ProcImpCmp* (proc: LISTS.ITEM; eq: BOOLEAN);
- BEGIN
- IF eq THEN
- Jmp(opEQIP, proc(IMPORT_PROC).label)
- ELSE
- Jmp(opNEIP, proc(IMPORT_PROC).label)
- END
- END ProcImpCmp;
- PROCEDURE load* (size: INTEGER);
- VAR
- last: COMMAND;
- BEGIN
- last := codes.last;
- CASE size OF
- |1:
- IF last.opcode = opLADR THEN
- last.opcode := opLLOAD8
- ELSIF last.opcode = opVADR THEN
- last.opcode := opVLOAD8
- ELSIF last.opcode = opGADR THEN
- last.opcode := opGLOAD8
- ELSE
- AddCmd0(opLOAD8)
- END
- |2:
- IF last.opcode = opLADR THEN
- last.opcode := opLLOAD16
- ELSIF last.opcode = opVADR THEN
- last.opcode := opVLOAD16
- ELSIF last.opcode = opGADR THEN
- last.opcode := opGLOAD16
- ELSE
- AddCmd0(opLOAD16)
- END
- |4:
- IF last.opcode = opLADR THEN
- last.opcode := opLLOAD32
- ELSIF last.opcode = opVADR THEN
- last.opcode := opVLOAD32
- ELSIF last.opcode = opGADR THEN
- last.opcode := opGLOAD32
- ELSE
- AddCmd0(opLOAD32)
- END
- |8:
- IF last.opcode = opLADR THEN
- last.opcode := opLLOAD64
- ELSIF last.opcode = opVADR THEN
- last.opcode := opVLOAD64
- ELSIF last.opcode = opGADR THEN
- last.opcode := opGLOAD64
- ELSE
- AddCmd0(opLOAD64)
- END
- END
- END load;
- PROCEDURE SysPut* (size: INTEGER);
- BEGIN
- CASE size OF
- |1: AddCmd0(opSAVE8)
- |2: AddCmd0(opSAVE16)
- |4: AddCmd0(opSAVE32)
- |8: AddCmd0(opSAVE64)
- END
- END SysPut;
- PROCEDURE savef* (inv: BOOLEAN);
- BEGIN
- IF inv THEN
- AddCmd0(opSAVEFI)
- ELSE
- AddCmd0(opSAVEF)
- END
- END savef;
- PROCEDURE saves* (offset, length: INTEGER);
- BEGIN
- AddCmd2(opSAVES, length, offset)
- END saves;
- PROCEDURE abs* (real: BOOLEAN);
- BEGIN
- IF real THEN
- AddCmd0(opFABS)
- ELSE
- AddCmd0(opABS)
- END
- END abs;
- PROCEDURE shift_minmax* (op: CHAR);
- BEGIN
- CASE op OF
- |"A": AddCmd0(opASR)
- |"L": AddCmd0(opLSL)
- |"O": AddCmd0(opROR)
- |"R": AddCmd0(opLSR)
- |"m": AddCmd0(opMIN)
- |"x": AddCmd0(opMAX)
- END
- END shift_minmax;
- PROCEDURE shift_minmax1* (op: CHAR; x: INTEGER);
- BEGIN
- CASE op OF
- |"A": AddCmd(opASR1, x)
- |"L": AddCmd(opLSL1, x)
- |"O": AddCmd(opROR1, x)
- |"R": AddCmd(opLSR1, x)
- |"m": AddCmd(opMINC, x)
- |"x": AddCmd(opMAXC, x)
- END
- END shift_minmax1;
- PROCEDURE shift_minmax2* (op: CHAR; x: INTEGER);
- BEGIN
- CASE op OF
- |"A": AddCmd(opASR2, x)
- |"L": AddCmd(opLSL2, x)
- |"O": AddCmd(opROR2, x)
- |"R": AddCmd(opLSR2, x)
- |"m": AddCmd(opMINC, x)
- |"x": AddCmd(opMAXC, x)
- END
- END shift_minmax2;
- PROCEDURE len* (dim: INTEGER);
- BEGIN
- AddCmd(opLEN, dim)
- END len;
- PROCEDURE Float* (r: REAL; line, col: INTEGER);
- VAR
- cmd: COMMAND;
- BEGIN
- cmd := NewCmd();
- cmd.opcode := opCONSTF;
- cmd.float := r;
- cmd.param1 := line;
- cmd.param2 := col;
- insert(codes.last, cmd)
- END Float;
- PROCEDURE drop*;
- BEGIN
- AddCmd0(opDROP)
- END drop;
- PROCEDURE _case* (a, b, L, R: INTEGER);
- VAR
- cmd: COMMAND;
- BEGIN
- IF a = b THEN
- cmd := NewCmd();
- cmd.opcode := opCASELR;
- cmd.param1 := a;
- cmd.param2 := L;
- cmd.param3 := R;
- insert(codes.last, cmd)
- ELSE
- AddCmd2(opCASEL, a, L);
- AddCmd2(opCASER, b, R)
- END
- END _case;
- PROCEDURE fname* (name: PATHS.PATH);
- VAR
- cmd: FNAMECMD;
- BEGIN
- NEW(cmd);
- cmd.opcode := opFNAME;
- cmd.fname := name;
- insert(codes.last, cmd)
- END fname;
- PROCEDURE AddExp* (label: INTEGER; name: SCAN.IDSTR);
- VAR
- exp: EXPORT_PROC;
- BEGIN
- NEW(exp);
- exp.label := label;
- exp.name := name;
- LISTS.push(codes.export, exp)
- END AddExp;
- PROCEDURE AddImp* (dll, proc: SCAN.TEXTSTR): IMPORT_PROC;
- VAR
- lib: IMPORT_LIB;
- p: IMPORT_PROC;
- BEGIN
- lib := codes._import.first(IMPORT_LIB);
- WHILE (lib # NIL) & (lib.name # dll) DO
- lib := lib.next(IMPORT_LIB)
- END;
- IF lib = NIL THEN
- NEW(lib);
- lib.name := dll;
- lib.procs := LISTS.create(NIL);
- LISTS.push(codes._import, lib)
- END;
- p := lib.procs.first(IMPORT_PROC);
- WHILE (p # NIL) & (p.name # proc) DO
- p := p.next(IMPORT_PROC)
- END;
- IF p = NIL THEN
- NEW(p);
- p.name := proc;
- p.label := NewLabel();
- p.lib := lib;
- p.count := 1;
- LISTS.push(lib.procs, p)
- ELSE
- INC(p.count)
- END
- RETURN p
- END AddImp;
- PROCEDURE DelImport* (imp: LISTS.ITEM);
- VAR
- lib: IMPORT_LIB;
- BEGIN
- DEC(imp(IMPORT_PROC).count);
- IF imp(IMPORT_PROC).count = 0 THEN
- lib := imp(IMPORT_PROC).lib;
- LISTS.delete(lib.procs, imp);
- IF lib.procs.first = NIL THEN
- LISTS.delete(codes._import, lib)
- END
- END
- END DelImport;
- PROCEDURE init* (pCPU: INTEGER);
- VAR
- cmd: COMMAND;
- i: INTEGER;
- BEGIN
- commands := C.create();
- CPU := pCPU;
- NEW(codes.begcall);
- codes.begcall.top := -1;
- NEW(codes.endcall);
- codes.endcall.top := -1;
- codes.commands := LISTS.create(NIL);
- codes.export := LISTS.create(NIL);
- codes._import := LISTS.create(NIL);
- codes.types := CHL.CreateIntList();
- codes.data := CHL.CreateByteList();
- NEW(cmd); cmd.opcode := opNOP; LISTS.push(codes.commands, cmd);
- codes.last := cmd;
- NEW(cmd); cmd.opcode := opNOP; LISTS.push(codes.commands, cmd);
- AddRec(0);
- codes.lcount := 0;
- FOR i := 0 TO LEN(codes.charoffs) - 1 DO
- codes.charoffs[i] := -1
- END;
- FOR i := 0 TO LEN(codes.wcharoffs) - 1 DO
- codes.wcharoffs[i] := -1
- END
- END init;
- END IL.
|