ncgld.pas 60 KB

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