pass_1.pas 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. This unit handles the typecheck and node conversion pass
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit pass_1;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. node;
  23. var
  24. resulttypepasscnt,
  25. multiresulttypepasscnt : longint;
  26. procedure resulttypepass(var p : tnode);
  27. function do_resulttypepass(var p : tnode) : boolean;
  28. procedure firstpass(var p : tnode);
  29. function do_firstpass(var p : tnode) : boolean;
  30. {$ifdef state_tracking}
  31. procedure do_track_state_pass(p:Tnode);
  32. {$endif}
  33. implementation
  34. uses
  35. globtype,systems,cclasses,
  36. cutils,globals,
  37. cgbase,symdef,
  38. {$ifdef extdebug}
  39. htypechk,
  40. {$endif extdebug}
  41. {$ifdef state_tracking}
  42. nstate,
  43. {$endif}
  44. tgobj
  45. ;
  46. {*****************************************************************************
  47. Global procedures
  48. *****************************************************************************}
  49. procedure resulttypepass(var p : tnode);
  50. var
  51. oldcodegenerror : boolean;
  52. oldlocalswitches : tlocalswitches;
  53. oldpos : tfileposinfo;
  54. hp : tnode;
  55. begin
  56. inc(resulttypepasscnt);
  57. if (p.resulttype.def=nil) then
  58. begin
  59. oldcodegenerror:=codegenerror;
  60. oldpos:=aktfilepos;
  61. oldlocalswitches:=aktlocalswitches;
  62. codegenerror:=false;
  63. aktfilepos:=p.fileinfo;
  64. aktlocalswitches:=p.localswitches;
  65. hp:=p.det_resulttype;
  66. { should the node be replaced? }
  67. if assigned(hp) then
  68. begin
  69. p.free;
  70. { run resulttypepass }
  71. resulttypepass(hp);
  72. { switch to new node }
  73. p:=hp;
  74. end;
  75. aktlocalswitches:=oldlocalswitches;
  76. aktfilepos:=oldpos;
  77. if codegenerror then
  78. begin
  79. include(p.flags,nf_error);
  80. { default to errortype if no type is set yet }
  81. if p.resulttype.def=nil then
  82. p.resulttype:=generrortype;
  83. end;
  84. codegenerror:=codegenerror or oldcodegenerror;
  85. end
  86. else
  87. begin
  88. { update the codegenerror boolean with the previous result of this node }
  89. if (nf_error in p.flags) then
  90. codegenerror:=true;
  91. inc(multiresulttypepasscnt);
  92. end;
  93. end;
  94. function do_resulttypepass(var p : tnode) : boolean;
  95. begin
  96. codegenerror:=false;
  97. resulttypepass(p);
  98. do_resulttypepass:=codegenerror;
  99. end;
  100. procedure firstpass(var p : tnode);
  101. var
  102. oldcodegenerror : boolean;
  103. oldlocalswitches : tlocalswitches;
  104. oldpos : tfileposinfo;
  105. hp : tnode;
  106. begin
  107. {$ifdef extdebug}
  108. { inc(total_of_firstpass);}
  109. {$endif extdebug}
  110. oldcodegenerror:=codegenerror;
  111. oldpos:=aktfilepos;
  112. oldlocalswitches:=aktlocalswitches;
  113. {$ifdef extdebug}
  114. { if p.firstpasscount>0 then
  115. inc(firstpass_several);}
  116. {$endif extdebug}
  117. if not(nf_error in p.flags) then
  118. begin
  119. codegenerror:=false;
  120. aktfilepos:=p.fileinfo;
  121. aktlocalswitches:=p.localswitches;
  122. { determine the resulttype if not done }
  123. if (p.resulttype.def=nil) then
  124. begin
  125. aktfilepos:=p.fileinfo;
  126. aktlocalswitches:=p.localswitches;
  127. hp:=p.det_resulttype;
  128. { should the node be replaced? }
  129. if assigned(hp) then
  130. begin
  131. p.free;
  132. { run resulttypepass }
  133. resulttypepass(hp);
  134. { switch to new node }
  135. p:=hp;
  136. end;
  137. if codegenerror then
  138. begin
  139. include(p.flags,nf_error);
  140. { default to errortype if no type is set yet }
  141. if p.resulttype.def=nil then
  142. p.resulttype:=generrortype;
  143. end;
  144. aktlocalswitches:=oldlocalswitches;
  145. aktfilepos:=oldpos;
  146. codegenerror:=codegenerror or oldcodegenerror;
  147. end;
  148. if not(nf_error in p.flags) then
  149. begin
  150. { first pass }
  151. aktfilepos:=p.fileinfo;
  152. aktlocalswitches:=p.localswitches;
  153. hp:=p.pass_1;
  154. { should the node be replaced? }
  155. if assigned(hp) then
  156. begin
  157. p.free;
  158. p:=hp;
  159. end;
  160. if codegenerror then
  161. include(p.flags,nf_error);
  162. end;
  163. codegenerror:=codegenerror or oldcodegenerror;
  164. aktlocalswitches:=oldlocalswitches;
  165. aktfilepos:=oldpos;
  166. end
  167. else
  168. codegenerror:=true;
  169. {$ifdef extdebug}
  170. { if count_ref then
  171. inc(p.firstpasscount);}
  172. {$endif extdebug}
  173. end;
  174. function do_firstpass(var p : tnode) : boolean;
  175. begin
  176. codegenerror:=false;
  177. firstpass(p);
  178. {$ifdef state_tracking}
  179. writeln('TRACKSTART');
  180. writeln('before');
  181. writenode(p);
  182. do_track_state_pass(p);
  183. writeln('after');
  184. writenode(p);
  185. writeln('TRACKDONE');
  186. {$endif}
  187. do_firstpass:=codegenerror;
  188. end;
  189. {$ifdef state_tracking}
  190. procedure do_track_state_pass(p:Tnode);
  191. begin
  192. aktstate:=Tstate_storage.create;
  193. p.track_state_pass(true);
  194. aktstate.destroy;
  195. end;
  196. {$endif}
  197. end.
  198. {
  199. $Log$
  200. Revision 1.27 2002-07-19 12:55:27 daniel
  201. * Further developed state tracking in whilerepeatn
  202. Revision 1.26 2002/07/19 11:41:36 daniel
  203. * State tracker work
  204. * The whilen and repeatn are now completely unified into whilerepeatn. This
  205. allows the state tracker to change while nodes automatically into
  206. repeat nodes.
  207. * Resulttypepass improvements to the notn. 'not not a' is optimized away and
  208. 'not(a>b)' is optimized into 'a<=b'.
  209. * Resulttypepass improvements to the whilerepeatn. 'while not a' is optimized
  210. by removing the notn and later switchting the true and falselabels. The
  211. same is done with 'repeat until not a'.
  212. Revision 1.25 2002/07/14 18:00:44 daniel
  213. + Added the beginning of a state tracker. This will track the values of
  214. variables through procedures and optimize things away.
  215. Revision 1.24 2002/06/16 08:15:54 carl
  216. * commented out uncompilable debug code
  217. Revision 1.23 2002/05/18 13:34:11 peter
  218. * readded missing revisions
  219. Revision 1.22 2002/05/16 19:46:42 carl
  220. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  221. + try to fix temp allocation (still in ifdef)
  222. + generic constructor calls
  223. + start of tassembler / tmodulebase class cleanup
  224. Revision 1.20 2002/04/04 19:06:00 peter
  225. * removed unused units
  226. * use tlocation.size in cg.a_*loc*() routines
  227. Revision 1.19 2002/03/31 20:26:35 jonas
  228. + a_loadfpu_* and a_loadmm_* methods in tcg
  229. * register allocation is now handled by a class and is mostly processor
  230. independent (+rgobj.pas and i386/rgcpu.pas)
  231. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  232. * some small improvements and fixes to the optimizer
  233. * some register allocation fixes
  234. * some fpuvaroffset fixes in the unary minus node
  235. * push/popusedregisters is now called rg.save/restoreusedregisters and
  236. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  237. also better optimizable)
  238. * fixed and optimized register saving/restoring for new/dispose nodes
  239. * LOC_FPU locations now also require their "register" field to be set to
  240. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  241. - list field removed of the tnode class because it's not used currently
  242. and can cause hard-to-find bugs
  243. }