ncgmem.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Generate assembler for memory related nodes which are
  5. the same for all (most?) processors
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit ncgmem;
  20. {$i defines.inc}
  21. interface
  22. uses
  23. node,nmem;
  24. type
  25. tcgloadvmtnode = class(tloadvmtnode)
  26. procedure pass_2;override;
  27. end;
  28. tcghnewnode = class(thnewnode)
  29. procedure pass_2;override;
  30. end;
  31. tcghdisposenode = class(thdisposenode)
  32. procedure pass_2;override;
  33. end;
  34. tcgaddrnode = class(taddrnode)
  35. procedure pass_2;override;
  36. end;
  37. tcgdoubleaddrnode = class(tdoubleaddrnode)
  38. procedure pass_2;override;
  39. end;
  40. tcgderefnode = class(tderefnode)
  41. procedure pass_2;override;
  42. end;
  43. tcgsubscriptnode = class(tsubscriptnode)
  44. procedure pass_2;override;
  45. end;
  46. tcgselfnode = class(tselfnode)
  47. procedure pass_2;override;
  48. end;
  49. tcgwithnode = class(twithnode)
  50. procedure pass_2;override;
  51. end;
  52. implementation
  53. uses
  54. globtype,systems,
  55. cutils,verbose,globals,
  56. symconst,symdef,symsym,aasm,
  57. cginfo,cgbase,pass_2,
  58. nld,ncon,nadd,
  59. cpubase,cgobj,cgcpu,
  60. tgobj,rgobj
  61. {$ifdef GDB}
  62. {$ifdef delphi}
  63. ,sysutils
  64. {$else}
  65. ,strings
  66. {$endif}
  67. ,cga
  68. ,symbase
  69. ,gdb
  70. {$endif GDB}
  71. ;
  72. {*****************************************************************************
  73. TCGLOADNODE
  74. *****************************************************************************}
  75. procedure tcgloadvmtnode.pass_2;
  76. begin
  77. location_reset(location,LOC_REGISTER,OS_ADDR);
  78. location.register:=rg.getregisterint(exprasmlist);
  79. cg.a_load_sym_ofs_reg(exprasmlist,
  80. newasmsymbol(tobjectdef(tclassrefdef(resulttype.def).pointertype.def).vmt_mangledname),
  81. 0,location.register);
  82. end;
  83. {*****************************************************************************
  84. TCGHNEWNODE
  85. *****************************************************************************}
  86. procedure tcghnewnode.pass_2;
  87. begin
  88. end;
  89. {*****************************************************************************
  90. TCGHDISPOSENODE
  91. *****************************************************************************}
  92. procedure tcghdisposenode.pass_2;
  93. begin
  94. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  95. secondpass(left);
  96. if codegenerror then
  97. exit;
  98. case left.location.loc of
  99. LOC_REGISTER:
  100. begin
  101. if not rg.isaddressregister(left.location.register) then
  102. begin
  103. location_release(exprasmlist,left.location);
  104. location.reference.index := rg.getaddressregister(exprasmlist);
  105. cg.a_load_reg_reg(exprasmlist,OS_ADDR,left.location.register,
  106. location.reference.index);
  107. end
  108. else
  109. location.reference.index := left.location.register;
  110. end;
  111. LOC_CREGISTER,
  112. LOC_CREFERENCE,
  113. LOC_REFERENCE:
  114. begin
  115. location_release(exprasmlist,left.location);
  116. location.reference.index:=rg.getaddressregister(exprasmlist);
  117. cg.a_load_loc_reg(exprasmlist,left.location,location.reference.index);
  118. end;
  119. else
  120. internalerror(2002032217);
  121. end;
  122. end;
  123. {*****************************************************************************
  124. TCGADDRNODE
  125. *****************************************************************************}
  126. procedure tcgaddrnode.pass_2;
  127. begin
  128. secondpass(left);
  129. { when loading procvar we do nothing with this node, so load the
  130. location of left }
  131. if nf_procvarload in flags then
  132. begin
  133. location_copy(location,left.location);
  134. exit;
  135. end;
  136. location_release(exprasmlist,left.location);
  137. location_reset(location,LOC_REGISTER,OS_ADDR);
  138. location.register:=rg.getaddressregister(exprasmlist);
  139. {@ on a procvar means returning an address to the procedure that
  140. is stored in it.}
  141. { yes but left.symtableentry can be nil
  142. for example on self !! }
  143. { symtableentry can be also invalid, if left is no tree node }
  144. if (m_tp_procvar in aktmodeswitches) and
  145. (left.nodetype=loadn) and
  146. assigned(tloadnode(left).symtableentry) and
  147. (tloadnode(left).symtableentry.typ=varsym) and
  148. (tvarsym(tloadnode(left).symtableentry).vartype.def.deftype=procvardef) then
  149. cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,
  150. location.register)
  151. else
  152. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,
  153. location.register);
  154. end;
  155. {*****************************************************************************
  156. TCGDOUBLEADDRNODE
  157. *****************************************************************************}
  158. procedure tcgdoubleaddrnode.pass_2;
  159. begin
  160. secondpass(left);
  161. location_release(exprasmlist,left.location);
  162. location_reset(location,LOC_REGISTER,OS_ADDR);
  163. location.register:=rg.getaddressregister(exprasmlist);
  164. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,
  165. location.register);
  166. end;
  167. {*****************************************************************************
  168. TCGDEREFNODE
  169. *****************************************************************************}
  170. procedure tcgderefnode.pass_2;
  171. begin
  172. secondpass(left);
  173. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  174. case left.location.loc of
  175. LOC_REGISTER:
  176. begin
  177. if not rg.isaddressregister(left.location.register) then
  178. begin
  179. location_release(exprasmlist,left.location);
  180. location.reference.base := rg.getaddressregister(exprasmlist);
  181. cg.a_load_reg_reg(exprasmlist,OS_ADDR,left.location.register,
  182. location.reference.base);
  183. end
  184. else
  185. location.reference.base := left.location.register;
  186. end;
  187. LOC_CREGISTER,
  188. LOC_CREFERENCE,
  189. LOC_REFERENCE:
  190. begin
  191. location_release(exprasmlist,left.location);
  192. location.reference.base:=rg.getaddressregister(exprasmlist);
  193. cg.a_load_loc_reg(exprasmlist,left.location,location.reference.base);
  194. end;
  195. end;
  196. { still needs generic checkpointer() support! }
  197. end;
  198. {*****************************************************************************
  199. TCGSUBSCRIPTNODE
  200. *****************************************************************************}
  201. procedure tcgsubscriptnode.pass_2;
  202. begin
  203. secondpass(left);
  204. if codegenerror then
  205. exit;
  206. { classes and interfaces must be dereferenced implicit }
  207. if is_class_or_interface(left.resulttype.def) then
  208. begin
  209. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  210. case left.location.loc of
  211. LOC_REGISTER:
  212. begin
  213. if not rg.isaddressregister(left.location.register) then
  214. begin
  215. location_release(exprasmlist,left.location);
  216. location.reference.base:=rg.getaddressregister(exprasmlist);
  217. cg.a_load_reg_reg(exprasmlist,OS_ADDR,
  218. left.location.register,location.reference.base);
  219. end
  220. else
  221. location.reference.base := left.location.register;
  222. end;
  223. LOC_CREGISTER,
  224. LOC_CREFERENCE,
  225. LOC_REFERENCE:
  226. begin
  227. location_release(exprasmlist,left.location);
  228. location.reference.base:=rg.getaddressregister(exprasmlist);
  229. cg.a_load_loc_reg(exprasmlist,left.location,location.reference.base);
  230. end;
  231. end;
  232. end
  233. else if is_interfacecom(left.resulttype.def) then
  234. begin
  235. tg.gettempintfcomreference(exprasmlist,location.reference);
  236. cg.a_load_loc_ref(exprasmlist,left.location,location.reference);
  237. end
  238. else
  239. location_copy(location,left.location);
  240. inc(location.reference.offset,vs.address);
  241. { also update the size of the location }
  242. location.size:=def_cgsize(resulttype.def);
  243. end;
  244. {*****************************************************************************
  245. TCGSELFNODE
  246. *****************************************************************************}
  247. procedure tcgselfnode.pass_2;
  248. begin
  249. rg.getexplicitregisterint(exprasmlist,SELF_POINTER);
  250. if (resulttype.def.deftype=classrefdef) or
  251. is_class(resulttype.def) then
  252. begin
  253. location_reset(location,LOC_CREGISTER,OS_ADDR);
  254. location.register:=SELF_POINTER;
  255. end
  256. else
  257. begin
  258. location_reset(location,LOC_CREFERENCE,OS_ADDR);
  259. location.reference.base:=SELF_POINTER;
  260. end;
  261. end;
  262. {*****************************************************************************
  263. TCGWITHNODE
  264. *****************************************************************************}
  265. procedure tcgwithnode.pass_2;
  266. var
  267. tmpreg: tregister;
  268. usetemp,with_expr_in_temp : boolean;
  269. {$ifdef GDB}
  270. withstartlabel,withendlabel : tasmlabel;
  271. pp : pchar;
  272. mangled_length : longint;
  273. const
  274. withlevel : longint = 0;
  275. {$endif GDB}
  276. begin
  277. if assigned(left) then
  278. begin
  279. secondpass(left);
  280. {$ifdef i386}
  281. if (left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  282. (left.location.reference.segment<>R_NO) then
  283. message(parser_e_no_with_for_variable_in_other_segments);
  284. {$endif i386}
  285. reference_reset(withreference);
  286. usetemp:=false;
  287. if (left.nodetype=loadn) and
  288. (tloadnode(left).symtable=aktprocdef.localst) then
  289. begin
  290. { for locals use the local storage }
  291. withreference:=left.location.reference;
  292. include(flags,nf_islocal);
  293. end
  294. else
  295. { call can have happend with a property }
  296. begin
  297. tmpreg := cg.get_scratch_reg(exprasmlist);
  298. usetemp:=true;
  299. if is_class_or_interface(left.resulttype.def) then
  300. cg.a_load_loc_reg(exprasmlist,left.location,tmpreg)
  301. else
  302. cg.a_loadaddr_ref_reg(exprasmlist,
  303. left.location.reference,tmpreg);
  304. end;
  305. location_release(exprasmlist,left.location);
  306. { if the with expression is stored in a temp }
  307. { area we must make it persistent and shouldn't }
  308. { release it (FK) }
  309. if (left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) and
  310. tg.istemp(left.location.reference) then
  311. begin
  312. tg.normaltemptopersistant(left.location.reference.offset);
  313. with_expr_in_temp:=true;
  314. end
  315. else
  316. with_expr_in_temp:=false;
  317. { if usetemp is set the value must be in tmpreg }
  318. if usetemp then
  319. begin
  320. tg.gettempofsizereference(exprasmlist,target_info.size_of_pointer,withreference);
  321. tg.normaltemptopersistant(withreference.offset);
  322. { move to temp reference }
  323. cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,withreference);
  324. cg.free_scratch_reg(exprasmlist,tmpreg);
  325. {$ifdef GDB}
  326. if (cs_debuginfo in aktmoduleswitches) then
  327. begin
  328. inc(withlevel);
  329. getaddrlabel(withstartlabel);
  330. getaddrlabel(withendlabel);
  331. emitlab(withstartlabel);
  332. withdebugList.concat(Tai_stabs.Create(strpnew(
  333. '"with'+tostr(withlevel)+':'+tostr(symtablestack.getnewtypecount)+
  334. '=*'+tstoreddef(left.resulttype.def).numberstring+'",'+
  335. tostr(N_LSYM)+',0,0,'+tostr(withreference.offset))));
  336. mangled_length:=length(aktprocdef.mangledname);
  337. getmem(pp,mangled_length+50);
  338. strpcopy(pp,'192,0,0,'+withstartlabel.name);
  339. if (target_info.use_function_relative_addresses) then
  340. begin
  341. strpcopy(strend(pp),'-');
  342. strpcopy(strend(pp),aktprocdef.mangledname);
  343. end;
  344. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  345. end;
  346. {$endif GDB}
  347. end;
  348. { right can be optimize out !!! }
  349. if assigned(right) then
  350. secondpass(right);
  351. if usetemp then
  352. begin
  353. tg.ungetpersistanttemp(exprasmlist,withreference.offset);
  354. {$ifdef GDB}
  355. if (cs_debuginfo in aktmoduleswitches) then
  356. begin
  357. emitlab(withendlabel);
  358. strpcopy(pp,'224,0,0,'+withendlabel.name);
  359. if (target_info.use_function_relative_addresses) then
  360. begin
  361. strpcopy(strend(pp),'-');
  362. strpcopy(strend(pp),aktprocdef.mangledname);
  363. end;
  364. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  365. freemem(pp,mangled_length+50);
  366. dec(withlevel);
  367. end;
  368. {$endif GDB}
  369. end;
  370. if with_expr_in_temp then
  371. tg.ungetpersistanttemp(exprasmlist,left.location.reference.offset);
  372. reference_reset(withreference);
  373. end;
  374. end;
  375. begin
  376. cloadvmtnode:=tcgloadvmtnode;
  377. chnewnode:=tcghnewnode;
  378. chdisposenode:=tcghdisposenode;
  379. caddrnode:=tcgaddrnode;
  380. cdoubleaddrnode:=tcgdoubleaddrnode;
  381. cderefnode:=tcgderefnode;
  382. csubscriptnode:=tcgsubscriptnode;
  383. cselfnode:=tcgselfnode;
  384. cwithnode:=tcgwithnode;
  385. end.
  386. {
  387. $Log$
  388. Revision 1.6 2002-04-04 19:05:57 peter
  389. * removed unused units
  390. * use tlocation.size in cg.a_*loc*() routines
  391. Revision 1.5 2002/04/02 17:11:28 peter
  392. * tlocation,treference update
  393. * LOC_CONSTANT added for better constant handling
  394. * secondadd splitted in multiple routines
  395. * location_force_reg added for loading a location to a register
  396. of a specified size
  397. * secondassignment parses now first the right and then the left node
  398. (this is compatible with Kylix). This saves a lot of push/pop especially
  399. with string operations
  400. * adapted some routines to use the new cg methods
  401. Revision 1.4 2002/03/31 20:26:34 jonas
  402. + a_loadfpu_* and a_loadmm_* methods in tcg
  403. * register allocation is now handled by a class and is mostly processor
  404. independent (+rgobj.pas and i386/rgcpu.pas)
  405. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  406. * some small improvements and fixes to the optimizer
  407. * some register allocation fixes
  408. * some fpuvaroffset fixes in the unary minus node
  409. * push/popusedregisters is now called rg.save/restoreusedregisters and
  410. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  411. also better optimizable)
  412. * fixed and optimized register saving/restoring for new/dispose nodes
  413. * LOC_FPU locations now also require their "register" field to be set to
  414. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  415. - list field removed of the tnode class because it's not used currently
  416. and can cause hard-to-find bugs
  417. Revision 1.3 2001/12/31 09:53:15 jonas
  418. * changed remaining "getregister32" calls to "getregisterint"
  419. Revision 1.2 2001/11/02 22:58:02 peter
  420. * procsym definition rewrite
  421. Revision 1.1 2001/09/30 16:17:17 jonas
  422. * made most constant and mem handling processor independent
  423. }