pass_1.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. {
  2. $Id$
  3. Copyright (c) 1996-98 by Florian Klaempfl
  4. This unit implements the first pass of the code generator
  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. {$ifdef tp}
  19. {$F+}
  20. {$endif tp}
  21. unit pass_1;
  22. interface
  23. uses
  24. tree;
  25. procedure firstpass(var p : ptree);
  26. function do_firstpass(var p : ptree) : boolean;
  27. implementation
  28. uses
  29. cobjects,verbose,systems,globals,
  30. aasm,symtable,types,
  31. hcodegen,htypechk,
  32. tcadd,tccal,tccnv,tccon,tcflw,
  33. tcinl,tcld,tcmat,tcmem,tcset
  34. {$ifdef i386}
  35. ,i386,tgeni386
  36. {$endif}
  37. {$ifdef m68k}
  38. ,m68k,tgen68k
  39. {$endif}
  40. ;
  41. {*****************************************************************************
  42. FirstPass
  43. *****************************************************************************}
  44. type
  45. firstpassproc = procedure(var p : ptree);
  46. procedure firstnothing(var p : ptree);
  47. begin
  48. p^.resulttype:=voiddef;
  49. end;
  50. procedure firsterror(var p : ptree);
  51. begin
  52. p^.error:=true;
  53. codegenerror:=true;
  54. p^.resulttype:=generrordef;
  55. end;
  56. procedure firststatement(var p : ptree);
  57. begin
  58. { left is the next statement in the list }
  59. p^.resulttype:=voiddef;
  60. { no temps over several statements }
  61. cleartempgen;
  62. { right is the statement itself calln assignn or a complex one }
  63. firstpass(p^.right);
  64. if (not (cs_extsyntax in aktmoduleswitches)) and
  65. assigned(p^.right^.resulttype) and
  66. (p^.right^.resulttype<>pdef(voiddef)) then
  67. CGMessage(cg_e_illegal_expression);
  68. if codegenerror then
  69. exit;
  70. p^.registers32:=p^.right^.registers32;
  71. p^.registersfpu:=p^.right^.registersfpu;
  72. {$ifdef SUPPORT_MMX}
  73. p^.registersmmx:=p^.right^.registersmmx;
  74. {$endif SUPPORT_MMX}
  75. { left is the next in the list }
  76. firstpass(p^.left);
  77. if codegenerror then
  78. exit;
  79. if p^.right^.registers32>p^.registers32 then
  80. p^.registers32:=p^.right^.registers32;
  81. if p^.right^.registersfpu>p^.registersfpu then
  82. p^.registersfpu:=p^.right^.registersfpu;
  83. {$ifdef SUPPORT_MMX}
  84. if p^.right^.registersmmx>p^.registersmmx then
  85. p^.registersmmx:=p^.right^.registersmmx;
  86. {$endif}
  87. end;
  88. procedure firstblock(var p : ptree);
  89. var
  90. hp : ptree;
  91. count : longint;
  92. begin
  93. count:=0;
  94. hp:=p^.left;
  95. while assigned(hp) do
  96. begin
  97. if cs_regalloc in aktglobalswitches then
  98. begin
  99. { Codeumstellungen }
  100. { Funktionsresultate an exit anh„ngen }
  101. { this is wrong for string or other complex
  102. result types !!! }
  103. if ret_in_acc(procinfo.retdef) and
  104. assigned(hp^.left) and
  105. (hp^.left^.right^.treetype=exitn) and
  106. (hp^.right^.treetype=assignn) and
  107. (hp^.right^.left^.treetype=funcretn) then
  108. begin
  109. if assigned(hp^.left^.right^.left) then
  110. CGMessage(cg_n_inefficient_code)
  111. else
  112. begin
  113. hp^.left^.right^.left:=getcopy(hp^.right^.right);
  114. disposetree(hp^.right);
  115. hp^.right:=nil;
  116. end;
  117. end
  118. { warning if unreachable code occurs and elimate this }
  119. else if (hp^.right^.treetype in
  120. [exitn,breakn,continuen,goton]) and
  121. assigned(hp^.left) and
  122. (hp^.left^.treetype<>labeln) then
  123. begin
  124. { use correct line number }
  125. aktfilepos:=hp^.left^.fileinfo;
  126. disposetree(hp^.left);
  127. hp^.left:=nil;
  128. CGMessage(cg_w_unreachable_code);
  129. { old lines }
  130. aktfilepos:=hp^.right^.fileinfo;
  131. end;
  132. end;
  133. if assigned(hp^.right) then
  134. begin
  135. cleartempgen;
  136. firstpass(hp^.right);
  137. if (not (cs_extsyntax in aktmoduleswitches)) and
  138. assigned(hp^.right^.resulttype) and
  139. (hp^.right^.resulttype<>pdef(voiddef)) then
  140. CGMessage(cg_e_illegal_expression);
  141. if codegenerror then
  142. exit;
  143. hp^.registers32:=hp^.right^.registers32;
  144. hp^.registersfpu:=hp^.right^.registersfpu;
  145. {$ifdef SUPPORT_MMX}
  146. hp^.registersmmx:=hp^.right^.registersmmx;
  147. {$endif SUPPORT_MMX}
  148. end
  149. else
  150. hp^.registers32:=0;
  151. if hp^.registers32>p^.registers32 then
  152. p^.registers32:=hp^.registers32;
  153. if hp^.registersfpu>p^.registersfpu then
  154. p^.registersfpu:=hp^.registersfpu;
  155. {$ifdef SUPPORT_MMX}
  156. if hp^.registersmmx>p^.registersmmx then
  157. p^.registersmmx:=hp^.registersmmx;
  158. {$endif}
  159. inc(count);
  160. hp:=hp^.left;
  161. end;
  162. end;
  163. procedure firstasm(var p : ptree);
  164. begin
  165. procinfo.flags:=procinfo.flags or pi_uses_asm;
  166. end;
  167. procedure firstpass(var p : ptree);
  168. const
  169. procedures : array[ttreetyp] of firstpassproc =
  170. (firstadd, {addn}
  171. firstadd, {muln}
  172. firstadd, {subn}
  173. firstmoddiv, {divn}
  174. firstadd, {symdifn}
  175. firstmoddiv, {modn}
  176. firstassignment, {assignn}
  177. firstload, {loadn}
  178. firstrange, {range}
  179. firstadd, {ltn}
  180. firstadd, {lten}
  181. firstadd, {gtn}
  182. firstadd, {gten}
  183. firstadd, {equaln}
  184. firstadd, {unequaln}
  185. firstin, {inn}
  186. firstadd, {orn}
  187. firstadd, {xorn}
  188. firstshlshr, {shrn}
  189. firstshlshr, {shln}
  190. firstadd, {slashn}
  191. firstadd, {andn}
  192. firstsubscript, {subscriptn}
  193. firstderef, {derefn}
  194. firstaddr, {addrn}
  195. firstdoubleaddr, {doubleaddrn}
  196. firstordconst, {ordconstn}
  197. firsttypeconv, {typeconvn}
  198. firstcalln, {calln}
  199. firstnothing, {callparan}
  200. firstrealconst, {realconstn}
  201. firstfixconst, {fixconstn}
  202. firstumminus, {umminusn}
  203. firstasm, {asmn}
  204. firstvec, {vecn}
  205. firststringconst, {stringconstn}
  206. firstfuncret, {funcretn}
  207. firstself, {selfn}
  208. firstnot, {notn}
  209. firstinline, {inlinen}
  210. firstniln, {niln}
  211. firsterror, {errorn}
  212. firsttype, {typen}
  213. firsthnew, {hnewn}
  214. firsthdispose, {hdisposen}
  215. firstnew, {newn}
  216. firstsimplenewdispose, {simpledisposen}
  217. firstsetelement, {setelementn}
  218. firstsetconst, {setconstn}
  219. firstblock, {blockn}
  220. firststatement, {statementn}
  221. firstnothing, {loopn}
  222. firstif, {ifn}
  223. firstnothing, {breakn}
  224. firstnothing, {continuen}
  225. first_while_repeat, {repeatn}
  226. first_while_repeat, {whilen}
  227. firstfor, {forn}
  228. firstexit, {exitn}
  229. firstwith, {withn}
  230. firstcase, {casen}
  231. firstlabel, {labeln}
  232. firstgoto, {goton}
  233. firstsimplenewdispose, {simplenewn}
  234. firsttryexcept, {tryexceptn}
  235. firstraise, {raisen}
  236. firstnothing, {switchesn}
  237. firsttryfinally, {tryfinallyn}
  238. firston, {onn}
  239. firstis, {isn}
  240. firstas, {asn}
  241. firsterror, {caretn}
  242. firstnothing, {failn}
  243. firstadd, {starstarn}
  244. firstprocinline, {procinlinen}
  245. firstarrayconstruct, {arrayconstructn}
  246. firstnothing, {arrayconstructrangen}
  247. firstnothing, {nothingn}
  248. firstloadvmt {loadvmtn}
  249. );
  250. var
  251. oldcodegenerror : boolean;
  252. oldlocalswitches : tlocalswitches;
  253. oldpos : tfileposinfo;
  254. {$ifdef extdebug}
  255. str1,str2 : string;
  256. oldp : ptree;
  257. not_first : boolean;
  258. {$endif extdebug}
  259. begin
  260. {$ifdef extdebug}
  261. inc(total_of_firstpass);
  262. if (p^.firstpasscount>0) and only_one_pass then
  263. exit;
  264. {$endif extdebug}
  265. oldcodegenerror:=codegenerror;
  266. oldpos:=aktfilepos;
  267. oldlocalswitches:=aktlocalswitches;
  268. {$ifdef extdebug}
  269. if p^.firstpasscount>0 then
  270. begin
  271. move(p^,str1[1],sizeof(ttree));
  272. str1[0]:=char(sizeof(ttree));
  273. new(oldp);
  274. oldp^:=p^;
  275. not_first:=true;
  276. inc(firstpass_several);
  277. end
  278. else
  279. not_first:=false;
  280. {$endif extdebug}
  281. if not p^.error then
  282. begin
  283. codegenerror:=false;
  284. aktfilepos:=p^.fileinfo;
  285. aktlocalswitches:=p^.localswitches;
  286. procedures[p^.treetype](p);
  287. aktlocalswitches:=oldlocalswitches;
  288. aktfilepos:=oldpos;
  289. p^.error:=codegenerror;
  290. codegenerror:=codegenerror or oldcodegenerror;
  291. end
  292. else
  293. codegenerror:=true;
  294. {$ifdef extdebug}
  295. if not_first then
  296. begin
  297. { dirty trick to compare two ttree's (PM) }
  298. move(p^,str2[1],sizeof(ttree));
  299. str2[0]:=char(sizeof(ttree));
  300. if str1<>str2 then
  301. begin
  302. comment(v_debug,'tree changed after first counting pass '
  303. +tostr(longint(p^.treetype)));
  304. compare_trees(oldp,p);
  305. end;
  306. dispose(oldp);
  307. end;
  308. if count_ref then
  309. inc(p^.firstpasscount);
  310. {$endif extdebug}
  311. end;
  312. function do_firstpass(var p : ptree) : boolean;
  313. begin
  314. codegenerror:=false;
  315. firstpass(p);
  316. do_firstpass:=codegenerror;
  317. end;
  318. end.
  319. {
  320. $Log$
  321. Revision 1.96 1998-10-06 20:49:07 peter
  322. * m68k compiler compiles again
  323. Revision 1.95 1998/09/24 15:13:44 peter
  324. * fixed type node which was always set to void :(
  325. Revision 1.94 1998/09/23 20:42:22 peter
  326. * splitted pass_1
  327. }