nflw.pas 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668
  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,symnot,
  25. symppu,symtype,symbase,symdef,symsym;
  26. type
  27. { flags used by loop nodes }
  28. tloopflag = (
  29. { set if it is a for ... downto ... do loop }
  30. lnf_backward,
  31. { Do we need to parse childs to set var state? }
  32. lnf_varstate,
  33. { Do a test at the begin of the loop?}
  34. lnf_testatbegin,
  35. { Negate the loop test? }
  36. lnf_checknegate,
  37. { Should the value of the loop variable on exit be correct. }
  38. lnf_dont_mind_loopvar_on_exit);
  39. tloopflags = set of tloopflag;
  40. const
  41. { loop flags which must match to consider loop nodes equal regarding the flags }
  42. loopflagsequal = [lnf_backward];
  43. type
  44. tloopnode = class(tbinarynode)
  45. t1,t2 : tnode;
  46. loopflags : tloopflags;
  47. constructor create(tt : tnodetype;l,r,_t1,_t2 : tnode);virtual;
  48. destructor destroy;override;
  49. function getcopy : tnode;override;
  50. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  51. procedure ppuwrite(ppufile:tcompilerppufile);override;
  52. procedure derefimpl;override;
  53. procedure insertintolist(l : tnodelist);override;
  54. procedure printnodetree(var t:text);override;
  55. function docompare(p: tnode): boolean; override;
  56. end;
  57. twhilerepeatnode = class(tloopnode)
  58. constructor create(l,r,_t1:Tnode;tab,cn:boolean);virtual;
  59. function det_resulttype:tnode;override;
  60. function pass_1 : tnode;override;
  61. {$ifdef state_tracking}
  62. function track_state_pass(exec_known:boolean):boolean;override;
  63. {$endif}
  64. end;
  65. twhilerepeatnodeclass = class of twhilerepeatnode;
  66. tifnode = class(tloopnode)
  67. constructor create(l,r,_t1 : tnode);virtual;
  68. function det_resulttype:tnode;override;
  69. function pass_1 : tnode;override;
  70. end;
  71. tifnodeclass = class of tifnode;
  72. tfornode = class(tloopnode)
  73. loopvar_notid:cardinal;
  74. constructor create(l,r,_t1,_t2 : tnode;back : boolean);virtual;
  75. procedure loop_var_access(not_type:Tnotification_flag;symbol:Tsym);
  76. function det_resulttype:tnode;override;
  77. function pass_1 : tnode;override;
  78. end;
  79. tfornodeclass = class of tfornode;
  80. texitnode = class(tunarynode)
  81. constructor create(l:tnode);virtual;
  82. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  83. procedure ppuwrite(ppufile:tcompilerppufile);override;
  84. function det_resulttype:tnode;override;
  85. function pass_1 : tnode;override;
  86. end;
  87. texitnodeclass = class of texitnode;
  88. tbreaknode = class(tnode)
  89. constructor create;virtual;
  90. function det_resulttype:tnode;override;
  91. function pass_1 : tnode;override;
  92. end;
  93. tbreaknodeclass = class of tbreaknode;
  94. tcontinuenode = class(tnode)
  95. constructor create;virtual;
  96. function det_resulttype:tnode;override;
  97. function pass_1 : tnode;override;
  98. end;
  99. tcontinuenodeclass = class of tcontinuenode;
  100. tgotonode = class(tnode)
  101. labsym : tlabelsym;
  102. labsymderef : tderef;
  103. exceptionblock : integer;
  104. { internlab : tinterngotolabel;}
  105. constructor create(p : tlabelsym);virtual;
  106. { constructor createintern(g:tinterngotolabel);}
  107. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  108. procedure ppuwrite(ppufile:tcompilerppufile);override;
  109. procedure derefimpl;override;
  110. function getcopy : tnode;override;
  111. function det_resulttype:tnode;override;
  112. function pass_1 : tnode;override;
  113. function docompare(p: tnode): boolean; override;
  114. end;
  115. tgotonodeclass = class of tgotonode;
  116. tlabelnode = class(tunarynode)
  117. labelnr : tasmlabel;
  118. labsym : tlabelsym;
  119. labsymderef : tderef;
  120. exceptionblock : integer;
  121. constructor createcase(p : tasmlabel;l:tnode);virtual;
  122. constructor create(p : tlabelsym;l: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. function det_resulttype:tnode;override;
  128. function pass_1 : tnode;override;
  129. function docompare(p: tnode): boolean; override;
  130. end;
  131. tlabelnodeclass = class of tlabelnode;
  132. traisenode = class(tbinarynode)
  133. frametree : tnode;
  134. constructor create(l,taddr,tframe:tnode);virtual;
  135. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  136. procedure ppuwrite(ppufile:tcompilerppufile);override;
  137. procedure derefimpl;override;
  138. function getcopy : tnode;override;
  139. procedure insertintolist(l : tnodelist);override;
  140. function det_resulttype:tnode;override;
  141. function pass_1 : tnode;override;
  142. function docompare(p: tnode): boolean; override;
  143. end;
  144. traisenodeclass = class of traisenode;
  145. ttryexceptnode = class(tloopnode)
  146. constructor create(l,r,_t1 : tnode);virtual;
  147. function det_resulttype:tnode;override;
  148. function pass_1 : tnode;override;
  149. end;
  150. ttryexceptnodeclass = class of ttryexceptnode;
  151. ttryfinallynode = class(tloopnode)
  152. implicitframe : boolean;
  153. constructor create(l,r:tnode);virtual;
  154. constructor create_implicit(l,r,_t1:tnode);virtual;
  155. function det_resulttype:tnode;override;
  156. function pass_1 : tnode;override;
  157. end;
  158. ttryfinallynodeclass = class of ttryfinallynode;
  159. tonnode = class(tbinarynode)
  160. exceptsymtable : tsymtable;
  161. excepttype : tobjectdef;
  162. constructor create(l,r:tnode);virtual;
  163. destructor destroy;override;
  164. constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
  165. function det_resulttype:tnode;override;
  166. function pass_1 : tnode;override;
  167. function getcopy : tnode;override;
  168. function docompare(p: tnode): boolean; override;
  169. end;
  170. tonnodeclass = class of tonnode;
  171. { for compatibilty }
  172. function genloopnode(t : tnodetype;l,r,n1 : tnode;back : boolean) : tnode;
  173. var
  174. cwhilerepeatnode : twhilerepeatnodeclass;
  175. cifnode : tifnodeclass;
  176. cfornode : tfornodeclass;
  177. cexitnode : texitnodeclass;
  178. cbreaknode : tbreaknodeclass;
  179. ccontinuenode : tcontinuenodeclass;
  180. cgotonode : tgotonodeclass;
  181. clabelnode : tlabelnodeclass;
  182. craisenode : traisenodeclass;
  183. ctryexceptnode : ttryexceptnodeclass;
  184. ctryfinallynode : ttryfinallynodeclass;
  185. connode : tonnodeclass;
  186. implementation
  187. uses
  188. globtype,systems,
  189. cutils,verbose,globals,
  190. symconst,symtable,paramgr,defutil,htypechk,pass_1,
  191. ncal,nadd,ncon,nmem,nld,ncnv,nbas,cgobj,
  192. {$ifdef state_tracking}
  193. nstate,
  194. {$endif}
  195. cgbase,procinfo
  196. ;
  197. function genloopnode(t : tnodetype;l,r,n1 : tnode;back : boolean) : tnode;
  198. var
  199. p : tnode;
  200. begin
  201. case t of
  202. ifn:
  203. p:=cifnode.create(l,r,n1);
  204. whilerepeatn:
  205. if back then
  206. {Repeat until.}
  207. p:=cwhilerepeatnode.create(l,r,n1,false,true)
  208. else
  209. {While do.}
  210. p:=cwhilerepeatnode.create(l,r,n1,true,false);
  211. forn:
  212. p:=cfornode.create(l,r,n1,nil,back);
  213. end;
  214. genloopnode:=p;
  215. end;
  216. {****************************************************************************
  217. TLOOPNODE
  218. *****************************************************************************}
  219. constructor tloopnode.create(tt : tnodetype;l,r,_t1,_t2 : tnode);
  220. begin
  221. inherited create(tt,l,r);
  222. t1:=_t1;
  223. t2:=_t2;
  224. set_file_line(l);
  225. end;
  226. destructor tloopnode.destroy;
  227. begin
  228. t1.free;
  229. t2.free;
  230. inherited destroy;
  231. end;
  232. constructor tloopnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  233. begin
  234. inherited ppuload(t,ppufile);
  235. t1:=ppuloadnode(ppufile);
  236. t2:=ppuloadnode(ppufile);
  237. end;
  238. procedure tloopnode.ppuwrite(ppufile:tcompilerppufile);
  239. begin
  240. inherited ppuwrite(ppufile);
  241. ppuwritenode(ppufile,t1);
  242. ppuwritenode(ppufile,t2);
  243. end;
  244. procedure tloopnode.derefimpl;
  245. begin
  246. inherited derefimpl;
  247. if assigned(t1) then
  248. t1.derefimpl;
  249. if assigned(t2) then
  250. t2.derefimpl;
  251. end;
  252. function tloopnode.getcopy : tnode;
  253. var
  254. p : tloopnode;
  255. begin
  256. p:=tloopnode(inherited getcopy);
  257. if assigned(t1) then
  258. p.t1:=t1.getcopy
  259. else
  260. p.t1:=nil;
  261. if assigned(t2) then
  262. p.t2:=t2.getcopy
  263. else
  264. p.t2:=nil;
  265. getcopy:=p;
  266. end;
  267. procedure tloopnode.insertintolist(l : tnodelist);
  268. begin
  269. end;
  270. procedure tloopnode.printnodetree(var t:text);
  271. begin
  272. write(t,printnodeindention,'(');
  273. printnodeindent;
  274. printnodeinfo(t);
  275. printnode(t,left);
  276. printnode(t,right);
  277. printnode(t,t1);
  278. printnode(t,t2);
  279. printnodeunindent;
  280. writeln(t,printnodeindention,')');
  281. end;
  282. function tloopnode.docompare(p: tnode): boolean;
  283. begin
  284. docompare :=
  285. inherited docompare(p) and
  286. (loopflags*loopflagsequal=tloopnode(p).loopflags*loopflagsequal) and
  287. t1.isequal(tloopnode(p).t1) and
  288. t2.isequal(tloopnode(p).t2);
  289. end;
  290. {****************************************************************************
  291. TWHILEREPEATNODE
  292. *****************************************************************************}
  293. constructor Twhilerepeatnode.create(l,r,_t1:Tnode;tab,cn:boolean);
  294. begin
  295. inherited create(whilerepeatn,l,r,_t1,nil);
  296. if tab then
  297. include(loopflags, lnf_testatbegin);
  298. if cn then
  299. include(loopflags,lnf_checknegate);
  300. end;
  301. function twhilerepeatnode.det_resulttype:tnode;
  302. var
  303. t:Tunarynode;
  304. begin
  305. result:=nil;
  306. resulttype:=voidtype;
  307. resulttypepass(left);
  308. {A not node can be removed.}
  309. if left.nodetype=notn then
  310. begin
  311. t:=Tunarynode(left);
  312. left:=Tunarynode(left).left;
  313. t.left:=nil;
  314. t.destroy;
  315. {$ifdef Delphi}
  316. { How can this be handled in Delphi ? }
  317. RunError(255);
  318. {$else}
  319. {Symdif operator, in case you are wondering:}
  320. loopflags:=loopflags >< [lnf_checknegate];
  321. {$endif}
  322. end;
  323. { loop instruction }
  324. if assigned(right) then
  325. resulttypepass(right);
  326. set_varstate(left,vs_used,true);
  327. if codegenerror then
  328. exit;
  329. if not is_boolean(left.resulttype.def) then
  330. begin
  331. CGMessage(type_e_mismatch);
  332. exit;
  333. end;
  334. end;
  335. function twhilerepeatnode.pass_1 : tnode;
  336. var
  337. old_t_times : longint;
  338. begin
  339. result:=nil;
  340. expectloc:=LOC_VOID;
  341. old_t_times:=cg.t_times;
  342. { calc register weight }
  343. if not(cs_littlesize in aktglobalswitches ) then
  344. cg.t_times:=cg.t_times*8;
  345. firstpass(left);
  346. if codegenerror then
  347. exit;
  348. registers32:=left.registers32;
  349. registersfpu:=left.registersfpu;
  350. {$ifdef SUPPORT_MMX}
  351. registersmmx:=left.registersmmx;
  352. {$endif SUPPORT_MMX}
  353. { loop instruction }
  354. if assigned(right) then
  355. begin
  356. firstpass(right);
  357. if codegenerror then
  358. exit;
  359. if registers32<right.registers32 then
  360. registers32:=right.registers32;
  361. if registersfpu<right.registersfpu then
  362. registersfpu:=right.registersfpu;
  363. {$ifdef SUPPORT_MMX}
  364. if registersmmx<right.registersmmx then
  365. registersmmx:=right.registersmmx;
  366. {$endif SUPPORT_MMX}
  367. end;
  368. cg.t_times:=old_t_times;
  369. end;
  370. {$ifdef state_tracking}
  371. function Twhilerepeatnode.track_state_pass(exec_known:boolean):boolean;
  372. var condition:Tnode;
  373. code:Tnode;
  374. done:boolean;
  375. value:boolean;
  376. change:boolean;
  377. firsttest:boolean;
  378. factval:Tnode;
  379. begin
  380. track_state_pass:=false;
  381. done:=false;
  382. firsttest:=true;
  383. {For repeat until statements, first do a pass through the code.}
  384. if not(lnf_testatbegin in flags) then
  385. begin
  386. code:=right.getcopy;
  387. if code.track_state_pass(exec_known) then
  388. track_state_pass:=true;
  389. code.destroy;
  390. end;
  391. repeat
  392. condition:=left.getcopy;
  393. code:=right.getcopy;
  394. change:=condition.track_state_pass(exec_known);
  395. factval:=aktstate.find_fact(left);
  396. if factval<>nil then
  397. begin
  398. condition.destroy;
  399. condition:=factval.getcopy;
  400. change:=true;
  401. end;
  402. if change then
  403. begin
  404. track_state_pass:=true;
  405. {Force new resulttype pass.}
  406. condition.resulttype.def:=nil;
  407. do_resulttypepass(condition);
  408. end;
  409. if is_constboolnode(condition) then
  410. begin
  411. {Try to turn a while loop into a repeat loop.}
  412. if firsttest then
  413. exclude(flags,testatbegin);
  414. value:=(Tordconstnode(condition).value<>0) xor checknegate;
  415. if value then
  416. begin
  417. if code.track_state_pass(exec_known) then
  418. track_state_pass:=true;
  419. end
  420. else
  421. done:=true;
  422. end
  423. else
  424. begin
  425. {Remove any modified variables from the state.}
  426. code.track_state_pass(false);
  427. done:=true;
  428. end;
  429. code.destroy;
  430. condition.destroy;
  431. firsttest:=false;
  432. until done;
  433. {The loop condition is also known, for example:
  434. while i<10 do
  435. begin
  436. ...
  437. end;
  438. When the loop is done, we do know that i<10 = false.
  439. }
  440. condition:=left.getcopy;
  441. if condition.track_state_pass(exec_known) then
  442. begin
  443. track_state_pass:=true;
  444. {Force new resulttype pass.}
  445. condition.resulttype.def:=nil;
  446. do_resulttypepass(condition);
  447. end;
  448. if not is_constboolnode(condition) then
  449. aktstate.store_fact(condition,
  450. cordconstnode.create(byte(checknegate),booltype,true))
  451. else
  452. condition.destroy;
  453. end;
  454. {$endif}
  455. {*****************************************************************************
  456. TIFNODE
  457. *****************************************************************************}
  458. constructor tifnode.create(l,r,_t1 : tnode);
  459. begin
  460. inherited create(ifn,l,r,_t1,nil);
  461. end;
  462. function tifnode.det_resulttype:tnode;
  463. begin
  464. result:=nil;
  465. resulttype:=voidtype;
  466. resulttypepass(left);
  467. { if path }
  468. if assigned(right) then
  469. resulttypepass(right);
  470. { else path }
  471. if assigned(t1) then
  472. resulttypepass(t1);
  473. set_varstate(left,vs_used,true);
  474. if codegenerror then
  475. exit;
  476. if not is_boolean(left.resulttype.def) then
  477. Message1(type_e_boolean_expr_expected,left.resulttype.def.typename);
  478. end;
  479. function tifnode.pass_1 : tnode;
  480. var
  481. old_t_times : longint;
  482. hp : tnode;
  483. begin
  484. result:=nil;
  485. expectloc:=LOC_VOID;
  486. old_t_times:=cg.t_times;
  487. firstpass(left);
  488. registers32:=left.registers32;
  489. registersfpu:=left.registersfpu;
  490. {$ifdef SUPPORT_MMX}
  491. registersmmx:=left.registersmmx;
  492. {$endif SUPPORT_MMX}
  493. { determines registers weigths }
  494. if not(cs_littlesize in aktglobalswitches) then
  495. cg.t_times:=cg.t_times div 2;
  496. if cg.t_times=0 then
  497. cg.t_times:=1;
  498. { if path }
  499. if assigned(right) then
  500. begin
  501. firstpass(right);
  502. if registers32<right.registers32 then
  503. registers32:=right.registers32;
  504. if registersfpu<right.registersfpu then
  505. registersfpu:=right.registersfpu;
  506. {$ifdef SUPPORT_MMX}
  507. if registersmmx<right.registersmmx then
  508. registersmmx:=right.registersmmx;
  509. {$endif SUPPORT_MMX}
  510. end;
  511. { else path }
  512. if assigned(t1) then
  513. begin
  514. firstpass(t1);
  515. if registers32<t1.registers32 then
  516. registers32:=t1.registers32;
  517. if registersfpu<t1.registersfpu then
  518. registersfpu:=t1.registersfpu;
  519. {$ifdef SUPPORT_MMX}
  520. if registersmmx<t1.registersmmx then
  521. registersmmx:=t1.registersmmx;
  522. {$endif SUPPORT_MMX}
  523. end;
  524. { leave if we've got an error in one of the paths }
  525. if codegenerror then
  526. exit;
  527. if left.nodetype=ordconstn then
  528. begin
  529. { optimize }
  530. if tordconstnode(left).value=1 then
  531. begin
  532. hp:=right;
  533. right:=nil;
  534. { we cannot set p to nil !!! }
  535. if assigned(hp) then
  536. result:=hp
  537. else
  538. result:=cnothingnode.create;
  539. end
  540. else
  541. begin
  542. hp:=t1;
  543. t1:=nil;
  544. { we cannot set p to nil !!! }
  545. if assigned(hp) then
  546. result:=hp
  547. else
  548. result:=cnothingnode.create;
  549. end;
  550. end;
  551. cg.t_times:=old_t_times;
  552. end;
  553. {*****************************************************************************
  554. TFORNODE
  555. *****************************************************************************}
  556. constructor tfornode.create(l,r,_t1,_t2 : tnode;back : boolean);
  557. begin
  558. inherited create(forn,l,r,_t1,_t2);
  559. if back then
  560. include(loopflags,lnf_backward);
  561. include(loopflags,lnf_testatbegin);
  562. end;
  563. procedure Tfornode.loop_var_access(not_type:Tnotification_flag;
  564. symbol:Tsym);
  565. begin
  566. {If there is a read access, the value of the loop counter is important;
  567. at the end of the loop the loop variable should contain the value it
  568. had in the last iteration.}
  569. if not_type=vn_onwrite then
  570. begin
  571. writeln('Loopvar does not matter on exit');
  572. end
  573. else
  574. begin
  575. exclude(loopflags,lnf_dont_mind_loopvar_on_exit);
  576. writeln('Loopvar does matter on exit');
  577. end;
  578. Tvarsym(symbol).unregister_notification(loopvar_notid);
  579. end;
  580. function tfornode.det_resulttype:tnode;
  581. var
  582. hp : tnode;
  583. begin
  584. result:=nil;
  585. resulttype:=voidtype;
  586. if left.nodetype<>assignn then
  587. begin
  588. CGMessage(cg_e_illegal_expression);
  589. exit;
  590. end;
  591. {Can we spare the first comparision?}
  592. if (right.nodetype=ordconstn) and (Tassignmentnode(left).right.nodetype=ordconstn) then
  593. if (
  594. (lnf_backward in loopflags) and
  595. (Tordconstnode(Tassignmentnode(left).right).value>=Tordconstnode(right).value)
  596. )
  597. or not(
  598. (lnf_backward in loopflags) and
  599. (Tordconstnode(Tassignmentnode(left).right).value<=Tordconstnode(right).value)
  600. ) then
  601. exclude(loopflags,lnf_testatbegin);
  602. { save counter var }
  603. t2:=tassignmentnode(left).left.getcopy;
  604. resulttypepass(left);
  605. set_varstate(left,vs_used,true);
  606. if assigned(t1) then
  607. begin
  608. resulttypepass(t1);
  609. if codegenerror then
  610. exit;
  611. end;
  612. { process count var }
  613. resulttypepass(t2);
  614. set_varstate(t2,vs_used,false);
  615. if codegenerror then
  616. exit;
  617. { Check count var, record fields are also allowed in tp7 }
  618. hp:=t2;
  619. while (hp.nodetype=subscriptn) or
  620. ((hp.nodetype=vecn) and
  621. is_constintnode(tvecnode(hp).right)) do
  622. hp:=tunarynode(hp).left;
  623. { we need a simple loadn, but the load must be in a global symtable or
  624. in the same level as the para of the current proc }
  625. if (
  626. (hp.nodetype=loadn) and
  627. (
  628. (tloadnode(hp).symtable.symtablelevel=main_program_level) or
  629. (tloadnode(hp).symtable.symtablelevel=current_procinfo.procdef.parast.symtablelevel)
  630. ) and
  631. not(
  632. (tloadnode(hp).symtableentry.typ=varsym) and
  633. ((tvarsym(tloadnode(hp).symtableentry).varspez in [vs_var,vs_out]) or
  634. (vo_is_thread_var in tvarsym(tloadnode(hp).symtableentry).varoptions))
  635. )
  636. ) then
  637. begin
  638. if (hp.nodetype=loadn) and
  639. (tloadnode(hp).symtableentry.typ=varsym) then
  640. tvarsym(tloadnode(hp).symtableentry).varstate:=vs_used;
  641. if not(is_ordinal(t2.resulttype.def))
  642. {$ifndef cpu64bit}
  643. or is_64bitint(t2.resulttype.def)
  644. {$endif cpu64bit}
  645. then
  646. CGMessagePos(hp.fileinfo,type_e_ordinal_expr_expected);
  647. end
  648. else
  649. CGMessagePos(hp.fileinfo,cg_e_illegal_count_var);
  650. resulttypepass(right);
  651. set_varstate(right,vs_used,true);
  652. inserttypeconv(right,t2.resulttype);
  653. end;
  654. function tfornode.pass_1 : tnode;
  655. var
  656. old_t_times : longint;
  657. {$ifdef loopvar_dont_mind}
  658. hp : Tnode;
  659. {$endif loopvar_dont_mind}
  660. begin
  661. result:=nil;
  662. expectloc:=LOC_VOID;
  663. { Calc register weight }
  664. old_t_times:=cg.t_times;
  665. if not(cs_littlesize in aktglobalswitches) then
  666. cg.t_times:=cg.t_times*8;
  667. firstpass(left);
  668. if assigned(t1) then
  669. begin
  670. firstpass(t1);
  671. if codegenerror then
  672. exit;
  673. end;
  674. registers32:=t1.registers32;
  675. registersfpu:=t1.registersfpu;
  676. {$ifdef SUPPORT_MMX}
  677. registersmmx:=left.registersmmx;
  678. {$endif SUPPORT_MMX}
  679. if left.registers32>registers32 then
  680. registers32:=left.registers32;
  681. if left.registersfpu>registersfpu then
  682. registersfpu:=left.registersfpu;
  683. {$ifdef SUPPORT_MMX}
  684. if left.registersmmx>registersmmx then
  685. registersmmx:=left.registersmmx;
  686. {$endif SUPPORT_MMX}
  687. { process count var }
  688. firstpass(t2);
  689. if codegenerror then
  690. exit;
  691. if t2.registers32>registers32 then
  692. registers32:=t2.registers32;
  693. if t2.registersfpu>registersfpu then
  694. registersfpu:=t2.registersfpu;
  695. {$ifdef SUPPORT_MMX}
  696. if t2.registersmmx>registersmmx then
  697. registersmmx:=t2.registersmmx;
  698. {$endif SUPPORT_MMX}
  699. firstpass(right);
  700. {$ifdef loopvar_dont_mind}
  701. { Check count var, record fields are also allowed in tp7 }
  702. include(loopflags,lnf_dont_mind_loopvar_on_exit);
  703. hp:=t2;
  704. while (hp.nodetype=subscriptn) or
  705. ((hp.nodetype=vecn) and
  706. is_constintnode(tvecnode(hp).right)) do
  707. hp:=tunarynode(hp).left;
  708. if (hp.nodetype=loadn) and (Tloadnode(hp).symtableentry.typ=varsym) then
  709. loopvar_notid:=Tvarsym(Tloadnode(hp).symtableentry).
  710. register_notification([vn_onread,vn_onwrite],@loop_var_access);
  711. {$endif}
  712. if right.registers32>registers32 then
  713. registers32:=right.registers32;
  714. if right.registersfpu>registersfpu then
  715. registersfpu:=right.registersfpu;
  716. {$ifdef SUPPORT_MMX}
  717. if right.registersmmx>registersmmx then
  718. registersmmx:=right.registersmmx;
  719. {$endif SUPPORT_MMX}
  720. { we need at least one register for comparisons PM }
  721. if registers32=0 then
  722. inc(registers32);
  723. cg.t_times:=old_t_times;
  724. end;
  725. {*****************************************************************************
  726. TEXITNODE
  727. *****************************************************************************}
  728. constructor texitnode.create(l:tnode);
  729. begin
  730. inherited create(exitn,l);
  731. end;
  732. constructor texitnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  733. begin
  734. inherited ppuload(t,ppufile);
  735. end;
  736. procedure texitnode.ppuwrite(ppufile:tcompilerppufile);
  737. begin
  738. inherited ppuwrite(ppufile);
  739. end;
  740. function texitnode.det_resulttype:tnode;
  741. begin
  742. result:=nil;
  743. if assigned(left) then
  744. begin
  745. { add assignment to funcretsym }
  746. inserttypeconv(left,current_procinfo.procdef.rettype);
  747. left:=cassignmentnode.create(
  748. cloadnode.create(current_procinfo.procdef.funcretsym,current_procinfo.procdef.funcretsym.owner),
  749. left);
  750. resulttypepass(left);
  751. set_varstate(left,vs_used,true);
  752. end;
  753. resulttype:=voidtype;
  754. end;
  755. function texitnode.pass_1 : tnode;
  756. begin
  757. result:=nil;
  758. expectloc:=LOC_VOID;
  759. if assigned(left) then
  760. begin
  761. firstpass(left);
  762. if codegenerror then
  763. exit;
  764. registers32:=left.registers32;
  765. registersfpu:=left.registersfpu;
  766. {$ifdef SUPPORT_MMX}
  767. registersmmx:=left.registersmmx;
  768. {$endif SUPPORT_MMX}
  769. end;
  770. end;
  771. {*****************************************************************************
  772. TBREAKNODE
  773. *****************************************************************************}
  774. constructor tbreaknode.create;
  775. begin
  776. inherited create(breakn);
  777. end;
  778. function tbreaknode.det_resulttype:tnode;
  779. begin
  780. result:=nil;
  781. resulttype:=voidtype;
  782. end;
  783. function tbreaknode.pass_1 : tnode;
  784. begin
  785. result:=nil;
  786. expectloc:=LOC_VOID;
  787. end;
  788. {*****************************************************************************
  789. TCONTINUENODE
  790. *****************************************************************************}
  791. constructor tcontinuenode.create;
  792. begin
  793. inherited create(continuen);
  794. end;
  795. function tcontinuenode.det_resulttype:tnode;
  796. begin
  797. result:=nil;
  798. resulttype:=voidtype;
  799. end;
  800. function tcontinuenode.pass_1 : tnode;
  801. begin
  802. result:=nil;
  803. expectloc:=LOC_VOID;
  804. end;
  805. {*****************************************************************************
  806. TGOTONODE
  807. *****************************************************************************}
  808. constructor tgotonode.create(p : tlabelsym);
  809. begin
  810. inherited create(goton);
  811. exceptionblock:=aktexceptblock;
  812. labsym:=p;
  813. end;
  814. constructor tgotonode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  815. begin
  816. inherited ppuload(t,ppufile);
  817. ppufile.getderef(labsymderef);
  818. exceptionblock:=ppufile.getbyte;
  819. end;
  820. procedure tgotonode.ppuwrite(ppufile:tcompilerppufile);
  821. begin
  822. inherited ppuwrite(ppufile);
  823. ppufile.putderef(labsym,labsymderef);
  824. ppufile.putbyte(exceptionblock);
  825. end;
  826. procedure tgotonode.derefimpl;
  827. begin
  828. inherited derefimpl;
  829. labsym:=tlabelsym(labsymderef.resolve);
  830. end;
  831. function tgotonode.det_resulttype:tnode;
  832. begin
  833. result:=nil;
  834. resulttype:=voidtype;
  835. end;
  836. function tgotonode.pass_1 : tnode;
  837. begin
  838. result:=nil;
  839. expectloc:=LOC_VOID;
  840. { check if }
  841. if assigned(labsym) and
  842. assigned(labsym.code) and
  843. (exceptionblock<>tlabelnode(labsym.code).exceptionblock) then
  844. begin
  845. writeln('goto exceptblock: ',exceptionblock);
  846. writeln('label exceptblock: ',tlabelnode(labsym.code).exceptionblock);
  847. CGMessage(cg_e_goto_inout_of_exception_block);
  848. end;
  849. end;
  850. function tgotonode.getcopy : tnode;
  851. var
  852. p : tgotonode;
  853. begin
  854. p:=tgotonode(inherited getcopy);
  855. p.labsym:=labsym;
  856. p.exceptionblock:=exceptionblock;
  857. result:=p;
  858. end;
  859. function tgotonode.docompare(p: tnode): boolean;
  860. begin
  861. docompare := false;
  862. end;
  863. {*****************************************************************************
  864. TLABELNODE
  865. *****************************************************************************}
  866. constructor tlabelnode.createcase(p : tasmlabel;l:tnode);
  867. begin
  868. inherited create(labeln,l);
  869. { it shouldn't be possible to jump to case labels using goto }
  870. exceptionblock:=-1;
  871. labsym:=nil;
  872. labelnr:=p;
  873. end;
  874. constructor tlabelnode.create(p : tlabelsym;l:tnode);
  875. begin
  876. inherited create(labeln,l);
  877. exceptionblock:=aktexceptblock;
  878. labsym:=p;
  879. labelnr:=p.lab;
  880. { save the current labelnode in the labelsym }
  881. p.code:=self;
  882. end;
  883. constructor tlabelnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  884. begin
  885. inherited ppuload(t,ppufile);
  886. ppufile.getderef(labsymderef);
  887. labelnr:=tasmlabel(ppufile.getasmsymbol);
  888. exceptionblock:=ppufile.getbyte;
  889. end;
  890. procedure tlabelnode.ppuwrite(ppufile:tcompilerppufile);
  891. begin
  892. inherited ppuwrite(ppufile);
  893. ppufile.putderef(labsym,labsymderef);
  894. ppufile.putasmsymbol(labelnr);
  895. ppufile.putbyte(exceptionblock);
  896. end;
  897. procedure tlabelnode.derefimpl;
  898. begin
  899. inherited derefimpl;
  900. labsym:=tlabelsym(labsymderef.resolve);
  901. objectlibrary.derefasmsymbol(tasmsymbol(labelnr));
  902. end;
  903. function tlabelnode.det_resulttype:tnode;
  904. begin
  905. result:=nil;
  906. { left could still be unassigned }
  907. if assigned(left) then
  908. resulttypepass(left);
  909. resulttype:=voidtype;
  910. end;
  911. function tlabelnode.pass_1 : tnode;
  912. begin
  913. result:=nil;
  914. expectloc:=LOC_VOID;
  915. if assigned(left) then
  916. begin
  917. firstpass(left);
  918. registers32:=left.registers32;
  919. registersfpu:=left.registersfpu;
  920. {$ifdef SUPPORT_MMX}
  921. registersmmx:=left.registersmmx;
  922. {$endif SUPPORT_MMX}
  923. end;
  924. end;
  925. function tlabelnode.getcopy : tnode;
  926. var
  927. p : tlabelnode;
  928. begin
  929. p:=tlabelnode(inherited getcopy);
  930. p.labelnr:=labelnr;
  931. p.exceptionblock:=exceptionblock;
  932. p.labsym:=labsym;
  933. result:=p;
  934. end;
  935. function tlabelnode.docompare(p: tnode): boolean;
  936. begin
  937. docompare := false;
  938. end;
  939. {*****************************************************************************
  940. TRAISENODE
  941. *****************************************************************************}
  942. constructor traisenode.create(l,taddr,tframe:tnode);
  943. begin
  944. inherited create(raisen,l,taddr);
  945. frametree:=tframe;
  946. end;
  947. constructor traisenode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  948. begin
  949. inherited ppuload(t,ppufile);
  950. frametree:=ppuloadnode(ppufile);
  951. end;
  952. procedure traisenode.ppuwrite(ppufile:tcompilerppufile);
  953. begin
  954. inherited ppuwrite(ppufile);
  955. ppuwritenode(ppufile,frametree);
  956. end;
  957. procedure traisenode.derefimpl;
  958. begin
  959. inherited derefimpl;
  960. if assigned(frametree) then
  961. frametree.derefimpl;
  962. end;
  963. function traisenode.getcopy : tnode;
  964. var
  965. n : traisenode;
  966. begin
  967. n:=traisenode(inherited getcopy);
  968. if assigned(frametree) then
  969. n.frametree:=frametree.getcopy
  970. else
  971. n.frametree:=nil;
  972. getcopy:=n;
  973. end;
  974. procedure traisenode.insertintolist(l : tnodelist);
  975. begin
  976. end;
  977. function traisenode.det_resulttype:tnode;
  978. begin
  979. result:=nil;
  980. resulttype:=voidtype;
  981. if assigned(left) then
  982. begin
  983. { first para must be a _class_ }
  984. resulttypepass(left);
  985. set_varstate(left,vs_used,true);
  986. if codegenerror then
  987. exit;
  988. if not(is_class(left.resulttype.def)) then
  989. CGMessage(type_e_mismatch);
  990. { insert needed typeconvs for addr,frame }
  991. if assigned(right) then
  992. begin
  993. { addr }
  994. resulttypepass(right);
  995. inserttypeconv(right,voidpointertype);
  996. { frame }
  997. if assigned(frametree) then
  998. begin
  999. resulttypepass(frametree);
  1000. inserttypeconv(frametree,voidpointertype);
  1001. end;
  1002. end;
  1003. end;
  1004. end;
  1005. function traisenode.pass_1 : tnode;
  1006. begin
  1007. result:=nil;
  1008. include(current_procinfo.flags,pi_do_call);
  1009. expectloc:=LOC_VOID;
  1010. if assigned(left) then
  1011. begin
  1012. { first para must be a _class_ }
  1013. firstpass(left);
  1014. { insert needed typeconvs for addr,frame }
  1015. if assigned(right) then
  1016. begin
  1017. { addr }
  1018. firstpass(right);
  1019. { frame }
  1020. if assigned(frametree) then
  1021. firstpass(frametree);
  1022. end;
  1023. left_right_max;
  1024. end;
  1025. end;
  1026. function traisenode.docompare(p: tnode): boolean;
  1027. begin
  1028. docompare := false;
  1029. end;
  1030. {*****************************************************************************
  1031. TTRYEXCEPTNODE
  1032. *****************************************************************************}
  1033. constructor ttryexceptnode.create(l,r,_t1 : tnode);
  1034. begin
  1035. inherited create(tryexceptn,l,r,_t1,nil);
  1036. end;
  1037. function ttryexceptnode.det_resulttype:tnode;
  1038. begin
  1039. result:=nil;
  1040. resulttypepass(left);
  1041. { on statements }
  1042. if assigned(right) then
  1043. resulttypepass(right);
  1044. { else block }
  1045. if assigned(t1) then
  1046. resulttypepass(t1);
  1047. resulttype:=voidtype;
  1048. end;
  1049. function ttryexceptnode.pass_1 : tnode;
  1050. begin
  1051. result:=nil;
  1052. expectloc:=LOC_VOID;
  1053. firstpass(left);
  1054. { on statements }
  1055. if assigned(right) then
  1056. begin
  1057. firstpass(right);
  1058. registers32:=max(registers32,right.registers32);
  1059. registersfpu:=max(registersfpu,right.registersfpu);
  1060. {$ifdef SUPPORT_MMX}
  1061. registersmmx:=max(registersmmx,right.registersmmx);
  1062. {$endif SUPPORT_MMX}
  1063. end;
  1064. { else block }
  1065. if assigned(t1) then
  1066. begin
  1067. firstpass(t1);
  1068. registers32:=max(registers32,t1.registers32);
  1069. registersfpu:=max(registersfpu,t1.registersfpu);
  1070. {$ifdef SUPPORT_MMX}
  1071. registersmmx:=max(registersmmx,t1.registersmmx);
  1072. {$endif SUPPORT_MMX}
  1073. end;
  1074. end;
  1075. {*****************************************************************************
  1076. TTRYFINALLYNODE
  1077. *****************************************************************************}
  1078. constructor ttryfinallynode.create(l,r:tnode);
  1079. begin
  1080. inherited create(tryfinallyn,l,r,nil,nil);
  1081. implicitframe:=false;
  1082. end;
  1083. constructor ttryfinallynode.create_implicit(l,r,_t1:tnode);
  1084. begin
  1085. inherited create(tryfinallyn,l,r,_t1,nil);
  1086. implicitframe:=true;
  1087. end;
  1088. function ttryfinallynode.det_resulttype:tnode;
  1089. begin
  1090. result:=nil;
  1091. resulttype:=voidtype;
  1092. resulttypepass(left);
  1093. set_varstate(left,vs_used,true);
  1094. resulttypepass(right);
  1095. set_varstate(right,vs_used,true);
  1096. { special finally block only executed when there was an exception }
  1097. if assigned(t1) then
  1098. begin
  1099. resulttypepass(t1);
  1100. set_varstate(t1,vs_used,true);
  1101. end;
  1102. end;
  1103. function ttryfinallynode.pass_1 : tnode;
  1104. begin
  1105. result:=nil;
  1106. expectloc:=LOC_VOID;
  1107. firstpass(left);
  1108. firstpass(right);
  1109. left_right_max;
  1110. if assigned(t1) then
  1111. begin
  1112. firstpass(t1);
  1113. registers32:=max(registers32,t1.registers32);
  1114. registersfpu:=max(registersfpu,t1.registersfpu);
  1115. {$ifdef SUPPORT_MMX}
  1116. registersmmx:=max(registersmmx,t1.registersmmx);
  1117. {$endif SUPPORT_MMX}
  1118. end;
  1119. end;
  1120. {*****************************************************************************
  1121. TONNODE
  1122. *****************************************************************************}
  1123. constructor tonnode.create(l,r:tnode);
  1124. begin
  1125. inherited create(onn,l,r);
  1126. exceptsymtable:=nil;
  1127. excepttype:=nil;
  1128. end;
  1129. destructor tonnode.destroy;
  1130. begin
  1131. if assigned(exceptsymtable) then
  1132. exceptsymtable.free;
  1133. inherited destroy;
  1134. end;
  1135. constructor tonnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
  1136. begin
  1137. inherited ppuload(t,ppufile);
  1138. exceptsymtable:=nil;
  1139. excepttype:=nil;
  1140. end;
  1141. function tonnode.getcopy : tnode;
  1142. var
  1143. n : tonnode;
  1144. begin
  1145. n:=tonnode(inherited getcopy);
  1146. n.exceptsymtable:=exceptsymtable;
  1147. n.excepttype:=excepttype;
  1148. result:=n;
  1149. end;
  1150. function tonnode.det_resulttype:tnode;
  1151. begin
  1152. result:=nil;
  1153. resulttype:=voidtype;
  1154. if not(is_class(excepttype)) then
  1155. CGMessage(type_e_mismatch);
  1156. if assigned(left) then
  1157. resulttypepass(left);
  1158. if assigned(right) then
  1159. resulttypepass(right);
  1160. end;
  1161. function tonnode.pass_1 : tnode;
  1162. begin
  1163. result:=nil;
  1164. expectloc:=LOC_VOID;
  1165. registers32:=0;
  1166. registersfpu:=0;
  1167. {$ifdef SUPPORT_MMX}
  1168. registersmmx:=0;
  1169. {$endif SUPPORT_MMX}
  1170. if assigned(left) then
  1171. begin
  1172. firstpass(left);
  1173. registers32:=left.registers32;
  1174. registersfpu:=left.registersfpu;
  1175. {$ifdef SUPPORT_MMX}
  1176. registersmmx:=left.registersmmx;
  1177. {$endif SUPPORT_MMX}
  1178. end;
  1179. if assigned(right) then
  1180. begin
  1181. firstpass(right);
  1182. registers32:=max(registers32,right.registers32);
  1183. registersfpu:=max(registersfpu,right.registersfpu);
  1184. {$ifdef SUPPORT_MMX}
  1185. registersmmx:=max(registersmmx,right.registersmmx);
  1186. {$endif SUPPORT_MMX}
  1187. end;
  1188. end;
  1189. function tonnode.docompare(p: tnode): boolean;
  1190. begin
  1191. docompare := false;
  1192. end;
  1193. begin
  1194. cwhilerepeatnode:=twhilerepeatnode;
  1195. cifnode:=tifnode;
  1196. cfornode:=tfornode;
  1197. cexitnode:=texitnode;
  1198. cgotonode:=tgotonode;
  1199. clabelnode:=tlabelnode;
  1200. craisenode:=traisenode;
  1201. ctryexceptnode:=ttryexceptnode;
  1202. ctryfinallynode:=ttryfinallynode;
  1203. connode:=tonnode;
  1204. end.
  1205. {
  1206. $Log$
  1207. Revision 1.83 2003-10-09 21:31:37 daniel
  1208. * Register allocator splitted, ans abstract now
  1209. Revision 1.82 2003/10/08 19:19:45 peter
  1210. * set_varstate cleanup
  1211. Revision 1.81 2003/10/05 11:53:57 florian
  1212. * writing of loop nodes fixed
  1213. Revision 1.80 2003/10/01 20:34:48 peter
  1214. * procinfo unit contains tprocinfo
  1215. * cginfo renamed to cgbase
  1216. * moved cgmessage to verbose
  1217. * fixed ppc and sparc compiles
  1218. Revision 1.79 2003/07/06 15:31:20 daniel
  1219. * Fixed register allocator. *Lots* of fixes.
  1220. Revision 1.78 2003/06/13 21:19:30 peter
  1221. * current_procdef removed, use current_procinfo.procdef instead
  1222. Revision 1.77 2003/06/07 20:26:32 peter
  1223. * re-resolving added instead of reloading from ppu
  1224. * tderef object added to store deref info for resolving
  1225. Revision 1.76 2003/06/07 18:57:04 jonas
  1226. + added freeintparaloc
  1227. * ppc get/freeintparaloc now check whether the parameter regs are
  1228. properly allocated/deallocated (and get an extra list para)
  1229. * ppc a_call_* now internalerrors if pi_do_call is not yet set
  1230. * fixed lot of missing pi_do_call's
  1231. Revision 1.75 2003/05/26 21:17:17 peter
  1232. * procinlinenode removed
  1233. * aktexit2label removed, fast exit removed
  1234. + tcallnode.inlined_pass_2 added
  1235. Revision 1.74 2003/05/13 19:14:41 peter
  1236. * failn removed
  1237. * inherited result code check moven to pexpr
  1238. Revision 1.73 2003/05/11 21:37:03 peter
  1239. * moved implicit exception frame from ncgutil to psub
  1240. * constructor/destructor helpers moved from cobj/ncgutil to psub
  1241. Revision 1.72 2003/05/01 07:59:42 florian
  1242. * introduced defaultordconsttype to decribe the default size of ordinal constants
  1243. on 64 bit CPUs it's equal to cs64bitdef while on 32 bit CPUs it's equal to s32bitdef
  1244. + added defines CPU32 and CPU64 for 32 bit and 64 bit CPUs
  1245. * int64s/qwords are allowed as for loop counter on 64 bit CPUs
  1246. Revision 1.71 2003/04/27 11:21:33 peter
  1247. * aktprocdef renamed to current_procinfo.procdef
  1248. * procinfo renamed to current_procinfo
  1249. * procinfo will now be stored in current_module so it can be
  1250. cleaned up properly
  1251. * gen_main_procsym changed to create_main_proc and release_main_proc
  1252. to also generate a tprocinfo structure
  1253. * fixed unit implicit initfinal
  1254. Revision 1.70 2003/04/27 07:29:50 peter
  1255. * current_procinfo.procdef cleanup, current_procdef is now always nil when parsing
  1256. a new procdef declaration
  1257. * aktprocsym removed
  1258. * lexlevel removed, use symtable.symtablelevel instead
  1259. * implicit init/final code uses the normal genentry/genexit
  1260. * funcret state checking updated for new funcret handling
  1261. Revision 1.69 2003/04/26 00:28:41 peter
  1262. * removed load_funcret
  1263. Revision 1.68 2003/04/25 20:59:33 peter
  1264. * removed funcretn,funcretsym, function result is now in varsym
  1265. and aliases for result and function name are added using absolutesym
  1266. * vs_hidden parameter for funcret passed in parameter
  1267. * vs_hidden fixes
  1268. * writenode changed to printnode and released from extdebug
  1269. * -vp option added to generate a tree.log with the nodetree
  1270. * nicer printnode for statements, callnode
  1271. Revision 1.67 2003/04/25 08:25:26 daniel
  1272. * Ifdefs around a lot of calls to cleartempgen
  1273. * Fixed registers that are allocated but not freed in several nodes
  1274. * Tweak to register allocator to cause less spills
  1275. * 8-bit registers now interfere with esi,edi and ebp
  1276. Compiler can now compile rtl successfully when using new register
  1277. allocator
  1278. Revision 1.66 2003/04/22 23:50:23 peter
  1279. * firstpass uses expectloc
  1280. * checks if there are differences between the expectloc and
  1281. location.loc from secondpass in EXTDEBUG
  1282. Revision 1.65 2003/03/20 15:54:46 peter
  1283. * don't allow var and out parameters as for loop counter
  1284. Revision 1.64 2003/01/09 21:52:37 peter
  1285. * merged some verbosity options.
  1286. * V_LineInfo is a verbosity flag to include line info
  1287. Revision 1.63 2003/01/04 08:08:47 daniel
  1288. * Readded missing variable
  1289. Revision 1.62 2003/01/03 17:16:57 peter
  1290. * fixed warning about unset funcret
  1291. Revision 1.61 2003/01/03 12:15:56 daniel
  1292. * Removed ifdefs around notifications
  1293. ifdefs around for loop optimizations remain
  1294. Revision 1.60 2002/12/31 09:55:58 daniel
  1295. + Notification implementation complete
  1296. + Add for loop code optimization using notifications
  1297. results in 1.5-1.9% speed improvement in nestloop benchmark
  1298. Optimization incomplete, compiler does not cycle yet with
  1299. notifications enabled.
  1300. Revision 1.59 2002/12/30 22:44:53 daniel
  1301. * Some work on notifications
  1302. Revision 1.58 2002/12/27 15:25:40 peter
  1303. * do not allow threadvar as loop counter
  1304. Revision 1.57 2002/11/28 11:17:02 florian
  1305. * loop node flags from node flags splitted
  1306. Revision 1.56 2002/11/25 17:43:18 peter
  1307. * splitted defbase in defutil,symutil,defcmp
  1308. * merged isconvertable and is_equal into compare_defs(_ext)
  1309. * made operator search faster by walking the list only once
  1310. Revision 1.55 2002/11/18 17:31:56 peter
  1311. * pass proccalloption to ret_in_xxx and push_xxx functions
  1312. Revision 1.54 2002/10/20 15:31:49 peter
  1313. * set funcret state for exit(0)
  1314. Revision 1.53 2002/10/05 12:43:25 carl
  1315. * fixes for Delphi 6 compilation
  1316. (warning : Some features do not work under Delphi)
  1317. Revision 1.52 2002/09/07 15:25:03 peter
  1318. * old logs removed and tabs fixed
  1319. Revision 1.51 2002/09/07 12:16:04 carl
  1320. * second part bug report 1996 fix, testrange in cordconstnode
  1321. only called if option is set (also make parsing a tiny faster)
  1322. Revision 1.50 2002/09/01 18:47:00 peter
  1323. * assignn check in exitnode changed to use a separate boolean as the
  1324. assignn can be changed to a calln
  1325. Revision 1.49 2002/09/01 08:01:16 daniel
  1326. * Removed sets from Tcallnode.det_resulttype
  1327. + Added read/write notifications of variables. These will be usefull
  1328. for providing information for several optimizations. For example
  1329. the value of the loop variable of a for loop does matter is the
  1330. variable is read after the for loop, but if it's no longer used
  1331. or written, it doesn't matter and this can be used to optimize
  1332. the loop code generation.
  1333. Revision 1.48 2002/08/22 15:15:20 daniel
  1334. * Fixed the detection wether the first check of a for loop can be skipped
  1335. Revision 1.47 2002/08/19 19:36:43 peter
  1336. * More fixes for cross unit inlining, all tnodes are now implemented
  1337. * Moved pocall_internconst to po_internconst because it is not a
  1338. calling type at all and it conflicted when inlining of these small
  1339. functions was requested
  1340. Revision 1.46 2002/08/17 22:09:46 florian
  1341. * result type handling in tcgcal.pass_2 overhauled
  1342. * better tnode.dowrite
  1343. * some ppc stuff fixed
  1344. Revision 1.45 2002/08/17 09:23:37 florian
  1345. * first part of current_procinfo rewrite
  1346. Revision 1.44 2002/07/21 06:58:49 daniel
  1347. * Changed booleans into flags
  1348. Revision 1.43 2002/07/20 11:57:54 florian
  1349. * types.pas renamed to defbase.pas because D6 contains a types
  1350. unit so this would conflicts if D6 programms are compiled
  1351. + Willamette/SSE2 instructions to assembler added
  1352. Revision 1.42 2002/07/20 11:18:18 daniel
  1353. * Small mistake fixed; the skip test was done before we know the for node
  1354. is correct.
  1355. Revision 1.40 2002/07/20 08:19:31 daniel
  1356. * State tracker automatically changes while loops into repeat loops
  1357. Revision 1.39 2002/07/19 12:55:27 daniel
  1358. * Further developed state tracking in whilerepeatn
  1359. Revision 1.38 2002/07/19 11:41:35 daniel
  1360. * State tracker work
  1361. * The whilen and repeatn are now completely unified into whilerepeatn. This
  1362. allows the state tracker to change while nodes automatically into
  1363. repeat nodes.
  1364. * Resulttypepass improvements to the notn. 'not not a' is optimized away and
  1365. 'not(a>b)' is optimized into 'a<=b'.
  1366. * Resulttypepass improvements to the whilerepeatn. 'while not a' is optimized
  1367. by removing the notn and later switchting the true and falselabels. The
  1368. same is done with 'repeat until not a'.
  1369. Revision 1.37 2002/07/16 13:57:02 florian
  1370. * raise takes now a void pointer as at and frame address
  1371. instead of a longint
  1372. Revision 1.36 2002/07/15 18:03:15 florian
  1373. * readded removed changes
  1374. Revision 1.35 2002/07/14 18:00:44 daniel
  1375. + Added the beginning of a state tracker. This will track the values of
  1376. variables through procedures and optimize things away.
  1377. Revision 1.34 2002/07/11 14:41:28 florian
  1378. * start of the new generic parameter handling
  1379. Revision 1.33 2002/07/01 18:46:23 peter
  1380. * internal linker
  1381. * reorganized aasm layer
  1382. Revision 1.32 2002/05/18 13:34:10 peter
  1383. * readded missing revisions
  1384. Revision 1.31 2002/05/16 19:46:38 carl
  1385. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1386. + try to fix temp allocation (still in ifdef)
  1387. + generic constructor calls
  1388. + start of tassembler / tmodulebase class cleanup
  1389. }