PROG.ob07 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276
  1. MODULE PROG;
  2. IMPORT SCAN, LISTS, ARITH, ERRORS, C := COLLECTIONS, IL, UTILS IN "./utils/UTILS.ob07", TARGETS, STRINGS, PATHS;
  3. CONST
  4. MAXARRDIM* = 5;
  5. MAXSCOPE = 16;
  6. MAXSYSVPARAM* = 26;
  7. idNONE* = 0; idGUARD = 1; idMODULE* = 2; idCONST* = 3;
  8. idTYPE* = 4; idSTFUNC* = 5; idSTPROC* = 6; idVAR* = 7;
  9. idPROC* = 8; idVPAR* = 9; idPARAM* = 10; idSYSFUNC* = 11;
  10. idSYSPROC* = 12; idIMP* = 13;
  11. tINTEGER* = 1; tBYTE* = 2; tCHAR* = 3; tSET* = 4;
  12. tBOOLEAN* = 5; tREAL* = 6; tARRAY* = 7; tRECORD* = 8;
  13. tPOINTER* = 9; tPROCEDURE* = 10; tSTRING* = 11; tNIL* = 12;
  14. tCARD32* = 13; tANYREC* = 14; tWCHAR* = 15; tNONE* = 16;
  15. BASICTYPES* = {tINTEGER, tBYTE, tCHAR, tSET, tBOOLEAN, tREAL, tCARD32, tWCHAR};
  16. stABS* = 1; stASR* = 2; stCHR* = 3; stFLOOR* = 4;
  17. stFLT* = 5; stLEN* = 6; stLSL* = 7; stODD* = 8;
  18. stORD* = 9; stROR* = 10; stASSERT* = 11; stDEC* = 12;
  19. stEXCL* = 13; stINC* = 14; stINCL* = 15; stNEW* = 16;
  20. stPACK* = 17; stUNPK* = 18; sysADR* = 19; sysSIZE* = 20;
  21. sysGET* = 21; sysPUT* = 22;
  22. stDISPOSE* = 23; stLSR* = 24; stBITS* = 25; sysCODE* = 26;
  23. sysMOVE* = 27; stLENGTH* = 28; stMIN* = 29; stMAX* = 30;
  24. sysSADR* = 31; sysTYPEID* = 32; sysCOPY* = 33; sysINF* = 34;
  25. sysPUT8* = 35; sysPUT16* = 36; stCOPY* = 37; stWCHR* = 38;
  26. sysWSADR* = 39; sysPUT32* = 40; (*sysNOP* = 41; sysEINT* = 42;
  27. sysDINT* = 43;*)sysGET8* = 44; sysGET16* = 45; sysGET32* = 46;
  28. sysVAL* = 47;
  29. default32* = 2; _default32* = default32 + 1;
  30. stdcall* = 4; _stdcall* = stdcall + 1;
  31. cdecl* = 6; _cdecl* = cdecl + 1;
  32. ccall* = 8; _ccall* = ccall + 1;
  33. win64* = 10; _win64* = win64 + 1;
  34. default64* = 12; _default64* = default64 + 1;
  35. systemv* = 14; _systemv* = systemv + 1;
  36. default16* = 16; _default16* = default16 + 1;
  37. code* = 18; _code* = code + 1;
  38. fastcall* = 20; _fastcall* = fastcall + 1;
  39. noalign* = 22;
  40. callee_clean_up* = {default32, _default32, stdcall, _stdcall, default64, _default64, fastcall, _fastcall};
  41. sf_stdcall* = 0; sf_oberon* = 1; sf_cdecl* = 2; sf_ccall* = 3;
  42. sf_win64* = 4; sf_systemv* = 5; sf_windows* = 6; sf_linux* = 7;
  43. sf_code* = 8; sf_fastcall* = 9;
  44. sf_noalign* = 10;
  45. proc_flags* = {sf_stdcall, sf_cdecl, sf_ccall, sf_win64, sf_systemv, sf_windows, sf_linux, sf_code, sf_oberon, sf_fastcall};
  46. rec_flags* = {sf_noalign};
  47. STACK_FRAME = 2;
  48. TYPE
  49. OPTIONS* = RECORD
  50. version*, stack*, ram*, rom*, tab*, PE32FileAlignment*: INTEGER;
  51. pic*, lower*, uses*: BOOLEAN;
  52. checking*: SET
  53. END;
  54. IDENT* = POINTER TO rIDENT;
  55. UNIT* = POINTER TO rUNIT;
  56. _TYPE* = POINTER TO rTYPE;
  57. FRWPTR* = POINTER TO RECORD (LISTS.ITEM)
  58. _type: _TYPE;
  59. baseIdent: SCAN.IDENT;
  60. linked: BOOLEAN;
  61. pos*: SCAN.POSITION;
  62. notRecord*: BOOLEAN
  63. END;
  64. PROC* = POINTER TO RECORD (LISTS.ITEM)
  65. label*: INTEGER;
  66. used*: BOOLEAN;
  67. processed*: BOOLEAN;
  68. _import*: LISTS.ITEM;
  69. using*: LISTS.LIST;
  70. enter*,
  71. leave*: LISTS.ITEM
  72. END;
  73. USED_PROC = POINTER TO RECORD (LISTS.ITEM)
  74. proc: PROC
  75. END;
  76. rUNIT = RECORD (LISTS.ITEM)
  77. fname*: PATHS.PATH;
  78. name*: SCAN.IDENT;
  79. idents*: LISTS.LIST;
  80. frwPointers: LISTS.LIST;
  81. gscope: IDENT;
  82. closed*: BOOLEAN;
  83. scopeLvl*: INTEGER;
  84. sysimport*: BOOLEAN;
  85. scopes*: ARRAY MAXSCOPE OF PROC
  86. END;
  87. FIELD* = POINTER TO rFIELD;
  88. PARAM* = POINTER TO rPARAM;
  89. rTYPE = RECORD (LISTS.ITEM)
  90. typ*: INTEGER;
  91. size*: INTEGER;
  92. parSize*: INTEGER;
  93. length*: INTEGER;
  94. align*: INTEGER;
  95. base*: _TYPE;
  96. fields*: LISTS.LIST;
  97. params*: LISTS.LIST;
  98. unit*: UNIT;
  99. closed*: BOOLEAN;
  100. num*: INTEGER;
  101. call*: INTEGER;
  102. _import*: BOOLEAN;
  103. noalign*: BOOLEAN
  104. END;
  105. rFIELD = RECORD (LISTS.ITEM)
  106. _type*: _TYPE;
  107. name*: SCAN.IDENT;
  108. export*: BOOLEAN;
  109. offset*: INTEGER
  110. END;
  111. rPARAM = RECORD (LISTS.ITEM)
  112. name*: SCAN.IDENT;
  113. _type*: _TYPE;
  114. vPar*: BOOLEAN;
  115. offset*: INTEGER
  116. END;
  117. rIDENT = RECORD (LISTS.ITEM)
  118. name*: SCAN.IDENT;
  119. typ*: INTEGER;
  120. export*: BOOLEAN;
  121. _import*: LISTS.ITEM;
  122. unit*: UNIT;
  123. value*: ARITH.VALUE;
  124. _type*: _TYPE;
  125. stproc*: INTEGER;
  126. global*: BOOLEAN;
  127. scopeLvl*: INTEGER;
  128. offset*: INTEGER;
  129. proc*: PROC;
  130. pos*: SCAN.POSITION
  131. END;
  132. PROGRAM = RECORD
  133. recCount: INTEGER;
  134. units*: LISTS.LIST;
  135. types*: LISTS.LIST;
  136. sysunit*: UNIT;
  137. rtl*: UNIT;
  138. bss*: INTEGER;
  139. locsize*: INTEGER;
  140. procs*: LISTS.LIST;
  141. sysflags*: SET;
  142. options*: OPTIONS;
  143. stTypes*: RECORD
  144. tINTEGER*, tBYTE*, tCHAR*, tWCHAR*, tSET*, tBOOLEAN*, tREAL*,
  145. tSTRING*, tNIL*, tCARD32*, tANYREC*, tNONE*: _TYPE
  146. END
  147. END;
  148. DELIMPORT = PROCEDURE (_import: LISTS.ITEM);
  149. VAR
  150. LowerCase*: BOOLEAN;
  151. idents: C.COLLECTION;
  152. program*: PROGRAM;
  153. PROCEDURE NewIdent (): IDENT;
  154. VAR
  155. ident: IDENT;
  156. citem: C.ITEM;
  157. BEGIN
  158. citem := C.pop(idents);
  159. IF citem = NIL THEN
  160. NEW(ident)
  161. ELSE
  162. ident := citem(IDENT)
  163. END
  164. RETURN ident
  165. END NewIdent;
  166. PROCEDURE getOffset* (varIdent: IDENT): INTEGER;
  167. VAR
  168. size, glob_align: INTEGER;
  169. BEGIN
  170. IF varIdent.offset = -1 THEN
  171. size := varIdent._type.size;
  172. IF varIdent.global THEN
  173. IF TARGETS.WinLin THEN
  174. glob_align := 16
  175. ELSE
  176. glob_align := varIdent._type.align
  177. END;
  178. IF UTILS.Align(program.bss, glob_align) THEN
  179. IF UTILS.maxint - program.bss >= size THEN
  180. varIdent.offset := program.bss;
  181. INC(program.bss, size)
  182. END
  183. END
  184. ELSE
  185. IF UTILS.Align(size, TARGETS.WordSize) THEN
  186. size := size DIV TARGETS.WordSize;
  187. IF UTILS.maxint - program.locsize >= size THEN
  188. INC(program.locsize, size);
  189. varIdent.offset := program.locsize
  190. END
  191. END
  192. END;
  193. IF varIdent.offset = -1 THEN
  194. ERRORS.Error(204)
  195. END
  196. END
  197. RETURN varIdent.offset
  198. END getOffset;
  199. PROCEDURE closeUnit* (unit: UNIT);
  200. VAR
  201. ident, prev: IDENT;
  202. offset: INTEGER;
  203. BEGIN
  204. ident := unit.idents.last(IDENT);
  205. WHILE (ident # NIL) & (ident.typ # idGUARD) DO
  206. IF (ident.typ = idVAR) & (ident.offset = -1) THEN
  207. ERRORS.HintMsg(ident.name.s, ident.pos.line, ident.pos.col, 0);
  208. IF ident.export THEN
  209. offset := getOffset(ident)
  210. END
  211. END;
  212. ident := ident.prev(IDENT)
  213. END;
  214. ident := unit.idents.last(IDENT);
  215. WHILE ident # NIL DO
  216. prev := ident.prev(IDENT);
  217. IF ~ident.export THEN
  218. LISTS.delete(unit.idents, ident);
  219. C.push(idents, ident)
  220. END;
  221. ident := prev
  222. END;
  223. unit.closed := TRUE
  224. END closeUnit;
  225. PROCEDURE IdEq* (a, b: SCAN.IDENT): BOOLEAN;
  226. RETURN (a.hash = b.hash) & (a.s = b.s)
  227. END IdEq;
  228. PROCEDURE unique (unit: UNIT; ident: SCAN.IDENT): BOOLEAN;
  229. VAR
  230. item: IDENT;
  231. BEGIN
  232. item := unit.idents.last(IDENT);
  233. WHILE (item.typ # idGUARD) & ~IdEq(item.name, ident) DO
  234. item := item.prev(IDENT)
  235. END
  236. RETURN item.typ = idGUARD
  237. END unique;
  238. PROCEDURE addIdent* (unit: UNIT; ident: SCAN.IDENT; typ: INTEGER): IDENT;
  239. VAR
  240. item: IDENT;
  241. res: BOOLEAN;
  242. proc: PROC;
  243. BEGIN
  244. ASSERT(unit # NIL);
  245. res := unique(unit, ident);
  246. IF res THEN
  247. item := NewIdent();
  248. item.name := ident;
  249. item.typ := typ;
  250. item.unit := NIL;
  251. item.export := FALSE;
  252. item._import := NIL;
  253. item._type := NIL;
  254. item.value.typ := 0;
  255. item.stproc := 0;
  256. item.global := unit.scopeLvl = 0;
  257. item.scopeLvl := unit.scopeLvl;
  258. item.offset := -1;
  259. IF item.typ IN {idPROC, idIMP} THEN
  260. NEW(proc);
  261. proc._import := NIL;
  262. proc.label := 0;
  263. proc.used := FALSE;
  264. proc.processed := FALSE;
  265. proc.using := LISTS.create(NIL);
  266. LISTS.push(program.procs, proc);
  267. item.proc := proc
  268. END;
  269. LISTS.push(unit.idents, item)
  270. ELSE
  271. item := NIL
  272. END
  273. RETURN item
  274. END addIdent;
  275. PROCEDURE UseProc* (unit: UNIT; call_proc: PROC);
  276. VAR
  277. procs: LISTS.LIST;
  278. cur: LISTS.ITEM;
  279. proc: USED_PROC;
  280. BEGIN
  281. IF unit.scopeLvl = 0 THEN
  282. call_proc.used := TRUE
  283. ELSE
  284. procs := unit.scopes[unit.scopeLvl].using;
  285. cur := procs.first;
  286. WHILE (cur # NIL) & (cur(USED_PROC).proc # call_proc) DO
  287. cur := cur.next
  288. END;
  289. IF cur = NIL THEN
  290. NEW(proc);
  291. proc.proc := call_proc;
  292. LISTS.push(procs, proc)
  293. END
  294. END
  295. END UseProc;
  296. PROCEDURE setVarsType* (unit: UNIT; _type: _TYPE);
  297. VAR
  298. item: IDENT;
  299. BEGIN
  300. ASSERT(_type # NIL);
  301. item := unit.idents.last(IDENT);
  302. WHILE (item # NIL) & (item.typ = idVAR) & (item._type = NIL) DO
  303. item._type := _type;
  304. item := item.prev(IDENT)
  305. END
  306. END setVarsType;
  307. PROCEDURE getIdent* (unit: UNIT; ident: SCAN.IDENT; currentScope: BOOLEAN): IDENT;
  308. VAR
  309. item: IDENT;
  310. BEGIN
  311. item := unit.idents.last(IDENT);
  312. IF item # NIL THEN
  313. IF currentScope THEN
  314. WHILE (item.typ # idGUARD) & ~IdEq(item.name, ident) DO
  315. item := item.prev(IDENT)
  316. END;
  317. IF item.typ = idGUARD THEN
  318. item := NIL
  319. END
  320. ELSE
  321. WHILE (item # NIL) & ~IdEq(item.name, ident) DO
  322. item := item.prev(IDENT)
  323. END
  324. END
  325. END
  326. RETURN item
  327. END getIdent;
  328. PROCEDURE openScope* (unit: UNIT; proc: PROC): BOOLEAN;
  329. VAR
  330. item: IDENT;
  331. res: BOOLEAN;
  332. BEGIN
  333. INC(unit.scopeLvl);
  334. res := unit.scopeLvl < MAXSCOPE;
  335. IF res THEN
  336. unit.scopes[unit.scopeLvl] := proc;
  337. NEW(item);
  338. item := NewIdent();
  339. item.name.s := "";
  340. item.name.hash := 0;
  341. item.typ := idGUARD;
  342. LISTS.push(unit.idents, item)
  343. END
  344. RETURN res
  345. END openScope;
  346. PROCEDURE closeScope* (unit: UNIT);
  347. VAR
  348. item: IDENT;
  349. del: IDENT;
  350. BEGIN
  351. item := unit.idents.last(IDENT);
  352. WHILE (item # NIL) & (item.typ # idGUARD) DO
  353. del := item;
  354. item := item.prev(IDENT);
  355. IF (del.typ = idVAR) & (del.offset = -1) THEN
  356. ERRORS.HintMsg(del.name.s, del.pos.line, del.pos.col, 0)
  357. END;
  358. LISTS.delete(unit.idents, del);
  359. C.push(idents, del)
  360. END;
  361. IF (item # NIL) & (item.typ = idGUARD) THEN
  362. LISTS.delete(unit.idents, item);
  363. C.push(idents, item)
  364. END;
  365. DEC(unit.scopeLvl)
  366. END closeScope;
  367. PROCEDURE frwPtr* (unit: UNIT; _type: _TYPE; baseIdent: SCAN.IDENT; pos: SCAN.POSITION);
  368. VAR
  369. newptr: FRWPTR;
  370. BEGIN
  371. ASSERT(unit # NIL);
  372. ASSERT(_type # NIL);
  373. NEW(newptr);
  374. newptr._type := _type;
  375. newptr.baseIdent := baseIdent;
  376. newptr.pos := pos;
  377. newptr.linked := FALSE;
  378. newptr.notRecord := FALSE;
  379. LISTS.push(unit.frwPointers, newptr)
  380. END frwPtr;
  381. PROCEDURE linkPtr* (unit: UNIT): FRWPTR;
  382. VAR
  383. item: FRWPTR;
  384. ident: IDENT;
  385. res: FRWPTR;
  386. BEGIN
  387. res := NIL;
  388. item := unit.frwPointers.last(FRWPTR);
  389. WHILE (item # NIL) & ~item.linked & (res = NIL) DO
  390. ident := getIdent(unit, item.baseIdent, TRUE);
  391. IF (ident # NIL) THEN
  392. IF (ident.typ = idTYPE) & (ident._type.typ = tRECORD) THEN
  393. item._type.base := ident._type;
  394. item.linked := TRUE
  395. ELSE
  396. item.notRecord := TRUE;
  397. res := item
  398. END
  399. ELSE
  400. item.notRecord := FALSE;
  401. res := item
  402. END;
  403. item := item.prev(FRWPTR)
  404. END
  405. RETURN res
  406. END linkPtr;
  407. PROCEDURE isTypeEq* (t1, t2: _TYPE): BOOLEAN;
  408. VAR
  409. res: BOOLEAN;
  410. param1, param2: LISTS.ITEM;
  411. BEGIN
  412. IF t1 = t2 THEN
  413. res := TRUE
  414. ELSIF (t1 = NIL) OR (t2 = NIL) THEN
  415. res := FALSE
  416. ELSIF (t1.typ = tPROCEDURE) & (t2.typ = tPROCEDURE) THEN
  417. param1 := t1.params.first;
  418. param2 := t2.params.first;
  419. res := ((t1.call = t2.call) OR (t1.call IN {code, _code}) OR (t2.call IN {code, _code})) & ((param1 # NIL) = (param2 # NIL));
  420. WHILE res & (param1 # NIL) & (param2 # NIL) DO
  421. res := (param1(PARAM).vPar = param2(PARAM).vPar) & isTypeEq(param1(PARAM)._type, param2(PARAM)._type);
  422. param1 := param1.next;
  423. param2 := param2.next;
  424. res := res & ((param1 # NIL) = (param2 # NIL))
  425. END;
  426. res := res & isTypeEq(t1.base, t2.base)
  427. ELSIF (t1.typ = tARRAY) & (t2.typ = tARRAY) THEN
  428. res := (t1.length = 0) & (t2.length = 0) & isTypeEq(t1.base, t2.base)
  429. ELSE
  430. res := FALSE
  431. END
  432. RETURN res
  433. END isTypeEq;
  434. PROCEDURE isBaseOf* (t0, t1: _TYPE): BOOLEAN;
  435. VAR
  436. res: BOOLEAN;
  437. BEGIN
  438. res := (t0.typ = t1.typ) & (t0.typ IN {tPOINTER, tRECORD});
  439. IF res & (t0.typ = tPOINTER) THEN
  440. t0 := t0.base;
  441. t1 := t1.base
  442. END;
  443. IF res THEN
  444. WHILE (t1 # NIL) & (t1 # t0) DO
  445. t1 := t1.base
  446. END;
  447. res := t1 # NIL
  448. END
  449. RETURN res
  450. END isBaseOf;
  451. PROCEDURE isOpenArray* (t: _TYPE): BOOLEAN;
  452. RETURN (t.typ = tARRAY) & (t.length = 0)
  453. END isOpenArray;
  454. PROCEDURE arrcomp* (src, dst: _TYPE): BOOLEAN;
  455. RETURN (dst.typ = tARRAY) & isOpenArray(src) &
  456. ~isOpenArray(src.base) & ~isOpenArray(dst.base) &
  457. isTypeEq(src.base, dst.base)
  458. END arrcomp;
  459. PROCEDURE getUnit* (name: PATHS.PATH): UNIT;
  460. VAR
  461. item: UNIT;
  462. BEGIN
  463. item := program.units.first(UNIT);
  464. WHILE (item # NIL) & (item.fname # name) DO
  465. item := item.next(UNIT)
  466. END;
  467. IF (item = NIL) & ((name = "SYSTEM") OR LowerCase & (name = "system")) THEN
  468. item := program.sysunit
  469. END
  470. RETURN item
  471. END getUnit;
  472. PROCEDURE enterStTypes (unit: UNIT);
  473. PROCEDURE enter (unit: UNIT; nameStr: SCAN.IDSTR; _type: _TYPE);
  474. VAR
  475. ident: IDENT;
  476. upper: SCAN.IDSTR;
  477. name: SCAN.IDENT;
  478. BEGIN
  479. IF LowerCase THEN
  480. SCAN.setIdent(name, nameStr);
  481. ident := addIdent(unit, name, idTYPE);
  482. ident._type := _type
  483. END;
  484. upper := nameStr;
  485. STRINGS.UpCase(upper);
  486. SCAN.setIdent(name, upper);
  487. ident := addIdent(unit, name, idTYPE);
  488. ident._type := _type
  489. END enter;
  490. BEGIN
  491. enter(unit, "integer", program.stTypes.tINTEGER);
  492. enter(unit, "byte", program.stTypes.tBYTE);
  493. enter(unit, "char", program.stTypes.tCHAR);
  494. enter(unit, "set", program.stTypes.tSET);
  495. enter(unit, "boolean", program.stTypes.tBOOLEAN);
  496. IF TARGETS.RealSize # 0 THEN
  497. enter(unit, "real", program.stTypes.tREAL)
  498. END;
  499. IF TARGETS.BitDepth >= 32 THEN
  500. enter(unit, "wchar", program.stTypes.tWCHAR)
  501. END
  502. END enterStTypes;
  503. PROCEDURE enterStProcs (unit: UNIT);
  504. PROCEDURE Enter (unit: UNIT; nameStr: SCAN.IDSTR; nfunc, tfunc: INTEGER);
  505. VAR
  506. ident: IDENT;
  507. upper: SCAN.IDSTR;
  508. name: SCAN.IDENT;
  509. BEGIN
  510. IF LowerCase THEN
  511. SCAN.setIdent(name, nameStr);
  512. ident := addIdent(unit, name, tfunc);
  513. ident.stproc := nfunc;
  514. ident._type := program.stTypes.tNONE
  515. END;
  516. upper := nameStr;
  517. STRINGS.UpCase(upper);
  518. SCAN.setIdent(name, upper);
  519. ident := addIdent(unit, name, tfunc);
  520. ident.stproc := nfunc;
  521. ident._type := program.stTypes.tNONE
  522. END Enter;
  523. BEGIN
  524. Enter(unit, "assert", stASSERT, idSTPROC);
  525. Enter(unit, "dec", stDEC, idSTPROC);
  526. Enter(unit, "excl", stEXCL, idSTPROC);
  527. Enter(unit, "inc", stINC, idSTPROC);
  528. Enter(unit, "incl", stINCL, idSTPROC);
  529. Enter(unit, "new", stNEW, idSTPROC);
  530. Enter(unit, "copy", stCOPY, idSTPROC);
  531. Enter(unit, "abs", stABS, idSTFUNC);
  532. Enter(unit, "asr", stASR, idSTFUNC);
  533. Enter(unit, "chr", stCHR, idSTFUNC);
  534. Enter(unit, "len", stLEN, idSTFUNC);
  535. Enter(unit, "lsl", stLSL, idSTFUNC);
  536. Enter(unit, "odd", stODD, idSTFUNC);
  537. Enter(unit, "ord", stORD, idSTFUNC);
  538. Enter(unit, "ror", stROR, idSTFUNC);
  539. Enter(unit, "bits", stBITS, idSTFUNC);
  540. Enter(unit, "lsr", stLSR, idSTFUNC);
  541. Enter(unit, "length", stLENGTH, idSTFUNC);
  542. Enter(unit, "min", stMIN, idSTFUNC);
  543. Enter(unit, "max", stMAX, idSTFUNC);
  544. IF TARGETS.RealSize # 0 THEN
  545. Enter(unit, "pack", stPACK, idSTPROC);
  546. Enter(unit, "unpk", stUNPK, idSTPROC);
  547. Enter(unit, "floor", stFLOOR, idSTFUNC);
  548. Enter(unit, "flt", stFLT, idSTFUNC)
  549. END;
  550. IF TARGETS.BitDepth >= 32 THEN
  551. Enter(unit, "wchr", stWCHR, idSTFUNC)
  552. END;
  553. IF TARGETS.Dispose THEN
  554. Enter(unit, "dispose", stDISPOSE, idSTPROC)
  555. END
  556. END enterStProcs;
  557. PROCEDURE newUnit* (name: SCAN.IDENT): UNIT;
  558. VAR
  559. unit: UNIT;
  560. BEGIN
  561. NEW(unit);
  562. unit.name := name;
  563. unit.closed := FALSE;
  564. unit.idents := LISTS.create(NIL);
  565. unit.frwPointers := LISTS.create(NIL);
  566. ASSERT(openScope(unit, NIL));
  567. enterStTypes(unit);
  568. enterStProcs(unit);
  569. ASSERT(openScope(unit, NIL));
  570. unit.gscope := unit.idents.last(IDENT);
  571. LISTS.push(program.units, unit);
  572. unit.scopeLvl := 0;
  573. unit.scopes[0] := NIL;
  574. unit.sysimport := FALSE;
  575. IF unit.name.s = UTILS.RTL_NAME THEN
  576. program.rtl := unit
  577. END
  578. RETURN unit
  579. END newUnit;
  580. PROCEDURE getField* (self: _TYPE; name: SCAN.IDENT; unit: UNIT): FIELD;
  581. VAR
  582. field: FIELD;
  583. BEGIN
  584. ASSERT(self # NIL);
  585. ASSERT(unit # NIL);
  586. field := NIL;
  587. WHILE (self # NIL) & (field = NIL) DO
  588. field := self.fields.first(FIELD);
  589. WHILE (field # NIL) & ~IdEq(field.name, name) DO
  590. field := field.next(FIELD)
  591. END;
  592. IF field = NIL THEN
  593. self := self.base
  594. END
  595. END;
  596. IF (field # NIL) & (self.unit # unit) & ~field.export THEN
  597. field := NIL
  598. END
  599. RETURN field
  600. END getField;
  601. PROCEDURE addField* (self: _TYPE; name: SCAN.IDENT; export: BOOLEAN): BOOLEAN;
  602. VAR
  603. field: FIELD;
  604. res: BOOLEAN;
  605. BEGIN
  606. res := getField(self, name, self.unit) = NIL;
  607. IF res THEN
  608. NEW(field);
  609. field.name := name;
  610. field.export := export;
  611. field._type := NIL;
  612. field.offset := self.size;
  613. LISTS.push(self.fields, field)
  614. END
  615. RETURN res
  616. END addField;
  617. PROCEDURE setFields* (self: _TYPE; _type: _TYPE): BOOLEAN;
  618. VAR
  619. item: FIELD;
  620. res: BOOLEAN;
  621. BEGIN
  622. ASSERT(_type # NIL);
  623. item := self.fields.first(FIELD);
  624. WHILE (item # NIL) & (item._type # NIL) DO
  625. item := item.next(FIELD)
  626. END;
  627. res := TRUE;
  628. WHILE res & (item # NIL) & (item._type = NIL) DO
  629. item._type := _type;
  630. IF ~self.noalign THEN
  631. res := UTILS.Align(self.size, _type.align)
  632. ELSE
  633. res := TRUE
  634. END;
  635. item.offset := self.size;
  636. res := res & (UTILS.maxint - self.size >= _type.size);
  637. IF res THEN
  638. INC(self.size, _type.size)
  639. END;
  640. item := item.next(FIELD)
  641. END
  642. RETURN res
  643. END setFields;
  644. PROCEDURE getParam* (self: _TYPE; name: SCAN.IDENT): PARAM;
  645. VAR
  646. item: PARAM;
  647. BEGIN
  648. item := self.params.first(PARAM);
  649. WHILE (item # NIL) & ~IdEq(item.name, name) DO
  650. item := item.next(PARAM)
  651. END
  652. RETURN item
  653. END getParam;
  654. PROCEDURE addParam* (self: _TYPE; name: SCAN.IDENT; vPar: BOOLEAN): BOOLEAN;
  655. VAR
  656. param: PARAM;
  657. res: BOOLEAN;
  658. BEGIN
  659. res := getParam(self, name) = NIL;
  660. IF res THEN
  661. NEW(param);
  662. param.name := name;
  663. param._type := NIL;
  664. param.vPar := vPar;
  665. LISTS.push(self.params, param)
  666. END
  667. RETURN res
  668. END addParam;
  669. PROCEDURE Dim* (t: _TYPE): INTEGER;
  670. VAR
  671. res: INTEGER;
  672. BEGIN
  673. res := 0;
  674. WHILE isOpenArray(t) DO
  675. t := t.base;
  676. INC(res)
  677. END
  678. RETURN res
  679. END Dim;
  680. PROCEDURE OpenBase* (t: _TYPE): _TYPE;
  681. BEGIN
  682. WHILE isOpenArray(t) DO t := t.base END
  683. RETURN t
  684. END OpenBase;
  685. PROCEDURE getFloatParamsPos* (self: _TYPE; maxoffs: INTEGER; VAR int, flt: INTEGER): SET;
  686. VAR
  687. res: SET;
  688. param: PARAM;
  689. BEGIN
  690. res := {};
  691. int := 0;
  692. flt := 0;
  693. param := self.params.first(PARAM);
  694. WHILE (param # NIL) & (param.offset <= maxoffs + STACK_FRAME) DO
  695. IF ~param.vPar & (param._type.typ = tREAL) THEN
  696. INCL(res, param.offset - STACK_FRAME);
  697. INC(flt)
  698. END;
  699. param := param.next(PARAM)
  700. END;
  701. int := self.parSize - flt
  702. RETURN res
  703. END getFloatParamsPos;
  704. PROCEDURE setParams* (self: _TYPE; _type: _TYPE);
  705. VAR
  706. item: LISTS.ITEM;
  707. param: PARAM;
  708. word, size: INTEGER;
  709. BEGIN
  710. ASSERT(_type # NIL);
  711. word := UTILS.target.bit_depth DIV 8;
  712. item := self.params.first;
  713. WHILE (item # NIL) & (item(PARAM)._type # NIL) DO
  714. item := item.next
  715. END;
  716. WHILE (item # NIL) & (item(PARAM)._type = NIL) DO
  717. param := item(PARAM);
  718. param._type := _type;
  719. IF param.vPar THEN
  720. IF _type.typ = tRECORD THEN
  721. size := 2
  722. ELSIF isOpenArray(_type) THEN
  723. size := Dim(_type) + 1
  724. ELSE
  725. size := 1
  726. END;
  727. param.offset := self.parSize + ORD(_type.typ = tRECORD) + Dim(_type) + STACK_FRAME;
  728. INC(self.parSize, size)
  729. ELSE
  730. IF _type.typ IN {tRECORD, tARRAY} THEN
  731. IF isOpenArray(_type) THEN
  732. size := Dim(_type) + 1
  733. ELSE
  734. size := 1
  735. END
  736. ELSE
  737. size := _type.size;
  738. ASSERT(UTILS.Align(size, word));
  739. size := size DIV word
  740. END;
  741. param.offset := self.parSize + Dim(_type) + STACK_FRAME;
  742. INC(self.parSize, size)
  743. END;
  744. item := item.next
  745. END
  746. END setParams;
  747. PROCEDURE enterType* (typ, size, length: INTEGER; unit: UNIT): _TYPE;
  748. VAR
  749. t: _TYPE;
  750. BEGIN
  751. NEW(t);
  752. t.typ := typ;
  753. t.size := size;
  754. t.length := length;
  755. t.align := 0;
  756. t.base := NIL;
  757. t.fields := LISTS.create(NIL);
  758. t.params := LISTS.create(NIL);
  759. t.unit := unit;
  760. t.num := 0;
  761. CASE TARGETS.BitDepth OF
  762. |16: t.call := default16
  763. |32: t.call := default32
  764. |64: t.call := default64
  765. END;
  766. t._import := FALSE;
  767. t.noalign := FALSE;
  768. t.parSize := 0;
  769. IF typ IN {tARRAY, tRECORD} THEN
  770. t.closed := FALSE;
  771. IF typ = tRECORD THEN
  772. INC(program.recCount);
  773. t.num := program.recCount
  774. END
  775. ELSE
  776. t.closed := TRUE
  777. END;
  778. LISTS.push(program.types, t)
  779. RETURN t
  780. END enterType;
  781. PROCEDURE getType* (typ: INTEGER): _TYPE;
  782. VAR
  783. res: _TYPE;
  784. BEGIN
  785. CASE typ OF
  786. |ARITH.tINTEGER: res := program.stTypes.tINTEGER
  787. |ARITH.tREAL: res := program.stTypes.tREAL
  788. |ARITH.tSET: res := program.stTypes.tSET
  789. |ARITH.tBOOLEAN: res := program.stTypes.tBOOLEAN
  790. |ARITH.tCHAR: res := program.stTypes.tCHAR
  791. |ARITH.tWCHAR: res := program.stTypes.tWCHAR
  792. |ARITH.tSTRING: res := program.stTypes.tSTRING
  793. END
  794. RETURN res
  795. END getType;
  796. PROCEDURE createSysUnit;
  797. VAR
  798. ident: IDENT;
  799. unit: UNIT;
  800. name: SCAN.IDENT;
  801. PROCEDURE EnterProc (sys: UNIT; nameStr: SCAN.IDSTR; idtyp, proc: INTEGER);
  802. VAR
  803. ident: IDENT;
  804. upper: SCAN.IDSTR;
  805. name: SCAN.IDENT;
  806. BEGIN
  807. IF LowerCase THEN
  808. SCAN.setIdent(name, nameStr);
  809. ident := addIdent(sys, name, idtyp);
  810. ident.stproc := proc;
  811. ident._type := program.stTypes.tNONE;
  812. ident.export := TRUE
  813. END;
  814. upper := nameStr;
  815. STRINGS.UpCase(upper);
  816. SCAN.setIdent(name, upper);
  817. ident := addIdent(sys, name, idtyp);
  818. ident.stproc := proc;
  819. ident._type := program.stTypes.tNONE;
  820. ident.export := TRUE
  821. END EnterProc;
  822. BEGIN
  823. SCAN.setIdent(name, "$SYSTEM");
  824. unit := newUnit(name);
  825. unit.fname := "SYSTEM";
  826. EnterProc(unit, "adr", idSYSFUNC, sysADR);
  827. EnterProc(unit, "size", idSYSFUNC, sysSIZE);
  828. EnterProc(unit, "sadr", idSYSFUNC, sysSADR);
  829. EnterProc(unit, "typeid", idSYSFUNC, sysTYPEID);
  830. EnterProc(unit, "get", idSYSPROC, sysGET);
  831. EnterProc(unit, "get8", idSYSPROC, sysGET8);
  832. EnterProc(unit, "put", idSYSPROC, sysPUT);
  833. EnterProc(unit, "put8", idSYSPROC, sysPUT8);
  834. EnterProc(unit, "code", idSYSPROC, sysCODE);
  835. EnterProc(unit, "move", idSYSPROC, sysMOVE);
  836. EnterProc(unit, "val", idSYSPROC, sysVAL);
  837. (*
  838. IF program.target.sys = mConst.Target_iMSP430 THEN
  839. EnterProc(unit, "nop", idSYSPROC, sysNOP);
  840. EnterProc(unit, "eint", idSYSPROC, sysEINT);
  841. EnterProc(unit, "dint", idSYSPROC, sysDINT)
  842. END;
  843. *)
  844. IF TARGETS.RealSize # 0 THEN
  845. EnterProc(unit, "inf", idSYSFUNC, sysINF);
  846. END;
  847. IF TARGETS.CPU IN {TARGETS.cpuX86, TARGETS.cpuAMD64} THEN
  848. EnterProc(unit, "copy", idSYSPROC, sysCOPY)
  849. END;
  850. IF TARGETS.BitDepth >= 32 THEN
  851. EnterProc(unit, "wsadr", idSYSFUNC, sysWSADR);
  852. EnterProc(unit, "put16", idSYSPROC, sysPUT16);
  853. EnterProc(unit, "put32", idSYSPROC, sysPUT32);
  854. EnterProc(unit, "get16", idSYSPROC, sysGET16);
  855. EnterProc(unit, "get32", idSYSPROC, sysGET32);
  856. IF LowerCase THEN
  857. SCAN.setIdent(name, "card32");
  858. ident := addIdent(unit, name, idTYPE);
  859. ident._type := program.stTypes.tCARD32;
  860. ident.export := TRUE
  861. END;
  862. SCAN.setIdent(name, "CARD32");
  863. ident := addIdent(unit, name, idTYPE);
  864. ident._type := program.stTypes.tCARD32;
  865. ident.export := TRUE;
  866. END;
  867. closeUnit(unit);
  868. program.sysunit := unit
  869. END createSysUnit;
  870. PROCEDURE DelUnused* (DelImport: DELIMPORT);
  871. VAR
  872. proc: PROC;
  873. flag: BOOLEAN;
  874. PROCEDURE process (proc: PROC);
  875. VAR
  876. used_proc: LISTS.ITEM;
  877. BEGIN
  878. proc.processed := TRUE;
  879. used_proc := proc.using.first;
  880. WHILE used_proc # NIL DO
  881. used_proc(USED_PROC).proc.used := TRUE;
  882. used_proc := used_proc.next
  883. END
  884. END process;
  885. BEGIN
  886. REPEAT
  887. flag := FALSE;
  888. proc := program.procs.first(PROC);
  889. WHILE proc # NIL DO
  890. IF proc.used & ~proc.processed THEN
  891. process(proc);
  892. flag := TRUE
  893. END;
  894. proc := proc.next(PROC)
  895. END
  896. UNTIL ~flag;
  897. proc := program.procs.first(PROC);
  898. WHILE proc # NIL DO
  899. IF ~proc.used THEN
  900. IF proc._import = NIL THEN
  901. IL.delete2(proc.enter, proc.leave)
  902. ELSE
  903. DelImport(proc._import)
  904. END
  905. END;
  906. proc := proc.next(PROC)
  907. END
  908. END DelUnused;
  909. PROCEDURE ResetLocSize*;
  910. BEGIN
  911. program.locsize := 0
  912. END ResetLocSize;
  913. PROCEDURE create* (options: OPTIONS);
  914. BEGIN
  915. LowerCase := options.lower;
  916. SCAN.init(options.lower);
  917. idents := C.create();
  918. UTILS.SetBitDepth(TARGETS.BitDepth, TARGETS.RealSize = 8);
  919. program.options := options;
  920. CASE TARGETS.OS OF
  921. |TARGETS.osWIN32: program.sysflags := {sf_oberon, sf_windows, sf_stdcall, sf_cdecl, sf_ccall, sf_fastcall, sf_noalign}
  922. |TARGETS.osLINUX32: program.sysflags := {sf_oberon, sf_linux, sf_stdcall, sf_cdecl, sf_ccall, sf_fastcall, sf_noalign}
  923. |TARGETS.osKOS: program.sysflags := {sf_oberon, sf_stdcall, sf_cdecl, sf_ccall, sf_fastcall, sf_noalign}
  924. |TARGETS.osWIN64: program.sysflags := {sf_oberon, sf_windows, sf_win64, sf_systemv, sf_ccall, sf_noalign}
  925. |TARGETS.osLINUX64: program.sysflags := {sf_oberon, sf_linux, sf_win64, sf_systemv, sf_ccall, sf_noalign}
  926. |TARGETS.osNONE: program.sysflags := {sf_code}
  927. END;
  928. program.recCount := -1;
  929. program.bss := 0;
  930. program.units := LISTS.create(NIL);
  931. program.types := LISTS.create(NIL);
  932. program.procs := LISTS.create(NIL);
  933. program.stTypes.tINTEGER := enterType(tINTEGER, TARGETS.WordSize, 0, NIL);
  934. program.stTypes.tBYTE := enterType(tBYTE, 1, 0, NIL);
  935. program.stTypes.tCHAR := enterType(tCHAR, 1, 0, NIL);
  936. program.stTypes.tSET := enterType(tSET, TARGETS.WordSize, 0, NIL);
  937. program.stTypes.tBOOLEAN := enterType(tBOOLEAN, 1, 0, NIL);
  938. program.stTypes.tINTEGER.align := TARGETS.WordSize;
  939. program.stTypes.tBYTE.align := 1;
  940. program.stTypes.tCHAR.align := 1;
  941. program.stTypes.tSET.align := TARGETS.WordSize;
  942. program.stTypes.tBOOLEAN.align := 1;
  943. IF TARGETS.BitDepth >= 32 THEN
  944. program.stTypes.tWCHAR := enterType(tWCHAR, 2, 0, NIL);
  945. program.stTypes.tCARD32 := enterType(tCARD32, 4, 0, NIL);
  946. program.stTypes.tWCHAR.align := 2;
  947. program.stTypes.tCARD32.align := 4
  948. END;
  949. IF TARGETS.RealSize # 0 THEN
  950. program.stTypes.tREAL := enterType(tREAL, TARGETS.RealSize, 0, NIL);
  951. IF TARGETS.OS = TARGETS.osLINUX32 THEN
  952. program.stTypes.tREAL.align := 4
  953. ELSE
  954. program.stTypes.tREAL.align := TARGETS.RealSize
  955. END
  956. END;
  957. program.stTypes.tSTRING := enterType(tSTRING, TARGETS.WordSize, 0, NIL);
  958. program.stTypes.tNIL := enterType(tNIL, TARGETS.WordSize, 0, NIL);
  959. program.stTypes.tNONE := enterType(tNONE, 0, 0, NIL);
  960. program.stTypes.tANYREC := enterType(tRECORD, 0, 0, NIL);
  961. program.stTypes.tANYREC.closed := TRUE;
  962. createSysUnit
  963. END create;
  964. END PROG.