ncgbas.pas 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778
  1. {
  2. Copyright (c) 2000-2002 by Florian Klaempfl
  3. This unit implements some basic nodes
  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. unit ncgbas;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,
  22. aasmtai,aasmdata,
  23. cpubase,cgutils,
  24. node,nbas;
  25. type
  26. tcgnothingnode = class(tnothingnode)
  27. procedure pass_generate_code;override;
  28. end;
  29. tcgasmnode = class(tasmnode)
  30. protected
  31. procedure ResolveRef(const filepos: tfileposinfo; var op:toper); virtual;
  32. public
  33. procedure pass_generate_code;override;
  34. end;
  35. tcgstatementnode = class(tstatementnode)
  36. procedure pass_generate_code;override;
  37. end;
  38. tcgblocknode = class(tblocknode)
  39. procedure pass_generate_code;override;
  40. end;
  41. tcgtempcreatenode = class(ttempcreatenode)
  42. procedure pass_generate_code;override;
  43. end;
  44. tcgtemprefnode = class(ttemprefnode)
  45. procedure pass_generate_code;override;
  46. { Changes the location of this temp to ref. Useful when assigning }
  47. { another temp to this one. The current location will be freed. }
  48. { Can only be called in pass 2 (since earlier, the temp location }
  49. { isn't known yet) }
  50. procedure changelocation(const ref: treference);
  51. end;
  52. tcgtempdeletenode = class(ttempdeletenode)
  53. procedure pass_generate_code;override;
  54. end;
  55. tcgfinalizetempsnode = class(tfinalizetempsnode)
  56. procedure pass_generate_code; override;
  57. end;
  58. implementation
  59. uses
  60. globals,
  61. cutils,verbose,
  62. aasmbase,aasmcpu,
  63. symsym,symconst,defutil,
  64. pass_2,ncgutil,
  65. cgbase,cgobj,hlcgobj,
  66. procinfo,
  67. cpuinfo,
  68. tgobj
  69. {$ifdef x86}
  70. ,cgx86
  71. {$endif x86}
  72. ;
  73. {*****************************************************************************
  74. TNOTHING
  75. *****************************************************************************}
  76. procedure tcgnothingnode.pass_generate_code;
  77. begin
  78. location_reset(location,LOC_VOID,OS_NO);
  79. { avoid an abstract rte }
  80. end;
  81. {*****************************************************************************
  82. TSTATEMENTNODE
  83. *****************************************************************************}
  84. procedure tcgstatementnode.pass_generate_code;
  85. var
  86. hp : tstatementnode;
  87. begin
  88. location_reset(location,LOC_VOID,OS_NO);
  89. hp:=self;
  90. while assigned(hp) do
  91. begin
  92. if assigned(hp.left) then
  93. begin
  94. secondpass(hp.left);
  95. { Compiler inserted blocks can return values }
  96. location_copy(hp.location,hp.left.location);
  97. end;
  98. hp:=tstatementnode(hp.right);
  99. end;
  100. end;
  101. {*****************************************************************************
  102. TASMNODE
  103. *****************************************************************************}
  104. procedure tcgasmnode.ResolveRef(const filepos: tfileposinfo; var op:toper);
  105. var
  106. sym : tabstractnormalvarsym;
  107. {$ifdef x86}
  108. segment : tregister;
  109. scale : byte;
  110. {$endif x86}
  111. forceref,
  112. getoffset : boolean;
  113. indexreg : tregister;
  114. sofs : longint;
  115. begin
  116. if (op.typ=top_local) then
  117. begin
  118. sofs:=op.localoper^.localsymofs;
  119. indexreg:=op.localoper^.localindexreg;
  120. {$ifdef x86}
  121. segment:=op.localoper^.localsegment;
  122. scale:=op.localoper^.localscale;
  123. {$endif x86}
  124. getoffset:=op.localoper^.localgetoffset;
  125. forceref:=op.localoper^.localforceref;
  126. sym:=tabstractnormalvarsym(pointer(op.localoper^.localsym));
  127. dispose(op.localoper);
  128. case sym.localloc.loc of
  129. LOC_REFERENCE :
  130. begin
  131. if getoffset then
  132. begin
  133. if (indexreg=NR_NO)
  134. {$ifdef x86}
  135. and (segment=NR_NO)
  136. {$endif x86}
  137. then
  138. begin
  139. op.typ:=top_const;
  140. op.val:=sym.localloc.reference.offset+sofs;
  141. end
  142. else
  143. begin
  144. op.typ:=top_ref;
  145. new(op.ref);
  146. reference_reset_base(op.ref^,indexreg,sym.localloc.reference.offset+sofs,
  147. sym.localloc.reference.temppos,newalignment(sym.localloc.reference.alignment,sofs),[]);
  148. {$ifdef x86}
  149. op.ref^.segment:=segment;
  150. {$endif x86}
  151. end;
  152. end
  153. else
  154. begin
  155. op.typ:=top_ref;
  156. new(op.ref);
  157. reference_reset_base(op.ref^,sym.localloc.reference.base,sym.localloc.reference.offset+sofs,
  158. sym.localloc.reference.temppos,newalignment(sym.localloc.reference.alignment,sofs),[]);
  159. op.ref^.index:=indexreg;
  160. {$ifdef x86}
  161. op.ref^.segment:=segment;
  162. op.ref^.scalefactor:=scale;
  163. {$endif x86}
  164. end;
  165. end;
  166. LOC_REGISTER :
  167. begin
  168. if getoffset then
  169. MessagePos(filepos,asmr_e_invalid_reference_syntax);
  170. { Subscribed access }
  171. if forceref or
  172. {$ifdef avr}
  173. (sofs>=tcgsize2size[sym.localloc.size])
  174. {$else avr}
  175. (sofs<>0)
  176. {$endif avr}
  177. then
  178. begin
  179. op.typ:=top_ref;
  180. new(op.ref);
  181. { no idea about the actual alignment }
  182. reference_reset_base(op.ref^,sym.localloc.register,sofs,ctempposinvalid,1,[]);
  183. op.ref^.index:=indexreg;
  184. {$ifdef x86}
  185. op.ref^.scalefactor:=scale;
  186. {$endif x86}
  187. end
  188. else
  189. begin
  190. op.typ:=top_reg;
  191. op.reg:=sym.localloc.register;
  192. {$ifdef x86}
  193. if reg2opsize(op.reg)<>TCGSize2Opsize[sym.localloc.size] then
  194. op.reg:=newreg(getregtype(op.reg),getsupreg(op.reg),cgsize2subreg(getregtype(op.reg),sym.localloc.size));
  195. {$endif x86}
  196. {$ifdef avr}
  197. case sofs of
  198. 1: op.reg:=cg.GetNextReg(op.reg);
  199. 2: op.reg:=cg.GetNextReg(cg.GetNextReg(op.reg));
  200. 3: op.reg:=cg.GetNextReg(cg.GetNextReg(cg.GetNextReg(op.reg)));
  201. end;
  202. {$endif avr}
  203. end;
  204. end;
  205. LOC_FPUREGISTER,
  206. LOC_MMXREGISTER,
  207. LOC_MMREGISTER :
  208. begin
  209. op.typ:=top_reg;
  210. op.reg:=NR_NO;
  211. if getoffset then
  212. MessagePos(filepos,asmr_e_invalid_reference_syntax);
  213. { Using an MM/FPU register in a reference is not possible }
  214. if forceref or (sofs<>0) then
  215. MessagePos1(filepos,asmr_e_invalid_ref_register,std_regname(sym.localloc.register))
  216. else
  217. op.reg:=sym.localloc.register;
  218. end;
  219. LOC_INVALID :
  220. begin
  221. { in "assembler; nostackframe;" routines, the
  222. funcret loc is set to LOC_INVALID in case the
  223. result is returned via a complex location
  224. (more than one register, ...) }
  225. if (vo_is_funcret in tabstractvarsym(sym).varoptions) then
  226. MessagePos(filepos,asmr_e_complex_function_result_location)
  227. else
  228. internalerror(2012082101);
  229. { recover }
  230. op.typ:=top_reg;
  231. op.reg:=NR_FUNCTION_RETURN_REG;
  232. end;
  233. else
  234. internalerror(201001031);
  235. end;
  236. end;
  237. end;
  238. procedure tcgasmnode.pass_generate_code;
  239. procedure ReLabel(var p:tasmsymbol);
  240. begin
  241. { Only relabel local tasmlabels }
  242. if (p.bind = AB_LOCAL) and
  243. (p is tasmlabel) then
  244. begin
  245. if not assigned(p.altsymbol) then
  246. current_asmdata.GenerateAltSymbol(p);
  247. p:=p.altsymbol;
  248. p.increfs;
  249. end;
  250. end;
  251. var
  252. hp,hp2 : tai;
  253. i : longint;
  254. vs : tabstractnormalvarsym;
  255. begin
  256. location_reset(location,LOC_VOID,OS_NO);
  257. if (nf_get_asm_position in flags) then
  258. begin
  259. { Add a marker, to be sure the list is not empty }
  260. current_asmdata.CurrAsmList.concat(tai_marker.create(mark_Position));
  261. currenttai:=tai(current_asmdata.CurrAsmList.last);
  262. exit;
  263. end;
  264. { Switch to the CPU instruction set, specified by the $ASMCPU directive }
  265. current_asmdata.CurrAsmList.Concat(tai_directive.create(asd_cpu,cputypestr[current_settings.asmcputype]));
  266. { Allocate registers used in the assembler block }
  267. { has_registerlist=true means that registers are specified and already allocated }
  268. if (not has_registerlist) then
  269. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  270. if (po_inline in current_procinfo.procdef.procoptions) then
  271. begin
  272. hp:=tai(p_asm.first);
  273. while assigned(hp) do
  274. begin
  275. hp2:=tai(hp.getcopy);
  276. case hp2.typ of
  277. ait_label :
  278. ReLabel(tasmsymbol(tai_label(hp2).labsym));
  279. ait_const :
  280. begin
  281. if assigned(tai_const(hp2).sym) then
  282. ReLabel(tai_const(hp2).sym);
  283. if assigned(tai_const(hp2).endsym) then
  284. ReLabel(tai_const(hp2).endsym);
  285. end;
  286. ait_instruction :
  287. begin
  288. { remove cached insentry, because the new code can
  289. require another less optimized instruction }
  290. {$ifdef i386}
  291. {$ifndef NOAG386BIN}
  292. taicpu(hp2).ResetPass1;
  293. {$endif}
  294. {$endif}
  295. { fixup the references }
  296. for i:=1 to taicpu(hp2).ops do
  297. begin
  298. ResolveRef(taicpu(hp2).fileinfo,taicpu(hp2).oper[i-1]^);
  299. with taicpu(hp2).oper[i-1]^ do
  300. begin
  301. case typ of
  302. top_ref :
  303. begin
  304. if assigned(ref^.symbol) then
  305. ReLabel(ref^.symbol);
  306. if assigned(ref^.relsymbol) then
  307. ReLabel(ref^.relsymbol);
  308. {$ifdef x86}
  309. if (ref^.segment<>NR_NO) and (ref^.segment<>get_default_segment_of_ref(ref^)) then
  310. taicpu(hp2).segprefix:=ref^.segment;
  311. {$endif x86}
  312. end;
  313. else
  314. ;
  315. end;
  316. end;
  317. end;
  318. {$if defined(x86) or defined(z80)}
  319. { can only be checked now that all local operands }
  320. { have been resolved }
  321. taicpu(hp2).CheckIfValid;
  322. {$endif x86 or z80}
  323. end;
  324. else
  325. ;
  326. end;
  327. current_asmdata.CurrAsmList.concat(hp2);
  328. hp:=tai(hp.next);
  329. end;
  330. { restore used symbols }
  331. current_asmdata.ResetAltSymbols;
  332. end
  333. else
  334. begin
  335. hp:=tai(p_asm.first);
  336. while assigned(hp) do
  337. begin
  338. case hp.typ of
  339. ait_instruction :
  340. begin
  341. { remove cached insentry, because the new code can
  342. require another less optimized instruction }
  343. {$ifdef i386}
  344. {$ifndef NOAG386BIN}
  345. taicpu(hp).ResetPass1;
  346. {$endif}
  347. {$endif}
  348. { fixup the references }
  349. for i:=1 to taicpu(hp).ops do
  350. begin
  351. ResolveRef(taicpu(hp).fileinfo,taicpu(hp).oper[i-1]^);
  352. {$ifdef x86}
  353. with taicpu(hp).oper[i-1]^ do
  354. begin
  355. case typ of
  356. top_ref :
  357. if (ref^.segment<>NR_NO) and (ref^.segment<>get_default_segment_of_ref(ref^)) then
  358. taicpu(hp).segprefix:=ref^.segment;
  359. else
  360. ;
  361. end;
  362. end;
  363. {$endif x86}
  364. end;
  365. {$if defined(x86) or defined(z80)}
  366. { can only be checked now that all local operands }
  367. { have been resolved }
  368. taicpu(hp).CheckIfValid;
  369. {$endif x86 or z80}
  370. end;
  371. ait_const:
  372. with tai_const(hp) do begin
  373. { Handle references to locals from TP-style INLINE(). }
  374. if assigned(sym) and (sym.bind=AB_NONE) then
  375. begin
  376. vs:=tabstractnormalvarsym(current_procinfo.procdef.parast.Find(sym.Name));
  377. if not assigned(vs) then
  378. vs:=tabstractnormalvarsym(current_procinfo.procdef.localst.Find(sym.Name));
  379. if not assigned(vs) then
  380. Internalerror(2021081401);
  381. if vs.localloc.loc<>LOC_REFERENCE then
  382. Internalerror(2021081402);
  383. value:=vs.localloc.reference.offset+symofs;
  384. sym:=nil;
  385. symofs:=0;
  386. end;
  387. end
  388. else
  389. ;
  390. end;
  391. hp:=tai(hp.next);
  392. end;
  393. { insert the list }
  394. current_asmdata.CurrAsmList.concatlist(p_asm);
  395. end;
  396. { Release register used in the assembler block }
  397. if (not has_registerlist) then
  398. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  399. { Switch back to the CPU instruction set of the target CPU }
  400. current_asmdata.CurrAsmList.Concat(tai_directive.create(asd_cpu,cputypestr[current_settings.cputype]));
  401. end;
  402. {*****************************************************************************
  403. TBLOCKNODE
  404. *****************************************************************************}
  405. procedure tcgblocknode.pass_generate_code;
  406. var
  407. hp : tstatementnode;
  408. oldexitlabel : tasmlabel;
  409. oldflowcontrol : tflowcontrol;
  410. begin
  411. location_reset(location,LOC_VOID,OS_NO);
  412. oldflowcontrol:=[];
  413. oldexitlabel:=nil;
  414. { replace exitlabel? }
  415. if nf_block_with_exit in flags then
  416. begin
  417. oldexitlabel:=current_procinfo.CurrExitLabel;
  418. current_asmdata.getjumplabel(current_procinfo.CurrExitLabel);
  419. oldflowcontrol:=flowcontrol;
  420. { the nested block will not span an exit statement of the parent }
  421. exclude(flowcontrol,fc_exit);
  422. include(flowcontrol,fc_no_direct_exit);
  423. end;
  424. { do second pass on left node }
  425. if assigned(left) then
  426. begin
  427. hp:=tstatementnode(left);
  428. while assigned(hp) do
  429. begin
  430. if assigned(hp.left) then
  431. begin
  432. secondpass(hp.left);
  433. location_copy(hp.location,hp.left.location);
  434. end;
  435. location_copy(location,hp.location);
  436. hp:=tstatementnode(hp.right);
  437. end;
  438. end;
  439. { write exitlabel }
  440. if nf_block_with_exit in flags then
  441. begin
  442. cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrExitLabel);
  443. current_procinfo.CurrExitLabel:=oldexitlabel;
  444. { the exit statements inside this block are not exit statements }
  445. { out of the parent }
  446. flowcontrol:=oldflowcontrol+(flowcontrol - [fc_exit,fc_no_direct_exit]);
  447. end;
  448. end;
  449. {*****************************************************************************
  450. TTEMPCREATENODE
  451. *****************************************************************************}
  452. procedure tcgtempcreatenode.pass_generate_code;
  453. begin
  454. location_reset(location,LOC_VOID,OS_NO);
  455. { if we're secondpassing the same tcgtempcreatenode twice, we have a bug }
  456. if (ti_valid in tempflags) then
  457. internalerror(200108222);
  458. { in case of ti_reference, the location will be initialised using the
  459. location of the tempinitnode once the first temprefnode is processed }
  460. if not(ti_reference in tempflags) then
  461. begin
  462. { get a (persistent) temp }
  463. if is_managed_type(tempinfo^.typedef) and
  464. not(ti_const in tempflags) then
  465. begin
  466. location_reset_ref(tempinfo^.location,LOC_REFERENCE,def_cgsize(tempinfo^.typedef),0,[]);
  467. tg.gethltempmanaged(current_asmdata.CurrAsmList,tempinfo^.typedef,tempinfo^.temptype,tempinfo^.location.reference);
  468. if not(ti_nofini in tempflags) then
  469. hlcg.g_finalize(current_asmdata.CurrAsmList,tempinfo^.typedef,tempinfo^.location.reference);
  470. end
  471. else if (ti_may_be_in_reg in tempflags) then
  472. begin
  473. location_allocate_register(current_asmdata.CurrAsmList,tempinfo^.location,tempinfo^.typedef,tempinfo^.temptype = tt_persistent);
  474. end
  475. else
  476. begin
  477. location_reset_ref(tempinfo^.location,LOC_REFERENCE,def_cgsize(tempinfo^.typedef),0,[]);
  478. tg.gethltemp(current_asmdata.CurrAsmList,tempinfo^.typedef,size,tempinfo^.temptype,tempinfo^.location.reference);
  479. end;
  480. end;
  481. includetempflag(ti_valid);
  482. if assigned(tempinfo^.tempinitcode) then
  483. includetempflag(ti_executeinitialisation);
  484. end;
  485. {*****************************************************************************
  486. TTEMPREFNODE
  487. *****************************************************************************}
  488. procedure tcgtemprefnode.pass_generate_code;
  489. begin
  490. if ti_executeinitialisation in tempflags then
  491. begin
  492. { avoid recursion }
  493. excludetempflag(ti_executeinitialisation);
  494. secondpass(tempinfo^.tempinitcode);
  495. if (ti_reference in tempflags) then
  496. begin
  497. case tempinfo^.tempinitcode.location.loc of
  498. LOC_CREGISTER,
  499. LOC_CFPUREGISTER,
  500. LOC_CMMREGISTER,
  501. LOC_CSUBSETREG:
  502. begin
  503. { although it's ok if we need this value multiple times
  504. for reading, it's not in case of writing (because the
  505. register could change due to SSA -> storing to the saved
  506. register afterwards would be wrong). }
  507. if not(ti_readonly in tempflags) then
  508. internalerror(2011031407);
  509. end;
  510. { in case reference contains CREGISTERS, that doesn't matter:
  511. we want to write to the location indicated by the current
  512. value of those registers, and we can save those values }
  513. else
  514. ;
  515. end;
  516. hlcg.g_reference_loc(current_asmdata.CurrAsmList,tempinfo^.typedef,tempinfo^.tempinitcode.location,tempinfo^.location);
  517. end;
  518. end;
  519. { check if the temp is valid }
  520. if not(ti_valid in tempflags) then
  521. internalerror(200108231);
  522. location:=tempinfo^.location;
  523. case tempinfo^.location.loc of
  524. LOC_REFERENCE:
  525. begin
  526. { ti_valid should be excluded if it's a normal temp }
  527. end;
  528. LOC_REGISTER,
  529. LOC_FPUREGISTER,
  530. LOC_MMREGISTER :
  531. excludetempflag(ti_valid);
  532. else
  533. ;
  534. end;
  535. end;
  536. procedure tcgtemprefnode.changelocation(const ref: treference);
  537. begin
  538. { check if the temp is valid }
  539. if not(ti_valid in tempflags) then
  540. internalerror(200306081);
  541. if (tempinfo^.location.loc<>LOC_REFERENCE) then
  542. internalerror(2004020203);
  543. if (tempinfo^.temptype = tt_persistent) then
  544. tg.ChangeTempType(current_asmdata.CurrAsmList,tempinfo^.location.reference,tt_normal);
  545. tg.ungettemp(current_asmdata.CurrAsmList,tempinfo^.location.reference);
  546. tempinfo^.location.reference := ref;
  547. tg.ChangeTempType(current_asmdata.CurrAsmList,tempinfo^.location.reference,tempinfo^.temptype);
  548. { adapt location }
  549. location.reference := ref;
  550. end;
  551. {*****************************************************************************
  552. TTEMPDELETENODE
  553. *****************************************************************************}
  554. procedure tcgtempdeletenode.pass_generate_code;
  555. begin
  556. if ti_reference in tempflags then
  557. begin
  558. { release_to_normal means that the temp will be freed the next
  559. time it's used. However, reference temps reference some other
  560. location that is not managed by this temp and hence cannot be
  561. freed }
  562. if release_to_normal then
  563. internalerror(2011052205);
  564. { so we only mark this temp location as "no longer valid" when
  565. it's deleted (ttempdeletenodes are also used during getcopy, so
  566. we really do need one) }
  567. excludetempflag(ti_valid);
  568. exit;
  569. end;
  570. location_reset(location,LOC_VOID,OS_NO);
  571. if ti_cleanup_only in tempflags then
  572. exit;
  573. { see comments at ti_const declaration: if we initialised this temp with
  574. the value of another temp, that other temp was not freed because the
  575. ti_const flag was set }
  576. if (ti_const in tempflags) and
  577. assigned(tempinfo^.tempinitcode) then
  578. begin
  579. if tempinfo^.tempinitcode.nodetype<>assignn then
  580. internalerror(2016081201);
  581. if tbinarynode(tempinfo^.tempinitcode).right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
  582. tg.ungetiftemp(current_asmdata.CurrAsmList,tbinarynode(tempinfo^.tempinitcode).right.location.reference);
  583. end;
  584. case tempinfo^.location.loc of
  585. LOC_REFERENCE:
  586. begin
  587. if release_to_normal then
  588. tg.ChangeTempType(current_asmdata.CurrAsmList,tempinfo^.location.reference,tt_normal)
  589. else
  590. begin
  591. tg.UnGetTemp(current_asmdata.CurrAsmList,tempinfo^.location.reference);
  592. excludetempflag(ti_valid);
  593. end;
  594. end;
  595. LOC_CREGISTER,
  596. LOC_REGISTER:
  597. begin
  598. if (not(cs_opt_regvar in current_settings.optimizerswitches) or
  599. (pi_has_label in current_procinfo.flags)) and not(ti_no_final_regsync in tempflags) then
  600. begin
  601. { make sure the register allocator doesn't reuse the }
  602. { register e.g. in the middle of a loop }
  603. {$if defined(cpu32bitalu) and not defined(cpuhighleveltarget)}
  604. if tempinfo^.location.size in [OS_64,OS_S64] then
  605. begin
  606. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reghi);
  607. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reglo);
  608. end
  609. else
  610. {$elseif defined(cpu16bitalu) and not defined(cpuhighleveltarget)}
  611. if tempinfo^.location.size in [OS_64,OS_S64] then
  612. begin
  613. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reghi);
  614. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(tempinfo^.location.register64.reghi));
  615. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reglo);
  616. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(tempinfo^.location.register64.reglo));
  617. end
  618. else
  619. if tempinfo^.location.size in [OS_32,OS_S32] then
  620. begin
  621. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register);
  622. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(tempinfo^.location.register));
  623. end
  624. else
  625. {$elseif defined(cpu8bitalu) and not defined(cpuhighleveltarget)}
  626. if tempinfo^.location.size in [OS_64,OS_S64] then
  627. begin
  628. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reghi);
  629. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(tempinfo^.location.register64.reghi));
  630. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(cg.GetNextReg(tempinfo^.location.register64.reghi)));
  631. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(cg.GetNextReg(cg.GetNextReg(tempinfo^.location.register64.reghi))));
  632. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reglo);
  633. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(tempinfo^.location.register64.reglo));
  634. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(cg.GetNextReg(tempinfo^.location.register64.reglo)));
  635. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(cg.GetNextReg(cg.GetNextReg(tempinfo^.location.register64.reglo))));
  636. end
  637. else
  638. if tempinfo^.location.size in [OS_32,OS_S32] then
  639. begin
  640. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register);
  641. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(tempinfo^.location.register));
  642. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(cg.GetNextReg(tempinfo^.location.register)));
  643. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(cg.GetNextReg(cg.GetNextReg(tempinfo^.location.register))));
  644. end
  645. else
  646. if tempinfo^.location.size in [OS_16,OS_S16] then
  647. begin
  648. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register);
  649. cg.a_reg_sync(current_asmdata.CurrAsmList,cg.GetNextReg(tempinfo^.location.register));
  650. end
  651. else
  652. {$endif}
  653. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register);
  654. end;
  655. if release_to_normal then
  656. tempinfo^.location.loc := LOC_REGISTER
  657. else
  658. excludetempflag(ti_valid);
  659. end;
  660. LOC_CFPUREGISTER,
  661. LOC_FPUREGISTER:
  662. begin
  663. if (not(cs_opt_regvar in current_settings.optimizerswitches) or
  664. (pi_has_label in current_procinfo.flags)) and not(ti_no_final_regsync in tempflags) then
  665. begin
  666. { make sure the register allocator doesn't reuse the }
  667. { register e.g. in the middle of a loop }
  668. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register);
  669. end;
  670. if release_to_normal then
  671. tempinfo^.location.loc := LOC_FPUREGISTER
  672. else
  673. excludetempflag(ti_valid);
  674. end;
  675. LOC_CMMREGISTER,
  676. LOC_MMREGISTER:
  677. begin
  678. if (not(cs_opt_regvar in current_settings.optimizerswitches) or
  679. (pi_has_label in current_procinfo.flags)) and not(ti_no_final_regsync in tempflags) then
  680. begin
  681. { make sure the register allocator doesn't reuse the }
  682. { register e.g. in the middle of a loop }
  683. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register);
  684. end;
  685. if release_to_normal then
  686. tempinfo^.location.loc := LOC_MMREGISTER
  687. else
  688. excludetempflag(ti_valid);
  689. end;
  690. else
  691. internalerror(200507161);
  692. end;
  693. end;
  694. {*****************************************************************************
  695. TCGFINALIZETEMPSNODE
  696. *****************************************************************************}
  697. procedure tcgfinalizetempsnode.pass_generate_code;
  698. begin
  699. hlcg.gen_finalize_code(current_asmdata.CurrAsmList);
  700. location.loc:=LOC_VOID;
  701. end;
  702. begin
  703. cnothingnode:=tcgnothingnode;
  704. casmnode:=tcgasmnode;
  705. cstatementnode:=tcgstatementnode;
  706. cblocknode:=tcgblocknode;
  707. ctempcreatenode:=tcgtempcreatenode;
  708. ctemprefnode:=tcgtemprefnode;
  709. ctempdeletenode:=tcgtempdeletenode;
  710. cfinalizetempsnode:=tcgfinalizetempsnode;
  711. end.