ncgmem.pas 42 KB

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