ncgld.pas 55 KB

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