PROG.ob07 32 KB

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