ncgmem.pas 40 KB

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