ncgmem.pas 41 KB

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