pass_1.pas 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. This unit handles the pass_typecheck and node conversion pass
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit pass_1;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. node;
  22. procedure typecheckpass(var p : tnode);
  23. function do_typecheckpass(var p : tnode) : boolean;
  24. function do_typecheckpass_changed(var p : tnode; out nodechanged: boolean) : boolean;
  25. procedure firstpass(var p : tnode);
  26. function do_firstpass(var p : tnode) : boolean;
  27. {$ifdef state_tracking}
  28. procedure do_track_state_pass(p:Tnode);
  29. {$endif}
  30. implementation
  31. uses
  32. globtype,comphook,
  33. globals,
  34. procinfo,
  35. symdef
  36. {$ifdef extdebug}
  37. ,verbose,htypechk
  38. ,cgbase
  39. {$endif extdebug}
  40. {$ifdef state_tracking}
  41. ,nstate
  42. {$endif}
  43. ;
  44. {*****************************************************************************
  45. Global procedures
  46. *****************************************************************************}
  47. procedure typecheckpass_internal_loop(var p : tnode; out node_changed: boolean);
  48. var
  49. hp : tnode;
  50. oldflags : tnodeflags;
  51. begin
  52. codegenerror:=false;
  53. repeat
  54. current_filepos:=p.fileinfo;
  55. current_settings.localswitches:=p.localswitches;
  56. status.verbosity:=p.verbosity;
  57. hp:=p.pass_typecheck;
  58. { should the node be replaced? }
  59. if assigned(hp) then
  60. begin
  61. node_changed:=true;
  62. oldflags:=p.flags;
  63. p.free;
  64. { switch to new node }
  65. p:=hp;
  66. { transfer generic paramter flag }
  67. if nf_generic_para in oldflags then
  68. include(p.flags,nf_generic_para);
  69. end;
  70. until not assigned(hp) or
  71. assigned(hp.resultdef);
  72. if codegenerror then
  73. begin
  74. include(p.flags,nf_error);
  75. { default to errortype if no type is set yet }
  76. if p.resultdef=nil then
  77. p.resultdef:=generrordef;
  78. end;
  79. end;
  80. procedure typecheckpass_internal(var p : tnode; out node_changed: boolean);
  81. var
  82. oldcodegenerror : boolean;
  83. oldlocalswitches : tlocalswitches;
  84. oldverbosity : longint;
  85. oldpos : tfileposinfo;
  86. begin
  87. node_changed:=false;
  88. if (p.resultdef=nil) then
  89. begin
  90. oldcodegenerror:=codegenerror;
  91. oldpos:=current_filepos;
  92. oldlocalswitches:=current_settings.localswitches;
  93. oldverbosity:=status.verbosity;
  94. typecheckpass_internal_loop(p, node_changed);
  95. current_settings.localswitches:=oldlocalswitches;
  96. current_filepos:=oldpos;
  97. status.verbosity:=oldverbosity;
  98. codegenerror:=codegenerror or oldcodegenerror;
  99. end
  100. else
  101. begin
  102. { update the codegenerror boolean with the previous result of this node }
  103. if (nf_error in p.flags) then
  104. codegenerror:=true;
  105. end;
  106. end;
  107. procedure typecheckpass(var p : tnode);
  108. var
  109. node_changed: boolean;
  110. begin
  111. typecheckpass_internal(p,node_changed);
  112. end;
  113. function do_typecheckpass_changed(var p : tnode; out nodechanged: boolean) : boolean;
  114. begin
  115. codegenerror:=false;
  116. typecheckpass_internal(p,nodechanged);
  117. do_typecheckpass_changed:=codegenerror;
  118. end;
  119. function do_typecheckpass(var p : tnode) : boolean;
  120. var
  121. nodechanged: boolean;
  122. begin
  123. result:=do_typecheckpass_changed(p,nodechanged);
  124. end;
  125. procedure firstpass(var p : tnode);
  126. var
  127. oldcodegenerror : boolean;
  128. oldlocalswitches : tlocalswitches;
  129. oldpos : tfileposinfo;
  130. oldverbosity: longint;
  131. hp : tnode;
  132. nodechanged : boolean;
  133. begin
  134. if (nf_pass1_done in p.flags) then
  135. exit;
  136. if not(nf_error in p.flags) then
  137. begin
  138. oldcodegenerror:=codegenerror;
  139. oldpos:=current_filepos;
  140. oldlocalswitches:=current_settings.localswitches;
  141. oldverbosity:=status.verbosity;
  142. codegenerror:=false;
  143. repeat
  144. { checks make always a call }
  145. if ([cs_check_range,cs_check_overflow,cs_check_stack] * current_settings.localswitches <> []) then
  146. include(current_procinfo.flags,pi_do_call);
  147. { determine the resultdef if not done }
  148. if (p.resultdef=nil) then
  149. begin
  150. typecheckpass_internal_loop(p,nodechanged);
  151. end;
  152. hp:=nil;
  153. if not(nf_error in p.flags) then
  154. begin
  155. current_filepos:=p.fileinfo;
  156. current_settings.localswitches:=p.localswitches;
  157. status.verbosity:=p.verbosity;
  158. { first pass }
  159. hp:=p.pass_1;
  160. { inlining happens in pass_1 and can cause new }
  161. { simplify opportunities }
  162. if not assigned(hp) then
  163. hp:=p.simplify(true);
  164. { should the node be replaced? }
  165. if assigned(hp) then
  166. begin
  167. hp.flags := hp.flags + (p.flags * [nf_usercode_entry]);
  168. p.free;
  169. { switch to new node }
  170. p:=hp;
  171. end;
  172. if codegenerror then
  173. include(p.flags,nf_error);
  174. end;
  175. until not assigned(hp) or
  176. (nf_pass1_done in hp.flags);
  177. include(p.flags,nf_pass1_done);
  178. {$ifdef EXTDEBUG}
  179. if not(nf_error in p.flags) then
  180. begin
  181. if (p.expectloc=LOC_INVALID) then
  182. Comment(V_Warning,'Expectloc is not set in firstpass: '+nodetype2str[p.nodetype]);
  183. end;
  184. {$endif EXTDEBUG}
  185. codegenerror:=codegenerror or oldcodegenerror;
  186. current_settings.localswitches:=oldlocalswitches;
  187. current_filepos:=oldpos;
  188. status.verbosity:=oldverbosity;
  189. end
  190. else
  191. codegenerror:=true;
  192. end;
  193. function do_firstpass(var p : tnode) : boolean;
  194. begin
  195. codegenerror:=false;
  196. firstpass(p);
  197. {$ifdef state_tracking}
  198. writeln('TRACKSTART');
  199. writeln('before');
  200. writenode(p);
  201. do_track_state_pass(p);
  202. writeln('after');
  203. writenode(p);
  204. writeln('TRACKDONE');
  205. {$endif}
  206. do_firstpass:=codegenerror;
  207. end;
  208. {$ifdef state_tracking}
  209. procedure do_track_state_pass(p:Tnode);
  210. begin
  211. aktstate:=Tstate_storage.create;
  212. p.track_state_pass(true);
  213. aktstate.destroy;
  214. end;
  215. {$endif}
  216. end.