ncgmem.pas 38 KB

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