ncgld.pas 62 KB

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