regvars.pas 33 KB

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