ncgbas.pas 19 KB

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