pass_2.pas 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. {
  2. $Id$
  3. Copyright (c) 1993-98 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. {$ifdef TP}
  19. {$E+,F+,N+}
  20. {$endif}
  21. unit pass_2;
  22. interface
  23. uses
  24. tree;
  25. { produces assembler for the expression in variable p }
  26. { and produces an assembler node at the end }
  27. procedure generatecode(var p : ptree);
  28. { produces the actual code }
  29. function do_secondpass(var p : ptree) : boolean;
  30. procedure secondpass(var p : ptree);
  31. implementation
  32. uses
  33. globtype,systems,
  34. cobjects,comphook,verbose,globals,files,
  35. symtable,types,aasm,scanner,
  36. pass_1,hcodegen,temp_gen
  37. {$ifdef GDB}
  38. ,gdb
  39. {$endif}
  40. {$ifdef i386}
  41. {$ifdef Ag386Bin}
  42. ,i386base,i386asm
  43. {$else}
  44. ,i386
  45. {$endif}
  46. ,tgeni386,cgai386
  47. ,cg386con,cg386mat,cg386cnv,cg386set,cg386add
  48. ,cg386mem,cg386cal,cg386ld,cg386flw,cg386inl
  49. {$endif}
  50. {$ifdef m68k}
  51. ,m68k,tgen68k,cga68k
  52. ,cg68kcon,cg68kmat,cg68kcnv,cg68kset,cg68kadd
  53. ,cg68kmem,cg68kcal,cg68kld,cg68kflw,cg68kinl
  54. {$endif}
  55. ;
  56. {*****************************************************************************
  57. SecondPass
  58. *****************************************************************************}
  59. type
  60. secondpassproc = procedure(var p : ptree);
  61. procedure secondnothing(var p : ptree);
  62. begin
  63. end;
  64. procedure seconderror(var p : ptree);
  65. begin
  66. p^.error:=true;
  67. codegenerror:=true;
  68. end;
  69. procedure secondstatement(var p : ptree);
  70. var
  71. hp : ptree;
  72. oldrl : plinkedlist;
  73. begin
  74. hp:=p;
  75. while assigned(hp) do
  76. begin
  77. if assigned(hp^.right) then
  78. begin
  79. cleartempgen;
  80. oldrl:=temptoremove;
  81. temptoremove:=new(plinkedlist,init);
  82. secondpass(hp^.right);
  83. { release temp. ansi strings }
  84. removetemps(exprasmlist,temptoremove);
  85. dispose(temptoremove,done);
  86. temptoremove:=oldrl;
  87. end;
  88. hp:=hp^.left;
  89. end;
  90. end;
  91. procedure secondblockn(var p : ptree);
  92. begin
  93. { do second pass on left node }
  94. if assigned(p^.left) then
  95. secondpass(p^.left);
  96. end;
  97. procedure secondasm(var p : ptree);
  98. {$ifdef AG386BIN}
  99. var
  100. hp,hp2 : pai;
  101. localfixup,parafixup,
  102. i : longint;
  103. r : preference;
  104. {$endif}
  105. begin
  106. {$ifdef AG386BIN}
  107. if (aktprocsym^.definition^.options and poinline)<>0 then
  108. begin
  109. localfixup:=aktprocsym^.definition^.localst^.address_fixup;
  110. parafixup:=aktprocsym^.definition^.parast^.address_fixup;
  111. hp:=pai(p^.p_asm^.first);
  112. while assigned(hp) do
  113. begin
  114. hp2:=pai(hp^.getcopy);
  115. case hp2^.typ of
  116. ait_instruction :
  117. begin
  118. { fixup the references }
  119. for i:=1 to pai386(hp2)^.ops do
  120. if pai386(hp2)^.oper[i-1].typ=top_ref then
  121. begin
  122. r:=pai386(hp2)^.oper[i-1].ref;
  123. case r^.options of
  124. ref_parafixup :
  125. r^.offsetfixup:=parafixup;
  126. ref_localfixup :
  127. r^.offsetfixup:=localfixup;
  128. end;
  129. end;
  130. exprasmlist^.concat(hp2);
  131. end;
  132. ait_marker :
  133. begin
  134. { it's not an assembler block anymore }
  135. if not(pai_marker(hp2)^.kind in [AsmBlockStart, AsmBlockEnd]) then
  136. exprasmlist^.concat(hp2);
  137. end;
  138. else
  139. exprasmlist^.concat(hp2);
  140. end;
  141. hp:=pai(hp^.next);
  142. end
  143. end
  144. else
  145. {$endif}
  146. exprasmlist^.concatlist(p^.p_asm);
  147. if not p^.object_preserved then
  148. begin
  149. {$ifdef i386}
  150. maybe_loadesi;
  151. {$endif}
  152. {$ifdef m68k}
  153. maybe_loada5;
  154. {$endif}
  155. end;
  156. end;
  157. procedure secondpass(var p : ptree);
  158. const
  159. procedures : array[ttreetyp] of secondpassproc =
  160. (secondadd, {addn}
  161. secondadd, {muln}
  162. secondadd, {subn}
  163. secondmoddiv, {divn}
  164. secondadd, {symdifn}
  165. secondmoddiv, {modn}
  166. secondassignment, {assignn}
  167. secondload, {loadn}
  168. secondnothing, {range}
  169. secondadd, {ltn}
  170. secondadd, {lten}
  171. secondadd, {gtn}
  172. secondadd, {gten}
  173. secondadd, {equaln}
  174. secondadd, {unequaln}
  175. secondin, {inn}
  176. secondadd, {orn}
  177. secondadd, {xorn}
  178. secondshlshr, {shrn}
  179. secondshlshr, {shln}
  180. secondadd, {slashn}
  181. secondadd, {andn}
  182. secondsubscriptn, {subscriptn}
  183. secondderef, {derefn}
  184. secondaddr, {addrn}
  185. seconddoubleaddr, {doubleaddrn}
  186. secondordconst, {ordconstn}
  187. secondtypeconv, {typeconvn}
  188. secondcalln, {calln}
  189. secondnothing, {callparan}
  190. secondrealconst, {realconstn}
  191. secondfixconst, {fixconstn}
  192. secondumminus, {umminusn}
  193. secondasm, {asmn}
  194. secondvecn, {vecn}
  195. secondstringconst, {stringconstn}
  196. secondfuncret, {funcretn}
  197. secondselfn, {selfn}
  198. secondnot, {notn}
  199. secondinline, {inlinen}
  200. secondniln, {niln}
  201. seconderror, {errorn}
  202. secondnothing, {typen}
  203. secondhnewn, {hnewn}
  204. secondhdisposen, {hdisposen}
  205. secondnewn, {newn}
  206. secondsimplenewdispose, {simpledisposen}
  207. secondsetelement, {setelementn}
  208. secondsetconst, {setconstn}
  209. secondblockn, {blockn}
  210. secondstatement, {statementn}
  211. secondnothing, {loopn}
  212. secondifn, {ifn}
  213. secondbreakn, {breakn}
  214. secondcontinuen, {continuen}
  215. second_while_repeatn, {repeatn}
  216. second_while_repeatn, {whilen}
  217. secondfor, {forn}
  218. secondexitn, {exitn}
  219. secondwith, {withn}
  220. secondcase, {casen}
  221. secondlabel, {labeln}
  222. secondgoto, {goton}
  223. secondsimplenewdispose, {simplenewn}
  224. secondtryexcept, {tryexceptn}
  225. secondraise, {raisen}
  226. secondnothing, {switchesn}
  227. secondtryfinally, {tryfinallyn}
  228. secondon, {onn}
  229. secondis, {isn}
  230. secondas, {asn}
  231. seconderror, {caretn}
  232. secondfail, {failn}
  233. secondadd, {starstarn}
  234. secondprocinline, {procinlinen}
  235. secondarrayconstruct, {arrayconstructn}
  236. secondnothing, {arrayconstructrangen}
  237. secondnothing, {nothingn}
  238. secondloadvmt {loadvmtn}
  239. );
  240. var
  241. oldcodegenerror : boolean;
  242. oldlocalswitches : tlocalswitches;
  243. oldpos : tfileposinfo;
  244. begin
  245. if not(p^.error) then
  246. begin
  247. oldcodegenerror:=codegenerror;
  248. oldlocalswitches:=aktlocalswitches;
  249. oldpos:=aktfilepos;
  250. aktfilepos:=p^.fileinfo;
  251. aktlocalswitches:=p^.localswitches;
  252. codegenerror:=false;
  253. procedures[p^.treetype](p);
  254. p^.error:=codegenerror;
  255. codegenerror:=codegenerror or oldcodegenerror;
  256. aktlocalswitches:=oldlocalswitches;
  257. aktfilepos:=oldpos;
  258. end
  259. else
  260. codegenerror:=true;
  261. end;
  262. function do_secondpass(var p : ptree) : boolean;
  263. begin
  264. codegenerror:=false;
  265. if not(p^.error) then
  266. secondpass(p);
  267. do_secondpass:=codegenerror;
  268. end;
  269. var
  270. regvars : array[1..maxvarregs] of pvarsym;
  271. regvars_para : array[1..maxvarregs] of boolean;
  272. regvars_refs : array[1..maxvarregs] of longint;
  273. parasym : boolean;
  274. procedure searchregvars(p : pnamedindexobject);
  275. var
  276. i,j,k : longint;
  277. begin
  278. if (psym(p)^.typ=varsym) and ((pvarsym(p)^.var_options and vo_regable)<>0) then
  279. begin
  280. { walk through all momentary register variables }
  281. for i:=1 to maxvarregs do
  282. begin
  283. { free register ? }
  284. if regvars[i]=nil then
  285. begin
  286. regvars[i]:=pvarsym(p);
  287. regvars_para[i]:=parasym;
  288. break;
  289. end;
  290. { else throw out a variable ? }
  291. j:=pvarsym(p)^.refs;
  292. { parameter get a less value }
  293. if parasym then
  294. begin
  295. if cs_littlesize in aktglobalswitches then
  296. dec(j,1)
  297. else
  298. dec(j,100);
  299. end;
  300. if (j>regvars_refs[i]) and (j>0) then
  301. begin
  302. for k:=maxvarregs-1 downto i do
  303. begin
  304. regvars[k+1]:=regvars[k];
  305. regvars_para[k+1]:=regvars_para[k];
  306. end;
  307. { calc the new refs
  308. pvarsym(p)^.refs:=j; }
  309. regvars[i]:=pvarsym(p);
  310. regvars_para[i]:=parasym;
  311. regvars_refs[i]:=j;
  312. break;
  313. end;
  314. end;
  315. end;
  316. end;
  317. procedure generatecode(var p : ptree);
  318. var
  319. i : longint;
  320. regsize : topsize;
  321. hr : preference;
  322. label
  323. nextreg;
  324. begin
  325. temptoremove:=nil;
  326. cleartempgen;
  327. { when size optimization only count occurrence }
  328. if cs_littlesize in aktglobalswitches then
  329. t_times:=1
  330. else
  331. { reference for repetition is 100 }
  332. t_times:=100;
  333. { clear register count }
  334. clearregistercount;
  335. use_esp_stackframe:=false;
  336. if not(do_firstpass(p)) then
  337. begin
  338. { max. optimizations }
  339. { only if no asm is used }
  340. { and no try statement }
  341. if (cs_regalloc in aktglobalswitches) and
  342. ((procinfo.flags and (pi_uses_asm or pi_uses_exceptions))=0) then
  343. begin
  344. { can we omit the stack frame ? }
  345. { conditions:
  346. 1. procedure (not main block)
  347. 2. no constructor or destructor
  348. 3. no call to other procedures
  349. 4. no interrupt handler
  350. }
  351. if assigned(aktprocsym) then
  352. begin
  353. if (aktprocsym^.definition^.options and
  354. (poconstructor+podestructor{+poinline}+pointerrupt)=0) and
  355. ((procinfo.flags and pi_do_call)=0) and
  356. (lexlevel>=normal_function_level) then
  357. begin
  358. { use ESP as frame pointer }
  359. procinfo.framepointer:=stack_pointer;
  360. use_esp_stackframe:=true;
  361. { calc parameter distance new }
  362. dec(procinfo.framepointer_offset,4);
  363. dec(procinfo.ESI_offset,4);
  364. { is this correct ???}
  365. { retoffset can be negativ for results in eax !! }
  366. { the value should be decreased only if positive }
  367. if procinfo.retoffset>=0 then
  368. dec(procinfo.retoffset,4);
  369. dec(procinfo.call_offset,4);
  370. aktprocsym^.definition^.parast^.address_fixup:=procinfo.call_offset;
  371. end;
  372. end;
  373. if (p^.registers32<4) then
  374. begin
  375. for i:=1 to maxvarregs do
  376. regvars[i]:=nil;
  377. parasym:=false;
  378. {$ifdef tp}
  379. symtablestack^.foreach(searchregvars);
  380. {$else}
  381. symtablestack^.foreach(@searchregvars);
  382. {$endif}
  383. { copy parameter into a register ? }
  384. parasym:=true;
  385. {$ifdef tp}
  386. symtablestack^.next^.foreach(searchregvars);
  387. {$else}
  388. symtablestack^.next^.foreach(@searchregvars);
  389. {$endif}
  390. { hold needed registers free }
  391. for i:=maxvarregs downto maxvarregs-p^.registers32+1 do
  392. regvars[i]:=nil;
  393. { now assign register }
  394. for i:=1 to maxvarregs-p^.registers32 do
  395. begin
  396. if assigned(regvars[i]) then
  397. begin
  398. { it is nonsens, to copy the variable to }
  399. { a register because we need then much }
  400. { too pushes ? }
  401. if reg_pushes[varregs[i]]>=regvars[i]^.refs then
  402. begin
  403. regvars[i]:=nil;
  404. goto nextreg;
  405. end;
  406. { register is no longer available for }
  407. { expressions }
  408. { search the register which is the most }
  409. { unused }
  410. usableregs:=usableregs-[varregs[i]];
  411. is_reg_var[varregs[i]]:=true;
  412. dec(c_usableregs);
  413. { possibly no 32 bit register are needed }
  414. { call by reference/const ? }
  415. if (regvars[i]^.varspez=vs_var) or
  416. ((regvars[i]^.varspez=vs_const) and
  417. push_addr_param(regvars[i]^.definition)) then
  418. begin
  419. regvars[i]^.reg:=varregs[i];
  420. regsize:=S_L;
  421. end
  422. else
  423. if (regvars[i]^.definition^.deftype=orddef) and
  424. (porddef(regvars[i]^.definition)^.size=1) then
  425. begin
  426. {$ifdef i386}
  427. regvars[i]^.reg:=reg32toreg8(varregs[i]);
  428. {$endif}
  429. regsize:=S_B;
  430. end
  431. else
  432. if (regvars[i]^.definition^.deftype=orddef) and
  433. (porddef(regvars[i]^.definition)^.size=2) then
  434. begin
  435. {$ifdef i386}
  436. regvars[i]^.reg:=reg32toreg16(varregs[i]);
  437. {$endif}
  438. regsize:=S_W;
  439. end
  440. else
  441. begin
  442. regvars[i]^.reg:=varregs[i];
  443. regsize:=S_L;
  444. end;
  445. { parameter must be load }
  446. if regvars_para[i] then
  447. begin
  448. { procinfo is there actual, }
  449. { because we can't never be in a }
  450. { nested procedure }
  451. { when loading parameter to reg }
  452. new(hr);
  453. reset_reference(hr^);
  454. hr^.offset:=pvarsym(regvars[i])^.address+procinfo.call_offset;
  455. hr^.base:=procinfo.framepointer;
  456. {$ifdef i386}
  457. procinfo.aktentrycode^.concat(new(pai386,op_ref_reg(A_MOV,regsize,
  458. hr,regvars[i]^.reg)));
  459. {$endif i386}
  460. {$ifdef m68k}
  461. procinfo.aktentrycode^.concat(new(pai68k,op_ref_reg(A_MOVE,regsize,
  462. hr,regvars[i]^.reg)));
  463. {$endif m68k}
  464. unused:=unused - [regvars[i]^.reg];
  465. end;
  466. { procedure uses this register }
  467. {$ifdef i386}
  468. usedinproc:=usedinproc or ($80 shr byte(varregs[i]));
  469. {$endif i386}
  470. {$ifdef m68k}
  471. usedinproc:=usedinproc or ($800 shr word(varregs[i]));
  472. {$endif m68k}
  473. end;
  474. nextreg:
  475. { dummy }
  476. regsize:=S_W;
  477. end;
  478. if (status.verbosity and v_debug)=v_debug then
  479. begin
  480. for i:=1 to maxvarregs do
  481. begin
  482. if assigned(regvars[i]) then
  483. Message3(cg_d_register_weight,reg2str(regvars[i]^.reg),
  484. tostr(regvars[i]^.refs),regvars[i]^.name);
  485. end;
  486. end;
  487. end;
  488. end;
  489. if assigned(aktprocsym) and
  490. ((aktprocsym^.definition^.options and poinline)<>0) then
  491. make_const_global:=true;
  492. do_secondpass(p);
  493. if assigned(procinfo.def) then
  494. procinfo.def^.fpu_used:=p^.registersfpu;
  495. { all registers can be used again }
  496. resetusableregisters;
  497. end;
  498. procinfo.aktproccode^.concatlist(exprasmlist);
  499. make_const_global:=false;
  500. end;
  501. end.
  502. {
  503. $Log$
  504. Revision 1.18 1999-04-28 06:02:04 florian
  505. * changes of Bruessel:
  506. + message handler can now take an explicit self
  507. * typinfo fixed: sometimes the type names weren't written
  508. * the type checking for pointer comparisations and subtraction
  509. and are now more strict (was also buggy)
  510. * small bug fix to link.pas to support compiling on another
  511. drive
  512. * probable bug in popt386 fixed: call/jmp => push/jmp
  513. transformation didn't count correctly the jmp references
  514. + threadvar support
  515. * warning if ln/sqrt gets an invalid constant argument
  516. Revision 1.17 1999/03/31 13:55:11 peter
  517. * assembler inlining working for ag386bin
  518. Revision 1.16 1999/03/24 23:17:11 peter
  519. * fixed bugs 212,222,225,227,229,231,233
  520. Revision 1.15 1999/02/22 02:15:25 peter
  521. * updates for ag386bin
  522. Revision 1.14 1999/01/23 23:29:37 florian
  523. * first running version of the new code generator
  524. * when compiling exceptions under Linux fixed
  525. Revision 1.13 1998/12/30 13:41:09 peter
  526. * released valuepara
  527. Revision 1.12 1998/12/19 00:23:51 florian
  528. * ansistring memory leaks fixed
  529. Revision 1.11 1998/12/11 00:03:28 peter
  530. + globtype,tokens,version unit splitted from globals
  531. Revision 1.10 1998/11/18 15:44:14 peter
  532. * VALUEPARA for tp7 compatible value parameters
  533. Revision 1.9 1998/11/13 15:40:21 pierre
  534. + added -Se in Makefile cvstest target
  535. + lexlevel cleanup
  536. normal_function_level main_program_level and unit_init_level defined
  537. * tins_cache grown to A_EMMS (gave range check error in asm readers)
  538. (test added in code !)
  539. * -Un option was wrong
  540. * _FAIL and _SELF only keyword inside
  541. constructors and methods respectively
  542. Revision 1.8 1998/10/29 15:42:49 florian
  543. + partial disposing of temp. ansistrings
  544. Revision 1.7 1998/10/26 22:58:19 florian
  545. * new introduded problem with classes fix, the parent class wasn't set
  546. correct, if the class was defined forward before
  547. Revision 1.6 1998/09/23 09:58:52 peter
  548. * first working array of const things
  549. Revision 1.5 1998/09/21 10:01:06 peter
  550. * check if procinfo.def is assigned before storing registersfpu
  551. Revision 1.4 1998/09/21 08:45:16 pierre
  552. + added vmt_offset in tobjectdef.write for fututre use
  553. (first steps to have objects without vmt if no virtual !!)
  554. + added fpu_used field for tabstractprocdef :
  555. sets this level to 2 if the functions return with value in FPU
  556. (is then set to correct value at parsing of implementation)
  557. THIS MIGHT refuse some code with FPU expression too complex
  558. that were accepted before and even in some cases
  559. that don't overflow in fact
  560. ( like if f : float; is a forward that finally in implementation
  561. only uses one fpu register !!)
  562. Nevertheless I think that it will improve security on
  563. FPU operations !!
  564. * most other changes only for UseBrowser code
  565. (added symtable references for record and objects)
  566. local switch for refs to args and local of each function
  567. (static symtable still missing)
  568. UseBrowser still not stable and probably broken by
  569. the definition hash array !!
  570. Revision 1.3 1998/09/17 09:42:40 peter
  571. + pass_2 for cg386
  572. * Message() -> CGMessage() for pass_1/pass_2
  573. Revision 1.2 1998/09/07 18:46:07 peter
  574. * update smartlinking, uses getdatalabel
  575. * renamed ptree.value vars to value_str,value_real,value_set
  576. Revision 1.1 1998/09/01 09:07:12 peter
  577. * m68k fixes, splitted cg68k like cgi386
  578. }