ncgmem.pas 39 KB

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