tgobj.pas 24 KB

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