pass_1.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  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. (hp^.left^.right^.treetype=exitn) and
  118. (hp^.right^.treetype=assignn) and
  119. (hp^.right^.left^.treetype=funcretn) then
  120. begin
  121. if assigned(hp^.left^.right^.left) then
  122. CGMessage(cg_n_inefficient_code)
  123. else
  124. begin
  125. hp^.left^.right^.left:=hp^.right^.right;
  126. hp^.right^.right:=nil;
  127. disposetree(hp^.right);
  128. hp^.right:=nil;
  129. end;
  130. end
  131. { warning if unreachable code occurs and elimate this }
  132. else if (hp^.right^.treetype in
  133. [exitn,breakn,continuen,goton]) and
  134. assigned(hp^.left) and
  135. (hp^.left^.treetype<>labeln) then
  136. begin
  137. { use correct line number }
  138. aktfilepos:=hp^.left^.fileinfo;
  139. disposetree(hp^.left);
  140. hp^.left:=nil;
  141. CGMessage(cg_w_unreachable_code);
  142. { old lines }
  143. aktfilepos:=hp^.right^.fileinfo;
  144. end;
  145. end;
  146. if assigned(hp^.right) then
  147. begin
  148. {$ifdef newcg}
  149. tg.cleartempgen;
  150. {$else newcg}
  151. cleartempgen;
  152. {$endif newcg}
  153. codegenerror:=false;
  154. firstpass(hp^.right);
  155. if (not (cs_extsyntax in aktmoduleswitches)) and
  156. assigned(hp^.right^.resulttype) and
  157. (hp^.right^.resulttype<>pdef(voiddef)) then
  158. CGMessage(cg_e_illegal_expression);
  159. {if codegenerror then
  160. exit;}
  161. hp^.registers32:=hp^.right^.registers32;
  162. hp^.registersfpu:=hp^.right^.registersfpu;
  163. {$ifdef SUPPORT_MMX}
  164. hp^.registersmmx:=hp^.right^.registersmmx;
  165. {$endif SUPPORT_MMX}
  166. end
  167. else
  168. hp^.registers32:=0;
  169. if hp^.registers32>p^.registers32 then
  170. p^.registers32:=hp^.registers32;
  171. if hp^.registersfpu>p^.registersfpu then
  172. p^.registersfpu:=hp^.registersfpu;
  173. {$ifdef SUPPORT_MMX}
  174. if hp^.registersmmx>p^.registersmmx then
  175. p^.registersmmx:=hp^.registersmmx;
  176. {$endif}
  177. inc(count);
  178. hp:=hp^.left;
  179. end;
  180. end;
  181. procedure firstasm(var p : ptree);
  182. begin
  183. procinfo^.flags:=procinfo^.flags or pi_uses_asm;
  184. end;
  185. procedure firstpass(var p : ptree);
  186. const
  187. procedures : array[ttreetyp] of firstpassproc =
  188. (firstadd, {addn}
  189. firstadd, {muln}
  190. firstadd, {subn}
  191. firstmoddiv, {divn}
  192. firstadd, {symdifn}
  193. firstmoddiv, {modn}
  194. firstassignment, {assignn}
  195. firstload, {loadn}
  196. firstrange, {range}
  197. firstadd, {ltn}
  198. firstadd, {lten}
  199. firstadd, {gtn}
  200. firstadd, {gten}
  201. firstadd, {equaln}
  202. firstadd, {unequaln}
  203. firstin, {inn}
  204. firstadd, {orn}
  205. firstadd, {xorn}
  206. firstshlshr, {shrn}
  207. firstshlshr, {shln}
  208. firstadd, {slashn}
  209. firstadd, {andn}
  210. firstsubscript, {subscriptn}
  211. firstderef, {derefn}
  212. firstaddr, {addrn}
  213. firstdoubleaddr, {doubleaddrn}
  214. firstordconst, {ordconstn}
  215. firsttypeconv, {typeconvn}
  216. firstcalln, {calln}
  217. firstnothing, {callparan}
  218. firstrealconst, {realconstn}
  219. firstfixconst, {fixconstn}
  220. firstunaryminus, {unaryminusn}
  221. firstasm, {asmn}
  222. firstvec, {vecn}
  223. firstpointerconst,{pointerconstn}
  224. firststringconst, {stringconstn}
  225. firstfuncret, {funcretn}
  226. firstself, {selfn}
  227. firstnot, {notn}
  228. firstinline, {inlinen}
  229. firstniln, {niln}
  230. firsterror, {errorn}
  231. firsttype, {typen}
  232. firsthnew, {hnewn}
  233. firsthdispose, {hdisposen}
  234. firstnew, {newn}
  235. firstsimplenewdispose, {simpledisposen}
  236. firstsetelement, {setelementn}
  237. firstsetconst, {setconstn}
  238. firstblock, {blockn}
  239. firststatement, {statementn}
  240. firstnothing, {loopn}
  241. firstif, {ifn}
  242. firstnothing, {breakn}
  243. firstnothing, {continuen}
  244. first_while_repeat, {repeatn}
  245. first_while_repeat, {whilen}
  246. firstfor, {forn}
  247. firstexit, {exitn}
  248. firstwith, {withn}
  249. firstcase, {casen}
  250. firstlabel, {labeln}
  251. firstgoto, {goton}
  252. firstsimplenewdispose, {simplenewn}
  253. firsttryexcept, {tryexceptn}
  254. firstraise, {raisen}
  255. firstnothing, {switchesn}
  256. firsttryfinally, {tryfinallyn}
  257. firston, {onn}
  258. firstis, {isn}
  259. firstas, {asn}
  260. firsterror, {caretn}
  261. firstnothing, {failn}
  262. firstadd, {starstarn}
  263. firstprocinline, {procinlinen}
  264. firstarrayconstruct, {arrayconstructn}
  265. firstarrayconstructrange, {arrayconstructrangen}
  266. firstnothing, {nothingn}
  267. firstloadvmt {loadvmtn}
  268. );
  269. var
  270. oldcodegenerror : boolean;
  271. oldlocalswitches : tlocalswitches;
  272. oldpos : tfileposinfo;
  273. {$ifdef extdebug}
  274. str1,str2 : string;
  275. oldp : ptree;
  276. not_first : boolean;
  277. {$endif extdebug}
  278. begin
  279. {$ifdef extdebug}
  280. inc(total_of_firstpass);
  281. if (p^.firstpasscount>0) and only_one_pass then
  282. exit;
  283. {$endif extdebug}
  284. oldcodegenerror:=codegenerror;
  285. oldpos:=aktfilepos;
  286. oldlocalswitches:=aktlocalswitches;
  287. {$ifdef extdebug}
  288. if p^.firstpasscount>0 then
  289. begin
  290. move(p^,str1[1],sizeof(ttree));
  291. {$ifndef TP}
  292. {$ifopt H+}
  293. SetLength(str1,sizeof(ttree));
  294. {$else}
  295. str1[0]:=char(sizeof(ttree));
  296. {$endif}
  297. {$else}
  298. str1[0]:=char(sizeof(ttree));
  299. {$endif}
  300. new(oldp);
  301. oldp^:=p^;
  302. not_first:=true;
  303. inc(firstpass_several);
  304. end
  305. else
  306. not_first:=false;
  307. {$endif extdebug}
  308. if not p^.error then
  309. begin
  310. codegenerror:=false;
  311. aktfilepos:=p^.fileinfo;
  312. aktlocalswitches:=p^.localswitches;
  313. procedures[p^.treetype](p);
  314. aktlocalswitches:=oldlocalswitches;
  315. aktfilepos:=oldpos;
  316. p^.error:=codegenerror;
  317. codegenerror:=codegenerror or oldcodegenerror;
  318. end
  319. else
  320. codegenerror:=true;
  321. {$ifdef extdebug}
  322. if not_first then
  323. begin
  324. { dirty trick to compare two ttree's (PM) }
  325. move(p^,str2[1],sizeof(ttree));
  326. {$ifndef TP}
  327. {$ifopt H+}
  328. SetLength(str2,sizeof(ttree));
  329. {$else}
  330. str2[0]:=char(sizeof(ttree));
  331. {$endif}
  332. {$else}
  333. str2[0]:=char(sizeof(ttree));
  334. {$endif}
  335. if str1<>str2 then
  336. begin
  337. comment(v_debug,'tree changed after first counting pass '
  338. +tostr(longint(p^.treetype)));
  339. compare_trees(oldp,p);
  340. end;
  341. dispose(oldp);
  342. end;
  343. if count_ref then
  344. inc(p^.firstpasscount);
  345. {$endif extdebug}
  346. end;
  347. function do_firstpass(var p : ptree) : boolean;
  348. begin
  349. aktexceptblock:=nil;
  350. codegenerror:=false;
  351. firstpass(p);
  352. do_firstpass:=codegenerror;
  353. end;
  354. end.
  355. {
  356. $Log$
  357. Revision 1.114 2000-02-17 14:53:42 florian
  358. * some updates for the newcg
  359. Revision 1.113 2000/02/09 13:22:55 peter
  360. * log truncated
  361. Revision 1.112 2000/01/07 01:14:28 peter
  362. * updated copyright to 2000
  363. Revision 1.111 1999/12/14 09:58:42 florian
  364. + compiler checks now if a goto leaves an exception block
  365. Revision 1.110 1999/11/30 10:40:44 peter
  366. + ttype, tsymlist
  367. Revision 1.109 1999/11/18 15:34:47 pierre
  368. * Notes/Hints for local syms changed to
  369. Set_varstate function
  370. Revision 1.108 1999/11/17 17:05:01 pierre
  371. * Notes/hints changes
  372. Revision 1.107 1999/10/26 12:30:43 peter
  373. * const parameter is now checked
  374. * better and generic check if a node can be used for assigning
  375. * export fixes
  376. * procvar equal works now (it never had worked at least from 0.99.8)
  377. * defcoll changed to linkedlist with pparaitem so it can easily be
  378. walked both directions
  379. Revision 1.106 1999/09/27 23:44:51 peter
  380. * procinfo is now a pointer
  381. * support for result setting in sub procedure
  382. Revision 1.105 1999/09/26 21:30:16 peter
  383. + constant pointer support which can happend with typecasting like
  384. const p=pointer(1)
  385. * better procvar parsing in typed consts
  386. Revision 1.104 1999/09/11 09:08:31 florian
  387. * fixed bug 596
  388. * fixed some problems with procedure variables and procedures of object,
  389. especially in TP mode. Procedure of object doesn't apply only to classes,
  390. it is also allowed for objects !!
  391. Revision 1.103 1999/08/04 00:23:09 florian
  392. * renamed i386asm and i386base to cpuasm and cpubase
  393. }