pass_1.pas 7.9 KB

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