ncgbas.pas 21 KB

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