pass_1.pas 7.8 KB

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