regvars.pas 32 KB

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