pass_1.pas 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  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. hcodegen,htypechk,
  33. tcadd,tccal,tccnv,tccon,tcflw,
  34. tcinl,tcld,tcmat,tcmem,tcset,cpubase,cpuasm
  35. {$ifdef i386}
  36. ,tgeni386
  37. {$endif}
  38. {$ifdef m68k}
  39. ,tgen68k
  40. {$endif}
  41. ;
  42. {*****************************************************************************
  43. FirstPass
  44. *****************************************************************************}
  45. type
  46. firstpassproc = procedure(var p : ptree);
  47. procedure firstnothing(var p : ptree);
  48. begin
  49. p^.resulttype:=voiddef;
  50. end;
  51. procedure firsterror(var p : ptree);
  52. begin
  53. p^.error:=true;
  54. codegenerror:=true;
  55. p^.resulttype:=generrordef;
  56. end;
  57. procedure firststatement(var p : ptree);
  58. begin
  59. { left is the next statement in the list }
  60. p^.resulttype:=voiddef;
  61. { no temps over several statements }
  62. cleartempgen;
  63. { right is the statement itself calln assignn or a complex one }
  64. {must_be_valid:=true; obsolete PM }
  65. firstpass(p^.right);
  66. if (not (cs_extsyntax in aktmoduleswitches)) and
  67. assigned(p^.right^.resulttype) and
  68. (p^.right^.resulttype<>pdef(voiddef)) then
  69. CGMessage(cg_e_illegal_expression);
  70. if codegenerror then
  71. exit;
  72. p^.registers32:=p^.right^.registers32;
  73. p^.registersfpu:=p^.right^.registersfpu;
  74. {$ifdef SUPPORT_MMX}
  75. p^.registersmmx:=p^.right^.registersmmx;
  76. {$endif SUPPORT_MMX}
  77. { left is the next in the list }
  78. firstpass(p^.left);
  79. if codegenerror then
  80. exit;
  81. if p^.right^.registers32>p^.registers32 then
  82. p^.registers32:=p^.right^.registers32;
  83. if p^.right^.registersfpu>p^.registersfpu then
  84. p^.registersfpu:=p^.right^.registersfpu;
  85. {$ifdef SUPPORT_MMX}
  86. if p^.right^.registersmmx>p^.registersmmx then
  87. p^.registersmmx:=p^.right^.registersmmx;
  88. {$endif}
  89. end;
  90. procedure firstblock(var p : ptree);
  91. var
  92. hp : ptree;
  93. count : longint;
  94. begin
  95. count:=0;
  96. hp:=p^.left;
  97. while assigned(hp) do
  98. begin
  99. if cs_regalloc in aktglobalswitches then
  100. begin
  101. { Codeumstellungen }
  102. { Funktionsresultate an exit anh„ngen }
  103. { this is wrong for string or other complex
  104. result types !!! }
  105. if ret_in_acc(procinfo^.returntype.def) and
  106. assigned(hp^.left) and
  107. (hp^.left^.right^.treetype=exitn) and
  108. (hp^.right^.treetype=assignn) and
  109. (hp^.right^.left^.treetype=funcretn) then
  110. begin
  111. if assigned(hp^.left^.right^.left) then
  112. CGMessage(cg_n_inefficient_code)
  113. else
  114. begin
  115. hp^.left^.right^.left:=hp^.right^.right;
  116. hp^.right^.right:=nil;
  117. disposetree(hp^.right);
  118. hp^.right:=nil;
  119. end;
  120. end
  121. { warning if unreachable code occurs and elimate this }
  122. else if (hp^.right^.treetype in
  123. [exitn,breakn,continuen,goton]) and
  124. assigned(hp^.left) and
  125. (hp^.left^.treetype<>labeln) then
  126. begin
  127. { use correct line number }
  128. aktfilepos:=hp^.left^.fileinfo;
  129. disposetree(hp^.left);
  130. hp^.left:=nil;
  131. CGMessage(cg_w_unreachable_code);
  132. { old lines }
  133. aktfilepos:=hp^.right^.fileinfo;
  134. end;
  135. end;
  136. if assigned(hp^.right) then
  137. begin
  138. cleartempgen;
  139. codegenerror:=false;
  140. firstpass(hp^.right);
  141. if (not (cs_extsyntax in aktmoduleswitches)) and
  142. assigned(hp^.right^.resulttype) and
  143. (hp^.right^.resulttype<>pdef(voiddef)) then
  144. CGMessage(cg_e_illegal_expression);
  145. {if codegenerror then
  146. exit;}
  147. hp^.registers32:=hp^.right^.registers32;
  148. hp^.registersfpu:=hp^.right^.registersfpu;
  149. {$ifdef SUPPORT_MMX}
  150. hp^.registersmmx:=hp^.right^.registersmmx;
  151. {$endif SUPPORT_MMX}
  152. end
  153. else
  154. hp^.registers32:=0;
  155. if hp^.registers32>p^.registers32 then
  156. p^.registers32:=hp^.registers32;
  157. if hp^.registersfpu>p^.registersfpu then
  158. p^.registersfpu:=hp^.registersfpu;
  159. {$ifdef SUPPORT_MMX}
  160. if hp^.registersmmx>p^.registersmmx then
  161. p^.registersmmx:=hp^.registersmmx;
  162. {$endif}
  163. inc(count);
  164. hp:=hp^.left;
  165. end;
  166. end;
  167. procedure firstasm(var p : ptree);
  168. begin
  169. procinfo^.flags:=procinfo^.flags or pi_uses_asm;
  170. end;
  171. procedure firstpass(var p : ptree);
  172. const
  173. procedures : array[ttreetyp] of firstpassproc =
  174. (firstadd, {addn}
  175. firstadd, {muln}
  176. firstadd, {subn}
  177. firstmoddiv, {divn}
  178. firstadd, {symdifn}
  179. firstmoddiv, {modn}
  180. firstassignment, {assignn}
  181. firstload, {loadn}
  182. firstrange, {range}
  183. firstadd, {ltn}
  184. firstadd, {lten}
  185. firstadd, {gtn}
  186. firstadd, {gten}
  187. firstadd, {equaln}
  188. firstadd, {unequaln}
  189. firstin, {inn}
  190. firstadd, {orn}
  191. firstadd, {xorn}
  192. firstshlshr, {shrn}
  193. firstshlshr, {shln}
  194. firstadd, {slashn}
  195. firstadd, {andn}
  196. firstsubscript, {subscriptn}
  197. firstderef, {derefn}
  198. firstaddr, {addrn}
  199. firstdoubleaddr, {doubleaddrn}
  200. firstordconst, {ordconstn}
  201. firsttypeconv, {typeconvn}
  202. firstcalln, {calln}
  203. firstnothing, {callparan}
  204. firstrealconst, {realconstn}
  205. firstfixconst, {fixconstn}
  206. firstunaryminus, {unaryminusn}
  207. firstasm, {asmn}
  208. firstvec, {vecn}
  209. firstpointerconst,{pointerconstn}
  210. firststringconst, {stringconstn}
  211. firstfuncret, {funcretn}
  212. firstself, {selfn}
  213. firstnot, {notn}
  214. firstinline, {inlinen}
  215. firstniln, {niln}
  216. firsterror, {errorn}
  217. firsttype, {typen}
  218. firsthnew, {hnewn}
  219. firsthdispose, {hdisposen}
  220. firstnew, {newn}
  221. firstsimplenewdispose, {simpledisposen}
  222. firstsetelement, {setelementn}
  223. firstsetconst, {setconstn}
  224. firstblock, {blockn}
  225. firststatement, {statementn}
  226. firstnothing, {loopn}
  227. firstif, {ifn}
  228. firstnothing, {breakn}
  229. firstnothing, {continuen}
  230. first_while_repeat, {repeatn}
  231. first_while_repeat, {whilen}
  232. firstfor, {forn}
  233. firstexit, {exitn}
  234. firstwith, {withn}
  235. firstcase, {casen}
  236. firstlabel, {labeln}
  237. firstgoto, {goton}
  238. firstsimplenewdispose, {simplenewn}
  239. firsttryexcept, {tryexceptn}
  240. firstraise, {raisen}
  241. firstnothing, {switchesn}
  242. firsttryfinally, {tryfinallyn}
  243. firston, {onn}
  244. firstis, {isn}
  245. firstas, {asn}
  246. firsterror, {caretn}
  247. firstnothing, {failn}
  248. firstadd, {starstarn}
  249. firstprocinline, {procinlinen}
  250. firstarrayconstruct, {arrayconstructn}
  251. firstarrayconstructrange, {arrayconstructrangen}
  252. firstnothing, {nothingn}
  253. firstloadvmt {loadvmtn}
  254. );
  255. var
  256. oldcodegenerror : boolean;
  257. oldlocalswitches : tlocalswitches;
  258. oldpos : tfileposinfo;
  259. {$ifdef extdebug}
  260. str1,str2 : string;
  261. oldp : ptree;
  262. not_first : boolean;
  263. {$endif extdebug}
  264. begin
  265. {$ifdef extdebug}
  266. inc(total_of_firstpass);
  267. if (p^.firstpasscount>0) and only_one_pass then
  268. exit;
  269. {$endif extdebug}
  270. oldcodegenerror:=codegenerror;
  271. oldpos:=aktfilepos;
  272. oldlocalswitches:=aktlocalswitches;
  273. {$ifdef extdebug}
  274. if p^.firstpasscount>0 then
  275. begin
  276. move(p^,str1[1],sizeof(ttree));
  277. {$ifndef TP}
  278. {$ifopt H+}
  279. SetLength(str1,sizeof(ttree));
  280. {$else}
  281. str1[0]:=char(sizeof(ttree));
  282. {$endif}
  283. {$else}
  284. str1[0]:=char(sizeof(ttree));
  285. {$endif}
  286. new(oldp);
  287. oldp^:=p^;
  288. not_first:=true;
  289. inc(firstpass_several);
  290. end
  291. else
  292. not_first:=false;
  293. {$endif extdebug}
  294. if not p^.error then
  295. begin
  296. codegenerror:=false;
  297. aktfilepos:=p^.fileinfo;
  298. aktlocalswitches:=p^.localswitches;
  299. procedures[p^.treetype](p);
  300. aktlocalswitches:=oldlocalswitches;
  301. aktfilepos:=oldpos;
  302. p^.error:=codegenerror;
  303. codegenerror:=codegenerror or oldcodegenerror;
  304. end
  305. else
  306. codegenerror:=true;
  307. {$ifdef extdebug}
  308. if not_first then
  309. begin
  310. { dirty trick to compare two ttree's (PM) }
  311. move(p^,str2[1],sizeof(ttree));
  312. {$ifndef TP}
  313. {$ifopt H+}
  314. SetLength(str2,sizeof(ttree));
  315. {$else}
  316. str2[0]:=char(sizeof(ttree));
  317. {$endif}
  318. {$else}
  319. str2[0]:=char(sizeof(ttree));
  320. {$endif}
  321. if str1<>str2 then
  322. begin
  323. comment(v_debug,'tree changed after first counting pass '
  324. +tostr(longint(p^.treetype)));
  325. compare_trees(oldp,p);
  326. end;
  327. dispose(oldp);
  328. end;
  329. if count_ref then
  330. inc(p^.firstpasscount);
  331. {$endif extdebug}
  332. end;
  333. function do_firstpass(var p : ptree) : boolean;
  334. begin
  335. aktexceptblock:=nil;
  336. codegenerror:=false;
  337. firstpass(p);
  338. do_firstpass:=codegenerror;
  339. end;
  340. end.
  341. {
  342. $Log$
  343. Revision 1.112 2000-01-07 01:14:28 peter
  344. * updated copyright to 2000
  345. Revision 1.111 1999/12/14 09:58:42 florian
  346. + compiler checks now if a goto leaves an exception block
  347. Revision 1.110 1999/11/30 10:40:44 peter
  348. + ttype, tsymlist
  349. Revision 1.109 1999/11/18 15:34:47 pierre
  350. * Notes/Hints for local syms changed to
  351. Set_varstate function
  352. Revision 1.108 1999/11/17 17:05:01 pierre
  353. * Notes/hints changes
  354. Revision 1.107 1999/10/26 12:30:43 peter
  355. * const parameter is now checked
  356. * better and generic check if a node can be used for assigning
  357. * export fixes
  358. * procvar equal works now (it never had worked at least from 0.99.8)
  359. * defcoll changed to linkedlist with pparaitem so it can easily be
  360. walked both directions
  361. Revision 1.106 1999/09/27 23:44:51 peter
  362. * procinfo is now a pointer
  363. * support for result setting in sub procedure
  364. Revision 1.105 1999/09/26 21:30:16 peter
  365. + constant pointer support which can happend with typecasting like
  366. const p=pointer(1)
  367. * better procvar parsing in typed consts
  368. Revision 1.104 1999/09/11 09:08:31 florian
  369. * fixed bug 596
  370. * fixed some problems with procedure variables and procedures of object,
  371. especially in TP mode. Procedure of object doesn't apply only to classes,
  372. it is also allowed for objects !!
  373. Revision 1.103 1999/08/04 00:23:09 florian
  374. * renamed i386asm and i386base to cpuasm and cpubase
  375. Revision 1.102 1999/05/27 19:44:42 peter
  376. * removed oldasm
  377. * plabel -> pasmlabel
  378. * -a switches to source writing automaticly
  379. * assembler readers OOPed
  380. * asmsymbol automaticly external
  381. * jumptables and other label fixes for asm readers
  382. Revision 1.101 1999/05/01 13:24:26 peter
  383. * merged nasm compiler
  384. * old asm moved to oldasm/
  385. Revision 1.100 1999/02/22 02:44:07 peter
  386. * ag386bin doesn't use i386.pas anymore
  387. Revision 1.99 1998/12/11 00:03:27 peter
  388. + globtype,tokens,version unit splitted from globals
  389. Revision 1.98 1998/11/23 17:49:03 pierre
  390. * ansistring support in extdebug code
  391. Revision 1.97 1998/11/05 14:26:47 peter
  392. * fixed variant warning with was sometimes said with sets
  393. Revision 1.96 1998/10/06 20:49:07 peter
  394. * m68k compiler compiles again
  395. Revision 1.95 1998/09/24 15:13:44 peter
  396. * fixed type node which was always set to void :(
  397. Revision 1.94 1998/09/23 20:42:22 peter
  398. * splitted pass_1
  399. }