ncgmem.pas 37 KB

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