ncgmem.pas 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Generate assembler for memory related nodes which are
  4. the same for all (most?) processors
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit ncgmem;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. globtype,cgbase,cpuinfo,cpubase,
  23. node,nmem;
  24. type
  25. tcgloadvmtaddrnode = class(tloadvmtaddrnode)
  26. procedure pass_2;override;
  27. end;
  28. tcgloadparentfpnode = class(tloadparentfpnode)
  29. procedure pass_2;override;
  30. end;
  31. tcgaddrnode = class(taddrnode)
  32. procedure pass_2;override;
  33. end;
  34. tcgderefnode = class(tderefnode)
  35. procedure pass_2;override;
  36. end;
  37. tcgsubscriptnode = class(tsubscriptnode)
  38. procedure pass_2;override;
  39. end;
  40. tcgwithnode = class(twithnode)
  41. procedure pass_2;override;
  42. end;
  43. tcgvecnode = class(tvecnode)
  44. private
  45. procedure rangecheck_array;
  46. protected
  47. function get_mul_size : aint;
  48. {# This routine is used to calculate the address of the reference.
  49. On entry reg contains the index in the array,
  50. and l contains the size of each element in the array.
  51. This routine should update location.reference correctly,
  52. so it points to the correct address.
  53. }
  54. procedure update_reference_reg_mul(reg:tregister;l:aint);virtual;
  55. procedure second_wideansistring;virtual;
  56. procedure second_dynamicarray;virtual;
  57. public
  58. procedure pass_2;override;
  59. end;
  60. implementation
  61. uses
  62. systems,
  63. cutils,verbose,globals,
  64. symconst,symdef,symsym,defutil,paramgr,
  65. aasmbase,aasmtai,aasmdata,
  66. procinfo,pass_2,parabase,
  67. pass_1,nld,ncon,nadd,nutils,
  68. cgutils,cgobj,
  69. tgobj,ncgutil
  70. ;
  71. {*****************************************************************************
  72. TCGLOADVMTADDRNODE
  73. *****************************************************************************}
  74. procedure tcgloadvmtaddrnode.pass_2;
  75. var
  76. href : treference;
  77. begin
  78. location_reset(location,LOC_REGISTER,OS_ADDR);
  79. if (left.nodetype=typen) then
  80. begin
  81. reference_reset_symbol(href,
  82. current_asmdata.RefAsmSymbol(tobjectdef(tclassrefdef(resulttype.def).pointertype.def).vmt_mangledname),0);
  83. location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
  84. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,location.register);
  85. end
  86. else
  87. begin
  88. { left contains self, load vmt from self }
  89. secondpass(left);
  90. gen_load_vmt_register(current_asmdata.CurrAsmList,tobjectdef(left.resulttype.def),left.location,location.register);
  91. end;
  92. end;
  93. {*****************************************************************************
  94. TCGLOADPARENTFPNODE
  95. *****************************************************************************}
  96. procedure tcgloadparentfpnode.pass_2;
  97. var
  98. currpi : tprocinfo;
  99. hsym : tparavarsym;
  100. href : treference;
  101. begin
  102. if (current_procinfo.procdef.parast.symtablelevel=parentpd.parast.symtablelevel) then
  103. begin
  104. location_reset(location,LOC_REGISTER,OS_ADDR);
  105. location.register:=current_procinfo.framepointer;
  106. end
  107. else
  108. begin
  109. currpi:=current_procinfo;
  110. location_reset(location,LOC_REGISTER,OS_ADDR);
  111. location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
  112. { load framepointer of current proc }
  113. hsym:=tparavarsym(currpi.procdef.parast.search('parentfp'));
  114. if not assigned(hsym) then
  115. internalerror(200309281);
  116. cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_ADDR,hsym.localloc,location.register);
  117. { walk parents }
  118. while (currpi.procdef.owner.symtablelevel>parentpd.parast.symtablelevel) do
  119. begin
  120. currpi:=currpi.parent;
  121. if not assigned(currpi) then
  122. internalerror(200311201);
  123. hsym:=tparavarsym(currpi.procdef.parast.search('parentfp'));
  124. if not assigned(hsym) then
  125. internalerror(200309282);
  126. if hsym.localloc.loc<>LOC_REFERENCE then
  127. internalerror(200309283);
  128. reference_reset_base(href,location.register,hsym.localloc.reference.offset);
  129. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,location.register);
  130. end;
  131. end;
  132. end;
  133. {*****************************************************************************
  134. TCGADDRNODE
  135. *****************************************************************************}
  136. procedure tcgaddrnode.pass_2;
  137. begin
  138. secondpass(left);
  139. location_reset(location,LOC_REGISTER,OS_ADDR);
  140. location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
  141. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,location.register);
  142. end;
  143. {*****************************************************************************
  144. TCGDEREFNODE
  145. *****************************************************************************}
  146. procedure tcgderefnode.pass_2;
  147. var
  148. paraloc1 : tcgpara;
  149. begin
  150. secondpass(left);
  151. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  152. case left.location.loc of
  153. LOC_CREGISTER,
  154. LOC_REGISTER:
  155. begin
  156. {$ifdef cpu_uses_separate_address_registers}
  157. if getregtype(left.location.register)<>R_ADDRESSREGISTER then
  158. begin
  159. location.reference.base := cg.getaddressregister(current_asmdata.CurrAsmList);
  160. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.register,
  161. location.reference.base);
  162. end
  163. else
  164. {$endif}
  165. location.reference.base := left.location.register;
  166. end;
  167. LOC_CREFERENCE,
  168. LOC_REFERENCE:
  169. begin
  170. location.reference.base:=cg.getaddressregister(current_asmdata.CurrAsmList);
  171. cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_ADDR,left.location,location.reference.base);
  172. end;
  173. LOC_CONSTANT:
  174. begin
  175. location.reference.offset:=left.location.value;
  176. end;
  177. else
  178. internalerror(200507031);
  179. end;
  180. if (cs_use_heaptrc in aktglobalswitches) and
  181. (cs_checkpointer in aktlocalswitches) and
  182. not(cs_compilesystem in aktmoduleswitches) and
  183. not(tpointerdef(left.resulttype.def).is_far) and
  184. not(nf_no_checkpointer in flags) then
  185. begin
  186. paraloc1.init;
  187. paramanager.getintparaloc(pocall_default,1,paraloc1);
  188. paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc1);
  189. cg.a_param_reg(current_asmdata.CurrAsmList, OS_ADDR,location.reference.base,paraloc1);
  190. paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc1);
  191. paraloc1.done;
  192. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  193. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_CHECKPOINTER');
  194. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  195. end;
  196. end;
  197. {*****************************************************************************
  198. TCGSUBSCRIPTNODE
  199. *****************************************************************************}
  200. procedure tcgsubscriptnode.pass_2;
  201. var
  202. paraloc1 : tcgpara;
  203. begin
  204. secondpass(left);
  205. if codegenerror then
  206. exit;
  207. paraloc1.init;
  208. { classes and interfaces must be dereferenced implicit }
  209. if is_class_or_interface(left.resulttype.def) then
  210. begin
  211. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  212. case left.location.loc of
  213. LOC_CREGISTER,
  214. LOC_REGISTER:
  215. begin
  216. {$ifdef cpu_uses_separate_address_registers}
  217. if getregtype(left.location.register)<>R_ADDRESSREGISTER then
  218. begin
  219. location.reference.base:=rg.getaddressregister(current_asmdata.CurrAsmList);
  220. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,
  221. left.location.register,location.reference.base);
  222. end
  223. else
  224. {$endif}
  225. location.reference.base := left.location.register;
  226. end;
  227. LOC_CREFERENCE,
  228. LOC_REFERENCE:
  229. begin
  230. location.reference.base:=cg.getaddressregister(current_asmdata.CurrAsmList);
  231. cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_ADDR,left.location,location.reference.base);
  232. end;
  233. end;
  234. { implicit deferencing }
  235. if (cs_use_heaptrc in aktglobalswitches) and
  236. (cs_checkpointer in aktlocalswitches) and
  237. not(cs_compilesystem in aktmoduleswitches) then
  238. begin
  239. paramanager.getintparaloc(pocall_default,1,paraloc1);
  240. paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc1);
  241. cg.a_param_reg(current_asmdata.CurrAsmList, OS_ADDR,location.reference.base,paraloc1);
  242. paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc1);
  243. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  244. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_CHECKPOINTER');
  245. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  246. end;
  247. end
  248. else if is_interfacecom(left.resulttype.def) then
  249. begin
  250. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  251. tg.GetTempTyped(current_asmdata.CurrAsmList,left.resulttype.def,tt_normal,location.reference);
  252. cg.a_load_loc_ref(current_asmdata.CurrAsmList,OS_ADDR,left.location,location.reference);
  253. { implicit deferencing also for interfaces }
  254. if (cs_use_heaptrc in aktglobalswitches) and
  255. (cs_checkpointer in aktlocalswitches) and
  256. not(cs_compilesystem in aktmoduleswitches) then
  257. begin
  258. paramanager.getintparaloc(pocall_default,1,paraloc1);
  259. paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc1);
  260. cg.a_param_reg(current_asmdata.CurrAsmList, OS_ADDR,location.reference.base,paraloc1);
  261. paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc1);
  262. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  263. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_CHECKPOINTER');
  264. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  265. end;
  266. end
  267. else
  268. begin
  269. location_copy(location,left.location);
  270. { some abi's require that functions return (some) records in }
  271. { registers }
  272. case location.loc of
  273. LOC_REGISTER:
  274. location_force_mem(current_asmdata.CurrAsmList,location);
  275. LOC_REFERENCE,
  276. LOC_CREFERENCE:
  277. ;
  278. { record regvars are not supported yet
  279. LOC_CREGISTER: }
  280. else
  281. internalerror(2006031901);
  282. end;
  283. end;
  284. inc(location.reference.offset,vs.fieldoffset);
  285. { also update the size of the location }
  286. location.size:=def_cgsize(resulttype.def);
  287. paraloc1.done;
  288. end;
  289. {*****************************************************************************
  290. TCGWITHNODE
  291. *****************************************************************************}
  292. procedure tcgwithnode.pass_2;
  293. begin
  294. location_reset(location,LOC_VOID,OS_NO);
  295. if assigned(left) then
  296. secondpass(left);
  297. end;
  298. {*****************************************************************************
  299. TCGVECNODE
  300. *****************************************************************************}
  301. function tcgvecnode.get_mul_size : aint;
  302. begin
  303. if nf_memindex in flags then
  304. get_mul_size:=1
  305. else
  306. begin
  307. if (left.resulttype.def.deftype=arraydef) then
  308. get_mul_size:=tarraydef(left.resulttype.def).elesize
  309. else
  310. get_mul_size:=resulttype.def.size;
  311. end
  312. end;
  313. procedure tcgvecnode.update_reference_reg_mul(reg:tregister;l:aint);
  314. var
  315. hreg: tregister;
  316. begin
  317. if location.reference.base=NR_NO then
  318. begin
  319. if l<>1 then
  320. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_IMUL,OS_ADDR,l,reg);
  321. location.reference.base:=reg;
  322. end
  323. else if location.reference.index=NR_NO then
  324. begin
  325. if l<>1 then
  326. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_IMUL,OS_ADDR,l,reg);
  327. location.reference.index:=reg;
  328. end
  329. else
  330. begin
  331. hreg := cg.getaddressregister(current_asmdata.CurrAsmList);
  332. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,location.reference,hreg);
  333. reference_reset_base(location.reference,hreg,0);
  334. { insert new index register }
  335. if l<>1 then
  336. cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_IMUL,OS_ADDR,l,reg);
  337. location.reference.index:=reg;
  338. end;
  339. end;
  340. procedure tcgvecnode.second_wideansistring;
  341. begin
  342. end;
  343. procedure tcgvecnode.second_dynamicarray;
  344. begin
  345. end;
  346. procedure tcgvecnode.rangecheck_array;
  347. var
  348. hightree : tnode;
  349. poslabel,
  350. neglabel : tasmlabel;
  351. hreg : tregister;
  352. paraloc1,paraloc2 : tcgpara;
  353. begin
  354. paraloc1.init;
  355. paraloc2.init;
  356. if is_open_array(left.resulttype.def) or
  357. is_array_of_const(left.resulttype.def) then
  358. begin
  359. { cdecl functions don't have high() so we can not check the range }
  360. if not(current_procinfo.procdef.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
  361. begin
  362. { Get high value }
  363. hightree:=load_high_value_node(tparavarsym(tloadnode(left).symtableentry));
  364. { it must be available }
  365. if not assigned(hightree) then
  366. internalerror(200212201);
  367. firstpass(hightree);
  368. secondpass(hightree);
  369. { generate compares }
  370. if (right.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  371. hreg:=cg.makeregsize(current_asmdata.CurrAsmList,right.location.register,OS_INT)
  372. else
  373. begin
  374. hreg:=cg.getintregister(current_asmdata.CurrAsmList,OS_INT);
  375. cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_INT,right.location,hreg);
  376. end;
  377. current_asmdata.getjumplabel(neglabel);
  378. current_asmdata.getjumplabel(poslabel);
  379. cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_LT,0,hreg,poslabel);
  380. cg.a_cmp_loc_reg_label(current_asmdata.CurrAsmList,OS_INT,OC_BE,hightree.location,hreg,neglabel);
  381. cg.a_label(current_asmdata.CurrAsmList,poslabel);
  382. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_RANGEERROR');
  383. cg.a_label(current_asmdata.CurrAsmList,neglabel);
  384. { release hightree }
  385. hightree.free;
  386. end;
  387. end
  388. else
  389. if is_dynamic_array(left.resulttype.def) then
  390. begin
  391. paramanager.getintparaloc(pocall_default,1,paraloc1);
  392. paramanager.getintparaloc(pocall_default,2,paraloc2);
  393. paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc2);
  394. cg.a_param_loc(current_asmdata.CurrAsmList,right.location,paraloc2);
  395. paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc1);
  396. cg.a_param_loc(current_asmdata.CurrAsmList,left.location,paraloc1);
  397. paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc1);
  398. paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc2);
  399. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  400. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_DYNARRAY_RANGECHECK');
  401. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  402. end
  403. else
  404. cg.g_rangecheck(current_asmdata.CurrAsmList,right.location,right.resulttype.def,left.resulttype.def);
  405. paraloc1.done;
  406. paraloc2.done;
  407. end;
  408. procedure tcgvecnode.pass_2;
  409. var
  410. offsetdec,
  411. extraoffset : aint;
  412. t : tnode;
  413. href : treference;
  414. otl,ofl : tasmlabel;
  415. newsize : tcgsize;
  416. mulsize : aint;
  417. isjump : boolean;
  418. paraloc1,
  419. paraloc2 : tcgpara;
  420. begin
  421. paraloc1.init;
  422. paraloc2.init;
  423. mulsize := get_mul_size;
  424. newsize:=def_cgsize(resulttype.def);
  425. secondpass(left);
  426. if left.location.loc=LOC_CREFERENCE then
  427. location_reset(location,LOC_CREFERENCE,newsize)
  428. else
  429. location_reset(location,LOC_REFERENCE,newsize);
  430. { an ansistring needs to be dereferenced }
  431. if is_ansistring(left.resulttype.def) or
  432. is_widestring(left.resulttype.def) then
  433. begin
  434. if nf_callunique in flags then
  435. internalerror(200304236);
  436. {DM!!!!!}
  437. case left.location.loc of
  438. LOC_REGISTER,
  439. LOC_CREGISTER :
  440. location.reference.base:=left.location.register;
  441. LOC_CREFERENCE,
  442. LOC_REFERENCE :
  443. begin
  444. location.reference.base:=cg.getaddressregister(current_asmdata.CurrAsmList);
  445. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.reference,location.reference.base);
  446. end;
  447. else
  448. internalerror(2002032218);
  449. end;
  450. { check for a zero length string,
  451. we can use the ansistring routine here }
  452. if (cs_check_range in aktlocalswitches) then
  453. begin
  454. paramanager.getintparaloc(pocall_default,1,paraloc1);
  455. paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc1);
  456. cg.a_param_reg(current_asmdata.CurrAsmList,OS_ADDR,location.reference.base,paraloc1);
  457. paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc1);
  458. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  459. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_CHECKZERO');
  460. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  461. end;
  462. { in ansistrings/widestrings S[1] is p<w>char(S)[0] !! }
  463. if is_ansistring(left.resulttype.def) then
  464. offsetdec:=1
  465. else
  466. offsetdec:=2;
  467. dec(location.reference.offset,offsetdec);
  468. end
  469. else if is_dynamic_array(left.resulttype.def) then
  470. begin
  471. case left.location.loc of
  472. LOC_REGISTER,
  473. LOC_CREGISTER :
  474. location.reference.base:=left.location.register;
  475. LOC_REFERENCE,
  476. LOC_CREFERENCE :
  477. begin
  478. location.reference.base:=cg.getaddressregister(current_asmdata.CurrAsmList);
  479. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,
  480. left.location.reference,location.reference.base);
  481. end;
  482. else
  483. internalerror(2002032219);
  484. end;
  485. end
  486. else
  487. location_copy(location,left.location);
  488. { location must be memory }
  489. if not(location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  490. internalerror(200411013);
  491. { offset can only differ from 0 if arraydef }
  492. if (left.resulttype.def.deftype=arraydef) and
  493. not(is_dynamic_array(left.resulttype.def)) then
  494. dec(location.reference.offset,mulsize*tarraydef(left.resulttype.def).lowrange);
  495. if right.nodetype=ordconstn then
  496. begin
  497. { offset can only differ from 0 if arraydef }
  498. case left.resulttype.def.deftype of
  499. arraydef :
  500. begin
  501. if not(is_open_array(left.resulttype.def)) and
  502. not(is_array_of_const(left.resulttype.def)) and
  503. not(is_dynamic_array(left.resulttype.def)) then
  504. begin
  505. if (tordconstnode(right).value>tarraydef(left.resulttype.def).highrange) or
  506. (tordconstnode(right).value<tarraydef(left.resulttype.def).lowrange) then
  507. begin
  508. { this should be caught in the resulttypepass! (JM) }
  509. if (cs_check_range in aktlocalswitches) then
  510. CGMessage(parser_e_range_check_error)
  511. else
  512. CGMessage(parser_w_range_check_error);
  513. end;
  514. end
  515. else
  516. begin
  517. { range checking for open and dynamic arrays needs
  518. runtime code }
  519. secondpass(right);
  520. if (cs_check_range in aktlocalswitches) then
  521. rangecheck_array;
  522. end;
  523. end;
  524. stringdef :
  525. begin
  526. if (cs_check_range in aktlocalswitches) then
  527. begin
  528. case tstringdef(left.resulttype.def).string_typ of
  529. { it's the same for ansi- and wide strings }
  530. st_widestring,
  531. st_ansistring:
  532. begin
  533. paramanager.getintparaloc(pocall_default,1,paraloc1);
  534. paramanager.getintparaloc(pocall_default,2,paraloc2);
  535. paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc2);
  536. cg.a_param_const(current_asmdata.CurrAsmList,OS_INT,tordconstnode(right).value,paraloc2);
  537. href:=location.reference;
  538. dec(href.offset,sizeof(aint)-offsetdec);
  539. paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc1);
  540. cg.a_param_ref(current_asmdata.CurrAsmList,OS_INT,href,paraloc1);
  541. paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc1);
  542. paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc2);
  543. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  544. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_RANGECHECK');
  545. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  546. end;
  547. st_shortstring:
  548. begin
  549. {!!!!!!!!!!!!!!!!!}
  550. end;
  551. st_longstring:
  552. begin
  553. {!!!!!!!!!!!!!!!!!}
  554. end;
  555. end;
  556. end;
  557. end;
  558. end;
  559. inc(location.reference.offset,
  560. mulsize*tordconstnode(right).value);
  561. end
  562. else
  563. { not nodetype=ordconstn }
  564. begin
  565. if (cs_opt_regvar in aktoptimizerswitches) and
  566. { if we do range checking, we don't }
  567. { need that fancy code (it would be }
  568. { buggy) }
  569. not(cs_check_range in aktlocalswitches) and
  570. (left.resulttype.def.deftype=arraydef) then
  571. begin
  572. extraoffset:=0;
  573. if (right.nodetype=addn) then
  574. begin
  575. if taddnode(right).right.nodetype=ordconstn then
  576. begin
  577. extraoffset:=tordconstnode(taddnode(right).right).value;
  578. t:=taddnode(right).left;
  579. { First pass processed this with the assumption }
  580. { that there was an add node which may require an }
  581. { extra register. Fake it or die with IE10 (JM) }
  582. t.registersint := taddnode(right).registersint;
  583. taddnode(right).left:=nil;
  584. right.free;
  585. right:=t;
  586. end
  587. else if taddnode(right).left.nodetype=ordconstn then
  588. begin
  589. extraoffset:=tordconstnode(taddnode(right).left).value;
  590. t:=taddnode(right).right;
  591. t.registersint := right.registersint;
  592. taddnode(right).right:=nil;
  593. right.free;
  594. right:=t;
  595. end;
  596. end
  597. else if (right.nodetype=subn) then
  598. begin
  599. if taddnode(right).right.nodetype=ordconstn then
  600. begin
  601. extraoffset:=-tordconstnode(taddnode(right).right).value;
  602. t:=taddnode(right).left;
  603. t.registersint := right.registersint;
  604. taddnode(right).left:=nil;
  605. right.free;
  606. right:=t;
  607. end
  608. { You also have to negate right.right in this case! I can't add an
  609. unaryminusn without causing a crash, so I've disabled it (JM)
  610. else if right.left.nodetype=ordconstn then
  611. begin
  612. extraoffset:=right.left.value;
  613. t:=right.right;
  614. t^.registersint := right.registersint;
  615. putnode(right);
  616. putnode(right.left);
  617. right:=t;
  618. end;}
  619. end;
  620. inc(location.reference.offset,
  621. mulsize*extraoffset);
  622. end;
  623. { calculate from left to right }
  624. if not(location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  625. internalerror(200304237);
  626. isjump:=(right.expectloc=LOC_JUMP);
  627. if isjump then
  628. begin
  629. otl:=current_procinfo.CurrTrueLabel;
  630. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  631. ofl:=current_procinfo.CurrFalseLabel;
  632. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  633. end;
  634. secondpass(right);
  635. { if mulsize = 1, we won't have to modify the index }
  636. location_force_reg(current_asmdata.CurrAsmList,right.location,OS_ADDR,(mulsize = 1));
  637. if isjump then
  638. begin
  639. current_procinfo.CurrTrueLabel:=otl;
  640. current_procinfo.CurrFalseLabel:=ofl;
  641. end
  642. else if (right.location.loc = LOC_JUMP) then
  643. internalerror(2006010801);
  644. { only range check now, we can't range check loc_flags/loc_jump }
  645. if cs_check_range in aktlocalswitches then
  646. begin
  647. if left.resulttype.def.deftype=arraydef then
  648. rangecheck_array;
  649. end;
  650. { produce possible range check code: }
  651. if cs_check_range in aktlocalswitches then
  652. begin
  653. if left.resulttype.def.deftype=arraydef then
  654. begin
  655. { done defore (PM) }
  656. end
  657. else if (left.resulttype.def.deftype=stringdef) then
  658. begin
  659. case tstringdef(left.resulttype.def).string_typ of
  660. { it's the same for ansi- and wide strings }
  661. st_widestring,
  662. st_ansistring:
  663. begin
  664. paramanager.getintparaloc(pocall_default,1,paraloc1);
  665. paramanager.getintparaloc(pocall_default,2,paraloc2);
  666. paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc2);
  667. cg.a_param_reg(current_asmdata.CurrAsmList,OS_INT,right.location.register,paraloc2);
  668. href:=location.reference;
  669. dec(href.offset,sizeof(aint)-offsetdec);
  670. //dec(href.offset,7);
  671. paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc1);
  672. cg.a_param_ref(current_asmdata.CurrAsmList,OS_INT,href,paraloc1);
  673. paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc1);
  674. paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc2);
  675. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  676. cg.a_call_name(current_asmdata.CurrAsmList,'FPC_'+upper(tstringdef(left.resulttype.def).stringtypname)+'_RANGECHECK');
  677. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  678. end;
  679. st_shortstring:
  680. begin
  681. {!!!!!!!!!!!!!!!!!}
  682. end;
  683. st_longstring:
  684. begin
  685. {!!!!!!!!!!!!!!!!!}
  686. end;
  687. end;
  688. end;
  689. end;
  690. { insert the register and the multiplication factor in the
  691. reference }
  692. update_reference_reg_mul(right.location.register,mulsize);
  693. end;
  694. location.size:=newsize;
  695. paraloc1.done;
  696. paraloc2.done;
  697. end;
  698. begin
  699. cloadvmtaddrnode:=tcgloadvmtaddrnode;
  700. cloadparentfpnode:=tcgloadparentfpnode;
  701. caddrnode:=tcgaddrnode;
  702. cderefnode:=tcgderefnode;
  703. csubscriptnode:=tcgsubscriptnode;
  704. cwithnode:=tcgwithnode;
  705. cvecnode:=tcgvecnode;
  706. end.