regvars.pas 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906
  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.registersint<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.registersint+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.registersint-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.72 2004-02-03 22:32:54 peter
  604. * renamed xNNbittype to xNNinttype
  605. * renamed registers32 to registersint
  606. * replace some s32bit,u32bit with torddef([su]inttype).def.typ
  607. Revision 1.71 2003/10/17 14:38:32 peter
  608. * 64k registers supported
  609. * fixed some memory leaks
  610. Revision 1.70 2003/10/10 17:48:14 peter
  611. * old trgobj moved to x86/rgcpu and renamed to trgx86fpu
  612. * tregisteralloctor renamed to trgobj
  613. * removed rgobj from a lot of units
  614. * moved location_* and reference_* to cgobj
  615. * first things for mmx register allocation
  616. Revision 1.69 2003/10/09 21:31:37 daniel
  617. * Register allocator splitted, ans abstract now
  618. Revision 1.68 2003/10/01 20:34:49 peter
  619. * procinfo unit contains tprocinfo
  620. * cginfo renamed to cgbase
  621. * moved cgmessage to verbose
  622. * fixed ppc and sparc compiles
  623. Revision 1.67 2003/09/25 13:13:32 florian
  624. * more x86-64 fixes
  625. Revision 1.66 2003/09/23 17:56:06 peter
  626. * locals and paras are allocated in the code generation
  627. * tvarsym.localloc contains the location of para/local when
  628. generating code for the current procedure
  629. Revision 1.65 2003/09/16 16:17:01 peter
  630. * varspez in calls to push_addr_param
  631. Revision 1.64 2003/09/07 22:09:35 peter
  632. * preparations for different default calling conventions
  633. * various RA fixes
  634. Revision 1.63 2003/09/03 15:55:01 peter
  635. * NEWRA branch merged
  636. Revision 1.62.2.2 2003/08/29 17:28:59 peter
  637. * next batch of updates
  638. Revision 1.62.2.1 2003/08/28 18:35:08 peter
  639. * tregister changed to cardinal
  640. Revision 1.62 2003/08/17 20:47:47 daniel
  641. * Notranslation changed into -sr functionality
  642. Revision 1.61 2003/08/17 16:59:20 jonas
  643. * fixed regvars so they work with newra (at least for ppc)
  644. * fixed some volatile register bugs
  645. + -dnotranslation option for -dnewra, which causes the registers not to
  646. be translated from virtual to normal registers. Requires support in
  647. the assembler writer as well, which is only implemented in aggas/
  648. agppcgas currently
  649. Revision 1.60 2003/08/11 21:18:20 peter
  650. * start of sparc support for newra
  651. Revision 1.59 2003/08/09 18:56:54 daniel
  652. * cs_regalloc renamed to cs_regvars to avoid confusion with register
  653. allocator
  654. * Some preventive changes to i386 spillinh code
  655. Revision 1.58 2003/07/02 22:18:04 peter
  656. * paraloc splitted in callerparaloc,calleeparaloc
  657. * sparc calling convention updates
  658. Revision 1.57 2003/06/13 21:19:31 peter
  659. * current_procdef removed, use current_procinfo.procdef instead
  660. Revision 1.56 2003/06/07 18:57:04 jonas
  661. + added freeintparaloc
  662. * ppc get/freeintparaloc now check whether the parameter regs are
  663. properly allocated/deallocated (and get an extra list para)
  664. * ppc a_call_* now internalerrors if pi_do_call is not yet set
  665. * fixed lot of missing pi_do_call's
  666. Revision 1.55 2003/06/03 21:11:09 peter
  667. * cg.a_load_* get a from and to size specifier
  668. * makeregsize only accepts newregister
  669. * i386 uses generic tcgnotnode,tcgunaryminus
  670. Revision 1.54 2003/06/03 13:01:59 daniel
  671. * Register allocator finished
  672. Revision 1.53 2003/05/31 20:33:57 jonas
  673. * temp fix/hack for nested procedures (disable regvars in all procedures
  674. that have nested procedures)
  675. * leave register parameters in their own register (instead of storing
  676. them to memory or assigning them to another register) if the current
  677. procedure doesn't call any other procedures
  678. Revision 1.52 2003/05/30 18:55:21 jonas
  679. * fixed several regvar related bugs for non-i386. make cycle with -Or now
  680. works for ppc
  681. Revision 1.51 2003/05/23 14:27:35 peter
  682. * remove some unit dependencies
  683. * current_procinfo changes to store more info
  684. Revision 1.50 2003/05/16 14:33:31 peter
  685. * regvar fixes
  686. Revision 1.49 2003/05/15 18:58:53 peter
  687. * removed selfpointer_offset, vmtpointer_offset
  688. * tvarsym.adjusted_address
  689. * address in localsymtable is now in the real direction
  690. * removed some obsolete globals
  691. Revision 1.48 2003/05/12 17:22:00 jonas
  692. * fixed (last?) remaining -tvarsym(X).address to
  693. tg.direction*tvarsym(X).address...
  694. Revision 1.47 2003/04/27 11:21:34 peter
  695. * aktprocdef renamed to current_procinfo.procdef
  696. * procinfo renamed to current_procinfo
  697. * procinfo will now be stored in current_module so it can be
  698. cleaned up properly
  699. * gen_main_procsym changed to create_main_proc and release_main_proc
  700. to also generate a tprocinfo structure
  701. * fixed unit implicit initfinal
  702. Revision 1.46 2003/03/28 19:16:57 peter
  703. * generic constructor working for i386
  704. * remove fixed self register
  705. * esi added as address register for i386
  706. Revision 1.45 2003/02/19 22:00:14 daniel
  707. * Code generator converted to new register notation
  708. - Horribily outdated todo.txt removed
  709. Revision 1.44 2003/01/08 18:43:57 daniel
  710. * Tregister changed into a record
  711. Revision 1.43 2002/11/25 17:43:24 peter
  712. * splitted defbase in defutil,symutil,defcmp
  713. * merged isconvertable and is_equal into compare_defs(_ext)
  714. * made operator search faster by walking the list only once
  715. Revision 1.42 2002/11/18 17:31:59 peter
  716. * pass proccalloption to ret_in_xxx and push_xxx functions
  717. Revision 1.41 2002/08/25 19:25:20 peter
  718. * sym.insert_in_data removed
  719. * symtable.insertvardata/insertconstdata added
  720. * removed insert_in_data call from symtable.insert, it needs to be
  721. called separatly. This allows to deref the address calculation
  722. * procedures now calculate the parast addresses after the procedure
  723. directives are parsed. This fixes the cdecl parast problem
  724. * push_addr_param has an extra argument that specifies if cdecl is used
  725. or not
  726. Revision 1.40 2002/08/18 20:06:25 peter
  727. * inlining is now also allowed in interface
  728. * renamed write/load to ppuwrite/ppuload
  729. * tnode storing in ppu
  730. * nld,ncon,nbas are already updated for storing in ppu
  731. Revision 1.39 2002/08/17 09:23:41 florian
  732. * first part of procinfo rewrite
  733. Revision 1.38 2002/08/06 20:55:22 florian
  734. * first part of ppc calling conventions fix
  735. Revision 1.37 2002/07/20 11:57:57 florian
  736. * types.pas renamed to defbase.pas because D6 contains a types
  737. unit so this would conflicts if D6 programms are compiled
  738. + Willamette/SSE2 instructions to assembler added
  739. Revision 1.36 2002/07/11 14:41:30 florian
  740. * start of the new generic parameter handling
  741. Revision 1.35 2002/07/01 18:46:25 peter
  742. * internal linker
  743. * reorganized aasm layer
  744. Revision 1.34 2002/06/24 12:43:00 jonas
  745. * fixed errors found with new -CR code from Peter when cycling with -O2p3r
  746. Revision 1.33 2002/05/18 13:34:17 peter
  747. * readded missing revisions
  748. Revision 1.32 2002/05/16 19:46:44 carl
  749. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  750. + try to fix temp allocation (still in ifdef)
  751. + generic constructor calls
  752. + start of tassembler / tmodulebase class cleanup
  753. Revision 1.30 2002/05/12 16:53:10 peter
  754. * moved entry and exitcode to ncgutil and cgobj
  755. * foreach gets extra argument for passing local data to the
  756. iterator function
  757. * -CR checks also class typecasts at runtime by changing them
  758. into as
  759. * fixed compiler to cycle with the -CR option
  760. * fixed stabs with elf writer, finally the global variables can
  761. be watched
  762. * removed a lot of routines from cga unit and replaced them by
  763. calls to cgobj
  764. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  765. u32bit then the other is typecasted also to u32bit without giving
  766. a rangecheck warning/error.
  767. * fixed pascal calling method with reversing also the high tree in
  768. the parast, detected by tcalcst3 test
  769. Revision 1.29 2002/04/21 15:23:34 carl
  770. + changeregsize -> makeregsize
  771. Revision 1.28 2002/04/19 15:46:03 peter
  772. * mangledname rewrite, tprocdef.mangledname is now created dynamicly
  773. in most cases and not written to the ppu
  774. * add mangeledname_prefix() routine to generate the prefix of
  775. manglednames depending on the current procedure, object and module
  776. * removed static procprefix since the mangledname is now build only
  777. on demand from tprocdef.mangledname
  778. Revision 1.27 2002/04/15 19:44:19 peter
  779. * fixed stackcheck that would be called recursively when a stack
  780. error was found
  781. * generic changeregsize(reg,size) for i386 register resizing
  782. * removed some more routines from cga unit
  783. * fixed returnvalue handling
  784. * fixed default stacksize of linux and go32v2, 8kb was a bit small :-)
  785. Revision 1.26 2002/04/15 19:04:04 carl
  786. + reg2str -> std_reg2str()
  787. Revision 1.25 2002/04/06 18:13:01 jonas
  788. * several powerpc-related additions and fixes
  789. Revision 1.24 2002/04/02 17:11:29 peter
  790. * tlocation,treference update
  791. * LOC_CONSTANT added for better constant handling
  792. * secondadd splitted in multiple routines
  793. * location_force_reg added for loading a location to a register
  794. of a specified size
  795. * secondassignment parses now first the right and then the left node
  796. (this is compatible with Kylix). This saves a lot of push/pop especially
  797. with string operations
  798. * adapted some routines to use the new cg methods
  799. Revision 1.23 2002/03/31 20:26:36 jonas
  800. + a_loadfpu_* and a_loadmm_* methods in tcg
  801. * register allocation is now handled by a class and is mostly processor
  802. independent (+rgobj.pas and i386/rgcpu.pas)
  803. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  804. * some small improvements and fixes to the optimizer
  805. * some register allocation fixes
  806. * some fpuvaroffset fixes in the unary minus node
  807. * push/popusedregisters is now called rg.save/restoreusedregisters and
  808. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  809. also better optimizable)
  810. * fixed and optimized register saving/restoring for new/dispose nodes
  811. * LOC_FPU locations now also require their "register" field to be set to
  812. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  813. - list field removed of the tnode class because it's not used currently
  814. and can cause hard-to-find bugs
  815. }