ncgld.pas 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169
  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. location.reference.alignment:=gvs.vardef.alignment;
  330. end;
  331. paravarsym,
  332. localvarsym :
  333. begin
  334. vs:=tabstractnormalvarsym(symtableentry);
  335. { Nested variable }
  336. if assigned(left) then
  337. begin
  338. secondpass(left);
  339. if left.location.loc<>LOC_REGISTER then
  340. internalerror(200309286);
  341. if vs.localloc.loc<>LOC_REFERENCE then
  342. internalerror(200409241);
  343. reference_reset_base(location.reference,left.location.register,vs.localloc.reference.offset);
  344. end
  345. else
  346. location:=vs.localloc;
  347. { handle call by reference variables when they are not
  348. alreayd copied to local copies. Also ignore the reference
  349. when we need to load the self pointer for objects }
  350. if is_addr_param_load then
  351. begin
  352. if (location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
  353. hregister:=location.register
  354. else
  355. begin
  356. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  357. { we need to load only an address }
  358. location.size:=OS_ADDR;
  359. cg.a_load_loc_reg(current_asmdata.CurrAsmList,location.size,location,hregister);
  360. end;
  361. location_reset(location,LOC_REFERENCE,newsize);
  362. location.reference.base:=hregister;
  363. end;
  364. { make const a LOC_CREFERENCE }
  365. if (vs.varspez=vs_const) and
  366. (location.loc=LOC_REFERENCE) then
  367. location.loc:=LOC_CREFERENCE;
  368. end;
  369. procsym:
  370. begin
  371. if not assigned(procdef) then
  372. internalerror(200312011);
  373. if assigned(left) then
  374. begin
  375. {$if sizeof(pint) = 4}
  376. location_reset(location,LOC_CREFERENCE,OS_64);
  377. {$else} {$if sizeof(pint) = 8}
  378. location_reset(location,LOC_CREFERENCE,OS_128);
  379. {$else}
  380. internalerror(20020520);
  381. {$endif} {$endif}
  382. tg.GetTemp(current_asmdata.CurrAsmList,2*sizeof(pint),tt_normal,location.reference);
  383. secondpass(left);
  384. { load class instance/classrefdef address }
  385. if left.location.loc=LOC_CONSTANT then
  386. location_force_reg(current_asmdata.CurrAsmList,left.location,OS_ADDR,false);
  387. case left.location.loc of
  388. LOC_CREGISTER,
  389. LOC_REGISTER:
  390. begin
  391. { this is not possible for objects }
  392. if is_object(left.resultdef) then
  393. internalerror(200304234);
  394. hregister:=left.location.register;
  395. end;
  396. LOC_CREFERENCE,
  397. LOC_REFERENCE:
  398. begin
  399. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  400. if not is_object(left.resultdef) then
  401. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.reference,hregister)
  402. else
  403. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,hregister);
  404. location_freetemp(current_asmdata.CurrAsmList,left.location);
  405. end;
  406. else
  407. internalerror(200610311);
  408. end;
  409. { store the class instance or classredef address }
  410. href:=location.reference;
  411. inc(href.offset,sizeof(pint));
  412. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,href);
  413. { virtual method ? }
  414. if (po_virtualmethod in procdef.procoptions) and
  415. not(nf_inherited in flags) then
  416. begin
  417. { a classrefdef already points to the VMT }
  418. if (left.resultdef.typ<>classrefdef) then
  419. begin
  420. { load vmt pointer }
  421. reference_reset_base(href,hregister,0);
  422. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  423. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
  424. end;
  425. { load method address }
  426. reference_reset_base(href,hregister,procdef._class.vmtmethodoffset(procdef.extnumber));
  427. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  428. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
  429. { ... and store it }
  430. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,location.reference);
  431. end
  432. else
  433. begin
  434. { load address of the function }
  435. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(procdef.mangledname),0);
  436. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  437. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,hregister);
  438. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,location.reference);
  439. end;
  440. end
  441. else
  442. begin
  443. pd:=tprocdef(tprocsym(symtableentry).ProcdefList[0]);
  444. if (po_external in pd.procoptions) then
  445. location.reference.base := cg.g_indirect_sym_load(current_asmdata.CurrAsmList,pd.mangledname);
  446. {!!!!! Be aware, work on virtual methods too }
  447. if (location.reference.base = NR_NO) then
  448. location.reference.symbol:=current_asmdata.RefAsmSymbol(procdef.mangledname);
  449. end;
  450. end;
  451. labelsym :
  452. location.reference.symbol:=tcglabelnode((tlabelsym(symtableentry).code)).getasmlabel;
  453. else internalerror(200510032);
  454. end;
  455. end;
  456. {*****************************************************************************
  457. SecondAssignment
  458. *****************************************************************************}
  459. procedure tcgassignmentnode.pass_generate_code;
  460. var
  461. otlabel,hlabel,oflabel : tasmlabel;
  462. href : treference;
  463. releaseright : boolean;
  464. len : aint;
  465. r : tregister;
  466. oldflowcontrol : tflowcontrol;
  467. begin
  468. location_reset(location,LOC_VOID,OS_NO);
  469. otlabel:=current_procinfo.CurrTrueLabel;
  470. oflabel:=current_procinfo.CurrFalseLabel;
  471. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  472. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  473. {
  474. in most cases we can process first the right node which contains
  475. the most complex code. Exceptions for this are:
  476. - result is in flags, loading left will then destroy the flags
  477. - result is a jump, loading left must be already done before the jump is made
  478. - result need reference count, when left points to a value used in
  479. right then decreasing the refcnt on left can possibly release
  480. the memory before right increased the refcnt, result is that an
  481. empty value is assigned
  482. But not when the result is in the flags, then
  483. loading the left node afterwards can destroy the flags.
  484. }
  485. if not(right.expectloc in [LOC_FLAGS,LOC_JUMP]) and
  486. ((right.resultdef.needs_inittable) or
  487. (node_complexity(right)>node_complexity(left))) then
  488. begin
  489. secondpass(right);
  490. { increment source reference counter, this is
  491. useless for constants }
  492. if (right.resultdef.needs_inittable) and
  493. not is_constnode(right) then
  494. begin
  495. location_force_mem(current_asmdata.CurrAsmList,right.location);
  496. location_get_data_ref(current_asmdata.CurrAsmList,right.location,href,false);
  497. cg.g_incrrefcount(current_asmdata.CurrAsmList,right.resultdef,href);
  498. end;
  499. if codegenerror then
  500. exit;
  501. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  502. { can be false }
  503. secondpass(left);
  504. { decrement destination reference counter }
  505. if (left.resultdef.needs_inittable) then
  506. begin
  507. location_get_data_ref(current_asmdata.CurrAsmList,left.location,href,false);
  508. cg.g_decrrefcount(current_asmdata.CurrAsmList,left.resultdef,href);
  509. end;
  510. if codegenerror then
  511. exit;
  512. end
  513. else
  514. begin
  515. { calculate left sides }
  516. secondpass(left);
  517. { decrement destination reference counter }
  518. if (left.resultdef.needs_inittable) then
  519. begin
  520. location_get_data_ref(current_asmdata.CurrAsmList,left.location,href,false);
  521. cg.g_decrrefcount(current_asmdata.CurrAsmList,left.resultdef,href);
  522. end;
  523. if codegenerror then
  524. exit;
  525. { tell the SSA/SSL code that the left side was handled first so
  526. ni SSL is done
  527. }
  528. oldflowcontrol:=flowcontrol;
  529. include(flowcontrol,fc_lefthandled);
  530. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  531. { can be false }
  532. secondpass(right);
  533. flowcontrol:=oldflowcontrol;
  534. { increment source reference counter, this is
  535. useless for string constants}
  536. if (right.resultdef.needs_inittable) and
  537. (right.nodetype<>stringconstn) then
  538. begin
  539. location_force_mem(current_asmdata.CurrAsmList,right.location);
  540. location_get_data_ref(current_asmdata.CurrAsmList,right.location,href,false);
  541. cg.g_incrrefcount(current_asmdata.CurrAsmList,right.resultdef,href);
  542. end;
  543. if codegenerror then
  544. exit;
  545. end;
  546. releaseright:=true;
  547. { shortstring assignments are handled separately }
  548. if is_shortstring(left.resultdef) then
  549. begin
  550. {
  551. we can get here only in the following situations
  552. for the right node:
  553. - empty constant string
  554. - char
  555. }
  556. { The addn is replaced by a blockn or calln that already returns
  557. a shortstring }
  558. if is_shortstring(right.resultdef) and
  559. (right.nodetype in [blockn,calln]) then
  560. begin
  561. { nothing to do }
  562. end
  563. { empty constant string }
  564. else if (right.nodetype=stringconstn) and
  565. (tstringconstnode(right).len=0) then
  566. begin
  567. cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_8,0,left.location.reference);
  568. end
  569. { char loading }
  570. else if is_char(right.resultdef) then
  571. begin
  572. if right.nodetype=ordconstn then
  573. begin
  574. if (target_info.endian = endian_little) then
  575. cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_16,(tordconstnode(right).value.svalue shl 8) or 1,
  576. setalignment(left.location.reference,1))
  577. else
  578. cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_16,tordconstnode(right).value.svalue or (1 shl 8),
  579. setalignment(left.location.reference,1));
  580. end
  581. else
  582. begin
  583. href:=left.location.reference;
  584. cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_8,1,href);
  585. inc(href.offset,1);
  586. case right.location.loc of
  587. LOC_REGISTER,
  588. LOC_CREGISTER :
  589. begin
  590. r:=cg.makeregsize(current_asmdata.CurrAsmList,right.location.register,OS_8);
  591. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_8,OS_8,r,href);
  592. end;
  593. LOC_REFERENCE,
  594. LOC_CREFERENCE :
  595. cg.a_load_ref_ref(current_asmdata.CurrAsmList,OS_8,OS_8,right.location.reference,href);
  596. else
  597. internalerror(200205111);
  598. end;
  599. end;
  600. end
  601. else
  602. internalerror(200204249);
  603. end
  604. { try to reuse memory locations instead of copying }
  605. { copy to a memory location ... }
  606. else if (right.location.loc = LOC_REFERENCE) and
  607. maybechangetemp(current_asmdata.CurrAsmList,left,right.location.reference) then
  608. begin
  609. { if it worked, we're done }
  610. end
  611. else
  612. begin
  613. { SSA support }
  614. maybechangeloadnodereg(current_asmdata.CurrAsmList,left,false);
  615. maybechangeloadnodereg(current_asmdata.CurrAsmList,right,true);
  616. case right.location.loc of
  617. LOC_CONSTANT :
  618. begin
  619. {$ifndef cpu64bitalu}
  620. if (left.location.size in [OS_64,OS_S64]) or (right.location.size in [OS_64,OS_S64]) then
  621. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,right.location.value64,left.location)
  622. else
  623. {$endif not cpu64bitalu}
  624. cg.a_load_const_loc(current_asmdata.CurrAsmList,right.location.value,left.location);
  625. end;
  626. LOC_REFERENCE,
  627. LOC_CREFERENCE :
  628. begin
  629. case left.location.loc of
  630. LOC_REGISTER,
  631. LOC_CREGISTER :
  632. begin
  633. {$ifndef cpu64bitalu}
  634. if left.location.size in [OS_64,OS_S64] then
  635. cg64.a_load64_ref_reg(current_asmdata.CurrAsmList,right.location.reference,left.location.register64)
  636. else
  637. {$endif not cpu64bitalu}
  638. cg.a_load_ref_reg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.register);
  639. end;
  640. LOC_FPUREGISTER,
  641. LOC_CFPUREGISTER :
  642. begin
  643. cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
  644. right.location.size,left.location.size,
  645. right.location.reference,
  646. left.location.register);
  647. end;
  648. LOC_REFERENCE,
  649. LOC_CREFERENCE :
  650. begin
  651. if (left.resultdef.typ=floatdef) and
  652. (right.resultdef.typ=floatdef) and
  653. (left.location.size<>right.location.size) then
  654. begin
  655. cg.a_loadfpu_ref_ref(current_asmdata.CurrAsmList,
  656. right.location.size,left.location.size,
  657. right.location.reference,left.location.reference)
  658. end
  659. else
  660. begin
  661. {$warning HACK: unaligned test, maybe remove all unaligned locations (array of char) from the compiler}
  662. { Use unaligned copy when the offset is not aligned }
  663. len:=left.resultdef.size;
  664. if (right.location.reference.offset mod sizeof(aint)<>0) or
  665. (left.location.reference.offset mod sizeof(aint)<>0) or
  666. (right.resultdef.alignment<sizeof(aint)) or
  667. ((right.location.reference.alignment<>0) and
  668. (right.location.reference.alignment<sizeof(aint))) or
  669. ((left.location.reference.alignment<>0) and
  670. (left.location.reference.alignment<sizeof(aint))) then
  671. cg.g_concatcopy_unaligned(current_asmdata.CurrAsmList,right.location.reference,left.location.reference,len)
  672. else
  673. cg.g_concatcopy(current_asmdata.CurrAsmList,right.location.reference,left.location.reference,len);
  674. end;
  675. end;
  676. LOC_MMREGISTER,
  677. LOC_CMMREGISTER:
  678. begin
  679. {$ifdef x86}
  680. if not use_sse(right.resultdef) then
  681. begin
  682. { perform size conversion if needed (the mm-code cannot }
  683. { convert an extended into a double/single, since sse }
  684. { doesn't support extended) }
  685. r:=cg.getfpuregister(current_asmdata.CurrAsmList,right.location.size);
  686. tg.gettemp(current_asmdata.CurrAsmList,left.resultdef.size,tt_normal,href);
  687. cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,right.location.size,right.location.size,right.location.reference,r);
  688. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,r,href);
  689. if releaseright then
  690. location_freetemp(current_asmdata.CurrAsmList,right.location);
  691. releaseright:=true;
  692. location_reset(right.location,LOC_REFERENCE,left.location.size);
  693. right.location.reference:=href;
  694. end;
  695. {$endif}
  696. cg.a_loadmm_ref_reg(current_asmdata.CurrAsmList,
  697. right.location.size,
  698. left.location.size,
  699. right.location.reference,
  700. left.location.register,mms_movescalar);
  701. end;
  702. LOC_SUBSETREG,
  703. LOC_CSUBSETREG:
  704. cg.a_load_ref_subsetreg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.sreg);
  705. LOC_SUBSETREF,
  706. LOC_CSUBSETREF:
  707. {$ifndef cpu64bitalu}
  708. if right.location.size in [OS_64,OS_S64] then
  709. cg64.a_load64_ref_subsetref(current_asmdata.CurrAsmList,right.location.reference,left.location.sref)
  710. else
  711. {$endif not cpu64bitalu}
  712. cg.a_load_ref_subsetref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.sref);
  713. else
  714. internalerror(200203284);
  715. end;
  716. end;
  717. {$ifdef SUPPORT_MMX}
  718. LOC_CMMXREGISTER,
  719. LOC_MMXREGISTER:
  720. begin
  721. if left.location.loc=LOC_CMMXREGISTER then
  722. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.register,nil)
  723. else
  724. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.reference,nil);
  725. end;
  726. {$endif SUPPORT_MMX}
  727. LOC_MMREGISTER,
  728. LOC_CMMREGISTER:
  729. begin
  730. if left.resultdef.typ=arraydef then
  731. begin
  732. end
  733. else
  734. begin
  735. if left.location.loc=LOC_CMMREGISTER then
  736. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,left.location.register,mms_movescalar)
  737. else
  738. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,left.location.reference,mms_movescalar);
  739. end;
  740. end;
  741. LOC_REGISTER,
  742. LOC_CREGISTER :
  743. begin
  744. {$ifndef cpu64bitalu}
  745. if left.location.size in [OS_64,OS_S64] then
  746. cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,
  747. right.location.register64,left.location)
  748. else
  749. {$endif not cpu64bitalu}
  750. cg.a_load_reg_loc(current_asmdata.CurrAsmList,right.location.size,right.location.register,left.location);
  751. end;
  752. LOC_FPUREGISTER,
  753. LOC_CFPUREGISTER :
  754. begin
  755. { we can't do direct moves between fpu and mm registers }
  756. if left.location.loc in [LOC_MMREGISTER,LOC_CMMREGISTER] then
  757. begin
  758. {$ifdef x86}
  759. if not use_sse(right.resultdef) then
  760. begin
  761. { perform size conversion if needed (the mm-code cannot convert an }
  762. { extended into a double/single, since sse doesn't support extended) }
  763. tg.gettemp(current_asmdata.CurrAsmList,left.resultdef.size,tt_normal,href);
  764. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,href);
  765. location_reset(right.location,LOC_REFERENCE,left.location.size);
  766. right.location.reference:=href;
  767. end;
  768. {$endif}
  769. location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,false);
  770. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,
  771. right.location.size,left.location.size,
  772. right.location.register,left.location.register,mms_movescalar);
  773. end
  774. else
  775. cg.a_loadfpu_reg_loc(current_asmdata.CurrAsmList,
  776. right.location.size,
  777. right.location.register,left.location);
  778. end;
  779. LOC_SUBSETREG,
  780. LOC_CSUBSETREG:
  781. begin
  782. cg.a_load_subsetreg_loc(current_asmdata.CurrAsmList,
  783. right.location.size,right.location.sreg,left.location);
  784. end;
  785. LOC_SUBSETREF,
  786. LOC_CSUBSETREF:
  787. begin
  788. {$ifndef cpu64bitalu}
  789. if right.location.size in [OS_64,OS_S64] then
  790. cg64.a_load64_subsetref_loc(current_asmdata.CurrAsmList,right.location.sref,left.location)
  791. else
  792. {$endif not cpu64bitalu}
  793. cg.a_load_subsetref_loc(current_asmdata.CurrAsmList,
  794. right.location.size,right.location.sref,left.location);
  795. end;
  796. LOC_JUMP :
  797. begin
  798. current_asmdata.getjumplabel(hlabel);
  799. cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
  800. if is_pasbool(left.resultdef) then
  801. cg.a_load_const_loc(current_asmdata.CurrAsmList,1,left.location)
  802. else
  803. cg.a_load_const_loc(current_asmdata.CurrAsmList,-1,left.location);
  804. cg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
  805. cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
  806. cg.a_load_const_loc(current_asmdata.CurrAsmList,0,left.location);
  807. cg.a_label(current_asmdata.CurrAsmList,hlabel);
  808. end;
  809. {$ifdef cpuflags}
  810. LOC_FLAGS :
  811. begin
  812. if is_pasbool(left.resultdef) then
  813. begin
  814. case left.location.loc of
  815. LOC_REGISTER,LOC_CREGISTER:
  816. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.register);
  817. LOC_REFERENCE:
  818. cg.g_flags2ref(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.reference);
  819. LOC_SUBSETREG,LOC_SUBSETREF:
  820. begin
  821. r:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
  822. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,r);
  823. cg.a_load_reg_loc(current_asmdata.CurrAsmList,left.location.size,r,left.location);
  824. end;
  825. else
  826. internalerror(200203273);
  827. end;
  828. end
  829. else
  830. begin
  831. r:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
  832. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,r);
  833. cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,left.location.size,r,r);
  834. cg.a_load_reg_loc(current_asmdata.CurrAsmList,left.location.size,r,left.location);
  835. end;
  836. end;
  837. {$endif cpuflags}
  838. end;
  839. end;
  840. if releaseright then
  841. location_freetemp(current_asmdata.CurrAsmList,right.location);
  842. current_procinfo.CurrTrueLabel:=otlabel;
  843. current_procinfo.CurrFalseLabel:=oflabel;
  844. end;
  845. {*****************************************************************************
  846. SecondArrayConstruct
  847. *****************************************************************************}
  848. const
  849. vtInteger = 0;
  850. vtBoolean = 1;
  851. vtChar = 2;
  852. vtExtended = 3;
  853. vtString = 4;
  854. vtPointer = 5;
  855. vtPChar = 6;
  856. vtObject = 7;
  857. vtClass = 8;
  858. vtWideChar = 9;
  859. vtPWideChar = 10;
  860. vtAnsiString32 = 11;
  861. vtCurrency = 12;
  862. vtVariant = 13;
  863. vtInterface = 14;
  864. vtWideString = 15;
  865. vtInt64 = 16;
  866. vtQWord = 17;
  867. vtAnsiString16 = 18;
  868. vtAnsiString64 = 19;
  869. procedure tcgarrayconstructornode.pass_generate_code;
  870. var
  871. hp : tarrayconstructornode;
  872. href : treference;
  873. lt : tdef;
  874. vaddr : boolean;
  875. vtype : longint;
  876. freetemp,
  877. dovariant : boolean;
  878. elesize : longint;
  879. tmpreg : tregister;
  880. paraloc : tcgparalocation;
  881. otlabel,
  882. oflabel : tasmlabel;
  883. begin
  884. if is_packed_array(resultdef) then
  885. internalerror(200608042);
  886. dovariant:=(nf_forcevaria in flags) or is_variant_array(resultdef);
  887. if dovariant then
  888. elesize:=sizeof(pint)+sizeof(pint)
  889. else
  890. elesize:=tarraydef(resultdef).elesize;
  891. location_reset(location,LOC_CREFERENCE,OS_NO);
  892. fillchar(paraloc,sizeof(paraloc),0);
  893. { Allocate always a temp, also if no elements are required, to
  894. be sure that location is valid (PFV) }
  895. if tarraydef(resultdef).highrange=-1 then
  896. tg.GetTemp(current_asmdata.CurrAsmList,elesize,tt_normal,location.reference)
  897. else
  898. tg.GetTemp(current_asmdata.CurrAsmList,(tarraydef(resultdef).highrange+1)*elesize,tt_normal,location.reference);
  899. href:=location.reference;
  900. { Process nodes in array constructor }
  901. hp:=self;
  902. while assigned(hp) do
  903. begin
  904. if assigned(hp.left) then
  905. begin
  906. freetemp:=true;
  907. if (hp.left.expectloc=LOC_JUMP) then
  908. begin
  909. otlabel:=current_procinfo.CurrTrueLabel;
  910. oflabel:=current_procinfo.CurrFalseLabel;
  911. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  912. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  913. end;
  914. secondpass(hp.left);
  915. { Move flags and jump in register }
  916. if hp.left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  917. location_force_reg(current_asmdata.CurrAsmList,hp.left.location,def_cgsize(hp.left.resultdef),false);
  918. if (hp.left.location.loc=LOC_JUMP) then
  919. begin
  920. if (hp.left.expectloc<>LOC_JUMP) then
  921. internalerror(2007103101);
  922. current_procinfo.CurrTrueLabel:=otlabel;
  923. current_procinfo.CurrFalseLabel:=oflabel;
  924. end;
  925. if dovariant then
  926. begin
  927. { find the correct vtype value }
  928. vtype:=$ff;
  929. vaddr:=false;
  930. lt:=hp.left.resultdef;
  931. case lt.typ of
  932. enumdef,
  933. orddef :
  934. begin
  935. if is_64bit(lt) then
  936. begin
  937. case torddef(lt).ordtype of
  938. scurrency:
  939. vtype:=vtCurrency;
  940. s64bit:
  941. vtype:=vtInt64;
  942. u64bit:
  943. vtype:=vtQWord;
  944. end;
  945. freetemp:=false;
  946. vaddr:=true;
  947. end
  948. else if (lt.typ=enumdef) or
  949. is_integer(lt) then
  950. vtype:=vtInteger
  951. else
  952. if is_boolean(lt) then
  953. vtype:=vtBoolean
  954. else
  955. if (lt.typ=orddef) then
  956. begin
  957. case torddef(lt).ordtype of
  958. uchar:
  959. vtype:=vtChar;
  960. uwidechar:
  961. vtype:=vtWideChar;
  962. end;
  963. end;
  964. end;
  965. floatdef :
  966. begin
  967. if is_currency(lt) then
  968. vtype:=vtCurrency
  969. else
  970. vtype:=vtExtended;
  971. freetemp:=false;
  972. vaddr:=true;
  973. end;
  974. procvardef,
  975. pointerdef :
  976. begin
  977. if is_pchar(lt) then
  978. vtype:=vtPChar
  979. else if is_pwidechar(lt) then
  980. vtype:=vtPWideChar
  981. else
  982. vtype:=vtPointer;
  983. end;
  984. variantdef :
  985. begin
  986. vtype:=vtVariant;
  987. vaddr:=true;
  988. freetemp:=false;
  989. end;
  990. classrefdef :
  991. vtype:=vtClass;
  992. objectdef :
  993. if is_interface(lt) then
  994. vtype:=vtInterface
  995. { vtObject really means a class based on TObject }
  996. else if is_class(lt) then
  997. vtype:=vtObject
  998. else
  999. internalerror(200505171);
  1000. stringdef :
  1001. begin
  1002. if is_shortstring(lt) then
  1003. begin
  1004. vtype:=vtString;
  1005. vaddr:=true;
  1006. freetemp:=false;
  1007. end
  1008. else
  1009. if is_ansistring(lt) then
  1010. begin
  1011. vtype:=vtAnsiString;
  1012. freetemp:=false;
  1013. end
  1014. else
  1015. if is_widestring(lt) then
  1016. begin
  1017. vtype:=vtWideString;
  1018. freetemp:=false;
  1019. end;
  1020. end;
  1021. end;
  1022. if vtype=$ff then
  1023. internalerror(14357);
  1024. { write changing field update href to the next element }
  1025. inc(href.offset,sizeof(pint));
  1026. if vaddr then
  1027. begin
  1028. location_force_mem(current_asmdata.CurrAsmList,hp.left.location);
  1029. tmpreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
  1030. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,hp.left.location.reference,tmpreg);
  1031. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,tmpreg,href);
  1032. end
  1033. else
  1034. cg.a_load_loc_ref(current_asmdata.CurrAsmList,OS_ADDR,hp.left.location,href);
  1035. { update href to the vtype field and write it }
  1036. dec(href.offset,sizeof(pint));
  1037. cg.a_load_const_ref(current_asmdata.CurrAsmList, OS_INT,vtype,href);
  1038. { goto next array element }
  1039. inc(href.offset,sizeof(pint)*2);
  1040. end
  1041. else
  1042. { normal array constructor of the same type }
  1043. begin
  1044. if resultdef.needs_inittable then
  1045. freetemp:=false;
  1046. case hp.left.location.loc of
  1047. LOC_MMREGISTER,
  1048. LOC_CMMREGISTER:
  1049. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location.size,
  1050. hp.left.location.register,href,mms_movescalar);
  1051. LOC_FPUREGISTER,
  1052. LOC_CFPUREGISTER :
  1053. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location.size,hp.left.location.register,href);
  1054. LOC_REFERENCE,
  1055. LOC_CREFERENCE :
  1056. begin
  1057. if is_shortstring(hp.left.resultdef) then
  1058. cg.g_copyshortstring(current_asmdata.CurrAsmList,hp.left.location.reference,href,
  1059. Tstringdef(hp.left.resultdef).len)
  1060. else
  1061. cg.g_concatcopy(current_asmdata.CurrAsmList,hp.left.location.reference,href,elesize);
  1062. end;
  1063. else
  1064. begin
  1065. {$ifndef cpu64bitalu}
  1066. if hp.left.location.size in [OS_64,OS_S64] then
  1067. cg64.a_load64_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
  1068. else
  1069. {$endif not cpu64bitalu}
  1070. cg.a_load_loc_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location,href);
  1071. end;
  1072. end;
  1073. inc(href.offset,elesize);
  1074. end;
  1075. if freetemp then
  1076. location_freetemp(current_asmdata.CurrAsmList,hp.left.location);
  1077. end;
  1078. { load next entry }
  1079. hp:=tarrayconstructornode(hp.right);
  1080. end;
  1081. end;
  1082. {*****************************************************************************
  1083. SecondRTTI
  1084. *****************************************************************************}
  1085. procedure tcgrttinode.pass_generate_code;
  1086. begin
  1087. location_reset(location,LOC_CREFERENCE,OS_NO);
  1088. case rttidatatype of
  1089. rdt_normal:
  1090. location.reference.symbol:=RTTIWriter.get_rtti_label(rttidef,rttitype);
  1091. rdt_ord2str:
  1092. location.reference.symbol:=RTTIWriter.get_rtti_label_ord2str(rttidef,rttitype);
  1093. rdt_str2ord:
  1094. location.reference.symbol:=RTTIWriter.get_rtti_label_str2ord(rttidef,rttitype);
  1095. end;
  1096. end;
  1097. begin
  1098. cloadnode:=tcgloadnode;
  1099. cassignmentnode:=tcgassignmentnode;
  1100. carrayconstructornode:=tcgarrayconstructornode;
  1101. crttinode:=tcgrttinode;
  1102. end.