tgobj.pas 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. This unit implements the base object for temp. generator
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. {#@abstract(Temporary reference allocator unit)
  18. Temporary reference allocator unit. This unit contains
  19. all which is related to allocating temporary memory
  20. space on the stack, as required, by the code generator.
  21. }
  22. unit tgobj;
  23. {$i fpcdefs.inc}
  24. interface
  25. uses
  26. cclasses,
  27. globals,globtype,
  28. symtype,
  29. cpubase,cpuinfo,cgbase,cgutils,
  30. aasmbase,aasmtai,aasmdata;
  31. type
  32. ptemprecord = ^ttemprecord;
  33. ttemprecord = record
  34. temptype : ttemptype;
  35. pos : longint;
  36. size : longint;
  37. def : tdef;
  38. next : ptemprecord;
  39. nextfree : ptemprecord; { for faster freeblock checking }
  40. {$ifdef EXTDEBUG}
  41. posinfo,
  42. releaseposinfo : tfileposinfo;
  43. {$endif}
  44. end;
  45. {# Generates temporary variables }
  46. ttgobj = class
  47. private
  48. { contains all free temps using nextfree links }
  49. tempfreelist : ptemprecord;
  50. function alloctemp(list: TAsmList; size,alignment : longint; temptype : ttemptype; def:tdef) : longint;
  51. procedure freetemp(list: TAsmList; pos:longint;temptypes:ttemptypeset);
  52. public
  53. { contains all temps }
  54. templist : ptemprecord;
  55. { Offsets of the first/last temp }
  56. firsttemp,
  57. lasttemp : longint;
  58. direction : shortint;
  59. constructor create;
  60. {# Clear and free the complete linked list of temporary memory
  61. locations. The list is set to nil.}
  62. procedure resettempgen;
  63. {# Sets the first offset from the frame pointer or stack pointer where
  64. the temporary references will be allocated. It is to note that this
  65. value should always be negative.
  66. @param(l start offset where temps will start in stack)
  67. }
  68. procedure setfirsttemp(l : longint);
  69. procedure gettemp(list: TAsmList; size : longint;temptype:ttemptype;out ref : treference);
  70. procedure gettemptyped(list: TAsmList; def:tdef;temptype:ttemptype;out ref : treference);
  71. procedure ungettemp(list: TAsmList; const ref : treference);
  72. function sizeoftemp(list: TAsmList; const ref: treference): longint;
  73. function changetemptype(list: TAsmList; const ref:treference;temptype:ttemptype):boolean;
  74. function gettypeoftemp(const ref:treference): ttemptype;
  75. {# Returns TRUE if the reference ref is allocated in temporary volatile memory space,
  76. otherwise returns FALSE.
  77. @param(ref reference to verify)
  78. }
  79. function istemp(const ref : treference) : boolean;
  80. {# Frees a reference @var(ref) which was allocated in the volatile temporary memory space.
  81. The freed space can later be reallocated and reused. If this reference
  82. is not in the temporary memory, it is simply not freed.
  83. }
  84. procedure ungetiftemp(list: TAsmList; const ref : treference);
  85. { Allocate space for a local }
  86. procedure getlocal(list: TAsmList; size : longint;def:tdef;var ref : treference);
  87. procedure getlocal(list: TAsmList; size : longint; alignment : shortint; def:tdef;var ref : treference);
  88. procedure UnGetLocal(list: TAsmList; const ref : treference);
  89. end;
  90. var
  91. tg: ttgobj;
  92. procedure location_freetemp(list:TAsmList; const l : tlocation);
  93. implementation
  94. uses
  95. cutils,
  96. systems,verbose,
  97. procinfo
  98. ;
  99. const
  100. FreeTempTypes = [tt_free,tt_freenoreuse];
  101. {$ifdef EXTDEBUG}
  102. TempTypeStr : array[ttemptype] of string[18] = (
  103. '<none>',
  104. 'free','normal','persistant',
  105. 'noreuse','freenoreuse'
  106. );
  107. {$endif EXTDEBUG}
  108. Used2Free : array[ttemptype] of ttemptype = (
  109. tt_none,
  110. tt_none,tt_free,tt_free,
  111. tt_freenoreuse,tt_none
  112. );
  113. {*****************************************************************************
  114. Helpers
  115. *****************************************************************************}
  116. procedure location_freetemp(list:TAsmList; const l : tlocation);
  117. begin
  118. if (l.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  119. tg.ungetiftemp(list,l.reference);
  120. end;
  121. {*****************************************************************************
  122. TTGOBJ
  123. *****************************************************************************}
  124. constructor ttgobj.create;
  125. begin
  126. tempfreelist:=nil;
  127. templist:=nil;
  128. { we could create a new child class for this but I don't if it is worth the effort (FK) }
  129. {$ifdef powerpc}
  130. direction:=1;
  131. {$else powerpc}
  132. {$ifdef POWERPC64}
  133. direction:=1;
  134. {$else POWERPC64}
  135. direction:=-1;
  136. {$endif POWERPC64}
  137. {$endif powerpc}
  138. end;
  139. procedure ttgobj.resettempgen;
  140. var
  141. hp : ptemprecord;
  142. begin
  143. { Clear the old templist }
  144. while assigned(templist) do
  145. begin
  146. {$ifdef EXTDEBUG}
  147. if not(templist^.temptype in FreeTempTypes) then
  148. begin
  149. Comment(V_Warning,'tgobj: (ResetTempgen) temp at pos '+tostr(templist^.pos)+
  150. ' with size '+tostr(templist^.size)+' and type '+TempTypeStr[templist^.temptype]+
  151. ' from pos '+tostr(templist^.posinfo.line)+':'+tostr(templist^.posinfo.column)+
  152. ' not freed at the end of the procedure');
  153. end;
  154. {$endif EXTDEBUG}
  155. hp:=templist;
  156. templist:=hp^.next;
  157. dispose(hp);
  158. end;
  159. templist:=nil;
  160. tempfreelist:=nil;
  161. firsttemp:=0;
  162. lasttemp:=0;
  163. end;
  164. procedure ttgobj.setfirsttemp(l : longint);
  165. begin
  166. { this is a negative value normally }
  167. if l*direction>=0 then
  168. begin
  169. if odd(l) then
  170. inc(l,direction);
  171. end
  172. else
  173. internalerror(200204221);
  174. firsttemp:=l;
  175. lasttemp:=l;
  176. end;
  177. function ttgobj.AllocTemp(list: TAsmList; size,alignment : longint; temptype : ttemptype;def : tdef) : longint;
  178. var
  179. tl,htl,
  180. bestslot,bestprev,
  181. hprev,hp : ptemprecord;
  182. freetype : ttemptype;
  183. bestatend,
  184. fitatbegin,
  185. fitatend : boolean;
  186. begin
  187. AllocTemp:=0;
  188. bestprev:=nil;
  189. bestslot:=nil;
  190. tl:=nil;
  191. bestatend:=false;
  192. if size=0 then
  193. begin
  194. {$ifdef EXTDEBUG}
  195. Comment(V_Warning,'tgobj: (AllocTemp) temp of size 0 requested, allocating 4 bytes');
  196. {$endif}
  197. size:=4;
  198. end;
  199. freetype:=Used2Free[temptype];
  200. if freetype=tt_none then
  201. internalerror(200208201);
  202. size:=align(size,alignment);
  203. { First check the tmpfreelist, but not when
  204. we don't want to reuse an already allocated block }
  205. if assigned(tempfreelist) and
  206. (temptype<>tt_noreuse) then
  207. begin
  208. hprev:=nil;
  209. hp:=tempfreelist;
  210. while assigned(hp) do
  211. begin
  212. {$ifdef EXTDEBUG}
  213. if not(hp^.temptype in FreeTempTypes) then
  214. Comment(V_Warning,'tgobj: (AllocTemp) temp at pos '+tostr(hp^.pos)+ ' in freelist is not set to tt_free !');
  215. {$endif}
  216. { Check only slots that are
  217. - free
  218. - share the same type
  219. - contain enough space
  220. - has a correct alignment }
  221. if (hp^.temptype=freetype) and
  222. (hp^.def=def) and
  223. (hp^.size>=size) and
  224. ((hp^.pos=align(hp^.pos,alignment)) or
  225. (hp^.pos+hp^.size-size = align(hp^.pos+hp^.size-size,alignment))) then
  226. begin
  227. { Slot is the same size then leave immediatly }
  228. if (hp^.size=size) then
  229. begin
  230. bestprev:=hprev;
  231. bestslot:=hp;
  232. break;
  233. end
  234. else
  235. begin
  236. { we can fit a smaller block either at the begin or at }
  237. { the end of a block. For direction=-1 we prefer the }
  238. { end, for direction=1 we prefer the begin (i.e., }
  239. { always closest to the source). We also try to use }
  240. { the block with the worst possible alignment that }
  241. { still suffices. And we pick the block which will }
  242. { have the best alignmenment after this new block is }
  243. { substracted from it. }
  244. fitatend:=(hp^.pos+hp^.size-size)=align(hp^.pos+hp^.size-size,alignment);
  245. fitatbegin:=hp^.pos=align(hp^.pos,alignment);
  246. if assigned(bestslot) then
  247. begin
  248. fitatend:=fitatend and
  249. ((not bestatend and
  250. (direction=-1)) or
  251. (bestatend and
  252. isbetteralignedthan(abs(bestslot^.pos+hp^.size-size),abs(hp^.pos+hp^.size-size),current_settings.alignment.localalignmax)));
  253. fitatbegin:=fitatbegin and
  254. (not bestatend or
  255. (direction=1)) and
  256. isbetteralignedthan(abs(hp^.pos+size),abs(bestslot^.pos+size),current_settings.alignment.localalignmax);
  257. end;
  258. if fitatend and
  259. fitatbegin then
  260. if isbetteralignedthan(abs(hp^.pos+hp^.size-size),abs(hp^.pos+size),current_settings.alignment.localalignmax) then
  261. fitatbegin:=false
  262. else if isbetteralignedthan(abs(hp^.pos+size),abs(hp^.pos+hp^.size-size),current_settings.alignment.localalignmax) then
  263. fitatend:=false
  264. else if (direction=1) then
  265. fitatend:=false
  266. else
  267. fitatbegin:=false;
  268. if fitatend or
  269. fitatbegin then
  270. begin
  271. bestprev:=hprev;
  272. bestslot:=hp;
  273. bestatend:=fitatend;
  274. end;
  275. end;
  276. end;
  277. hprev:=hp;
  278. hp:=hp^.nextfree;
  279. end;
  280. end;
  281. { Reuse an old temp ? }
  282. if assigned(bestslot) then
  283. begin
  284. if bestslot^.size=size then
  285. begin
  286. tl:=bestslot;
  287. { Remove from the tempfreelist }
  288. if assigned(bestprev) then
  289. bestprev^.nextfree:=tl^.nextfree
  290. else
  291. tempfreelist:=tl^.nextfree;
  292. end
  293. else
  294. begin
  295. { Duplicate bestlost and the block in the list }
  296. new(tl);
  297. move(bestslot^,tl^,sizeof(ttemprecord));
  298. tl^.next:=bestslot^.next;
  299. bestslot^.next:=tl;
  300. { Now we split the block in 2 parts. Depending on the direction
  301. we need to resize the newly inserted block or the old reused block.
  302. For direction=1 we can use tl for the new block. For direction=-1 we
  303. will be reusing bestslot and resize the new block, that means we need
  304. to swap the pointers }
  305. if (direction=-1) xor
  306. bestatend then
  307. begin
  308. htl:=tl;
  309. tl:=bestslot;
  310. bestslot:=htl;
  311. { Update the tempfreelist to point to the new block }
  312. if assigned(bestprev) then
  313. bestprev^.nextfree:=bestslot
  314. else
  315. tempfreelist:=bestslot;
  316. end;
  317. if not bestatend then
  318. inc(bestslot^.pos,size)
  319. else
  320. inc(tl^.pos,tl^.size-size);
  321. { Create new block and resize the old block }
  322. tl^.size:=size;
  323. tl^.nextfree:=nil;
  324. { Resize the old block }
  325. dec(bestslot^.size,size);
  326. end;
  327. tl^.temptype:=temptype;
  328. tl^.def:=def;
  329. tl^.nextfree:=nil;
  330. end
  331. else
  332. begin
  333. { now we can create the templist entry }
  334. new(tl);
  335. tl^.temptype:=temptype;
  336. tl^.def:=def;
  337. { Extend the temp }
  338. if direction=-1 then
  339. begin
  340. lasttemp:=(-align(-lasttemp,alignment))-size;
  341. tl^.pos:=lasttemp;
  342. end
  343. else
  344. begin
  345. tl^.pos:=align(lasttemp,alignment);
  346. lasttemp:=tl^.pos+size;
  347. end;
  348. tl^.size:=size;
  349. tl^.next:=templist;
  350. tl^.nextfree:=nil;
  351. templist:=tl;
  352. end;
  353. {$ifdef EXTDEBUG}
  354. tl^.posinfo:=current_filepos;
  355. if assigned(tl^.def) then
  356. list.concat(tai_tempalloc.allocinfo(tl^.pos,tl^.size,'allocated with type '+TempTypeStr[tl^.temptype]+' for def '+tl^.def.typename))
  357. else
  358. list.concat(tai_tempalloc.allocinfo(tl^.pos,tl^.size,'allocated with type '+TempTypeStr[tl^.temptype]));
  359. {$else}
  360. list.concat(tai_tempalloc.alloc(tl^.pos,tl^.size));
  361. {$endif}
  362. AllocTemp:=tl^.pos;
  363. end;
  364. procedure ttgobj.FreeTemp(list: TAsmList; pos:longint;temptypes:ttemptypeset);
  365. var
  366. hp,hnext,hprev,hprevfree : ptemprecord;
  367. begin
  368. hp:=templist;
  369. hprev:=nil;
  370. hprevfree:=nil;
  371. while assigned(hp) do
  372. begin
  373. if (hp^.pos=pos) then
  374. begin
  375. { check if already freed }
  376. if hp^.temptype in FreeTempTypes then
  377. begin
  378. {$ifdef EXTDEBUG}
  379. Comment(V_Warning,'tgobj: (FreeTemp) temp at pos '+tostr(pos)+ ' is already free !');
  380. list.concat(tai_tempalloc.allocinfo(hp^.pos,hp^.size,'temp is already freed'));
  381. {$endif}
  382. exit;
  383. end;
  384. { check type that are allowed to be released }
  385. if not(hp^.temptype in temptypes) then
  386. begin
  387. {$ifdef EXTDEBUG}
  388. Comment(V_Debug,'tgobj: (Freetemp) temp at pos '+tostr(pos)+ ' has different type ('+TempTypeStr[hp^.temptype]+'), not releasing');
  389. list.concat(tai_tempalloc.allocinfo(hp^.pos,hp^.size,'temp has wrong type ('+TempTypeStr[hp^.temptype]+') not releasing'));
  390. {$endif}
  391. exit;
  392. end;
  393. list.concat(tai_tempalloc.dealloc(hp^.pos,hp^.size));
  394. { set this block to free }
  395. hp^.temptype:=Used2Free[hp^.temptype];
  396. { Update tempfreelist }
  397. if assigned(hprevfree) then
  398. begin
  399. { Concat blocks when the previous block is free and
  400. there is no block assigned for a tdef }
  401. if assigned(hprev) and
  402. (hp^.temptype=tt_free) and
  403. not assigned(hp^.def) and
  404. (hprev^.temptype=tt_free) and
  405. not assigned(hprev^.def) then
  406. begin
  407. inc(hprev^.size,hp^.size);
  408. if direction=1 then
  409. hprev^.pos:=hp^.pos;
  410. hprev^.next:=hp^.next;
  411. dispose(hp);
  412. hp:=hprev;
  413. end
  414. else
  415. hprevfree^.nextfree:=hp;
  416. end
  417. else
  418. begin
  419. hp^.nextfree:=tempfreelist;
  420. tempfreelist:=hp;
  421. end;
  422. { Concat blocks when the next block is free and
  423. there is no block assigned for a tdef }
  424. hnext:=hp^.next;
  425. if assigned(hnext) and
  426. (hp^.temptype=tt_free) and
  427. not assigned(hp^.def) and
  428. (hnext^.temptype=tt_free) and
  429. not assigned(hnext^.def) then
  430. begin
  431. inc(hp^.size,hnext^.size);
  432. if direction=1 then
  433. hp^.pos:=hnext^.pos;
  434. hp^.nextfree:=hnext^.nextfree;
  435. hp^.next:=hnext^.next;
  436. dispose(hnext);
  437. end;
  438. { Stop }
  439. exit;
  440. end;
  441. if (hp^.temptype=tt_free) then
  442. hprevfree:=hp;
  443. hprev:=hp;
  444. hp:=hp^.next;
  445. end;
  446. end;
  447. procedure ttgobj.gettemp(list: TAsmList; size : longint;temptype:ttemptype;out ref : treference);
  448. var
  449. varalign : shortint;
  450. begin
  451. varalign:=size_2_align(size);
  452. varalign:=used_align(varalign,current_settings.alignment.localalignmin,current_settings.alignment.localalignmax);
  453. { can't use reference_reset_base, because that will let tgobj depend
  454. on cgobj (PFV) }
  455. fillchar(ref,sizeof(ref),0);
  456. ref.base:=current_procinfo.framepointer;
  457. ref.offset:=alloctemp(list,size,varalign,temptype,nil);
  458. end;
  459. procedure ttgobj.gettemptyped(list: TAsmList; def:tdef;temptype:ttemptype;out ref : treference);
  460. var
  461. varalign : shortint;
  462. begin
  463. varalign:=def.alignment;
  464. varalign:=used_align(varalign,current_settings.alignment.localalignmin,current_settings.alignment.localalignmax);
  465. { can't use reference_reset_base, because that will let tgobj depend
  466. on cgobj (PFV) }
  467. fillchar(ref,sizeof(ref),0);
  468. ref.base:=current_procinfo.framepointer;
  469. ref.offset:=alloctemp(list,def.size,varalign,temptype,def);
  470. end;
  471. function ttgobj.istemp(const ref : treference) : boolean;
  472. begin
  473. { ref.index = R_NO was missing
  474. led to problems with local arrays
  475. with lower bound > 0 (PM) }
  476. if direction = 1 then
  477. begin
  478. istemp:=(ref.base=current_procinfo.framepointer) and
  479. (ref.index=NR_NO) and
  480. (ref.offset>=firsttemp);
  481. end
  482. else
  483. begin
  484. istemp:=(ref.base=current_procinfo.framepointer) and
  485. (ref.index=NR_NO) and
  486. (ref.offset<firsttemp);
  487. end;
  488. end;
  489. function ttgobj.sizeoftemp(list: TAsmList; const ref: treference): longint;
  490. var
  491. hp : ptemprecord;
  492. begin
  493. SizeOfTemp := -1;
  494. hp:=templist;
  495. while assigned(hp) do
  496. begin
  497. if (hp^.pos=ref.offset) then
  498. begin
  499. sizeoftemp := hp^.size;
  500. exit;
  501. end;
  502. hp := hp^.next;
  503. end;
  504. {$ifdef EXTDEBUG}
  505. comment(v_debug,'tgobj: (SizeOfTemp) temp at pos '+tostr(ref.offset)+' not found !');
  506. list.concat(tai_tempalloc.allocinfo(ref.offset,0,'temp not found'));
  507. {$endif}
  508. end;
  509. function ttgobj.changetemptype(list: tasmList; const ref:treference; temptype:ttemptype):boolean;
  510. var
  511. hp : ptemprecord;
  512. begin
  513. ChangeTempType:=false;
  514. hp:=templist;
  515. while assigned(hp) do
  516. begin
  517. if (hp^.pos=ref.offset) then
  518. begin
  519. if hp^.temptype<>tt_free then
  520. begin
  521. {$ifdef EXTDEBUG}
  522. if hp^.temptype=temptype then
  523. Comment(V_Warning,'tgobj: (ChangeTempType) temp'+
  524. ' at pos '+tostr(ref.offset)+ ' is already of the correct type !');
  525. list.concat(tai_tempalloc.allocinfo(hp^.pos,hp^.size,'type changed to '+TempTypeStr[temptype]));
  526. {$endif}
  527. ChangeTempType:=true;
  528. hp^.temptype:=temptype;
  529. end
  530. else
  531. begin
  532. {$ifdef EXTDEBUG}
  533. Comment(V_Warning,'tgobj: (ChangeTempType) temp'+
  534. ' at pos '+tostr(ref.offset)+ ' is already freed !');
  535. list.concat(tai_tempalloc.allocinfo(hp^.pos,hp^.size,'temp is already freed'));
  536. {$endif}
  537. end;
  538. exit;
  539. end;
  540. hp:=hp^.next;
  541. end;
  542. {$ifdef EXTDEBUG}
  543. Comment(V_Warning,'tgobj: (ChangeTempType) temp'+
  544. ' at pos '+tostr(ref.offset)+ ' not found !');
  545. list.concat(tai_tempalloc.allocinfo(ref.offset,0,'temp not found'));
  546. {$endif}
  547. end;
  548. function ttgobj.gettypeoftemp(const ref:treference): ttemptype;
  549. var
  550. hp : ptemprecord;
  551. begin
  552. hp:=templist;
  553. while assigned(hp) do
  554. begin
  555. if (hp^.pos=ref.offset) then
  556. begin
  557. if hp^.temptype<>tt_free then
  558. result:=hp^.temptype
  559. else
  560. internalerror(2007020810);
  561. exit;
  562. end;
  563. hp:=hp^.next;
  564. end;
  565. result:=tt_none;
  566. end;
  567. procedure ttgobj.UnGetTemp(list: TAsmList; const ref : treference);
  568. begin
  569. FreeTemp(list,ref.offset,[tt_normal,tt_noreuse,tt_persistent]);
  570. end;
  571. procedure ttgobj.UnGetIfTemp(list: TAsmList; const ref : treference);
  572. begin
  573. if istemp(ref) then
  574. FreeTemp(list,ref.offset,[tt_normal]);
  575. end;
  576. procedure ttgobj.getlocal(list: TAsmList; size : longint;def:tdef;var ref : treference);
  577. begin
  578. getlocal(list, size, def.alignment, def, ref);
  579. end;
  580. procedure ttgobj.getlocal(list: TAsmList; size : longint; alignment : shortint; def:tdef;var ref : treference);
  581. begin
  582. alignment:=used_align(alignment,current_settings.alignment.localalignmin,current_settings.alignment.localalignmax);
  583. { can't use reference_reset_base, because that will let tgobj depend
  584. on cgobj (PFV) }
  585. fillchar(ref,sizeof(ref),0);
  586. ref.base:=current_procinfo.framepointer;
  587. ref.offset:=alloctemp(list,size,alignment,tt_persistent,nil);
  588. end;
  589. procedure ttgobj.UnGetLocal(list: TAsmList; const ref : treference);
  590. begin
  591. FreeTemp(list,ref.offset,[tt_persistent]);
  592. end;
  593. end.