regvars.pas 34 KB

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