pass_2.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. This unit handles the codegeneration pass
  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. unit pass_2;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. node;
  23. type
  24. tenumflowcontrol = (fc_exit,fc_break,fc_continue);
  25. tflowcontrol = set of tenumflowcontrol;
  26. var
  27. allow_multi_pass2 : boolean;
  28. flowcontrol : tflowcontrol;
  29. { produces assembler for the expression in variable p }
  30. { and produces an assembler node at the end }
  31. procedure generatecode(var p : tnode);
  32. { produces the actual code }
  33. function do_secondpass(var p : tnode) : boolean;
  34. procedure secondpass(var p : tnode);
  35. implementation
  36. uses
  37. {$ifdef EXTDEBUG}
  38. cutils,
  39. {$endif}
  40. globtype,systems,verbose,
  41. cclasses,globals,
  42. symconst,symbase,symtype,symsym,paramgr,
  43. aasmbase,aasmtai,
  44. pass_1,cpubase,cginfo,cgbase,
  45. {$ifdef EXTDEBUG}
  46. cgobj,
  47. {$endif EXTDEBUG}
  48. regvars,nflw,rgobj;
  49. {*****************************************************************************
  50. SecondPass
  51. *****************************************************************************}
  52. {$ifdef EXTDEBUG}
  53. procedure logsecond(ht:tnodetype; entry: boolean);
  54. const
  55. secondnames: array[tnodetype] of string[13] =
  56. ('<emptynode>',
  57. 'add-addn', {addn}
  58. 'add-muln', {muln}
  59. 'add-subn', {subn}
  60. 'moddiv-divn', {divn}
  61. 'add-symdifn', {symdifn}
  62. 'moddiv-modn', {modn}
  63. 'assignment', {assignn}
  64. 'load', {loadn}
  65. 'nothing-range', {range}
  66. 'add-ltn', {ltn}
  67. 'add-lten', {lten}
  68. 'add-gtn', {gtn}
  69. 'add-gten', {gten}
  70. 'add-equaln', {equaln}
  71. 'add-unequaln', {unequaln}
  72. 'in', {inn}
  73. 'add-orn', {orn}
  74. 'add-xorn', {xorn}
  75. 'shlshr-shrn', {shrn}
  76. 'shlshr-shln', {shln}
  77. 'add-slashn', {slashn}
  78. 'add-andn', {andn}
  79. 'subscriptn', {subscriptn}
  80. 'deref', {derefn}
  81. 'addr', {addrn}
  82. 'ordconst', {ordconstn}
  83. 'typeconv', {typeconvn}
  84. 'calln', {calln}
  85. 'noth-callpar',{callparan}
  86. 'realconst', {realconstn}
  87. 'unaryminus', {unaryminusn}
  88. 'asm', {asmn}
  89. 'vecn', {vecn}
  90. 'pointerconst',{pointerconstn}
  91. 'stringconst', {stringconstn}
  92. 'not', {notn}
  93. 'inline', {inlinen}
  94. 'niln', {niln}
  95. 'error', {errorn}
  96. 'nothing-typen', {typen}
  97. 'setelement', {setelementn}
  98. 'setconst', {setconstn}
  99. 'blockn', {blockn}
  100. 'statement', {statementn}
  101. 'ifn', {ifn}
  102. 'breakn', {breakn}
  103. 'continuen', {continuen}
  104. 'while_repeat', {whilerepeatn}
  105. 'for', {forn}
  106. 'exitn', {exitn}
  107. 'with', {withn}
  108. 'case', {casen}
  109. 'label', {labeln}
  110. 'goto', {goton}
  111. 'tryexcept', {tryexceptn}
  112. 'raise', {raisen}
  113. 'tryfinally', {tryfinallyn}
  114. 'on', {onn}
  115. 'is', {isn}
  116. 'as', {asn}
  117. 'error-caret', {caretn}
  118. 'add-starstar', {starstarn}
  119. 'arrayconstruc', {arrayconstructn}
  120. 'noth-arrcnstr', {arrayconstructrangen}
  121. 'tempcreaten',
  122. 'temprefn',
  123. 'tempdeleten',
  124. 'addoptn',
  125. 'nothing-nothg', {nothingn}
  126. 'loadvmt', {loadvmtn}
  127. 'guidconstn',
  128. 'rttin',
  129. 'loadparentfpn'
  130. );
  131. var
  132. p: pchar;
  133. begin
  134. if entry then
  135. p := strpnew('second '+secondnames[ht]+' (entry)')
  136. else
  137. p := strpnew('second '+secondnames[ht]+' (exit)');
  138. exprasmlist.concat(tai_comment.create(p));
  139. end;
  140. {$endif EXTDEBUG}
  141. procedure secondpass(var p : tnode);
  142. var
  143. oldcodegenerror : boolean;
  144. oldlocalswitches : tlocalswitches;
  145. oldpos : tfileposinfo;
  146. {$ifdef TEMPREGDEBUG}
  147. prevp : pptree;
  148. {$endif TEMPREGDEBUG}
  149. {$ifdef EXTDEBUG}
  150. {$endif EXTDEBUG}
  151. begin
  152. if not assigned(p) then
  153. internalerror(200208221);
  154. if not(nf_error in p.flags) then
  155. begin
  156. oldcodegenerror:=codegenerror;
  157. oldlocalswitches:=aktlocalswitches;
  158. oldpos:=aktfilepos;
  159. {$ifdef TEMPREGDEBUG}
  160. testregisters32;
  161. prevp:=curptree;
  162. curptree:=@p;
  163. p^.usableregs:=usablereg32;
  164. {$endif TEMPREGDEBUG}
  165. aktfilepos:=p.fileinfo;
  166. aktlocalswitches:=p.localswitches;
  167. codegenerror:=false;
  168. {$ifdef EXTDEBUG}
  169. if (p.expectloc=LOC_INVALID) then
  170. Comment(V_Warning,'ExpectLoc is not set before secondpass: '+nodetype2str[p.nodetype]);
  171. if (not allow_multi_pass2) and
  172. (p.location.loc<>LOC_INVALID) then
  173. Comment(V_Warning,'Location.Loc is already set before secondpass: '+nodetype2str[p.nodetype]);
  174. if (cs_asm_nodes in aktglobalswitches) then
  175. logsecond(p.nodetype,true);
  176. {$endif EXTDEBUG}
  177. p.pass_2;
  178. {$ifdef EXTDEBUG}
  179. if (cs_asm_nodes in aktglobalswitches) then
  180. logsecond(p.nodetype,false);
  181. if (not codegenerror) then
  182. begin
  183. if (p.location.loc=LOC_INVALID) then
  184. Comment(V_Warning,'Location not set in secondpass: '+nodetype2str[p.nodetype])
  185. else if (p.location.loc<>p.expectloc) then
  186. Comment(V_Warning,'Location is different in secondpass: '+nodetype2str[p.nodetype]);
  187. end;
  188. {$ifdef i386}
  189. if rg.unusedregsint*([first_int_supreg..last_int_supreg] - [RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG])<>
  190. ([first_int_supreg..last_int_supreg] - [RS_FRAME_POINTER_REG,RS_STACK_POINTER_REG]) then
  191. internalerror(200306171);
  192. {$endif i386}
  193. {$endif EXTDEBUG}
  194. if codegenerror then
  195. include(p.flags,nf_error);
  196. codegenerror:=codegenerror or oldcodegenerror;
  197. aktlocalswitches:=oldlocalswitches;
  198. aktfilepos:=oldpos;
  199. {$ifdef TEMPREGDEBUG}
  200. curptree:=prevp;
  201. {$endif TEMPREGDEBUG}
  202. {$ifdef EXTTEMPREGDEBUG}
  203. if p.usableregs-usablereg32>p.reallyusedregs then
  204. p.reallyusedregs:=p.usableregs-usablereg32;
  205. if p.reallyusedregs<p.registers32 then
  206. Comment(V_Debug,'registers32 overestimated '+tostr(p^.registers32)+
  207. '>'+tostr(p^.reallyusedregs));
  208. {$endif EXTTEMPREGDEBUG}
  209. end
  210. else
  211. codegenerror:=true;
  212. end;
  213. function do_secondpass(var p : tnode) : boolean;
  214. begin
  215. codegenerror:=false;
  216. if not(nf_error in p.flags) then
  217. secondpass(p);
  218. do_secondpass:=codegenerror;
  219. end;
  220. procedure clearrefs(p : tnamedindexitem;arg:pointer);
  221. begin
  222. if (tsym(p).typ=varsym) then
  223. if tvarsym(p).refs>1 then
  224. tvarsym(p).refs:=1;
  225. end;
  226. procedure generatecode(var p : tnode);
  227. {$ifdef EXTDEBUG}
  228. var
  229. sr : tsuperregister;
  230. {$endif EXTDEBUG}
  231. begin
  232. flowcontrol:=[];
  233. { when size optimization only count occurrence }
  234. if cs_littlesize in aktglobalswitches then
  235. rg.t_times:=1
  236. else
  237. { reference for repetition is 100 }
  238. rg.t_times:=100;
  239. { clear register count }
  240. rg.clearregistercount;
  241. symtablestack.foreach_static({$ifdef FPCPROCVAR}@{$endif}clearrefs,nil);
  242. symtablestack.next.foreach_static({$ifdef FPCPROCVAR}@{$endif}clearrefs,nil);
  243. { firstpass everything }
  244. do_firstpass(p);
  245. { only do secondpass if there are no errors }
  246. if ErrorCount=0 then
  247. begin
  248. { assign parameter locations }
  249. current_procinfo.after_pass1;
  250. { caller paraloc info is also necessary in the stackframe_entry }
  251. { code of the ppc (and possibly other processors) }
  252. if not current_procinfo.procdef.has_paraloc_info then
  253. begin
  254. paramanager.create_paraloc_info(current_procinfo.procdef,callerside);
  255. current_procinfo.procdef.has_paraloc_info:=true;
  256. end;
  257. { process register variable stuff (JM) }
  258. assign_regvars(p);
  259. // load_regvars(current_procinfo.aktentrycode,p);
  260. { for the i386 it must be done in genexitcode because it has }
  261. { to add 'fstp' instructions when using fpu regvars and those }
  262. { must come after the "exitlabel" (JM) }
  263. {$ifndef i386}
  264. // cleanup_regvars(current_procinfo.aktexitcode);
  265. {$endif i386}
  266. current_procinfo.allocate_framepointer_reg;
  267. do_secondpass(p);
  268. {$ifdef EXTDEBUG}
  269. for sr:=first_int_imreg to last_int_imreg do
  270. if not(sr in rg.unusedregsint) then
  271. Comment(V_Warning,'Register '+std_regname(newreg(R_INTREGISTER,sr,R_SUBNONE))+' not released');
  272. {$endif EXTDEBUG}
  273. if assigned(current_procinfo.procdef) then
  274. current_procinfo.procdef.fpu_used:=p.registersfpu;
  275. end;
  276. current_procinfo.aktproccode.concatlist(exprasmlist);
  277. end;
  278. end.
  279. {
  280. $Log$
  281. Revision 1.66 2003-09-28 21:45:52 peter
  282. * fix register leak in with debug
  283. Revision 1.65 2003/09/28 17:55:04 peter
  284. * parent framepointer changed to hidden parameter
  285. * tloadparentfpnode added
  286. Revision 1.64 2003/09/03 15:55:01 peter
  287. * NEWRA branch merged
  288. Revision 1.63.2.3 2003/08/31 15:46:26 peter
  289. * more updates for tregister
  290. Revision 1.63.2.2 2003/08/31 13:50:16 daniel
  291. * Remove sorting and use pregenerated indexes
  292. * Some work on making things compile
  293. Revision 1.63.2.1 2003/08/29 17:28:59 peter
  294. * next batch of updates
  295. Revision 1.63 2003/08/11 21:18:20 peter
  296. * start of sparc support for newra
  297. Revision 1.62 2003/08/10 17:25:23 peter
  298. * fixed some reported bugs
  299. Revision 1.61 2003/07/06 17:58:22 peter
  300. * framepointer fixes for sparc
  301. * parent framepointer code more generic
  302. Revision 1.60 2003/07/06 15:31:20 daniel
  303. * Fixed register allocator. *Lots* of fixes.
  304. Revision 1.59 2003/07/06 10:18:47 jonas
  305. * also generate the caller paraloc info of a procedure if it doesn't exist
  306. yet at the start of pass_2
  307. Revision 1.58 2003/07/05 20:13:03 jonas
  308. * create_paraloc_info() is now called separately for the caller and
  309. callee info
  310. * fixed ppc cycle
  311. Revision 1.57 2003/06/13 21:19:30 peter
  312. * current_procdef removed, use current_procinfo.procdef instead
  313. Revision 1.56 2003/06/12 16:43:07 peter
  314. * newra compiles for sparc
  315. Revision 1.55 2003/06/09 12:23:30 peter
  316. * init/final of procedure data splitted from genentrycode
  317. * use asmnode getposition to insert final at the correct position
  318. als for the implicit try...finally
  319. Revision 1.54 2003/06/03 13:01:59 daniel
  320. * Register allocator finished
  321. Revision 1.53 2003/05/26 21:17:17 peter
  322. * procinlinenode removed
  323. * aktexit2label removed, fast exit removed
  324. + tcallnode.inlined_pass_2 added
  325. Revision 1.52 2003/05/15 18:58:53 peter
  326. * removed selfpointer_offset, vmtpointer_offset
  327. * tvarsym.adjusted_address
  328. * address in localsymtable is now in the real direction
  329. * removed some obsolete globals
  330. Revision 1.51 2003/05/13 19:14:41 peter
  331. * failn removed
  332. * inherited result code check moven to pexpr
  333. Revision 1.50 2003/05/09 17:47:02 peter
  334. * self moved to hidden parameter
  335. * removed hdisposen,hnewn,selfn
  336. Revision 1.49 2003/04/27 11:21:33 peter
  337. * aktprocdef renamed to current_procinfo.procdef
  338. * procinfo renamed to current_procinfo
  339. * procinfo will now be stored in current_module so it can be
  340. cleaned up properly
  341. * gen_main_procsym changed to create_main_proc and release_main_proc
  342. to also generate a tprocinfo structure
  343. * fixed unit implicit initfinal
  344. Revision 1.48 2003/04/27 07:29:50 peter
  345. * current_procinfo.procdef cleanup, current_procdef is now always nil when parsing
  346. a new procdef declaration
  347. * aktprocsym removed
  348. * lexlevel removed, use symtable.symtablelevel instead
  349. * implicit init/final code uses the normal genentry/genexit
  350. * funcret state checking updated for new funcret handling
  351. Revision 1.47 2003/04/25 20:59:33 peter
  352. * removed funcretn,funcretsym, function result is now in varsym
  353. and aliases for result and function name are added using absolutesym
  354. * vs_hidden parameter for funcret passed in parameter
  355. * vs_hidden fixes
  356. * writenode changed to printnode and released from extdebug
  357. * -vp option added to generate a tree.log with the nodetree
  358. * nicer printnode for statements, callnode
  359. Revision 1.46 2003/04/23 10:12:14 peter
  360. * allow multi pass2 changed to global boolean instead of node flag
  361. Revision 1.45 2003/04/22 23:50:23 peter
  362. * firstpass uses expectloc
  363. * checks if there are differences between the expectloc and
  364. location.loc from secondpass in EXTDEBUG
  365. Revision 1.44 2003/04/22 12:45:58 florian
  366. * fixed generic in operator code
  367. + added debug code to check if all scratch registers are released
  368. Revision 1.43 2003/01/09 20:40:59 daniel
  369. * Converted some code in cgx86.pas to new register numbering
  370. Revision 1.42 2003/01/09 15:49:56 daniel
  371. * Added register conversion
  372. Revision 1.41 2002/12/22 14:35:39 peter
  373. * removed Writeln
  374. Revision 1.40 2002/12/21 23:21:47 mazen
  375. + added support for the shift nodes
  376. + added debug output on screen with -an command line option
  377. Revision 1.39 2002/08/23 16:14:49 peter
  378. * tempgen cleanup
  379. * tt_noreuse temp type added that will be used in genentrycode
  380. Revision 1.38 2002/08/20 16:55:38 peter
  381. * don't write (stabs)line info when inlining a procedure
  382. Revision 1.37 2002/08/19 19:36:44 peter
  383. * More fixes for cross unit inlining, all tnodes are now implemented
  384. * Moved pocall_internconst to po_internconst because it is not a
  385. calling type at all and it conflicted when inlining of these small
  386. functions was requested
  387. Revision 1.36 2002/08/18 20:06:24 peter
  388. * inlining is now also allowed in interface
  389. * renamed write/load to ppuwrite/ppuload
  390. * tnode storing in ppu
  391. * nld,ncon,nbas are already updated for storing in ppu
  392. Revision 1.35 2002/08/17 09:23:38 florian
  393. * first part of procinfo rewrite
  394. Revision 1.34 2002/08/15 19:10:35 peter
  395. * first things tai,tnode storing in ppu
  396. Revision 1.33 2002/07/30 20:50:44 florian
  397. * the code generator knows now if parameters are in registers
  398. Revision 1.32 2002/07/19 11:41:36 daniel
  399. * State tracker work
  400. * The whilen and repeatn are now completely unified into whilerepeatn. This
  401. allows the state tracker to change while nodes automatically into
  402. repeat nodes.
  403. * Resulttypepass improvements to the notn. 'not not a' is optimized away and
  404. 'not(a>b)' is optimized into 'a<=b'.
  405. * Resulttypepass improvements to the whilerepeatn. 'while not a' is optimized
  406. by removing the notn and later switchting the true and falselabels. The
  407. same is done with 'repeat until not a'.
  408. Revision 1.31 2002/07/01 18:46:25 peter
  409. * internal linker
  410. * reorganized aasm layer
  411. Revision 1.30 2002/05/18 13:34:11 peter
  412. * readded missing revisions
  413. Revision 1.29 2002/05/16 19:46:42 carl
  414. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  415. + try to fix temp allocation (still in ifdef)
  416. + generic constructor calls
  417. + start of tassembler / tmodulebase class cleanup
  418. Revision 1.27 2002/05/12 16:53:08 peter
  419. * moved entry and exitcode to ncgutil and cgobj
  420. * foreach gets extra argument for passing local data to the
  421. iterator function
  422. * -CR checks also class typecasts at runtime by changing them
  423. into as
  424. * fixed compiler to cycle with the -CR option
  425. * fixed stabs with elf writer, finally the global variables can
  426. be watched
  427. * removed a lot of routines from cga unit and replaced them by
  428. calls to cgobj
  429. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  430. u32bit then the other is typecasted also to u32bit without giving
  431. a rangecheck warning/error.
  432. * fixed pascal calling method with reversing also the high tree in
  433. the parast, detected by tcalcst3 test
  434. Revision 1.26 2002/04/21 19:02:04 peter
  435. * removed newn and disposen nodes, the code is now directly
  436. inlined from pexpr
  437. * -an option that will write the secondpass nodes to the .s file, this
  438. requires EXTDEBUG define to actually write the info
  439. * fixed various internal errors and crashes due recent code changes
  440. Revision 1.25 2002/04/20 21:32:24 carl
  441. + generic FPC_CHECKPOINTER
  442. + first parameter offset in stack now portable
  443. * rename some constants
  444. + move some cpu stuff to other units
  445. - remove unused constents
  446. * fix stacksize for some targets
  447. * fix generic size problems which depend now on EXTEND_SIZE constant
  448. Revision 1.24 2002/04/07 13:30:13 carl
  449. - removed unused variable
  450. Revision 1.23 2002/04/02 17:11:29 peter
  451. * tlocation,treference update
  452. * LOC_CONSTANT added for better constant handling
  453. * secondadd splitted in multiple routines
  454. * location_force_reg added for loading a location to a register
  455. of a specified size
  456. * secondassignment parses now first the right and then the left node
  457. (this is compatible with Kylix). This saves a lot of push/pop especially
  458. with string operations
  459. * adapted some routines to use the new cg methods
  460. Revision 1.22 2002/03/31 20:26:35 jonas
  461. + a_loadfpu_* and a_loadmm_* methods in tcg
  462. * register allocation is now handled by a class and is mostly processor
  463. independent (+rgobj.pas and i386/rgcpu.pas)
  464. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  465. * some small improvements and fixes to the optimizer
  466. * some register allocation fixes
  467. * some fpuvaroffset fixes in the unary minus node
  468. * push/popusedregisters is now called rg.save/restoreusedregisters and
  469. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  470. also better optimizable)
  471. * fixed and optimized register saving/restoring for new/dispose nodes
  472. * LOC_FPU locations now also require their "register" field to be set to
  473. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  474. - list field removed of the tnode class because it's not used currently
  475. and can cause hard-to-find bugs
  476. }