ncgbas.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. {
  2. $Id$
  3. Copyright (c) 2000 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 defines.inc}
  20. interface
  21. uses
  22. node,nbas;
  23. type
  24. tcgnothingnode = class(tnothingnode)
  25. procedure pass_2;override;
  26. end;
  27. tcgasmnode = class(tasmnode)
  28. procedure pass_2;override;
  29. end;
  30. tcgstatementnode = class(tstatementnode)
  31. procedure pass_2;override;
  32. end;
  33. tcgblocknode = class(tblocknode)
  34. procedure pass_2;override;
  35. end;
  36. tcgtempcreatenode = class(ttempcreatenode)
  37. procedure pass_2;override;
  38. end;
  39. tcgtemprefnode = class(ttemprefnode)
  40. procedure pass_2;override;
  41. end;
  42. tcgtempdeletenode = class(ttempdeletenode)
  43. procedure pass_2;override;
  44. end;
  45. implementation
  46. uses
  47. globtype,systems,
  48. cutils,verbose,globals,
  49. aasm,symsym,
  50. cpubase,cpuasm,
  51. nflw,pass_2,
  52. cga,
  53. cgbase,tgobj,rgobj
  54. ;
  55. {*****************************************************************************
  56. TNOTHING
  57. *****************************************************************************}
  58. procedure tcgnothingnode.pass_2;
  59. begin
  60. { avoid an abstract rte }
  61. end;
  62. {*****************************************************************************
  63. TSTATEMENTNODE
  64. *****************************************************************************}
  65. procedure tcgstatementnode.pass_2;
  66. var
  67. hp : tnode;
  68. begin
  69. hp:=self;
  70. while assigned(hp) do
  71. begin
  72. if assigned(tstatementnode(hp).right) then
  73. begin
  74. rg.cleartempgen;
  75. secondpass(tstatementnode(hp).right);
  76. end;
  77. hp:=tstatementnode(hp).left;
  78. end;
  79. end;
  80. {*****************************************************************************
  81. TASMNODE
  82. *****************************************************************************}
  83. procedure tcgasmnode.pass_2;
  84. procedure ReLabel(var p:tasmsymbol);
  85. begin
  86. if p.proclocal then
  87. begin
  88. if not assigned(p.altsymbol) then
  89. begin
  90. { generatealtsymbol will also increase the refs }
  91. p.GenerateAltSymbol;
  92. UsedAsmSymbolListInsert(p);
  93. end
  94. else
  95. begin
  96. { increase the refs, they will be decreased when the
  97. asmnode is destroyed }
  98. inc(p.refs);
  99. end;
  100. p:=p.altsymbol;
  101. end;
  102. end;
  103. var
  104. hp,hp2 : tai;
  105. localfixup,parafixup,
  106. i : longint;
  107. skipnode : boolean;
  108. begin
  109. if inlining_procedure then
  110. begin
  111. CreateUsedAsmSymbolList;
  112. localfixup:=aktprocdef.localst.address_fixup;
  113. parafixup:=aktprocdef.parast.address_fixup;
  114. hp:=tai(p_asm.first);
  115. while assigned(hp) do
  116. begin
  117. hp2:=tai(hp.getcopy);
  118. skipnode:=false;
  119. case hp2.typ of
  120. ait_label :
  121. begin
  122. { regenerate the labels by setting altsymbol }
  123. ReLabel(tasmsymbol(tai_label(hp2).l));
  124. end;
  125. ait_const_rva,
  126. ait_const_symbol :
  127. begin
  128. ReLabel(tai_const_symbol(hp2).sym);
  129. end;
  130. ait_instruction :
  131. begin
  132. { remove cached insentry, because the new code can
  133. require an other less optimized instruction }
  134. taicpu(hp2).ResetPass1;
  135. { fixup the references }
  136. for i:=1 to taicpu(hp2).ops do
  137. begin
  138. with taicpu(hp2).oper[i-1] do
  139. begin
  140. case typ of
  141. top_ref :
  142. begin
  143. case ref^.options of
  144. ref_parafixup :
  145. ref^.offsetfixup:=parafixup;
  146. ref_localfixup :
  147. ref^.offsetfixup:=localfixup;
  148. end;
  149. if assigned(ref^.symbol) then
  150. ReLabel(ref^.symbol);
  151. end;
  152. top_symbol :
  153. begin
  154. ReLabel(sym);
  155. end;
  156. end;
  157. end;
  158. end;
  159. end;
  160. ait_marker :
  161. begin
  162. { it's not an assembler block anymore }
  163. if (tai_marker(hp2).kind in [AsmBlockStart, AsmBlockEnd]) then
  164. skipnode:=true;
  165. end;
  166. else
  167. end;
  168. if not skipnode then
  169. exprasmList.concat(hp2)
  170. else
  171. hp2.free;
  172. hp:=tai(hp.next);
  173. end;
  174. { restore used symbols }
  175. UsedAsmSymbolListResetAltSym;
  176. DestroyUsedAsmSymbolList;
  177. end
  178. else
  179. begin
  180. { if the routine is an inline routine, then we must hold a copy
  181. because it can be necessary for inlining later }
  182. if (aktprocdef.proccalloption=pocall_inline) then
  183. exprasmList.concatlistcopy(p_asm)
  184. else
  185. exprasmList.concatlist(p_asm);
  186. end;
  187. if not (nf_object_preserved in flags) then
  188. maybe_loadself;
  189. end;
  190. {*****************************************************************************
  191. TBLOCKNODE
  192. *****************************************************************************}
  193. procedure tcgblocknode.pass_2;
  194. begin
  195. { do second pass on left node }
  196. if assigned(left) then
  197. secondpass(left);
  198. end;
  199. {*****************************************************************************
  200. TTEMPCREATENODE
  201. *****************************************************************************}
  202. procedure tcgtempcreatenode.pass_2;
  203. begin
  204. { if we're secondpassing the same tcgtempcreatenode twice, we have a bug }
  205. if tempinfo^.valid then
  206. internalerror(200108222);
  207. { get a (persistent) temp }
  208. if persistent then
  209. tg.gettempofsizereferencepersistant(exprasmlist,size,tempinfo^.ref)
  210. else
  211. tg.gettempofsizereference(exprasmlist,size,tempinfo^.ref);
  212. tempinfo^.valid := true;
  213. end;
  214. {*****************************************************************************
  215. TTEMPREFNODE
  216. *****************************************************************************}
  217. procedure tcgtemprefnode.pass_2;
  218. begin
  219. { check if the temp is valid }
  220. if not tempinfo^.valid then
  221. internalerror(200108231);
  222. { set the temp's location }
  223. location_reset(location,LOC_REFERENCE,int_cgsize(tempinfo^.size));
  224. location.reference := tempinfo^.ref;
  225. end;
  226. {*****************************************************************************
  227. TTEMPDELETENODE
  228. *****************************************************************************}
  229. procedure tcgtempdeletenode.pass_2;
  230. begin
  231. tg.ungetpersistanttempreference(exprasmlist,tempinfo^.ref);
  232. end;
  233. begin
  234. cnothingnode:=tcgnothingnode;
  235. casmnode:=tcgasmnode;
  236. cstatementnode:=tcgstatementnode;
  237. cblocknode:=tcgblocknode;
  238. ctempcreatenode:=tcgtempcreatenode;
  239. ctemprefnode:=tcgtemprefnode;
  240. ctempdeletenode:=tcgtempdeletenode;
  241. end.
  242. {
  243. $Log$
  244. Revision 1.12 2002-04-04 19:05:57 peter
  245. * removed unused units
  246. * use tlocation.size in cg.a_*loc*() routines
  247. Revision 1.11 2002/03/31 20:26:34 jonas
  248. + a_loadfpu_* and a_loadmm_* methods in tcg
  249. * register allocation is now handled by a class and is mostly processor
  250. independent (+rgobj.pas and i386/rgcpu.pas)
  251. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  252. * some small improvements and fixes to the optimizer
  253. * some register allocation fixes
  254. * some fpuvaroffset fixes in the unary minus node
  255. * push/popusedregisters is now called rg.save/restoreusedregisters and
  256. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  257. also better optimizable)
  258. * fixed and optimized register saving/restoring for new/dispose nodes
  259. * LOC_FPU locations now also require their "register" field to be set to
  260. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  261. - list field removed of the tnode class because it's not used currently
  262. and can cause hard-to-find bugs
  263. Revision 1.10 2001/12/31 16:54:14 peter
  264. * fixed inline crash with assembler routines
  265. Revision 1.9 2001/11/02 22:58:01 peter
  266. * procsym definition rewrite
  267. Revision 1.8 2001/10/25 21:22:35 peter
  268. * calling convention rewrite
  269. Revision 1.7 2001/08/26 13:36:39 florian
  270. * some cg reorganisation
  271. * some PPC updates
  272. Revision 1.6 2001/08/24 13:47:27 jonas
  273. * moved "reverseparameters" from ninl.pas to ncal.pas
  274. + support for non-persistent temps in ttempcreatenode.create, for use
  275. with typeconversion nodes
  276. Revision 1.5 2001/08/23 14:28:35 jonas
  277. + tempcreate/ref/delete nodes (allows the use of temps in the
  278. resulttype and first pass)
  279. * made handling of read(ln)/write(ln) processor independent
  280. * moved processor independent handling for str and reset/rewrite-typed
  281. from firstpass to resulttype pass
  282. * changed names of helpers in text.inc to be generic for use as
  283. compilerprocs + added "iocheck" directive for most of them
  284. * reading of ordinals is done by procedures instead of functions
  285. because otherwise FPC_IOCHECK overwrote the result before it could
  286. be stored elsewhere (range checking still works)
  287. * compilerprocs can now be used in the system unit before they are
  288. implemented
  289. * added note to errore.msg that booleans can't be read using read/readln
  290. Revision 1.4 2001/06/02 19:22:15 peter
  291. * refs count for relabeled asmsymbols fixed
  292. Revision 1.3 2001/05/18 22:31:06 peter
  293. * tasmnode.pass_2 is independent of cpu, moved to ncgbas
  294. * include ncgbas for independent nodes
  295. Revision 1.2 2001/04/13 01:22:08 peter
  296. * symtable change to classes
  297. * range check generation and errors fixed, make cycle DEBUG=1 works
  298. * memory leaks fixed
  299. Revision 1.1 2000/10/14 10:14:50 peter
  300. * moehrendorf oct 2000 rewrite
  301. }