ncgld.pas 57 KB

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