pass_1.pas 14 KB

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