ncgmem.pas 35 KB

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