ncgbas.pas 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  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. { has_registerlist=true means that registers are specified and already allocated }
  227. if (not has_registerlist) then
  228. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  229. if (po_inline in current_procinfo.procdef.procoptions) then
  230. begin
  231. hp:=tai(p_asm.first);
  232. while assigned(hp) do
  233. begin
  234. hp2:=tai(hp.getcopy);
  235. case hp2.typ of
  236. ait_label :
  237. ReLabel(tasmsymbol(tai_label(hp2).labsym));
  238. ait_const :
  239. begin
  240. if assigned(tai_const(hp2).sym) then
  241. ReLabel(tai_const(hp2).sym);
  242. if assigned(tai_const(hp2).endsym) then
  243. ReLabel(tai_const(hp2).endsym);
  244. end;
  245. ait_instruction :
  246. begin
  247. { remove cached insentry, because the new code can
  248. require another less optimized instruction }
  249. {$ifdef i386}
  250. {$ifndef NOAG386BIN}
  251. taicpu(hp2).ResetPass1;
  252. {$endif}
  253. {$endif}
  254. { fixup the references }
  255. for i:=1 to taicpu(hp2).ops do
  256. begin
  257. ResolveRef(taicpu(hp2).fileinfo,taicpu(hp2).oper[i-1]^);
  258. with taicpu(hp2).oper[i-1]^ do
  259. begin
  260. case typ of
  261. top_ref :
  262. begin
  263. if assigned(ref^.symbol) then
  264. ReLabel(ref^.symbol);
  265. if assigned(ref^.relsymbol) then
  266. ReLabel(ref^.relsymbol);
  267. end;
  268. end;
  269. end;
  270. end;
  271. {$ifdef x86}
  272. { can only be checked now that all local operands }
  273. { have been resolved }
  274. taicpu(hp2).CheckIfValid;
  275. {$endif x86}
  276. end;
  277. end;
  278. current_asmdata.CurrAsmList.concat(hp2);
  279. hp:=tai(hp.next);
  280. end;
  281. { restore used symbols }
  282. current_asmdata.ResetAltSymbols;
  283. end
  284. else
  285. begin
  286. hp:=tai(p_asm.first);
  287. while assigned(hp) do
  288. begin
  289. case hp.typ of
  290. ait_instruction :
  291. begin
  292. { remove cached insentry, because the new code can
  293. require another less optimized instruction }
  294. {$ifdef i386}
  295. {$ifndef NOAG386BIN}
  296. taicpu(hp).ResetPass1;
  297. {$endif}
  298. {$endif}
  299. { fixup the references }
  300. for i:=1 to taicpu(hp).ops do
  301. ResolveRef(taicpu(hp).fileinfo,taicpu(hp).oper[i-1]^);
  302. {$ifdef x86}
  303. { can only be checked now that all local operands }
  304. { have been resolved }
  305. taicpu(hp).CheckIfValid;
  306. {$endif x86}
  307. end;
  308. end;
  309. hp:=tai(hp.next);
  310. end;
  311. { insert the list }
  312. current_asmdata.CurrAsmList.concatlist(p_asm);
  313. end;
  314. { Release register used in the assembler block }
  315. if (not has_registerlist) then
  316. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  317. end;
  318. {*****************************************************************************
  319. TBLOCKNODE
  320. *****************************************************************************}
  321. procedure tcgblocknode.pass_generate_code;
  322. var
  323. hp : tstatementnode;
  324. oldexitlabel : tasmlabel;
  325. oldflowcontrol : tflowcontrol;
  326. begin
  327. location_reset(location,LOC_VOID,OS_NO);
  328. oldflowcontrol:=[];
  329. oldexitlabel:=nil;
  330. { replace exitlabel? }
  331. if nf_block_with_exit in flags then
  332. begin
  333. oldexitlabel:=current_procinfo.CurrExitLabel;
  334. current_asmdata.getjumplabel(current_procinfo.CurrExitLabel);
  335. oldflowcontrol:=flowcontrol;
  336. { the nested block will not span an exit statement of the parent }
  337. exclude(flowcontrol,fc_exit);
  338. end;
  339. { do second pass on left node }
  340. if assigned(left) then
  341. begin
  342. hp:=tstatementnode(left);
  343. while assigned(hp) do
  344. begin
  345. if assigned(hp.left) then
  346. begin
  347. secondpass(hp.left);
  348. location_copy(hp.location,hp.left.location);
  349. end;
  350. location_copy(location,hp.location);
  351. hp:=tstatementnode(hp.right);
  352. end;
  353. end;
  354. { write exitlabel }
  355. if nf_block_with_exit in flags then
  356. begin
  357. cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrExitLabel);
  358. current_procinfo.CurrExitLabel:=oldexitlabel;
  359. { the exit statements inside this block are not exit statements }
  360. { out of the parent }
  361. flowcontrol:=oldflowcontrol+(flowcontrol - [fc_exit]);
  362. end;
  363. end;
  364. {*****************************************************************************
  365. TTEMPCREATENODE
  366. *****************************************************************************}
  367. procedure tcgtempcreatenode.pass_generate_code;
  368. begin
  369. location_reset(location,LOC_VOID,OS_NO);
  370. { if we're secondpassing the same tcgtempcreatenode twice, we have a bug }
  371. if (ti_valid in tempinfo^.flags) then
  372. internalerror(200108222);
  373. { in case of ti_reference, the location will be initialised using the
  374. location of the tempinitnode once the first temprefnode is processed }
  375. if not(ti_reference in tempinfo^.flags) then
  376. begin
  377. { get a (persistent) temp }
  378. if is_managed_type(tempinfo^.typedef) and
  379. not(ti_const in tempinfo^.flags) then
  380. begin
  381. location_reset_ref(tempinfo^.location,LOC_REFERENCE,def_cgsize(tempinfo^.typedef),0);
  382. tg.gethltemptyped(current_asmdata.CurrAsmList,tempinfo^.typedef,tempinfo^.temptype,tempinfo^.location.reference);
  383. if not(ti_nofini in tempinfo^.flags) then
  384. hlcg.g_finalize(current_asmdata.CurrAsmList,tempinfo^.typedef,tempinfo^.location.reference);
  385. end
  386. else if (ti_may_be_in_reg in tempinfo^.flags) then
  387. begin
  388. location_allocate_register(current_asmdata.CurrAsmList,tempinfo^.location,tempinfo^.typedef,tempinfo^.temptype = tt_persistent);
  389. end
  390. else
  391. begin
  392. location_reset_ref(tempinfo^.location,LOC_REFERENCE,def_cgsize(tempinfo^.typedef),0);
  393. tg.gethltemp(current_asmdata.CurrAsmList,tempinfo^.typedef,size,tempinfo^.temptype,tempinfo^.location.reference);
  394. end;
  395. end;
  396. include(tempinfo^.flags,ti_valid);
  397. if assigned(tempinfo^.tempinitcode) then
  398. include(tempinfo^.flags,ti_executeinitialisation);
  399. end;
  400. {*****************************************************************************
  401. TTEMPREFNODE
  402. *****************************************************************************}
  403. procedure tcgtemprefnode.pass_generate_code;
  404. begin
  405. if ti_executeinitialisation in tempinfo^.flags then
  406. begin
  407. { avoid recursion }
  408. exclude(tempinfo^.flags, ti_executeinitialisation);
  409. secondpass(tempinfo^.tempinitcode);
  410. if (ti_reference in tempinfo^.flags) then
  411. begin
  412. case tempinfo^.tempinitcode.location.loc of
  413. LOC_CREGISTER,
  414. LOC_CFPUREGISTER,
  415. LOC_CMMREGISTER,
  416. LOC_CSUBSETREG:
  417. begin
  418. { although it's ok if we need this value multiple times
  419. for reading, it's not in case of writing (because the
  420. register could change due to SSA -> storing to the saved
  421. register afterwards would be wrong). }
  422. if not(ti_readonly in tempinfo^.flags) then
  423. internalerror(2011031407);
  424. end;
  425. { in case reference contains CREGISTERS, that doesn't matter:
  426. we want to write to the location indicated by the current
  427. value of those registers, and we can save those values }
  428. end;
  429. hlcg.g_reference_loc(current_asmdata.CurrAsmList,tempinfo^.typedef,tempinfo^.tempinitcode.location,tempinfo^.location);
  430. end;
  431. end;
  432. { check if the temp is valid }
  433. if not(ti_valid in tempinfo^.flags) then
  434. internalerror(200108231);
  435. location:=tempinfo^.location;
  436. case tempinfo^.location.loc of
  437. LOC_REFERENCE:
  438. begin
  439. inc(location.reference.offset,offset);
  440. location.reference.alignment:=newalignment(location.reference.alignment,offset);
  441. { ti_valid should be excluded if it's a normal temp }
  442. end;
  443. LOC_REGISTER,
  444. LOC_FPUREGISTER,
  445. LOC_MMREGISTER :
  446. exclude(tempinfo^.flags,ti_valid);
  447. end;
  448. end;
  449. procedure tcgtemprefnode.changelocation(const ref: treference);
  450. begin
  451. { check if the temp is valid }
  452. if not(ti_valid in tempinfo^.flags) then
  453. internalerror(200306081);
  454. if (tempinfo^.location.loc<>LOC_REFERENCE) then
  455. internalerror(2004020203);
  456. if (tempinfo^.temptype = tt_persistent) then
  457. tg.ChangeTempType(current_asmdata.CurrAsmList,tempinfo^.location.reference,tt_normal);
  458. tg.ungettemp(current_asmdata.CurrAsmList,tempinfo^.location.reference);
  459. tempinfo^.location.reference := ref;
  460. tg.ChangeTempType(current_asmdata.CurrAsmList,tempinfo^.location.reference,tempinfo^.temptype);
  461. { adapt location }
  462. location.reference := ref;
  463. inc(location.reference.offset,offset);
  464. location.reference.alignment:=newalignment(location.reference.alignment,offset);
  465. end;
  466. {*****************************************************************************
  467. TTEMPDELETENODE
  468. *****************************************************************************}
  469. procedure tcgtempdeletenode.pass_generate_code;
  470. begin
  471. if ti_reference in tempinfo^.flags then
  472. begin
  473. { release_to_normal means that the temp will be freed the next
  474. time it's used. However, reference temps reference some other
  475. location that is not managed by this temp and hence cannot be
  476. freed }
  477. if release_to_normal then
  478. internalerror(2011052205);
  479. { so we only mark this temp location as "no longer valid" when
  480. it's deleted (ttempdeletenodes are also used during getcopy, so
  481. we really do need one) }
  482. exclude(tempinfo^.flags,ti_valid);
  483. exit;
  484. end;
  485. location_reset(location,LOC_VOID,OS_NO);
  486. case tempinfo^.location.loc of
  487. LOC_REFERENCE:
  488. begin
  489. if release_to_normal then
  490. tg.ChangeTempType(current_asmdata.CurrAsmList,tempinfo^.location.reference,tt_normal)
  491. else
  492. begin
  493. tg.UnGetTemp(current_asmdata.CurrAsmList,tempinfo^.location.reference);
  494. exclude(tempinfo^.flags,ti_valid);
  495. end;
  496. end;
  497. LOC_CREGISTER,
  498. LOC_REGISTER:
  499. begin
  500. if not(cs_opt_regvar in current_settings.optimizerswitches) or
  501. (pi_has_label in current_procinfo.flags) then
  502. begin
  503. { make sure the register allocator doesn't reuse the }
  504. { register e.g. in the middle of a loop }
  505. {$if defined(cpu32bitalu)}
  506. if tempinfo^.location.size in [OS_64,OS_S64] then
  507. begin
  508. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reghi);
  509. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reglo);
  510. end
  511. else
  512. {$elseif defined(cpu16bitalu)}
  513. if tempinfo^.location.size in [OS_64,OS_S64] then
  514. begin
  515. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reghi);
  516. cg.a_reg_sync(current_asmdata.CurrAsmList,GetNextReg(tempinfo^.location.register64.reghi));
  517. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reglo);
  518. cg.a_reg_sync(current_asmdata.CurrAsmList,GetNextReg(tempinfo^.location.register64.reglo));
  519. end
  520. else
  521. if tempinfo^.location.size in [OS_32,OS_S32] then
  522. begin
  523. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register);
  524. cg.a_reg_sync(current_asmdata.CurrAsmList,GetNextReg(tempinfo^.location.register));
  525. end
  526. else
  527. {$elseif defined(cpu8bitalu)}
  528. if tempinfo^.location.size in [OS_64,OS_S64] then
  529. begin
  530. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reghi);
  531. cg.a_reg_sync(current_asmdata.CurrAsmList,GetNextReg(tempinfo^.location.register64.reghi));
  532. cg.a_reg_sync(current_asmdata.CurrAsmList,GetNextReg(GetNextReg(tempinfo^.location.register64.reghi)));
  533. cg.a_reg_sync(current_asmdata.CurrAsmList,GetNextReg(GetNextReg(GetNextReg(tempinfo^.location.register64.reghi))));
  534. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register64.reglo);
  535. cg.a_reg_sync(current_asmdata.CurrAsmList,GetNextReg(tempinfo^.location.register64.reglo));
  536. cg.a_reg_sync(current_asmdata.CurrAsmList,GetNextReg(GetNextReg(tempinfo^.location.register64.reglo)));
  537. cg.a_reg_sync(current_asmdata.CurrAsmList,GetNextReg(GetNextReg(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. cg.a_reg_sync(current_asmdata.CurrAsmList,GetNextReg(GetNextReg(tempinfo^.location.register)));
  545. cg.a_reg_sync(current_asmdata.CurrAsmList,GetNextReg(GetNextReg(GetNextReg(tempinfo^.location.register))));
  546. end
  547. else
  548. if tempinfo^.location.size in [OS_16,OS_S16] then
  549. begin
  550. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register);
  551. cg.a_reg_sync(current_asmdata.CurrAsmList,GetNextReg(tempinfo^.location.register));
  552. end
  553. else
  554. {$endif}
  555. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register);
  556. end;
  557. if release_to_normal then
  558. tempinfo^.location.loc := LOC_REGISTER
  559. else
  560. exclude(tempinfo^.flags,ti_valid);
  561. end;
  562. LOC_CFPUREGISTER,
  563. LOC_FPUREGISTER:
  564. begin
  565. if not(cs_opt_regvar in current_settings.optimizerswitches) or
  566. (pi_has_label in current_procinfo.flags) then
  567. begin
  568. { make sure the register allocator doesn't reuse the }
  569. { register e.g. in the middle of a loop }
  570. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register);
  571. end;
  572. if release_to_normal then
  573. tempinfo^.location.loc := LOC_FPUREGISTER
  574. else
  575. exclude(tempinfo^.flags,ti_valid);
  576. end;
  577. LOC_CMMREGISTER,
  578. LOC_MMREGISTER:
  579. begin
  580. if not(cs_opt_regvar in current_settings.optimizerswitches) or
  581. (pi_has_label in current_procinfo.flags) then
  582. begin
  583. { make sure the register allocator doesn't reuse the }
  584. { register e.g. in the middle of a loop }
  585. cg.a_reg_sync(current_asmdata.CurrAsmList,tempinfo^.location.register);
  586. end;
  587. if release_to_normal then
  588. tempinfo^.location.loc := LOC_MMREGISTER
  589. else
  590. exclude(tempinfo^.flags,ti_valid);
  591. end;
  592. else
  593. internalerror(200507161);
  594. end;
  595. end;
  596. begin
  597. cnothingnode:=tcgnothingnode;
  598. casmnode:=tcgasmnode;
  599. cstatementnode:=tcgstatementnode;
  600. cblocknode:=tcgblocknode;
  601. ctempcreatenode:=tcgtempcreatenode;
  602. ctemprefnode:=tcgtemprefnode;
  603. ctempdeletenode:=tcgtempdeletenode;
  604. end.