ncgbas.pas 15 KB

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