ncgbas.pas 18 KB

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