pass_2.pas 24 KB

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