ncgmem.pas 20 KB

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