pass_1.pas 13 KB

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