tgobj.pas 24 KB

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