ncgmem.pas 42 KB

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