ncgld.pas 54 KB

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