ncgbas.pas 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. {
  2. $Id$
  3. Copyright (c) 2000-2002 by Florian Klaempfl
  4. This unit implements some basic nodes
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit ncgbas;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. cpubase,cgutils,
  23. node,nbas;
  24. type
  25. tcgnothingnode = class(tnothingnode)
  26. procedure pass_2;override;
  27. end;
  28. tcgasmnode = class(tasmnode)
  29. procedure pass_2;override;
  30. end;
  31. tcgstatementnode = class(tstatementnode)
  32. procedure pass_2;override;
  33. end;
  34. tcgblocknode = class(tblocknode)
  35. procedure pass_2;override;
  36. end;
  37. tcgtempcreatenode = class(ttempcreatenode)
  38. procedure pass_2;override;
  39. end;
  40. tcgtemprefnode = class(ttemprefnode)
  41. procedure pass_2;override;
  42. { Changes the location of this temp to ref. Useful when assigning }
  43. { another temp to this one. The current location will be freed. }
  44. { Can only be called in pass 2 (since earlier, the temp location }
  45. { isn't known yet) }
  46. procedure changelocation(const ref: treference);
  47. end;
  48. tcgtempdeletenode = class(ttempdeletenode)
  49. procedure pass_2;override;
  50. end;
  51. implementation
  52. uses
  53. globtype,systems,
  54. cutils,verbose,
  55. aasmbase,aasmtai,aasmcpu,symsym,symconst,
  56. defutil,
  57. nflw,pass_2,
  58. cgbase,cgobj,
  59. procinfo,
  60. tgobj
  61. ;
  62. {*****************************************************************************
  63. TNOTHING
  64. *****************************************************************************}
  65. procedure tcgnothingnode.pass_2;
  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_2;
  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_2;
  94. procedure ReLabel(var p:tasmsymbol);
  95. begin
  96. { Only relabel local tasmlabels }
  97. if (p.defbind = AB_LOCAL) and
  98. (p is tasmlabel) then
  99. begin
  100. if not assigned(p.altsymbol) then
  101. objectlibrary.GenerateAltSymbol(p);
  102. p:=p.altsymbol;
  103. p.increfs;
  104. end;
  105. end;
  106. procedure ResolveRef(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. 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. op.ref^.index:=indexreg;
  151. {$ifdef x86}
  152. op.ref^.scalefactor:=scale;
  153. {$endif x86}
  154. end;
  155. end;
  156. LOC_REGISTER :
  157. begin
  158. if getoffset then
  159. Message(asmr_e_invalid_reference_syntax);
  160. { Subscribed access }
  161. if forceref or
  162. (sofs<>0) then
  163. begin
  164. op.typ:=top_ref;
  165. new(op.ref);
  166. reference_reset_base(op.ref^,sym.localloc.register,sofs);
  167. op.ref^.index:=indexreg;
  168. {$ifdef x86}
  169. op.ref^.scalefactor:=scale;
  170. {$endif x86}
  171. end
  172. else
  173. begin
  174. op.typ:=top_reg;
  175. op.reg:=sym.localloc.register;
  176. end;
  177. end;
  178. end;
  179. end;
  180. end;
  181. var
  182. hp,hp2 : tai;
  183. i : longint;
  184. skipnode : boolean;
  185. begin
  186. location_reset(location,LOC_VOID,OS_NO);
  187. if (nf_get_asm_position in flags) then
  188. begin
  189. { Add a marker, to be sure the list is not empty }
  190. exprasmlist.concat(tai_marker.create(marker_position));
  191. currenttai:=tai(exprasmlist.last);
  192. exit;
  193. end;
  194. { Allocate registers used in the assembler block }
  195. cg.alloccpuregisters(exprasmlist,R_INTREGISTER,used_regs_int);
  196. if (current_procinfo.procdef.proccalloption=pocall_inline) then
  197. begin
  198. objectlibrary.CreateUsedAsmSymbolList;
  199. hp:=tai(p_asm.first);
  200. while assigned(hp) do
  201. begin
  202. hp2:=tai(hp.getcopy);
  203. skipnode:=false;
  204. case hp2.typ of
  205. ait_label :
  206. ReLabel(tasmsymbol(tai_label(hp2).l));
  207. ait_const_64bit,
  208. ait_const_32bit,
  209. ait_const_16bit,
  210. ait_const_8bit,
  211. ait_const_rva_symbol,
  212. ait_const_indirect_symbol :
  213. begin
  214. if assigned(tai_const(hp2).sym) then
  215. ReLabel(tai_const(hp2).sym);
  216. if assigned(tai_const(hp2).endsym) then
  217. ReLabel(tai_const(hp2).endsym);
  218. end;
  219. ait_instruction :
  220. begin
  221. { remove cached insentry, because the new code can
  222. require an other less optimized instruction }
  223. {$ifdef i386}
  224. {$ifndef NOAG386BIN}
  225. taicpu(hp2).ResetPass1;
  226. {$endif}
  227. {$endif}
  228. { fixup the references }
  229. for i:=1 to taicpu(hp2).ops do
  230. begin
  231. ResolveRef(taicpu(hp2).oper[i-1]^);
  232. with taicpu(hp2).oper[i-1]^ do
  233. begin
  234. case typ of
  235. top_ref :
  236. begin
  237. if assigned(ref^.symbol) then
  238. ReLabel(ref^.symbol);
  239. if assigned(ref^.relsymbol) then
  240. ReLabel(ref^.relsymbol);
  241. end;
  242. end;
  243. end;
  244. end;
  245. end;
  246. ait_marker :
  247. begin
  248. { it's not an assembler block anymore }
  249. if (tai_marker(hp2).kind in [AsmBlockStart, AsmBlockEnd]) then
  250. skipnode:=true;
  251. end;
  252. end;
  253. if not skipnode then
  254. exprasmList.concat(hp2)
  255. else
  256. hp2.free;
  257. hp:=tai(hp.next);
  258. end;
  259. { restore used symbols }
  260. objectlibrary.UsedAsmSymbolListResetAltSym;
  261. objectlibrary.DestroyUsedAsmSymbolList;
  262. end
  263. else
  264. begin
  265. hp:=tai(p_asm.first);
  266. while assigned(hp) do
  267. begin
  268. case hp.typ of
  269. ait_instruction :
  270. begin
  271. { remove cached insentry, because the new code can
  272. require an other less optimized instruction }
  273. {$ifdef i386}
  274. {$ifndef NOAG386BIN}
  275. taicpu(hp).ResetPass1;
  276. {$endif}
  277. {$endif}
  278. { fixup the references }
  279. for i:=1 to taicpu(hp).ops do
  280. ResolveRef(taicpu(hp).oper[i-1]^);
  281. end;
  282. end;
  283. hp:=tai(hp.next);
  284. end;
  285. { insert the list }
  286. exprasmList.concatlist(p_asm);
  287. end;
  288. { Release register used in the assembler block }
  289. cg.dealloccpuregisters(exprasmlist,R_INTREGISTER,used_regs_int);
  290. end;
  291. {*****************************************************************************
  292. TBLOCKNODE
  293. *****************************************************************************}
  294. procedure tcgblocknode.pass_2;
  295. var
  296. hp : tstatementnode;
  297. oldexitlabel : tasmlabel;
  298. begin
  299. location_reset(location,LOC_VOID,OS_NO);
  300. { replace exitlabel? }
  301. if nf_block_with_exit in flags then
  302. begin
  303. oldexitlabel:=current_procinfo.aktexitlabel;
  304. objectlibrary.getlabel(current_procinfo.aktexitlabel);
  305. end;
  306. { do second pass on left node }
  307. if assigned(left) then
  308. begin
  309. hp:=tstatementnode(left);
  310. while assigned(hp) do
  311. begin
  312. if assigned(hp.left) then
  313. begin
  314. secondpass(hp.left);
  315. location_copy(hp.location,hp.left.location);
  316. end;
  317. location_copy(location,hp.location);
  318. hp:=tstatementnode(hp.right);
  319. end;
  320. end;
  321. { write exitlabel }
  322. if nf_block_with_exit in flags then
  323. begin
  324. cg.a_label(exprasmlist,current_procinfo.aktexitlabel);
  325. current_procinfo.aktexitlabel:=oldexitlabel;
  326. end;
  327. end;
  328. {*****************************************************************************
  329. TTEMPCREATENODE
  330. *****************************************************************************}
  331. procedure tcgtempcreatenode.pass_2;
  332. begin
  333. location_reset(location,LOC_VOID,OS_NO);
  334. { if we're secondpassing the same tcgtempcreatenode twice, we have a bug }
  335. if tempinfo^.valid then
  336. internalerror(200108222);
  337. { get a (persistent) temp }
  338. if tempinfo^.restype.def.needs_inittable then
  339. begin
  340. location_reset(tempinfo^.location,LOC_REFERENCE,def_cgsize(tempinfo^.restype.def));
  341. tg.GetTempTyped(exprasmlist,tempinfo^.restype.def,tempinfo^.temptype,tempinfo^.location.reference);
  342. end
  343. else if tempinfo^.may_be_in_reg then
  344. begin
  345. if tempinfo^.restype.def.deftype=floatdef then
  346. begin
  347. if (tempinfo^.temptype = tt_persistent) then
  348. location_reset(tempinfo^.location,LOC_CFPUREGISTER,def_cgsize(tempinfo^.restype.def))
  349. else
  350. location_reset(tempinfo^.location,LOC_FPUREGISTER,def_cgsize(tempinfo^.restype.def));
  351. tempinfo^.location.register:=cg.getfpuregister(exprasmlist,tempinfo^.location.size);
  352. end
  353. else
  354. begin
  355. if (tempinfo^.temptype = tt_persistent) then
  356. location_reset(tempinfo^.location,LOC_CREGISTER,def_cgsize(tempinfo^.restype.def))
  357. else
  358. location_reset(tempinfo^.location,LOC_REGISTER,def_cgsize(tempinfo^.restype.def));
  359. {$ifndef cpu64bit}
  360. if tempinfo^.location.size in [OS_64,OS_S64] then
  361. begin
  362. tempinfo^.location.register64.reglo:=cg.getintregister(exprasmlist,OS_32);
  363. tempinfo^.location.register64.reghi:=cg.getintregister(exprasmlist,OS_32);
  364. end
  365. else
  366. {$endif cpu64bit}
  367. tempinfo^.location.register:=cg.getintregister(exprasmlist,tempinfo^.location.size);
  368. end;
  369. end
  370. else
  371. begin
  372. location_reset(tempinfo^.location,LOC_REFERENCE,def_cgsize(tempinfo^.restype.def));
  373. tg.GetTemp(exprasmlist,size,tempinfo^.temptype,tempinfo^.location.reference);
  374. end;
  375. tempinfo^.valid := true;
  376. end;
  377. {*****************************************************************************
  378. TTEMPREFNODE
  379. *****************************************************************************}
  380. procedure tcgtemprefnode.pass_2;
  381. begin
  382. { check if the temp is valid }
  383. if not tempinfo^.valid then
  384. internalerror(200108231);
  385. location:=tempinfo^.location;
  386. if tempinfo^.location.loc=LOC_REFERENCE then
  387. inc(location.reference.offset,offset);
  388. end;
  389. procedure tcgtemprefnode.changelocation(const ref: treference);
  390. begin
  391. { check if the temp is valid }
  392. if not tempinfo^.valid then
  393. internalerror(200306081);
  394. if (tempinfo^.location.loc<>LOC_REFERENCE) then
  395. internalerror(2004020203);
  396. if (tempinfo^.temptype = tt_persistent) then
  397. tg.ChangeTempType(exprasmlist,tempinfo^.location.reference,tt_normal);
  398. tg.ungettemp(exprasmlist,tempinfo^.location.reference);
  399. tempinfo^.location.reference := ref;
  400. tg.ChangeTempType(exprasmlist,tempinfo^.location.reference,tempinfo^.temptype);
  401. { adapt location }
  402. location.reference := ref;
  403. inc(location.reference.offset,offset);
  404. end;
  405. {*****************************************************************************
  406. TTEMPDELETENODE
  407. *****************************************************************************}
  408. procedure tcgtempdeletenode.pass_2;
  409. begin
  410. location_reset(location,LOC_VOID,OS_NO);
  411. case tempinfo^.location.loc of
  412. LOC_REFERENCE:
  413. begin
  414. if release_to_normal then
  415. tg.ChangeTempType(exprasmlist,tempinfo^.location.reference,tt_normal)
  416. else
  417. tg.UnGetTemp(exprasmlist,tempinfo^.location.reference);
  418. end;
  419. LOC_CREGISTER,
  420. LOC_REGISTER:
  421. begin
  422. { make sure the register allocator doesn't reuse the }
  423. { register e.g. in the middle of a loop }
  424. {$ifndef cpu64bit}
  425. if tempinfo^.location.size in [OS_64,OS_S64] then
  426. begin
  427. cg.a_reg_sync(exprasmlist,tempinfo^.location.register64.reghi);
  428. cg.a_reg_sync(exprasmlist,tempinfo^.location.register64.reglo);
  429. end
  430. else
  431. {$endif cpu64bit}
  432. cg.a_reg_sync(exprasmlist,tempinfo^.location.register);
  433. if release_to_normal then
  434. tempinfo^.location.loc := LOC_REGISTER;
  435. end;
  436. end;
  437. end;
  438. begin
  439. cnothingnode:=tcgnothingnode;
  440. casmnode:=tcgasmnode;
  441. cstatementnode:=tcgstatementnode;
  442. cblocknode:=tcgblocknode;
  443. ctempcreatenode:=tcgtempcreatenode;
  444. ctemprefnode:=tcgtemprefnode;
  445. ctempdeletenode:=tcgtempdeletenode;
  446. end.
  447. {
  448. $Log$
  449. Revision 1.76 2005-02-14 17:13:06 peter
  450. * truncate log
  451. Revision 1.75 2005/01/31 17:07:50 peter
  452. * fix [regpara] in intel assembler
  453. }