regvars.pas 30 KB

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