ncgmem.pas 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024
  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. cpuinfo,cpubase,
  26. node,nmem;
  27. type
  28. tcgloadvmtnode = class(tloadvmtnode)
  29. procedure pass_2;override;
  30. end;
  31. tcghnewnode = class(thnewnode)
  32. procedure pass_2;override;
  33. end;
  34. tcghdisposenode = class(thdisposenode)
  35. procedure pass_2;override;
  36. end;
  37. tcgaddrnode = class(taddrnode)
  38. procedure pass_2;override;
  39. end;
  40. tcgdoubleaddrnode = class(tdoubleaddrnode)
  41. procedure pass_2;override;
  42. end;
  43. tcgderefnode = class(tderefnode)
  44. procedure pass_2;override;
  45. end;
  46. tcgsubscriptnode = class(tsubscriptnode)
  47. procedure pass_2;override;
  48. end;
  49. tcgselfnode = class(tselfnode)
  50. procedure pass_2;override;
  51. end;
  52. tcgwithnode = class(twithnode)
  53. procedure pass_2;override;
  54. end;
  55. tcgvecnode = class(tvecnode)
  56. private
  57. procedure rangecheck_array;
  58. protected
  59. function get_mul_size : aword;
  60. procedure update_reference_reg_mul(reg:tregister;l:aword);virtual;
  61. procedure second_wideansistring;virtual;
  62. procedure second_dynamicarray;virtual;
  63. public
  64. procedure pass_2;override;
  65. end;
  66. implementation
  67. uses
  68. {$ifdef delphi}
  69. sysutils,
  70. {$else}
  71. strings,
  72. {$endif}
  73. {$ifdef GDB}
  74. gdb,
  75. {$endif GDB}
  76. globtype,systems,
  77. cutils,verbose,globals,
  78. symconst,symtype,symdef,symsym,symtable,defbase,paramgr,
  79. aasmbase,aasmtai,aasmcpu,
  80. cginfo,cgbase,pass_2,
  81. pass_1,nld,ncon,nadd,
  82. cgobj,tgobj,rgobj,ncgutil,symbase
  83. ;
  84. {*****************************************************************************
  85. TCGLOADNODE
  86. *****************************************************************************}
  87. procedure tcgloadvmtnode.pass_2;
  88. var
  89. href : treference;
  90. begin
  91. location_reset(location,LOC_REGISTER,OS_ADDR);
  92. location.register:=rg.getaddressregister(exprasmlist);
  93. { on 80386, LEA is the same as mov imm32 }
  94. reference_reset_symbol(href,
  95. objectlibrary.newasmsymbol(tobjectdef(tclassrefdef(resulttype.def).pointertype.def).vmt_mangledname),0);
  96. cg.a_loadaddr_ref_reg(exprasmlist,href,location.register);
  97. end;
  98. {*****************************************************************************
  99. TCGHNEWNODE
  100. *****************************************************************************}
  101. procedure tcghnewnode.pass_2;
  102. begin
  103. { completely resolved in first pass now }
  104. end;
  105. {*****************************************************************************
  106. TCGHDISPOSENODE
  107. *****************************************************************************}
  108. procedure tcghdisposenode.pass_2;
  109. begin
  110. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  111. secondpass(left);
  112. if codegenerror then
  113. exit;
  114. case left.location.loc of
  115. LOC_REGISTER:
  116. begin
  117. if not rg.isaddressregister(left.location.register) then
  118. begin
  119. location_release(exprasmlist,left.location);
  120. location.reference.base := rg.getaddressregister(exprasmlist);
  121. cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.register,
  122. location.reference.base);
  123. end
  124. else
  125. location.reference.base := left.location.register;
  126. end;
  127. LOC_CREGISTER,
  128. LOC_CREFERENCE,
  129. LOC_REFERENCE:
  130. begin
  131. location_release(exprasmlist,left.location);
  132. location.reference.base:=rg.getaddressregister(exprasmlist);
  133. cg.a_load_loc_reg(exprasmlist,left.location,location.reference.base);
  134. end;
  135. else
  136. internalerror(2002032217);
  137. end;
  138. end;
  139. {*****************************************************************************
  140. TCGADDRNODE
  141. *****************************************************************************}
  142. procedure tcgaddrnode.pass_2;
  143. begin
  144. secondpass(left);
  145. { when loading procvar we do nothing with this node, so load the
  146. location of left }
  147. if nf_procvarload in flags then
  148. begin
  149. location_copy(location,left.location);
  150. exit;
  151. end;
  152. location_release(exprasmlist,left.location);
  153. location_reset(location,LOC_REGISTER,OS_ADDR);
  154. location.register:=rg.getaddressregister(exprasmlist);
  155. {@ on a procvar means returning an address to the procedure that
  156. is stored in it.}
  157. { yes but left.symtableentry can be nil
  158. for example on self !! }
  159. { symtableentry can be also invalid, if left is no tree node }
  160. if (m_tp_procvar in aktmodeswitches) and
  161. (left.nodetype=loadn) and
  162. assigned(tloadnode(left).symtableentry) and
  163. (tloadnode(left).symtableentry.typ=varsym) and
  164. (tvarsym(tloadnode(left).symtableentry).vartype.def.deftype=procvardef) then
  165. cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,
  166. location.register)
  167. else
  168. begin
  169. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,
  170. location.register);
  171. end;
  172. end;
  173. {*****************************************************************************
  174. TCGDOUBLEADDRNODE
  175. *****************************************************************************}
  176. procedure tcgdoubleaddrnode.pass_2;
  177. begin
  178. secondpass(left);
  179. location_release(exprasmlist,left.location);
  180. location_reset(location,LOC_REGISTER,OS_ADDR);
  181. location.register:=rg.getaddressregister(exprasmlist);
  182. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,
  183. location.register);
  184. end;
  185. {*****************************************************************************
  186. TCGDEREFNODE
  187. *****************************************************************************}
  188. procedure tcgderefnode.pass_2;
  189. begin
  190. secondpass(left);
  191. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  192. case left.location.loc of
  193. LOC_REGISTER:
  194. begin
  195. if not rg.isaddressregister(left.location.register) then
  196. begin
  197. location_release(exprasmlist,left.location);
  198. location.reference.base := rg.getaddressregister(exprasmlist);
  199. cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.register,
  200. location.reference.base);
  201. end
  202. else
  203. location.reference.base := left.location.register;
  204. end;
  205. LOC_CREGISTER,
  206. LOC_CREFERENCE,
  207. LOC_REFERENCE:
  208. begin
  209. location_release(exprasmlist,left.location);
  210. location.reference.base:=rg.getaddressregister(exprasmlist);
  211. cg.a_load_loc_reg(exprasmlist,left.location,location.reference.base);
  212. end;
  213. end;
  214. if (cs_gdb_heaptrc in aktglobalswitches) and
  215. (cs_checkpointer in aktglobalswitches) then
  216. begin
  217. cg.a_param_reg(exprasmlist, OS_ADDR,location.reference.base,paramanager.getintparaloc(1));
  218. cg.a_call_name(exprasmlist,'FPC_CHECKPOINTER');
  219. end;
  220. end;
  221. {*****************************************************************************
  222. TCGSUBSCRIPTNODE
  223. *****************************************************************************}
  224. procedure tcgsubscriptnode.pass_2;
  225. begin
  226. secondpass(left);
  227. if codegenerror then
  228. exit;
  229. { classes and interfaces must be dereferenced implicit }
  230. if is_class_or_interface(left.resulttype.def) then
  231. begin
  232. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  233. case left.location.loc of
  234. LOC_REGISTER:
  235. begin
  236. if not rg.isaddressregister(left.location.register) then
  237. begin
  238. location_release(exprasmlist,left.location);
  239. location.reference.base:=rg.getaddressregister(exprasmlist);
  240. cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,
  241. left.location.register,location.reference.base);
  242. end
  243. else
  244. location.reference.base := left.location.register;
  245. end;
  246. LOC_CREGISTER,
  247. LOC_CREFERENCE,
  248. LOC_REFERENCE:
  249. begin
  250. location_release(exprasmlist,left.location);
  251. location.reference.base:=rg.getaddressregister(exprasmlist);
  252. cg.a_load_loc_reg(exprasmlist,left.location,location.reference.base);
  253. end;
  254. end;
  255. end
  256. else if is_interfacecom(left.resulttype.def) then
  257. begin
  258. tg.GetTemp(exprasmlist,pointer_size,tt_interfacecom,location.reference);
  259. cg.a_load_loc_ref(exprasmlist,left.location,location.reference);
  260. end
  261. else
  262. location_copy(location,left.location);
  263. inc(location.reference.offset,vs.address);
  264. { also update the size of the location }
  265. location.size:=def_cgsize(resulttype.def);
  266. end;
  267. {*****************************************************************************
  268. TCGSELFNODE
  269. *****************************************************************************}
  270. procedure tcgselfnode.pass_2;
  271. begin
  272. rg.getexplicitregisterint(exprasmlist,SELF_POINTER_REG);
  273. if (resulttype.def.deftype=classrefdef) or
  274. is_class(resulttype.def) then
  275. begin
  276. location_reset(location,LOC_CREGISTER,OS_ADDR);
  277. location.register:=SELF_POINTER_REG;
  278. end
  279. else
  280. begin
  281. location_reset(location,LOC_CREFERENCE,OS_ADDR);
  282. location.reference.base:=SELF_POINTER_REG;
  283. end;
  284. end;
  285. {*****************************************************************************
  286. TCGWITHNODE
  287. *****************************************************************************}
  288. procedure tcgwithnode.pass_2;
  289. var
  290. tmpreg: tregister;
  291. usetemp,with_expr_in_temp : boolean;
  292. {$ifdef GDB}
  293. withstartlabel,withendlabel : tasmlabel;
  294. pp : pchar;
  295. mangled_length : longint;
  296. const
  297. withlevel : longint = 0;
  298. {$endif GDB}
  299. begin
  300. if assigned(left) then
  301. begin
  302. secondpass(left);
  303. {$ifdef i386}
  304. if (left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) and
  305. (left.location.reference.segment<>R_NO) then
  306. message(parser_e_no_with_for_variable_in_other_segments);
  307. {$endif i386}
  308. reference_reset(withreference);
  309. usetemp:=false;
  310. if (left.nodetype=loadn) and
  311. (tloadnode(left).symtable=aktprocdef.localst) then
  312. begin
  313. { for locals use the local storage }
  314. withreference:=left.location.reference;
  315. include(flags,nf_islocal);
  316. end
  317. else
  318. { call can have happend with a property }
  319. begin
  320. usetemp:=true;
  321. if is_class_or_interface(left.resulttype.def) then
  322. begin
  323. tmpreg := cg.get_scratch_reg_int(exprasmlist);
  324. cg.a_load_loc_reg(exprasmlist,left.location,tmpreg)
  325. end
  326. else
  327. begin
  328. tmpreg := cg.get_scratch_reg_address(exprasmlist);
  329. cg.a_loadaddr_ref_reg(exprasmlist,
  330. left.location.reference,tmpreg);
  331. end;
  332. end;
  333. location_release(exprasmlist,left.location);
  334. { if the with expression is stored in a temp }
  335. { area we must make it persistent and shouldn't }
  336. { release it (FK) }
  337. if (left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) and
  338. tg.istemp(left.location.reference) then
  339. begin
  340. tg.ChangeTempType(left.location.reference,tt_persistant);
  341. with_expr_in_temp:=true;
  342. end
  343. else
  344. with_expr_in_temp:=false;
  345. { if usetemp is set the value must be in tmpreg }
  346. if usetemp then
  347. begin
  348. tg.GetTemp(exprasmlist,pointer_size,tt_persistant,withreference);
  349. { move to temp reference }
  350. cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,withreference);
  351. cg.free_scratch_reg(exprasmlist,tmpreg);
  352. {$ifdef GDB}
  353. if (cs_debuginfo in aktmoduleswitches) then
  354. begin
  355. inc(withlevel);
  356. objectlibrary.getaddrlabel(withstartlabel);
  357. objectlibrary.getaddrlabel(withendlabel);
  358. cg.a_label(exprasmlist,withstartlabel);
  359. withdebugList.concat(Tai_stabs.Create(strpnew(
  360. '"with'+tostr(withlevel)+':'+tostr(symtablestack.getnewtypecount)+
  361. '=*'+tstoreddef(left.resulttype.def).numberstring+'",'+
  362. tostr(N_LSYM)+',0,0,'+tostr(withreference.offset))));
  363. mangled_length:=length(aktprocdef.mangledname);
  364. getmem(pp,mangled_length+50);
  365. strpcopy(pp,'192,0,0,'+withstartlabel.name);
  366. if (target_info.use_function_relative_addresses) then
  367. begin
  368. strpcopy(strend(pp),'-');
  369. strpcopy(strend(pp),aktprocdef.mangledname);
  370. end;
  371. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  372. end;
  373. {$endif GDB}
  374. end;
  375. { right can be optimize out !!! }
  376. if assigned(right) then
  377. secondpass(right);
  378. if usetemp then
  379. begin
  380. tg.UnGetTemp(exprasmlist,withreference);
  381. {$ifdef GDB}
  382. if (cs_debuginfo in aktmoduleswitches) then
  383. begin
  384. cg.a_label(exprasmlist,withendlabel);
  385. strpcopy(pp,'224,0,0,'+withendlabel.name);
  386. if (target_info.use_function_relative_addresses) then
  387. begin
  388. strpcopy(strend(pp),'-');
  389. strpcopy(strend(pp),aktprocdef.mangledname);
  390. end;
  391. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  392. freemem(pp,mangled_length+50);
  393. dec(withlevel);
  394. end;
  395. {$endif GDB}
  396. end;
  397. if with_expr_in_temp then
  398. tg.UnGetTemp(exprasmlist,left.location.reference);
  399. reference_reset(withreference);
  400. end;
  401. end;
  402. {*****************************************************************************
  403. TCGVECNODE
  404. *****************************************************************************}
  405. function tcgvecnode.get_mul_size : aword;
  406. begin
  407. if nf_memindex in flags then
  408. get_mul_size:=1
  409. else
  410. begin
  411. if (left.resulttype.def.deftype=arraydef) then
  412. get_mul_size:=tarraydef(left.resulttype.def).elesize
  413. else
  414. get_mul_size:=resulttype.def.size;
  415. end
  416. end;
  417. procedure tcgvecnode.update_reference_reg_mul(reg:tregister;l:aword);
  418. begin
  419. if location.reference.base=R_NO then
  420. begin
  421. cg.a_op_const_reg(exprasmlist,OP_IMUL,l,reg);
  422. location.reference.base:=reg;
  423. end
  424. else if location.reference.index=R_NO then
  425. begin
  426. cg.a_op_const_reg(exprasmlist,OP_IMUL,l,reg);
  427. location.reference.index:=reg;
  428. end
  429. else
  430. begin
  431. cg.a_loadaddr_ref_reg(exprasmlist,location.reference,location.reference.index);
  432. rg.ungetregisterint(exprasmlist,location.reference.base);
  433. reference_reset_base(location.reference,location.reference.index,0);
  434. { insert new index register }
  435. cg.a_op_const_reg(exprasmlist,OP_IMUL,l,reg);
  436. location.reference.index:=reg;
  437. end;
  438. end;
  439. procedure tcgvecnode.second_wideansistring;
  440. begin
  441. end;
  442. procedure tcgvecnode.second_dynamicarray;
  443. begin
  444. end;
  445. procedure tcgvecnode.rangecheck_array;
  446. var
  447. freereg : boolean;
  448. hightree : tnode;
  449. srsym : tsym;
  450. poslabel,
  451. neglabel : tasmlabel;
  452. hreg : tregister;
  453. begin
  454. if is_open_array(left.resulttype.def) or
  455. is_array_of_const(left.resulttype.def) then
  456. begin
  457. { Get high value }
  458. srsym:=searchsymonlyin(tloadnode(left).symtable,
  459. 'high'+tvarsym(tloadnode(left).symtableentry).name);
  460. hightree:=cloadnode.create(tvarsym(srsym),tloadnode(left).symtable);
  461. firstpass(hightree);
  462. secondpass(hightree);
  463. { generate compares }
  464. freereg:=false;
  465. if (right.location.loc in [LOC_REGISTER,LOC_CREGISTER]) then
  466. hreg:=right.location.register
  467. else
  468. begin
  469. hreg := cg.get_scratch_reg_int(exprasmlist);
  470. freereg:=true;
  471. cg.a_load_loc_reg(exprasmlist,right.location,hreg);
  472. end;
  473. objectlibrary.getlabel(neglabel);
  474. objectlibrary.getlabel(poslabel);
  475. cg.a_cmp_const_reg_label(exprasmlist,OS_INT,OC_LT,0,hreg,poslabel);
  476. cg.a_cmp_loc_reg_label(exprasmlist,OS_INT,OC_BE,hightree.location,hreg,neglabel);
  477. cg.a_label(exprasmlist,poslabel);
  478. { !!! should happen right after the compare (JM) }
  479. if freereg then
  480. cg.free_scratch_reg(exprasmlist,hreg);
  481. cg.a_call_name(exprasmlist,'FPC_RANGEERROR');
  482. cg.a_label(exprasmlist,neglabel);
  483. { release hightree }
  484. location_release(exprasmlist,hightree.location);
  485. hightree.free;
  486. end
  487. else
  488. if is_dynamic_array(left.resulttype.def) then
  489. begin
  490. {$ifdef fpc}
  491. {$warning Rangecheck for dynamic array}
  492. {$endif fpc}
  493. internalerror(200210074);
  494. end
  495. else
  496. cg.g_rangecheck(exprasmlist,right,left.resulttype.def);
  497. end;
  498. procedure tcgvecnode.pass_2;
  499. var
  500. extraoffset : longint;
  501. t : tnode;
  502. href : treference;
  503. pushed : tpushedsaved;
  504. isjump : boolean;
  505. otl,ofl : tasmlabel;
  506. newsize : tcgsize;
  507. pushedregs : tmaybesave;
  508. begin
  509. newsize:=def_cgsize(resulttype.def);
  510. location_reset(location,LOC_REFERENCE,newsize);
  511. secondpass(left);
  512. { we load the array reference to location }
  513. { an ansistring needs to be dereferenced }
  514. if is_ansistring(left.resulttype.def) or
  515. is_widestring(left.resulttype.def) then
  516. begin
  517. if nf_callunique in flags then
  518. begin
  519. if left.location.loc<>LOC_REFERENCE then
  520. begin
  521. CGMessage(cg_e_illegal_expression);
  522. exit;
  523. end;
  524. rg.saveusedregisters(exprasmlist,pushed,all_registers);
  525. cg.a_paramaddr_ref(exprasmlist,left.location.reference,paramanager.getintparaloc(1));
  526. rg.saveregvars(exprasmlist,all_registers);
  527. cg.a_call_name(exprasmlist,'FPC_'+Upper(tstringdef(left.resulttype.def).stringtypname)+'_UNIQUE');
  528. cg.g_maybe_loadself(exprasmlist);
  529. rg.restoreusedregisters(exprasmlist,pushed);
  530. end;
  531. case left.location.loc of
  532. LOC_REGISTER,
  533. LOC_CREGISTER :
  534. location.reference.base:=left.location.register;
  535. LOC_CREFERENCE,
  536. LOC_REFERENCE :
  537. begin
  538. location_release(exprasmlist,left.location);
  539. location.reference.base:=rg.getregisterint(exprasmlist);
  540. cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,location.reference.base);
  541. end;
  542. else
  543. internalerror(2002032218);
  544. end;
  545. { check for a zero length string,
  546. we can use the ansistring routine here }
  547. if (cs_check_range in aktlocalswitches) then
  548. begin
  549. rg.saveusedregisters(exprasmlist,pushed,all_registers);
  550. cg.a_param_reg(exprasmlist,OS_ADDR,location.reference.base,paramanager.getintparaloc(1));
  551. rg.saveregvars(exprasmlist,all_registers);
  552. cg.a_call_name(exprasmlist,'FPC_'+Upper(tstringdef(left.resulttype.def).stringtypname)+'_CHECKZERO');
  553. cg.g_maybe_loadself(exprasmlist);
  554. rg.restoreusedregisters(exprasmlist,pushed);
  555. end;
  556. { in ansistrings/widestrings S[1] is p<w>char(S)[0] !! }
  557. if is_ansistring(left.resulttype.def) then
  558. dec(location.reference.offset)
  559. else
  560. dec(location.reference.offset,2);
  561. end
  562. else if is_dynamic_array(left.resulttype.def) then
  563. { ... also a dynamic string }
  564. begin
  565. case left.location.loc of
  566. LOC_REGISTER,
  567. LOC_CREGISTER :
  568. location.reference.base:=left.location.register;
  569. LOC_REFERENCE,
  570. LOC_CREFERENCE :
  571. begin
  572. location_release(exprasmlist,left.location);
  573. location.reference.base:=rg.getaddressregister(exprasmlist);
  574. cg.a_load_ref_reg(exprasmlist,OS_ADDR,
  575. left.location.reference,location.reference.base);
  576. end;
  577. else
  578. internalerror(2002032219);
  579. end;
  580. {$ifdef fpc}
  581. {$warning FIXME}
  582. {$endif}
  583. { check for a zero length string,
  584. we can use the ansistring routine here }
  585. if (cs_check_range in aktlocalswitches) then
  586. begin
  587. rg.saveusedregisters(exprasmlist,pushed,all_registers);
  588. cg.a_param_reg(exprasmlist,OS_ADDR,location.reference.base,paramanager.getintparaloc(1));
  589. rg.saveregvars(exprasmlist,all_registers);
  590. cg.a_call_name(exprasmlist,'FPC_ANSISTR_CHECKZERO');
  591. cg.g_maybe_loadself(exprasmlist);
  592. rg.restoreusedregisters(exprasmlist,pushed);
  593. end;
  594. end
  595. else
  596. location_copy(location,left.location);
  597. { offset can only differ from 0 if arraydef }
  598. if (left.resulttype.def.deftype=arraydef) and
  599. not(is_dynamic_array(left.resulttype.def)) then
  600. dec(location.reference.offset,get_mul_size*tarraydef(left.resulttype.def).lowrange);
  601. if right.nodetype=ordconstn then
  602. begin
  603. { offset can only differ from 0 if arraydef }
  604. case left.resulttype.def.deftype of
  605. arraydef :
  606. begin
  607. if not(is_open_array(left.resulttype.def)) and
  608. not(is_array_of_const(left.resulttype.def)) and
  609. not(is_dynamic_array(left.resulttype.def)) then
  610. begin
  611. if (tordconstnode(right).value>tarraydef(left.resulttype.def).highrange) or
  612. (tordconstnode(right).value<tarraydef(left.resulttype.def).lowrange) then
  613. begin
  614. { this should be caught in the resulttypepass! (JM) }
  615. if (cs_check_range in aktlocalswitches) then
  616. CGMessage(parser_e_range_check_error)
  617. else
  618. CGMessage(parser_w_range_check_error);
  619. end;
  620. end
  621. else
  622. begin
  623. { range checking for open and dynamic arrays needs
  624. runtime code }
  625. secondpass(right);
  626. rangecheck_array;
  627. end;
  628. end;
  629. stringdef :
  630. begin
  631. if (cs_check_range in aktlocalswitches) then
  632. begin
  633. case tstringdef(left.resulttype.def).string_typ of
  634. { it's the same for ansi- and wide strings }
  635. st_widestring,
  636. st_ansistring:
  637. begin
  638. rg.saveusedregisters(exprasmlist,pushed,all_registers);
  639. cg.a_param_const(exprasmlist,OS_INT,tordconstnode(right).value,paramanager.getintparaloc(2));
  640. href:=location.reference;
  641. dec(href.offset,7);
  642. cg.a_param_ref(exprasmlist,OS_INT,href,paramanager.getintparaloc(1));
  643. rg.saveregvars(exprasmlist,all_registers);
  644. cg.a_call_name(exprasmlist,'FPC_'+Upper(tstringdef(left.resulttype.def).stringtypname)+'_RANGECHECK');
  645. rg.restoreusedregisters(exprasmlist,pushed);
  646. cg.g_maybe_loadself(exprasmlist);
  647. end;
  648. st_shortstring:
  649. begin
  650. {!!!!!!!!!!!!!!!!!}
  651. end;
  652. st_longstring:
  653. begin
  654. {!!!!!!!!!!!!!!!!!}
  655. end;
  656. end;
  657. end;
  658. end;
  659. end;
  660. inc(location.reference.offset,
  661. get_mul_size*tordconstnode(right).value);
  662. end
  663. else
  664. { not nodetype=ordconstn }
  665. begin
  666. if (cs_regalloc in aktglobalswitches) and
  667. { if we do range checking, we don't }
  668. { need that fancy code (it would be }
  669. { buggy) }
  670. not(cs_check_range in aktlocalswitches) and
  671. (left.resulttype.def.deftype=arraydef) then
  672. begin
  673. extraoffset:=0;
  674. if (right.nodetype=addn) then
  675. begin
  676. if taddnode(right).right.nodetype=ordconstn then
  677. begin
  678. extraoffset:=tordconstnode(taddnode(right).right).value;
  679. t:=taddnode(right).left;
  680. { First pass processed this with the assumption }
  681. { that there was an add node which may require an }
  682. { extra register. Fake it or die with IE10 (JM) }
  683. t.registers32 := taddnode(right).registers32;
  684. taddnode(right).left:=nil;
  685. right.free;
  686. right:=t;
  687. end
  688. else if taddnode(right).left.nodetype=ordconstn then
  689. begin
  690. extraoffset:=tordconstnode(taddnode(right).left).value;
  691. t:=taddnode(right).right;
  692. t.registers32 := right.registers32;
  693. taddnode(right).right:=nil;
  694. right.free;
  695. right:=t;
  696. end;
  697. end
  698. else if (right.nodetype=subn) then
  699. begin
  700. if taddnode(right).right.nodetype=ordconstn then
  701. begin
  702. extraoffset:=-tordconstnode(taddnode(right).right).value;
  703. t:=taddnode(right).left;
  704. t.registers32 := right.registers32;
  705. taddnode(right).left:=nil;
  706. right.free;
  707. right:=t;
  708. end
  709. { You also have to negate right.right in this case! I can't add an
  710. unaryminusn without causing a crash, so I've disabled it (JM)
  711. else if right.left.nodetype=ordconstn then
  712. begin
  713. extraoffset:=right.left.value;
  714. t:=right.right;
  715. t^.registers32 := right.registers32;
  716. putnode(right);
  717. putnode(right.left);
  718. right:=t;
  719. end;}
  720. end;
  721. inc(location.reference.offset,
  722. get_mul_size*extraoffset);
  723. end;
  724. { calculate from left to right }
  725. if not(location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  726. { should be internalerror! (JM) }
  727. CGMessage(cg_e_illegal_expression);
  728. isjump:=(right.location.loc=LOC_JUMP);
  729. if isjump then
  730. begin
  731. otl:=truelabel;
  732. objectlibrary.getlabel(truelabel);
  733. ofl:=falselabel;
  734. objectlibrary.getlabel(falselabel);
  735. end;
  736. maybe_save(exprasmlist,right.registers32,location,pushedregs);
  737. secondpass(right);
  738. maybe_restore(exprasmlist,location,pushedregs);
  739. { here we change the location of right
  740. and the update was forgotten so it
  741. led to wrong code in emitrangecheck later PM
  742. so make range check before }
  743. if cs_check_range in aktlocalswitches then
  744. begin
  745. if left.resulttype.def.deftype=arraydef then
  746. rangecheck_array;
  747. end;
  748. location_force_reg(exprasmlist,right.location,OS_32,false);
  749. if isjump then
  750. begin
  751. truelabel:=otl;
  752. falselabel:=ofl;
  753. end;
  754. { produce possible range check code: }
  755. if cs_check_range in aktlocalswitches then
  756. begin
  757. if left.resulttype.def.deftype=arraydef then
  758. begin
  759. { done defore (PM) }
  760. end
  761. else if (left.resulttype.def.deftype=stringdef) then
  762. begin
  763. case tstringdef(left.resulttype.def).string_typ of
  764. { it's the same for ansi- and wide strings }
  765. st_widestring,
  766. st_ansistring:
  767. begin
  768. rg.saveusedregisters(exprasmlist,pushed,all_registers);
  769. cg.a_param_reg(exprasmlist,OS_INT,right.location.register,paramanager.getintparaloc(1));
  770. href:=location.reference;
  771. dec(href.offset,7);
  772. cg.a_param_ref(exprasmlist,OS_INT,href,paramanager.getintparaloc(1));
  773. rg.saveregvars(exprasmlist,all_registers);
  774. cg.a_call_name(exprasmlist,'FPC_'+Upper(tstringdef(left.resulttype.def).stringtypname)+'_RANGECHECK');
  775. rg.restoreusedregisters(exprasmlist,pushed);
  776. cg.g_maybe_loadself(exprasmlist);
  777. end;
  778. st_shortstring:
  779. begin
  780. {!!!!!!!!!!!!!!!!!}
  781. end;
  782. st_longstring:
  783. begin
  784. {!!!!!!!!!!!!!!!!!}
  785. end;
  786. end;
  787. end;
  788. end;
  789. { insert the register and the multiplication factor in the
  790. reference }
  791. update_reference_reg_mul(right.location.register,get_mul_size);
  792. end;
  793. location.size:=newsize;
  794. end;
  795. begin
  796. cloadvmtnode:=tcgloadvmtnode;
  797. chnewnode:=tcghnewnode;
  798. chdisposenode:=tcghdisposenode;
  799. caddrnode:=tcgaddrnode;
  800. cdoubleaddrnode:=tcgdoubleaddrnode;
  801. cderefnode:=tcgderefnode;
  802. csubscriptnode:=tcgsubscriptnode;
  803. cselfnode:=tcgselfnode;
  804. cwithnode:=tcgwithnode;
  805. cvecnode:=tcgvecnode;
  806. end.
  807. {
  808. $Log$
  809. Revision 1.30 2002-10-07 21:30:45 peter
  810. * rangecheck for open arrays added
  811. Revision 1.29 2002/10/05 12:43:25 carl
  812. * fixes for Delphi 6 compilation
  813. (warning : Some features do not work under Delphi)
  814. Revision 1.28 2002/09/17 18:54:02 jonas
  815. * a_load_reg_reg() now has two size parameters: source and dest. This
  816. allows some optimizations on architectures that don't encode the
  817. register size in the register name.
  818. Revision 1.27 2002/09/07 15:25:03 peter
  819. * old logs removed and tabs fixed
  820. Revision 1.26 2002/09/01 18:46:01 peter
  821. * fixed generic tcgvecnode
  822. * move code that updates a reference with index register and multiplier
  823. to separate method so it can be overriden for scaled indexing
  824. * i386 uses generic tcgvecnode
  825. Revision 1.25 2002/08/23 16:14:48 peter
  826. * tempgen cleanup
  827. * tt_noreuse temp type added that will be used in genentrycode
  828. Revision 1.24 2002/08/15 08:13:54 carl
  829. - a_load_sym_ofs_reg removed
  830. * loadvmt now calls loadaddr_ref_reg instead
  831. Revision 1.23 2002/08/11 14:32:26 peter
  832. * renamed current_library to objectlibrary
  833. Revision 1.22 2002/08/11 13:24:12 peter
  834. * saving of asmsymbols in ppu supported
  835. * asmsymbollist global is removed and moved into a new class
  836. tasmlibrarydata that will hold the info of a .a file which
  837. corresponds with a single module. Added librarydata to tmodule
  838. to keep the library info stored for the module. In the future the
  839. objectfiles will also be stored to the tasmlibrarydata class
  840. * all getlabel/newasmsymbol and friends are moved to the new class
  841. Revision 1.21 2002/08/11 11:36:57 jonas
  842. * always first try to use base and only then index
  843. Revision 1.20 2002/08/11 06:14:40 florian
  844. * fixed powerpc compilation problems
  845. Revision 1.19 2002/08/10 14:46:29 carl
  846. + moved target_cpu_string to cpuinfo
  847. * renamed asmmode enum.
  848. * assembler reader has now less ifdef's
  849. * move from nppcmem.pas -> ncgmem.pas vec. node.
  850. Revision 1.18 2002/07/28 21:34:31 florian
  851. * more powerpc fixes
  852. + dummy tcgvecnode
  853. Revision 1.17 2002/07/11 14:41:28 florian
  854. * start of the new generic parameter handling
  855. Revision 1.16 2002/07/07 09:52:32 florian
  856. * powerpc target fixed, very simple units can be compiled
  857. * some basic stuff for better callparanode handling, far from being finished
  858. Revision 1.15 2002/07/01 18:46:23 peter
  859. * internal linker
  860. * reorganized aasm layer
  861. Revision 1.14 2002/07/01 16:23:53 peter
  862. * cg64 patch
  863. * basics for currency
  864. * asnode updates for class and interface (not finished)
  865. Revision 1.13 2002/05/20 13:30:40 carl
  866. * bugfix of hdisponen (base must be set, not index)
  867. * more portability fixes
  868. Revision 1.12 2002/05/18 13:34:09 peter
  869. * readded missing revisions
  870. Revision 1.11 2002/05/16 19:46:37 carl
  871. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  872. + try to fix temp allocation (still in ifdef)
  873. + generic constructor calls
  874. + start of tassembler / tmodulebase class cleanup
  875. Revision 1.9 2002/05/12 16:53:07 peter
  876. * moved entry and exitcode to ncgutil and cgobj
  877. * foreach gets extra argument for passing local data to the
  878. iterator function
  879. * -CR checks also class typecasts at runtime by changing them
  880. into as
  881. * fixed compiler to cycle with the -CR option
  882. * fixed stabs with elf writer, finally the global variables can
  883. be watched
  884. * removed a lot of routines from cga unit and replaced them by
  885. calls to cgobj
  886. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  887. u32bit then the other is typecasted also to u32bit without giving
  888. a rangecheck warning/error.
  889. * fixed pascal calling method with reversing also the high tree in
  890. the parast, detected by tcalcst3 test
  891. Revision 1.8 2002/04/20 21:32:23 carl
  892. + generic FPC_CHECKPOINTER
  893. + first parameter offset in stack now portable
  894. * rename some constants
  895. + move some cpu stuff to other units
  896. - remove unused constents
  897. * fix stacksize for some targets
  898. * fix generic size problems which depend now on EXTEND_SIZE constant
  899. Revision 1.7 2002/04/15 18:58:47 carl
  900. + target_info.size_of_pointer -> pointer_Size
  901. Revision 1.6 2002/04/04 19:05:57 peter
  902. * removed unused units
  903. * use tlocation.size in cg.a_*loc*() routines
  904. }