ncgmem.pas 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979
  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,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,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,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.28 2002-09-17 18:54:02 jonas
  774. * a_load_reg_reg() now has two size parameters: source and dest. This
  775. allows some optimizations on architectures that don't encode the
  776. register size in the register name.
  777. Revision 1.27 2002/09/07 15:25:03 peter
  778. * old logs removed and tabs fixed
  779. Revision 1.26 2002/09/01 18:46:01 peter
  780. * fixed generic tcgvecnode
  781. * move code that updates a reference with index register and multiplier
  782. to separate method so it can be overriden for scaled indexing
  783. * i386 uses generic tcgvecnode
  784. Revision 1.25 2002/08/23 16:14:48 peter
  785. * tempgen cleanup
  786. * tt_noreuse temp type added that will be used in genentrycode
  787. Revision 1.24 2002/08/15 08:13:54 carl
  788. - a_load_sym_ofs_reg removed
  789. * loadvmt now calls loadaddr_ref_reg instead
  790. Revision 1.23 2002/08/11 14:32:26 peter
  791. * renamed current_library to objectlibrary
  792. Revision 1.22 2002/08/11 13:24:12 peter
  793. * saving of asmsymbols in ppu supported
  794. * asmsymbollist global is removed and moved into a new class
  795. tasmlibrarydata that will hold the info of a .a file which
  796. corresponds with a single module. Added librarydata to tmodule
  797. to keep the library info stored for the module. In the future the
  798. objectfiles will also be stored to the tasmlibrarydata class
  799. * all getlabel/newasmsymbol and friends are moved to the new class
  800. Revision 1.21 2002/08/11 11:36:57 jonas
  801. * always first try to use base and only then index
  802. Revision 1.20 2002/08/11 06:14:40 florian
  803. * fixed powerpc compilation problems
  804. Revision 1.19 2002/08/10 14:46:29 carl
  805. + moved target_cpu_string to cpuinfo
  806. * renamed asmmode enum.
  807. * assembler reader has now less ifdef's
  808. * move from nppcmem.pas -> ncgmem.pas vec. node.
  809. Revision 1.18 2002/07/28 21:34:31 florian
  810. * more powerpc fixes
  811. + dummy tcgvecnode
  812. Revision 1.17 2002/07/11 14:41:28 florian
  813. * start of the new generic parameter handling
  814. Revision 1.16 2002/07/07 09:52:32 florian
  815. * powerpc target fixed, very simple units can be compiled
  816. * some basic stuff for better callparanode handling, far from being finished
  817. Revision 1.15 2002/07/01 18:46:23 peter
  818. * internal linker
  819. * reorganized aasm layer
  820. Revision 1.14 2002/07/01 16:23:53 peter
  821. * cg64 patch
  822. * basics for currency
  823. * asnode updates for class and interface (not finished)
  824. Revision 1.13 2002/05/20 13:30:40 carl
  825. * bugfix of hdisponen (base must be set, not index)
  826. * more portability fixes
  827. Revision 1.12 2002/05/18 13:34:09 peter
  828. * readded missing revisions
  829. Revision 1.11 2002/05/16 19:46:37 carl
  830. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  831. + try to fix temp allocation (still in ifdef)
  832. + generic constructor calls
  833. + start of tassembler / tmodulebase class cleanup
  834. Revision 1.9 2002/05/12 16:53:07 peter
  835. * moved entry and exitcode to ncgutil and cgobj
  836. * foreach gets extra argument for passing local data to the
  837. iterator function
  838. * -CR checks also class typecasts at runtime by changing them
  839. into as
  840. * fixed compiler to cycle with the -CR option
  841. * fixed stabs with elf writer, finally the global variables can
  842. be watched
  843. * removed a lot of routines from cga unit and replaced them by
  844. calls to cgobj
  845. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  846. u32bit then the other is typecasted also to u32bit without giving
  847. a rangecheck warning/error.
  848. * fixed pascal calling method with reversing also the high tree in
  849. the parast, detected by tcalcst3 test
  850. Revision 1.8 2002/04/20 21:32:23 carl
  851. + generic FPC_CHECKPOINTER
  852. + first parameter offset in stack now portable
  853. * rename some constants
  854. + move some cpu stuff to other units
  855. - remove unused constents
  856. * fix stacksize for some targets
  857. * fix generic size problems which depend now on EXTEND_SIZE constant
  858. Revision 1.7 2002/04/15 18:58:47 carl
  859. + target_info.size_of_pointer -> pointer_Size
  860. Revision 1.6 2002/04/04 19:05:57 peter
  861. * removed unused units
  862. * use tlocation.size in cg.a_*loc*() routines
  863. }