ncgmem.pas 39 KB

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