pass_2.pas 21 KB

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