ncgbas.pas 27 KB

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