tgobj.pas 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665
  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. protected
  48. { contains all free temps using nextfree links }
  49. tempfreelist : ptemprecord;
  50. function alloctemp(list: TAsmList; size,alignment : longint; temptype : ttemptype; def:tdef) : longint; virtual;
  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;virtual;reintroduce;
  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, alignment : 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. ttgobjclass = class of ttgobj;
  91. var
  92. tg: ttgobj;
  93. tgobjclass: ttgobjclass = ttgobj;
  94. procedure location_freetemp(list:TAsmList; const l : tlocation);
  95. implementation
  96. uses
  97. cutils,
  98. systems,verbose,
  99. procinfo,
  100. symconst
  101. ;
  102. const
  103. FreeTempTypes = [tt_free,tt_freenoreuse];
  104. {$ifdef EXTDEBUG}
  105. TempTypeStr : array[ttemptype] of string[18] = (
  106. '<none>',
  107. 'free','normal','persistant',
  108. 'noreuse','freenoreuse'
  109. );
  110. {$endif EXTDEBUG}
  111. Used2Free : array[ttemptype] of ttemptype = (
  112. tt_none,
  113. tt_none,tt_free,tt_free,
  114. tt_freenoreuse,tt_none
  115. );
  116. {*****************************************************************************
  117. Helpers
  118. *****************************************************************************}
  119. procedure location_freetemp(list:TAsmList; const l : tlocation);
  120. begin
  121. if (l.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  122. tg.ungetiftemp(list,l.reference);
  123. end;
  124. {*****************************************************************************
  125. TTGOBJ
  126. *****************************************************************************}
  127. constructor ttgobj.create;
  128. begin
  129. tempfreelist:=nil;
  130. templist:=nil;
  131. { we could create a new child class for this but I don't if it is worth the effort (FK) }
  132. {$if defined(powerpc) or defined(powerpc64) or defined(avr)}
  133. direction:=1;
  134. {$else}
  135. direction:=-1;
  136. {$endif}
  137. end;
  138. procedure ttgobj.resettempgen;
  139. var
  140. hp : ptemprecord;
  141. begin
  142. { Clear the old templist }
  143. while assigned(templist) do
  144. begin
  145. {$ifdef EXTDEBUG}
  146. if not(templist^.temptype in FreeTempTypes) then
  147. begin
  148. Comment(V_Warning,'tgobj: (ResetTempgen) temp at pos '+tostr(templist^.pos)+
  149. ' with size '+tostr(templist^.size)+' and type '+TempTypeStr[templist^.temptype]+
  150. ' from pos '+tostr(templist^.posinfo.line)+':'+tostr(templist^.posinfo.column)+
  151. ' not freed at the end of the procedure');
  152. end;
  153. {$endif EXTDEBUG}
  154. hp:=templist;
  155. templist:=hp^.next;
  156. dispose(hp);
  157. end;
  158. templist:=nil;
  159. tempfreelist:=nil;
  160. firsttemp:=0;
  161. lasttemp:=0;
  162. end;
  163. procedure ttgobj.setfirsttemp(l : longint);
  164. begin
  165. { this is a negative value normally }
  166. if l*direction>=0 then
  167. begin
  168. if odd(l) then
  169. inc(l,direction);
  170. end
  171. else
  172. internalerror(200204221);
  173. firsttemp:=l;
  174. lasttemp:=l;
  175. end;
  176. function ttgobj.AllocTemp(list: TAsmList; size,alignment : longint; temptype : ttemptype;def : tdef) : longint;
  177. var
  178. tl,htl,
  179. bestslot,bestprev,
  180. hprev,hp : ptemprecord;
  181. freetype : ttemptype;
  182. bestatend,
  183. fitatbegin,
  184. fitatend : boolean;
  185. begin
  186. AllocTemp:=0;
  187. bestprev:=nil;
  188. bestslot:=nil;
  189. tl:=nil;
  190. bestatend:=false;
  191. if size=0 then
  192. begin
  193. {$ifdef EXTDEBUG}
  194. Comment(V_Warning,'tgobj: (AllocTemp) temp of size 0 requested, allocating 4 bytes');
  195. {$endif}
  196. size:=4;
  197. end;
  198. freetype:=Used2Free[temptype];
  199. if freetype=tt_none then
  200. internalerror(200208201);
  201. size:=align(size,alignment);
  202. { First check the tmpfreelist, but not when
  203. we don't want to reuse an already allocated block }
  204. if assigned(tempfreelist) and
  205. (temptype<>tt_noreuse) then
  206. begin
  207. hprev:=nil;
  208. hp:=tempfreelist;
  209. while assigned(hp) do
  210. begin
  211. {$ifdef EXTDEBUG}
  212. if not(hp^.temptype in FreeTempTypes) then
  213. Comment(V_Warning,'tgobj: (AllocTemp) temp at pos '+tostr(hp^.pos)+ ' in freelist is not set to tt_free !');
  214. {$endif}
  215. { Check only slots that are
  216. - free
  217. - share the same type
  218. - contain enough space
  219. - has a correct alignment }
  220. if (hp^.temptype=freetype) and
  221. (hp^.def=def) and
  222. (hp^.size>=size) and
  223. ((hp^.pos=align(hp^.pos,alignment)) or
  224. (hp^.pos+hp^.size-size = align(hp^.pos+hp^.size-size,alignment))) then
  225. begin
  226. { Slot is the same size then leave immediatly }
  227. if (hp^.size=size) then
  228. begin
  229. bestprev:=hprev;
  230. bestslot:=hp;
  231. break;
  232. end
  233. else
  234. begin
  235. { we can fit a smaller block either at the begin or at }
  236. { the end of a block. For direction=-1 we prefer the }
  237. { end, for direction=1 we prefer the begin (i.e., }
  238. { always closest to the source). We also try to use }
  239. { the block with the worst possible alignment that }
  240. { still suffices. And we pick the block which will }
  241. { have the best alignmenment after this new block is }
  242. { substracted from it. }
  243. fitatend:=(hp^.pos+hp^.size-size)=align(hp^.pos+hp^.size-size,alignment);
  244. fitatbegin:=hp^.pos=align(hp^.pos,alignment);
  245. if assigned(bestslot) then
  246. begin
  247. fitatend:=fitatend and
  248. ((not bestatend and
  249. (direction=-1)) or
  250. (bestatend and
  251. isbetteralignedthan(abs(bestslot^.pos+hp^.size-size),abs(hp^.pos+hp^.size-size),current_settings.alignment.localalignmax)));
  252. fitatbegin:=fitatbegin and
  253. (not bestatend or
  254. (direction=1)) and
  255. isbetteralignedthan(abs(hp^.pos+size),abs(bestslot^.pos+size),current_settings.alignment.localalignmax);
  256. end;
  257. if fitatend and
  258. fitatbegin then
  259. if isbetteralignedthan(abs(hp^.pos+hp^.size-size),abs(hp^.pos+size),current_settings.alignment.localalignmax) then
  260. fitatbegin:=false
  261. else if isbetteralignedthan(abs(hp^.pos+size),abs(hp^.pos+hp^.size-size),current_settings.alignment.localalignmax) then
  262. fitatend:=false
  263. else if (direction=1) then
  264. fitatend:=false
  265. else
  266. fitatbegin:=false;
  267. if fitatend or
  268. fitatbegin then
  269. begin
  270. bestprev:=hprev;
  271. bestslot:=hp;
  272. bestatend:=fitatend;
  273. end;
  274. end;
  275. end;
  276. hprev:=hp;
  277. hp:=hp^.nextfree;
  278. end;
  279. end;
  280. { Reuse an old temp ? }
  281. if assigned(bestslot) then
  282. begin
  283. if bestslot^.size=size then
  284. begin
  285. tl:=bestslot;
  286. { Remove from the tempfreelist }
  287. if assigned(bestprev) then
  288. bestprev^.nextfree:=tl^.nextfree
  289. else
  290. tempfreelist:=tl^.nextfree;
  291. end
  292. else
  293. begin
  294. { Duplicate bestlost and the block in the list }
  295. new(tl);
  296. move(bestslot^,tl^,sizeof(ttemprecord));
  297. tl^.next:=bestslot^.next;
  298. bestslot^.next:=tl;
  299. { Now we split the block in 2 parts. Depending on the direction
  300. we need to resize the newly inserted block or the old reused block.
  301. For direction=1 we can use tl for the new block. For direction=-1 we
  302. will be reusing bestslot and resize the new block, that means we need
  303. to swap the pointers }
  304. if (direction=-1) xor
  305. bestatend then
  306. begin
  307. htl:=tl;
  308. tl:=bestslot;
  309. bestslot:=htl;
  310. { Update the tempfreelist to point to the new block }
  311. if assigned(bestprev) then
  312. bestprev^.nextfree:=bestslot
  313. else
  314. tempfreelist:=bestslot;
  315. end;
  316. if not bestatend then
  317. inc(bestslot^.pos,size)
  318. else
  319. inc(tl^.pos,tl^.size-size);
  320. { Create new block and resize the old block }
  321. tl^.size:=size;
  322. tl^.nextfree:=nil;
  323. { Resize the old block }
  324. dec(bestslot^.size,size);
  325. end;
  326. tl^.temptype:=temptype;
  327. tl^.def:=def;
  328. tl^.nextfree:=nil;
  329. end
  330. else
  331. begin
  332. { now we can create the templist entry }
  333. new(tl);
  334. tl^.temptype:=temptype;
  335. tl^.def:=def;
  336. { Extend the temp }
  337. if direction=-1 then
  338. begin
  339. lasttemp:=(-align(-lasttemp,alignment))-size;
  340. tl^.pos:=lasttemp;
  341. end
  342. else
  343. begin
  344. tl^.pos:=align(lasttemp,alignment);
  345. lasttemp:=tl^.pos+size;
  346. end;
  347. tl^.size:=size;
  348. tl^.next:=templist;
  349. tl^.nextfree:=nil;
  350. templist:=tl;
  351. end;
  352. {$ifdef EXTDEBUG}
  353. tl^.posinfo:=current_filepos;
  354. if assigned(tl^.def) then
  355. list.concat(tai_tempalloc.allocinfo(tl^.pos,tl^.size,'allocated with type '+TempTypeStr[tl^.temptype]+' for def '+tl^.def.typename))
  356. else
  357. list.concat(tai_tempalloc.allocinfo(tl^.pos,tl^.size,'allocated with type '+TempTypeStr[tl^.temptype]));
  358. {$else}
  359. list.concat(tai_tempalloc.alloc(tl^.pos,tl^.size));
  360. {$endif}
  361. AllocTemp:=tl^.pos;
  362. end;
  363. procedure ttgobj.FreeTemp(list: TAsmList; pos:longint;temptypes:ttemptypeset);
  364. var
  365. hp,hnext,hprev,hprevfree : ptemprecord;
  366. begin
  367. hp:=templist;
  368. hprev:=nil;
  369. hprevfree:=nil;
  370. while assigned(hp) do
  371. begin
  372. if (hp^.pos=pos) then
  373. begin
  374. { check if already freed }
  375. if hp^.temptype in FreeTempTypes then
  376. begin
  377. {$ifdef EXTDEBUG}
  378. Comment(V_Warning,'tgobj: (FreeTemp) temp at pos '+tostr(pos)+ ' is already free !');
  379. list.concat(tai_tempalloc.allocinfo(hp^.pos,hp^.size,'temp is already freed'));
  380. {$endif}
  381. exit;
  382. end;
  383. { check type that are allowed to be released }
  384. if not(hp^.temptype in temptypes) then
  385. begin
  386. {$ifdef EXTDEBUG}
  387. Comment(V_Debug,'tgobj: (Freetemp) temp at pos '+tostr(pos)+ ' has different type ('+TempTypeStr[hp^.temptype]+'), not releasing');
  388. list.concat(tai_tempalloc.allocinfo(hp^.pos,hp^.size,'temp has wrong type ('+TempTypeStr[hp^.temptype]+') not releasing'));
  389. {$endif}
  390. exit;
  391. end;
  392. list.concat(tai_tempalloc.dealloc(hp^.pos,hp^.size));
  393. { set this block to free }
  394. hp^.temptype:=Used2Free[hp^.temptype];
  395. { Update tempfreelist }
  396. if assigned(hprevfree) then
  397. begin
  398. { Concat blocks when the previous block is free and
  399. there is no block assigned for a tdef }
  400. if assigned(hprev) and
  401. (hp^.temptype=tt_free) and
  402. not assigned(hp^.def) and
  403. (hprev^.temptype=tt_free) and
  404. not assigned(hprev^.def) then
  405. begin
  406. inc(hprev^.size,hp^.size);
  407. if direction=1 then
  408. hprev^.pos:=hp^.pos;
  409. hprev^.next:=hp^.next;
  410. dispose(hp);
  411. hp:=hprev;
  412. end
  413. else
  414. hprevfree^.nextfree:=hp;
  415. end
  416. else
  417. begin
  418. hp^.nextfree:=tempfreelist;
  419. tempfreelist:=hp;
  420. end;
  421. { Concat blocks when the next block is free and
  422. there is no block assigned for a tdef }
  423. hnext:=hp^.next;
  424. if assigned(hnext) and
  425. (hp^.temptype=tt_free) and
  426. not assigned(hp^.def) and
  427. (hnext^.temptype=tt_free) and
  428. not assigned(hnext^.def) then
  429. begin
  430. inc(hp^.size,hnext^.size);
  431. if direction=1 then
  432. hp^.pos:=hnext^.pos;
  433. hp^.nextfree:=hnext^.nextfree;
  434. hp^.next:=hnext^.next;
  435. dispose(hnext);
  436. end;
  437. { Stop }
  438. exit;
  439. end;
  440. if (hp^.temptype=tt_free) then
  441. hprevfree:=hp;
  442. hprev:=hp;
  443. hp:=hp^.next;
  444. end;
  445. end;
  446. procedure ttgobj.gettemp(list: TAsmList; size, alignment : longint;temptype:ttemptype;out ref : treference);
  447. var
  448. varalign : shortint;
  449. begin
  450. varalign:=used_align(alignment,current_settings.alignment.localalignmin,current_settings.alignment.localalignmax);
  451. { can't use reference_reset_base, because that will let tgobj depend
  452. on cgobj (PFV) }
  453. fillchar(ref,sizeof(ref),0);
  454. ref.base:=current_procinfo.framepointer;
  455. ref.offset:=alloctemp(list,size,varalign,temptype,nil);
  456. ref.alignment:=varalign;
  457. end;
  458. procedure ttgobj.gettemptyped(list: TAsmList; def:tdef;temptype:ttemptype;out ref : treference);
  459. var
  460. varalign : shortint;
  461. begin
  462. varalign:=def.alignment;
  463. varalign:=used_align(varalign,current_settings.alignment.localalignmin,current_settings.alignment.localalignmax);
  464. { can't use reference_reset_base, because that will let tgobj depend
  465. on cgobj (PFV) }
  466. fillchar(ref,sizeof(ref),0);
  467. ref.base:=current_procinfo.framepointer;
  468. ref.offset:=alloctemp(list,def.size,varalign,temptype,def);
  469. ref.alignment:=varalign;
  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. ref.alignment:=alignment;
  589. end;
  590. procedure ttgobj.UnGetLocal(list: TAsmList; const ref : treference);
  591. begin
  592. FreeTemp(list,ref.offset,[tt_persistent]);
  593. end;
  594. end.