pass_1.pas 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. {
  2. $Id$
  3. Copyright (c) 1996-98 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
  35. {$ifdef i386}
  36. ,i386base,i386asm
  37. ,tgeni386
  38. {$endif}
  39. {$ifdef m68k}
  40. ,m68k,tgen68k
  41. {$endif}
  42. ;
  43. {*****************************************************************************
  44. FirstPass
  45. *****************************************************************************}
  46. type
  47. firstpassproc = procedure(var p : ptree);
  48. procedure firstnothing(var p : ptree);
  49. begin
  50. p^.resulttype:=voiddef;
  51. end;
  52. procedure firsterror(var p : ptree);
  53. begin
  54. p^.error:=true;
  55. codegenerror:=true;
  56. p^.resulttype:=generrordef;
  57. end;
  58. procedure firststatement(var p : ptree);
  59. begin
  60. { left is the next statement in the list }
  61. p^.resulttype:=voiddef;
  62. { no temps over several statements }
  63. cleartempgen;
  64. { right is the statement itself calln assignn or a complex one }
  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.retdef) 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:=getcopy(hp^.right^.right);
  116. disposetree(hp^.right);
  117. hp^.right:=nil;
  118. end;
  119. end
  120. { warning if unreachable code occurs and elimate this }
  121. else if (hp^.right^.treetype in
  122. [exitn,breakn,continuen,goton]) and
  123. assigned(hp^.left) and
  124. (hp^.left^.treetype<>labeln) then
  125. begin
  126. { use correct line number }
  127. aktfilepos:=hp^.left^.fileinfo;
  128. disposetree(hp^.left);
  129. hp^.left:=nil;
  130. CGMessage(cg_w_unreachable_code);
  131. { old lines }
  132. aktfilepos:=hp^.right^.fileinfo;
  133. end;
  134. end;
  135. if assigned(hp^.right) then
  136. begin
  137. cleartempgen;
  138. firstpass(hp^.right);
  139. if (not (cs_extsyntax in aktmoduleswitches)) and
  140. assigned(hp^.right^.resulttype) and
  141. (hp^.right^.resulttype<>pdef(voiddef)) then
  142. CGMessage(cg_e_illegal_expression);
  143. if codegenerror then
  144. exit;
  145. hp^.registers32:=hp^.right^.registers32;
  146. hp^.registersfpu:=hp^.right^.registersfpu;
  147. {$ifdef SUPPORT_MMX}
  148. hp^.registersmmx:=hp^.right^.registersmmx;
  149. {$endif SUPPORT_MMX}
  150. end
  151. else
  152. hp^.registers32:=0;
  153. if hp^.registers32>p^.registers32 then
  154. p^.registers32:=hp^.registers32;
  155. if hp^.registersfpu>p^.registersfpu then
  156. p^.registersfpu:=hp^.registersfpu;
  157. {$ifdef SUPPORT_MMX}
  158. if hp^.registersmmx>p^.registersmmx then
  159. p^.registersmmx:=hp^.registersmmx;
  160. {$endif}
  161. inc(count);
  162. hp:=hp^.left;
  163. end;
  164. end;
  165. procedure firstasm(var p : ptree);
  166. begin
  167. procinfo.flags:=procinfo.flags or pi_uses_asm;
  168. end;
  169. procedure firstpass(var p : ptree);
  170. const
  171. procedures : array[ttreetyp] of firstpassproc =
  172. (firstadd, {addn}
  173. firstadd, {muln}
  174. firstadd, {subn}
  175. firstmoddiv, {divn}
  176. firstadd, {symdifn}
  177. firstmoddiv, {modn}
  178. firstassignment, {assignn}
  179. firstload, {loadn}
  180. firstrange, {range}
  181. firstadd, {ltn}
  182. firstadd, {lten}
  183. firstadd, {gtn}
  184. firstadd, {gten}
  185. firstadd, {equaln}
  186. firstadd, {unequaln}
  187. firstin, {inn}
  188. firstadd, {orn}
  189. firstadd, {xorn}
  190. firstshlshr, {shrn}
  191. firstshlshr, {shln}
  192. firstadd, {slashn}
  193. firstadd, {andn}
  194. firstsubscript, {subscriptn}
  195. firstderef, {derefn}
  196. firstaddr, {addrn}
  197. firstdoubleaddr, {doubleaddrn}
  198. firstordconst, {ordconstn}
  199. firsttypeconv, {typeconvn}
  200. firstcalln, {calln}
  201. firstnothing, {callparan}
  202. firstrealconst, {realconstn}
  203. firstfixconst, {fixconstn}
  204. firstumminus, {umminusn}
  205. firstasm, {asmn}
  206. firstvec, {vecn}
  207. firststringconst, {stringconstn}
  208. firstfuncret, {funcretn}
  209. firstself, {selfn}
  210. firstnot, {notn}
  211. firstinline, {inlinen}
  212. firstniln, {niln}
  213. firsterror, {errorn}
  214. firsttype, {typen}
  215. firsthnew, {hnewn}
  216. firsthdispose, {hdisposen}
  217. firstnew, {newn}
  218. firstsimplenewdispose, {simpledisposen}
  219. firstsetelement, {setelementn}
  220. firstsetconst, {setconstn}
  221. firstblock, {blockn}
  222. firststatement, {statementn}
  223. firstnothing, {loopn}
  224. firstif, {ifn}
  225. firstnothing, {breakn}
  226. firstnothing, {continuen}
  227. first_while_repeat, {repeatn}
  228. first_while_repeat, {whilen}
  229. firstfor, {forn}
  230. firstexit, {exitn}
  231. firstwith, {withn}
  232. firstcase, {casen}
  233. firstlabel, {labeln}
  234. firstgoto, {goton}
  235. firstsimplenewdispose, {simplenewn}
  236. firsttryexcept, {tryexceptn}
  237. firstraise, {raisen}
  238. firstnothing, {switchesn}
  239. firsttryfinally, {tryfinallyn}
  240. firston, {onn}
  241. firstis, {isn}
  242. firstas, {asn}
  243. firsterror, {caretn}
  244. firstnothing, {failn}
  245. firstadd, {starstarn}
  246. firstprocinline, {procinlinen}
  247. firstarrayconstruct, {arrayconstructn}
  248. firstarrayconstructrange, {arrayconstructrangen}
  249. firstnothing, {nothingn}
  250. firstloadvmt {loadvmtn}
  251. );
  252. var
  253. oldcodegenerror : boolean;
  254. oldlocalswitches : tlocalswitches;
  255. oldpos : tfileposinfo;
  256. {$ifdef extdebug}
  257. str1,str2 : string;
  258. oldp : ptree;
  259. not_first : boolean;
  260. {$endif extdebug}
  261. begin
  262. {$ifdef extdebug}
  263. inc(total_of_firstpass);
  264. if (p^.firstpasscount>0) and only_one_pass then
  265. exit;
  266. {$endif extdebug}
  267. oldcodegenerror:=codegenerror;
  268. oldpos:=aktfilepos;
  269. oldlocalswitches:=aktlocalswitches;
  270. {$ifdef extdebug}
  271. if p^.firstpasscount>0 then
  272. begin
  273. move(p^,str1[1],sizeof(ttree));
  274. {$ifndef TP}
  275. {$ifopt H+}
  276. SetLength(str1,sizeof(ttree));
  277. {$else}
  278. str1[0]:=char(sizeof(ttree));
  279. {$endif}
  280. {$else}
  281. str1[0]:=char(sizeof(ttree));
  282. {$endif}
  283. new(oldp);
  284. oldp^:=p^;
  285. not_first:=true;
  286. inc(firstpass_several);
  287. end
  288. else
  289. not_first:=false;
  290. {$endif extdebug}
  291. if not p^.error then
  292. begin
  293. codegenerror:=false;
  294. aktfilepos:=p^.fileinfo;
  295. aktlocalswitches:=p^.localswitches;
  296. procedures[p^.treetype](p);
  297. aktlocalswitches:=oldlocalswitches;
  298. aktfilepos:=oldpos;
  299. p^.error:=codegenerror;
  300. codegenerror:=codegenerror or oldcodegenerror;
  301. end
  302. else
  303. codegenerror:=true;
  304. {$ifdef extdebug}
  305. if not_first then
  306. begin
  307. { dirty trick to compare two ttree's (PM) }
  308. move(p^,str2[1],sizeof(ttree));
  309. {$ifndef TP}
  310. {$ifopt H+}
  311. SetLength(str2,sizeof(ttree));
  312. {$else}
  313. str2[0]:=char(sizeof(ttree));
  314. {$endif}
  315. {$else}
  316. str2[0]:=char(sizeof(ttree));
  317. {$endif}
  318. if str1<>str2 then
  319. begin
  320. comment(v_debug,'tree changed after first counting pass '
  321. +tostr(longint(p^.treetype)));
  322. compare_trees(oldp,p);
  323. end;
  324. dispose(oldp);
  325. end;
  326. if count_ref then
  327. inc(p^.firstpasscount);
  328. {$endif extdebug}
  329. end;
  330. function do_firstpass(var p : ptree) : boolean;
  331. begin
  332. codegenerror:=false;
  333. firstpass(p);
  334. do_firstpass:=codegenerror;
  335. end;
  336. end.
  337. {
  338. $Log$
  339. Revision 1.102 1999-05-27 19:44:42 peter
  340. * removed oldasm
  341. * plabel -> pasmlabel
  342. * -a switches to source writing automaticly
  343. * assembler readers OOPed
  344. * asmsymbol automaticly external
  345. * jumptables and other label fixes for asm readers
  346. Revision 1.101 1999/05/01 13:24:26 peter
  347. * merged nasm compiler
  348. * old asm moved to oldasm/
  349. Revision 1.100 1999/02/22 02:44:07 peter
  350. * ag386bin doesn't use i386.pas anymore
  351. Revision 1.99 1998/12/11 00:03:27 peter
  352. + globtype,tokens,version unit splitted from globals
  353. Revision 1.98 1998/11/23 17:49:03 pierre
  354. * ansistring support in extdebug code
  355. Revision 1.97 1998/11/05 14:26:47 peter
  356. * fixed variant warning with was sometimes said with sets
  357. Revision 1.96 1998/10/06 20:49:07 peter
  358. * m68k compiler compiles again
  359. Revision 1.95 1998/09/24 15:13:44 peter
  360. * fixed type node which was always set to void :(
  361. Revision 1.94 1998/09/23 20:42:22 peter
  362. * splitted pass_1
  363. }