ncgmem.pas 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920
  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. globtype,cgbase,cpuinfo,cpubase,
  24. node,nmem;
  25. type
  26. tcgloadvmtaddrnode = class(tloadvmtaddrnode)
  27. procedure pass_2;override;
  28. end;
  29. tcgloadparentfpnode = class(tloadparentfpnode)
  30. procedure pass_2;override;
  31. end;
  32. tcgaddrnode = class(taddrnode)
  33. procedure pass_2;override;
  34. end;
  35. tcgderefnode = class(tderefnode)
  36. procedure pass_2;override;
  37. end;
  38. tcgsubscriptnode = class(tsubscriptnode)
  39. procedure pass_2;override;
  40. end;
  41. tcgwithnode = class(twithnode)
  42. procedure pass_2;override;
  43. end;
  44. tcgvecnode = class(tvecnode)
  45. private
  46. procedure rangecheck_array;
  47. protected
  48. function get_mul_size : longint;
  49. {# This routine is used to calculate the address of the reference.
  50. On entry reg contains the index in the array,
  51. and l contains the size of each element in the array.
  52. This routine should update location.reference correctly,
  53. so it points to the correct address.
  54. }
  55. procedure update_reference_reg_mul(reg:tregister;l:aint);virtual;
  56. procedure second_wideansistring;virtual;
  57. procedure second_dynamicarray;virtual;
  58. public
  59. procedure pass_2;override;
  60. end;
  61. implementation
  62. uses
  63. {$ifdef GDB}
  64. strings,
  65. gdb,
  66. {$endif GDB}
  67. systems,
  68. cutils,verbose,globals,
  69. symconst,symdef,symsym,defutil,paramgr,
  70. aasmbase,aasmtai,
  71. procinfo,pass_2,parabase,
  72. pass_1,nld,ncon,nadd,nutils,
  73. cgutils,cgobj,
  74. tgobj,ncgutil
  75. ;
  76. {*****************************************************************************
  77. TCGLOADVMTADDRNODE
  78. *****************************************************************************}
  79. procedure tcgloadvmtaddrnode.pass_2;
  80. var
  81. href : treference;
  82. begin
  83. location_reset(location,LOC_REGISTER,OS_ADDR);
  84. if (left.nodetype<>typen) then
  85. begin
  86. { left contains self, load vmt from self }
  87. secondpass(left);
  88. if is_object(left.resulttype.def) then
  89. begin
  90. case left.location.loc of
  91. LOC_CREFERENCE,
  92. LOC_REFERENCE:
  93. begin
  94. reference_reset_base(href,cg.getaddressregister(exprasmlist),tobjectdef(left.resulttype.def).vmt_offset);
  95. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,href.base);
  96. end;
  97. else
  98. internalerror(200305056);
  99. end;
  100. end
  101. else
  102. begin
  103. case left.location.loc of
  104. LOC_REGISTER:
  105. begin
  106. {$ifdef cpu_uses_separate_address_registers}
  107. if getregtype(left.location.register)<>R_ADDRESSREGISTER then
  108. begin
  109. reference_reset_base(href,cg.getaddressregister(exprasmlist),tobjectdef(left.resulttype.def).vmt_offset);
  110. cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.register,href.base);
  111. end
  112. else
  113. {$endif}
  114. reference_reset_base(href,left.location.register,tobjectdef(left.resulttype.def).vmt_offset);
  115. end;
  116. LOC_CREGISTER,
  117. LOC_CREFERENCE,
  118. LOC_REFERENCE:
  119. begin
  120. reference_reset_base(href,cg.getaddressregister(exprasmlist),tobjectdef(left.resulttype.def).vmt_offset);
  121. cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,href.base);
  122. end;
  123. else
  124. internalerror(200305057);
  125. end;
  126. end;
  127. location.register:=cg.getaddressregister(exprasmlist);
  128. cg.g_maybe_testself(exprasmlist,href.base);
  129. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,location.register);
  130. end
  131. else
  132. begin
  133. reference_reset_symbol(href,
  134. objectlibrary.newasmsymbol(tobjectdef(tclassrefdef(resulttype.def).pointertype.def).vmt_mangledname,AB_EXTERNAL,AT_DATA),0);
  135. location.register:=cg.getaddressregister(exprasmlist);
  136. cg.a_loadaddr_ref_reg(exprasmlist,href,location.register);
  137. end;
  138. end;
  139. {*****************************************************************************
  140. TCGLOADPARENTFPNODE
  141. *****************************************************************************}
  142. procedure tcgloadparentfpnode.pass_2;
  143. var
  144. currpi : tprocinfo;
  145. hsym : tvarsym;
  146. href : treference;
  147. begin
  148. if (current_procinfo.procdef.parast.symtablelevel=parentpd.parast.symtablelevel) then
  149. begin
  150. location_reset(location,LOC_REGISTER,OS_ADDR);
  151. location.register:=current_procinfo.framepointer;
  152. end
  153. else
  154. begin
  155. currpi:=current_procinfo;
  156. location_reset(location,LOC_REGISTER,OS_ADDR);
  157. location.register:=cg.getaddressregister(exprasmlist);
  158. { load framepointer of current proc }
  159. hsym:=tvarsym(currpi.procdef.parast.search('parentfp'));
  160. if not assigned(hsym) then
  161. internalerror(200309281);
  162. cg.a_load_loc_reg(exprasmlist,OS_ADDR,hsym.localloc,location.register);
  163. { walk parents }
  164. while (currpi.procdef.owner.symtablelevel>parentpd.parast.symtablelevel) do
  165. begin
  166. currpi:=currpi.parent;
  167. if not assigned(currpi) then
  168. internalerror(200311201);
  169. hsym:=tvarsym(currpi.procdef.parast.search('parentfp'));
  170. if not assigned(hsym) then
  171. internalerror(200309282);
  172. if hsym.localloc.loc<>LOC_REFERENCE then
  173. internalerror(200309283);
  174. reference_reset_base(href,location.register,hsym.localloc.reference.offset);
  175. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,location.register);
  176. end;
  177. end;
  178. end;
  179. {*****************************************************************************
  180. TCGADDRNODE
  181. *****************************************************************************}
  182. procedure tcgaddrnode.pass_2;
  183. begin
  184. secondpass(left);
  185. { when loading procvar we do nothing with this node, so load the
  186. location of left }
  187. if nf_procvarload in flags then
  188. begin
  189. location_copy(location,left.location);
  190. exit;
  191. end;
  192. location_reset(location,LOC_REGISTER,OS_ADDR);
  193. location.register:=cg.getaddressregister(exprasmlist);
  194. { @ on a procvar means returning an address to the procedure that
  195. is stored in it }
  196. if (m_tp_procvar in aktmodeswitches) and
  197. (left.nodetype=loadn) and
  198. (tloadnode(left).resulttype.def.deftype=procvardef) and
  199. assigned(tloadnode(left).symtableentry) and
  200. (tloadnode(left).symtableentry.typ=varsym) then
  201. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.reference,location.register)
  202. else
  203. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,location.register);
  204. end;
  205. {*****************************************************************************
  206. TCGDEREFNODE
  207. *****************************************************************************}
  208. procedure tcgderefnode.pass_2;
  209. var
  210. paraloc1 : tcgpara;
  211. begin
  212. secondpass(left);
  213. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  214. case left.location.loc of
  215. LOC_REGISTER:
  216. begin
  217. {$ifdef cpu_uses_separate_address_registers}
  218. if getregtype(left.location.register)<>R_ADDRESSREGISTER then
  219. begin
  220. location.reference.base := cg.getaddressregister(exprasmlist);
  221. cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.register,
  222. location.reference.base);
  223. end
  224. else
  225. {$endif}
  226. location.reference.base := left.location.register;
  227. end;
  228. LOC_CREGISTER,
  229. LOC_CREFERENCE,
  230. LOC_REFERENCE:
  231. begin
  232. location.reference.base:=cg.getaddressregister(exprasmlist);
  233. cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,location.reference.base);
  234. end;
  235. end;
  236. if (cs_gdb_heaptrc in aktglobalswitches) and
  237. (cs_checkpointer in aktglobalswitches) and
  238. not(cs_compilesystem in aktmoduleswitches) and
  239. (not tpointerdef(left.resulttype.def).is_far) then
  240. begin
  241. paraloc1.init;
  242. paramanager.getintparaloc(pocall_default,1,paraloc1);
  243. paramanager.allocparaloc(exprasmlist,paraloc1);
  244. cg.a_param_reg(exprasmlist, OS_ADDR,location.reference.base,paraloc1);
  245. paramanager.freeparaloc(exprasmlist,paraloc1);
  246. paraloc1.done;
  247. cg.alloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  248. cg.a_call_name(exprasmlist,'FPC_CHECKPOINTER');
  249. cg.dealloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  250. end;
  251. end;
  252. {*****************************************************************************
  253. TCGSUBSCRIPTNODE
  254. *****************************************************************************}
  255. procedure tcgsubscriptnode.pass_2;
  256. var
  257. paraloc1 : tcgpara;
  258. begin
  259. secondpass(left);
  260. if codegenerror then
  261. exit;
  262. paraloc1.init;
  263. { classes and interfaces must be dereferenced implicit }
  264. if is_class_or_interface(left.resulttype.def) then
  265. begin
  266. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  267. case left.location.loc of
  268. LOC_CREGISTER,
  269. LOC_REGISTER:
  270. begin
  271. {$ifdef cpu_uses_separate_address_registers}
  272. if getregtype(left.location.register)<>R_ADDRESSREGISTER then
  273. begin
  274. location.reference.base:=rg.getaddressregister(exprasmlist);
  275. cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,
  276. left.location.register,location.reference.base);
  277. end
  278. else
  279. {$endif}
  280. location.reference.base := left.location.register;
  281. end;
  282. LOC_CREFERENCE,
  283. LOC_REFERENCE:
  284. begin
  285. location.reference.base:=cg.getaddressregister(exprasmlist);
  286. cg.a_load_loc_reg(exprasmlist,OS_ADDR,left.location,location.reference.base);
  287. end;
  288. end;
  289. { implicit deferencing }
  290. if (cs_gdb_heaptrc in aktglobalswitches) and
  291. (cs_checkpointer in aktglobalswitches) and
  292. not(cs_compilesystem in aktmoduleswitches) then
  293. begin
  294. paramanager.getintparaloc(pocall_default,1,paraloc1);
  295. paramanager.allocparaloc(exprasmlist,paraloc1);
  296. cg.a_param_reg(exprasmlist, OS_ADDR,location.reference.base,paraloc1);
  297. paramanager.freeparaloc(exprasmlist,paraloc1);
  298. cg.alloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  299. cg.a_call_name(exprasmlist,'FPC_CHECKPOINTER');
  300. cg.dealloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  301. end;
  302. end
  303. else if is_interfacecom(left.resulttype.def) then
  304. begin
  305. tg.GetTempTyped(exprasmlist,left.resulttype.def,tt_normal,location.reference);
  306. cg.a_load_loc_ref(exprasmlist,OS_ADDR,left.location,location.reference);
  307. { implicit deferencing also for interfaces }
  308. if (cs_gdb_heaptrc in aktglobalswitches) and
  309. (cs_checkpointer in aktglobalswitches) and
  310. not(cs_compilesystem in aktmoduleswitches) then
  311. begin
  312. paramanager.getintparaloc(pocall_default,1,paraloc1);
  313. paramanager.allocparaloc(exprasmlist,paraloc1);
  314. cg.a_param_reg(exprasmlist, OS_ADDR,location.reference.base,paraloc1);
  315. paramanager.freeparaloc(exprasmlist,paraloc1);
  316. cg.alloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  317. cg.a_call_name(exprasmlist,'FPC_CHECKPOINTER');
  318. cg.dealloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  319. end;
  320. end
  321. else
  322. location_copy(location,left.location);
  323. inc(location.reference.offset,vs.fieldoffset);
  324. { also update the size of the location }
  325. location.size:=def_cgsize(resulttype.def);
  326. paraloc1.done;
  327. end;
  328. {*****************************************************************************
  329. TCGWITHNODE
  330. *****************************************************************************}
  331. procedure tcgwithnode.pass_2;
  332. {$ifdef WITHNODEDEBUG}
  333. const
  334. withlevel : longint = 0;
  335. var
  336. withstartlabel,withendlabel : tasmlabel;
  337. pp : pchar;
  338. mangled_length : longint;
  339. refnode : tnode;
  340. {$endif WITHNODEDEBUG}
  341. begin
  342. location_reset(location,LOC_VOID,OS_NO);
  343. {$ifdef WITHNODEDEBUG}
  344. if (cs_debuginfo in aktmoduleswitches) then
  345. begin
  346. { load reference }
  347. if (withrefnode.nodetype=derefn) and
  348. (tderefnode(withrefnode).left.nodetype=temprefn) then
  349. refnode:=tderefnode(withrefnode).left
  350. else
  351. refnode:=withrefnode;
  352. secondpass(refnode);
  353. location_freetemp(exprasmlist,refnode.location);
  354. if not(refnode.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  355. internalerror(2003092810);
  356. inc(withlevel);
  357. objectlibrary.getaddrlabel(withstartlabel);
  358. objectlibrary.getaddrlabel(withendlabel);
  359. cg.a_label(exprasmlist,withstartlabel);
  360. withdebugList.concat(Tai_stabs.Create(strpnew(
  361. '"with'+tostr(withlevel)+':'+tostr(symtablestack.getnewtypecount)+
  362. '=*'+tstoreddef(left.resulttype.def).numberstring+'",'+
  363. tostr(N_LSYM)+',0,0,'+tostr(refnode.location.reference.offset))));
  364. mangled_length:=length(current_procinfo.procdef.mangledname);
  365. getmem(pp,mangled_length+50);
  366. strpcopy(pp,'192,0,0,'+withstartlabel.name);
  367. if (target_info.use_function_relative_addresses) then
  368. begin
  369. strpcopy(strend(pp),'-');
  370. strpcopy(strend(pp),current_procinfo.procdef.mangledname);
  371. end;
  372. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  373. end;
  374. {$endif WITHNODEDEBUG}
  375. if assigned(left) then
  376. secondpass(left);
  377. {$ifdef WITHNODEDEBUG}
  378. if (cs_debuginfo in aktmoduleswitches) then
  379. begin
  380. cg.a_label(exprasmlist,withendlabel);
  381. strpcopy(pp,'224,0,0,'+withendlabel.name);
  382. if (target_info.use_function_relative_addresses) then
  383. begin
  384. strpcopy(strend(pp),'-');
  385. strpcopy(strend(pp),current_procinfo.procdef.mangledname);
  386. end;
  387. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  388. freemem(pp,mangled_length+50);
  389. dec(withlevel);
  390. end;
  391. {$endif WITHNODEDEBUG}
  392. end;
  393. {*****************************************************************************
  394. TCGVECNODE
  395. *****************************************************************************}
  396. function tcgvecnode.get_mul_size : longint;
  397. begin
  398. if nf_memindex in flags then
  399. get_mul_size:=1
  400. else
  401. begin
  402. if (left.resulttype.def.deftype=arraydef) then
  403. get_mul_size:=tarraydef(left.resulttype.def).elesize
  404. else
  405. get_mul_size:=resulttype.def.size;
  406. end
  407. end;
  408. procedure tcgvecnode.update_reference_reg_mul(reg:tregister;l:aint);
  409. var
  410. hreg: tregister;
  411. begin
  412. if location.reference.base=NR_NO then
  413. begin
  414. if l<>1 then
  415. cg.a_op_const_reg(exprasmlist,OP_IMUL,OS_ADDR,l,reg);
  416. location.reference.base:=reg;
  417. end
  418. else if location.reference.index=NR_NO then
  419. begin
  420. if l<>1 then
  421. cg.a_op_const_reg(exprasmlist,OP_IMUL,OS_ADDR,l,reg);
  422. location.reference.index:=reg;
  423. end
  424. else
  425. begin
  426. hreg := cg.getaddressregister(exprasmlist);
  427. cg.a_loadaddr_ref_reg(exprasmlist,location.reference,hreg);
  428. reference_reset_base(location.reference,hreg,0);
  429. { insert new index register }
  430. if l<>1 then
  431. cg.a_op_const_reg(exprasmlist,OP_IMUL,OS_ADDR,l,reg);
  432. location.reference.index:=reg;
  433. end;
  434. end;
  435. procedure tcgvecnode.second_wideansistring;
  436. begin
  437. end;
  438. procedure tcgvecnode.second_dynamicarray;
  439. begin
  440. end;
  441. procedure tcgvecnode.rangecheck_array;
  442. var
  443. freereg : boolean;
  444. hightree : tnode;
  445. poslabel,
  446. neglabel : tasmlabel;
  447. hreg : tregister;
  448. paraloc1,paraloc2 : tcgpara;
  449. begin
  450. paraloc1.init;
  451. paraloc2.init;
  452. if is_open_array(left.resulttype.def) or
  453. is_array_of_const(left.resulttype.def) then
  454. begin
  455. { cdecl functions don't have high() so we can not check the range }
  456. if not(current_procinfo.procdef.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
  457. begin
  458. { Get high value }
  459. hightree:=load_high_value_node(tvarsym(tloadnode(left).symtableentry));
  460. { it must be available }
  461. if not assigned(hightree) then
  462. internalerror(200212201);
  463. firstpass(hightree);
  464. secondpass(hightree);
  465. { generate compares }
  466. freereg:=false;
  467. if (right.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  468. hreg:=cg.makeregsize(exprasmlist,right.location.register,OS_INT)
  469. else
  470. begin
  471. hreg:=cg.getintregister(exprasmlist,OS_INT);
  472. freereg:=true;
  473. cg.a_load_loc_reg(exprasmlist,OS_INT,right.location,hreg);
  474. end;
  475. objectlibrary.getlabel(neglabel);
  476. objectlibrary.getlabel(poslabel);
  477. cg.a_cmp_const_reg_label(exprasmlist,OS_INT,OC_LT,0,hreg,poslabel);
  478. cg.a_cmp_loc_reg_label(exprasmlist,OS_INT,OC_BE,hightree.location,hreg,neglabel);
  479. cg.a_label(exprasmlist,poslabel);
  480. cg.a_call_name(exprasmlist,'FPC_RANGEERROR');
  481. cg.a_label(exprasmlist,neglabel);
  482. { release hightree }
  483. hightree.free;
  484. end;
  485. end
  486. else
  487. if is_dynamic_array(left.resulttype.def) then
  488. begin
  489. paramanager.getintparaloc(pocall_default,1,paraloc1);
  490. paramanager.getintparaloc(pocall_default,2,paraloc2);
  491. paramanager.allocparaloc(exprasmlist,paraloc2);
  492. cg.a_param_loc(exprasmlist,right.location,paraloc2);
  493. paramanager.allocparaloc(exprasmlist,paraloc1);
  494. cg.a_param_loc(exprasmlist,left.location,paraloc1);
  495. paramanager.freeparaloc(exprasmlist,paraloc1);
  496. paramanager.freeparaloc(exprasmlist,paraloc2);
  497. cg.alloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  498. cg.a_call_name(exprasmlist,'FPC_DYNARRAY_RANGECHECK');
  499. cg.dealloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  500. end
  501. else
  502. cg.g_rangecheck(exprasmlist,right.location,right.resulttype.def,left.resulttype.def);
  503. paraloc1.done;
  504. paraloc2.done;
  505. end;
  506. procedure tcgvecnode.pass_2;
  507. var
  508. offsetdec,
  509. extraoffset : longint;
  510. t : tnode;
  511. href : treference;
  512. otl,ofl : tasmlabel;
  513. newsize : tcgsize;
  514. mulsize: longint;
  515. isjump : boolean;
  516. paraloc1,paraloc2 : tcgpara;
  517. begin
  518. paraloc1.init;
  519. paraloc2.init;
  520. mulsize := get_mul_size;
  521. newsize:=def_cgsize(resulttype.def);
  522. secondpass(left);
  523. if left.location.loc=LOC_CREFERENCE then
  524. location_reset(location,LOC_CREFERENCE,newsize)
  525. else
  526. location_reset(location,LOC_REFERENCE,newsize);
  527. { an ansistring needs to be dereferenced }
  528. if is_ansistring(left.resulttype.def) or
  529. is_widestring(left.resulttype.def) then
  530. begin
  531. if nf_callunique in flags then
  532. internalerror(200304236);
  533. {DM!!!!!}
  534. case left.location.loc of
  535. LOC_REGISTER,
  536. LOC_CREGISTER :
  537. location.reference.base:=left.location.register;
  538. LOC_CREFERENCE,
  539. LOC_REFERENCE :
  540. begin
  541. location.reference.base:=cg.getaddressregister(exprasmlist);
  542. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.reference,location.reference.base);
  543. end;
  544. else
  545. internalerror(2002032218);
  546. end;
  547. { check for a zero length string,
  548. we can use the ansistring routine here }
  549. if (cs_check_range in aktlocalswitches) then
  550. begin
  551. paramanager.getintparaloc(pocall_default,1,paraloc1);
  552. paramanager.allocparaloc(exprasmlist,paraloc1);
  553. cg.a_param_reg(exprasmlist,OS_ADDR,location.reference.base,paraloc1);
  554. paramanager.freeparaloc(exprasmlist,paraloc1);
  555. cg.alloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  556. cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_CHECKZERO');
  557. cg.dealloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  558. end;
  559. { in ansistrings/widestrings S[1] is p<w>char(S)[0] !! }
  560. if is_ansistring(left.resulttype.def) then
  561. offsetdec:=1
  562. else
  563. offsetdec:=2;
  564. dec(location.reference.offset,offsetdec);
  565. end
  566. else if is_dynamic_array(left.resulttype.def) then
  567. begin
  568. case left.location.loc of
  569. LOC_REGISTER,
  570. LOC_CREGISTER :
  571. location.reference.base:=left.location.register;
  572. LOC_REFERENCE,
  573. LOC_CREFERENCE :
  574. begin
  575. location.reference.base:=cg.getaddressregister(exprasmlist);
  576. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,
  577. left.location.reference,location.reference.base);
  578. end;
  579. else
  580. internalerror(2002032219);
  581. end;
  582. end
  583. else
  584. location_copy(location,left.location);
  585. { offset can only differ from 0 if arraydef }
  586. if (left.resulttype.def.deftype=arraydef) and
  587. not(is_dynamic_array(left.resulttype.def)) then
  588. dec(location.reference.offset,mulsize*tarraydef(left.resulttype.def).lowrange);
  589. if right.nodetype=ordconstn then
  590. begin
  591. { offset can only differ from 0 if arraydef }
  592. case left.resulttype.def.deftype of
  593. arraydef :
  594. begin
  595. if not(is_open_array(left.resulttype.def)) and
  596. not(is_array_of_const(left.resulttype.def)) and
  597. not(is_dynamic_array(left.resulttype.def)) then
  598. begin
  599. if (tordconstnode(right).value>tarraydef(left.resulttype.def).highrange) or
  600. (tordconstnode(right).value<tarraydef(left.resulttype.def).lowrange) then
  601. begin
  602. { this should be caught in the resulttypepass! (JM) }
  603. if (cs_check_range in aktlocalswitches) then
  604. CGMessage(parser_e_range_check_error)
  605. else
  606. CGMessage(parser_w_range_check_error);
  607. end;
  608. end
  609. else
  610. begin
  611. { range checking for open and dynamic arrays needs
  612. runtime code }
  613. secondpass(right);
  614. if (cs_check_range in aktlocalswitches) then
  615. rangecheck_array;
  616. end;
  617. end;
  618. stringdef :
  619. begin
  620. if (cs_check_range in aktlocalswitches) then
  621. begin
  622. case tstringdef(left.resulttype.def).string_typ of
  623. { it's the same for ansi- and wide strings }
  624. st_widestring,
  625. {$ifdef ansistring_bits}
  626. st_ansistring16,st_ansistring32,st_ansistring64:
  627. {$else}
  628. st_ansistring:
  629. {$endif}
  630. begin
  631. paramanager.getintparaloc(pocall_default,1,paraloc1);
  632. paramanager.getintparaloc(pocall_default,2,paraloc2);
  633. paramanager.allocparaloc(exprasmlist,paraloc2);
  634. cg.a_param_const(exprasmlist,OS_INT,tordconstnode(right).value,paraloc2);
  635. href:=location.reference;
  636. dec(href.offset,sizeof(aint)-offsetdec);
  637. paramanager.allocparaloc(exprasmlist,paraloc1);
  638. cg.a_param_ref(exprasmlist,OS_INT,href,paraloc1);
  639. paramanager.freeparaloc(exprasmlist,paraloc1);
  640. paramanager.freeparaloc(exprasmlist,paraloc2);
  641. cg.alloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  642. cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_RANGECHECK');
  643. cg.dealloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  644. end;
  645. st_shortstring:
  646. begin
  647. {!!!!!!!!!!!!!!!!!}
  648. end;
  649. st_longstring:
  650. begin
  651. {!!!!!!!!!!!!!!!!!}
  652. end;
  653. end;
  654. end;
  655. end;
  656. end;
  657. inc(location.reference.offset,
  658. mulsize*tordconstnode(right).value);
  659. end
  660. else
  661. { not nodetype=ordconstn }
  662. begin
  663. if (cs_regvars in aktglobalswitches) and
  664. { if we do range checking, we don't }
  665. { need that fancy code (it would be }
  666. { buggy) }
  667. not(cs_check_range in aktlocalswitches) and
  668. (left.resulttype.def.deftype=arraydef) then
  669. begin
  670. extraoffset:=0;
  671. if (right.nodetype=addn) then
  672. begin
  673. if taddnode(right).right.nodetype=ordconstn then
  674. begin
  675. extraoffset:=tordconstnode(taddnode(right).right).value;
  676. t:=taddnode(right).left;
  677. { First pass processed this with the assumption }
  678. { that there was an add node which may require an }
  679. { extra register. Fake it or die with IE10 (JM) }
  680. t.registersint := taddnode(right).registersint;
  681. taddnode(right).left:=nil;
  682. right.free;
  683. right:=t;
  684. end
  685. else if taddnode(right).left.nodetype=ordconstn then
  686. begin
  687. extraoffset:=tordconstnode(taddnode(right).left).value;
  688. t:=taddnode(right).right;
  689. t.registersint := right.registersint;
  690. taddnode(right).right:=nil;
  691. right.free;
  692. right:=t;
  693. end;
  694. end
  695. else if (right.nodetype=subn) then
  696. begin
  697. if taddnode(right).right.nodetype=ordconstn then
  698. begin
  699. extraoffset:=-tordconstnode(taddnode(right).right).value;
  700. t:=taddnode(right).left;
  701. t.registersint := right.registersint;
  702. taddnode(right).left:=nil;
  703. right.free;
  704. right:=t;
  705. end
  706. { You also have to negate right.right in this case! I can't add an
  707. unaryminusn without causing a crash, so I've disabled it (JM)
  708. else if right.left.nodetype=ordconstn then
  709. begin
  710. extraoffset:=right.left.value;
  711. t:=right.right;
  712. t^.registersint := right.registersint;
  713. putnode(right);
  714. putnode(right.left);
  715. right:=t;
  716. end;}
  717. end;
  718. inc(location.reference.offset,
  719. mulsize*extraoffset);
  720. end;
  721. { calculate from left to right }
  722. if not(location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  723. internalerror(200304237);
  724. isjump:=(right.location.loc=LOC_JUMP);
  725. if isjump then
  726. begin
  727. otl:=truelabel;
  728. objectlibrary.getlabel(truelabel);
  729. ofl:=falselabel;
  730. objectlibrary.getlabel(falselabel);
  731. end;
  732. secondpass(right);
  733. if cs_check_range in aktlocalswitches then
  734. begin
  735. if left.resulttype.def.deftype=arraydef then
  736. rangecheck_array;
  737. end;
  738. { if mulsize = 1, we won't have to modify the index }
  739. location_force_reg(exprasmlist,right.location,OS_ADDR,(mulsize = 1));
  740. if isjump then
  741. begin
  742. truelabel:=otl;
  743. falselabel:=ofl;
  744. end;
  745. { produce possible range check code: }
  746. if cs_check_range in aktlocalswitches then
  747. begin
  748. if left.resulttype.def.deftype=arraydef then
  749. begin
  750. { done defore (PM) }
  751. end
  752. else if (left.resulttype.def.deftype=stringdef) then
  753. begin
  754. case tstringdef(left.resulttype.def).string_typ of
  755. { it's the same for ansi- and wide strings }
  756. st_widestring,
  757. {$ifdef ansistring_bits}
  758. st_ansistring16,st_ansistring32,st_ansistring64:
  759. {$else}
  760. st_ansistring:
  761. {$endif}
  762. begin
  763. paramanager.getintparaloc(pocall_default,1,paraloc1);
  764. paramanager.getintparaloc(pocall_default,2,paraloc2);
  765. paramanager.allocparaloc(exprasmlist,paraloc2);
  766. cg.a_param_reg(exprasmlist,OS_INT,right.location.register,paraloc2);
  767. href:=location.reference;
  768. dec(href.offset,sizeof(aint)-offsetdec);
  769. //dec(href.offset,7);
  770. paramanager.allocparaloc(exprasmlist,paraloc1);
  771. cg.a_param_ref(exprasmlist,OS_INT,href,paraloc1);
  772. paramanager.freeparaloc(exprasmlist,paraloc1);
  773. paramanager.freeparaloc(exprasmlist,paraloc2);
  774. cg.alloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  775. cg.a_call_name(exprasmlist,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_RANGECHECK');
  776. cg.dealloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  777. end;
  778. st_shortstring:
  779. begin
  780. {!!!!!!!!!!!!!!!!!}
  781. end;
  782. st_longstring:
  783. begin
  784. {!!!!!!!!!!!!!!!!!}
  785. end;
  786. end;
  787. end;
  788. end;
  789. { insert the register and the multiplication factor in the
  790. reference }
  791. update_reference_reg_mul(right.location.register,mulsize);
  792. end;
  793. location.size:=newsize;
  794. paraloc1.done;
  795. paraloc2.done;
  796. end;
  797. begin
  798. cloadvmtaddrnode:=tcgloadvmtaddrnode;
  799. cloadparentfpnode:=tcgloadparentfpnode;
  800. caddrnode:=tcgaddrnode;
  801. cderefnode:=tcgderefnode;
  802. csubscriptnode:=tcgsubscriptnode;
  803. cwithnode:=tcgwithnode;
  804. cvecnode:=tcgvecnode;
  805. end.
  806. {
  807. $Log$
  808. Revision 1.97 2004-09-25 14:23:54 peter
  809. * ungetregister is now only used for cpuregisters, renamed to
  810. ungetcpuregister
  811. * renamed (get|unget)explicitregister(s) to ..cpuregister
  812. * removed location-release/reference_release
  813. Revision 1.96 2004/09/21 17:25:12 peter
  814. * paraloc branch merged
  815. Revision 1.95.4.1 2004/08/31 20:43:06 peter
  816. * paraloc patch
  817. Revision 1.95 2004/08/02 09:15:03 michael
  818. + Fixed range check for non-constant indexes in strings
  819. Revision 1.94 2004/07/12 17:58:19 peter
  820. * remove maxlen field from ansistring/widestrings
  821. Revision 1.93 2004/06/20 08:55:29 florian
  822. * logs truncated
  823. Revision 1.92 2004/06/16 20:07:08 florian
  824. * dwarf branch merged
  825. Revision 1.91 2004/04/29 19:56:37 daniel
  826. * Prepare compiler infrastructure for multiple ansistring types
  827. Revision 1.90 2004/04/21 17:39:40 jonas
  828. - disabled with-symtable debugging code since it was broken and
  829. at the same time confused the register allocator and therefore also
  830. the optimizer. May be fixed in the future using dwarf support
  831. Revision 1.89.2.4 2004/05/10 21:28:34 peter
  832. * section_smartlink enabled for gas under linux
  833. Revision 1.89.2.3 2004/05/02 13:04:28 peter
  834. * ofs fixed
  835. }