regvars.pas 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl and Jonas Maebe
  4. This unit handles register variable allocation
  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 regvars;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. aasmbase,aasmtai,aasmcpu,
  23. node,
  24. symsym,
  25. cpubase, cgbase, tgobj;
  26. {$ifdef OLDREGVARS}
  27. procedure assign_regvars(p: tnode);
  28. procedure load_regvars(asml: TAAsmoutput; p: tnode);
  29. procedure cleanup_regvars(asml: TAAsmoutput);
  30. procedure store_regvar(asml: TAAsmoutput; reg: tregister);
  31. procedure load_regvar(asml: TAAsmoutput; vsym: tvarsym);
  32. procedure load_regvar_reg(asml: TAAsmoutput; reg: tregister);
  33. procedure load_all_regvars(asml: TAAsmoutput);
  34. procedure free_regvars(list: taasmoutput);
  35. procedure translate_regvars(list: taasmoutput; const table:Ttranstable);
  36. {$endif OLDREGVARS}
  37. {$ifdef i386}
  38. (*
  39. procedure sync_regvars_other(list1, list2: taasmoutput; const regvarsloaded1,
  40. regvarsloaded2: regvarother_booleanarray);
  41. procedure sync_regvars_int(list1, list2: taasmoutput; const regvarsloaded1,
  42. regvarsloaded2: Tsuperregisterset);
  43. *)
  44. {$endif i386}
  45. implementation
  46. uses
  47. globtype,systems,comphook,
  48. cutils,cclasses,verbose,globals,
  49. psub,
  50. symconst,symbase,symtype,symdef,paramgr,defutil,
  51. cpuinfo,cgobj,procinfo;
  52. {$ifdef OLDREGVARS}
  53. procedure searchregvars(p : tnamedindexitem;arg:pointer);
  54. var
  55. i,j,k : longint;
  56. parasym : boolean;
  57. begin
  58. parasym:=pboolean(arg)^;
  59. if (tsym(p).typ=varsym) and (vo_regable in tvarsym(p).varoptions) then
  60. begin
  61. j:=tvarsym(p).refs;
  62. { parameter get a less value }
  63. if parasym then
  64. begin
  65. if cs_littlesize in aktglobalswitches then
  66. dec(j,1)
  67. else
  68. dec(j,100);
  69. end;
  70. { walk through all momentary register variables }
  71. for i:=1 to maxvarregs do
  72. begin
  73. with pregvarinfo(current_procinfo.procdef.regvarinfo)^ do
  74. if ((regvars[i]=nil) or (j>regvars_refs[i])) and (j>0) then
  75. begin
  76. for k:=maxvarregs-1 downto i do
  77. begin
  78. regvars[k+1]:=regvars[k];
  79. regvars_para[k+1]:=regvars_para[k];
  80. regvars_refs[k+1]:=regvars_refs[k];
  81. end;
  82. { calc the new refs
  83. tvarsym(p).refs:=j; }
  84. regvars[i]:=tvarsym(p);
  85. regvars_para[i]:=parasym;
  86. regvars_refs[i]:=j;
  87. break;
  88. end;
  89. end;
  90. end;
  91. end;
  92. procedure searchfpuregvars(p : tnamedindexitem;arg:pointer);
  93. var
  94. i,j,k : longint;
  95. parasym : boolean;
  96. begin
  97. parasym:=pboolean(arg)^;
  98. if (tsym(p).typ=varsym) and (vo_fpuregable in tvarsym(p).varoptions) then
  99. begin
  100. j:=tvarsym(p).refs;
  101. { parameter get a less value }
  102. if parasym then
  103. begin
  104. if cs_littlesize in aktglobalswitches then
  105. dec(j,1)
  106. else
  107. dec(j,100);
  108. end;
  109. { walk through all momentary register variables }
  110. for i:=1 to maxfpuvarregs do
  111. begin
  112. with pregvarinfo(current_procinfo.procdef.regvarinfo)^ do
  113. if ((fpuregvars[i]=nil) or (j>fpuregvars_refs[i])) and (j>0) then
  114. begin
  115. for k:=maxfpuvarregs-1 downto i do
  116. begin
  117. fpuregvars[k+1]:=fpuregvars[k];
  118. fpuregvars_para[k+1]:=fpuregvars_para[k];
  119. fpuregvars_refs[k+1]:=fpuregvars_refs[k];
  120. end;
  121. { calc the new refs
  122. tvarsym(p).refs:=j; }
  123. fpuregvars[i]:=tvarsym(p);
  124. fpuregvars_para[i]:=parasym;
  125. fpuregvars_refs[i]:=j;
  126. break;
  127. end;
  128. end;
  129. end;
  130. end;
  131. procedure assign_regvars(p: tnode);
  132. { register variables }
  133. var
  134. {$ifndef i386}
  135. hp: tparaitem;
  136. {$endif i386}
  137. regvarinfo: pregvarinfo;
  138. i: longint;
  139. parasym : boolean;
  140. siz : tcgsize;
  141. begin
  142. { max. optimizations }
  143. { only if no asm is used }
  144. { and no try statement }
  145. if (cs_regvars in aktglobalswitches) and
  146. {$ifndef i386}
  147. { we have to store regvars back to memory in this case! }
  148. (tcgprocinfo(current_procinfo).nestedprocs.count = 0) and
  149. {$endif i386}
  150. not(pi_uses_asm in current_procinfo.flags) and
  151. not(pi_uses_exceptions in current_procinfo.flags) then
  152. begin
  153. new(regvarinfo);
  154. fillchar(regvarinfo^,sizeof(regvarinfo^),0);
  155. current_procinfo.procdef.regvarinfo := regvarinfo;
  156. if (p.registers32<maxvarregs) then
  157. begin
  158. parasym:=false;
  159. symtablestack.foreach_static({$ifdef FPCPROCVAR}@{$endif}searchregvars,@parasym);
  160. { copy parameter into a register ? }
  161. parasym:=true;
  162. symtablestack.next.foreach_static({$ifdef FPCPROCVAR}@{$endif}searchregvars,@parasym);
  163. { hold needed registers free }
  164. for i:=maxvarregs downto maxvarregs-p.registers32+1-maxintscratchregs do
  165. begin
  166. regvarinfo^.regvars[i]:=nil;
  167. regvarinfo^.regvars_para[i] := false;
  168. end;
  169. { now assign register }
  170. for i:=1 to maxvarregs-p.registers32-maxintscratchregs do
  171. begin
  172. if assigned(regvarinfo^.regvars[i]) and
  173. { currently we assume we can use volatile registers for all }
  174. { regvars if procedure does no call }
  175. (not(pi_do_call in current_procinfo.flags) or
  176. { otherwise, demand some (arbitrary) minimum usage }
  177. (regvarinfo^.regvars[i].refs > 100)) then
  178. begin
  179. { register is no longer available for }
  180. { expressions }
  181. { search the register which is the most }
  182. { unused }
  183. { call by reference/const ? }
  184. if paramanager.push_addr_param(regvarinfo^.regvars[i].varspez,regvarinfo^.regvars[i].vartype.def,current_procinfo.procdef.proccalloption) then
  185. siz:=OS_32
  186. else
  187. if (regvarinfo^.regvars[i].vartype.def.deftype in [orddef,enumdef]) and
  188. (regvarinfo^.regvars[i].vartype.def.size=1) then
  189. siz:=OS_8
  190. else
  191. if (regvarinfo^.regvars[i].vartype.def.deftype in [orddef,enumdef]) and
  192. (regvarinfo^.regvars[i].vartype.def.size=2) then
  193. siz:=OS_16
  194. else
  195. siz:=OS_32;
  196. {$warning fixme regvars}
  197. { allocate a register for this regvar }
  198. { regvarinfo^.regvars[i].localloc.register:=rg.getregisterint(exprasmlist,siz);}
  199. { and make sure it can't be freed }
  200. { rg.makeregvarint(getsupreg(regvarinfo^.regvars[i].localloc.register));}
  201. end
  202. else
  203. begin
  204. regvarinfo^.regvars[i] := nil;
  205. regvarinfo^.regvars_para[i] := false;
  206. end;
  207. end;
  208. end;
  209. if ((p.registersfpu+1)<maxfpuvarregs) then
  210. begin
  211. parasym:=false;
  212. symtablestack.foreach_static({$ifdef FPCPROCVAR}@{$endif}searchfpuregvars,@parasym);
  213. {$ifdef dummy}
  214. { this code should be never enabled because }
  215. { 1. the caller loads parameters into registers }
  216. { 2. (later) the CSE loads a parameter into a }
  217. { register, if necessary }
  218. { (FK) }
  219. { copy parameter into a register ? }
  220. parasym:=true;
  221. symtablestack.next.foreach_static({$ifdef FPCPROCVAR}@{$endif}searchregvars);
  222. {$endif dummy}
  223. { hold needed registers free }
  224. { in non leaf procedures we must be very careful }
  225. { with assigning registers }
  226. if aktmaxfpuregisters=-1 then
  227. begin
  228. if (pi_do_call in current_procinfo.flags) then
  229. begin
  230. for i:=maxfpuvarregs downto 2 do
  231. regvarinfo^.fpuregvars[i]:=nil;
  232. end
  233. else
  234. begin
  235. for i:=maxfpuvarregs downto maxfpuvarregs-p.registersfpu do
  236. regvarinfo^.fpuregvars[i]:=nil;
  237. end;
  238. end
  239. else
  240. begin
  241. for i:=aktmaxfpuregisters+1 to maxfpuvarregs do
  242. regvarinfo^.fpuregvars[i]:=nil;
  243. end;
  244. { now assign register }
  245. for i:=1 to maxfpuvarregs do
  246. begin
  247. if assigned(regvarinfo^.fpuregvars[i]) then
  248. begin
  249. {$ifdef i386}
  250. { reserve place on the FPU stack }
  251. {$warning fixme regvars}
  252. { regvarinfo^.fpuregvars[i].localloc.register:=trgcpu(rg).correct_fpuregister(NR_ST0,i);}
  253. {$else i386}
  254. {$ifdef x86_64}
  255. {$endif x86_64}
  256. begin
  257. regvarinfo^.fpuregvars[i].localloc.register:=fpuvarregs[i];
  258. { rg.makeregvarother(regvarinfo^.fpuregvars[i].localloc.register);}
  259. end;
  260. {$endif i386}
  261. end;
  262. end;
  263. end;
  264. end;
  265. end;
  266. procedure store_regvar(asml: TAAsmoutput; reg: tregister);
  267. var
  268. i: longint;
  269. cgsize : tcgsize;
  270. r : tregister;
  271. hr: treference;
  272. regvarinfo: pregvarinfo;
  273. vsym: tvarsym;
  274. regidx : tregisterindex;
  275. supreg : tsuperregister;
  276. begin
  277. {$ifdef i386}
  278. regvarinfo := pregvarinfo(current_procinfo.procdef.regvarinfo);
  279. if not assigned(regvarinfo) then
  280. exit;
  281. if getregtype(reg)=R_INTREGISTER then
  282. begin
  283. supreg:=getsupreg(reg);
  284. for i := 1 to maxvarregs do
  285. if assigned(regvarinfo^.regvars[i]) and
  286. (getsupreg(regvarinfo^.regvars[i].localloc.register)=supreg) then
  287. begin
  288. {$warning fixme regvar_loaded_int}
  289. (* if supreg in rg.regvar_loaded_int then
  290. begin
  291. vsym := tvarsym(regvarinfo^.regvars[i]);
  292. { we only have to store the regvar back to memory if it's }
  293. { possible that it's been modified (JM) }
  294. if not(vsym.varspez in [vs_const,vs_var,vs_out]) then
  295. begin
  296. {$warning FIXME Check vsym.localloc for regvars}
  297. // reference_reset_base(hr,current_procinfo.framepointer,vsym.adjusted_address);
  298. cgsize:=def_cgsize(vsym.vartype.def);
  299. cg.a_load_reg_ref(asml,cgsize,cgsize,vsym.localloc.register,hr);
  300. end;
  301. asml.concat(tai_regalloc.dealloc(vsym.localloc.register));
  302. exclude(rg.regvar_loaded_int,supreg);
  303. end;
  304. *)
  305. break;
  306. end;
  307. end
  308. else
  309. begin
  310. for i := 1 to maxvarregs do
  311. if assigned(regvarinfo^.regvars[i]) then
  312. begin
  313. {$warning fixme regvars}
  314. (*
  315. r:=rg.makeregsize(regvarinfo^.regvars[i].localloc.register,OS_INT);
  316. if (r = reg) then
  317. begin
  318. regidx:=findreg_by_number(r);
  319. if rg.regvar_loaded_other[regidx] then
  320. begin
  321. vsym := tvarsym(regvarinfo^.regvars[i]);
  322. { we only have to store the regvar back to memory if it's }
  323. { possible that it's been modified (JM) }
  324. if not(vsym.varspez in [vs_const,vs_var,vs_out]) then
  325. begin
  326. {$warning FIXME Check vsym.localloc for regvars}
  327. // reference_reset_base(hr,current_procinfo.framepointer,vsym.adjusted_address);
  328. cgsize:=def_cgsize(vsym.vartype.def);
  329. cg.a_load_reg_ref(asml,cgsize,cgsize,vsym.localloc.register,hr);
  330. end;
  331. asml.concat(tai_regalloc.dealloc(vsym.localloc.register));
  332. rg.regvar_loaded_other[regidx] := false;
  333. end;
  334. break;
  335. end;
  336. *)
  337. end;
  338. end;
  339. {$endif i386}
  340. end;
  341. procedure load_regvar(asml: TAAsmoutput; vsym: tvarsym);
  342. var
  343. hr: treference;
  344. opsize: tcgsize;
  345. r,
  346. reg : tregister;
  347. regidx : tregisterindex;
  348. begin
  349. {$ifndef i386}
  350. exit;
  351. {$endif i386}
  352. reg:=vsym.localloc.register;
  353. {$warning fixme regvars}
  354. (*
  355. if getregtype(reg)=R_INTREGISTER then
  356. begin
  357. if not(getsupreg(reg) in rg.regvar_loaded_int) then
  358. begin
  359. asml.concat(tai_regalloc.alloc(reg));
  360. {$warning FIXME Check vsym.localloc for regvars}
  361. // reference_reset_base(hr,current_procinfo.framepointer,vsym.adjusted_address);
  362. if paramanager.push_addr_param(vsym.varspez,vsym.vartype.def,current_procinfo.procdef.proccalloption) then
  363. opsize := OS_ADDR
  364. else
  365. opsize := def_cgsize(vsym.vartype.def);
  366. cg.a_load_ref_reg(asml,opsize,opsize,hr,reg);
  367. include(rg.regvar_loaded_int,getsupreg(reg));
  368. end;
  369. end
  370. else
  371. begin
  372. r:=rg.makeregsize(reg,OS_INT);
  373. regidx:=findreg_by_number(r);
  374. if not rg.regvar_loaded_other[regidx] then
  375. begin
  376. asml.concat(tai_regalloc.alloc(reg));
  377. {$warning FIXME Check vsym.localloc for regvars}
  378. // reference_reset_base(hr,current_procinfo.framepointer,vsym.adjusted_address);
  379. if paramanager.push_addr_param(vsym.varspez,vsym.vartype.def,current_procinfo.procdef.proccalloption) then
  380. opsize := OS_ADDR
  381. else
  382. opsize := def_cgsize(vsym.vartype.def);
  383. cg.a_load_ref_reg(asml,opsize,opsize,hr,reg);
  384. rg.regvar_loaded_other[regidx] := true;
  385. end;
  386. end;
  387. *)
  388. end;
  389. procedure load_regvar_reg(asml: TAAsmoutput; reg: tregister);
  390. var
  391. i: longint;
  392. regvarinfo: pregvarinfo;
  393. reg_spare : tregister;
  394. supreg : tsuperregister;
  395. begin
  396. regvarinfo := pregvarinfo(current_procinfo.procdef.regvarinfo);
  397. if not assigned(regvarinfo) then
  398. exit;
  399. if getregtype(reg)=R_INTREGISTER then
  400. begin
  401. supreg:=getsupreg(reg);
  402. for i := 1 to maxvarregs do
  403. if assigned(regvarinfo^.regvars[i]) and
  404. (getsupreg(regvarinfo^.regvars[i].localloc.register) = supreg) then
  405. load_regvar(asml,tvarsym(regvarinfo^.regvars[i]))
  406. end
  407. else
  408. begin
  409. reg_spare := cg.makeregsize(reg,OS_INT);
  410. for i := 1 to maxvarregs do
  411. if assigned(regvarinfo^.regvars[i]) and
  412. (cg.makeregsize(regvarinfo^.regvars[i].localloc.register,OS_INT) = reg_spare) then
  413. load_regvar(asml,tvarsym(regvarinfo^.regvars[i]))
  414. end;
  415. end;
  416. procedure load_all_regvars(asml: TAAsmoutput);
  417. var
  418. i: longint;
  419. regvarinfo: pregvarinfo;
  420. begin
  421. regvarinfo := pregvarinfo(current_procinfo.procdef.regvarinfo);
  422. if not assigned(regvarinfo) then
  423. exit;
  424. for i := 1 to maxvarregs do
  425. if assigned(regvarinfo^.regvars[i]) then
  426. load_regvar(asml,tvarsym(regvarinfo^.regvars[i]))
  427. end;
  428. procedure load_regvars(asml: TAAsmoutput; p: tnode);
  429. var
  430. i: longint;
  431. regvarinfo: pregvarinfo;
  432. begin
  433. if (cs_regvars in aktglobalswitches) and
  434. not(pi_uses_asm in current_procinfo.flags) and
  435. not(pi_uses_exceptions in current_procinfo.flags) then
  436. begin
  437. regvarinfo := pregvarinfo(current_procinfo.procdef.regvarinfo);
  438. { can happen when inlining assembler procedures (JM) }
  439. if not assigned(regvarinfo) then
  440. exit;
  441. for i:=1 to maxfpuvarregs do
  442. begin
  443. if assigned(regvarinfo^.fpuregvars[i]) then
  444. begin
  445. {$ifdef i386}
  446. { reserve place on the FPU stack }
  447. {$warning fixme fpustack}
  448. (*
  449. regvarinfo^.fpuregvars[i].localloc.register:=trgcpu(rg).correct_fpuregister(NR_ST0,i-1);
  450. *)
  451. asml.concat(Taicpu.op_none(A_FLDZ,S_NO));
  452. {$endif i386}
  453. end;
  454. end;
  455. {$ifdef i386}
  456. if assigned(p) then
  457. if cs_asm_source in aktglobalswitches then
  458. asml.insert(tai_comment.Create(strpnew(tostr(p.registersfpu)+
  459. ' registers on FPU stack used by temp. expressions')));
  460. {$endif i386}
  461. for i:=1 to maxfpuvarregs do
  462. begin
  463. if assigned(regvarinfo^.fpuregvars[i]) then
  464. begin
  465. if cs_asm_source in aktglobalswitches then
  466. asml.insert(tai_comment.Create(strpnew(regvarinfo^.fpuregvars[i].name+
  467. ' with weight '+tostr(regvarinfo^.fpuregvars[i].refs)+' assigned to register '+
  468. std_regname(regvarinfo^.fpuregvars[i].localloc.register))));
  469. if (status.verbosity and v_debug)=v_debug then
  470. Message3(cg_d_register_weight,std_regname(regvarinfo^.fpuregvars[i].localloc.register),
  471. tostr(regvarinfo^.fpuregvars[i].refs),regvarinfo^.fpuregvars[i].name);
  472. end;
  473. end;
  474. if cs_asm_source in aktglobalswitches then
  475. asml.insert(tai_comment.Create(strpnew('Register variable assignment:')));
  476. end;
  477. end;
  478. {$ifdef i386}
  479. (*
  480. procedure sync_regvars_other(list1, list2: taasmoutput; const regvarsloaded1,
  481. regvarsloaded2: regvarother_booleanarray);
  482. var
  483. counter: tregisterindex;
  484. begin
  485. for counter := low(rg.regvar_loaded_other) to high(rg.regvar_loaded_other) do
  486. begin
  487. rg.regvar_loaded_other[counter] := regvarsloaded1[counter] and
  488. regvarsloaded2[counter];
  489. if regvarsloaded1[counter] xor regvarsloaded2[counter] then
  490. if regvarsloaded1[counter] then
  491. load_regvar_reg(list2,counter)
  492. else
  493. load_regvar_reg(list1,counter);
  494. end;
  495. end;
  496. procedure sync_regvars_int(list1, list2: taasmoutput; const regvarsloaded1,
  497. regvarsloaded2: Tsuperregisterset);
  498. var
  499. i : longint;
  500. r : tregister;
  501. begin
  502. for i:=1 to maxvarregs do
  503. begin
  504. r:=newreg(R_INTREGISTER,varregs[i],R_SUBWHOLE);
  505. if (varregs[i] in regvarsloaded1) and
  506. not(varregs[i] in regvarsloaded2) then
  507. load_regvar_reg(list2,r)
  508. else
  509. if (varregs[i] in regvarsloaded2) and
  510. not(varregs[i] in regvarsloaded1) then
  511. load_regvar_reg(list1,r);
  512. end;
  513. end;
  514. *)
  515. {$endif i386}
  516. procedure cleanup_regvars(asml: TAAsmoutput);
  517. var
  518. i: longint;
  519. reg : tregister;
  520. regidx : tregisterindex;
  521. begin
  522. { can happen when inlining assembler procedures (JM) }
  523. if not assigned(current_procinfo.procdef.regvarinfo) then
  524. exit;
  525. if (cs_regvars in aktglobalswitches) and
  526. not(pi_uses_asm in current_procinfo.flags) and
  527. not(pi_uses_exceptions in current_procinfo.flags) then
  528. with pregvarinfo(current_procinfo.procdef.regvarinfo)^ do
  529. begin
  530. {$ifdef i386}
  531. for i:=1 to maxfpuvarregs do
  532. if assigned(fpuregvars[i]) then
  533. { ... and clean it up }
  534. asml.concat(Taicpu.op_reg(A_FSTP,S_NO,NR_ST0));
  535. {$endif i386}
  536. for i := 1 to maxvarregs do
  537. begin
  538. if assigned(regvars[i]) then
  539. begin
  540. reg:=regvars[i].localloc.register;
  541. if getregtype(reg)=R_INTREGISTER then
  542. begin
  543. end
  544. else
  545. begin
  546. reg:=cg.makeregsize(reg,OS_INT);
  547. regidx:=findreg_by_number(reg);
  548. {$warning fixme regvar dealloc}
  549. (*
  550. if (rg.regvar_loaded_other[regidx]) then
  551. asml.concat(tai_regalloc.dealloc(reg));
  552. *)
  553. end;
  554. end;
  555. end;
  556. end;
  557. end;
  558. procedure free_regvars(list: taasmoutput);
  559. var
  560. i: longint;
  561. begin
  562. if not assigned(current_procinfo.procdef.regvarinfo) then
  563. exit;
  564. with pregvarinfo(current_procinfo.procdef.regvarinfo)^ do
  565. for i := 1 to maxvarregs do
  566. if assigned(regvars[i]) { and
  567. (regvars[i] <> tvarsym(current_procinfo.procdef.funcretsym))} then
  568. begin
  569. {$warning fixme regvarexclude}
  570. { make sure the unget isn't just a nop }
  571. (*
  572. exclude(rg.is_reg_var_int,getsupreg(regvars[i].localloc.register));
  573. *)
  574. cg.ungetregister(list,regvars[i].localloc.register);
  575. end;
  576. end;
  577. procedure translate_regvars(list: taasmoutput; const table:Ttranstable);
  578. var
  579. i: longint;
  580. r: tregister;
  581. begin
  582. if not assigned(current_procinfo.procdef.regvarinfo) then
  583. exit;
  584. with pregvarinfo(current_procinfo.procdef.regvarinfo)^ do
  585. for i := 1 to maxvarregs do
  586. if assigned(regvars[i]) { and
  587. (regvars[i] <> tvarsym(current_procinfo.procdef.funcretsym))} then
  588. begin
  589. setsupreg(regvars[i].localloc.register,getsupreg(table[getsupreg(regvars[i].localloc.register)]));
  590. r:=regvars[i].localloc.register;
  591. if cs_asm_source in aktglobalswitches then
  592. list.insert(tai_comment.Create(strpnew(regvars[i].name+
  593. ' with weight '+tostr(regvars[i].refs)+' assigned to register '+
  594. std_regname(r))));
  595. Message3(cg_d_register_weight,std_regname(r),
  596. tostr(regvars[i].refs),regvars[i].name);
  597. end;
  598. end;
  599. {$endif OLDREGVARS}
  600. end.
  601. {
  602. $Log$
  603. Revision 1.71 2003-10-17 14:38:32 peter
  604. * 64k registers supported
  605. * fixed some memory leaks
  606. Revision 1.70 2003/10/10 17:48:14 peter
  607. * old trgobj moved to x86/rgcpu and renamed to trgx86fpu
  608. * tregisteralloctor renamed to trgobj
  609. * removed rgobj from a lot of units
  610. * moved location_* and reference_* to cgobj
  611. * first things for mmx register allocation
  612. Revision 1.69 2003/10/09 21:31:37 daniel
  613. * Register allocator splitted, ans abstract now
  614. Revision 1.68 2003/10/01 20:34:49 peter
  615. * procinfo unit contains tprocinfo
  616. * cginfo renamed to cgbase
  617. * moved cgmessage to verbose
  618. * fixed ppc and sparc compiles
  619. Revision 1.67 2003/09/25 13:13:32 florian
  620. * more x86-64 fixes
  621. Revision 1.66 2003/09/23 17:56:06 peter
  622. * locals and paras are allocated in the code generation
  623. * tvarsym.localloc contains the location of para/local when
  624. generating code for the current procedure
  625. Revision 1.65 2003/09/16 16:17:01 peter
  626. * varspez in calls to push_addr_param
  627. Revision 1.64 2003/09/07 22:09:35 peter
  628. * preparations for different default calling conventions
  629. * various RA fixes
  630. Revision 1.63 2003/09/03 15:55:01 peter
  631. * NEWRA branch merged
  632. Revision 1.62.2.2 2003/08/29 17:28:59 peter
  633. * next batch of updates
  634. Revision 1.62.2.1 2003/08/28 18:35:08 peter
  635. * tregister changed to cardinal
  636. Revision 1.62 2003/08/17 20:47:47 daniel
  637. * Notranslation changed into -sr functionality
  638. Revision 1.61 2003/08/17 16:59:20 jonas
  639. * fixed regvars so they work with newra (at least for ppc)
  640. * fixed some volatile register bugs
  641. + -dnotranslation option for -dnewra, which causes the registers not to
  642. be translated from virtual to normal registers. Requires support in
  643. the assembler writer as well, which is only implemented in aggas/
  644. agppcgas currently
  645. Revision 1.60 2003/08/11 21:18:20 peter
  646. * start of sparc support for newra
  647. Revision 1.59 2003/08/09 18:56:54 daniel
  648. * cs_regalloc renamed to cs_regvars to avoid confusion with register
  649. allocator
  650. * Some preventive changes to i386 spillinh code
  651. Revision 1.58 2003/07/02 22:18:04 peter
  652. * paraloc splitted in callerparaloc,calleeparaloc
  653. * sparc calling convention updates
  654. Revision 1.57 2003/06/13 21:19:31 peter
  655. * current_procdef removed, use current_procinfo.procdef instead
  656. Revision 1.56 2003/06/07 18:57:04 jonas
  657. + added freeintparaloc
  658. * ppc get/freeintparaloc now check whether the parameter regs are
  659. properly allocated/deallocated (and get an extra list para)
  660. * ppc a_call_* now internalerrors if pi_do_call is not yet set
  661. * fixed lot of missing pi_do_call's
  662. Revision 1.55 2003/06/03 21:11:09 peter
  663. * cg.a_load_* get a from and to size specifier
  664. * makeregsize only accepts newregister
  665. * i386 uses generic tcgnotnode,tcgunaryminus
  666. Revision 1.54 2003/06/03 13:01:59 daniel
  667. * Register allocator finished
  668. Revision 1.53 2003/05/31 20:33:57 jonas
  669. * temp fix/hack for nested procedures (disable regvars in all procedures
  670. that have nested procedures)
  671. * leave register parameters in their own register (instead of storing
  672. them to memory or assigning them to another register) if the current
  673. procedure doesn't call any other procedures
  674. Revision 1.52 2003/05/30 18:55:21 jonas
  675. * fixed several regvar related bugs for non-i386. make cycle with -Or now
  676. works for ppc
  677. Revision 1.51 2003/05/23 14:27:35 peter
  678. * remove some unit dependencies
  679. * current_procinfo changes to store more info
  680. Revision 1.50 2003/05/16 14:33:31 peter
  681. * regvar fixes
  682. Revision 1.49 2003/05/15 18:58:53 peter
  683. * removed selfpointer_offset, vmtpointer_offset
  684. * tvarsym.adjusted_address
  685. * address in localsymtable is now in the real direction
  686. * removed some obsolete globals
  687. Revision 1.48 2003/05/12 17:22:00 jonas
  688. * fixed (last?) remaining -tvarsym(X).address to
  689. tg.direction*tvarsym(X).address...
  690. Revision 1.47 2003/04/27 11:21:34 peter
  691. * aktprocdef renamed to current_procinfo.procdef
  692. * procinfo renamed to current_procinfo
  693. * procinfo will now be stored in current_module so it can be
  694. cleaned up properly
  695. * gen_main_procsym changed to create_main_proc and release_main_proc
  696. to also generate a tprocinfo structure
  697. * fixed unit implicit initfinal
  698. Revision 1.46 2003/03/28 19:16:57 peter
  699. * generic constructor working for i386
  700. * remove fixed self register
  701. * esi added as address register for i386
  702. Revision 1.45 2003/02/19 22:00:14 daniel
  703. * Code generator converted to new register notation
  704. - Horribily outdated todo.txt removed
  705. Revision 1.44 2003/01/08 18:43:57 daniel
  706. * Tregister changed into a record
  707. Revision 1.43 2002/11/25 17:43:24 peter
  708. * splitted defbase in defutil,symutil,defcmp
  709. * merged isconvertable and is_equal into compare_defs(_ext)
  710. * made operator search faster by walking the list only once
  711. Revision 1.42 2002/11/18 17:31:59 peter
  712. * pass proccalloption to ret_in_xxx and push_xxx functions
  713. Revision 1.41 2002/08/25 19:25:20 peter
  714. * sym.insert_in_data removed
  715. * symtable.insertvardata/insertconstdata added
  716. * removed insert_in_data call from symtable.insert, it needs to be
  717. called separatly. This allows to deref the address calculation
  718. * procedures now calculate the parast addresses after the procedure
  719. directives are parsed. This fixes the cdecl parast problem
  720. * push_addr_param has an extra argument that specifies if cdecl is used
  721. or not
  722. Revision 1.40 2002/08/18 20:06:25 peter
  723. * inlining is now also allowed in interface
  724. * renamed write/load to ppuwrite/ppuload
  725. * tnode storing in ppu
  726. * nld,ncon,nbas are already updated for storing in ppu
  727. Revision 1.39 2002/08/17 09:23:41 florian
  728. * first part of procinfo rewrite
  729. Revision 1.38 2002/08/06 20:55:22 florian
  730. * first part of ppc calling conventions fix
  731. Revision 1.37 2002/07/20 11:57:57 florian
  732. * types.pas renamed to defbase.pas because D6 contains a types
  733. unit so this would conflicts if D6 programms are compiled
  734. + Willamette/SSE2 instructions to assembler added
  735. Revision 1.36 2002/07/11 14:41:30 florian
  736. * start of the new generic parameter handling
  737. Revision 1.35 2002/07/01 18:46:25 peter
  738. * internal linker
  739. * reorganized aasm layer
  740. Revision 1.34 2002/06/24 12:43:00 jonas
  741. * fixed errors found with new -CR code from Peter when cycling with -O2p3r
  742. Revision 1.33 2002/05/18 13:34:17 peter
  743. * readded missing revisions
  744. Revision 1.32 2002/05/16 19:46:44 carl
  745. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  746. + try to fix temp allocation (still in ifdef)
  747. + generic constructor calls
  748. + start of tassembler / tmodulebase class cleanup
  749. Revision 1.30 2002/05/12 16:53:10 peter
  750. * moved entry and exitcode to ncgutil and cgobj
  751. * foreach gets extra argument for passing local data to the
  752. iterator function
  753. * -CR checks also class typecasts at runtime by changing them
  754. into as
  755. * fixed compiler to cycle with the -CR option
  756. * fixed stabs with elf writer, finally the global variables can
  757. be watched
  758. * removed a lot of routines from cga unit and replaced them by
  759. calls to cgobj
  760. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  761. u32bit then the other is typecasted also to u32bit without giving
  762. a rangecheck warning/error.
  763. * fixed pascal calling method with reversing also the high tree in
  764. the parast, detected by tcalcst3 test
  765. Revision 1.29 2002/04/21 15:23:34 carl
  766. + changeregsize -> makeregsize
  767. Revision 1.28 2002/04/19 15:46:03 peter
  768. * mangledname rewrite, tprocdef.mangledname is now created dynamicly
  769. in most cases and not written to the ppu
  770. * add mangeledname_prefix() routine to generate the prefix of
  771. manglednames depending on the current procedure, object and module
  772. * removed static procprefix since the mangledname is now build only
  773. on demand from tprocdef.mangledname
  774. Revision 1.27 2002/04/15 19:44:19 peter
  775. * fixed stackcheck that would be called recursively when a stack
  776. error was found
  777. * generic changeregsize(reg,size) for i386 register resizing
  778. * removed some more routines from cga unit
  779. * fixed returnvalue handling
  780. * fixed default stacksize of linux and go32v2, 8kb was a bit small :-)
  781. Revision 1.26 2002/04/15 19:04:04 carl
  782. + reg2str -> std_reg2str()
  783. Revision 1.25 2002/04/06 18:13:01 jonas
  784. * several powerpc-related additions and fixes
  785. Revision 1.24 2002/04/02 17:11:29 peter
  786. * tlocation,treference update
  787. * LOC_CONSTANT added for better constant handling
  788. * secondadd splitted in multiple routines
  789. * location_force_reg added for loading a location to a register
  790. of a specified size
  791. * secondassignment parses now first the right and then the left node
  792. (this is compatible with Kylix). This saves a lot of push/pop especially
  793. with string operations
  794. * adapted some routines to use the new cg methods
  795. Revision 1.23 2002/03/31 20:26:36 jonas
  796. + a_loadfpu_* and a_loadmm_* methods in tcg
  797. * register allocation is now handled by a class and is mostly processor
  798. independent (+rgobj.pas and i386/rgcpu.pas)
  799. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  800. * some small improvements and fixes to the optimizer
  801. * some register allocation fixes
  802. * some fpuvaroffset fixes in the unary minus node
  803. * push/popusedregisters is now called rg.save/restoreusedregisters and
  804. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  805. also better optimizable)
  806. * fixed and optimized register saving/restoring for new/dispose nodes
  807. * LOC_FPU locations now also require their "register" field to be set to
  808. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  809. - list field removed of the tnode class because it's not used currently
  810. and can cause hard-to-find bugs
  811. }