regvars.pas 33 KB

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