ncgmem.pas 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003
  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.gettempintfcomreference(exprasmlist,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.normaltemptopersistant(left.location.reference.offset);
  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.gettempofsizereference(exprasmlist,pointer_size,withreference);
  343. tg.normaltemptopersistant(withreference.offset);
  344. { move to temp reference }
  345. cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,withreference);
  346. cg.free_scratch_reg(exprasmlist,tmpreg);
  347. {$ifdef GDB}
  348. if (cs_debuginfo in aktmoduleswitches) then
  349. begin
  350. inc(withlevel);
  351. objectlibrary.getaddrlabel(withstartlabel);
  352. objectlibrary.getaddrlabel(withendlabel);
  353. cg.a_label(exprasmlist,withstartlabel);
  354. withdebugList.concat(Tai_stabs.Create(strpnew(
  355. '"with'+tostr(withlevel)+':'+tostr(symtablestack.getnewtypecount)+
  356. '=*'+tstoreddef(left.resulttype.def).numberstring+'",'+
  357. tostr(N_LSYM)+',0,0,'+tostr(withreference.offset))));
  358. mangled_length:=length(aktprocdef.mangledname);
  359. getmem(pp,mangled_length+50);
  360. strpcopy(pp,'192,0,0,'+withstartlabel.name);
  361. if (target_info.use_function_relative_addresses) then
  362. begin
  363. strpcopy(strend(pp),'-');
  364. strpcopy(strend(pp),aktprocdef.mangledname);
  365. end;
  366. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  367. end;
  368. {$endif GDB}
  369. end;
  370. { right can be optimize out !!! }
  371. if assigned(right) then
  372. secondpass(right);
  373. if usetemp then
  374. begin
  375. tg.ungetpersistanttemp(exprasmlist,withreference.offset);
  376. {$ifdef GDB}
  377. if (cs_debuginfo in aktmoduleswitches) then
  378. begin
  379. cg.a_label(exprasmlist,withendlabel);
  380. strpcopy(pp,'224,0,0,'+withendlabel.name);
  381. if (target_info.use_function_relative_addresses) then
  382. begin
  383. strpcopy(strend(pp),'-');
  384. strpcopy(strend(pp),aktprocdef.mangledname);
  385. end;
  386. withdebugList.concat(Tai_stabn.Create(strnew(pp)));
  387. freemem(pp,mangled_length+50);
  388. dec(withlevel);
  389. end;
  390. {$endif GDB}
  391. end;
  392. if with_expr_in_temp then
  393. tg.ungetpersistanttemp(exprasmlist,left.location.reference.offset);
  394. reference_reset(withreference);
  395. end;
  396. end;
  397. {*****************************************************************************
  398. TCGVECNODE
  399. *****************************************************************************}
  400. function tcgvecnode.get_mul_size : aword;
  401. begin
  402. if nf_memindex in flags then
  403. get_mul_size:=1
  404. else
  405. begin
  406. if (left.resulttype.def.deftype=arraydef) then
  407. get_mul_size:=tarraydef(left.resulttype.def).elesize
  408. else
  409. get_mul_size:=resulttype.def.size;
  410. end
  411. end;
  412. procedure tcgvecnode.second_wideansistring;
  413. begin
  414. end;
  415. procedure tcgvecnode.second_dynamicarray;
  416. begin
  417. end;
  418. procedure tcgvecnode.pass_2;
  419. var
  420. extraoffset : longint;
  421. { rl stores the resulttype.def of the left node, this is necessary }
  422. { to detect if it is an ansistring }
  423. { because in constant nodes which constant index }
  424. { the left tree is removed }
  425. t : tnode;
  426. href : treference;
  427. srsym : tsym;
  428. pushed : tpushedsaved;
  429. hightree : tnode;
  430. isjump : boolean;
  431. otl,ofl : tasmlabel;
  432. newsize : tcgsize;
  433. pushedregs : tmaybesave;
  434. begin
  435. newsize:=def_cgsize(resulttype.def);
  436. location_reset(location,LOC_REFERENCE,newsize);
  437. secondpass(left);
  438. { we load the array reference to location }
  439. { an ansistring needs to be dereferenced }
  440. if is_ansistring(left.resulttype.def) or
  441. is_widestring(left.resulttype.def) then
  442. begin
  443. if nf_callunique in flags then
  444. begin
  445. if left.location.loc<>LOC_REFERENCE then
  446. begin
  447. CGMessage(cg_e_illegal_expression);
  448. exit;
  449. end;
  450. rg.saveusedregisters(exprasmlist,pushed,all_registers);
  451. cg.a_paramaddr_ref(exprasmlist,left.location.reference,paramanager.getintparaloc(1));
  452. rg.saveregvars(exprasmlist,all_registers);
  453. cg.a_call_name(exprasmlist,'FPC_'+Upper(tstringdef(left.resulttype.def).stringtypname)+'_UNIQUE');
  454. cg.g_maybe_loadself(exprasmlist);
  455. rg.restoreusedregisters(exprasmlist,pushed);
  456. end;
  457. case left.location.loc of
  458. LOC_REGISTER,
  459. LOC_CREGISTER :
  460. location.reference.base:=left.location.register;
  461. LOC_CREFERENCE,
  462. LOC_REFERENCE :
  463. begin
  464. location_release(exprasmlist,left.location);
  465. location.reference.base:=rg.getregisterint(exprasmlist);
  466. cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,location.reference.base);
  467. end;
  468. else
  469. internalerror(2002032218);
  470. end;
  471. { check for a zero length string,
  472. we can use the ansistring routine here }
  473. if (cs_check_range in aktlocalswitches) then
  474. begin
  475. rg.saveusedregisters(exprasmlist,pushed,all_registers);
  476. cg.a_param_reg(exprasmlist,OS_ADDR,location.reference.base,paramanager.getintparaloc(1));
  477. rg.saveregvars(exprasmlist,all_registers);
  478. cg.a_call_name(exprasmlist,'FPC_'+Upper(tstringdef(left.resulttype.def).stringtypname)+'_CHECKZERO');
  479. cg.g_maybe_loadself(exprasmlist);
  480. rg.restoreusedregisters(exprasmlist,pushed);
  481. end;
  482. { in ansistrings/widestrings S[1] is p<w>char(S)[0] !! }
  483. if is_ansistring(left.resulttype.def) then
  484. dec(location.reference.offset)
  485. else
  486. dec(location.reference.offset,2);
  487. { we've also to keep left up-to-date, because it is used }
  488. { if a constant array index occurs, subject to change (FK) }
  489. location_copy(left.location,location);
  490. end
  491. else if is_dynamic_array(left.resulttype.def) then
  492. { ... also a dynamic string }
  493. begin
  494. case left.location.loc of
  495. LOC_REGISTER,
  496. LOC_CREGISTER :
  497. location.reference.base:=left.location.register;
  498. LOC_REFERENCE,
  499. LOC_CREFERENCE :
  500. begin
  501. location_release(exprasmlist,left.location);
  502. location.reference.base:=rg.getaddressregister(exprasmlist);
  503. cg.a_load_ref_reg(exprasmlist,OS_ADDR,
  504. left.location.reference,location.reference.base);
  505. end;
  506. else
  507. internalerror(2002032219);
  508. end;
  509. {$warning FIXME}
  510. { check for a zero length string,
  511. we can use the ansistring routine here }
  512. if (cs_check_range in aktlocalswitches) then
  513. begin
  514. rg.saveusedregisters(exprasmlist,pushed,all_registers);
  515. cg.a_param_reg(exprasmlist,OS_ADDR,location.reference.base,paramanager.getintparaloc(1));
  516. rg.saveregvars(exprasmlist,all_registers);
  517. cg.a_call_name(exprasmlist,'FPC_ANSISTR_CHECKZERO');
  518. cg.g_maybe_loadself(exprasmlist);
  519. rg.restoreusedregisters(exprasmlist,pushed);
  520. end;
  521. { we've also to keep left up-to-date, because it is used }
  522. { if a constant array index occurs, subject to change (FK) }
  523. location_copy(left.location,location);
  524. end
  525. else
  526. location_copy(location,left.location);
  527. { offset can only differ from 0 if arraydef }
  528. if (left.resulttype.def.deftype=arraydef) and
  529. not(is_dynamic_array(left.resulttype.def)) then
  530. dec(location.reference.offset,
  531. get_mul_size*tarraydef(left.resulttype.def).lowrange);
  532. if right.nodetype=ordconstn then
  533. begin
  534. { offset can only differ from 0 if arraydef }
  535. if (left.resulttype.def.deftype=arraydef) then
  536. begin
  537. if not(is_open_array(left.resulttype.def)) and
  538. not(is_array_of_const(left.resulttype.def)) and
  539. not(is_dynamic_array(left.resulttype.def)) then
  540. begin
  541. if (tordconstnode(right).value>tarraydef(left.resulttype.def).highrange) or
  542. (tordconstnode(right).value<tarraydef(left.resulttype.def).lowrange) then
  543. begin
  544. { this should be caught in the resulttypepass! (JM) }
  545. if (cs_check_range in aktlocalswitches) then
  546. CGMessage(parser_e_range_check_error)
  547. else
  548. CGMessage(parser_w_range_check_error);
  549. end;
  550. dec(left.location.reference.offset,
  551. get_mul_size*tarraydef(left.resulttype.def).lowrange);
  552. end
  553. else
  554. begin
  555. { range checking for open and dynamic arrays !!!! }
  556. {$warning FIXME}
  557. {!!!!!!!!!!!!!!!!!}
  558. end;
  559. end
  560. else if (left.resulttype.def.deftype=stringdef) then
  561. begin
  562. if (tordconstnode(right).value=0) and
  563. not(is_shortstring(left.resulttype.def)) then
  564. { this should be caught in the resulttypepass! (JM) }
  565. CGMessage(cg_e_can_access_element_zero);
  566. if (cs_check_range in aktlocalswitches) then
  567. begin
  568. case tstringdef(left.resulttype.def).string_typ of
  569. { it's the same for ansi- and wide strings }
  570. st_widestring,
  571. st_ansistring:
  572. begin
  573. rg.saveusedregisters(exprasmlist,pushed,all_registers);
  574. cg.a_param_const(exprasmlist,OS_INT,tordconstnode(right).value,paramanager.getintparaloc(2));
  575. href:=location.reference;
  576. dec(href.offset,7);
  577. cg.a_param_ref(exprasmlist,OS_INT,href,paramanager.getintparaloc(1));
  578. rg.saveregvars(exprasmlist,all_registers);
  579. cg.a_call_name(exprasmlist,'FPC_'+Upper(tstringdef(left.resulttype.def).stringtypname)+'_RANGECHECK');
  580. rg.restoreusedregisters(exprasmlist,pushed);
  581. cg.g_maybe_loadself(exprasmlist);
  582. end;
  583. st_shortstring:
  584. begin
  585. {!!!!!!!!!!!!!!!!!}
  586. end;
  587. st_longstring:
  588. begin
  589. {!!!!!!!!!!!!!!!!!}
  590. end;
  591. end;
  592. end;
  593. end;
  594. inc(left.location.reference.offset,
  595. get_mul_size*tordconstnode(right).value);
  596. location_copy(location,left.location);
  597. end
  598. else
  599. { not nodetype=ordconstn }
  600. begin
  601. if (cs_regalloc in aktglobalswitches) and
  602. { if we do range checking, we don't }
  603. { need that fancy code (it would be }
  604. { buggy) }
  605. not(cs_check_range in aktlocalswitches) and
  606. (left.resulttype.def.deftype=arraydef) then
  607. begin
  608. extraoffset:=0;
  609. if (right.nodetype=addn) then
  610. begin
  611. if taddnode(right).right.nodetype=ordconstn then
  612. begin
  613. extraoffset:=tordconstnode(taddnode(right).right).value;
  614. t:=taddnode(right).left;
  615. { First pass processed this with the assumption }
  616. { that there was an add node which may require an }
  617. { extra register. Fake it or die with IE10 (JM) }
  618. t.registers32 := taddnode(right).registers32;
  619. taddnode(right).left:=nil;
  620. right.free;
  621. right:=t;
  622. end
  623. else if taddnode(right).left.nodetype=ordconstn then
  624. begin
  625. extraoffset:=tordconstnode(taddnode(right).left).value;
  626. t:=taddnode(right).right;
  627. t.registers32 := right.registers32;
  628. taddnode(right).right:=nil;
  629. right.free;
  630. right:=t;
  631. end;
  632. end
  633. else if (right.nodetype=subn) then
  634. begin
  635. if taddnode(right).right.nodetype=ordconstn then
  636. begin
  637. { this was "extraoffset:=right.right.value;" Looks a bit like
  638. copy-paste bug :) (JM) }
  639. extraoffset:=-tordconstnode(taddnode(right).right).value;
  640. t:=taddnode(right).left;
  641. t.registers32 := right.registers32;
  642. taddnode(right).left:=nil;
  643. right.free;
  644. right:=t;
  645. end
  646. { You also have to negate right.right in this case! I can't add an
  647. unaryminusn without causing a crash, so I've disabled it (JM)
  648. else if right.left.nodetype=ordconstn then
  649. begin
  650. extraoffset:=right.left.value;
  651. t:=right.right;
  652. t^.registers32 := right.registers32;
  653. putnode(right);
  654. putnode(right.left);
  655. right:=t;
  656. end;}
  657. end;
  658. inc(location.reference.offset,
  659. get_mul_size*extraoffset);
  660. end;
  661. { calculate from left to right }
  662. if not(location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  663. { should be internalerror! (JM) }
  664. CGMessage(cg_e_illegal_expression);
  665. isjump:=(right.location.loc=LOC_JUMP);
  666. if isjump then
  667. begin
  668. otl:=truelabel;
  669. objectlibrary.getlabel(truelabel);
  670. ofl:=falselabel;
  671. objectlibrary.getlabel(falselabel);
  672. end;
  673. maybe_save(exprasmlist,right.registers32,location,pushedregs);
  674. secondpass(right);
  675. maybe_restore(exprasmlist,location,pushedregs);
  676. { here we change the location of right
  677. and the update was forgotten so it
  678. led to wrong code in emitrangecheck later PM
  679. so make range check before }
  680. if cs_check_range in aktlocalswitches then
  681. begin
  682. if left.resulttype.def.deftype=arraydef then
  683. begin
  684. if is_open_array(left.resulttype.def) or
  685. is_array_of_const(left.resulttype.def) then
  686. begin
  687. tarraydef(left.resulttype.def).genrangecheck;
  688. srsym:=searchsymonlyin(tloadnode(left).symtable,
  689. 'high'+tvarsym(tloadnode(left).symtableentry).name);
  690. hightree:=cloadnode.create(tvarsym(srsym),tloadnode(left).symtable);
  691. firstpass(hightree);
  692. secondpass(hightree);
  693. location_release(exprasmlist,hightree.location);
  694. reference_reset_symbol(href,objectlibrary.newasmsymbol(tarraydef(left.resulttype.def).getrangecheckstring),4);
  695. cg.a_load_loc_ref(exprasmlist,hightree.location,href);
  696. hightree.free;
  697. hightree:=nil;
  698. end;
  699. cg.g_rangecheck(exprasmlist,right,left.resulttype.def);
  700. end;
  701. end;
  702. location_force_reg(exprasmlist,right.location,OS_32,false);
  703. if isjump then
  704. begin
  705. truelabel:=otl;
  706. falselabel:=ofl;
  707. end;
  708. { produce possible range check code: }
  709. if cs_check_range in aktlocalswitches then
  710. begin
  711. if left.resulttype.def.deftype=arraydef then
  712. begin
  713. { done defore (PM) }
  714. end
  715. else if (left.resulttype.def.deftype=stringdef) then
  716. begin
  717. case tstringdef(left.resulttype.def).string_typ of
  718. { it's the same for ansi- and wide strings }
  719. st_widestring,
  720. st_ansistring:
  721. begin
  722. rg.saveusedregisters(exprasmlist,pushed,all_registers);
  723. cg.a_param_reg(exprasmlist,OS_INT,right.location.register,paramanager.getintparaloc(1));
  724. href:=location.reference;
  725. dec(href.offset,7);
  726. cg.a_param_ref(exprasmlist,OS_INT,href,paramanager.getintparaloc(1));
  727. rg.saveregvars(exprasmlist,all_registers);
  728. cg.a_call_name(exprasmlist,'FPC_'+Upper(tstringdef(left.resulttype.def).stringtypname)+'_RANGECHECK');
  729. rg.restoreusedregisters(exprasmlist,pushed);
  730. cg.g_maybe_loadself(exprasmlist);
  731. end;
  732. st_shortstring:
  733. begin
  734. {!!!!!!!!!!!!!!!!!}
  735. end;
  736. st_longstring:
  737. begin
  738. {!!!!!!!!!!!!!!!!!}
  739. end;
  740. end;
  741. end;
  742. end;
  743. if location.reference.base=R_NO then
  744. begin
  745. location.reference.base:=right.location.register;
  746. cg.a_op_const_reg(exprasmlist,OP_IMUL,get_mul_size,
  747. right.location.register);
  748. end
  749. else if location.reference.index=R_NO then
  750. begin
  751. location.reference.index:=right.location.register;
  752. cg.a_op_const_reg(exprasmlist,OP_IMUL,get_mul_size,
  753. right.location.register);
  754. end
  755. else
  756. begin
  757. cg.a_loadaddr_ref_reg(exprasmlist,location.reference,
  758. location.reference.base);
  759. rg.ungetregisterint(exprasmlist,location.reference.index);
  760. { the symbol offset is loaded, }
  761. { so release the symbol name and set symbol }
  762. { to nil }
  763. location.reference.symbol:=nil;
  764. location.reference.offset:=0;
  765. cg.a_op_const_reg(exprasmlist,OP_IMUL,
  766. get_mul_size,right.location.register);
  767. location.reference.index:=right.location.register;
  768. end;
  769. end;
  770. location.size:=newsize;
  771. end;
  772. begin
  773. cloadvmtnode:=tcgloadvmtnode;
  774. chnewnode:=tcghnewnode;
  775. chdisposenode:=tcghdisposenode;
  776. caddrnode:=tcgaddrnode;
  777. cdoubleaddrnode:=tcgdoubleaddrnode;
  778. cderefnode:=tcgderefnode;
  779. csubscriptnode:=tcgsubscriptnode;
  780. cselfnode:=tcgselfnode;
  781. cwithnode:=tcgwithnode;
  782. cvecnode:=tcgvecnode;
  783. end.
  784. {
  785. $Log$
  786. Revision 1.24 2002-08-15 08:13:54 carl
  787. - a_load_sym_ofs_reg removed
  788. * loadvmt now calls loadaddr_ref_reg instead
  789. Revision 1.23 2002/08/11 14:32:26 peter
  790. * renamed current_library to objectlibrary
  791. Revision 1.22 2002/08/11 13:24:12 peter
  792. * saving of asmsymbols in ppu supported
  793. * asmsymbollist global is removed and moved into a new class
  794. tasmlibrarydata that will hold the info of a .a file which
  795. corresponds with a single module. Added librarydata to tmodule
  796. to keep the library info stored for the module. In the future the
  797. objectfiles will also be stored to the tasmlibrarydata class
  798. * all getlabel/newasmsymbol and friends are moved to the new class
  799. Revision 1.21 2002/08/11 11:36:57 jonas
  800. * always first try to use base and only then index
  801. Revision 1.20 2002/08/11 06:14:40 florian
  802. * fixed powerpc compilation problems
  803. Revision 1.19 2002/08/10 14:46:29 carl
  804. + moved target_cpu_string to cpuinfo
  805. * renamed asmmode enum.
  806. * assembler reader has now less ifdef's
  807. * move from nppcmem.pas -> ncgmem.pas vec. node.
  808. Revision 1.18 2002/07/28 21:34:31 florian
  809. * more powerpc fixes
  810. + dummy tcgvecnode
  811. Revision 1.17 2002/07/11 14:41:28 florian
  812. * start of the new generic parameter handling
  813. Revision 1.16 2002/07/07 09:52:32 florian
  814. * powerpc target fixed, very simple units can be compiled
  815. * some basic stuff for better callparanode handling, far from being finished
  816. Revision 1.15 2002/07/01 18:46:23 peter
  817. * internal linker
  818. * reorganized aasm layer
  819. Revision 1.14 2002/07/01 16:23:53 peter
  820. * cg64 patch
  821. * basics for currency
  822. * asnode updates for class and interface (not finished)
  823. Revision 1.13 2002/05/20 13:30:40 carl
  824. * bugfix of hdisponen (base must be set, not index)
  825. * more portability fixes
  826. Revision 1.12 2002/05/18 13:34:09 peter
  827. * readded missing revisions
  828. Revision 1.11 2002/05/16 19:46:37 carl
  829. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  830. + try to fix temp allocation (still in ifdef)
  831. + generic constructor calls
  832. + start of tassembler / tmodulebase class cleanup
  833. Revision 1.9 2002/05/12 16:53:07 peter
  834. * moved entry and exitcode to ncgutil and cgobj
  835. * foreach gets extra argument for passing local data to the
  836. iterator function
  837. * -CR checks also class typecasts at runtime by changing them
  838. into as
  839. * fixed compiler to cycle with the -CR option
  840. * fixed stabs with elf writer, finally the global variables can
  841. be watched
  842. * removed a lot of routines from cga unit and replaced them by
  843. calls to cgobj
  844. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  845. u32bit then the other is typecasted also to u32bit without giving
  846. a rangecheck warning/error.
  847. * fixed pascal calling method with reversing also the high tree in
  848. the parast, detected by tcalcst3 test
  849. Revision 1.8 2002/04/20 21:32:23 carl
  850. + generic FPC_CHECKPOINTER
  851. + first parameter offset in stack now portable
  852. * rename some constants
  853. + move some cpu stuff to other units
  854. - remove unused constents
  855. * fix stacksize for some targets
  856. * fix generic size problems which depend now on EXTEND_SIZE constant
  857. Revision 1.7 2002/04/15 18:58:47 carl
  858. + target_info.size_of_pointer -> pointer_Size
  859. Revision 1.6 2002/04/04 19:05:57 peter
  860. * removed unused units
  861. * use tlocation.size in cg.a_*loc*() routines
  862. Revision 1.5 2002/04/02 17:11:28 peter
  863. * tlocation,treference update
  864. * LOC_CONSTANT added for better constant handling
  865. * secondadd splitted in multiple routines
  866. * location_force_reg added for loading a location to a register
  867. of a specified size
  868. * secondassignment parses now first the right and then the left node
  869. (this is compatible with Kylix). This saves a lot of push/pop especially
  870. with string operations
  871. * adapted some routines to use the new cg methods
  872. Revision 1.4 2002/03/31 20:26:34 jonas
  873. + a_loadfpu_* and a_loadmm_* methods in tcg
  874. * register allocation is now handled by a class and is mostly processor
  875. independent (+rgobj.pas and i386/rgcpu.pas)
  876. * temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
  877. * some small improvements and fixes to the optimizer
  878. * some register allocation fixes
  879. * some fpuvaroffset fixes in the unary minus node
  880. * push/popusedregisters is now called rg.save/restoreusedregisters and
  881. (for i386) uses temps instead of push/pop's when using -Op3 (that code is
  882. also better optimizable)
  883. * fixed and optimized register saving/restoring for new/dispose nodes
  884. * LOC_FPU locations now also require their "register" field to be set to
  885. R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
  886. - list field removed of the tnode class because it's not used currently
  887. and can cause hard-to-find bugs
  888. }