ncgmem.pas 40 KB

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