ncgbas.pas 29 KB

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