ncgbas.pas 21 KB

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