ncgmem.pas 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177
  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. { This unit generate assembler for memory related nodes.
  20. }
  21. unit ncgmem;
  22. {$i fpcdefs.inc}
  23. interface
  24. uses
  25. cginfo,cpuinfo,cpubase,
  26. node,nmem;
  27. type
  28. tcgloadvmtaddrnode = class(tloadvmtaddrnode)
  29. procedure pass_2;override;
  30. end;
  31. tcgloadparentfpnode = class(tloadparentfpnode)
  32. procedure pass_2;override;
  33. end;
  34. tcgaddrnode = class(taddrnode)
  35. procedure pass_2;override;
  36. end;
  37. tcgderefnode = class(tderefnode)
  38. procedure pass_2;override;
  39. end;
  40. tcgsubscriptnode = class(tsubscriptnode)
  41. procedure pass_2;override;
  42. end;
  43. tcgwithnode = class(twithnode)
  44. procedure pass_2;override;
  45. end;
  46. tcgvecnode = class(tvecnode)
  47. private
  48. procedure rangecheck_array;
  49. protected
  50. function get_mul_size : longint;
  51. {# This routine is used to calculate the address of the reference.
  52. On entry reg contains the index in the array,
  53. and l contains the size of each element in the array.
  54. This routine should update location.reference correctly,
  55. so it points to the correct address.
  56. }
  57. procedure update_reference_reg_mul(reg:tregister;l:aword);virtual;
  58. procedure second_wideansistring;virtual;
  59. procedure second_dynamicarray;virtual;
  60. public
  61. procedure pass_2;override;
  62. end;
  63. implementation
  64. uses
  65. {$ifdef delphi}
  66. sysutils,
  67. {$else}
  68. strings,
  69. {$endif}
  70. {$ifdef GDB}
  71. gdb,
  72. {$endif GDB}
  73. globtype,systems,
  74. cutils,verbose,globals,
  75. symconst,symdef,symsym,symtable,defutil,paramgr,
  76. aasmbase,aasmtai,
  77. cgbase,pass_2,
  78. pass_1,nld,ncon,nadd,
  79. cgobj,tgobj,rgobj,ncgutil,symbase
  80. ;
  81. {*****************************************************************************
  82. TCGLOADVMTADDRNODE
  83. *****************************************************************************}
  84. procedure tcgloadvmtaddrnode.pass_2;
  85. var
  86. href : treference;
  87. begin
  88. location_reset(location,LOC_REGISTER,OS_ADDR);
  89. if (left.nodetype<>typen) then
  90. begin
  91. { left contains self, load vmt from self }
  92. secondpass(left);
  93. if is_object(left.resulttype.def) then
  94. begin
  95. case left.location.loc of
  96. LOC_CREFERENCE,
  97. LOC_REFERENCE:
  98. begin
  99. location_release(exprasmlist,left.location);
  100. reference_reset_base(href,rg.getaddressregister(exprasmlist),tobjectdef(left.resulttype.def).vmt_offset);
  101. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,href.base);
  102. end;
  103. else
  104. internalerror(200305056);
  105. end;
  106. end
  107. else
  108. begin
  109. case left.location.loc of
  110. LOC_REGISTER:
  111. begin
  112. if not rg.isaddressregister(left.location.register) then
  113. begin
  114. location_release(exprasmlist,left.location);
  115. reference_reset_base(href,rg.getaddressregister(exprasmlist),tobjectdef(left.resulttype.def).vmt_offset);
  116. cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.register,href.base);
  117. end
  118. else
  119. reference_reset_base(href,left.location.register,tobjectdef(left.resulttype.def).vmt_offset);
  120. end;
  121. LOC_CREGISTER,
  122. LOC_CREFERENCE,
  123. LOC_REFERENCE:
  124. begin
  125. location_release(exprasmlist,left.location);
  126. reference_reset_base(href,rg.getaddressregister(exprasmlist),tobjectdef(left.resulttype.def).vmt_offset);
  127. cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,href.base);
  128. end;
  129. else
  130. internalerror(200305057);
  131. end;
  132. end;
  133. reference_release(exprasmlist,href);
  134. location.register:=rg.getaddressregister(exprasmlist);
  135. cg.g_maybe_testself(exprasmlist,href.base);
  136. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,location.register);
  137. end
  138. else
  139. begin
  140. reference_reset_symbol(href,
  141. objectlibrary.newasmsymboldata(tobjectdef(tclassrefdef(resulttype.def).pointertype.def).vmt_mangledname),0);
  142. location.register:=rg.getaddressregister(exprasmlist);
  143. cg.a_loadaddr_ref_reg(exprasmlist,href,location.register);
  144. end;
  145. end;
  146. {*****************************************************************************
  147. TCGLOADPARENTFPNODE
  148. *****************************************************************************}
  149. procedure tcgloadparentfpnode.pass_2;
  150. var
  151. currpi : tprocinfo;
  152. hsym : tvarsym;
  153. href : treference;
  154. begin
  155. if (current_procinfo.procdef.parast.symtablelevel=parentpd.parast.symtablelevel) then
  156. begin
  157. location_reset(location,LOC_REGISTER,OS_ADDR);
  158. location.register:=current_procinfo.framepointer;
  159. end
  160. else
  161. begin
  162. currpi:=current_procinfo;
  163. location_reset(location,LOC_REGISTER,OS_ADDR);
  164. location.register:=rg.getaddressregister(exprasmlist);
  165. { load framepointer of current proc }
  166. hsym:=tvarsym(currpi.procdef.parast.search('parentfp'));
  167. if not assigned(hsym) then
  168. internalerror(200309281);
  169. case hsym.localloc.loc of
  170. LOC_REFERENCE :
  171. begin
  172. reference_reset_base(href,hsym.localloc.reference.index,hsym.localloc.reference.offset);
  173. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,location.register);
  174. end;
  175. LOC_REGISTER :
  176. cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,hsym.localloc.register,location.register);
  177. end;
  178. { walk parents }
  179. while (currpi.procdef.owner.symtablelevel>parentpd.parast.symtablelevel) do
  180. begin
  181. hsym:=tvarsym(currpi.procdef.parast.search('parentfp'));
  182. if not assigned(hsym) then
  183. internalerror(200309282);
  184. if hsym.localloc.loc<>LOC_REFERENCE then
  185. internalerror(200309283);
  186. reference_reset_base(href,location.register,hsym.localloc.reference.offset);
  187. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,location.register);
  188. currpi:=currpi.parent;
  189. end;
  190. end;
  191. end;
  192. {*****************************************************************************
  193. TCGADDRNODE
  194. *****************************************************************************}
  195. procedure tcgaddrnode.pass_2;
  196. begin
  197. secondpass(left);
  198. { when loading procvar we do nothing with this node, so load the
  199. location of left }
  200. if nf_procvarload in flags then
  201. begin
  202. location_copy(location,left.location);
  203. exit;
  204. end;
  205. location_release(exprasmlist,left.location);
  206. location_reset(location,LOC_REGISTER,OS_ADDR);
  207. location.register:=rg.getaddressregister(exprasmlist);
  208. { @ on a procvar means returning an address to the procedure that
  209. is stored in it }
  210. if (m_tp_procvar in aktmodeswitches) and
  211. (left.nodetype=loadn) and
  212. (tloadnode(left).resulttype.def.deftype=procvardef) and
  213. assigned(tloadnode(left).symtableentry) and
  214. (tloadnode(left).symtableentry.typ=varsym) then
  215. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.reference,location.register)
  216. else
  217. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,location.register);
  218. end;
  219. {*****************************************************************************
  220. TCGDEREFNODE
  221. *****************************************************************************}
  222. procedure tcgderefnode.pass_2;
  223. var
  224. paraloc1 : tparalocation;
  225. begin
  226. secondpass(left);
  227. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  228. case left.location.loc of
  229. LOC_REGISTER:
  230. begin
  231. if not rg.isaddressregister(left.location.register) then
  232. begin
  233. location_release(exprasmlist,left.location);
  234. location.reference.base := rg.getaddressregister(exprasmlist);
  235. cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.register,
  236. location.reference.base);
  237. end
  238. else
  239. location.reference.base := left.location.register;
  240. end;
  241. LOC_CREGISTER,
  242. LOC_CREFERENCE,
  243. LOC_REFERENCE:
  244. begin
  245. location_release(exprasmlist,left.location);
  246. location.reference.base:=rg.getaddressregister(exprasmlist);
  247. cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,location.reference.base);
  248. end;
  249. end;
  250. if (cs_gdb_heaptrc in aktglobalswitches) and
  251. (cs_checkpointer in aktglobalswitches) and
  252. not(cs_compilesystem in aktmoduleswitches) and
  253. (not tpointerdef(left.resulttype.def).is_far) then
  254. begin
  255. paraloc1:=paramanager.getintparaloc(pocall_default,1);
  256. paramanager.allocparaloc(exprasmlist,paraloc1);
  257. cg.a_param_reg(exprasmlist, OS_ADDR,location.reference.base,paraloc1);
  258. paramanager.freeparaloc(exprasmlist,paraloc1);
  259. rg.allocexplicitregistersint(exprasmlist,paramanager.get_volatile_registers_int(pocall_default));
  260. cg.a_call_name(exprasmlist,'FPC_CHECKPOINTER');
  261. rg.deallocexplicitregistersint(exprasmlist,paramanager.get_volatile_registers_int(pocall_default));
  262. end;
  263. end;
  264. {*****************************************************************************
  265. TCGSUBSCRIPTNODE
  266. *****************************************************************************}
  267. procedure tcgsubscriptnode.pass_2;
  268. var
  269. paraloc1 : tparalocation;
  270. begin
  271. secondpass(left);
  272. if codegenerror then
  273. exit;
  274. { classes and interfaces must be dereferenced implicit }
  275. if is_class_or_interface(left.resulttype.def) then
  276. begin
  277. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  278. case left.location.loc of
  279. LOC_CREGISTER,
  280. LOC_REGISTER:
  281. begin
  282. if not rg.isaddressregister(left.location.register) then
  283. begin
  284. location_release(exprasmlist,left.location);
  285. location.reference.base:=rg.getaddressregister(exprasmlist);
  286. cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,
  287. left.location.register,location.reference.base);
  288. end
  289. else
  290. location.reference.base := left.location.register;
  291. end;
  292. LOC_CREFERENCE,
  293. LOC_REFERENCE:
  294. begin
  295. location_release(exprasmlist,left.location);
  296. location.reference.base:=rg.getaddressregister(exprasmlist);
  297. cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,location.reference.base);
  298. end;
  299. end;
  300. { implicit deferencing }
  301. if (cs_gdb_heaptrc in aktglobalswitches) and
  302. (cs_checkpointer in aktglobalswitches) and
  303. not(cs_compilesystem in aktmoduleswitches) then
  304. begin
  305. paraloc1:=paramanager.getintparaloc(pocall_default,1);
  306. paramanager.allocparaloc(exprasmlist,paraloc1);
  307. cg.a_param_reg(exprasmlist, OS_ADDR,location.reference.base,paraloc1);
  308. paramanager.freeparaloc(exprasmlist,paraloc1);
  309. rg.allocexplicitregistersint(exprasmlist,paramanager.get_volatile_registers_int(pocall_default));
  310. cg.a_call_name(exprasmlist,'FPC_CHECKPOINTER');
  311. rg.deallocexplicitregistersint(exprasmlist,paramanager.get_volatile_registers_int(pocall_default));
  312. end;
  313. end
  314. else if is_interfacecom(left.resulttype.def) then
  315. begin
  316. tg.GetTemp(exprasmlist,pointer_size,tt_interfacecom,location.reference);
  317. cg.a_load_loc_ref(exprasmlist,OS_ADDR,left.location,location.reference);
  318. { implicit deferencing also for interfaces }
  319. if (cs_gdb_heaptrc in aktglobalswitches) and
  320. (cs_checkpointer in aktglobalswitches) and
  321. not(cs_compilesystem in aktmoduleswitches) then
  322. begin
  323. paraloc1:=paramanager.getintparaloc(pocall_default,1);
  324. paramanager.allocparaloc(exprasmlist,paraloc1);
  325. cg.a_param_reg(exprasmlist, OS_ADDR,location.reference.base,paraloc1);
  326. paramanager.freeparaloc(exprasmlist,paraloc1);
  327. rg.allocexplicitregistersint(exprasmlist,paramanager.get_volatile_registers_int(pocall_default));
  328. cg.a_call_name(exprasmlist,'FPC_CHECKPOINTER');
  329. rg.allocexplicitregistersint(exprasmlist,paramanager.get_volatile_registers_int(pocall_default));
  330. end;
  331. end
  332. else
  333. location_copy(location,left.location);
  334. inc(location.reference.offset,vs.fieldoffset);
  335. { also update the size of the location }
  336. location.size:=def_cgsize(resulttype.def);
  337. end;
  338. {*****************************************************************************
  339. TCGWITHNODE
  340. *****************************************************************************}
  341. procedure tcgwithnode.pass_2;
  342. {$ifdef GDB}
  343. const
  344. withlevel : longint = 0;
  345. var
  346. withstartlabel,withendlabel : tasmlabel;
  347. pp : pchar;
  348. mangled_length : longint;
  349. {$endif GDB}
  350. begin
  351. location_reset(location,LOC_VOID,OS_NO);
  352. {$ifdef GDB}
  353. if (cs_debuginfo in aktmoduleswitches) then
  354. begin
  355. { load reference }
  356. if (withrefnode.nodetype=derefn) and
  357. (tderefnode(withrefnode).left.nodetype=temprefn) then
  358. secondpass(withrefnode);
  359. inc(withlevel);
  360. objectlibrary.getaddrlabel(withstartlabel);
  361. objectlibrary.getaddrlabel(withendlabel);
  362. cg.a_label(exprasmlist,withstartlabel);
  363. withdebugList.concat(Tai_stabs.Create(strpnew(
  364. '"with'+tostr(withlevel)+':'+tostr(symtablestack.getnewtypecount)+
  365. '=*'+tstoreddef(left.resulttype.def).numberstring+'",'+
  366. tostr(N_LSYM)+',0,0,'+tostr(withrefnode.location.reference.offset))));
  367. mangled_length:=length(current_procinfo.procdef.mangledname);
  368. getmem(pp,mangled_length+50);
  369. strpcopy(pp,'192,0,0,'+withstartlabel.name);
  370. if (target_info.use_function_relative_addresses) then
  371. begin
  372. strpcopy(strend(pp),'-');
  373. strpcopy(strend(pp),current_procinfo.procdef.mangledname);
  374. end;
  375. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  376. end;
  377. {$endif GDB}
  378. if assigned(left) then
  379. secondpass(left);
  380. {$ifdef GDB}
  381. if (cs_debuginfo in aktmoduleswitches) then
  382. begin
  383. cg.a_label(exprasmlist,withendlabel);
  384. strpcopy(pp,'224,0,0,'+withendlabel.name);
  385. if (target_info.use_function_relative_addresses) then
  386. begin
  387. strpcopy(strend(pp),'-');
  388. strpcopy(strend(pp),current_procinfo.procdef.mangledname);
  389. end;
  390. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  391. freemem(pp,mangled_length+50);
  392. dec(withlevel);
  393. end;
  394. {$endif GDB}
  395. end;
  396. {*****************************************************************************
  397. TCGVECNODE
  398. *****************************************************************************}
  399. function tcgvecnode.get_mul_size : longint;
  400. begin
  401. if nf_memindex in flags then
  402. get_mul_size:=1
  403. else
  404. begin
  405. if (left.resulttype.def.deftype=arraydef) then
  406. get_mul_size:=tarraydef(left.resulttype.def).elesize
  407. else
  408. get_mul_size:=resulttype.def.size;
  409. end
  410. end;
  411. procedure tcgvecnode.update_reference_reg_mul(reg:tregister;l:aword);
  412. var
  413. hreg: tregister;
  414. begin
  415. if location.reference.base=NR_NO then
  416. begin
  417. cg.a_op_const_reg(exprasmlist,OP_IMUL,OS_ADDR,l,reg);
  418. location.reference.base:=reg;
  419. end
  420. else if location.reference.index=NR_NO then
  421. begin
  422. cg.a_op_const_reg(exprasmlist,OP_IMUL,OS_ADDR,l,reg);
  423. location.reference.index:=reg;
  424. end
  425. else
  426. begin
  427. rg.ungetreference(exprasmlist,location.reference);
  428. hreg := rg.getaddressregister(exprasmlist);
  429. cg.a_loadaddr_ref_reg(exprasmlist,location.reference,hreg);
  430. reference_reset_base(location.reference,hreg,0);
  431. { insert new index register }
  432. cg.a_op_const_reg(exprasmlist,OP_IMUL,OS_ADDR,l,reg);
  433. location.reference.index:=reg;
  434. end;
  435. end;
  436. procedure tcgvecnode.second_wideansistring;
  437. begin
  438. end;
  439. procedure tcgvecnode.second_dynamicarray;
  440. begin
  441. end;
  442. procedure tcgvecnode.rangecheck_array;
  443. var
  444. freereg : boolean;
  445. hightree : tnode;
  446. poslabel,
  447. neglabel : tasmlabel;
  448. hreg : tregister;
  449. paraloc1,paraloc2 : tparalocation;
  450. begin
  451. if is_open_array(left.resulttype.def) or
  452. is_array_of_const(left.resulttype.def) then
  453. begin
  454. { cdecl functions don't have high() so we can not check the range }
  455. if not(current_procinfo.procdef.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
  456. begin
  457. { Get high value }
  458. hightree:=load_high_value_node(tvarsym(tloadnode(left).symtableentry));
  459. { it must be available }
  460. if not assigned(hightree) then
  461. internalerror(200212201);
  462. firstpass(hightree);
  463. secondpass(hightree);
  464. { generate compares }
  465. freereg:=false;
  466. if (right.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  467. hreg:=right.location.register
  468. else
  469. begin
  470. hreg:=rg.getregisterint(exprasmlist,OS_INT);
  471. freereg:=true;
  472. cg.a_load_loc_reg(exprasmlist,OS_INT,right.location,hreg);
  473. end;
  474. objectlibrary.getlabel(neglabel);
  475. objectlibrary.getlabel(poslabel);
  476. cg.a_cmp_const_reg_label(exprasmlist,OS_INT,OC_LT,0,hreg,poslabel);
  477. cg.a_cmp_loc_reg_label(exprasmlist,OS_INT,OC_BE,hightree.location,hreg,neglabel);
  478. if freereg then
  479. rg.ungetregisterint(exprasmlist,hreg);
  480. cg.a_label(exprasmlist,poslabel);
  481. cg.a_call_name(exprasmlist,'FPC_RANGEERROR');
  482. cg.a_label(exprasmlist,neglabel);
  483. { release hightree }
  484. location_release(exprasmlist,hightree.location);
  485. hightree.free;
  486. end;
  487. end
  488. else
  489. if is_dynamic_array(left.resulttype.def) then
  490. begin
  491. paraloc1:=paramanager.getintparaloc(pocall_default,1);
  492. paraloc2:=paramanager.getintparaloc(pocall_default,2);
  493. paramanager.allocparaloc(exprasmlist,paraloc2);
  494. cg.a_param_loc(exprasmlist,right.location,paraloc2);
  495. paramanager.allocparaloc(exprasmlist,paraloc1);
  496. cg.a_param_loc(exprasmlist,left.location,paraloc1);
  497. paramanager.freeparaloc(exprasmlist,paraloc1);
  498. paramanager.freeparaloc(exprasmlist,paraloc2);
  499. rg.allocexplicitregistersint(exprasmlist,paramanager.get_volatile_registers_int(pocall_default));
  500. cg.a_call_name(exprasmlist,'FPC_DYNARRAY_RANGECHECK');
  501. rg.deallocexplicitregistersint(exprasmlist,paramanager.get_volatile_registers_int(pocall_default));
  502. end
  503. else
  504. cg.g_rangecheck(exprasmlist,right.location,right.resulttype.def,left.resulttype.def);
  505. end;
  506. procedure tcgvecnode.pass_2;
  507. var
  508. extraoffset : longint;
  509. t : tnode;
  510. href : treference;
  511. otl,ofl : tasmlabel;
  512. newsize : tcgsize;
  513. mulsize: longint;
  514. isjump : boolean;
  515. paraloc1,paraloc2 : tparalocation;
  516. begin
  517. mulsize := get_mul_size;
  518. newsize:=def_cgsize(resulttype.def);
  519. secondpass(left);
  520. if left.location.loc=LOC_CREFERENCE then
  521. location_reset(location,LOC_CREFERENCE,newsize)
  522. else
  523. location_reset(location,LOC_REFERENCE,newsize);
  524. { an ansistring needs to be dereferenced }
  525. if is_ansistring(left.resulttype.def) or
  526. is_widestring(left.resulttype.def) then
  527. begin
  528. if nf_callunique in flags then
  529. internalerror(200304236);
  530. case left.location.loc of
  531. LOC_REGISTER,
  532. LOC_CREGISTER :
  533. location.reference.base:=left.location.register;
  534. LOC_CREFERENCE,
  535. LOC_REFERENCE :
  536. begin
  537. location_release(exprasmlist,left.location);
  538. location.reference.base:=rg.getaddressregister(exprasmlist);
  539. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.reference,location.reference.base);
  540. end;
  541. else
  542. internalerror(2002032218);
  543. end;
  544. { check for a zero length string,
  545. we can use the ansistring routine here }
  546. if (cs_check_range in aktlocalswitches) then
  547. begin
  548. paraloc1:=paramanager.getintparaloc(pocall_default,1);
  549. paramanager.allocparaloc(exprasmlist,paraloc1);
  550. cg.a_param_reg(exprasmlist,OS_ADDR,location.reference.base,paraloc1);
  551. paramanager.freeparaloc(exprasmlist,paraloc1);
  552. rg.allocexplicitregistersint(exprasmlist,paramanager.get_volatile_registers_int(pocall_default));
  553. cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_CHECKZERO');
  554. rg.deallocexplicitregistersint(exprasmlist,paramanager.get_volatile_registers_int(pocall_default));
  555. end;
  556. { in ansistrings/widestrings S[1] is p<w>char(S)[0] !! }
  557. if is_ansistring(left.resulttype.def) then
  558. dec(location.reference.offset)
  559. else
  560. dec(location.reference.offset,2);
  561. end
  562. else if is_dynamic_array(left.resulttype.def) then
  563. begin
  564. case left.location.loc of
  565. LOC_REGISTER,
  566. LOC_CREGISTER :
  567. location.reference.base:=left.location.register;
  568. LOC_REFERENCE,
  569. LOC_CREFERENCE :
  570. begin
  571. location_release(exprasmlist,left.location);
  572. location.reference.base:=rg.getaddressregister(exprasmlist);
  573. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,
  574. left.location.reference,location.reference.base);
  575. end;
  576. else
  577. internalerror(2002032219);
  578. end;
  579. end
  580. else
  581. location_copy(location,left.location);
  582. { offset can only differ from 0 if arraydef }
  583. if (left.resulttype.def.deftype=arraydef) and
  584. not(is_dynamic_array(left.resulttype.def)) then
  585. dec(location.reference.offset,mulsize*tarraydef(left.resulttype.def).lowrange);
  586. if right.nodetype=ordconstn then
  587. begin
  588. { offset can only differ from 0 if arraydef }
  589. case left.resulttype.def.deftype of
  590. arraydef :
  591. begin
  592. if not(is_open_array(left.resulttype.def)) and
  593. not(is_array_of_const(left.resulttype.def)) and
  594. not(is_dynamic_array(left.resulttype.def)) then
  595. begin
  596. if (tordconstnode(right).value>tarraydef(left.resulttype.def).highrange) or
  597. (tordconstnode(right).value<tarraydef(left.resulttype.def).lowrange) then
  598. begin
  599. { this should be caught in the resulttypepass! (JM) }
  600. if (cs_check_range in aktlocalswitches) then
  601. CGMessage(parser_e_range_check_error)
  602. else
  603. CGMessage(parser_w_range_check_error);
  604. end;
  605. end
  606. else
  607. begin
  608. { range checking for open and dynamic arrays needs
  609. runtime code }
  610. secondpass(right);
  611. if (cs_check_range in aktlocalswitches) then
  612. rangecheck_array;
  613. end;
  614. end;
  615. stringdef :
  616. begin
  617. if (cs_check_range in aktlocalswitches) then
  618. begin
  619. case tstringdef(left.resulttype.def).string_typ of
  620. { it's the same for ansi- and wide strings }
  621. st_widestring,
  622. st_ansistring:
  623. begin
  624. paraloc1:=paramanager.getintparaloc(pocall_default,1);
  625. paraloc2:=paramanager.getintparaloc(pocall_default,2);
  626. paramanager.allocparaloc(exprasmlist,paraloc2);
  627. cg.a_param_const(exprasmlist,OS_INT,tordconstnode(right).value,paraloc2);
  628. href:=location.reference;
  629. dec(href.offset,7);
  630. paramanager.allocparaloc(exprasmlist,paraloc1);
  631. cg.a_param_ref(exprasmlist,OS_INT,href,paraloc1);
  632. paramanager.freeparaloc(exprasmlist,paraloc1);
  633. paramanager.freeparaloc(exprasmlist,paraloc2);
  634. rg.allocexplicitregistersint(exprasmlist,paramanager.get_volatile_registers_int(pocall_default));
  635. cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_RANGECHECK');
  636. rg.deallocexplicitregistersint(exprasmlist,paramanager.get_volatile_registers_int(pocall_default));
  637. end;
  638. st_shortstring:
  639. begin
  640. {!!!!!!!!!!!!!!!!!}
  641. end;
  642. st_longstring:
  643. begin
  644. {!!!!!!!!!!!!!!!!!}
  645. end;
  646. end;
  647. end;
  648. end;
  649. end;
  650. inc(location.reference.offset,
  651. mulsize*tordconstnode(right).value);
  652. end
  653. else
  654. { not nodetype=ordconstn }
  655. begin
  656. if (cs_regvars in aktglobalswitches) and
  657. { if we do range checking, we don't }
  658. { need that fancy code (it would be }
  659. { buggy) }
  660. not(cs_check_range in aktlocalswitches) and
  661. (left.resulttype.def.deftype=arraydef) then
  662. begin
  663. extraoffset:=0;
  664. if (right.nodetype=addn) then
  665. begin
  666. if taddnode(right).right.nodetype=ordconstn then
  667. begin
  668. extraoffset:=tordconstnode(taddnode(right).right).value;
  669. t:=taddnode(right).left;
  670. { First pass processed this with the assumption }
  671. { that there was an add node which may require an }
  672. { extra register. Fake it or die with IE10 (JM) }
  673. t.registers32 := taddnode(right).registers32;
  674. taddnode(right).left:=nil;
  675. right.free;
  676. right:=t;
  677. end
  678. else if taddnode(right).left.nodetype=ordconstn then
  679. begin
  680. extraoffset:=tordconstnode(taddnode(right).left).value;
  681. t:=taddnode(right).right;
  682. t.registers32 := right.registers32;
  683. taddnode(right).right:=nil;
  684. right.free;
  685. right:=t;
  686. end;
  687. end
  688. else if (right.nodetype=subn) then
  689. begin
  690. if taddnode(right).right.nodetype=ordconstn then
  691. begin
  692. extraoffset:=-tordconstnode(taddnode(right).right).value;
  693. t:=taddnode(right).left;
  694. t.registers32 := right.registers32;
  695. taddnode(right).left:=nil;
  696. right.free;
  697. right:=t;
  698. end
  699. { You also have to negate right.right in this case! I can't add an
  700. unaryminusn without causing a crash, so I've disabled it (JM)
  701. else if right.left.nodetype=ordconstn then
  702. begin
  703. extraoffset:=right.left.value;
  704. t:=right.right;
  705. t^.registers32 := right.registers32;
  706. putnode(right);
  707. putnode(right.left);
  708. right:=t;
  709. end;}
  710. end;
  711. inc(location.reference.offset,
  712. mulsize*extraoffset);
  713. end;
  714. { calculate from left to right }
  715. if not(location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  716. internalerror(200304237);
  717. isjump:=(right.location.loc=LOC_JUMP);
  718. if isjump then
  719. begin
  720. otl:=truelabel;
  721. objectlibrary.getlabel(truelabel);
  722. ofl:=falselabel;
  723. objectlibrary.getlabel(falselabel);
  724. end;
  725. secondpass(right);
  726. if cs_check_range in aktlocalswitches then
  727. begin
  728. if left.resulttype.def.deftype=arraydef then
  729. rangecheck_array;
  730. end;
  731. { if mulsize = 1, we won't have to modify the index }
  732. location_force_reg(exprasmlist,right.location,OS_32,mulsize = 1);
  733. if isjump then
  734. begin
  735. truelabel:=otl;
  736. falselabel:=ofl;
  737. end;
  738. { produce possible range check code: }
  739. if cs_check_range in aktlocalswitches then
  740. begin
  741. if left.resulttype.def.deftype=arraydef then
  742. begin
  743. { done defore (PM) }
  744. end
  745. else if (left.resulttype.def.deftype=stringdef) then
  746. begin
  747. case tstringdef(left.resulttype.def).string_typ of
  748. { it's the same for ansi- and wide strings }
  749. st_widestring,
  750. st_ansistring:
  751. begin
  752. paraloc1:=paramanager.getintparaloc(pocall_default,1);
  753. paraloc2:=paramanager.getintparaloc(pocall_default,2);
  754. paramanager.allocparaloc(exprasmlist,paraloc2);
  755. cg.a_param_reg(exprasmlist,OS_INT,right.location.register,paraloc2);
  756. href:=location.reference;
  757. dec(href.offset,7);
  758. paramanager.allocparaloc(exprasmlist,paraloc1);
  759. cg.a_param_ref(exprasmlist,OS_INT,href,paraloc1);
  760. paramanager.freeparaloc(exprasmlist,paraloc1);
  761. paramanager.freeparaloc(exprasmlist,paraloc2);
  762. rg.allocexplicitregistersint(exprasmlist,paramanager.get_volatile_registers_int(pocall_default));
  763. cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_RANGECHECK');
  764. rg.deallocexplicitregistersint(exprasmlist,paramanager.get_volatile_registers_int(pocall_default));
  765. end;
  766. st_shortstring:
  767. begin
  768. {!!!!!!!!!!!!!!!!!}
  769. end;
  770. st_longstring:
  771. begin
  772. {!!!!!!!!!!!!!!!!!}
  773. end;
  774. end;
  775. end;
  776. end;
  777. { insert the register and the multiplication factor in the
  778. reference }
  779. update_reference_reg_mul(right.location.register,mulsize);
  780. end;
  781. location.size:=newsize;
  782. end;
  783. begin
  784. cloadvmtaddrnode:=tcgloadvmtaddrnode;
  785. cloadparentfpnode:=tcgloadparentfpnode;
  786. caddrnode:=tcgaddrnode;
  787. cderefnode:=tcgderefnode;
  788. csubscriptnode:=tcgsubscriptnode;
  789. cwithnode:=tcgwithnode;
  790. cvecnode:=tcgvecnode;
  791. end.
  792. {
  793. $Log$
  794. Revision 1.74 2003-09-28 17:55:03 peter
  795. * parent framepointer changed to hidden parameter
  796. * tloadparentfpnode added
  797. Revision 1.73 2003/09/23 17:56:05 peter
  798. * locals and paras are allocated in the code generation
  799. * tvarsym.localloc contains the location of para/local when
  800. generating code for the current procedure
  801. Revision 1.72 2003/09/10 08:31:47 marco
  802. * Patch from Peter for paraloc
  803. Revision 1.71 2003/09/07 22:09:35 peter
  804. * preparations for different default calling conventions
  805. * various RA fixes
  806. Revision 1.70 2003/09/03 15:55:00 peter
  807. * NEWRA branch merged
  808. Revision 1.69.2.1 2003/08/29 17:28:59 peter
  809. * next batch of updates
  810. Revision 1.69 2003/08/10 17:25:23 peter
  811. * fixed some reported bugs
  812. Revision 1.68 2003/08/09 18:56:54 daniel
  813. * cs_regalloc renamed to cs_regvars to avoid confusion with register
  814. allocator
  815. * Some preventive changes to i386 spillinh code
  816. Revision 1.67 2003/07/23 11:01:14 jonas
  817. * several rg.allocexplicitregistersint/rg.deallocexplicitregistersint
  818. pairs round calls to helpers
  819. Revision 1.66 2003/07/06 21:50:33 jonas
  820. * fixed ppc compilation problems and changed VOLATILE_REGISTERS for x86
  821. so that it doesn't include ebp and esp anymore
  822. Revision 1.65 2003/07/06 15:31:20 daniel
  823. * Fixed register allocator. *Lots* of fixes.
  824. Revision 1.64 2003/06/17 19:24:08 jonas
  825. * fixed conversion of fpc_*str_unique to compilerproc
  826. Revision 1.63 2003/06/17 16:34:44 jonas
  827. * lots of newra fixes (need getfuncretparaloc implementation for i386)!
  828. * renamed all_intregisters to paramanager.get_volatile_registers_int(pocall_default) and made it
  829. processor dependent
  830. Revision 1.62 2003/06/13 21:19:30 peter
  831. * current_procdef removed, use current_procinfo.procdef instead
  832. Revision 1.61 2003/06/09 16:45:41 jonas
  833. * fixed update_reference_reg_mul() so that it won't modify CREGISTERs
  834. in a reference
  835. * cache value of get_mul_size()
  836. * if get_mul_size = 1, the index can be a CREGISTER since it won't be
  837. modified
  838. Revision 1.60 2003/06/07 18:57:04 jonas
  839. + added freeintparaloc
  840. * ppc get/freeintparaloc now check whether the parameter regs are
  841. properly allocated/deallocated (and get an extra list para)
  842. * ppc a_call_* now internalerrors if pi_do_call is not yet set
  843. * fixed lot of missing pi_do_call's
  844. Revision 1.59 2003/06/03 21:11:09 peter
  845. * cg.a_load_* get a from and to size specifier
  846. * makeregsize only accepts newregister
  847. * i386 uses generic tcgnotnode,tcgunaryminus
  848. Revision 1.58 2003/06/03 13:01:59 daniel
  849. * Register allocator finished
  850. Revision 1.57 2003/06/02 22:35:45 florian
  851. * better handling of CREGISTER in subscript nodes
  852. Revision 1.56 2003/06/01 21:38:06 peter
  853. * getregisterfpu size parameter added
  854. * op_const_reg size parameter added
  855. * sparc updates
  856. Revision 1.55 2003/05/30 23:49:18 jonas
  857. * a_load_loc_reg now has an extra size parameter for the destination
  858. register (properly fixes what I worked around in revision 1.106 of
  859. ncgutil.pas)
  860. Revision 1.54 2003/05/15 16:10:37 florian
  861. * fixed getintparaloc call for ansi- and widestring range checking
  862. Revision 1.53 2003/05/11 21:37:03 peter
  863. * moved implicit exception frame from ncgutil to psub
  864. * constructor/destructor helpers moved from cobj/ncgutil to psub
  865. Revision 1.52 2003/05/11 14:45:12 peter
  866. * tloadnode does not support objectsymtable,withsymtable anymore
  867. * withnode cleanup
  868. * direct with rewritten to use temprefnode
  869. Revision 1.51 2003/05/09 17:47:02 peter
  870. * self moved to hidden parameter
  871. * removed hdisposen,hnewn,selfn
  872. Revision 1.50 2003/05/07 09:16:23 mazen
  873. - non used units removed from uses clause
  874. Revision 1.49 2003/04/27 11:21:33 peter
  875. * aktprocdef renamed to current_procinfo.procdef
  876. * procinfo renamed to current_procinfo
  877. * procinfo will now be stored in current_module so it can be
  878. cleaned up properly
  879. * gen_main_procsym changed to create_main_proc and release_main_proc
  880. to also generate a tprocinfo structure
  881. * fixed unit implicit initfinal
  882. Revision 1.48 2003/04/22 23:50:22 peter
  883. * firstpass uses expectloc
  884. * checks if there are differences between the expectloc and
  885. location.loc from secondpass in EXTDEBUG
  886. Revision 1.47 2003/04/22 13:47:08 peter
  887. * fixed C style array of const
  888. * fixed C array passing
  889. * fixed left to right with high parameters
  890. Revision 1.46 2003/04/22 10:09:35 daniel
  891. + Implemented the actual register allocator
  892. + Scratch registers unavailable when new register allocator used
  893. + maybe_save/maybe_restore unavailable when new register allocator used
  894. Revision 1.45 2003/04/06 21:11:23 olle
  895. * changed newasmsymbol to newasmsymboldata for data symbols
  896. Revision 1.44 2003/03/28 19:16:56 peter
  897. * generic constructor working for i386
  898. * remove fixed self register
  899. * esi added as address register for i386
  900. Revision 1.43 2003/03/12 22:43:38 jonas
  901. * more powerpc and generic fixes related to the new register allocator
  902. Revision 1.42 2003/02/19 22:00:14 daniel
  903. * Code generator converted to new register notation
  904. - Horribily outdated todo.txt removed
  905. Revision 1.41 2003/01/30 21:46:57 peter
  906. * self fixes for static methods (merged)
  907. Revision 1.40 2003/01/08 18:43:56 daniel
  908. * Tregister changed into a record
  909. Revision 1.39 2002/12/20 18:13:19 peter
  910. * no rangecheck for openarrays with cdecl
  911. Revision 1.38 2002/12/17 22:19:33 peter
  912. * fixed pushing of records>8 bytes with stdcall
  913. * simplified hightree loading
  914. Revision 1.37 2002/12/08 13:39:03 carl
  915. + some documentation added
  916. Revision 1.36 2002/12/07 14:14:19 carl
  917. * bugfix on invalid typecast
  918. Revision 1.35 2002/11/25 17:43:18 peter
  919. * splitted defbase in defutil,symutil,defcmp
  920. * merged isconvertable and is_equal into compare_defs(_ext)
  921. * made operator search faster by walking the list only once
  922. Revision 1.34 2002/11/24 18:19:20 carl
  923. + checkpointer for interfaces also
  924. Revision 1.33 2002/11/23 22:50:06 carl
  925. * some small speed optimizations
  926. + added several new warnings/hints
  927. Revision 1.32 2002/11/15 01:58:51 peter
  928. * merged changes from 1.0.7 up to 04-11
  929. - -V option for generating bug report tracing
  930. - more tracing for option parsing
  931. - errors for cdecl and high()
  932. - win32 import stabs
  933. - win32 records<=8 are returned in eax:edx (turned off by default)
  934. - heaptrc update
  935. - more info for temp management in .s file with EXTDEBUG
  936. Revision 1.31 2002/10/09 20:24:47 florian
  937. + range checking for dyn. arrays
  938. Revision 1.30 2002/10/07 21:30:45 peter
  939. * rangecheck for open arrays added
  940. Revision 1.29 2002/10/05 12:43:25 carl
  941. * fixes for Delphi 6 compilation
  942. (warning : Some features do not work under Delphi)
  943. Revision 1.28 2002/09/17 18:54:02 jonas
  944. * a_load_reg_reg() now has two size parameters: source and dest. This
  945. allows some optimizations on architectures that don't encode the
  946. register size in the register name.
  947. Revision 1.27 2002/09/07 15:25:03 peter
  948. * old logs removed and tabs fixed
  949. Revision 1.26 2002/09/01 18:46:01 peter
  950. * fixed generic tcgvecnode
  951. * move code that updates a reference with index register and multiplier
  952. to separate method so it can be overriden for scaled indexing
  953. * i386 uses generic tcgvecnode
  954. Revision 1.25 2002/08/23 16:14:48 peter
  955. * tempgen cleanup
  956. * tt_noreuse temp type added that will be used in genentrycode
  957. Revision 1.24 2002/08/15 08:13:54 carl
  958. - a_load_sym_ofs_reg removed
  959. * loadvmt now calls loadaddr_ref_reg instead
  960. Revision 1.23 2002/08/11 14:32:26 peter
  961. * renamed current_library to objectlibrary
  962. Revision 1.22 2002/08/11 13:24:12 peter
  963. * saving of asmsymbols in ppu supported
  964. * asmsymbollist global is removed and moved into a new class
  965. tasmlibrarydata that will hold the info of a .a file which
  966. corresponds with a single module. Added librarydata to tmodule
  967. to keep the library info stored for the module. In the future the
  968. objectfiles will also be stored to the tasmlibrarydata class
  969. * all getlabel/newasmsymbol and friends are moved to the new class
  970. Revision 1.21 2002/08/11 11:36:57 jonas
  971. * always first try to use base and only then index
  972. Revision 1.20 2002/08/11 06:14:40 florian
  973. * fixed powerpc compilation problems
  974. Revision 1.19 2002/08/10 14:46:29 carl
  975. + moved target_cpu_string to cpuinfo
  976. * renamed asmmode enum.
  977. * assembler reader has now less ifdef's
  978. * move from nppcmem.pas -> ncgmem.pas vec. node.
  979. Revision 1.18 2002/07/28 21:34:31 florian
  980. * more powerpc fixes
  981. + dummy tcgvecnode
  982. Revision 1.17 2002/07/11 14:41:28 florian
  983. * start of the new generic parameter handling
  984. Revision 1.16 2002/07/07 09:52:32 florian
  985. * powerpc target fixed, very simple units can be compiled
  986. * some basic stuff for better callparanode handling, far from being finished
  987. Revision 1.15 2002/07/01 18:46:23 peter
  988. * internal linker
  989. * reorganized aasm layer
  990. Revision 1.14 2002/07/01 16:23:53 peter
  991. * cg64 patch
  992. * basics for currency
  993. * asnode updates for class and interface (not finished)
  994. Revision 1.13 2002/05/20 13:30:40 carl
  995. * bugfix of hdisponen (base must be set, not index)
  996. * more portability fixes
  997. Revision 1.12 2002/05/18 13:34:09 peter
  998. * readded missing revisions
  999. Revision 1.11 2002/05/16 19:46:37 carl
  1000. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1001. + try to fix temp allocation (still in ifdef)
  1002. + generic constructor calls
  1003. + start of tassembler / tmodulebase class cleanup
  1004. Revision 1.9 2002/05/12 16:53:07 peter
  1005. * moved entry and exitcode to ncgutil and cgobj
  1006. * foreach gets extra argument for passing local data to the
  1007. iterator function
  1008. * -CR checks also class typecasts at runtime by changing them
  1009. into as
  1010. * fixed compiler to cycle with the -CR option
  1011. * fixed stabs with elf writer, finally the global variables can
  1012. be watched
  1013. * removed a lot of routines from cga unit and replaced them by
  1014. calls to cgobj
  1015. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  1016. u32bit then the other is typecasted also to u32bit without giving
  1017. a rangecheck warning/error.
  1018. * fixed pascal calling method with reversing also the high tree in
  1019. the parast, detected by tcalcst3 test
  1020. Revision 1.8 2002/04/20 21:32:23 carl
  1021. + generic FPC_CHECKPOINTER
  1022. + first parameter offset in stack now portable
  1023. * rename some constants
  1024. + move some cpu stuff to other units
  1025. - remove unused constents
  1026. * fix stacksize for some targets
  1027. * fix generic size problems which depend now on EXTEND_SIZE constant
  1028. Revision 1.7 2002/04/15 18:58:47 carl
  1029. + target_info.size_of_pointer -> pointer_Size
  1030. Revision 1.6 2002/04/04 19:05:57 peter
  1031. * removed unused units
  1032. * use tlocation.size in cg.a_*loc*() routines
  1033. }