ncgbas.pas 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  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. node,nbas;
  23. type
  24. tcgnothingnode = class(tnothingnode)
  25. procedure pass_2;override;
  26. end;
  27. tcgasmnode = class(tasmnode)
  28. procedure pass_2;override;
  29. end;
  30. tcgstatementnode = class(tstatementnode)
  31. procedure pass_2;override;
  32. end;
  33. tcgblocknode = class(tblocknode)
  34. procedure pass_2;override;
  35. end;
  36. tcgtempcreatenode = class(ttempcreatenode)
  37. procedure pass_2;override;
  38. end;
  39. tcgtemprefnode = class(ttemprefnode)
  40. procedure pass_2;override;
  41. end;
  42. tcgtempdeletenode = class(ttempdeletenode)
  43. procedure pass_2;override;
  44. end;
  45. implementation
  46. uses
  47. globtype,systems,
  48. cutils,verbose,globals,
  49. aasmbase,aasmtai,aasmcpu,symsym,
  50. cpubase,
  51. nflw,pass_2,
  52. cgbase,cginfo,cgobj,tgobj,rgobj
  53. ;
  54. {*****************************************************************************
  55. TNOTHING
  56. *****************************************************************************}
  57. procedure tcgnothingnode.pass_2;
  58. begin
  59. location_reset(location,LOC_VOID,OS_NO);
  60. { avoid an abstract rte }
  61. end;
  62. {*****************************************************************************
  63. TSTATEMENTNODE
  64. *****************************************************************************}
  65. procedure tcgstatementnode.pass_2;
  66. var
  67. hp : tstatementnode;
  68. begin
  69. location_reset(location,LOC_VOID,OS_NO);
  70. hp:=self;
  71. while assigned(hp) do
  72. begin
  73. if assigned(hp.left) then
  74. begin
  75. secondpass(hp.left);
  76. { Compiler inserted blocks can return values }
  77. location_copy(hp.location,hp.left.location);
  78. end;
  79. hp:=tstatementnode(hp.right);
  80. end;
  81. end;
  82. {*****************************************************************************
  83. TASMNODE
  84. *****************************************************************************}
  85. procedure tcgasmnode.pass_2;
  86. procedure ReLabel(var p:tasmsymbol);
  87. begin
  88. { Only relabel local tasmlabels }
  89. if (p.defbind = AB_LOCAL) and
  90. (p is tasmlabel) then
  91. begin
  92. if not assigned(p.altsymbol) then
  93. objectlibrary.GenerateAltSymbol(p);
  94. p:=p.altsymbol;
  95. p.increfs;
  96. end;
  97. end;
  98. var
  99. hp,hp2 : tai;
  100. localfixup,parafixup,
  101. i : longint;
  102. skipnode : boolean;
  103. begin
  104. location_reset(location,LOC_VOID,OS_NO);
  105. if getposition then
  106. begin
  107. currenttai:=tai(exprasmlist.last);
  108. exit;
  109. end;
  110. { Allocate registers used in the assembler block }
  111. rg.allocexplicitregistersint(exprasmlist,used_regs_int);
  112. if inlining_procedure then
  113. begin
  114. objectlibrary.CreateUsedAsmSymbolList;
  115. localfixup:=current_procinfo.procdef.localst.address_fixup;
  116. parafixup:=current_procinfo.procdef.parast.address_fixup;
  117. hp:=tai(p_asm.first);
  118. while assigned(hp) do
  119. begin
  120. hp2:=tai(hp.getcopy);
  121. skipnode:=false;
  122. case hp2.typ of
  123. ait_label :
  124. begin
  125. { regenerate the labels by setting altsymbol }
  126. ReLabel(tasmsymbol(tai_label(hp2).l));
  127. end;
  128. ait_const_rva,
  129. ait_const_symbol :
  130. begin
  131. ReLabel(tai_const_symbol(hp2).sym);
  132. end;
  133. ait_instruction :
  134. begin
  135. { remove cached insentry, because the new code can
  136. require an other less optimized instruction }
  137. {$ifdef i386}
  138. {$ifndef NOAG386BIN}
  139. taicpu(hp2).ResetPass1;
  140. {$endif}
  141. {$endif}
  142. { fixup the references }
  143. for i:=1 to taicpu(hp2).ops do
  144. begin
  145. with taicpu(hp2).oper[i-1] do
  146. begin
  147. case typ of
  148. top_ref :
  149. begin
  150. case ref^.options of
  151. ref_parafixup :
  152. ref^.offsetfixup:=parafixup;
  153. ref_localfixup :
  154. ref^.offsetfixup:=localfixup;
  155. end;
  156. if assigned(ref^.symbol) then
  157. ReLabel(ref^.symbol);
  158. end;
  159. top_symbol :
  160. begin
  161. ReLabel(sym);
  162. end;
  163. end;
  164. end;
  165. end;
  166. end;
  167. ait_marker :
  168. begin
  169. { it's not an assembler block anymore }
  170. if (tai_marker(hp2).kind in [AsmBlockStart, AsmBlockEnd]) then
  171. skipnode:=true;
  172. end;
  173. else
  174. end;
  175. if not skipnode then
  176. exprasmList.concat(hp2)
  177. else
  178. hp2.free;
  179. hp:=tai(hp.next);
  180. end;
  181. { restore used symbols }
  182. objectlibrary.UsedAsmSymbolListResetAltSym;
  183. objectlibrary.DestroyUsedAsmSymbolList;
  184. end
  185. else
  186. begin
  187. { if the routine is an inline routine, then we must hold a copy
  188. because it can be necessary for inlining later }
  189. if (current_procinfo.procdef.proccalloption=pocall_inline) then
  190. exprasmList.concatlistcopy(p_asm)
  191. else
  192. exprasmList.concatlist(p_asm);
  193. end;
  194. { Release register used in the assembler block }
  195. rg.deallocexplicitregistersint(exprasmlist,used_regs_int);
  196. end;
  197. {*****************************************************************************
  198. TBLOCKNODE
  199. *****************************************************************************}
  200. procedure tcgblocknode.pass_2;
  201. var
  202. hp : tstatementnode;
  203. begin
  204. location_reset(location,LOC_VOID,OS_NO);
  205. { do second pass on left node }
  206. if assigned(left) then
  207. begin
  208. hp:=tstatementnode(left);
  209. while assigned(hp) do
  210. begin
  211. if assigned(hp.left) then
  212. begin
  213. secondpass(hp.left);
  214. location_copy(hp.location,hp.left.location);
  215. end;
  216. location_copy(location,hp.location);
  217. hp:=tstatementnode(hp.right);
  218. end;
  219. end;
  220. end;
  221. {*****************************************************************************
  222. TTEMPCREATENODE
  223. *****************************************************************************}
  224. procedure tcgtempcreatenode.pass_2;
  225. begin
  226. location_reset(location,LOC_VOID,OS_NO);
  227. { if we're secondpassing the same tcgtempcreatenode twice, we have a bug }
  228. if tempinfo^.valid then
  229. internalerror(200108222);
  230. { get a (persistent) temp }
  231. tg.GetTemp(exprasmlist,size,tempinfo^.temptype,tempinfo^.ref);
  232. tempinfo^.valid := true;
  233. end;
  234. {*****************************************************************************
  235. TTEMPREFNODE
  236. *****************************************************************************}
  237. procedure tcgtemprefnode.pass_2;
  238. begin
  239. { check if the temp is valid }
  240. if not tempinfo^.valid then
  241. internalerror(200108231);
  242. { set the temp's location }
  243. location_reset(location,LOC_REFERENCE,def_cgsize(tempinfo^.restype.def));
  244. location.reference := tempinfo^.ref;
  245. inc(location.reference.offset,offset);
  246. end;
  247. {*****************************************************************************
  248. TTEMPDELETENODE
  249. *****************************************************************************}
  250. procedure tcgtempdeletenode.pass_2;
  251. begin
  252. location_reset(location,LOC_VOID,OS_NO);
  253. if release_to_normal then
  254. tg.ChangeTempType(exprasmlist,tempinfo^.ref,tt_normal)
  255. else
  256. tg.UnGetTemp(exprasmlist,tempinfo^.ref);
  257. end;
  258. begin
  259. cnothingnode:=tcgnothingnode;
  260. casmnode:=tcgasmnode;
  261. cstatementnode:=tcgstatementnode;
  262. cblocknode:=tcgblocknode;
  263. ctempcreatenode:=tcgtempcreatenode;
  264. ctemprefnode:=tcgtemprefnode;
  265. ctempdeletenode:=tcgtempdeletenode;
  266. end.
  267. {
  268. $Log$
  269. Revision 1.39 2003-09-07 22:09:35 peter
  270. * preparations for different default calling conventions
  271. * various RA fixes
  272. Revision 1.38 2003/09/03 15:55:00 peter
  273. * NEWRA branch merged
  274. Revision 1.37.2.1 2003/08/27 20:23:55 peter
  275. * remove old ra code
  276. Revision 1.37 2003/06/13 21:19:30 peter
  277. * current_procdef removed, use current_procinfo.procdef instead
  278. Revision 1.36 2003/06/09 18:26:46 peter
  279. * remove temptype, use tempinfo.temptype instead
  280. Revision 1.35 2003/06/09 12:20:47 peter
  281. * getposition added to retrieve the the current tai item
  282. Revision 1.34 2003/05/17 13:30:08 jonas
  283. * changed tt_persistant to tt_persistent :)
  284. * tempcreatenode now doesn't accept a boolean anymore for persistent
  285. temps, but a ttemptype, so you can also create ansistring temps etc
  286. Revision 1.33 2003/04/27 11:21:33 peter
  287. * aktprocdef renamed to current_procinfo.procdef
  288. * procinfo renamed to current_procinfo
  289. * procinfo will now be stored in current_module so it can be
  290. cleaned up properly
  291. * gen_main_procsym changed to create_main_proc and release_main_proc
  292. to also generate a tprocinfo structure
  293. * fixed unit implicit initfinal
  294. Revision 1.32 2002/04/25 20:15:39 florian
  295. * block nodes within expressions shouldn't release the used registers,
  296. fixed using a flag till the new rg is ready
  297. Revision 1.31 2003/04/22 23:50:22 peter
  298. * firstpass uses expectloc
  299. * checks if there are differences between the expectloc and
  300. location.loc from secondpass in EXTDEBUG
  301. Revision 1.30 2003/04/17 07:50:24 daniel
  302. * Some work on interference graph construction
  303. Revision 1.29 2003/03/28 19:16:56 peter
  304. * generic constructor working for i386
  305. * remove fixed self register
  306. * esi added as address register for i386
  307. Revision 1.28 2002/11/27 15:33:19 peter
  308. * fixed relabeling to relabel only tasmlabel (formerly proclocal)
  309. Revision 1.27 2002/11/27 02:37:13 peter
  310. * case statement inlining added
  311. * fixed inlining of write()
  312. * switched statementnode left and right parts so the statements are
  313. processed in the correct order when getcopy is used. This is
  314. required for tempnodes
  315. Revision 1.26 2002/11/17 16:31:56 carl
  316. * memory optimization (3-4%) : cleanup of tai fields,
  317. cleanup of tdef and tsym fields.
  318. * make it work for m68k
  319. Revision 1.25 2002/11/15 16:29:30 peter
  320. * made tasmsymbol.refs private (merged)
  321. Revision 1.24 2002/11/15 01:58:51 peter
  322. * merged changes from 1.0.7 up to 04-11
  323. - -V option for generating bug report tracing
  324. - more tracing for option parsing
  325. - errors for cdecl and high()
  326. - win32 import stabs
  327. - win32 records<=8 are returned in eax:edx (turned off by default)
  328. - heaptrc update
  329. - more info for temp management in .s file with EXTDEBUG
  330. Revision 1.23 2002/08/23 16:14:48 peter
  331. * tempgen cleanup
  332. * tt_noreuse temp type added that will be used in genentrycode
  333. Revision 1.22 2002/08/11 14:32:26 peter
  334. * renamed current_library to objectlibrary
  335. Revision 1.21 2002/08/11 13:24:11 peter
  336. * saving of asmsymbols in ppu supported
  337. * asmsymbollist global is removed and moved into a new class
  338. tasmlibrarydata that will hold the info of a .a file which
  339. corresponds with a single module. Added librarydata to tmodule
  340. to keep the library info stored for the module. In the future the
  341. objectfiles will also be stored to the tasmlibrarydata class
  342. * all getlabel/newasmsymbol and friends are moved to the new class
  343. Revision 1.20 2002/07/01 18:46:22 peter
  344. * internal linker
  345. * reorganized aasm layer
  346. Revision 1.19 2002/05/18 13:34:09 peter
  347. * readded missing revisions
  348. Revision 1.18 2002/05/16 19:46:37 carl
  349. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  350. + try to fix temp allocation (still in ifdef)
  351. + generic constructor calls
  352. + start of tassembler / tmodulebase class cleanup
  353. Revision 1.16 2002/05/13 19:54:37 peter
  354. * removed n386ld and n386util units
  355. * maybe_save/maybe_restore added instead of the old maybe_push
  356. Revision 1.15 2002/05/12 16:53:07 peter
  357. * moved entry and exitcode to ncgutil and cgobj
  358. * foreach gets extra argument for passing local data to the
  359. iterator function
  360. * -CR checks also class typecasts at runtime by changing them
  361. into as
  362. * fixed compiler to cycle with the -CR option
  363. * fixed stabs with elf writer, finally the global variables can
  364. be watched
  365. * removed a lot of routines from cga unit and replaced them by
  366. calls to cgobj
  367. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  368. u32bit then the other is typecasted also to u32bit without giving
  369. a rangecheck warning/error.
  370. * fixed pascal calling method with reversing also the high tree in
  371. the parast, detected by tcalcst3 test
  372. Revision 1.14 2002/04/23 19:16:34 peter
  373. * add pinline unit that inserts compiler supported functions using
  374. one or more statements
  375. * moved finalize and setlength from ninl to pinline
  376. Revision 1.13 2002/04/21 19:02:03 peter
  377. * removed newn and disposen nodes, the code is now directly
  378. inlined from pexpr
  379. * -an option that will write the secondpass nodes to the .s file, this
  380. requires EXTDEBUG define to actually write the info
  381. * fixed various internal errors and crashes due recent code changes
  382. Revision 1.12 2002/04/04 19:05:57 peter
  383. * removed unused units
  384. * use tlocation.size in cg.a_*loc*() routines
  385. Revision 1.11 2002/03/31 20:26:34 jonas
  386. + a_loadfpu_* and a_loadmm_* methods in tcg
  387. * register allocation is now handled by a class and is mostly processor
  388. independent (+rgobj.pas and i386/rgcpu.pas)
  389. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  390. * some small improvements and fixes to the optimizer
  391. * some register allocation fixes
  392. * some fpuvaroffset fixes in the unary minus node
  393. * push/popusedregisters is now called rg.save/restoreusedregisters and
  394. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  395. also better optimizable)
  396. * fixed and optimized register saving/restoring for new/dispose nodes
  397. * LOC_FPU locations now also require their "register" field to be set to
  398. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  399. - list field removed of the tnode class because it's not used currently
  400. and can cause hard-to-find bugs
  401. }