ncgld.pas 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Generate assembler for nodes that handle loads and assignments which
  4. are the same for all (most) processors
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit ncgld;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. node,nld,cgutils;
  23. type
  24. tcgloadnode = class(tloadnode)
  25. procedure pass_generate_code;override;
  26. procedure generate_picvaraccess;virtual;
  27. procedure changereflocation(const ref: treference);
  28. end;
  29. tcgassignmentnode = class(tassignmentnode)
  30. procedure pass_generate_code;override;
  31. end;
  32. tcgarrayconstructornode = class(tarrayconstructornode)
  33. procedure pass_generate_code;override;
  34. end;
  35. tcgrttinode = class(trttinode)
  36. procedure pass_generate_code;override;
  37. end;
  38. implementation
  39. uses
  40. cutils,
  41. systems,
  42. verbose,globtype,globals,constexp,
  43. nutils,
  44. symconst,symtype,symdef,symsym,defutil,paramgr,
  45. ncnv,ncon,nmem,nbas,ncgrtti,
  46. aasmbase,aasmtai,aasmdata,aasmcpu,
  47. cgbase,pass_2,
  48. procinfo,
  49. cpubase,parabase,
  50. tgobj,ncgutil,
  51. cgobj,
  52. ncgbas,ncgflw;
  53. {*****************************************************************************
  54. SSA (for memory temps) support
  55. *****************************************************************************}
  56. type
  57. preplacerefrec = ^treplacerefrec;
  58. treplacerefrec = record
  59. old, new: preference;
  60. ressym: tsym;
  61. end;
  62. function doreplaceref(var n: tnode; para: pointer): foreachnoderesult;
  63. var
  64. rr: preplacerefrec absolute para;
  65. begin
  66. result := fen_false;
  67. case n.nodetype of
  68. loadn:
  69. begin
  70. { regular variable }
  71. if (tabstractvarsym(tloadnode(n).symtableentry).varoptions * [vo_is_dll_var, vo_is_thread_var] = []) and
  72. not assigned(tloadnode(n).left) and
  73. { not function result, or no exit in function }
  74. (((tloadnode(n).symtableentry <> rr^.ressym) and
  75. not(vo_is_funcret in tabstractvarsym(tloadnode(n).symtableentry).varoptions)) or
  76. not(fc_exit in flowcontrol)) and
  77. { stored in memory... }
  78. (tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.loc in [LOC_REFERENCE]) and
  79. { ... at the place we are looking for }
  80. references_equal(tabstractnormalvarsym(tloadnode(n).symtableentry).localloc.reference,rr^.old^) then
  81. begin
  82. { relocate variable }
  83. tcgloadnode(n).changereflocation(rr^.new^);
  84. result := fen_norecurse_true;
  85. end;
  86. end;
  87. temprefn:
  88. begin
  89. if (ti_valid in ttemprefnode(n).tempinfo^.flags) and
  90. { memory temp... }
  91. (ttemprefnode(n).tempinfo^.location.loc in [LOC_REFERENCE]) and
  92. { ... at the place we are looking for }
  93. references_equal(ttemprefnode(n).tempinfo^.location.reference,rr^.old^) then
  94. begin
  95. { relocate the temp }
  96. tcgtemprefnode(n).changelocation(rr^.new^);
  97. result := fen_norecurse_true;
  98. end;
  99. end;
  100. { optimize the searching a bit }
  101. derefn,addrn,
  102. calln,inlinen,casen,
  103. addn,subn,muln,
  104. andn,orn,xorn,
  105. ltn,lten,gtn,gten,equaln,unequaln,
  106. slashn,divn,shrn,shln,notn,
  107. inn,
  108. asn,isn:
  109. result := fen_norecurse_false;
  110. end;
  111. end;
  112. function maybechangetemp(list: TAsmList; var n: tnode; const newref: treference): boolean;
  113. var
  114. rr: treplacerefrec;
  115. begin
  116. result := false;
  117. { only do for -O2 or higher (breaks debugging since }
  118. { variables move to different memory locations) }
  119. if not(cs_opt_level2 in current_settings.optimizerswitches) or
  120. { must be a copy to a memory location ... }
  121. (n.location.loc <> LOC_REFERENCE) or
  122. { not inside a control flow statement and no goto's in sight }
  123. ([fc_inflowcontrol,fc_gotolabel] * flowcontrol <> []) or
  124. { not for refcounted types, because those locations are }
  125. { still used later on in initialisation/finalisation code }
  126. (not(is_class(n.resultdef)) and
  127. n.resultdef.needs_inittable) or
  128. { source and destination are temps (= not global variables) }
  129. not tg.istemp(n.location.reference) or
  130. not tg.istemp(newref) or
  131. { and both point to the start of a temp, and the source is a }
  132. { non-persistent temp (otherwise we need some kind of copy- }
  133. { on-write support in case later on both are still used) }
  134. (tg.gettypeoftemp(newref) <> tt_normal) or
  135. not (tg.gettypeoftemp(n.location.reference) in [tt_normal,tt_persistent]) or
  136. { and both have the same size }
  137. (tg.sizeoftemp(current_asmdata.CurrAsmList,newref) <> tg.sizeoftemp(current_asmdata.CurrAsmList,n.location.reference)) then
  138. exit;
  139. { find the source of the old reference (loadnode or tempnode) }
  140. { and replace it with the new reference }
  141. rr.old := @n.location.reference;
  142. rr.new := @newref;
  143. rr.ressym := nil;
  144. if (current_procinfo.procdef.funcretloc[calleeside].loc<>LOC_VOID) and
  145. assigned(current_procinfo.procdef.funcretsym) and
  146. (tabstractvarsym(current_procinfo.procdef.funcretsym).refs <> 0) then
  147. if (current_procinfo.procdef.proctypeoption=potype_constructor) then
  148. rr.ressym:=tsym(current_procinfo.procdef.parast.Find('self'))
  149. else
  150. rr.ressym:=current_procinfo.procdef.funcretsym;
  151. { if source not found, don't do anything }
  152. if not foreachnodestatic(n,@doreplaceref,@rr) then
  153. exit;
  154. n.location.reference := newref;
  155. result:=true;
  156. end;
  157. {*****************************************************************************
  158. SecondLoad
  159. *****************************************************************************}
  160. procedure tcgloadnode.generate_picvaraccess;
  161. begin
  162. {$ifndef sparc}
  163. location.reference.base:=current_procinfo.got;
  164. location.reference.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname+'@GOT');
  165. {$endif sparc}
  166. end;
  167. procedure tcgloadnode.changereflocation(const ref: treference);
  168. var
  169. oldtemptype: ttemptype;
  170. begin
  171. if (location.loc<>LOC_REFERENCE) then
  172. internalerror(2007020812);
  173. if not tg.istemp(location.reference) then
  174. internalerror(2007020813);
  175. oldtemptype:=tg.gettypeoftemp(location.reference);
  176. if (oldtemptype = tt_persistent) then
  177. tg.ChangeTempType(current_asmdata.CurrAsmList,location.reference,tt_normal);
  178. tg.ungettemp(current_asmdata.CurrAsmList,location.reference);
  179. location.reference:=ref;
  180. tg.ChangeTempType(current_asmdata.CurrAsmList,location.reference,oldtemptype);
  181. tabstractnormalvarsym(symtableentry).localloc:=location;
  182. end;
  183. procedure tcgloadnode.pass_generate_code;
  184. var
  185. hregister : tregister;
  186. vs : tabstractnormalvarsym;
  187. gvs : tstaticvarsym;
  188. pd : tprocdef;
  189. href : treference;
  190. newsize : tcgsize;
  191. endrelocatelab,
  192. norelocatelab : tasmlabel;
  193. paraloc1 : tcgpara;
  194. begin
  195. { we don't know the size of all arrays }
  196. newsize:=def_cgsize(resultdef);
  197. location_reset(location,LOC_REFERENCE,newsize);
  198. case symtableentry.typ of
  199. absolutevarsym :
  200. begin
  201. { this is only for toasm and toaddr }
  202. case tabsolutevarsym(symtableentry).abstyp of
  203. toaddr :
  204. begin
  205. {$ifdef i386}
  206. if tabsolutevarsym(symtableentry).absseg then
  207. location.reference.segment:=NR_FS;
  208. {$endif i386}
  209. location.reference.offset:=tabsolutevarsym(symtableentry).addroffset;
  210. end;
  211. toasm :
  212. location.reference.symbol:=current_asmdata.RefAsmSymbol(tabsolutevarsym(symtableentry).mangledname);
  213. else
  214. internalerror(200310283);
  215. end;
  216. end;
  217. constsym:
  218. begin
  219. if tconstsym(symtableentry).consttyp=constresourcestring then
  220. begin
  221. location_reset(location,LOC_CREFERENCE,OS_ADDR);
  222. location.reference.symbol:=current_asmdata.RefAsmSymbol(make_mangledname('RESSTR',symtableentry.owner,symtableentry.name));
  223. { Resourcestring layout:
  224. TResourceStringRecord = Packed Record
  225. Name,
  226. CurrentValue,
  227. DefaultValue : AnsiString;
  228. HashValue : LongWord;
  229. end;
  230. }
  231. location.reference.offset:=sizeof(pint);
  232. end
  233. else
  234. internalerror(22798);
  235. end;
  236. staticvarsym :
  237. begin
  238. gvs:=tstaticvarsym(symtableentry);
  239. if ([vo_is_dll_var,vo_is_external] * gvs.varoptions <> []) then
  240. begin
  241. location.reference.base := cg.g_indirect_sym_load(current_asmdata.CurrAsmList,tstaticvarsym(symtableentry).mangledname);
  242. if (location.reference.base <> NR_NO) then
  243. exit;
  244. end;
  245. if (vo_is_dll_var in gvs.varoptions) then
  246. { DLL variable }
  247. begin
  248. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  249. location.reference.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname);
  250. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,location.reference,hregister);
  251. reference_reset_base(location.reference,hregister,0);
  252. end
  253. { Thread variable }
  254. else if (vo_is_thread_var in gvs.varoptions) and
  255. not(tf_section_threadvars in target_info.flags) then
  256. begin
  257. if (tf_section_threadvars in target_info.flags) then
  258. begin
  259. if gvs.localloc.loc=LOC_INVALID then
  260. reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname),0)
  261. else
  262. location:=gvs.localloc;
  263. {$ifdef i386}
  264. case target_info.system of
  265. system_i386_linux:
  266. location.reference.segment:=NR_GS;
  267. system_i386_win32:
  268. location.reference.segment:=NR_FS;
  269. end;
  270. {$endif i386}
  271. end
  272. else
  273. begin
  274. {
  275. Thread var loading is optimized to first check if
  276. a relocate function is available. When the function
  277. is available it is called to retrieve the address.
  278. Otherwise the address is loaded with the symbol
  279. The code needs to be in the order to first handle the
  280. call and then the address load to be sure that the
  281. register that is used for returning is the same (PFV)
  282. }
  283. current_asmdata.getjumplabel(norelocatelab);
  284. current_asmdata.getjumplabel(endrelocatelab);
  285. { make sure hregister can't allocate the register necessary for the parameter }
  286. paraloc1.init;
  287. paramanager.getintparaloc(pocall_default,1,paraloc1);
  288. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  289. reference_reset_symbol(href,current_asmdata.RefAsmSymbol('FPC_THREADVAR_RELOCATE'),0);
  290. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
  291. cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_ADDR,OC_EQ,0,hregister,norelocatelab);
  292. { don't save the allocated register else the result will be destroyed later }
  293. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname),0);
  294. paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc1);
  295. cg.a_param_ref(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
  296. paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc1);
  297. paraloc1.done;
  298. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  299. cg.a_call_reg(current_asmdata.CurrAsmList,hregister);
  300. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  301. cg.getcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
  302. cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
  303. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  304. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_ADDR,NR_FUNCTION_RESULT_REG,hregister);
  305. cg.a_jmp_always(current_asmdata.CurrAsmList,endrelocatelab);
  306. cg.a_label(current_asmdata.CurrAsmList,norelocatelab);
  307. { no relocation needed, load the address of the variable only, the
  308. layout of a threadvar is (4 bytes pointer):
  309. 0 - Threadvar index
  310. 4 - Threadvar value in single threading }
  311. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname),sizeof(pint));
  312. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,hregister);
  313. cg.a_label(current_asmdata.CurrAsmList,endrelocatelab);
  314. location.reference.base:=hregister;
  315. end;
  316. end
  317. { Normal (or external) variable }
  318. else
  319. begin
  320. if gvs.localloc.loc=LOC_INVALID then
  321. reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname),0)
  322. else
  323. location:=gvs.localloc;
  324. end;
  325. { make const a LOC_CREFERENCE }
  326. if (gvs.varspez=vs_const) and
  327. (location.loc=LOC_REFERENCE) then
  328. location.loc:=LOC_CREFERENCE;
  329. end;
  330. paravarsym,
  331. localvarsym :
  332. begin
  333. vs:=tabstractnormalvarsym(symtableentry);
  334. { Nested variable }
  335. if assigned(left) then
  336. begin
  337. secondpass(left);
  338. if left.location.loc<>LOC_REGISTER then
  339. internalerror(200309286);
  340. if vs.localloc.loc<>LOC_REFERENCE then
  341. internalerror(200409241);
  342. reference_reset_base(location.reference,left.location.register,vs.localloc.reference.offset);
  343. end
  344. else
  345. location:=vs.localloc;
  346. { handle call by reference variables when they are not
  347. alreayd copied to local copies. Also ignore the reference
  348. when we need to load the self pointer for objects }
  349. if is_addr_param_load then
  350. begin
  351. if (location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
  352. hregister:=location.register
  353. else
  354. begin
  355. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  356. { we need to load only an address }
  357. location.size:=OS_ADDR;
  358. cg.a_load_loc_reg(current_asmdata.CurrAsmList,location.size,location,hregister);
  359. end;
  360. location_reset(location,LOC_REFERENCE,newsize);
  361. location.reference.base:=hregister;
  362. end;
  363. { make const a LOC_CREFERENCE }
  364. if (vs.varspez=vs_const) and
  365. (location.loc=LOC_REFERENCE) then
  366. location.loc:=LOC_CREFERENCE;
  367. end;
  368. procsym:
  369. begin
  370. if not assigned(procdef) then
  371. internalerror(200312011);
  372. if assigned(left) then
  373. begin
  374. if (sizeof(pint) = 4) then
  375. location_reset(location,LOC_CREFERENCE,OS_64)
  376. else if (sizeof(pint) = 8) then
  377. location_reset(location,LOC_CREFERENCE,OS_128)
  378. else
  379. internalerror(20020520);
  380. tg.GetTemp(current_asmdata.CurrAsmList,2*sizeof(pint),tt_normal,location.reference);
  381. secondpass(left);
  382. { load class instance/classrefdef address }
  383. if left.location.loc=LOC_CONSTANT then
  384. location_force_reg(current_asmdata.CurrAsmList,left.location,OS_ADDR,false);
  385. case left.location.loc of
  386. LOC_CREGISTER,
  387. LOC_REGISTER:
  388. begin
  389. { this is not possible for objects }
  390. if is_object(left.resultdef) then
  391. internalerror(200304234);
  392. hregister:=left.location.register;
  393. end;
  394. LOC_CREFERENCE,
  395. LOC_REFERENCE:
  396. begin
  397. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  398. if not is_object(left.resultdef) then
  399. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.reference,hregister)
  400. else
  401. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,hregister);
  402. location_freetemp(current_asmdata.CurrAsmList,left.location);
  403. end;
  404. else
  405. internalerror(200610311);
  406. end;
  407. { store the class instance or classredef address }
  408. href:=location.reference;
  409. inc(href.offset,sizeof(pint));
  410. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,href);
  411. { virtual method ? }
  412. if (po_virtualmethod in procdef.procoptions) and
  413. not(nf_inherited in flags) then
  414. begin
  415. { a classrefdef already points to the VMT }
  416. if (left.resultdef.typ<>classrefdef) then
  417. begin
  418. { load vmt pointer }
  419. reference_reset_base(href,hregister,0);
  420. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  421. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
  422. end;
  423. { load method address }
  424. reference_reset_base(href,hregister,procdef._class.vmtmethodoffset(procdef.extnumber));
  425. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  426. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
  427. { ... and store it }
  428. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,location.reference);
  429. end
  430. else
  431. begin
  432. { load address of the function }
  433. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(procdef.mangledname),0);
  434. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  435. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,hregister);
  436. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,location.reference);
  437. end;
  438. end
  439. else
  440. begin
  441. pd:=tprocdef(tprocsym(symtableentry).ProcdefList[0]);
  442. if (po_external in pd.procoptions) then
  443. location.reference.base := cg.g_indirect_sym_load(current_asmdata.CurrAsmList,pd.mangledname);
  444. {!!!!! Be aware, work on virtual methods too }
  445. if (location.reference.base = NR_NO) then
  446. location.reference.symbol:=current_asmdata.RefAsmSymbol(procdef.mangledname);
  447. end;
  448. end;
  449. labelsym :
  450. location.reference.symbol:=tcglabelnode((tlabelsym(symtableentry).code)).getasmlabel;
  451. else internalerror(200510032);
  452. end;
  453. end;
  454. {*****************************************************************************
  455. SecondAssignment
  456. *****************************************************************************}
  457. procedure tcgassignmentnode.pass_generate_code;
  458. var
  459. otlabel,hlabel,oflabel : tasmlabel;
  460. href : treference;
  461. releaseright : boolean;
  462. len : aint;
  463. r:Tregister;
  464. begin
  465. location_reset(location,LOC_VOID,OS_NO);
  466. otlabel:=current_procinfo.CurrTrueLabel;
  467. oflabel:=current_procinfo.CurrFalseLabel;
  468. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  469. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  470. {
  471. in most cases we can process first the right node which contains
  472. the most complex code. Exceptions for this are:
  473. - result is in flags, loading left will then destroy the flags
  474. - result is a jump, loading left must be already done before the jump is made
  475. - result need reference count, when left points to a value used in
  476. right then decreasing the refcnt on left can possibly release
  477. the memory before right increased the refcnt, result is that an
  478. empty value is assigned
  479. But not when the result is in the flags, then
  480. loading the left node afterwards can destroy the flags.
  481. }
  482. if not(right.expectloc in [LOC_FLAGS,LOC_JUMP]) and
  483. ((right.resultdef.needs_inittable) or
  484. (node_complexity(right)>node_complexity(left))) then
  485. begin
  486. secondpass(right);
  487. { increment source reference counter, this is
  488. useless for constants }
  489. if (right.resultdef.needs_inittable) and
  490. not is_constnode(right) then
  491. begin
  492. location_force_mem(current_asmdata.CurrAsmList,right.location);
  493. location_get_data_ref(current_asmdata.CurrAsmList,right.location,href,false);
  494. cg.g_incrrefcount(current_asmdata.CurrAsmList,right.resultdef,href);
  495. end;
  496. if codegenerror then
  497. exit;
  498. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  499. { can be false }
  500. secondpass(left);
  501. { decrement destination reference counter }
  502. if (left.resultdef.needs_inittable) then
  503. begin
  504. location_get_data_ref(current_asmdata.CurrAsmList,left.location,href,false);
  505. cg.g_decrrefcount(current_asmdata.CurrAsmList,left.resultdef,href);
  506. end;
  507. if codegenerror then
  508. exit;
  509. end
  510. else
  511. begin
  512. { calculate left sides }
  513. secondpass(left);
  514. { decrement destination reference counter }
  515. if (left.resultdef.needs_inittable) then
  516. begin
  517. location_get_data_ref(current_asmdata.CurrAsmList,left.location,href,false);
  518. cg.g_decrrefcount(current_asmdata.CurrAsmList,left.resultdef,href);
  519. end;
  520. if codegenerror then
  521. exit;
  522. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  523. { can be false }
  524. secondpass(right);
  525. { increment source reference counter, this is
  526. useless for string constants}
  527. if (right.resultdef.needs_inittable) and
  528. (right.nodetype<>stringconstn) then
  529. begin
  530. location_force_mem(current_asmdata.CurrAsmList,right.location);
  531. location_get_data_ref(current_asmdata.CurrAsmList,right.location,href,false);
  532. cg.g_incrrefcount(current_asmdata.CurrAsmList,right.resultdef,href);
  533. end;
  534. if codegenerror then
  535. exit;
  536. end;
  537. releaseright:=true;
  538. { shortstring assignments are handled separately }
  539. if is_shortstring(left.resultdef) then
  540. begin
  541. {
  542. we can get here only in the following situations
  543. for the right node:
  544. - empty constant string
  545. - char
  546. }
  547. { The addn is replaced by a blockn or calln that already returns
  548. a shortstring }
  549. if is_shortstring(right.resultdef) and
  550. (right.nodetype in [blockn,calln]) then
  551. begin
  552. { nothing to do }
  553. end
  554. { empty constant string }
  555. else if (right.nodetype=stringconstn) and
  556. (tstringconstnode(right).len=0) then
  557. begin
  558. cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_8,0,left.location.reference);
  559. end
  560. { char loading }
  561. else if is_char(right.resultdef) then
  562. begin
  563. if right.nodetype=ordconstn then
  564. begin
  565. if (target_info.endian = endian_little) then
  566. cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_16,(tordconstnode(right).value.svalue shl 8) or 1,
  567. setalignment(left.location.reference,1))
  568. else
  569. cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_16,tordconstnode(right).value.svalue or (1 shl 8),
  570. setalignment(left.location.reference,1));
  571. end
  572. else
  573. begin
  574. href:=left.location.reference;
  575. cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_8,1,href);
  576. inc(href.offset,1);
  577. case right.location.loc of
  578. LOC_REGISTER,
  579. LOC_CREGISTER :
  580. begin
  581. r:=cg.makeregsize(current_asmdata.CurrAsmList,right.location.register,OS_8);
  582. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_8,OS_8,r,href);
  583. end;
  584. LOC_REFERENCE,
  585. LOC_CREFERENCE :
  586. cg.a_load_ref_ref(current_asmdata.CurrAsmList,OS_8,OS_8,right.location.reference,href);
  587. else
  588. internalerror(200205111);
  589. end;
  590. end;
  591. end
  592. else
  593. internalerror(200204249);
  594. end
  595. { try to reuse memory locations instead of copying }
  596. { copy to a memory location ... }
  597. else if (right.location.loc = LOC_REFERENCE) and
  598. maybechangetemp(current_asmdata.CurrAsmList,left,right.location.reference) then
  599. begin
  600. { if it worked, we're done }
  601. end
  602. else
  603. begin
  604. { SSA support }
  605. maybechangeloadnodereg(current_asmdata.CurrAsmList,left,false);
  606. maybechangeloadnodereg(current_asmdata.CurrAsmList,right,true);
  607. case right.location.loc of
  608. LOC_CONSTANT :
  609. begin
  610. {$ifndef cpu64bitalu}
  611. if (left.location.size in [OS_64,OS_S64]) or (right.location.size in [OS_64,OS_S64]) then
  612. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,right.location.value64,left.location)
  613. else
  614. {$endif not cpu64bitalu}
  615. cg.a_load_const_loc(current_asmdata.CurrAsmList,right.location.value,left.location);
  616. end;
  617. LOC_REFERENCE,
  618. LOC_CREFERENCE :
  619. begin
  620. case left.location.loc of
  621. LOC_REGISTER,
  622. LOC_CREGISTER :
  623. begin
  624. {$ifndef cpu64bitalu}
  625. if left.location.size in [OS_64,OS_S64] then
  626. cg64.a_load64_ref_reg(current_asmdata.CurrAsmList,right.location.reference,left.location.register64)
  627. else
  628. {$endif not cpu64bitalu}
  629. cg.a_load_ref_reg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.register);
  630. end;
  631. LOC_FPUREGISTER,
  632. LOC_CFPUREGISTER :
  633. begin
  634. cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
  635. right.location.size,left.location.size,
  636. right.location.reference,
  637. left.location.register);
  638. end;
  639. LOC_REFERENCE,
  640. LOC_CREFERENCE :
  641. begin
  642. if (left.resultdef.typ=floatdef) and
  643. (right.resultdef.typ=floatdef) and
  644. (left.location.size<>right.location.size) then
  645. begin
  646. cg.a_loadfpu_ref_ref(current_asmdata.CurrAsmList,
  647. right.location.size,left.location.size,
  648. right.location.reference,left.location.reference)
  649. end
  650. else
  651. begin
  652. {$warning HACK: unaligned test, maybe remove all unaligned locations (array of char) from the compiler}
  653. { Use unaligned copy when the offset is not aligned }
  654. len:=left.resultdef.size;
  655. if (right.location.reference.offset mod sizeof(aint)<>0) or
  656. (left.location.reference.offset mod sizeof(aint)<>0) or
  657. (right.resultdef.alignment<sizeof(aint)) or
  658. ((right.location.reference.alignment<>0) and
  659. (right.location.reference.alignment<sizeof(aint))) or
  660. ((left.location.reference.alignment<>0) and
  661. (left.location.reference.alignment<sizeof(aint))) then
  662. cg.g_concatcopy_unaligned(current_asmdata.CurrAsmList,right.location.reference,left.location.reference,len)
  663. else
  664. cg.g_concatcopy(current_asmdata.CurrAsmList,right.location.reference,left.location.reference,len);
  665. end;
  666. end;
  667. LOC_MMREGISTER,
  668. LOC_CMMREGISTER:
  669. begin
  670. {$ifdef x86}
  671. if not use_sse(right.resultdef) then
  672. begin
  673. { perform size conversion if needed (the mm-code cannot }
  674. { convert an extended into a double/single, since sse }
  675. { doesn't support extended) }
  676. r:=cg.getfpuregister(current_asmdata.CurrAsmList,right.location.size);
  677. tg.gettemp(current_asmdata.CurrAsmList,left.resultdef.size,tt_normal,href);
  678. cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,right.location.size,right.location.size,right.location.reference,r);
  679. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,r,href);
  680. if releaseright then
  681. location_freetemp(current_asmdata.CurrAsmList,right.location);
  682. releaseright:=true;
  683. location_reset(right.location,LOC_REFERENCE,left.location.size);
  684. right.location.reference:=href;
  685. end;
  686. {$endif}
  687. cg.a_loadmm_ref_reg(current_asmdata.CurrAsmList,
  688. right.location.size,
  689. left.location.size,
  690. right.location.reference,
  691. left.location.register,mms_movescalar);
  692. end;
  693. LOC_SUBSETREG,
  694. LOC_CSUBSETREG:
  695. cg.a_load_ref_subsetreg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.sreg);
  696. LOC_SUBSETREF,
  697. LOC_CSUBSETREF:
  698. {$ifndef cpu64bitalu}
  699. if right.location.size in [OS_64,OS_S64] then
  700. cg64.a_load64_ref_subsetref(current_asmdata.CurrAsmList,right.location.reference,left.location.sref)
  701. else
  702. {$endif not cpu64bitalu}
  703. cg.a_load_ref_subsetref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.sref);
  704. else
  705. internalerror(200203284);
  706. end;
  707. end;
  708. {$ifdef SUPPORT_MMX}
  709. LOC_CMMXREGISTER,
  710. LOC_MMXREGISTER:
  711. begin
  712. if left.location.loc=LOC_CMMXREGISTER then
  713. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.register,nil)
  714. else
  715. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.reference,nil);
  716. end;
  717. {$endif SUPPORT_MMX}
  718. LOC_MMREGISTER,
  719. LOC_CMMREGISTER:
  720. begin
  721. if left.resultdef.typ=arraydef then
  722. begin
  723. end
  724. else
  725. begin
  726. if left.location.loc=LOC_CMMREGISTER then
  727. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,left.location.register,mms_movescalar)
  728. else
  729. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,left.location.reference,mms_movescalar);
  730. end;
  731. end;
  732. LOC_REGISTER,
  733. LOC_CREGISTER :
  734. begin
  735. {$ifndef cpu64bitalu}
  736. if left.location.size in [OS_64,OS_S64] then
  737. cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,
  738. right.location.register64,left.location)
  739. else
  740. {$endif not cpu64bitalu}
  741. cg.a_load_reg_loc(current_asmdata.CurrAsmList,right.location.size,right.location.register,left.location);
  742. end;
  743. LOC_FPUREGISTER,
  744. LOC_CFPUREGISTER :
  745. begin
  746. { we can't do direct moves between fpu and mm registers }
  747. if left.location.loc in [LOC_MMREGISTER,LOC_CMMREGISTER] then
  748. begin
  749. {$ifdef x86}
  750. if not use_sse(right.resultdef) then
  751. begin
  752. { perform size conversion if needed (the mm-code cannot convert an }
  753. { extended into a double/single, since sse doesn't support extended) }
  754. tg.gettemp(current_asmdata.CurrAsmList,left.resultdef.size,tt_normal,href);
  755. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,href);
  756. location_reset(right.location,LOC_REFERENCE,left.location.size);
  757. right.location.reference:=href;
  758. end;
  759. {$endif}
  760. location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,false);
  761. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,
  762. right.location.size,left.location.size,
  763. right.location.register,left.location.register,mms_movescalar);
  764. end
  765. else
  766. cg.a_loadfpu_reg_loc(current_asmdata.CurrAsmList,
  767. right.location.size,
  768. right.location.register,left.location);
  769. end;
  770. LOC_SUBSETREG,
  771. LOC_CSUBSETREG:
  772. begin
  773. cg.a_load_subsetreg_loc(current_asmdata.CurrAsmList,
  774. right.location.size,right.location.sreg,left.location);
  775. end;
  776. LOC_SUBSETREF,
  777. LOC_CSUBSETREF:
  778. begin
  779. {$ifndef cpu64bitalu}
  780. if right.location.size in [OS_64,OS_S64] then
  781. cg64.a_load64_subsetref_loc(current_asmdata.CurrAsmList,right.location.sref,left.location)
  782. else
  783. {$endif not cpu64bitalu}
  784. cg.a_load_subsetref_loc(current_asmdata.CurrAsmList,
  785. right.location.size,right.location.sref,left.location);
  786. end;
  787. LOC_JUMP :
  788. begin
  789. current_asmdata.getjumplabel(hlabel);
  790. cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
  791. if is_pasbool(left.resultdef) then
  792. cg.a_load_const_loc(current_asmdata.CurrAsmList,1,left.location)
  793. else
  794. cg.a_load_const_loc(current_asmdata.CurrAsmList,-1,left.location);
  795. cg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
  796. cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
  797. cg.a_load_const_loc(current_asmdata.CurrAsmList,0,left.location);
  798. cg.a_label(current_asmdata.CurrAsmList,hlabel);
  799. end;
  800. {$ifdef cpuflags}
  801. LOC_FLAGS :
  802. begin
  803. if is_pasbool(left.resultdef) then
  804. begin
  805. case left.location.loc of
  806. LOC_REGISTER,LOC_CREGISTER:
  807. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.register);
  808. LOC_REFERENCE:
  809. cg.g_flags2ref(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.reference);
  810. LOC_SUBSETREG,LOC_SUBSETREF:
  811. begin
  812. r:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
  813. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,r);
  814. cg.a_load_reg_loc(current_asmdata.CurrAsmList,left.location.size,r,left.location);
  815. end;
  816. else
  817. internalerror(200203273);
  818. end;
  819. end
  820. else
  821. begin
  822. r:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
  823. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,r);
  824. cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,left.location.size,r,r);
  825. cg.a_load_reg_loc(current_asmdata.CurrAsmList,left.location.size,r,left.location);
  826. end;
  827. end;
  828. {$endif cpuflags}
  829. end;
  830. end;
  831. if releaseright then
  832. location_freetemp(current_asmdata.CurrAsmList,right.location);
  833. current_procinfo.CurrTrueLabel:=otlabel;
  834. current_procinfo.CurrFalseLabel:=oflabel;
  835. end;
  836. {*****************************************************************************
  837. SecondArrayConstruct
  838. *****************************************************************************}
  839. const
  840. vtInteger = 0;
  841. vtBoolean = 1;
  842. vtChar = 2;
  843. vtExtended = 3;
  844. vtString = 4;
  845. vtPointer = 5;
  846. vtPChar = 6;
  847. vtObject = 7;
  848. vtClass = 8;
  849. vtWideChar = 9;
  850. vtPWideChar = 10;
  851. vtAnsiString32 = 11;
  852. vtCurrency = 12;
  853. vtVariant = 13;
  854. vtInterface = 14;
  855. vtWideString = 15;
  856. vtInt64 = 16;
  857. vtQWord = 17;
  858. vtAnsiString16 = 18;
  859. vtAnsiString64 = 19;
  860. procedure tcgarrayconstructornode.pass_generate_code;
  861. var
  862. hp : tarrayconstructornode;
  863. href : treference;
  864. lt : tdef;
  865. vaddr : boolean;
  866. vtype : longint;
  867. freetemp,
  868. dovariant : boolean;
  869. elesize : longint;
  870. tmpreg : tregister;
  871. paraloc : tcgparalocation;
  872. otlabel,
  873. oflabel : tasmlabel;
  874. begin
  875. if is_packed_array(resultdef) then
  876. internalerror(200608042);
  877. dovariant:=(nf_forcevaria in flags) or is_variant_array(resultdef);
  878. if dovariant then
  879. elesize:=sizeof(pint)+sizeof(pint)
  880. else
  881. elesize:=tarraydef(resultdef).elesize;
  882. location_reset(location,LOC_CREFERENCE,OS_NO);
  883. fillchar(paraloc,sizeof(paraloc),0);
  884. { Allocate always a temp, also if no elements are required, to
  885. be sure that location is valid (PFV) }
  886. if tarraydef(resultdef).highrange=-1 then
  887. tg.GetTemp(current_asmdata.CurrAsmList,elesize,tt_normal,location.reference)
  888. else
  889. tg.GetTemp(current_asmdata.CurrAsmList,(tarraydef(resultdef).highrange+1)*elesize,tt_normal,location.reference);
  890. href:=location.reference;
  891. { Process nodes in array constructor }
  892. hp:=self;
  893. while assigned(hp) do
  894. begin
  895. if assigned(hp.left) then
  896. begin
  897. freetemp:=true;
  898. if (hp.left.expectloc=LOC_JUMP) then
  899. begin
  900. otlabel:=current_procinfo.CurrTrueLabel;
  901. oflabel:=current_procinfo.CurrFalseLabel;
  902. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  903. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  904. end;
  905. secondpass(hp.left);
  906. { Move flags and jump in register }
  907. if hp.left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  908. location_force_reg(current_asmdata.CurrAsmList,hp.left.location,def_cgsize(hp.left.resultdef),false);
  909. if (hp.left.location.loc=LOC_JUMP) then
  910. begin
  911. if (hp.left.expectloc<>LOC_JUMP) then
  912. internalerror(2007103101);
  913. current_procinfo.CurrTrueLabel:=otlabel;
  914. current_procinfo.CurrFalseLabel:=oflabel;
  915. end;
  916. if dovariant then
  917. begin
  918. { find the correct vtype value }
  919. vtype:=$ff;
  920. vaddr:=false;
  921. lt:=hp.left.resultdef;
  922. case lt.typ of
  923. enumdef,
  924. orddef :
  925. begin
  926. if is_64bit(lt) then
  927. begin
  928. case torddef(lt).ordtype of
  929. scurrency:
  930. vtype:=vtCurrency;
  931. s64bit:
  932. vtype:=vtInt64;
  933. u64bit:
  934. vtype:=vtQWord;
  935. end;
  936. freetemp:=false;
  937. vaddr:=true;
  938. end
  939. else if (lt.typ=enumdef) or
  940. is_integer(lt) then
  941. vtype:=vtInteger
  942. else
  943. if is_boolean(lt) then
  944. vtype:=vtBoolean
  945. else
  946. if (lt.typ=orddef) then
  947. begin
  948. case torddef(lt).ordtype of
  949. uchar:
  950. vtype:=vtChar;
  951. uwidechar:
  952. vtype:=vtWideChar;
  953. end;
  954. end;
  955. end;
  956. floatdef :
  957. begin
  958. if is_currency(lt) then
  959. vtype:=vtCurrency
  960. else
  961. vtype:=vtExtended;
  962. freetemp:=false;
  963. vaddr:=true;
  964. end;
  965. procvardef,
  966. pointerdef :
  967. begin
  968. if is_pchar(lt) then
  969. vtype:=vtPChar
  970. else if is_pwidechar(lt) then
  971. vtype:=vtPWideChar
  972. else
  973. vtype:=vtPointer;
  974. end;
  975. variantdef :
  976. begin
  977. vtype:=vtVariant;
  978. vaddr:=true;
  979. freetemp:=false;
  980. end;
  981. classrefdef :
  982. vtype:=vtClass;
  983. objectdef :
  984. if is_interface(lt) then
  985. vtype:=vtInterface
  986. { vtObject really means a class based on TObject }
  987. else if is_class(lt) then
  988. vtype:=vtObject
  989. else
  990. internalerror(200505171);
  991. stringdef :
  992. begin
  993. if is_shortstring(lt) then
  994. begin
  995. vtype:=vtString;
  996. vaddr:=true;
  997. freetemp:=false;
  998. end
  999. else
  1000. if is_ansistring(lt) then
  1001. begin
  1002. vtype:=vtAnsiString;
  1003. freetemp:=false;
  1004. end
  1005. else
  1006. if is_widestring(lt) then
  1007. begin
  1008. vtype:=vtWideString;
  1009. freetemp:=false;
  1010. end;
  1011. end;
  1012. end;
  1013. if vtype=$ff then
  1014. internalerror(14357);
  1015. { write changing field update href to the next element }
  1016. inc(href.offset,sizeof(pint));
  1017. if vaddr then
  1018. begin
  1019. location_force_mem(current_asmdata.CurrAsmList,hp.left.location);
  1020. tmpreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
  1021. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,hp.left.location.reference,tmpreg);
  1022. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,tmpreg,href);
  1023. end
  1024. else
  1025. cg.a_load_loc_ref(current_asmdata.CurrAsmList,OS_ADDR,hp.left.location,href);
  1026. { update href to the vtype field and write it }
  1027. dec(href.offset,sizeof(pint));
  1028. cg.a_load_const_ref(current_asmdata.CurrAsmList, OS_INT,vtype,href);
  1029. { goto next array element }
  1030. inc(href.offset,sizeof(pint)*2);
  1031. end
  1032. else
  1033. { normal array constructor of the same type }
  1034. begin
  1035. if resultdef.needs_inittable then
  1036. freetemp:=false;
  1037. case hp.left.location.loc of
  1038. LOC_MMREGISTER,
  1039. LOC_CMMREGISTER:
  1040. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location.size,
  1041. hp.left.location.register,href,mms_movescalar);
  1042. LOC_FPUREGISTER,
  1043. LOC_CFPUREGISTER :
  1044. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location.size,hp.left.location.register,href);
  1045. LOC_REFERENCE,
  1046. LOC_CREFERENCE :
  1047. begin
  1048. if is_shortstring(hp.left.resultdef) then
  1049. cg.g_copyshortstring(current_asmdata.CurrAsmList,hp.left.location.reference,href,
  1050. Tstringdef(hp.left.resultdef).len)
  1051. else
  1052. cg.g_concatcopy(current_asmdata.CurrAsmList,hp.left.location.reference,href,elesize);
  1053. end;
  1054. else
  1055. begin
  1056. {$ifndef cpu64bitalu}
  1057. if hp.left.location.size in [OS_64,OS_S64] then
  1058. cg64.a_load64_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
  1059. else
  1060. {$endif not cpu64bitalu}
  1061. cg.a_load_loc_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location,href);
  1062. end;
  1063. end;
  1064. inc(href.offset,elesize);
  1065. end;
  1066. if freetemp then
  1067. location_freetemp(current_asmdata.CurrAsmList,hp.left.location);
  1068. end;
  1069. { load next entry }
  1070. hp:=tarrayconstructornode(hp.right);
  1071. end;
  1072. end;
  1073. {*****************************************************************************
  1074. SecondRTTI
  1075. *****************************************************************************}
  1076. procedure tcgrttinode.pass_generate_code;
  1077. begin
  1078. location_reset(location,LOC_CREFERENCE,OS_NO);
  1079. case rttidatatype of
  1080. rdt_normal:
  1081. location.reference.symbol:=RTTIWriter.get_rtti_label(rttidef,rttitype);
  1082. rdt_ord2str:
  1083. location.reference.symbol:=RTTIWriter.get_rtti_label_ord2str(rttidef,rttitype);
  1084. rdt_str2ord:
  1085. location.reference.symbol:=RTTIWriter.get_rtti_label_str2ord(rttidef,rttitype);
  1086. end;
  1087. end;
  1088. begin
  1089. cloadnode:=tcgloadnode;
  1090. cassignmentnode:=tcgassignmentnode;
  1091. carrayconstructornode:=tcgarrayconstructornode;
  1092. crttinode:=tcgrttinode;
  1093. end.