regvars.pas 36 KB

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