pass_1.pas 14 KB

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