ncgbas.pas 26 KB

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