ncgmem.pas 43 KB

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