ncgmem.pas 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  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 fpcdefs.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. 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. ,symbase
  68. ,gdb
  69. {$endif GDB}
  70. ;
  71. {*****************************************************************************
  72. TCGLOADNODE
  73. *****************************************************************************}
  74. procedure tcgloadvmtnode.pass_2;
  75. begin
  76. location_reset(location,LOC_REGISTER,OS_ADDR);
  77. location.register:=rg.getregisterint(exprasmlist);
  78. cg.a_load_sym_ofs_reg(exprasmlist,
  79. newasmsymbol(tobjectdef(tclassrefdef(resulttype.def).pointertype.def).vmt_mangledname),
  80. 0,location.register);
  81. end;
  82. {*****************************************************************************
  83. TCGHNEWNODE
  84. *****************************************************************************}
  85. procedure tcghnewnode.pass_2;
  86. begin
  87. end;
  88. {*****************************************************************************
  89. TCGHDISPOSENODE
  90. *****************************************************************************}
  91. procedure tcghdisposenode.pass_2;
  92. begin
  93. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  94. secondpass(left);
  95. if codegenerror then
  96. exit;
  97. case left.location.loc of
  98. LOC_REGISTER:
  99. begin
  100. if not rg.isaddressregister(left.location.register) then
  101. begin
  102. location_release(exprasmlist,left.location);
  103. location.reference.index := rg.getaddressregister(exprasmlist);
  104. cg.a_load_reg_reg(exprasmlist,OS_ADDR,left.location.register,
  105. location.reference.index);
  106. end
  107. else
  108. location.reference.index := left.location.register;
  109. end;
  110. LOC_CREGISTER,
  111. LOC_CREFERENCE,
  112. LOC_REFERENCE:
  113. begin
  114. location_release(exprasmlist,left.location);
  115. location.reference.index:=rg.getaddressregister(exprasmlist);
  116. cg.a_load_loc_reg(exprasmlist,left.location,location.reference.index);
  117. end;
  118. else
  119. internalerror(2002032217);
  120. end;
  121. end;
  122. {*****************************************************************************
  123. TCGADDRNODE
  124. *****************************************************************************}
  125. procedure tcgaddrnode.pass_2;
  126. begin
  127. secondpass(left);
  128. { when loading procvar we do nothing with this node, so load the
  129. location of left }
  130. if nf_procvarload in flags then
  131. begin
  132. location_copy(location,left.location);
  133. exit;
  134. end;
  135. location_release(exprasmlist,left.location);
  136. location_reset(location,LOC_REGISTER,OS_ADDR);
  137. location.register:=rg.getaddressregister(exprasmlist);
  138. {@ on a procvar means returning an address to the procedure that
  139. is stored in it.}
  140. { yes but left.symtableentry can be nil
  141. for example on self !! }
  142. { symtableentry can be also invalid, if left is no tree node }
  143. if (m_tp_procvar in aktmodeswitches) and
  144. (left.nodetype=loadn) and
  145. assigned(tloadnode(left).symtableentry) and
  146. (tloadnode(left).symtableentry.typ=varsym) and
  147. (tvarsym(tloadnode(left).symtableentry).vartype.def.deftype=procvardef) then
  148. cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,
  149. location.register)
  150. else
  151. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,
  152. location.register);
  153. end;
  154. {*****************************************************************************
  155. TCGDOUBLEADDRNODE
  156. *****************************************************************************}
  157. procedure tcgdoubleaddrnode.pass_2;
  158. begin
  159. secondpass(left);
  160. location_release(exprasmlist,left.location);
  161. location_reset(location,LOC_REGISTER,OS_ADDR);
  162. location.register:=rg.getaddressregister(exprasmlist);
  163. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,
  164. location.register);
  165. end;
  166. {*****************************************************************************
  167. TCGDEREFNODE
  168. *****************************************************************************}
  169. procedure tcgderefnode.pass_2;
  170. begin
  171. secondpass(left);
  172. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  173. case left.location.loc of
  174. LOC_REGISTER:
  175. begin
  176. if not rg.isaddressregister(left.location.register) then
  177. begin
  178. location_release(exprasmlist,left.location);
  179. location.reference.base := rg.getaddressregister(exprasmlist);
  180. cg.a_load_reg_reg(exprasmlist,OS_ADDR,left.location.register,
  181. location.reference.base);
  182. end
  183. else
  184. location.reference.base := left.location.register;
  185. end;
  186. LOC_CREGISTER,
  187. LOC_CREFERENCE,
  188. LOC_REFERENCE:
  189. begin
  190. location_release(exprasmlist,left.location);
  191. location.reference.base:=rg.getaddressregister(exprasmlist);
  192. cg.a_load_loc_reg(exprasmlist,left.location,location.reference.base);
  193. end;
  194. end;
  195. if (cs_gdb_heaptrc in aktglobalswitches) and
  196. (cs_checkpointer in aktglobalswitches) then
  197. begin
  198. cg.a_param_reg(exprasmlist, OS_ADDR,location.reference.base,1);
  199. cg.a_call_name(exprasmlist,'FPC_CHECKPOINTER');
  200. end;
  201. end;
  202. {*****************************************************************************
  203. TCGSUBSCRIPTNODE
  204. *****************************************************************************}
  205. procedure tcgsubscriptnode.pass_2;
  206. begin
  207. secondpass(left);
  208. if codegenerror then
  209. exit;
  210. { classes and interfaces must be dereferenced implicit }
  211. if is_class_or_interface(left.resulttype.def) then
  212. begin
  213. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  214. case left.location.loc of
  215. LOC_REGISTER:
  216. begin
  217. if not rg.isaddressregister(left.location.register) then
  218. begin
  219. location_release(exprasmlist,left.location);
  220. location.reference.base:=rg.getaddressregister(exprasmlist);
  221. cg.a_load_reg_reg(exprasmlist,OS_ADDR,
  222. left.location.register,location.reference.base);
  223. end
  224. else
  225. location.reference.base := left.location.register;
  226. end;
  227. LOC_CREGISTER,
  228. LOC_CREFERENCE,
  229. LOC_REFERENCE:
  230. begin
  231. location_release(exprasmlist,left.location);
  232. location.reference.base:=rg.getaddressregister(exprasmlist);
  233. cg.a_load_loc_reg(exprasmlist,left.location,location.reference.base);
  234. end;
  235. end;
  236. end
  237. else if is_interfacecom(left.resulttype.def) then
  238. begin
  239. tg.gettempintfcomreference(exprasmlist,location.reference);
  240. cg.a_load_loc_ref(exprasmlist,left.location,location.reference);
  241. end
  242. else
  243. location_copy(location,left.location);
  244. inc(location.reference.offset,vs.address);
  245. { also update the size of the location }
  246. location.size:=def_cgsize(resulttype.def);
  247. end;
  248. {*****************************************************************************
  249. TCGSELFNODE
  250. *****************************************************************************}
  251. procedure tcgselfnode.pass_2;
  252. begin
  253. rg.getexplicitregisterint(exprasmlist,SELF_POINTER_REG);
  254. if (resulttype.def.deftype=classrefdef) or
  255. is_class(resulttype.def) then
  256. begin
  257. location_reset(location,LOC_CREGISTER,OS_ADDR);
  258. location.register:=SELF_POINTER_REG;
  259. end
  260. else
  261. begin
  262. location_reset(location,LOC_CREFERENCE,OS_ADDR);
  263. location.reference.base:=SELF_POINTER_REG;
  264. end;
  265. end;
  266. {*****************************************************************************
  267. TCGWITHNODE
  268. *****************************************************************************}
  269. procedure tcgwithnode.pass_2;
  270. var
  271. tmpreg: tregister;
  272. usetemp,with_expr_in_temp : boolean;
  273. {$ifdef GDB}
  274. withstartlabel,withendlabel : tasmlabel;
  275. pp : pchar;
  276. mangled_length : longint;
  277. const
  278. withlevel : longint = 0;
  279. {$endif GDB}
  280. begin
  281. if assigned(left) then
  282. begin
  283. secondpass(left);
  284. {$ifdef i386}
  285. if (left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  286. (left.location.reference.segment<>R_NO) then
  287. message(parser_e_no_with_for_variable_in_other_segments);
  288. {$endif i386}
  289. reference_reset(withreference);
  290. usetemp:=false;
  291. if (left.nodetype=loadn) and
  292. (tloadnode(left).symtable=aktprocdef.localst) then
  293. begin
  294. { for locals use the local storage }
  295. withreference:=left.location.reference;
  296. include(flags,nf_islocal);
  297. end
  298. else
  299. { call can have happend with a property }
  300. begin
  301. tmpreg := cg.get_scratch_reg(exprasmlist);
  302. usetemp:=true;
  303. if is_class_or_interface(left.resulttype.def) then
  304. cg.a_load_loc_reg(exprasmlist,left.location,tmpreg)
  305. else
  306. cg.a_loadaddr_ref_reg(exprasmlist,
  307. left.location.reference,tmpreg);
  308. end;
  309. location_release(exprasmlist,left.location);
  310. { if the with expression is stored in a temp }
  311. { area we must make it persistent and shouldn't }
  312. { release it (FK) }
  313. if (left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) and
  314. tg.istemp(left.location.reference) then
  315. begin
  316. tg.normaltemptopersistant(left.location.reference.offset);
  317. with_expr_in_temp:=true;
  318. end
  319. else
  320. with_expr_in_temp:=false;
  321. { if usetemp is set the value must be in tmpreg }
  322. if usetemp then
  323. begin
  324. tg.gettempofsizereference(exprasmlist,pointer_size,withreference);
  325. tg.normaltemptopersistant(withreference.offset);
  326. { move to temp reference }
  327. cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,withreference);
  328. cg.free_scratch_reg(exprasmlist,tmpreg);
  329. {$ifdef GDB}
  330. if (cs_debuginfo in aktmoduleswitches) then
  331. begin
  332. inc(withlevel);
  333. getaddrlabel(withstartlabel);
  334. getaddrlabel(withendlabel);
  335. cg.a_label(exprasmlist,withstartlabel);
  336. withdebugList.concat(Tai_stabs.Create(strpnew(
  337. '"with'+tostr(withlevel)+':'+tostr(symtablestack.getnewtypecount)+
  338. '=*'+tstoreddef(left.resulttype.def).numberstring+'",'+
  339. tostr(N_LSYM)+',0,0,'+tostr(withreference.offset))));
  340. mangled_length:=length(aktprocdef.mangledname);
  341. getmem(pp,mangled_length+50);
  342. strpcopy(pp,'192,0,0,'+withstartlabel.name);
  343. if (target_info.use_function_relative_addresses) then
  344. begin
  345. strpcopy(strend(pp),'-');
  346. strpcopy(strend(pp),aktprocdef.mangledname);
  347. end;
  348. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  349. end;
  350. {$endif GDB}
  351. end;
  352. { right can be optimize out !!! }
  353. if assigned(right) then
  354. secondpass(right);
  355. if usetemp then
  356. begin
  357. tg.ungetpersistanttemp(exprasmlist,withreference.offset);
  358. {$ifdef GDB}
  359. if (cs_debuginfo in aktmoduleswitches) then
  360. begin
  361. cg.a_label(exprasmlist,withendlabel);
  362. strpcopy(pp,'224,0,0,'+withendlabel.name);
  363. if (target_info.use_function_relative_addresses) then
  364. begin
  365. strpcopy(strend(pp),'-');
  366. strpcopy(strend(pp),aktprocdef.mangledname);
  367. end;
  368. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  369. freemem(pp,mangled_length+50);
  370. dec(withlevel);
  371. end;
  372. {$endif GDB}
  373. end;
  374. if with_expr_in_temp then
  375. tg.ungetpersistanttemp(exprasmlist,left.location.reference.offset);
  376. reference_reset(withreference);
  377. end;
  378. end;
  379. begin
  380. cloadvmtnode:=tcgloadvmtnode;
  381. chnewnode:=tcghnewnode;
  382. chdisposenode:=tcghdisposenode;
  383. caddrnode:=tcgaddrnode;
  384. cdoubleaddrnode:=tcgdoubleaddrnode;
  385. cderefnode:=tcgderefnode;
  386. csubscriptnode:=tcgsubscriptnode;
  387. cselfnode:=tcgselfnode;
  388. cwithnode:=tcgwithnode;
  389. end.
  390. {
  391. $Log$
  392. Revision 1.11 2002-05-16 19:46:37 carl
  393. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  394. + try to fix temp allocation (still in ifdef)
  395. + generic constructor calls
  396. + start of tassembler / tmodulebase class cleanup
  397. Revision 1.9 2002/05/12 16:53:07 peter
  398. * moved entry and exitcode to ncgutil and cgobj
  399. * foreach gets extra argument for passing local data to the
  400. iterator function
  401. * -CR checks also class typecasts at runtime by changing them
  402. into as
  403. * fixed compiler to cycle with the -CR option
  404. * fixed stabs with elf writer, finally the global variables can
  405. be watched
  406. * removed a lot of routines from cga unit and replaced them by
  407. calls to cgobj
  408. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  409. u32bit then the other is typecasted also to u32bit without giving
  410. a rangecheck warning/error.
  411. * fixed pascal calling method with reversing also the high tree in
  412. the parast, detected by tcalcst3 test
  413. Revision 1.8 2002/04/20 21:32:23 carl
  414. + generic FPC_CHECKPOINTER
  415. + first parameter offset in stack now portable
  416. * rename some constants
  417. + move some cpu stuff to other units
  418. - remove unused constents
  419. * fix stacksize for some targets
  420. * fix generic size problems which depend now on EXTEND_SIZE constant
  421. Revision 1.7 2002/04/15 18:58:47 carl
  422. + target_info.size_of_pointer -> pointer_Size
  423. Revision 1.6 2002/04/04 19:05:57 peter
  424. * removed unused units
  425. * use tlocation.size in cg.a_*loc*() routines
  426. Revision 1.5 2002/04/02 17:11:28 peter
  427. * tlocation,treference update
  428. * LOC_CONSTANT added for better constant handling
  429. * secondadd splitted in multiple routines
  430. * location_force_reg added for loading a location to a register
  431. of a specified size
  432. * secondassignment parses now first the right and then the left node
  433. (this is compatible with Kylix). This saves a lot of push/pop especially
  434. with string operations
  435. * adapted some routines to use the new cg methods
  436. Revision 1.4 2002/03/31 20:26:34 jonas
  437. + a_loadfpu_* and a_loadmm_* methods in tcg
  438. * register allocation is now handled by a class and is mostly processor
  439. independent (+rgobj.pas and i386/rgcpu.pas)
  440. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  441. * some small improvements and fixes to the optimizer
  442. * some register allocation fixes
  443. * some fpuvaroffset fixes in the unary minus node
  444. * push/popusedregisters is now called rg.save/restoreusedregisters and
  445. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  446. also better optimizable)
  447. * fixed and optimized register saving/restoring for new/dispose nodes
  448. * LOC_FPU locations now also require their "register" field to be set to
  449. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  450. - list field removed of the tnode class because it's not used currently
  451. and can cause hard-to-find bugs
  452. Revision 1.3 2001/12/31 09:53:15 jonas
  453. * changed remaining "getregister32" calls to "getregisterint"
  454. Revision 1.2 2001/11/02 22:58:02 peter
  455. * procsym definition rewrite
  456. Revision 1.1 2001/09/30 16:17:17 jonas
  457. * made most constant and mem handling processor independent
  458. }