ncgbas.pas 27 KB

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