2
0

ncgmem.pas 39 KB

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