ncgmem.pas 44 KB

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