ncgmem.pas 45 KB

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