regvars.pas 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 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 defines.inc}
  20. interface
  21. uses
  22. aasm,
  23. node,
  24. symsym,
  25. cpubase;
  26. procedure assign_regvars(p: tnode);
  27. procedure load_regvars(asml: TAAsmoutput; p: tnode);
  28. procedure cleanup_regvars(asml: TAAsmoutput);
  29. {$ifdef i386}
  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. {$endif i386}
  35. implementation
  36. uses
  37. globtype,systems,comphook,
  38. cutils,cclasses,verbose,globals,
  39. symconst,symbase,symtype,symdef,types,
  40. cgbase,cpuasm,tgcpu;
  41. var
  42. parasym : boolean;
  43. procedure searchregvars(p : tnamedindexitem);
  44. var
  45. i,j,k : longint;
  46. begin
  47. if (tsym(p).typ=varsym) and (vo_regable in tvarsym(p).varoptions) then
  48. begin
  49. j:=tvarsym(p).refs;
  50. { parameter get a less value }
  51. if parasym then
  52. begin
  53. if cs_littlesize in aktglobalswitches then
  54. dec(j,1)
  55. else
  56. dec(j,100);
  57. end;
  58. { walk through all momentary register variables }
  59. for i:=1 to maxvarregs do
  60. begin
  61. with pregvarinfo(aktprocsym.definition.regvarinfo)^ do
  62. if ((regvars[i]=nil) or (j>regvars_refs[i])) and (j>0) then
  63. begin
  64. for k:=maxvarregs-1 downto i do
  65. begin
  66. regvars[k+1]:=regvars[k];
  67. regvars_para[k+1]:=regvars_para[k];
  68. regvars_refs[k+1]:=regvars_refs[k];
  69. end;
  70. { calc the new refs
  71. tvarsym(p).refs:=j; }
  72. regvars[i]:=tvarsym(p);
  73. regvars_para[i]:=parasym;
  74. regvars_refs[i]:=j;
  75. break;
  76. end;
  77. end;
  78. end;
  79. end;
  80. procedure searchfpuregvars(p : tnamedindexitem);
  81. var
  82. i,j,k : longint;
  83. begin
  84. if (tsym(p).typ=varsym) and (vo_fpuregable in tvarsym(p).varoptions) then
  85. begin
  86. j:=tvarsym(p).refs;
  87. { parameter get a less value }
  88. if parasym then
  89. begin
  90. if cs_littlesize in aktglobalswitches then
  91. dec(j,1)
  92. else
  93. dec(j,100);
  94. end;
  95. { walk through all momentary register variables }
  96. for i:=1 to maxfpuvarregs do
  97. begin
  98. with pregvarinfo(aktprocsym.definition.regvarinfo)^ do
  99. if ((fpuregvars[i]=nil) or (j>fpuregvars_refs[i])) and (j>0) then
  100. begin
  101. for k:=maxfpuvarregs-1 downto i do
  102. begin
  103. fpuregvars[k+1]:=fpuregvars[k];
  104. fpuregvars_para[k+1]:=fpuregvars_para[k];
  105. fpuregvars_refs[k+1]:=fpuregvars_refs[k];
  106. end;
  107. { calc the new refs
  108. tvarsym(p).refs:=j; }
  109. fpuregvars[i]:=tvarsym(p);
  110. fpuregvars_para[i]:=parasym;
  111. fpuregvars_refs[i]:=j;
  112. break;
  113. end;
  114. end;
  115. end;
  116. end;
  117. {$ifdef i386}
  118. function reg32(reg: tregister): tregister;
  119. begin
  120. case regsize(reg) of
  121. S_B: reg32 := reg8toreg32(reg);
  122. S_W: reg32 := reg16toreg32(reg);
  123. S_L: reg32 := reg;
  124. end;
  125. end;
  126. {$else i386}
  127. function reg32(reg: tregister): tregister;
  128. begin
  129. reg32 := reg;
  130. end;
  131. {$endif i386}
  132. procedure assign_regvars(p: tnode);
  133. { register variables }
  134. var
  135. regvarinfo: pregvarinfo;
  136. i: longint;
  137. begin
  138. {$ifdef i386}
  139. { max. optimizations }
  140. { only if no asm is used }
  141. { and no try statement }
  142. if (cs_regalloc in aktglobalswitches) and
  143. ((procinfo^.flags and (pi_uses_asm or pi_uses_exceptions))=0) then
  144. begin
  145. new(regvarinfo);
  146. fillchar(regvarinfo^,sizeof(regvarinfo^),0);
  147. aktprocsym.definition.regvarinfo := regvarinfo;
  148. if (p.registers32<4) then
  149. begin
  150. parasym:=false;
  151. symtablestack.foreach_static({$ifdef FPCPROCVAR}@{$endif}searchregvars);
  152. { copy parameter into a register ? }
  153. parasym:=true;
  154. symtablestack.next.foreach_static({$ifdef FPCPROCVAR}@{$endif}searchregvars);
  155. { hold needed registers free }
  156. for i:=maxvarregs downto maxvarregs-p.registers32+1 do
  157. begin
  158. regvarinfo^.regvars[i]:=nil;
  159. regvarinfo^.regvars_para[i] := false;
  160. end;
  161. { now assign register }
  162. for i:=1 to maxvarregs-p.registers32 do
  163. begin
  164. if assigned(regvarinfo^.regvars[i]) and
  165. (reg_pushes[varregs[i]] < regvarinfo^.regvars[i].refs) then
  166. begin
  167. { register is no longer available for }
  168. { expressions }
  169. { search the register which is the most }
  170. { unused }
  171. usableregs:=usableregs-[varregs[i]];
  172. is_reg_var[varregs[i]]:=true;
  173. dec(c_usableregs);
  174. { possibly no 32 bit register are needed }
  175. { call by reference/const ? }
  176. if (regvarinfo^.regvars[i].varspez in [vs_var,vs_out]) or
  177. ((regvarinfo^.regvars[i].varspez=vs_const) and
  178. push_addr_param(regvarinfo^.regvars[i].vartype.def)) then
  179. begin
  180. regvarinfo^.regvars[i].reg:=varregs[i];
  181. end
  182. else
  183. if (regvarinfo^.regvars[i].vartype.def.deftype in [orddef,enumdef]) and
  184. (torddef(regvarinfo^.regvars[i].vartype.def).size=1) then
  185. begin
  186. {$ifdef i386}
  187. regvarinfo^.regvars[i].reg:=reg32toreg8(varregs[i]);
  188. {$endif}
  189. end
  190. else
  191. if (regvarinfo^.regvars[i].vartype.def.deftype in [orddef,enumdef]) and
  192. (torddef(regvarinfo^.regvars[i].vartype.def).size=2) then
  193. begin
  194. {$ifdef i386}
  195. regvarinfo^.regvars[i].reg:=reg32toreg16(varregs[i]);
  196. {$endif}
  197. end
  198. else
  199. begin
  200. regvarinfo^.regvars[i].reg:=varregs[i];
  201. end;
  202. if regvarinfo^.regvars_para[i] then
  203. unused:=unused - [regvarinfo^.regvars[i].reg];
  204. { procedure uses this register }
  205. {$ifdef i386}
  206. usedinproc:=usedinproc or ($80 shr byte(varregs[i]));
  207. {$else i386}
  208. usedinproc:=usedinproc + [varregs[i]];
  209. {$endif i386}
  210. end
  211. else
  212. begin
  213. regvarinfo^.regvars[i] := nil;
  214. regvarinfo^.regvars_para[i] := false;
  215. end;
  216. end;
  217. end;
  218. if ((p.registersfpu+1)<maxfpuvarregs) then
  219. begin
  220. parasym:=false;
  221. symtablestack.foreach_static({$ifdef FPCPROCVAR}@{$endif}searchfpuregvars);
  222. {$ifdef dummy}
  223. { copy parameter into a register ? }
  224. parasym:=true;
  225. symtablestack.next.foreach_static({$ifdef FPCPROCVAR}@{$endif}searchregvars);
  226. {$endif dummy}
  227. { hold needed registers free }
  228. { in non leaf procedures we must be very careful }
  229. { with assigning registers }
  230. if aktmaxfpuregisters=-1 then
  231. begin
  232. if (procinfo^.flags and pi_do_call)<>0 then
  233. begin
  234. for i:=maxfpuvarregs downto 2 do
  235. regvarinfo^.fpuregvars[i]:=nil;
  236. end
  237. else
  238. begin
  239. for i:=maxfpuvarregs downto maxfpuvarregs-p.registersfpu do
  240. regvarinfo^.fpuregvars[i]:=nil;
  241. end;
  242. end
  243. else
  244. begin
  245. for i:=aktmaxfpuregisters+1 to maxfpuvarregs do
  246. regvarinfo^.fpuregvars[i]:=nil;
  247. end;
  248. { now assign register }
  249. for i:=1 to maxfpuvarregs do
  250. begin
  251. if assigned(regvarinfo^.fpuregvars[i]) then
  252. begin
  253. {$ifdef i386}
  254. { reserve place on the FPU stack }
  255. regvarinfo^.fpuregvars[i].reg:=correct_fpuregister(R_ST0,i-1);
  256. {$endif i386}
  257. {$ifdef m68k}
  258. regvarinfo^.fpuregvars[i].reg:=fpuvarregs[i];
  259. {$endif m68k}
  260. end;
  261. end;
  262. end;
  263. end;
  264. {$endif i386}
  265. end;
  266. {$ifdef i386}
  267. procedure store_regvar(asml: TAAsmoutput; reg: tregister);
  268. var
  269. i: longint;
  270. hr: preference;
  271. regvarinfo: pregvarinfo;
  272. vsym: tvarsym;
  273. begin
  274. regvarinfo := pregvarinfo(aktprocsym.definition.regvarinfo);
  275. if not assigned(regvarinfo) then
  276. exit;
  277. for i := 1 to maxvarregs do
  278. if assigned(regvarinfo^.regvars[i]) and
  279. (reg32(regvarinfo^.regvars[i].reg) = reg) then
  280. begin
  281. if regvar_loaded[reg32(reg)] then
  282. begin
  283. vsym := tvarsym(regvarinfo^.regvars[i]);
  284. new(hr);
  285. reset_reference(hr^);
  286. if vsym.owner.symtabletype in [inlinelocalsymtable,localsymtable] then
  287. hr^.offset:=-vsym.address+vsym.owner.address_fixup
  288. else hr^.offset:=vsym.address+vsym.owner.address_fixup;
  289. hr^.base:=procinfo^.framepointer;
  290. asml.concat(Taicpu.op_reg_ref(A_MOV,regsize(vsym.reg),vsym.reg,hr));
  291. asml.concat(Tairegalloc.dealloc(reg32(reg)));
  292. regvar_loaded[reg32(reg)] := false;
  293. end;
  294. break;
  295. end;
  296. end;
  297. procedure load_regvar(asml: TAAsmoutput; vsym: tvarsym);
  298. var
  299. hr: preference;
  300. opsize: topsize;
  301. opcode: tasmop;
  302. begin
  303. if not regvar_loaded[reg32(vsym.reg)] then
  304. begin
  305. asml.concat(Tairegalloc.alloc(reg32(vsym.reg)));
  306. { zero the regvars because the upper 48bits must be clear }
  307. { for 8bits vars when using them with btrl }
  308. { don't care about sign extension, since the upper 24/16 }
  309. { bits won't be adapted when doing maths anyway (JM) }
  310. case regsize(vsym.reg) of
  311. S_L:
  312. begin
  313. opsize := S_L;
  314. opcode := A_MOV;
  315. end;
  316. S_W:
  317. begin
  318. opsize := S_WL;
  319. opcode := A_MOVZX;
  320. end;
  321. S_B:
  322. begin
  323. opsize := S_BL;
  324. opcode := A_MOVZX;
  325. end;
  326. end;
  327. asml.concat(Tairegalloc.alloc(reg32(vsym.reg)));
  328. new(hr);
  329. reset_reference(hr^);
  330. if vsym.owner.symtabletype in [inlinelocalsymtable,localsymtable] then
  331. hr^.offset:=-vsym.address+vsym.owner.address_fixup
  332. else hr^.offset:=vsym.address+vsym.owner.address_fixup;
  333. hr^.base:=procinfo^.framepointer;
  334. asml.concat(Taicpu.op_ref_reg(opcode,opsize,hr,reg32(vsym.reg)));
  335. regvar_loaded[reg32(vsym.reg)] := true;
  336. end;
  337. end;
  338. procedure load_regvar_reg(asml: TAAsmoutput; reg: tregister);
  339. var
  340. i: longint;
  341. regvarinfo: pregvarinfo;
  342. begin
  343. regvarinfo := pregvarinfo(aktprocsym.definition.regvarinfo);
  344. if not assigned(regvarinfo) then
  345. exit;
  346. reg := reg32(reg);
  347. for i := 1 to maxvarregs do
  348. if assigned(regvarinfo^.regvars[i]) and
  349. (reg32(regvarinfo^.regvars[i].reg) = reg) then
  350. load_regvar(asml,tvarsym(regvarinfo^.regvars[i]))
  351. end;
  352. procedure load_all_regvars(asml: TAAsmoutput);
  353. var
  354. i: longint;
  355. regvarinfo: pregvarinfo;
  356. begin
  357. regvarinfo := pregvarinfo(aktprocsym.definition.regvarinfo);
  358. if not assigned(regvarinfo) then
  359. exit;
  360. for i := 1 to maxvarregs do
  361. if assigned(regvarinfo^.regvars[i]) and
  362. (reg32(regvarinfo^.regvars[i].reg) in [R_EAX,R_EBX,R_ECX,R_EDX]) then
  363. load_regvar(asml,tvarsym(regvarinfo^.regvars[i]))
  364. end;
  365. {$endif i386}
  366. procedure load_regvars(asml: TAAsmoutput; p: tnode);
  367. var
  368. i: longint;
  369. {hr : treference;}
  370. regvarinfo: pregvarinfo;
  371. begin
  372. if (cs_regalloc in aktglobalswitches) and
  373. ((procinfo^.flags and (pi_uses_asm or pi_uses_exceptions))=0) then
  374. begin
  375. regvarinfo := pregvarinfo(aktprocsym.definition.regvarinfo);
  376. { can happen when inlining assembler procedures (JM) }
  377. if not assigned(regvarinfo) then
  378. exit;
  379. {$ifdef m68k}
  380. for i:=1 to maxvarregs do
  381. begin
  382. { parameter must be load }
  383. if regvarinfo^.regvars_para[i] then
  384. begin
  385. { procinfo is there actual, }
  386. { because we can't never be in a }
  387. { nested procedure }
  388. { when loading parameter to reg }
  389. new(hr);
  390. reset_reference(hr^);
  391. hr^.offset:=tvarsym(regvarinfo^.regvars[i])^.address+procinfo^.para_offset;
  392. hr^.base:=procinfo^.framepointer;
  393. asml.concat(Taicpu,op_ref_reg(A_MOVE,regsize(regvarinfo^.regvars[i].reg),
  394. hr,regvarinfo^.regvars[i].reg)));
  395. end
  396. end;
  397. {$endif m68k}
  398. for i:=1 to maxvarregs do
  399. begin
  400. if assigned(regvarinfo^.regvars[i]) then
  401. begin
  402. if cs_asm_source in aktglobalswitches then
  403. asml.insert(Tai_asm_comment.Create(strpnew(regvarinfo^.regvars[i].name+
  404. ' with weight '+tostr(regvarinfo^.regvars[i].refs)+' assigned to register '+
  405. reg2str(regvarinfo^.regvars[i].reg))));
  406. if (status.verbosity and v_debug)=v_debug then
  407. Message3(cg_d_register_weight,reg2str(regvarinfo^.regvars[i].reg),
  408. tostr(regvarinfo^.regvars[i].refs),regvarinfo^.regvars[i].name);
  409. end;
  410. end;
  411. for i:=1 to maxfpuvarregs do
  412. begin
  413. if assigned(regvarinfo^.fpuregvars[i]) then
  414. begin
  415. {$ifdef i386}
  416. { reserve place on the FPU stack }
  417. regvarinfo^.fpuregvars[i].reg:=correct_fpuregister(R_ST0,i-1);
  418. asml.concat(Taicpu.op_none(A_FLDZ,S_NO));
  419. {$endif i386}
  420. {$ifdef dummy}
  421. { parameter must be load }
  422. if regvarinfo^.fpuregvars_para[i] then
  423. begin
  424. { procinfo is there actual, }
  425. { because we can't never be in a }
  426. { nested procedure }
  427. { when loading parameter to reg }
  428. new(hr);
  429. reset_reference(hr^);
  430. hr^.offset:=tvarsym(regvarinfo^.regvars[i])^.address+procinfo^.para_offset;
  431. hr^.base:=procinfo^.framepointer;
  432. {$ifdef i386}
  433. asml.concat(Taicpu,op_ref_reg(A_MOV,regsize(regvarinfo^.regvars[i].reg),
  434. hr,regvarinfo^.regvars[i].reg)));
  435. {$endif i386}
  436. {$ifdef m68k}
  437. asml.concat(Taicpu,op_ref_reg(A_MOVE,regsize(regvarinfo^.regvars[i].reg),
  438. hr,regvarinfo^.regvars[i].reg)));
  439. {$endif m68k}
  440. end;
  441. {$endif dummy}
  442. end;
  443. end;
  444. if assigned(p) then
  445. if cs_asm_source in aktglobalswitches then
  446. asml.insert(Tai_asm_comment.Create(strpnew(tostr(p.registersfpu)+
  447. ' registers on FPU stack used by temp. expressions')));
  448. for i:=1 to maxfpuvarregs do
  449. begin
  450. if assigned(regvarinfo^.fpuregvars[i]) then
  451. begin
  452. if cs_asm_source in aktglobalswitches then
  453. asml.insert(Tai_asm_comment.Create(strpnew(regvarinfo^.fpuregvars[i].name+
  454. ' with weight '+tostr(regvarinfo^.fpuregvars[i].refs)+' assigned to register '+
  455. reg2str(regvarinfo^.fpuregvars[i].reg))));
  456. if (status.verbosity and v_debug)=v_debug then
  457. Message3(cg_d_register_weight,reg2str(regvarinfo^.fpuregvars[i].reg),
  458. tostr(regvarinfo^.fpuregvars[i].refs),regvarinfo^.fpuregvars[i].name);
  459. end;
  460. end;
  461. if cs_asm_source in aktglobalswitches then
  462. asml.insert(Tai_asm_comment.Create(strpnew('Register variable assignment:')));
  463. end;
  464. end;
  465. procedure cleanup_regvars(asml: TAAsmoutput);
  466. var
  467. i: longint;
  468. begin
  469. {$ifdef i386}
  470. { can happen when inlining assembler procedures (JM) }
  471. if not assigned(aktprocsym.definition.regvarinfo) then
  472. exit;
  473. if (cs_regalloc in aktglobalswitches) and
  474. ((procinfo^.flags and (pi_uses_asm or pi_uses_exceptions))=0) then
  475. with pregvarinfo(aktprocsym.definition.regvarinfo)^ do
  476. begin
  477. for i:=1 to maxfpuvarregs do
  478. if assigned(fpuregvars[i]) then
  479. { ... and clean it up }
  480. asml.concat(Taicpu.op_reg(A_FSTP,S_NO,R_ST0));
  481. for i := 1 to maxvarregs do
  482. if assigned(regvars[i]) and
  483. (regvar_loaded[reg32(regvars[i].reg)]) then
  484. asml.concat(Tairegalloc.dealloc(reg32(regvars[i].reg)));
  485. end;
  486. {$endif i386}
  487. end;
  488. end.
  489. {
  490. $Log$
  491. Revision 1.18 2001-08-26 13:36:49 florian
  492. * some cg reorganisation
  493. * some PPC updates
  494. Revision 1.17 2001/04/21 12:03:12 peter
  495. * m68k updates merged from fixes branch
  496. Revision 1.16 2001/04/13 01:22:13 peter
  497. * symtable change to classes
  498. * range check generation and errors fixed, make cycle DEBUG=1 works
  499. * memory leaks fixed
  500. Revision 1.15 2000/12/25 00:07:28 peter
  501. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  502. tlinkedlist objects)
  503. Revision 1.14 2000/12/05 11:44:32 jonas
  504. + new integer regvar handling, should be much more efficient
  505. Revision 1.13 2000/11/29 00:30:39 florian
  506. * unused units removed from uses clause
  507. * some changes for widestrings
  508. Revision 1.12 2000/11/04 14:25:21 florian
  509. + merged Attila's changes for interfaces, not tested yet
  510. Revision 1.11 2000/10/31 22:02:51 peter
  511. * symtable splitted, no real code changes
  512. Revision 1.10 2000/10/14 10:14:52 peter
  513. * moehrendorf oct 2000 rewrite
  514. Revision 1.9 2000/10/01 19:48:25 peter
  515. * lot of compile updates for cg11
  516. Revision 1.8 2000/09/30 16:08:45 peter
  517. * more cg11 updates
  518. Revision 1.7 2000/09/30 13:08:16 jonas
  519. * regvars are now zeroed at the start of their life if they contain an 8
  520. or 16bit var/parameter, because the full 32bits are used if they are
  521. necessary for a btrl instruction
  522. Revision 1.6 2000/09/24 15:06:27 peter
  523. * use defines.inc
  524. Revision 1.5 2000/08/27 16:11:52 peter
  525. * moved some util functions from globals,cobjects to cutils
  526. * splitted files into finput,fmodule
  527. Revision 1.4 2000/08/17 11:07:51 jonas
  528. * fixed crash when inlining assembler procedures with -Or
  529. Revision 1.3 2000/08/04 05:52:00 jonas
  530. * correct version (I also had a regvars.pp locally, which was used
  531. instead of the regvars.pas on CVS, so I didn't notice the errors :( )
  532. Revision 1.2 2000/08/03 14:36:47 jonas
  533. * fixed inserting of allocated register for regvars (only those for
  534. parameters were done, and sometimes even the wrong ones)
  535. Revision 1.1 2000/08/03 13:17:25 jonas
  536. + allow regvars to be used inside inlined procs, which required the
  537. following changes:
  538. + load regvars in genentrycode/free them in genexitcode (cgai386)
  539. * moved all regvar related code to new regvars unit
  540. + added pregvarinfo type to hcodegen
  541. + added regvarinfo field to tprocinfo (symdef/symdefh)
  542. * deallocate the regvars of the caller in secondprocinline before
  543. inlining the called procedure and reallocate them afterwards
  544. }