ncgmem.pas 47 KB

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