pass_1.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  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. 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.115 2000-05-25 12:00:14 jonas
  362. * fixed unreachable code detection
  363. Revision 1.114 2000/02/17 14:53:42 florian
  364. * some updates for the newcg
  365. Revision 1.113 2000/02/09 13:22:55 peter
  366. * log truncated
  367. Revision 1.112 2000/01/07 01:14:28 peter
  368. * updated copyright to 2000
  369. Revision 1.111 1999/12/14 09:58:42 florian
  370. + compiler checks now if a goto leaves an exception block
  371. Revision 1.110 1999/11/30 10:40:44 peter
  372. + ttype, tsymlist
  373. Revision 1.109 1999/11/18 15:34:47 pierre
  374. * Notes/Hints for local syms changed to
  375. Set_varstate function
  376. Revision 1.108 1999/11/17 17:05:01 pierre
  377. * Notes/hints changes
  378. Revision 1.107 1999/10/26 12:30:43 peter
  379. * const parameter is now checked
  380. * better and generic check if a node can be used for assigning
  381. * export fixes
  382. * procvar equal works now (it never had worked at least from 0.99.8)
  383. * defcoll changed to linkedlist with pparaitem so it can easily be
  384. walked both directions
  385. Revision 1.106 1999/09/27 23:44:51 peter
  386. * procinfo is now a pointer
  387. * support for result setting in sub procedure
  388. Revision 1.105 1999/09/26 21:30:16 peter
  389. + constant pointer support which can happend with typecasting like
  390. const p=pointer(1)
  391. * better procvar parsing in typed consts
  392. Revision 1.104 1999/09/11 09:08:31 florian
  393. * fixed bug 596
  394. * fixed some problems with procedure variables and procedures of object,
  395. especially in TP mode. Procedure of object doesn't apply only to classes,
  396. it is also allowed for objects !!
  397. Revision 1.103 1999/08/04 00:23:09 florian
  398. * renamed i386asm and i386base to cpuasm and cpubase
  399. }