ncgmem.pas 38 KB

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