pass_1.pas 13 KB

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