ncgmem.pas 44 KB

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