nflw.pas 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Type checking and register allocation for nodes that influence
  5. the flow
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit nflw;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. node,cpubase,
  24. aasmbase,aasmtai,aasmcpu,
  25. {$ifdef var_notification}
  26. symnot,
  27. {$endif}
  28. symppu,symtype,symbase,symdef,symsym;
  29. type
  30. tloopnode = class(tbinarynode)
  31. t1,t2 : tnode;
  32. constructor create(tt : tnodetype;l,r,_t1,_t2 : tnode);virtual;
  33. destructor destroy;override;
  34. function getcopy : tnode;override;
  35. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  36. procedure ppuwrite(ppufile:tcompilerppufile);override;
  37. procedure derefimpl;override;
  38. procedure insertintolist(l : tnodelist);override;
  39. {$ifdef extdebug}
  40. procedure _dowrite;override;
  41. {$endif extdebug}
  42. function docompare(p: tnode): boolean; override;
  43. end;
  44. twhilerepeatnode = class(tloopnode)
  45. constructor create(l,r,_t1:Tnode;tab,cn:boolean);virtual;
  46. function det_resulttype:tnode;override;
  47. function pass_1 : tnode;override;
  48. {$ifdef state_tracking}
  49. function track_state_pass(exec_known:boolean):boolean;override;
  50. {$endif}
  51. end;
  52. twhilerepeatnodeclass = class of twhilerepeatnode;
  53. tifnode = class(tloopnode)
  54. constructor create(l,r,_t1 : tnode);virtual;
  55. function det_resulttype:tnode;override;
  56. function pass_1 : tnode;override;
  57. end;
  58. tifnodeclass = class of tifnode;
  59. tfornode = class(tloopnode)
  60. {$ifdef var_notification}
  61. loopvar_notid:cardinal;
  62. {$endif}
  63. constructor create(l,r,_t1,_t2 : tnode;back : boolean);virtual;
  64. {$ifdef var_notification}
  65. procedure loop_var_access(not_type:Tnotification_flag;symbol:Tsym);
  66. {$endif}
  67. function det_resulttype:tnode;override;
  68. function pass_1 : tnode;override;
  69. end;
  70. tfornodeclass = class of tfornode;
  71. texitnode = class(tunarynode)
  72. onlyassign : boolean;
  73. constructor create(l:tnode);virtual;
  74. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  75. procedure ppuwrite(ppufile:tcompilerppufile);override;
  76. function det_resulttype:tnode;override;
  77. function pass_1 : tnode;override;
  78. end;
  79. texitnodeclass = class of texitnode;
  80. tbreaknode = class(tnode)
  81. constructor create;virtual;
  82. function det_resulttype:tnode;override;
  83. function pass_1 : tnode;override;
  84. end;
  85. tbreaknodeclass = class of tbreaknode;
  86. tcontinuenode = class(tnode)
  87. constructor create;virtual;
  88. function det_resulttype:tnode;override;
  89. function pass_1 : tnode;override;
  90. end;
  91. tcontinuenodeclass = class of tcontinuenode;
  92. tgotonode = class(tnode)
  93. labsym : tlabelsym;
  94. exceptionblock : integer;
  95. constructor create(p : tlabelsym);virtual;
  96. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  97. procedure ppuwrite(ppufile:tcompilerppufile);override;
  98. procedure derefimpl;override;
  99. function getcopy : tnode;override;
  100. function det_resulttype:tnode;override;
  101. function pass_1 : tnode;override;
  102. function docompare(p: tnode): boolean; override;
  103. end;
  104. tgotonodeclass = class of tgotonode;
  105. tlabelnode = class(tunarynode)
  106. labelnr : tasmlabel;
  107. labsym : tlabelsym;
  108. exceptionblock : integer;
  109. constructor createcase(p : tasmlabel;l:tnode);virtual;
  110. constructor create(p : tlabelsym;l:tnode);virtual;
  111. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  112. procedure ppuwrite(ppufile:tcompilerppufile);override;
  113. procedure derefimpl;override;
  114. function getcopy : tnode;override;
  115. function det_resulttype:tnode;override;
  116. function pass_1 : tnode;override;
  117. function docompare(p: tnode): boolean; override;
  118. end;
  119. tlabelnodeclass = class of tlabelnode;
  120. traisenode = class(tbinarynode)
  121. frametree : tnode;
  122. constructor create(l,taddr,tframe:tnode);virtual;
  123. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  124. procedure ppuwrite(ppufile:tcompilerppufile);override;
  125. procedure derefimpl;override;
  126. function getcopy : tnode;override;
  127. procedure insertintolist(l : tnodelist);override;
  128. function det_resulttype:tnode;override;
  129. function pass_1 : tnode;override;
  130. function docompare(p: tnode): boolean; override;
  131. end;
  132. traisenodeclass = class of traisenode;
  133. ttryexceptnode = class(tloopnode)
  134. constructor create(l,r,_t1 : tnode);virtual;
  135. function det_resulttype:tnode;override;
  136. function pass_1 : tnode;override;
  137. end;
  138. ttryexceptnodeclass = class of ttryexceptnode;
  139. ttryfinallynode = class(tbinarynode)
  140. constructor create(l,r:tnode);virtual;
  141. function det_resulttype:tnode;override;
  142. function pass_1 : tnode;override;
  143. end;
  144. ttryfinallynodeclass = class of ttryfinallynode;
  145. tonnode = class(tbinarynode)
  146. exceptsymtable : tsymtable;
  147. excepttype : tobjectdef;
  148. constructor create(l,r:tnode);virtual;
  149. destructor destroy;override;
  150. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  151. function det_resulttype:tnode;override;
  152. function pass_1 : tnode;override;
  153. function getcopy : tnode;override;
  154. function docompare(p: tnode): boolean; override;
  155. end;
  156. tonnodeclass = class of tonnode;
  157. tfailnode = class(tnode)
  158. constructor create;virtual;
  159. function det_resulttype:tnode;override;
  160. function pass_1: tnode;override;
  161. function docompare(p: tnode): boolean; override;
  162. end;
  163. tfailnodeclass = class of tfailnode;
  164. { for compatibilty }
  165. function genloopnode(t : tnodetype;l,r,n1 : tnode;back : boolean) : tnode;
  166. var
  167. cwhilerepeatnode : twhilerepeatnodeclass;
  168. cifnode : tifnodeclass;
  169. cfornode : tfornodeclass;
  170. cexitnode : texitnodeclass;
  171. cbreaknode : tbreaknodeclass;
  172. ccontinuenode : tcontinuenodeclass;
  173. cgotonode : tgotonodeclass;
  174. clabelnode : tlabelnodeclass;
  175. craisenode : traisenodeclass;
  176. ctryexceptnode : ttryexceptnodeclass;
  177. ctryfinallynode : ttryfinallynodeclass;
  178. connode : tonnodeclass;
  179. cfailnode : tfailnodeclass;
  180. implementation
  181. uses
  182. globtype,systems,
  183. cutils,verbose,globals,
  184. symconst,symtable,paramgr,defbase,htypechk,pass_1,
  185. ncon,nmem,nld,ncnv,nbas,rgobj,
  186. {$ifdef state_tracking}
  187. nstate,
  188. {$endif}
  189. cgbase
  190. ;
  191. function genloopnode(t : tnodetype;l,r,n1 : tnode;back : boolean) : tnode;
  192. var
  193. p : tnode;
  194. begin
  195. case t of
  196. ifn:
  197. p:=cifnode.create(l,r,n1);
  198. whilerepeatn:
  199. if back then
  200. {Repeat until.}
  201. p:=cwhilerepeatnode.create(l,r,n1,false,true)
  202. else
  203. {While do.}
  204. p:=cwhilerepeatnode.create(l,r,n1,true,false);
  205. forn:
  206. p:=cfornode.create(l,r,n1,nil,back);
  207. end;
  208. genloopnode:=p;
  209. end;
  210. {****************************************************************************
  211. TLOOPNODE
  212. *****************************************************************************}
  213. constructor tloopnode.create(tt : tnodetype;l,r,_t1,_t2 : tnode);
  214. begin
  215. inherited create(tt,l,r);
  216. t1:=_t1;
  217. t2:=_t2;
  218. set_file_line(l);
  219. end;
  220. destructor tloopnode.destroy;
  221. begin
  222. t1.free;
  223. t2.free;
  224. inherited destroy;
  225. end;
  226. constructor tloopnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  227. begin
  228. inherited ppuload(t,ppufile);
  229. t1:=ppuloadnode(ppufile);
  230. t2:=ppuloadnode(ppufile);
  231. end;
  232. procedure tloopnode.ppuwrite(ppufile:tcompilerppufile);
  233. begin
  234. inherited ppuwrite(ppufile);
  235. ppuwritenode(ppufile,t1);
  236. ppuwritenode(ppufile,t2);
  237. end;
  238. procedure tloopnode.derefimpl;
  239. begin
  240. inherited derefimpl;
  241. if assigned(t1) then
  242. t1.derefimpl;
  243. if assigned(t2) then
  244. t2.derefimpl;
  245. end;
  246. function tloopnode.getcopy : tnode;
  247. var
  248. p : tloopnode;
  249. begin
  250. p:=tloopnode(inherited getcopy);
  251. if assigned(t1) then
  252. p.t1:=t1.getcopy
  253. else
  254. p.t1:=nil;
  255. if assigned(t2) then
  256. p.t2:=t2.getcopy
  257. else
  258. p.t2:=nil;
  259. getcopy:=p;
  260. end;
  261. procedure tloopnode.insertintolist(l : tnodelist);
  262. begin
  263. end;
  264. {$ifdef extdebug}
  265. procedure tloopnode._dowrite;
  266. begin
  267. inherited _dowrite;
  268. writenodeindention:=writenodeindention+' ';
  269. writenode(t1);
  270. writenode(t2);
  271. delete(writenodeindention,1,4);
  272. end;
  273. {$endif extdebug}
  274. function tloopnode.docompare(p: tnode): boolean;
  275. begin
  276. docompare :=
  277. inherited docompare(p) and
  278. t1.isequal(tloopnode(p).t1) and
  279. t2.isequal(tloopnode(p).t2);
  280. end;
  281. {****************************************************************************
  282. TWHILEREPEATNODE
  283. *****************************************************************************}
  284. constructor Twhilerepeatnode.create(l,r,_t1:Tnode;tab,cn:boolean);
  285. begin
  286. inherited create(whilerepeatn,l,r,_t1,nil);
  287. if tab then
  288. include(flags,nf_testatbegin);
  289. if cn then
  290. include(flags,nf_checknegate);
  291. end;
  292. function twhilerepeatnode.det_resulttype:tnode;
  293. var
  294. t:Tunarynode;
  295. begin
  296. result:=nil;
  297. resulttype:=voidtype;
  298. resulttypepass(left);
  299. {A not node can be removed.}
  300. if left.nodetype=notn then
  301. begin
  302. t:=Tunarynode(left);
  303. left:=Tunarynode(left).left;
  304. t.left:=nil;
  305. t.destroy;
  306. {Symdif operator, in case you are wondering:}
  307. flags:=flags >< [nf_checknegate];
  308. end;
  309. { loop instruction }
  310. if assigned(right) then
  311. resulttypepass(right);
  312. set_varstate(left,true);
  313. if codegenerror then
  314. exit;
  315. if not is_boolean(left.resulttype.def) then
  316. begin
  317. CGMessage(type_e_mismatch);
  318. exit;
  319. end;
  320. end;
  321. function twhilerepeatnode.pass_1 : tnode;
  322. var
  323. old_t_times : longint;
  324. begin
  325. result:=nil;
  326. old_t_times:=rg.t_times;
  327. { calc register weight }
  328. if not(cs_littlesize in aktglobalswitches ) then
  329. rg.t_times:=rg.t_times*8;
  330. rg.cleartempgen;
  331. firstpass(left);
  332. if codegenerror then
  333. exit;
  334. registers32:=left.registers32;
  335. registersfpu:=left.registersfpu;
  336. {$ifdef SUPPORT_MMX}
  337. registersmmx:=left.registersmmx;
  338. {$endif SUPPORT_MMX}
  339. { loop instruction }
  340. if assigned(right) then
  341. begin
  342. rg.cleartempgen;
  343. firstpass(right);
  344. if codegenerror then
  345. exit;
  346. if registers32<right.registers32 then
  347. registers32:=right.registers32;
  348. if registersfpu<right.registersfpu then
  349. registersfpu:=right.registersfpu;
  350. {$ifdef SUPPORT_MMX}
  351. if registersmmx<right.registersmmx then
  352. registersmmx:=right.registersmmx;
  353. {$endif SUPPORT_MMX}
  354. end;
  355. rg.t_times:=old_t_times;
  356. end;
  357. {$ifdef state_tracking}
  358. function Twhilerepeatnode.track_state_pass(exec_known:boolean):boolean;
  359. var condition:Tnode;
  360. code:Tnode;
  361. done:boolean;
  362. value:boolean;
  363. change:boolean;
  364. firsttest:boolean;
  365. factval:Tnode;
  366. begin
  367. track_state_pass:=false;
  368. done:=false;
  369. firsttest:=true;
  370. {For repeat until statements, first do a pass through the code.}
  371. if not(nf_testatbegin in flags) then
  372. begin
  373. code:=right.getcopy;
  374. if code.track_state_pass(exec_known) then
  375. track_state_pass:=true;
  376. code.destroy;
  377. end;
  378. repeat
  379. condition:=left.getcopy;
  380. code:=right.getcopy;
  381. change:=condition.track_state_pass(exec_known);
  382. factval:=aktstate.find_fact(left);
  383. if factval<>nil then
  384. begin
  385. condition.destroy;
  386. condition:=factval.getcopy;
  387. change:=true;
  388. end;
  389. if change then
  390. begin
  391. track_state_pass:=true;
  392. {Force new resulttype pass.}
  393. condition.resulttype.def:=nil;
  394. do_resulttypepass(condition);
  395. end;
  396. if is_constboolnode(condition) then
  397. begin
  398. {Try to turn a while loop into a repeat loop.}
  399. if firsttest then
  400. exclude(flags,testatbegin);
  401. value:=(Tordconstnode(condition).value<>0) xor checknegate;
  402. if value then
  403. begin
  404. if code.track_state_pass(exec_known) then
  405. track_state_pass:=true;
  406. end
  407. else
  408. done:=true;
  409. end
  410. else
  411. begin
  412. {Remove any modified variables from the state.}
  413. code.track_state_pass(false);
  414. done:=true;
  415. end;
  416. code.destroy;
  417. condition.destroy;
  418. firsttest:=false;
  419. until done;
  420. {The loop condition is also known, for example:
  421. while i<10 do
  422. begin
  423. ...
  424. end;
  425. When the loop is done, we do know that i<10 = false.
  426. }
  427. condition:=left.getcopy;
  428. if condition.track_state_pass(exec_known) then
  429. begin
  430. track_state_pass:=true;
  431. {Force new resulttype pass.}
  432. condition.resulttype.def:=nil;
  433. do_resulttypepass(condition);
  434. end;
  435. if not is_constboolnode(condition) then
  436. aktstate.store_fact(condition,
  437. cordconstnode.create(byte(checknegate),booltype,true))
  438. else
  439. condition.destroy;
  440. end;
  441. {$endif}
  442. {*****************************************************************************
  443. TIFNODE
  444. *****************************************************************************}
  445. constructor tifnode.create(l,r,_t1 : tnode);
  446. begin
  447. inherited create(ifn,l,r,_t1,nil);
  448. end;
  449. function tifnode.det_resulttype:tnode;
  450. begin
  451. result:=nil;
  452. resulttype:=voidtype;
  453. resulttypepass(left);
  454. { if path }
  455. if assigned(right) then
  456. resulttypepass(right);
  457. { else path }
  458. if assigned(t1) then
  459. resulttypepass(t1);
  460. set_varstate(left,true);
  461. if codegenerror then
  462. exit;
  463. if not is_boolean(left.resulttype.def) then
  464. Message1(type_e_boolean_expr_expected,left.resulttype.def.typename);
  465. end;
  466. function tifnode.pass_1 : tnode;
  467. var
  468. old_t_times : longint;
  469. hp : tnode;
  470. begin
  471. result:=nil;
  472. old_t_times:=rg.t_times;
  473. rg.cleartempgen;
  474. firstpass(left);
  475. registers32:=left.registers32;
  476. registersfpu:=left.registersfpu;
  477. {$ifdef SUPPORT_MMX}
  478. registersmmx:=left.registersmmx;
  479. {$endif SUPPORT_MMX}
  480. { determines registers weigths }
  481. if not(cs_littlesize in aktglobalswitches) then
  482. rg.t_times:=rg.t_times div 2;
  483. if rg.t_times=0 then
  484. rg.t_times:=1;
  485. { if path }
  486. if assigned(right) then
  487. begin
  488. rg.cleartempgen;
  489. firstpass(right);
  490. if registers32<right.registers32 then
  491. registers32:=right.registers32;
  492. if registersfpu<right.registersfpu then
  493. registersfpu:=right.registersfpu;
  494. {$ifdef SUPPORT_MMX}
  495. if registersmmx<right.registersmmx then
  496. registersmmx:=right.registersmmx;
  497. {$endif SUPPORT_MMX}
  498. end;
  499. { else path }
  500. if assigned(t1) then
  501. begin
  502. rg.cleartempgen;
  503. firstpass(t1);
  504. if registers32<t1.registers32 then
  505. registers32:=t1.registers32;
  506. if registersfpu<t1.registersfpu then
  507. registersfpu:=t1.registersfpu;
  508. {$ifdef SUPPORT_MMX}
  509. if registersmmx<t1.registersmmx then
  510. registersmmx:=t1.registersmmx;
  511. {$endif SUPPORT_MMX}
  512. end;
  513. { leave if we've got an error in one of the paths }
  514. if codegenerror then
  515. exit;
  516. if left.nodetype=ordconstn then
  517. begin
  518. { optimize }
  519. if tordconstnode(left).value=1 then
  520. begin
  521. hp:=right;
  522. right:=nil;
  523. { we cannot set p to nil !!! }
  524. if assigned(hp) then
  525. result:=hp
  526. else
  527. result:=cnothingnode.create;
  528. end
  529. else
  530. begin
  531. hp:=t1;
  532. t1:=nil;
  533. { we cannot set p to nil !!! }
  534. if assigned(hp) then
  535. result:=hp
  536. else
  537. result:=cnothingnode.create;
  538. end;
  539. end;
  540. rg.t_times:=old_t_times;
  541. end;
  542. {*****************************************************************************
  543. TFORNODE
  544. *****************************************************************************}
  545. constructor tfornode.create(l,r,_t1,_t2 : tnode;back : boolean);
  546. begin
  547. inherited create(forn,l,r,_t1,_t2);
  548. if back then
  549. include(flags,nf_backward);
  550. include(flags,nf_testatbegin);
  551. end;
  552. {$ifdef var_notification}
  553. procedure Tfornode.loop_var_access(not_type:Tnotification_flag;
  554. symbol:Tsym);
  555. begin
  556. end;
  557. {$endif}
  558. function tfornode.det_resulttype:tnode;
  559. var
  560. hp : tnode;
  561. begin
  562. result:=nil;
  563. resulttype:=voidtype;
  564. if left.nodetype<>assignn then
  565. begin
  566. CGMessage(cg_e_illegal_expression);
  567. exit;
  568. end;
  569. {Can we spare the first comparision?}
  570. if (right.nodetype=ordconstn) and (Tassignmentnode(left).right.nodetype=ordconstn) then
  571. if (
  572. (nf_backward in flags) and
  573. (Tordconstnode(Tassignmentnode(left).right).value>=Tordconstnode(right).value)
  574. )
  575. or not(
  576. (nf_backward in flags) and
  577. (Tordconstnode(Tassignmentnode(left).right).value<=Tordconstnode(right).value)
  578. ) then
  579. exclude(flags,nf_testatbegin);
  580. { save counter var }
  581. t2:=tassignmentnode(left).left.getcopy;
  582. resulttypepass(left);
  583. set_varstate(left,false);
  584. if assigned(t1) then
  585. begin
  586. resulttypepass(t1);
  587. if codegenerror then
  588. exit;
  589. end;
  590. { process count var }
  591. resulttypepass(t2);
  592. set_varstate(t2,true);
  593. if codegenerror then
  594. exit;
  595. { Check count var, record fields are also allowed in tp7 }
  596. hp:=t2;
  597. while (hp.nodetype=subscriptn) or
  598. ((hp.nodetype=vecn) and
  599. is_constintnode(tvecnode(hp).right)) do
  600. hp:=tunarynode(hp).left;
  601. { we need a simple loadn, but the load must be in a global symtable or
  602. in the same lexlevel }
  603. if (hp.nodetype=funcretn) or
  604. ((hp.nodetype=loadn) and
  605. ((tloadnode(hp).symtable.symtablelevel<=1) or
  606. (tloadnode(hp).symtable.symtablelevel=lexlevel))) then
  607. begin
  608. if (hp.nodetype=loadn) and
  609. (tloadnode(hp).symtableentry.typ=varsym) then
  610. tvarsym(tloadnode(hp).symtableentry).varstate:=vs_used;
  611. if (not(is_ordinal(t2.resulttype.def)) or is_64bitint(t2.resulttype.def)) then
  612. CGMessagePos(hp.fileinfo,type_e_ordinal_expr_expected);
  613. end
  614. else
  615. CGMessagePos(hp.fileinfo,cg_e_illegal_count_var);
  616. resulttypepass(right);
  617. set_varstate(right,true);
  618. inserttypeconv(right,t2.resulttype);
  619. {$ifdef var_notification}
  620. if (hp.nodetype=loadn) and (Tloadnode(hp).symtableentry.typ=varsym) then
  621. loopvar_notid:=Tvarsym(Tloadnode(hp).symtableentry).
  622. register_notification([vn_onread,vn_onwrite],@loop_var_access);
  623. {$endif}
  624. end;
  625. function tfornode.pass_1 : tnode;
  626. var
  627. old_t_times : longint;
  628. begin
  629. result:=nil;
  630. { Calc register weight }
  631. old_t_times:=rg.t_times;
  632. if not(cs_littlesize in aktglobalswitches) then
  633. rg.t_times:=rg.t_times*8;
  634. rg.cleartempgen;
  635. firstpass(left);
  636. rg.cleartempgen;
  637. if assigned(t1) then
  638. begin
  639. firstpass(t1);
  640. if codegenerror then
  641. exit;
  642. end;
  643. registers32:=t1.registers32;
  644. registersfpu:=t1.registersfpu;
  645. {$ifdef SUPPORT_MMX}
  646. registersmmx:=left.registersmmx;
  647. {$endif SUPPORT_MMX}
  648. if left.registers32>registers32 then
  649. registers32:=left.registers32;
  650. if left.registersfpu>registersfpu then
  651. registersfpu:=left.registersfpu;
  652. {$ifdef SUPPORT_MMX}
  653. if left.registersmmx>registersmmx then
  654. registersmmx:=left.registersmmx;
  655. {$endif SUPPORT_MMX}
  656. { process count var }
  657. rg.cleartempgen;
  658. firstpass(t2);
  659. if codegenerror then
  660. exit;
  661. if t2.registers32>registers32 then
  662. registers32:=t2.registers32;
  663. if t2.registersfpu>registersfpu then
  664. registersfpu:=t2.registersfpu;
  665. {$ifdef SUPPORT_MMX}
  666. if t2.registersmmx>registersmmx then
  667. registersmmx:=t2.registersmmx;
  668. {$endif SUPPORT_MMX}
  669. rg.cleartempgen;
  670. firstpass(right);
  671. if right.registers32>registers32 then
  672. registers32:=right.registers32;
  673. if right.registersfpu>registersfpu then
  674. registersfpu:=right.registersfpu;
  675. {$ifdef SUPPORT_MMX}
  676. if right.registersmmx>registersmmx then
  677. registersmmx:=right.registersmmx;
  678. {$endif SUPPORT_MMX}
  679. { we need at least one register for comparisons PM }
  680. if registers32=0 then
  681. inc(registers32);
  682. rg.t_times:=old_t_times;
  683. end;
  684. {*****************************************************************************
  685. TEXITNODE
  686. *****************************************************************************}
  687. constructor texitnode.create(l:tnode);
  688. begin
  689. inherited create(exitn,l);
  690. onlyassign:=false;
  691. end;
  692. constructor texitnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  693. begin
  694. inherited ppuload(t,ppufile);
  695. onlyassign:=boolean(ppufile.getbyte);
  696. end;
  697. procedure texitnode.ppuwrite(ppufile:tcompilerppufile);
  698. begin
  699. inherited ppuwrite(ppufile);
  700. ppufile.putbyte(byte(onlyassign));
  701. end;
  702. function texitnode.det_resulttype:tnode;
  703. var
  704. pt : tnode;
  705. begin
  706. result:=nil;
  707. { Check the 2 types }
  708. if not inlining_procedure then
  709. begin
  710. if assigned(left) then
  711. begin
  712. inserttypeconv(left,aktprocdef.rettype);
  713. if paramanager.ret_in_param(aktprocdef.rettype.def) or
  714. (procinfo.no_fast_exit) or
  715. ((procinfo.flags and pi_uses_exceptions)<>0) then
  716. begin
  717. pt:=cfuncretnode.create(aktprocdef.funcretsym);
  718. left:=cassignmentnode.create(pt,left);
  719. onlyassign:=true;
  720. end;
  721. end;
  722. end;
  723. if assigned(left) then
  724. begin
  725. resulttypepass(left);
  726. set_varstate(left,true);
  727. end;
  728. resulttype:=voidtype;
  729. end;
  730. function texitnode.pass_1 : tnode;
  731. begin
  732. result:=nil;
  733. if assigned(left) then
  734. begin
  735. firstpass(left);
  736. if codegenerror then
  737. exit;
  738. registers32:=left.registers32;
  739. registersfpu:=left.registersfpu;
  740. {$ifdef SUPPORT_MMX}
  741. registersmmx:=left.registersmmx;
  742. {$endif SUPPORT_MMX}
  743. end;
  744. end;
  745. {*****************************************************************************
  746. TBREAKNODE
  747. *****************************************************************************}
  748. constructor tbreaknode.create;
  749. begin
  750. inherited create(breakn);
  751. end;
  752. function tbreaknode.det_resulttype:tnode;
  753. begin
  754. result:=nil;
  755. resulttype:=voidtype;
  756. end;
  757. function tbreaknode.pass_1 : tnode;
  758. begin
  759. result:=nil;
  760. end;
  761. {*****************************************************************************
  762. TCONTINUENODE
  763. *****************************************************************************}
  764. constructor tcontinuenode.create;
  765. begin
  766. inherited create(continuen);
  767. end;
  768. function tcontinuenode.det_resulttype:tnode;
  769. begin
  770. result:=nil;
  771. resulttype:=voidtype;
  772. end;
  773. function tcontinuenode.pass_1 : tnode;
  774. begin
  775. result:=nil;
  776. end;
  777. {*****************************************************************************
  778. TGOTONODE
  779. *****************************************************************************}
  780. constructor tgotonode.create(p : tlabelsym);
  781. begin
  782. inherited create(goton);
  783. exceptionblock:=aktexceptblock;
  784. labsym:=p;
  785. end;
  786. constructor tgotonode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  787. begin
  788. inherited ppuload(t,ppufile);
  789. labsym:=tlabelsym(ppufile.getderef);
  790. exceptionblock:=ppufile.getbyte;
  791. end;
  792. procedure tgotonode.ppuwrite(ppufile:tcompilerppufile);
  793. begin
  794. inherited ppuwrite(ppufile);
  795. ppufile.putderef(labsym);
  796. ppufile.putbyte(exceptionblock);
  797. end;
  798. procedure tgotonode.derefimpl;
  799. begin
  800. inherited derefimpl;
  801. resolvesym(pointer(labsym));
  802. end;
  803. function tgotonode.det_resulttype:tnode;
  804. begin
  805. result:=nil;
  806. resulttype:=voidtype;
  807. end;
  808. function tgotonode.pass_1 : tnode;
  809. begin
  810. result:=nil;
  811. { check if }
  812. if assigned(labsym) and
  813. assigned(labsym.code) and
  814. (exceptionblock<>tlabelnode(labsym.code).exceptionblock) then
  815. begin
  816. writeln('goto exceptblock: ',exceptionblock);
  817. writeln('label exceptblock: ',tlabelnode(labsym.code).exceptionblock);
  818. CGMessage(cg_e_goto_inout_of_exception_block);
  819. end;
  820. end;
  821. function tgotonode.getcopy : tnode;
  822. var
  823. p : tgotonode;
  824. begin
  825. p:=tgotonode(inherited getcopy);
  826. p.labsym:=labsym;
  827. p.exceptionblock:=exceptionblock;
  828. result:=p;
  829. end;
  830. function tgotonode.docompare(p: tnode): boolean;
  831. begin
  832. docompare := false;
  833. end;
  834. {*****************************************************************************
  835. TLABELNODE
  836. *****************************************************************************}
  837. constructor tlabelnode.createcase(p : tasmlabel;l:tnode);
  838. begin
  839. inherited create(labeln,l);
  840. { it shouldn't be possible to jump to case labels using goto }
  841. exceptionblock:=-1;
  842. labsym:=nil;
  843. labelnr:=p;
  844. end;
  845. constructor tlabelnode.create(p : tlabelsym;l:tnode);
  846. begin
  847. inherited create(labeln,l);
  848. exceptionblock:=aktexceptblock;
  849. labsym:=p;
  850. labelnr:=p.lab;
  851. { save the current labelnode in the labelsym }
  852. p.code:=self;
  853. end;
  854. constructor tlabelnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  855. begin
  856. inherited ppuload(t,ppufile);
  857. labsym:=tlabelsym(ppufile.getderef);
  858. labelnr:=tasmlabel(ppufile.getasmsymbol);
  859. exceptionblock:=ppufile.getbyte;
  860. end;
  861. procedure tlabelnode.ppuwrite(ppufile:tcompilerppufile);
  862. begin
  863. inherited ppuwrite(ppufile);
  864. ppufile.putderef(labsym);
  865. ppufile.putasmsymbol(labelnr);
  866. ppufile.putbyte(exceptionblock);
  867. end;
  868. procedure tlabelnode.derefimpl;
  869. begin
  870. inherited derefimpl;
  871. resolvesym(pointer(labsym));
  872. objectlibrary.derefasmsymbol(labelnr);
  873. end;
  874. function tlabelnode.det_resulttype:tnode;
  875. begin
  876. result:=nil;
  877. { left could still be unassigned }
  878. if assigned(left) then
  879. resulttypepass(left);
  880. resulttype:=voidtype;
  881. end;
  882. function tlabelnode.pass_1 : tnode;
  883. begin
  884. result:=nil;
  885. if assigned(left) then
  886. begin
  887. rg.cleartempgen;
  888. firstpass(left);
  889. registers32:=left.registers32;
  890. registersfpu:=left.registersfpu;
  891. {$ifdef SUPPORT_MMX}
  892. registersmmx:=left.registersmmx;
  893. {$endif SUPPORT_MMX}
  894. end;
  895. end;
  896. function tlabelnode.getcopy : tnode;
  897. var
  898. p : tlabelnode;
  899. begin
  900. p:=tlabelnode(inherited getcopy);
  901. p.labelnr:=labelnr;
  902. p.exceptionblock:=exceptionblock;
  903. p.labsym:=labsym;
  904. result:=p;
  905. end;
  906. function tlabelnode.docompare(p: tnode): boolean;
  907. begin
  908. docompare := false;
  909. end;
  910. {*****************************************************************************
  911. TRAISENODE
  912. *****************************************************************************}
  913. constructor traisenode.create(l,taddr,tframe:tnode);
  914. begin
  915. inherited create(raisen,l,taddr);
  916. frametree:=tframe;
  917. end;
  918. constructor traisenode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  919. begin
  920. inherited ppuload(t,ppufile);
  921. frametree:=ppuloadnode(ppufile);
  922. end;
  923. procedure traisenode.ppuwrite(ppufile:tcompilerppufile);
  924. begin
  925. inherited ppuwrite(ppufile);
  926. ppuwritenode(ppufile,frametree);
  927. end;
  928. procedure traisenode.derefimpl;
  929. begin
  930. inherited derefimpl;
  931. if assigned(frametree) then
  932. frametree.derefimpl;
  933. end;
  934. function traisenode.getcopy : tnode;
  935. var
  936. n : traisenode;
  937. begin
  938. n:=traisenode(inherited getcopy);
  939. if assigned(frametree) then
  940. n.frametree:=frametree.getcopy
  941. else
  942. n.frametree:=nil;
  943. getcopy:=n;
  944. end;
  945. procedure traisenode.insertintolist(l : tnodelist);
  946. begin
  947. end;
  948. function traisenode.det_resulttype:tnode;
  949. begin
  950. result:=nil;
  951. resulttype:=voidtype;
  952. if assigned(left) then
  953. begin
  954. { first para must be a _class_ }
  955. resulttypepass(left);
  956. set_varstate(left,true);
  957. if codegenerror then
  958. exit;
  959. if not(is_class(left.resulttype.def)) then
  960. CGMessage(type_e_mismatch);
  961. { insert needed typeconvs for addr,frame }
  962. if assigned(right) then
  963. begin
  964. { addr }
  965. resulttypepass(right);
  966. inserttypeconv(right,voidpointertype);
  967. { frame }
  968. if assigned(frametree) then
  969. begin
  970. resulttypepass(frametree);
  971. inserttypeconv(frametree,voidpointertype);
  972. end;
  973. end;
  974. end;
  975. end;
  976. function traisenode.pass_1 : tnode;
  977. begin
  978. result:=nil;
  979. if assigned(left) then
  980. begin
  981. { first para must be a _class_ }
  982. firstpass(left);
  983. { insert needed typeconvs for addr,frame }
  984. if assigned(right) then
  985. begin
  986. { addr }
  987. firstpass(right);
  988. { frame }
  989. if assigned(frametree) then
  990. firstpass(frametree);
  991. end;
  992. left_right_max;
  993. end;
  994. end;
  995. function traisenode.docompare(p: tnode): boolean;
  996. begin
  997. docompare := false;
  998. end;
  999. {*****************************************************************************
  1000. TTRYEXCEPTNODE
  1001. *****************************************************************************}
  1002. constructor ttryexceptnode.create(l,r,_t1 : tnode);
  1003. begin
  1004. inherited create(tryexceptn,l,r,_t1,nil);
  1005. end;
  1006. function ttryexceptnode.det_resulttype:tnode;
  1007. begin
  1008. result:=nil;
  1009. resulttypepass(left);
  1010. { on statements }
  1011. if assigned(right) then
  1012. resulttypepass(right);
  1013. { else block }
  1014. if assigned(t1) then
  1015. resulttypepass(t1);
  1016. resulttype:=voidtype;
  1017. end;
  1018. function ttryexceptnode.pass_1 : tnode;
  1019. begin
  1020. result:=nil;
  1021. rg.cleartempgen;
  1022. firstpass(left);
  1023. { on statements }
  1024. if assigned(right) then
  1025. begin
  1026. rg.cleartempgen;
  1027. firstpass(right);
  1028. registers32:=max(registers32,right.registers32);
  1029. registersfpu:=max(registersfpu,right.registersfpu);
  1030. {$ifdef SUPPORT_MMX}
  1031. registersmmx:=max(registersmmx,right.registersmmx);
  1032. {$endif SUPPORT_MMX}
  1033. end;
  1034. { else block }
  1035. if assigned(t1) then
  1036. begin
  1037. firstpass(t1);
  1038. registers32:=max(registers32,t1.registers32);
  1039. registersfpu:=max(registersfpu,t1.registersfpu);
  1040. {$ifdef SUPPORT_MMX}
  1041. registersmmx:=max(registersmmx,t1.registersmmx);
  1042. {$endif SUPPORT_MMX}
  1043. end;
  1044. end;
  1045. {*****************************************************************************
  1046. TTRYFINALLYNODE
  1047. *****************************************************************************}
  1048. constructor ttryfinallynode.create(l,r:tnode);
  1049. begin
  1050. inherited create(tryfinallyn,l,r);
  1051. end;
  1052. function ttryfinallynode.det_resulttype:tnode;
  1053. begin
  1054. result:=nil;
  1055. resulttype:=voidtype;
  1056. resulttypepass(left);
  1057. set_varstate(left,true);
  1058. resulttypepass(right);
  1059. set_varstate(right,true);
  1060. end;
  1061. function ttryfinallynode.pass_1 : tnode;
  1062. begin
  1063. result:=nil;
  1064. rg.cleartempgen;
  1065. firstpass(left);
  1066. rg.cleartempgen;
  1067. firstpass(right);
  1068. left_right_max;
  1069. end;
  1070. {*****************************************************************************
  1071. TONNODE
  1072. *****************************************************************************}
  1073. constructor tonnode.create(l,r:tnode);
  1074. begin
  1075. inherited create(onn,l,r);
  1076. exceptsymtable:=nil;
  1077. excepttype:=nil;
  1078. end;
  1079. destructor tonnode.destroy;
  1080. begin
  1081. if assigned(exceptsymtable) then
  1082. exceptsymtable.free;
  1083. inherited destroy;
  1084. end;
  1085. constructor tonnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  1086. begin
  1087. inherited ppuload(t,ppufile);
  1088. exceptsymtable:=nil;
  1089. excepttype:=nil;
  1090. end;
  1091. function tonnode.getcopy : tnode;
  1092. var
  1093. n : tonnode;
  1094. begin
  1095. n:=tonnode(inherited getcopy);
  1096. n.exceptsymtable:=exceptsymtable;
  1097. n.excepttype:=excepttype;
  1098. result:=n;
  1099. end;
  1100. function tonnode.det_resulttype:tnode;
  1101. begin
  1102. result:=nil;
  1103. resulttype:=voidtype;
  1104. if not(is_class(excepttype)) then
  1105. CGMessage(type_e_mismatch);
  1106. if assigned(left) then
  1107. resulttypepass(left);
  1108. if assigned(right) then
  1109. resulttypepass(right);
  1110. end;
  1111. function tonnode.pass_1 : tnode;
  1112. begin
  1113. result:=nil;
  1114. rg.cleartempgen;
  1115. registers32:=0;
  1116. registersfpu:=0;
  1117. {$ifdef SUPPORT_MMX}
  1118. registersmmx:=0;
  1119. {$endif SUPPORT_MMX}
  1120. if assigned(left) then
  1121. begin
  1122. firstpass(left);
  1123. registers32:=left.registers32;
  1124. registersfpu:=left.registersfpu;
  1125. {$ifdef SUPPORT_MMX}
  1126. registersmmx:=left.registersmmx;
  1127. {$endif SUPPORT_MMX}
  1128. end;
  1129. rg.cleartempgen;
  1130. if assigned(right) then
  1131. begin
  1132. firstpass(right);
  1133. registers32:=max(registers32,right.registers32);
  1134. registersfpu:=max(registersfpu,right.registersfpu);
  1135. {$ifdef SUPPORT_MMX}
  1136. registersmmx:=max(registersmmx,right.registersmmx);
  1137. {$endif SUPPORT_MMX}
  1138. end;
  1139. end;
  1140. function tonnode.docompare(p: tnode): boolean;
  1141. begin
  1142. docompare := false;
  1143. end;
  1144. {*****************************************************************************
  1145. TFAILNODE
  1146. *****************************************************************************}
  1147. constructor tfailnode.create;
  1148. begin
  1149. inherited create(failn);
  1150. end;
  1151. function tfailnode.det_resulttype:tnode;
  1152. begin
  1153. result:=nil;
  1154. resulttype:=voidtype;
  1155. end;
  1156. function tfailnode.pass_1 : tnode;
  1157. begin
  1158. result:=nil;
  1159. end;
  1160. function tfailnode.docompare(p: tnode): boolean;
  1161. begin
  1162. docompare := false;
  1163. end;
  1164. begin
  1165. cwhilerepeatnode:=twhilerepeatnode;
  1166. cifnode:=tifnode;
  1167. cfornode:=tfornode;
  1168. cexitnode:=texitnode;
  1169. cgotonode:=tgotonode;
  1170. clabelnode:=tlabelnode;
  1171. craisenode:=traisenode;
  1172. ctryexceptnode:=ttryexceptnode;
  1173. ctryfinallynode:=ttryfinallynode;
  1174. connode:=tonnode;
  1175. cfailnode:=tfailnode;
  1176. end.
  1177. {
  1178. $Log$
  1179. Revision 1.52 2002-09-07 15:25:03 peter
  1180. * old logs removed and tabs fixed
  1181. Revision 1.51 2002/09/07 12:16:04 carl
  1182. * second part bug report 1996 fix, testrange in cordconstnode
  1183. only called if option is set (also make parsing a tiny faster)
  1184. Revision 1.50 2002/09/01 18:47:00 peter
  1185. * assignn check in exitnode changed to use a separate boolean as the
  1186. assignn can be changed to a calln
  1187. Revision 1.49 2002/09/01 08:01:16 daniel
  1188. * Removed sets from Tcallnode.det_resulttype
  1189. + Added read/write notifications of variables. These will be usefull
  1190. for providing information for several optimizations. For example
  1191. the value of the loop variable of a for loop does matter is the
  1192. variable is read after the for loop, but if it's no longer used
  1193. or written, it doesn't matter and this can be used to optimize
  1194. the loop code generation.
  1195. Revision 1.48 2002/08/22 15:15:20 daniel
  1196. * Fixed the detection wether the first check of a for loop can be skipped
  1197. Revision 1.47 2002/08/19 19:36:43 peter
  1198. * More fixes for cross unit inlining, all tnodes are now implemented
  1199. * Moved pocall_internconst to po_internconst because it is not a
  1200. calling type at all and it conflicted when inlining of these small
  1201. functions was requested
  1202. Revision 1.46 2002/08/17 22:09:46 florian
  1203. * result type handling in tcgcal.pass_2 overhauled
  1204. * better tnode.dowrite
  1205. * some ppc stuff fixed
  1206. Revision 1.45 2002/08/17 09:23:37 florian
  1207. * first part of procinfo rewrite
  1208. Revision 1.44 2002/07/21 06:58:49 daniel
  1209. * Changed booleans into flags
  1210. Revision 1.43 2002/07/20 11:57:54 florian
  1211. * types.pas renamed to defbase.pas because D6 contains a types
  1212. unit so this would conflicts if D6 programms are compiled
  1213. + Willamette/SSE2 instructions to assembler added
  1214. Revision 1.42 2002/07/20 11:18:18 daniel
  1215. * Small mistake fixed; the skip test was done before we know the for node
  1216. is correct.
  1217. Revision 1.40 2002/07/20 08:19:31 daniel
  1218. * State tracker automatically changes while loops into repeat loops
  1219. Revision 1.39 2002/07/19 12:55:27 daniel
  1220. * Further developed state tracking in whilerepeatn
  1221. Revision 1.38 2002/07/19 11:41:35 daniel
  1222. * State tracker work
  1223. * The whilen and repeatn are now completely unified into whilerepeatn. This
  1224. allows the state tracker to change while nodes automatically into
  1225. repeat nodes.
  1226. * Resulttypepass improvements to the notn. 'not not a' is optimized away and
  1227. 'not(a>b)' is optimized into 'a<=b'.
  1228. * Resulttypepass improvements to the whilerepeatn. 'while not a' is optimized
  1229. by removing the notn and later switchting the true and falselabels. The
  1230. same is done with 'repeat until not a'.
  1231. Revision 1.37 2002/07/16 13:57:02 florian
  1232. * raise takes now a void pointer as at and frame address
  1233. instead of a longint
  1234. Revision 1.36 2002/07/15 18:03:15 florian
  1235. * readded removed changes
  1236. Revision 1.35 2002/07/14 18:00:44 daniel
  1237. + Added the beginning of a state tracker. This will track the values of
  1238. variables through procedures and optimize things away.
  1239. Revision 1.34 2002/07/11 14:41:28 florian
  1240. * start of the new generic parameter handling
  1241. Revision 1.33 2002/07/01 18:46:23 peter
  1242. * internal linker
  1243. * reorganized aasm layer
  1244. Revision 1.32 2002/05/18 13:34:10 peter
  1245. * readded missing revisions
  1246. Revision 1.31 2002/05/16 19:46:38 carl
  1247. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1248. + try to fix temp allocation (still in ifdef)
  1249. + generic constructor calls
  1250. + start of tassembler / tmodulebase class cleanup
  1251. }