ncgmem.pas 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  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. {$ifdef delphi}
  55. sysutils,
  56. {$else}
  57. strings,
  58. {$endif}
  59. {$ifdef GDB}
  60. gdb,
  61. {$endif GDB}
  62. globtype,systems,
  63. cutils,verbose,globals,
  64. symconst,symbase,symdef,symsym,aasm,
  65. cgbase,temp_gen,pass_2,
  66. nld,ncon,nadd,
  67. cpubase,cgobj,cgcpu,
  68. cga,tgcpu;
  69. {*****************************************************************************
  70. TCGLOADNODE
  71. *****************************************************************************}
  72. procedure tcgloadvmtnode.pass_2;
  73. begin
  74. location.register:=getregister32;
  75. cg.a_load_sym_ofs_reg(exprasmlist,
  76. newasmsymbol(tobjectdef(tclassrefdef(resulttype.def).pointertype.def).vmt_mangledname),
  77. 0,location.register);
  78. end;
  79. {*****************************************************************************
  80. TCGHNEWNODE
  81. *****************************************************************************}
  82. procedure tcghnewnode.pass_2;
  83. begin
  84. end;
  85. {*****************************************************************************
  86. TCGHDISPOSENODE
  87. *****************************************************************************}
  88. procedure tcghdisposenode.pass_2;
  89. begin
  90. secondpass(left);
  91. if codegenerror then
  92. exit;
  93. { is this already set somewhere else? It wasn't present in the }
  94. { original i386 code either (JM) }
  95. { location.loc := LOC_REFERENCE; }
  96. reset_reference(location.reference);
  97. case left.location.loc of
  98. LOC_REGISTER:
  99. begin
  100. if not isaddressregister(left.location.register) then
  101. begin
  102. ungetregister(left.location.register);
  103. location.reference.index := getaddressregister;
  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,LOC_MEM,LOC_REFERENCE:
  111. begin
  112. del_location(left.location);
  113. location.reference.index:=getaddressregister;
  114. cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,
  115. location.reference.index);
  116. end;
  117. end;
  118. end;
  119. {*****************************************************************************
  120. TCGADDRNODE
  121. *****************************************************************************}
  122. procedure tcgaddrnode.pass_2;
  123. begin
  124. secondpass(left);
  125. { when loading procvar we do nothing with this node, so load the
  126. location of left }
  127. if nf_procvarload in flags then
  128. begin
  129. set_location(location,left.location);
  130. exit;
  131. end;
  132. location.loc:=LOC_REGISTER;
  133. del_reference(left.location.reference);
  134. location.register:=getaddressregister;
  135. {@ on a procvar means returning an address to the procedure that
  136. is stored in it.}
  137. { yes but left.symtableentry can be nil
  138. for example on self !! }
  139. { symtableentry can be also invalid, if left is no tree node }
  140. if (m_tp_procvar in aktmodeswitches) and
  141. (left.nodetype=loadn) and
  142. assigned(tloadnode(left).symtableentry) and
  143. (tloadnode(left).symtableentry.typ=varsym) and
  144. (tvarsym(tloadnode(left).symtableentry).vartype.def.deftype=procvardef) then
  145. cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,
  146. location.register)
  147. else
  148. cg.a_loadaddress_ref_reg(exprasmlist,left.location.reference,
  149. location.register);
  150. end;
  151. {*****************************************************************************
  152. TCGDOUBLEADDRNODE
  153. *****************************************************************************}
  154. procedure tcgdoubleaddrnode.pass_2;
  155. begin
  156. secondpass(left);
  157. location.loc:=LOC_REGISTER;
  158. del_reference(left.location.reference);
  159. location.register:=getaddressregister;
  160. cg.a_loadaddress_ref_reg(exprasmlist,left.location.reference,
  161. location.register);
  162. end;
  163. {*****************************************************************************
  164. TCGDEREFNODE
  165. *****************************************************************************}
  166. procedure tcgderefnode.pass_2;
  167. begin
  168. secondpass(left);
  169. reset_reference(location.reference);
  170. case left.location.loc of
  171. LOC_REGISTER:
  172. begin
  173. if not isaddressregister(left.location.register) then
  174. begin
  175. ungetregister(left.location.register);
  176. location.reference.base := getaddressregister;
  177. cg.a_load_reg_reg(exprasmlist,OS_ADDR,left.location.register,
  178. location.reference.base);
  179. end
  180. else
  181. location.reference.base := left.location.register;
  182. end;
  183. LOC_CREGISTER,LOC_MEM,LOC_REFERENCE:
  184. begin
  185. del_location(left.location);
  186. location.reference.base:=getaddressregister;
  187. cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,
  188. location.reference.base);
  189. end;
  190. end;
  191. { still needs generic checkpointer() support! }
  192. end;
  193. {*****************************************************************************
  194. TCGSUBSCRIPTNODE
  195. *****************************************************************************}
  196. procedure tcgsubscriptnode.pass_2;
  197. begin
  198. secondpass(left);
  199. if codegenerror then
  200. exit;
  201. { classes and interfaces must be dereferenced implicit }
  202. if is_class_or_interface(left.resulttype.def) then
  203. begin
  204. reset_reference(location.reference);
  205. case left.location.loc of
  206. LOC_REGISTER:
  207. begin
  208. if not isaddressregister(left.location.register) then
  209. begin
  210. ungetregister(left.location.register);
  211. location.reference.base := getaddressregister;
  212. cg.a_load_reg_reg(exprasmlist,OS_ADDR,
  213. left.location.register,location.reference.base);
  214. end
  215. else
  216. location.reference.base := left.location.register;
  217. end;
  218. LOC_CREGISTER,LOC_MEM,LOC_REFERENCE:
  219. begin
  220. del_location(left.location);
  221. location.reference.base:=getaddressregister;
  222. cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,
  223. location.reference.base);
  224. end;
  225. end;
  226. end
  227. else if is_interfacecom(left.resulttype.def) then
  228. begin
  229. gettempintfcomreference(location.reference);
  230. cg.a_load_loc_ref(exprasmlist,OS_ADDR,left.location,
  231. location.reference);
  232. end
  233. else
  234. set_location(location,left.location);
  235. { is this already set somewhere else? It wasn't present in the }
  236. { original i386 code either (JM) }
  237. { location.loc := LOC_REFERENCE; }
  238. inc(location.reference.offset,vs.address);
  239. end;
  240. {*****************************************************************************
  241. TCGSELFNODE
  242. *****************************************************************************}
  243. procedure tcgselfnode.pass_2;
  244. begin
  245. reset_reference(location.reference);
  246. getexplicitregister32(SELF_POINTER);
  247. if (resulttype.def.deftype=classrefdef) or
  248. is_class(resulttype.def) then
  249. begin
  250. location.loc := LOC_CREGISTER;
  251. location.register:=SELF_POINTER;
  252. end
  253. else
  254. begin
  255. location.loc := LOC_REFERENCE;
  256. location.reference.base:=SELF_POINTER;
  257. end;
  258. end;
  259. {*****************************************************************************
  260. TCGWITHNODE
  261. *****************************************************************************}
  262. procedure tcgwithnode.pass_2;
  263. var
  264. tmpreg: tregister;
  265. usetemp,with_expr_in_temp : boolean;
  266. {$ifdef GDB}
  267. withstartlabel,withendlabel : tasmlabel;
  268. pp : pchar;
  269. mangled_length : longint;
  270. const
  271. withlevel : longint = 0;
  272. {$endif GDB}
  273. begin
  274. if assigned(left) then
  275. begin
  276. secondpass(left);
  277. {$ifdef i386}
  278. if left.location.reference.segment<>R_NO then
  279. message(parser_e_no_with_for_variable_in_other_segments);
  280. {$endif i386}
  281. new(withreference);
  282. usetemp:=false;
  283. if (left.nodetype=loadn) and
  284. (tloadnode(left).symtable=aktprocdef.localst) then
  285. begin
  286. { for locals use the local storage }
  287. withreference^:=left.location.reference;
  288. include(flags,nf_islocal);
  289. end
  290. else
  291. { call can have happend with a property }
  292. begin
  293. tmpreg := cg.get_scratch_reg(exprasmlist);
  294. usetemp:=true;
  295. if is_class_or_interface(left.resulttype.def) then
  296. cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,tmpreg)
  297. else
  298. cg.a_loadaddress_ref_reg(exprasmlist,
  299. left.location.reference,tmpreg);
  300. end;
  301. del_location(left.location);
  302. { if the with expression is stored in a temp }
  303. { area we must make it persistent and shouldn't }
  304. { release it (FK) }
  305. if (left.location.loc in [LOC_MEM,LOC_REFERENCE]) and
  306. istemp(left.location.reference) then
  307. begin
  308. normaltemptopersistant(left.location.reference.offset);
  309. with_expr_in_temp:=true;
  310. end
  311. else
  312. with_expr_in_temp:=false;
  313. { if usetemp is set the value must be in tmpreg }
  314. if usetemp then
  315. begin
  316. gettempofsizereference(target_info.size_of_pointer,
  317. withreference^);
  318. normaltemptopersistant(withreference^.offset);
  319. { move to temp reference }
  320. cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,withreference^);
  321. cg.free_scratch_reg(exprasmlist,tmpreg);
  322. {$ifdef GDB}
  323. if (cs_debuginfo in aktmoduleswitches) then
  324. begin
  325. inc(withlevel);
  326. getaddrlabel(withstartlabel);
  327. getaddrlabel(withendlabel);
  328. emitlab(withstartlabel);
  329. withdebugList.concat(Tai_stabs.Create(strpnew(
  330. '"with'+tostr(withlevel)+':'+tostr(symtablestack.getnewtypecount)+
  331. '=*'+tstoreddef(left.resulttype.def).numberstring+'",'+
  332. tostr(N_LSYM)+',0,0,'+tostr(withreference^.offset))));
  333. mangled_length:=length(aktprocdef.mangledname);
  334. getmem(pp,mangled_length+50);
  335. strpcopy(pp,'192,0,0,'+withstartlabel.name);
  336. if (target_info.use_function_relative_addresses) then
  337. begin
  338. strpcopy(strend(pp),'-');
  339. strpcopy(strend(pp),aktprocdef.mangledname);
  340. end;
  341. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  342. end;
  343. {$endif GDB}
  344. end;
  345. { right can be optimize out !!! }
  346. if assigned(right) then
  347. secondpass(right);
  348. if usetemp then
  349. begin
  350. ungetpersistanttemp(withreference^.offset);
  351. {$ifdef GDB}
  352. if (cs_debuginfo in aktmoduleswitches) then
  353. begin
  354. emitlab(withendlabel);
  355. strpcopy(pp,'224,0,0,'+withendlabel.name);
  356. if (target_info.use_function_relative_addresses) then
  357. begin
  358. strpcopy(strend(pp),'-');
  359. strpcopy(strend(pp),aktprocdef.mangledname);
  360. end;
  361. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  362. freemem(pp,mangled_length+50);
  363. dec(withlevel);
  364. end;
  365. {$endif GDB}
  366. end;
  367. if with_expr_in_temp then
  368. ungetpersistanttemp(left.location.reference.offset);
  369. dispose(withreference);
  370. withreference:=nil;
  371. end;
  372. end;
  373. begin
  374. cloadvmtnode:=tcgloadvmtnode;
  375. chnewnode:=tcghnewnode;
  376. chdisposenode:=tcghdisposenode;
  377. caddrnode:=tcgaddrnode;
  378. cdoubleaddrnode:=tcgdoubleaddrnode;
  379. cderefnode:=tcgderefnode;
  380. csubscriptnode:=tcgsubscriptnode;
  381. cselfnode:=tcgselfnode;
  382. cwithnode:=tcgwithnode;
  383. end.
  384. {
  385. $Log$
  386. Revision 1.2 2001-11-02 22:58:02 peter
  387. * procsym definition rewrite
  388. Revision 1.1 2001/09/30 16:17:17 jonas
  389. * made most constant and mem handling processor independent
  390. }