ncgbas.pas 18 KB

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