pass_1.pas 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  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. begin
  51. codegenerror:=false;
  52. repeat
  53. current_filepos:=p.fileinfo;
  54. current_settings.localswitches:=p.localswitches;
  55. status.verbosity:=p.verbosity;
  56. hp:=p.pass_typecheck;
  57. { should the node be replaced? }
  58. if assigned(hp) then
  59. begin
  60. node_changed:=true;
  61. p.free;
  62. { switch to new node }
  63. p:=hp;
  64. end;
  65. until not assigned(hp) or
  66. assigned(hp.resultdef);
  67. if codegenerror then
  68. begin
  69. include(p.flags,nf_error);
  70. { default to errortype if no type is set yet }
  71. if p.resultdef=nil then
  72. p.resultdef:=generrordef;
  73. end;
  74. end;
  75. procedure typecheckpass_internal(var p : tnode; out node_changed: boolean);
  76. var
  77. oldcodegenerror : boolean;
  78. oldlocalswitches : tlocalswitches;
  79. oldverbosity : longint;
  80. oldpos : tfileposinfo;
  81. begin
  82. node_changed:=false;
  83. if (p.resultdef=nil) then
  84. begin
  85. oldcodegenerror:=codegenerror;
  86. oldpos:=current_filepos;
  87. oldlocalswitches:=current_settings.localswitches;
  88. oldverbosity:=status.verbosity;
  89. typecheckpass_internal_loop(p, node_changed);
  90. current_settings.localswitches:=oldlocalswitches;
  91. current_filepos:=oldpos;
  92. status.verbosity:=oldverbosity;
  93. codegenerror:=codegenerror or oldcodegenerror;
  94. end
  95. else
  96. begin
  97. { update the codegenerror boolean with the previous result of this node }
  98. if (nf_error in p.flags) then
  99. codegenerror:=true;
  100. end;
  101. end;
  102. procedure typecheckpass(var p : tnode);
  103. var
  104. node_changed: boolean;
  105. begin
  106. typecheckpass_internal(p,node_changed);
  107. end;
  108. function do_typecheckpass_changed(var p : tnode; out nodechanged: boolean) : boolean;
  109. begin
  110. codegenerror:=false;
  111. typecheckpass_internal(p,nodechanged);
  112. do_typecheckpass_changed:=codegenerror;
  113. end;
  114. function do_typecheckpass(var p : tnode) : boolean;
  115. var
  116. nodechanged: boolean;
  117. begin
  118. result:=do_typecheckpass_changed(p,nodechanged);
  119. end;
  120. procedure firstpass(var p : tnode);
  121. var
  122. oldcodegenerror : boolean;
  123. oldlocalswitches : tlocalswitches;
  124. oldpos : tfileposinfo;
  125. oldverbosity: longint;
  126. hp : tnode;
  127. nodechanged : boolean;
  128. begin
  129. if (nf_pass1_done in p.flags) then
  130. exit;
  131. if not(nf_error in p.flags) then
  132. begin
  133. oldcodegenerror:=codegenerror;
  134. oldpos:=current_filepos;
  135. oldlocalswitches:=current_settings.localswitches;
  136. oldverbosity:=status.verbosity;
  137. codegenerror:=false;
  138. repeat
  139. { checks make always a call }
  140. if ([cs_check_range,cs_check_overflow,cs_check_stack] * current_settings.localswitches <> []) then
  141. include(current_procinfo.flags,pi_do_call);
  142. { determine the resultdef if not done }
  143. if (p.resultdef=nil) then
  144. begin
  145. typecheckpass_internal_loop(p,nodechanged);
  146. end;
  147. hp:=nil;
  148. if not(nf_error in p.flags) then
  149. begin
  150. current_filepos:=p.fileinfo;
  151. current_settings.localswitches:=p.localswitches;
  152. status.verbosity:=p.verbosity;
  153. { first pass }
  154. hp:=p.pass_1;
  155. { inlining happens in pass_1 and can cause new }
  156. { simplify opportunities }
  157. if not assigned(hp) then
  158. hp:=p.simplify(true);
  159. { should the node be replaced? }
  160. if assigned(hp) then
  161. begin
  162. p.free;
  163. { switch to new node }
  164. p:=hp;
  165. end;
  166. if codegenerror then
  167. include(p.flags,nf_error)
  168. else
  169. begin
  170. {$ifdef EXTDEBUG}
  171. if (p.expectloc=LOC_INVALID) then
  172. Comment(V_Warning,'Expectloc is not set in firstpass: '+nodetype2str[p.nodetype]);
  173. {$endif EXTDEBUG}
  174. end;
  175. end;
  176. until not assigned(hp) or
  177. (nf_pass1_done in hp.flags);
  178. include(p.flags,nf_pass1_done);
  179. codegenerror:=codegenerror or oldcodegenerror;
  180. current_settings.localswitches:=oldlocalswitches;
  181. current_filepos:=oldpos;
  182. status.verbosity:=oldverbosity;
  183. end
  184. else
  185. codegenerror:=true;
  186. end;
  187. function do_firstpass(var p : tnode) : boolean;
  188. begin
  189. codegenerror:=false;
  190. firstpass(p);
  191. {$ifdef state_tracking}
  192. writeln('TRACKSTART');
  193. writeln('before');
  194. writenode(p);
  195. do_track_state_pass(p);
  196. writeln('after');
  197. writenode(p);
  198. writeln('TRACKDONE');
  199. {$endif}
  200. do_firstpass:=codegenerror;
  201. end;
  202. {$ifdef state_tracking}
  203. procedure do_track_state_pass(p:Tnode);
  204. begin
  205. aktstate:=Tstate_storage.create;
  206. p.track_state_pass(true);
  207. aktstate.destroy;
  208. end;
  209. {$endif}
  210. end.