pass_2.pas 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  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. cobjects,verbose,comphook,systems,globals,files,
  34. symtable,types,aasm,scanner,
  35. pass_1,hcodegen,temp_gen
  36. {$ifdef GDB}
  37. ,gdb
  38. {$endif}
  39. {$ifdef i386}
  40. ,i386,tgeni386,cgai386
  41. ,cg386con,cg386mat,cg386cnv,cg386set,cg386add
  42. ,cg386mem,cg386cal,cg386ld,cg386flw,cg386inl
  43. {$endif}
  44. {$ifdef m68k}
  45. ,m68k,tgen68k,cga68k
  46. ,cg68kcon,cg68kmat,cg68kcnv,cg68kset,cg68kadd
  47. ,cg68kmem,cg68kcal,cg68kld,cg68kflw,cg68kinl
  48. {$endif}
  49. ;
  50. {*****************************************************************************
  51. SecondPass
  52. *****************************************************************************}
  53. type
  54. secondpassproc = procedure(var p : ptree);
  55. procedure secondnothing(var p : ptree);
  56. begin
  57. end;
  58. procedure seconderror(var p : ptree);
  59. begin
  60. p^.error:=true;
  61. codegenerror:=true;
  62. end;
  63. procedure secondstatement(var p : ptree);
  64. var
  65. hp : ptree;
  66. begin
  67. hp:=p;
  68. while assigned(hp) do
  69. begin
  70. if assigned(hp^.right) then
  71. begin
  72. cleartempgen;
  73. secondpass(hp^.right);
  74. end;
  75. hp:=hp^.left;
  76. end;
  77. end;
  78. procedure secondblockn(var p : ptree);
  79. begin
  80. { do second pass on left node }
  81. if assigned(p^.left) then
  82. secondpass(p^.left);
  83. end;
  84. procedure secondasm(var p : ptree);
  85. begin
  86. exprasmlist^.concatlist(p^.p_asm);
  87. if not p^.object_preserved then
  88. begin
  89. {$ifdef i386}
  90. maybe_loadesi;
  91. {$endif}
  92. {$ifdef m68k}
  93. maybe_loada5;
  94. {$endif}
  95. end;
  96. end;
  97. procedure secondpass(var p : ptree);
  98. const
  99. procedures : array[ttreetyp] of secondpassproc =
  100. (secondadd, {addn}
  101. secondadd, {muln}
  102. secondadd, {subn}
  103. secondmoddiv, {divn}
  104. secondadd, {symdifn}
  105. secondmoddiv, {modn}
  106. secondassignment, {assignn}
  107. secondload, {loadn}
  108. secondnothing, {range}
  109. secondadd, {ltn}
  110. secondadd, {lten}
  111. secondadd, {gtn}
  112. secondadd, {gten}
  113. secondadd, {equaln}
  114. secondadd, {unequaln}
  115. secondin, {inn}
  116. secondadd, {orn}
  117. secondadd, {xorn}
  118. secondshlshr, {shrn}
  119. secondshlshr, {shln}
  120. secondadd, {slashn}
  121. secondadd, {andn}
  122. secondsubscriptn, {subscriptn}
  123. secondderef, {derefn}
  124. secondaddr, {addrn}
  125. seconddoubleaddr, {doubleaddrn}
  126. secondordconst, {ordconstn}
  127. secondtypeconv, {typeconvn}
  128. secondcalln, {calln}
  129. secondnothing, {callparan}
  130. secondrealconst, {realconstn}
  131. secondfixconst, {fixconstn}
  132. secondumminus, {umminusn}
  133. secondasm, {asmn}
  134. secondvecn, {vecn}
  135. secondstringconst, {stringconstn}
  136. secondfuncret, {funcretn}
  137. secondselfn, {selfn}
  138. secondnot, {notn}
  139. secondinline, {inlinen}
  140. secondniln, {niln}
  141. seconderror, {errorn}
  142. secondnothing, {typen}
  143. secondhnewn, {hnewn}
  144. secondhdisposen, {hdisposen}
  145. secondnewn, {newn}
  146. secondsimplenewdispose, {simpledisposen}
  147. secondsetelement, {setelementn}
  148. secondsetconst, {setconstn}
  149. secondblockn, {blockn}
  150. secondstatement, {statementn}
  151. secondnothing, {loopn}
  152. secondifn, {ifn}
  153. secondbreakn, {breakn}
  154. secondcontinuen, {continuen}
  155. second_while_repeatn, {repeatn}
  156. second_while_repeatn, {whilen}
  157. secondfor, {forn}
  158. secondexitn, {exitn}
  159. secondwith, {withn}
  160. secondcase, {casen}
  161. secondlabel, {labeln}
  162. secondgoto, {goton}
  163. secondsimplenewdispose, {simplenewn}
  164. secondtryexcept, {tryexceptn}
  165. secondraise, {raisen}
  166. secondnothing, {switchesn}
  167. secondtryfinally, {tryfinallyn}
  168. secondon, {onn}
  169. secondis, {isn}
  170. secondas, {asn}
  171. seconderror, {caretn}
  172. secondfail, {failn}
  173. secondadd, {starstarn}
  174. secondprocinline, {procinlinen}
  175. secondarrayconstruct, {arrayconstructn}
  176. secondnothing, {arrayconstructrangen}
  177. secondnothing, {nothingn}
  178. secondloadvmt {loadvmtn}
  179. );
  180. var
  181. oldcodegenerror : boolean;
  182. oldlocalswitches : tlocalswitches;
  183. oldpos : tfileposinfo;
  184. begin
  185. if not(p^.error) then
  186. begin
  187. oldcodegenerror:=codegenerror;
  188. oldlocalswitches:=aktlocalswitches;
  189. oldpos:=aktfilepos;
  190. aktfilepos:=p^.fileinfo;
  191. aktlocalswitches:=p^.localswitches;
  192. codegenerror:=false;
  193. procedures[p^.treetype](p);
  194. p^.error:=codegenerror;
  195. codegenerror:=codegenerror or oldcodegenerror;
  196. aktlocalswitches:=oldlocalswitches;
  197. aktfilepos:=oldpos;
  198. end
  199. else
  200. codegenerror:=true;
  201. end;
  202. function do_secondpass(var p : ptree) : boolean;
  203. begin
  204. codegenerror:=false;
  205. if not(p^.error) then
  206. secondpass(p);
  207. do_secondpass:=codegenerror;
  208. end;
  209. var
  210. regvars : array[1..maxvarregs] of pvarsym;
  211. regvars_para : array[1..maxvarregs] of boolean;
  212. regvars_refs : array[1..maxvarregs] of longint;
  213. parasym : boolean;
  214. procedure searchregvars(p : psym);
  215. var
  216. i,j,k : longint;
  217. begin
  218. if (p^.typ=varsym) and ((pvarsym(p)^.var_options and vo_regable)<>0) then
  219. begin
  220. { walk through all momentary register variables }
  221. for i:=1 to maxvarregs do
  222. begin
  223. { free register ? }
  224. if regvars[i]=nil then
  225. begin
  226. regvars[i]:=pvarsym(p);
  227. regvars_para[i]:=parasym;
  228. break;
  229. end;
  230. { else throw out a variable ? }
  231. j:=pvarsym(p)^.refs;
  232. { parameter get a less value }
  233. if parasym then
  234. begin
  235. if cs_littlesize in aktglobalswitches then
  236. dec(j,1)
  237. else
  238. dec(j,100);
  239. end;
  240. if (j>regvars_refs[i]) and (j>0) then
  241. begin
  242. for k:=maxvarregs-1 downto i do
  243. begin
  244. regvars[k+1]:=regvars[k];
  245. regvars_para[k+1]:=regvars_para[k];
  246. end;
  247. { calc the new refs
  248. pvarsym(p)^.refs:=j; }
  249. regvars[i]:=pvarsym(p);
  250. regvars_para[i]:=parasym;
  251. regvars_refs[i]:=j;
  252. break;
  253. end;
  254. end;
  255. end;
  256. end;
  257. procedure generatecode(var p : ptree);
  258. var
  259. i : longint;
  260. regsize : topsize;
  261. hr : preference;
  262. label
  263. nextreg;
  264. begin
  265. cleartempgen;
  266. { when size optimization only count occurrence }
  267. if cs_littlesize in aktglobalswitches then
  268. t_times:=1
  269. else
  270. { reference for repetition is 100 }
  271. t_times:=100;
  272. { clear register count }
  273. clearregistercount;
  274. use_esp_stackframe:=false;
  275. if not(do_firstpass(p)) then
  276. begin
  277. { max. optimizations }
  278. { only if no asm is used }
  279. { and no try statement }
  280. if (cs_regalloc in aktglobalswitches) and
  281. ((procinfo.flags and (pi_uses_asm or pi_uses_exceptions))=0) then
  282. begin
  283. { can we omit the stack frame ? }
  284. { conditions:
  285. 1. procedure (not main block)
  286. 2. no constructor or destructor
  287. 3. no call to other procedures
  288. 4. no interrupt handler
  289. }
  290. if assigned(aktprocsym) then
  291. begin
  292. if (aktprocsym^.definition^.options and
  293. (poconstructor+podestructor{+poinline}+pointerrupt)=0) and
  294. ((procinfo.flags and pi_do_call)=0) and (lexlevel>1) then
  295. begin
  296. { use ESP as frame pointer }
  297. procinfo.framepointer:=stack_pointer;
  298. use_esp_stackframe:=true;
  299. { calc parameter distance new }
  300. dec(procinfo.framepointer_offset,4);
  301. dec(procinfo.ESI_offset,4);
  302. { is this correct ???}
  303. { retoffset can be negativ for results in eax !! }
  304. { the value should be decreased only if positive }
  305. if procinfo.retoffset>=0 then
  306. dec(procinfo.retoffset,4);
  307. dec(procinfo.call_offset,4);
  308. aktprocsym^.definition^.parast^.call_offset:=procinfo.call_offset;
  309. end;
  310. end;
  311. if (p^.registers32<4) then
  312. begin
  313. for i:=1 to maxvarregs do
  314. regvars[i]:=nil;
  315. parasym:=false;
  316. {$ifdef tp}
  317. symtablestack^.foreach(searchregvars);
  318. {$else}
  319. symtablestack^.foreach(@searchregvars);
  320. {$endif}
  321. { copy parameter into a register ? }
  322. parasym:=true;
  323. {$ifdef tp}
  324. symtablestack^.next^.foreach(searchregvars);
  325. {$else}
  326. symtablestack^.next^.foreach(@searchregvars);
  327. {$endif}
  328. { hold needed registers free }
  329. for i:=maxvarregs downto maxvarregs-p^.registers32+1 do
  330. regvars[i]:=nil;
  331. { now assign register }
  332. for i:=1 to maxvarregs-p^.registers32 do
  333. begin
  334. if assigned(regvars[i]) then
  335. begin
  336. { it is nonsens, to copy the variable to }
  337. { a register because we need then much }
  338. { pushes ? }
  339. if reg_pushes[varregs[i]]>=regvars[i]^.refs then
  340. begin
  341. regvars[i]:=nil;
  342. goto nextreg;
  343. end;
  344. { register is no longer available for }
  345. { expressions }
  346. { search the register which is the most }
  347. { unused }
  348. usableregs:=usableregs-[varregs[i]];
  349. is_reg_var[varregs[i]]:=true;
  350. dec(c_usableregs);
  351. { possibly no 32 bit register are needed }
  352. { call by reference/const ? }
  353. if (regvars[i]^.varspez=vs_var) or
  354. ((regvars[i]^.varspez=vs_const) and
  355. dont_copy_const_param(regvars[i]^.definition)) then
  356. begin
  357. regvars[i]^.reg:=varregs[i];
  358. regsize:=S_L;
  359. end
  360. else
  361. if (regvars[i]^.definition^.deftype=orddef) and
  362. (porddef(regvars[i]^.definition)^.typ in [bool8bit,uchar,u8bit,s8bit]) then
  363. begin
  364. {$ifdef i386}
  365. regvars[i]^.reg:=reg32toreg8(varregs[i]);
  366. {$endif}
  367. regsize:=S_B;
  368. end
  369. else if (regvars[i]^.definition^.deftype=orddef) and
  370. (porddef(regvars[i]^.definition)^.typ in [bool16bit,u16bit,s16bit]) then
  371. begin
  372. {$ifdef i386}
  373. regvars[i]^.reg:=reg32toreg16(varregs[i]);
  374. {$endif}
  375. regsize:=S_W;
  376. end
  377. else
  378. begin
  379. regvars[i]^.reg:=varregs[i];
  380. regsize:=S_L;
  381. end;
  382. { parameter must be load }
  383. if regvars_para[i] then
  384. begin
  385. { procinfo is there actual, }
  386. { because we can't never be in a }
  387. { nested procedure }
  388. { when loading parameter to reg }
  389. new(hr);
  390. reset_reference(hr^);
  391. hr^.offset:=pvarsym(regvars[i])^.address+procinfo.call_offset;
  392. hr^.base:=procinfo.framepointer;
  393. {$ifdef i386}
  394. procinfo.aktentrycode^.concat(new(pai386,op_ref_reg(A_MOV,regsize,
  395. hr,regvars[i]^.reg)));
  396. {$endif i386}
  397. {$ifdef m68k}
  398. procinfo.aktentrycode^.concat(new(pai68k,op_ref_reg(A_MOVE,regsize,
  399. hr,regvars[i]^.reg)));
  400. {$endif m68k}
  401. unused:=unused - [regvars[i]^.reg];
  402. end;
  403. { procedure uses this register }
  404. {$ifdef i386}
  405. usedinproc:=usedinproc or ($80 shr byte(varregs[i]));
  406. {$endif i386}
  407. {$ifdef m68k}
  408. usedinproc:=usedinproc or ($800 shr word(varregs[i]));
  409. {$endif m68k}
  410. end;
  411. nextreg:
  412. { dummy }
  413. regsize:=S_W;
  414. end;
  415. if (status.verbosity and v_debug)=v_debug then
  416. begin
  417. for i:=1 to maxvarregs do
  418. begin
  419. if assigned(regvars[i]) then
  420. Message3(cg_d_register_weight,reg2str(regvars[i]^.reg),
  421. tostr(regvars[i]^.refs),regvars[i]^.name);
  422. end;
  423. end;
  424. end;
  425. end;
  426. if assigned(aktprocsym) and
  427. ((aktprocsym^.definition^.options and poinline)<>0) then
  428. make_const_global:=true;
  429. do_secondpass(p);
  430. if assigned(procinfo.def) then
  431. procinfo.def^.fpu_used:=p^.registersfpu;
  432. { all registers can be used again }
  433. resetusableregisters;
  434. end;
  435. procinfo.aktproccode^.concatlist(exprasmlist);
  436. make_const_global:=false;
  437. end;
  438. end.
  439. {
  440. $Log$
  441. Revision 1.6 1998-09-23 09:58:52 peter
  442. * first working array of const things
  443. Revision 1.5 1998/09/21 10:01:06 peter
  444. * check if procinfo.def is assigned before storing registersfpu
  445. Revision 1.4 1998/09/21 08:45:16 pierre
  446. + added vmt_offset in tobjectdef.write for fututre use
  447. (first steps to have objects without vmt if no virtual !!)
  448. + added fpu_used field for tabstractprocdef :
  449. sets this level to 2 if the functions return with value in FPU
  450. (is then set to correct value at parsing of implementation)
  451. THIS MIGHT refuse some code with FPU expression too complex
  452. that were accepted before and even in some cases
  453. that don't overflow in fact
  454. ( like if f : float; is a forward that finally in implementation
  455. only uses one fpu register !!)
  456. Nevertheless I think that it will improve security on
  457. FPU operations !!
  458. * most other changes only for UseBrowser code
  459. (added symtable references for record and objects)
  460. local switch for refs to args and local of each function
  461. (static symtable still missing)
  462. UseBrowser still not stable and probably broken by
  463. the definition hash array !!
  464. Revision 1.3 1998/09/17 09:42:40 peter
  465. + pass_2 for cg386
  466. * Message() -> CGMessage() for pass_1/pass_2
  467. Revision 1.2 1998/09/07 18:46:07 peter
  468. * update smartlinking, uses getdatalabel
  469. * renamed ptree.value vars to value_str,value_real,value_set
  470. Revision 1.1 1998/09/01 09:07:12 peter
  471. * m68k fixes, splitted cg68k like cgi386
  472. }