ncgmem.pas 39 KB

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