ncgld.pas 57 KB

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