ncgmem.pas 38 KB

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