ncgmem.pas 38 KB

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