ncgmem.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  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. cpuinfo,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. if (cs_gdb_heaptrc in aktglobalswitches) and
  197. (cs_checkpointer in aktglobalswitches) then
  198. begin
  199. cg.a_param_reg(exprasmlist, OS_ADDR,location.reference.base,1);
  200. cg.a_call_name(exprasmlist,'FPC_CHECKPOINTER',0);
  201. end;
  202. end;
  203. {*****************************************************************************
  204. TCGSUBSCRIPTNODE
  205. *****************************************************************************}
  206. procedure tcgsubscriptnode.pass_2;
  207. begin
  208. secondpass(left);
  209. if codegenerror then
  210. exit;
  211. { classes and interfaces must be dereferenced implicit }
  212. if is_class_or_interface(left.resulttype.def) then
  213. begin
  214. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  215. case left.location.loc of
  216. LOC_REGISTER:
  217. begin
  218. if not rg.isaddressregister(left.location.register) then
  219. begin
  220. location_release(exprasmlist,left.location);
  221. location.reference.base:=rg.getaddressregister(exprasmlist);
  222. cg.a_load_reg_reg(exprasmlist,OS_ADDR,
  223. left.location.register,location.reference.base);
  224. end
  225. else
  226. location.reference.base := left.location.register;
  227. end;
  228. LOC_CREGISTER,
  229. LOC_CREFERENCE,
  230. LOC_REFERENCE:
  231. begin
  232. location_release(exprasmlist,left.location);
  233. location.reference.base:=rg.getaddressregister(exprasmlist);
  234. cg.a_load_loc_reg(exprasmlist,left.location,location.reference.base);
  235. end;
  236. end;
  237. end
  238. else if is_interfacecom(left.resulttype.def) then
  239. begin
  240. tg.gettempintfcomreference(exprasmlist,location.reference);
  241. cg.a_load_loc_ref(exprasmlist,left.location,location.reference);
  242. end
  243. else
  244. location_copy(location,left.location);
  245. inc(location.reference.offset,vs.address);
  246. { also update the size of the location }
  247. location.size:=def_cgsize(resulttype.def);
  248. end;
  249. {*****************************************************************************
  250. TCGSELFNODE
  251. *****************************************************************************}
  252. procedure tcgselfnode.pass_2;
  253. begin
  254. rg.getexplicitregisterint(exprasmlist,SELF_POINTER_REG);
  255. if (resulttype.def.deftype=classrefdef) or
  256. is_class(resulttype.def) then
  257. begin
  258. location_reset(location,LOC_CREGISTER,OS_ADDR);
  259. location.register:=SELF_POINTER_REG;
  260. end
  261. else
  262. begin
  263. location_reset(location,LOC_CREFERENCE,OS_ADDR);
  264. location.reference.base:=SELF_POINTER_REG;
  265. end;
  266. end;
  267. {*****************************************************************************
  268. TCGWITHNODE
  269. *****************************************************************************}
  270. procedure tcgwithnode.pass_2;
  271. var
  272. tmpreg: tregister;
  273. usetemp,with_expr_in_temp : boolean;
  274. {$ifdef GDB}
  275. withstartlabel,withendlabel : tasmlabel;
  276. pp : pchar;
  277. mangled_length : longint;
  278. const
  279. withlevel : longint = 0;
  280. {$endif GDB}
  281. begin
  282. if assigned(left) then
  283. begin
  284. secondpass(left);
  285. {$ifdef i386}
  286. if (left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  287. (left.location.reference.segment<>R_NO) then
  288. message(parser_e_no_with_for_variable_in_other_segments);
  289. {$endif i386}
  290. reference_reset(withreference);
  291. usetemp:=false;
  292. if (left.nodetype=loadn) and
  293. (tloadnode(left).symtable=aktprocdef.localst) then
  294. begin
  295. { for locals use the local storage }
  296. withreference:=left.location.reference;
  297. include(flags,nf_islocal);
  298. end
  299. else
  300. { call can have happend with a property }
  301. begin
  302. tmpreg := cg.get_scratch_reg(exprasmlist);
  303. usetemp:=true;
  304. if is_class_or_interface(left.resulttype.def) then
  305. cg.a_load_loc_reg(exprasmlist,left.location,tmpreg)
  306. else
  307. cg.a_loadaddr_ref_reg(exprasmlist,
  308. left.location.reference,tmpreg);
  309. end;
  310. location_release(exprasmlist,left.location);
  311. { if the with expression is stored in a temp }
  312. { area we must make it persistent and shouldn't }
  313. { release it (FK) }
  314. if (left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) and
  315. tg.istemp(left.location.reference) then
  316. begin
  317. tg.normaltemptopersistant(left.location.reference.offset);
  318. with_expr_in_temp:=true;
  319. end
  320. else
  321. with_expr_in_temp:=false;
  322. { if usetemp is set the value must be in tmpreg }
  323. if usetemp then
  324. begin
  325. tg.gettempofsizereference(exprasmlist,pointer_size,withreference);
  326. tg.normaltemptopersistant(withreference.offset);
  327. { move to temp reference }
  328. cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,withreference);
  329. cg.free_scratch_reg(exprasmlist,tmpreg);
  330. {$ifdef GDB}
  331. if (cs_debuginfo in aktmoduleswitches) then
  332. begin
  333. inc(withlevel);
  334. getaddrlabel(withstartlabel);
  335. getaddrlabel(withendlabel);
  336. emitlab(withstartlabel);
  337. withdebugList.concat(Tai_stabs.Create(strpnew(
  338. '"with'+tostr(withlevel)+':'+tostr(symtablestack.getnewtypecount)+
  339. '=*'+tstoreddef(left.resulttype.def).numberstring+'",'+
  340. tostr(N_LSYM)+',0,0,'+tostr(withreference.offset))));
  341. mangled_length:=length(aktprocdef.mangledname);
  342. getmem(pp,mangled_length+50);
  343. strpcopy(pp,'192,0,0,'+withstartlabel.name);
  344. if (target_info.use_function_relative_addresses) then
  345. begin
  346. strpcopy(strend(pp),'-');
  347. strpcopy(strend(pp),aktprocdef.mangledname);
  348. end;
  349. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  350. end;
  351. {$endif GDB}
  352. end;
  353. { right can be optimize out !!! }
  354. if assigned(right) then
  355. secondpass(right);
  356. if usetemp then
  357. begin
  358. tg.ungetpersistanttemp(exprasmlist,withreference.offset);
  359. {$ifdef GDB}
  360. if (cs_debuginfo in aktmoduleswitches) then
  361. begin
  362. emitlab(withendlabel);
  363. strpcopy(pp,'224,0,0,'+withendlabel.name);
  364. if (target_info.use_function_relative_addresses) then
  365. begin
  366. strpcopy(strend(pp),'-');
  367. strpcopy(strend(pp),aktprocdef.mangledname);
  368. end;
  369. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  370. freemem(pp,mangled_length+50);
  371. dec(withlevel);
  372. end;
  373. {$endif GDB}
  374. end;
  375. if with_expr_in_temp then
  376. tg.ungetpersistanttemp(exprasmlist,left.location.reference.offset);
  377. reference_reset(withreference);
  378. end;
  379. end;
  380. begin
  381. cloadvmtnode:=tcgloadvmtnode;
  382. chnewnode:=tcghnewnode;
  383. chdisposenode:=tcghdisposenode;
  384. caddrnode:=tcgaddrnode;
  385. cdoubleaddrnode:=tcgdoubleaddrnode;
  386. cderefnode:=tcgderefnode;
  387. csubscriptnode:=tcgsubscriptnode;
  388. cselfnode:=tcgselfnode;
  389. cwithnode:=tcgwithnode;
  390. end.
  391. {
  392. $Log$
  393. Revision 1.8 2002-04-20 21:32:23 carl
  394. + generic FPC_CHECKPOINTER
  395. + first parameter offset in stack now portable
  396. * rename some constants
  397. + move some cpu stuff to other units
  398. - remove unused constents
  399. * fix stacksize for some targets
  400. * fix generic size problems which depend now on EXTEND_SIZE constant
  401. Revision 1.7 2002/04/15 18:58:47 carl
  402. + target_info.size_of_pointer -> pointer_Size
  403. Revision 1.6 2002/04/04 19:05:57 peter
  404. * removed unused units
  405. * use tlocation.size in cg.a_*loc*() routines
  406. Revision 1.5 2002/04/02 17:11:28 peter
  407. * tlocation,treference update
  408. * LOC_CONSTANT added for better constant handling
  409. * secondadd splitted in multiple routines
  410. * location_force_reg added for loading a location to a register
  411. of a specified size
  412. * secondassignment parses now first the right and then the left node
  413. (this is compatible with Kylix). This saves a lot of push/pop especially
  414. with string operations
  415. * adapted some routines to use the new cg methods
  416. Revision 1.4 2002/03/31 20:26:34 jonas
  417. + a_loadfpu_* and a_loadmm_* methods in tcg
  418. * register allocation is now handled by a class and is mostly processor
  419. independent (+rgobj.pas and i386/rgcpu.pas)
  420. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  421. * some small improvements and fixes to the optimizer
  422. * some register allocation fixes
  423. * some fpuvaroffset fixes in the unary minus node
  424. * push/popusedregisters is now called rg.save/restoreusedregisters and
  425. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  426. also better optimizable)
  427. * fixed and optimized register saving/restoring for new/dispose nodes
  428. * LOC_FPU locations now also require their "register" field to be set to
  429. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  430. - list field removed of the tnode class because it's not used currently
  431. and can cause hard-to-find bugs
  432. Revision 1.3 2001/12/31 09:53:15 jonas
  433. * changed remaining "getregister32" calls to "getregisterint"
  434. Revision 1.2 2001/11/02 22:58:02 peter
  435. * procsym definition rewrite
  436. Revision 1.1 2001/09/30 16:17:17 jonas
  437. * made most constant and mem handling processor independent
  438. }