ncgmem.pas 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925
  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.103 2004-12-05 12:28:11 peter
  791. * procvar handling for tp procvar mode fixed
  792. * proc to procvar moved from addrnode to typeconvnode
  793. * inlininginfo is now allocated only for inline routines that
  794. can be inlined, introduced a new flag po_has_inlining_info
  795. Revision 1.102 2004/11/08 22:09:59 peter
  796. * tvarsym splitted
  797. Revision 1.101 2004/11/01 23:30:11 peter
  798. * support > 32bit accesses for x86_64
  799. * rewrote array size checking to support 64bit
  800. Revision 1.100 2004/11/01 17:15:47 peter
  801. * no checkpointer code for dynarr to openarr
  802. Revision 1.99 2004/11/01 15:31:57 peter
  803. * -Or fix for absolute
  804. Revision 1.98 2004/10/25 15:38:41 peter
  805. * heap and heapsize removed
  806. * checkpointer fixes
  807. Revision 1.97 2004/09/25 14:23:54 peter
  808. * ungetregister is now only used for cpuregisters, renamed to
  809. ungetcpuregister
  810. * renamed (get|unget)explicitregister(s) to ..cpuregister
  811. * removed location-release/reference_release
  812. Revision 1.96 2004/09/21 17:25:12 peter
  813. * paraloc branch merged
  814. Revision 1.95.4.1 2004/08/31 20:43:06 peter
  815. * paraloc patch
  816. Revision 1.95 2004/08/02 09:15:03 michael
  817. + Fixed range check for non-constant indexes in strings
  818. Revision 1.94 2004/07/12 17:58:19 peter
  819. * remove maxlen field from ansistring/widestrings
  820. Revision 1.93 2004/06/20 08:55:29 florian
  821. * logs truncated
  822. Revision 1.92 2004/06/16 20:07:08 florian
  823. * dwarf branch merged
  824. Revision 1.91 2004/04/29 19:56:37 daniel
  825. * Prepare compiler infrastructure for multiple ansistring types
  826. Revision 1.90 2004/04/21 17:39:40 jonas
  827. - disabled with-symtable debugging code since it was broken and
  828. at the same time confused the register allocator and therefore also
  829. the optimizer. May be fixed in the future using dwarf support
  830. Revision 1.89.2.4 2004/05/10 21:28:34 peter
  831. * section_smartlink enabled for gas under linux
  832. Revision 1.89.2.3 2004/05/02 13:04:28 peter
  833. * ofs fixed
  834. }