ncgld.pas 64 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367
  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. pvd : tdef;
  235. begin
  236. { we don't know the size of all arrays }
  237. newsize:=def_cgsize(resultdef);
  238. { alignment is overridden per case below }
  239. location_reset_ref(location,LOC_REFERENCE,newsize,resultdef.alignment);
  240. case symtableentry.typ of
  241. absolutevarsym :
  242. begin
  243. { this is only for toasm and toaddr }
  244. case tabsolutevarsym(symtableentry).abstyp of
  245. toaddr :
  246. begin
  247. {$ifdef i386}
  248. if tabsolutevarsym(symtableentry).absseg then
  249. location.reference.segment:=NR_FS;
  250. {$endif i386}
  251. location.reference.offset:=aint(tabsolutevarsym(symtableentry).addroffset);
  252. end;
  253. toasm :
  254. location.reference.symbol:=current_asmdata.RefAsmSymbol(tabsolutevarsym(symtableentry).mangledname);
  255. else
  256. internalerror(200310283);
  257. end;
  258. end;
  259. constsym:
  260. begin
  261. if tconstsym(symtableentry).consttyp=constresourcestring then
  262. begin
  263. location_reset_ref(location,LOC_CREFERENCE,OS_ADDR,sizeof(pint));
  264. location.reference.symbol:=current_asmdata.RefAsmSymbol(make_mangledname('RESSTR',symtableentry.owner,symtableentry.name));
  265. { Resourcestring layout:
  266. TResourceStringRecord = Packed Record
  267. Name,
  268. CurrentValue,
  269. DefaultValue : AnsiString;
  270. HashValue : LongWord;
  271. end;
  272. }
  273. location.reference.offset:=sizeof(pint);
  274. end
  275. else
  276. internalerror(22798);
  277. end;
  278. staticvarsym :
  279. begin
  280. gvs:=tstaticvarsym(symtableentry);
  281. if (vo_is_dll_var in gvs.varoptions) then
  282. { DLL variable }
  283. begin
  284. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  285. if not(vo_is_weak_external in gvs.varoptions) then
  286. location.reference.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname)
  287. else
  288. location.reference.symbol:=current_asmdata.WeakRefAsmSymbol(tstaticvarsym(symtableentry).mangledname);
  289. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,location.reference,hregister);
  290. reference_reset_base(location.reference,hregister,0,location.reference.alignment);
  291. end
  292. { Thread variable }
  293. else if (vo_is_thread_var in gvs.varoptions) then
  294. begin
  295. if (tf_section_threadvars in target_info.flags) then
  296. begin
  297. if target_info.system in [system_i386_win32,system_x86_64_win64] then
  298. begin
  299. paraloc1.init;
  300. pd:=search_system_proc('fpc_tls_add');
  301. paramanager.getintparaloc(pd,1,paraloc1);
  302. if not(vo_is_weak_external in gvs.varoptions) then
  303. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname),0,sizeof(pint))
  304. else
  305. reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0,sizeof(pint));
  306. cg.a_loadaddr_ref_cgpara(current_asmdata.CurrAsmList,href,paraloc1);
  307. paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
  308. paraloc1.done;
  309. cg.g_call(current_asmdata.CurrAsmList,'FPC_TLS_ADD');
  310. cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
  311. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  312. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,NR_FUNCTION_RESULT_REG,hregister);
  313. location.reference.base:=hregister;
  314. end
  315. else
  316. begin
  317. if gvs.localloc.loc=LOC_INVALID then
  318. if not(vo_is_weak_external in gvs.varoptions) then
  319. reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname),0,location.reference.alignment)
  320. else
  321. reference_reset_symbol(location.reference,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0,location.reference.alignment)
  322. else
  323. location:=gvs.localloc;
  324. {$ifdef i386}
  325. case target_info.system of
  326. system_i386_linux,system_i386_android:
  327. location.reference.segment:=NR_GS;
  328. end;
  329. {$endif i386}
  330. end;
  331. end
  332. else
  333. begin
  334. {
  335. Thread var loading is optimized to first check if
  336. a relocate function is available. When the function
  337. is available it is called to retrieve the address.
  338. Otherwise the address is loaded with the symbol
  339. The code needs to be in the order to first handle the
  340. call and then the address load to be sure that the
  341. register that is used for returning is the same (PFV)
  342. }
  343. current_asmdata.getjumplabel(norelocatelab);
  344. current_asmdata.getjumplabel(endrelocatelab);
  345. { make sure hregister can't allocate the register necessary for the parameter }
  346. pvd:=search_system_type('TRELOCATETHREADVARHANDLER').typedef;
  347. if pvd.typ<>procvardef then
  348. internalerror(2012120901);
  349. paraloc1.init;
  350. paramanager.getintparaloc(tprocvardef(pvd),1,paraloc1);
  351. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  352. reference_reset_symbol(href,current_asmdata.RefAsmSymbol('FPC_THREADVAR_RELOCATE'),0,sizeof(pint));
  353. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
  354. cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_ADDR,OC_EQ,0,hregister,norelocatelab);
  355. { don't save the allocated register else the result will be destroyed later }
  356. if not(vo_is_weak_external in gvs.varoptions) then
  357. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname),0,sizeof(pint))
  358. else
  359. reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0,sizeof(pint));
  360. cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
  361. paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
  362. paraloc1.done;
  363. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  364. cg.a_call_reg(current_asmdata.CurrAsmList,hregister);
  365. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  366. cg.getcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
  367. cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
  368. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  369. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_ADDR,NR_FUNCTION_RESULT_REG,hregister);
  370. cg.a_jmp_always(current_asmdata.CurrAsmList,endrelocatelab);
  371. cg.a_label(current_asmdata.CurrAsmList,norelocatelab);
  372. { no relocation needed, load the address of the variable only, the
  373. layout of a threadvar is (4 bytes pointer):
  374. 0 - Threadvar index
  375. 4 - Threadvar value in single threading }
  376. if not(vo_is_weak_external in gvs.varoptions) then
  377. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname),sizeof(pint),sizeof(pint))
  378. else
  379. reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),sizeof(pint),sizeof(pint));
  380. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,hregister);
  381. cg.a_label(current_asmdata.CurrAsmList,endrelocatelab);
  382. location.reference.base:=hregister;
  383. end;
  384. end
  385. { Normal (or external) variable }
  386. else
  387. begin
  388. if gvs.localloc.loc=LOC_INVALID then
  389. if not(vo_is_weak_external in gvs.varoptions) then
  390. reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname),0,location.reference.alignment)
  391. else
  392. reference_reset_symbol(location.reference,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0,location.reference.alignment)
  393. else
  394. location:=gvs.localloc;
  395. end;
  396. { make const a LOC_CREFERENCE }
  397. if (gvs.varspez=vs_const) and
  398. (location.loc=LOC_REFERENCE) then
  399. location.loc:=LOC_CREFERENCE;
  400. end;
  401. paravarsym,
  402. localvarsym :
  403. begin
  404. vs:=tabstractnormalvarsym(symtableentry);
  405. { Nested variable }
  406. if assigned(left) then
  407. generate_nested_access(vs)
  408. else
  409. location:=vs.localloc;
  410. { handle call by reference variables when they are not
  411. already copied to local copies. Also ignore the reference
  412. when we need to load the self pointer for objects }
  413. if is_addr_param_load then
  414. begin
  415. if (location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
  416. hregister:=location.register
  417. else
  418. begin
  419. hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,voidpointertype);
  420. { we need to load only an address }
  421. location.size:=OS_ADDR;
  422. hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,voidpointertype,voidpointertype,location,hregister);
  423. end;
  424. { assume packed records may always be unaligned }
  425. if not(resultdef.typ in [recorddef,objectdef]) or
  426. (tabstractrecordsymtable(tabstractrecorddef(resultdef).symtable).usefieldalignment<>1) then
  427. location_reset_ref(location,LOC_REFERENCE,newsize,resultdef.alignment)
  428. else
  429. location_reset_ref(location,LOC_REFERENCE,newsize,1);
  430. location.reference.base:=hregister;
  431. end;
  432. { make const a LOC_CREFERENCE }
  433. if (vs.varspez=vs_const) and
  434. (location.loc=LOC_REFERENCE) then
  435. location.loc:=LOC_CREFERENCE;
  436. end;
  437. procsym:
  438. begin
  439. if not assigned(procdef) then
  440. internalerror(200312011);
  441. if assigned(left) then
  442. begin
  443. {$if sizeof(pint) = 4}
  444. location_reset(location,LOC_CREGISTER,OS_64);
  445. {$else} {$if sizeof(pint) = 8}
  446. location_reset(location,LOC_CREGISTER,OS_128);
  447. {$else}
  448. internalerror(20020520);
  449. {$endif} {$endif}
  450. secondpass(left);
  451. { load class instance/classrefdef address }
  452. if left.location.loc=LOC_CONSTANT then
  453. { todo: exact type for hlcg (can't use left.resultdef, because can be TP-style object, which is not pointer-sized) }
  454. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,voidpointertype,false);
  455. case left.location.loc of
  456. LOC_CREGISTER,
  457. LOC_REGISTER:
  458. begin
  459. { this is not possible for objects }
  460. if is_object(left.resultdef) then
  461. internalerror(200304234);
  462. location.registerhi:=left.location.register;
  463. end;
  464. LOC_CREFERENCE,
  465. LOC_REFERENCE:
  466. begin
  467. location.registerhi:=cg.getaddressregister(current_asmdata.CurrAsmList);
  468. if not is_object(left.resultdef) then
  469. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.reference,location.registerhi)
  470. else
  471. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,location.registerhi);
  472. location_freetemp(current_asmdata.CurrAsmList,left.location);
  473. end;
  474. else
  475. internalerror(200610311);
  476. end;
  477. { virtual method ? }
  478. if (po_virtualmethod in procdef.procoptions) and
  479. not(loadnf_inherited in loadnodeflags) 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,location.registerhi,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. else
  501. hregister:=location.registerhi;
  502. { load method address }
  503. reference_reset_base(href,hregister,tobjectdef(procdef.struct).vmtmethodoffset(procdef.extnumber),sizeof(pint));
  504. location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
  505. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,location.register);
  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. location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
  512. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,location.register);
  513. end;
  514. { to get methodpointers stored correctly, code and self register must be swapped on
  515. big endian targets }
  516. if target_info.endian=endian_big then
  517. begin
  518. hregister:=location.register;
  519. location.register:=location.registerhi;
  520. location.registerhi:=hregister;
  521. end;
  522. end
  523. else
  524. begin
  525. { def_cgsize does not work for procdef }
  526. location.size:=OS_ADDR;
  527. pd:=tprocdef(tprocsym(symtableentry).ProcdefList[0]);
  528. if not(po_weakexternal in pd.procoptions) then
  529. location.reference.symbol:=current_asmdata.RefAsmSymbol(procdef.mangledname)
  530. else
  531. location.reference.symbol:=current_asmdata.WeakRefAsmSymbol(procdef.mangledname);
  532. end;
  533. end;
  534. labelsym :
  535. if assigned(tlabelsym(symtableentry).asmblocklabel) then
  536. location.reference.symbol:=tlabelsym(symtableentry).asmblocklabel
  537. else
  538. location.reference.symbol:=tcglabelnode((tlabelsym(symtableentry).code)).getasmlabel;
  539. else internalerror(200510032);
  540. end;
  541. end;
  542. {*****************************************************************************
  543. SecondAssignment
  544. *****************************************************************************}
  545. procedure tcgassignmentnode.pass_generate_code;
  546. var
  547. otlabel,hlabel,oflabel : tasmlabel;
  548. href : treference;
  549. releaseright : boolean;
  550. alignmentrequirement,
  551. len : aint;
  552. r : tregister;
  553. r64 : tregister64;
  554. oldflowcontrol : tflowcontrol;
  555. begin
  556. location_reset(location,LOC_VOID,OS_NO);
  557. { managed types should be handled in firstpass }
  558. if not(target_info.system in systems_garbage_collected_managed_types) and
  559. (is_managed_type(left.resultdef) or
  560. is_managed_type(right.resultdef)) then
  561. InternalError(2012011901);
  562. otlabel:=current_procinfo.CurrTrueLabel;
  563. oflabel:=current_procinfo.CurrFalseLabel;
  564. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  565. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  566. {
  567. in most cases we can process first the right node which contains
  568. the most complex code. Exceptions for this are:
  569. - result is in flags, loading left will then destroy the flags
  570. - result is a jump, loading left must be already done before the jump is made
  571. - result need reference count, when left points to a value used in
  572. right then decreasing the refcnt on left can possibly release
  573. the memory before right increased the refcnt, result is that an
  574. empty value is assigned
  575. But not when the result is in the flags, then
  576. loading the left node afterwards can destroy the flags.
  577. }
  578. if not(right.expectloc in [LOC_FLAGS,LOC_JUMP]) and
  579. (node_complexity(right)>node_complexity(left)) then
  580. begin
  581. secondpass(right);
  582. if codegenerror then
  583. exit;
  584. secondpass(left);
  585. if codegenerror then
  586. exit;
  587. end
  588. else
  589. begin
  590. { calculate left sides }
  591. secondpass(left);
  592. if codegenerror then
  593. exit;
  594. { tell the SSA/SSL code that the left side was handled first so
  595. ni SSL is done
  596. }
  597. oldflowcontrol:=flowcontrol;
  598. include(flowcontrol,fc_lefthandled);
  599. secondpass(right);
  600. flowcontrol:=oldflowcontrol;
  601. if codegenerror then
  602. exit;
  603. end;
  604. releaseright:=true;
  605. { shortstring assignments are handled separately }
  606. if is_shortstring(left.resultdef) then
  607. begin
  608. {
  609. we can get here only in the following situations
  610. for the right node:
  611. - empty constant string
  612. - char
  613. }
  614. { The addn is replaced by a blockn or calln that already returns
  615. a shortstring }
  616. if is_shortstring(right.resultdef) and
  617. (right.nodetype in [blockn,calln]) then
  618. begin
  619. { nothing to do }
  620. end
  621. { empty constant string }
  622. else if (right.nodetype=stringconstn) and
  623. (tstringconstnode(right).len=0) then
  624. begin
  625. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,u8inttype,0,left.location.reference);
  626. end
  627. { char loading }
  628. else if is_char(right.resultdef) then
  629. begin
  630. if right.nodetype=ordconstn then
  631. begin
  632. if (target_info.endian = endian_little) then
  633. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,u16inttype,(tordconstnode(right).value.svalue shl 8) or 1,
  634. setalignment(left.location.reference,1))
  635. else
  636. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,u16inttype,tordconstnode(right).value.svalue or (1 shl 8),
  637. setalignment(left.location.reference,1));
  638. end
  639. else
  640. begin
  641. href:=left.location.reference;
  642. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,u8inttype,1,href);
  643. inc(href.offset,1);
  644. case right.location.loc of
  645. LOC_REGISTER,
  646. LOC_CREGISTER :
  647. begin
  648. {$ifndef cpuhighleveltarget}
  649. r:=cg.makeregsize(current_asmdata.CurrAsmList,right.location.register,OS_8);
  650. {$else not cpuhighleveltarget}
  651. r:=hlcg.getintregister(current_asmdata.CurrAsmList,u8inttype);
  652. hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,u8inttype,u8inttype,right.location.register,r);
  653. {$endif cpuhighleveltarget}
  654. hlcg.a_load_reg_ref(current_asmdata.CurrAsmList,u8inttype,u8inttype,r,href);
  655. end;
  656. LOC_REFERENCE,
  657. LOC_CREFERENCE :
  658. hlcg.a_load_ref_ref(current_asmdata.CurrAsmList,u8inttype,u8inttype,right.location.reference,href);
  659. else
  660. internalerror(200205111);
  661. end;
  662. end;
  663. end
  664. else
  665. internalerror(2002042410);
  666. end
  667. { try to reuse memory locations instead of copying }
  668. { copy to a memory location ... }
  669. else if (right.location.loc = LOC_REFERENCE) and
  670. maybechangetemp(current_asmdata.CurrAsmList,left,right.location.reference) then
  671. begin
  672. { if it worked, we're done }
  673. end
  674. else
  675. begin
  676. { SSA support }
  677. maybechangeloadnodereg(current_asmdata.CurrAsmList,left,false);
  678. maybechangeloadnodereg(current_asmdata.CurrAsmList,right,true);
  679. case right.location.loc of
  680. LOC_CONSTANT :
  681. begin
  682. {$ifndef cpu64bitalu}
  683. if (left.location.size in [OS_64,OS_S64]) or (right.location.size in [OS_64,OS_S64]) then
  684. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,right.location.value64,left.location)
  685. else
  686. {$endif not cpu64bitalu}
  687. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,right.location.value,left.location);
  688. end;
  689. LOC_REFERENCE,
  690. LOC_CREFERENCE :
  691. begin
  692. case left.location.loc of
  693. LOC_REGISTER,
  694. LOC_CREGISTER :
  695. begin
  696. {$ifdef cpu64bitalu}
  697. if left.location.size in [OS_128,OS_S128] then
  698. cg128.a_load128_ref_reg(current_asmdata.CurrAsmList,right.location.reference,left.location.register128)
  699. else
  700. {$else cpu64bitalu}
  701. if left.location.size in [OS_64,OS_S64] then
  702. cg64.a_load64_ref_reg(current_asmdata.CurrAsmList,right.location.reference,left.location.register64)
  703. else
  704. {$endif cpu64bitalu}
  705. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.register);
  706. end;
  707. LOC_FPUREGISTER,
  708. LOC_CFPUREGISTER :
  709. begin
  710. hlcg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
  711. right.resultdef,left.resultdef,
  712. right.location.reference,
  713. left.location.register);
  714. end;
  715. LOC_REFERENCE,
  716. LOC_CREFERENCE :
  717. begin
  718. if (left.resultdef.typ=floatdef) and
  719. (right.resultdef.typ=floatdef) and
  720. (left.location.size<>right.location.size) then
  721. begin
  722. hlcg.a_loadfpu_ref_ref(current_asmdata.CurrAsmList,
  723. right.resultdef,left.resultdef,
  724. right.location.reference,left.location.reference)
  725. end
  726. else
  727. begin
  728. { TODO: HACK: unaligned test, maybe remove all unaligned locations (array of char) from the compiler}
  729. { Use unaligned copy when the offset is not aligned }
  730. len:=left.resultdef.size;
  731. { can be 0 in case of formaldef on JVM target }
  732. if len=0 then
  733. len:=sizeof(pint);
  734. { data smaller than an aint has less alignment requirements }
  735. { max(1,...) avoids div by zero in case of an empty record }
  736. alignmentrequirement:=min(max(1,len),sizeof(aint));
  737. if (right.location.reference.offset mod alignmentrequirement<>0) or
  738. (left.location.reference.offset mod alignmentrequirement<>0) or
  739. (right.resultdef.alignment<alignmentrequirement) or
  740. ((right.location.reference.alignment<>0) and
  741. (right.location.reference.alignment<alignmentrequirement)) or
  742. ((left.location.reference.alignment<>0) and
  743. (left.location.reference.alignment<alignmentrequirement)) then
  744. hlcg.g_concatcopy_unaligned(current_asmdata.CurrAsmList,left.resultdef,right.location.reference,left.location.reference)
  745. else
  746. hlcg.g_concatcopy(current_asmdata.CurrAsmList,left.resultdef,right.location.reference,left.location.reference);
  747. end;
  748. end;
  749. LOC_MMREGISTER,
  750. LOC_CMMREGISTER:
  751. begin
  752. {$ifdef x86}
  753. if (right.resultdef.typ=floatdef) and
  754. not use_vectorfpu(right.resultdef) then
  755. begin
  756. { perform size conversion if needed (the mm-code cannot }
  757. { convert an extended into a double/single, since sse }
  758. { doesn't support extended) }
  759. r:=cg.getfpuregister(current_asmdata.CurrAsmList,right.location.size);
  760. tg.gethltemp(current_asmdata.CurrAsmList,left.resultdef,left.resultdef.size,tt_normal,href);
  761. cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,right.location.size,right.location.size,right.location.reference,r);
  762. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,r,href);
  763. if releaseright then
  764. location_freetemp(current_asmdata.CurrAsmList,right.location);
  765. releaseright:=true;
  766. location_reset_ref(right.location,LOC_REFERENCE,left.location.size,0);
  767. right.location.reference:=href;
  768. end;
  769. {$endif}
  770. cg.a_loadmm_ref_reg(current_asmdata.CurrAsmList,
  771. right.location.size,
  772. left.location.size,
  773. right.location.reference,
  774. left.location.register,mms_movescalar);
  775. end;
  776. LOC_SUBSETREG,
  777. LOC_CSUBSETREG:
  778. hlcg.a_load_ref_subsetreg(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.sreg);
  779. LOC_SUBSETREF,
  780. LOC_CSUBSETREF:
  781. {$ifndef cpu64bitalu}
  782. if right.location.size in [OS_64,OS_S64] then
  783. cg64.a_load64_ref_subsetref(current_asmdata.CurrAsmList,right.location.reference,left.location.sref)
  784. else
  785. {$endif not cpu64bitalu}
  786. hlcg.a_load_ref_subsetref(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.reference,left.location.sref);
  787. else
  788. internalerror(200203284);
  789. end;
  790. end;
  791. {$ifdef SUPPORT_MMX}
  792. LOC_CMMXREGISTER,
  793. LOC_MMXREGISTER:
  794. begin
  795. if left.location.loc=LOC_CMMXREGISTER then
  796. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.register,nil)
  797. else
  798. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.reference,nil);
  799. end;
  800. {$endif SUPPORT_MMX}
  801. LOC_MMREGISTER,
  802. LOC_CMMREGISTER:
  803. begin
  804. if left.resultdef.typ=arraydef then
  805. begin
  806. end
  807. else
  808. begin
  809. case left.location.loc of
  810. LOC_CMMREGISTER,
  811. LOC_MMREGISTER:
  812. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,left.location.register,mms_movescalar);
  813. LOC_REFERENCE,
  814. LOC_CREFERENCE:
  815. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,left.location.reference,mms_movescalar);
  816. else
  817. internalerror(2009112601);
  818. end;
  819. end;
  820. end;
  821. LOC_REGISTER,
  822. LOC_CREGISTER :
  823. begin
  824. {$ifdef cpu64bitalu}
  825. if left.location.size in [OS_128,OS_S128] then
  826. cg128.a_load128_reg_loc(current_asmdata.CurrAsmList,
  827. right.location.register128,left.location)
  828. else
  829. {$else cpu64bitalu}
  830. { also OS_F64 in case of mmreg -> intreg }
  831. if left.location.size in [OS_64,OS_S64,OS_F64] then
  832. cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,
  833. right.location.register64,left.location)
  834. else
  835. {$endif cpu64bitalu}
  836. hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,right.resultdef,left.resultdef,right.location.register,left.location);
  837. end;
  838. LOC_FPUREGISTER,
  839. LOC_CFPUREGISTER :
  840. begin
  841. { we can't do direct moves between fpu and mm registers }
  842. if left.location.loc in [LOC_MMREGISTER,LOC_CMMREGISTER] then
  843. begin
  844. {$ifdef x86}
  845. if not use_vectorfpu(right.resultdef) then
  846. begin
  847. { perform size conversion if needed (the mm-code cannot convert an }
  848. { extended into a double/single, since sse doesn't support extended) }
  849. tg.gethltemp(current_asmdata.CurrAsmList,left.resultdef, left.resultdef.size,tt_normal,href);
  850. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,href);
  851. location_reset_ref(right.location,LOC_REFERENCE,left.location.size,0);
  852. right.location.reference:=href;
  853. end;
  854. {$endif}
  855. location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,false);
  856. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,
  857. right.location.size,left.location.size,
  858. right.location.register,left.location.register,mms_movescalar);
  859. end
  860. else
  861. hlcg.a_loadfpu_reg_loc(current_asmdata.CurrAsmList,
  862. right.resultdef,left.resultdef,
  863. right.location.register,left.location);
  864. end;
  865. LOC_SUBSETREG,
  866. LOC_CSUBSETREG:
  867. begin
  868. hlcg.a_load_subsetreg_loc(current_asmdata.CurrAsmList,
  869. right.resultdef,left.resultdef,right.location.sreg,left.location);
  870. end;
  871. LOC_SUBSETREF,
  872. LOC_CSUBSETREF:
  873. begin
  874. {$ifndef cpu64bitalu}
  875. if right.location.size in [OS_64,OS_S64] then
  876. cg64.a_load64_subsetref_loc(current_asmdata.CurrAsmList,right.location.sref,left.location)
  877. else
  878. {$endif not cpu64bitalu}
  879. hlcg.a_load_subsetref_loc(current_asmdata.CurrAsmList,
  880. right.resultdef,left.resultdef,right.location.sref,left.location);
  881. end;
  882. LOC_JUMP :
  883. begin
  884. current_asmdata.getjumplabel(hlabel);
  885. hlcg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
  886. if is_pasbool(left.resultdef) then
  887. begin
  888. {$ifndef cpu64bitalu}
  889. if left.location.size in [OS_64,OS_S64] then
  890. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,1,left.location)
  891. else
  892. {$endif not cpu64bitalu}
  893. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,1,left.location)
  894. end
  895. else
  896. begin
  897. {$ifndef cpu64bitalu}
  898. if left.location.size in [OS_64,OS_S64] then
  899. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,-1,left.location)
  900. else
  901. {$endif not cpu64bitalu}
  902. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,-1,left.location);
  903. end;
  904. hlcg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
  905. hlcg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
  906. {$ifndef cpu64bitalu}
  907. if left.location.size in [OS_64,OS_S64] then
  908. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,0,left.location)
  909. else
  910. {$endif not cpu64bitalu}
  911. hlcg.a_load_const_loc(current_asmdata.CurrAsmList,left.resultdef,0,left.location);
  912. hlcg.a_label(current_asmdata.CurrAsmList,hlabel);
  913. end;
  914. {$ifdef cpuflags}
  915. LOC_FLAGS :
  916. begin
  917. if is_pasbool(left.resultdef) then
  918. begin
  919. case left.location.loc of
  920. LOC_REGISTER,LOC_CREGISTER:
  921. {$ifdef cpu32bitalu}
  922. if left.location.size in [OS_S64,OS_64] then
  923. begin
  924. cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,left.location.register64.reglo);
  925. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  926. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,left.location.register64.reghi);
  927. end
  928. else
  929. {$endif cpu32bitalu}
  930. begin
  931. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.register);
  932. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  933. end;
  934. LOC_REFERENCE:
  935. { i386 has a hack in its code generator so that it can
  936. deal with 64 bit locations in this parcticular case }
  937. {$if defined(cpu32bitalu) and not defined(x86)}
  938. if left.location.size in [OS_S64,OS_64] then
  939. begin
  940. r64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  941. r64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  942. cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,r64.reglo);
  943. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  944. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,r64.reghi);
  945. cg64.a_load64_reg_ref(current_asmdata.CurrAsmList,r64,left.location.reference);
  946. end
  947. else
  948. {$endif cpu32bitalu}
  949. begin
  950. cg.g_flags2ref(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,left.location.reference);
  951. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  952. end;
  953. LOC_SUBSETREG,LOC_SUBSETREF:
  954. begin
  955. r:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
  956. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,r);
  957. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  958. hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,r,left.location);
  959. end;
  960. else
  961. internalerror(200203273);
  962. end;
  963. end
  964. else
  965. begin
  966. {$ifdef cpu32bitalu}
  967. if left.location.size in [OS_S64,OS_64] then
  968. begin
  969. r64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  970. r64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
  971. cg.g_flags2reg(current_asmdata.CurrAsmList,OS_32,right.location.resflags,r64.reglo);
  972. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  973. cg.a_load_const_reg(current_asmdata.CurrAsmList,OS_32,0,r64.reghi);
  974. cg64.a_op64_reg_reg(current_asmdata.CurrAsmList,OP_NEG,OS_S64,
  975. r64,r64);
  976. cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,r64,left.location);
  977. end
  978. else
  979. {$endif cpu32bitalu}
  980. begin
  981. r:=cg.getintregister(current_asmdata.CurrAsmList,left.location.size);
  982. cg.g_flags2reg(current_asmdata.CurrAsmList,left.location.size,right.location.resflags,r);
  983. cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_DEFAULTFLAGS);
  984. cg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NEG,left.location.size,r,r);
  985. hlcg.a_load_reg_loc(current_asmdata.CurrAsmList,left.resultdef,left.resultdef,r,left.location);
  986. end
  987. end;
  988. end;
  989. {$endif cpuflags}
  990. end;
  991. end;
  992. if releaseright then
  993. location_freetemp(current_asmdata.CurrAsmList,right.location);
  994. current_procinfo.CurrTrueLabel:=otlabel;
  995. current_procinfo.CurrFalseLabel:=oflabel;
  996. end;
  997. {*****************************************************************************
  998. SecondArrayConstruct
  999. *****************************************************************************}
  1000. const
  1001. vtInteger = 0;
  1002. vtBoolean = 1;
  1003. vtChar = 2;
  1004. vtExtended = 3;
  1005. vtString = 4;
  1006. vtPointer = 5;
  1007. vtPChar = 6;
  1008. vtObject = 7;
  1009. vtClass = 8;
  1010. vtWideChar = 9;
  1011. vtPWideChar = 10;
  1012. vtAnsiString32 = 11;
  1013. vtCurrency = 12;
  1014. vtVariant = 13;
  1015. vtInterface = 14;
  1016. vtWideString = 15;
  1017. vtInt64 = 16;
  1018. vtQWord = 17;
  1019. vtUnicodeString = 18;
  1020. vtAnsiString16 = 19;
  1021. vtAnsiString64 = 20;
  1022. procedure tcgarrayconstructornode.makearrayref(var ref: treference; eledef: tdef);
  1023. begin
  1024. { do nothing by default }
  1025. end;
  1026. procedure tcgarrayconstructornode.advancearrayoffset(var ref: treference; elesize: asizeint);
  1027. begin
  1028. inc(ref.offset,elesize);
  1029. end;
  1030. procedure tcgarrayconstructornode.pass_generate_code;
  1031. var
  1032. hp : tarrayconstructornode;
  1033. href : treference;
  1034. lt : tdef;
  1035. paraloc : tcgparalocation;
  1036. otlabel,
  1037. oflabel : tasmlabel;
  1038. vtype : longint;
  1039. eledef: tdef;
  1040. elesize : longint;
  1041. tmpreg : tregister;
  1042. vaddr : boolean;
  1043. freetemp,
  1044. dovariant: boolean;
  1045. begin
  1046. if is_packed_array(resultdef) then
  1047. internalerror(200608042);
  1048. dovariant:=
  1049. ((nf_forcevaria in flags) or is_variant_array(resultdef)) and
  1050. not(target_info.system in systems_managed_vm);
  1051. if dovariant then
  1052. begin
  1053. eledef:=search_system_type('TVARREC').typedef;
  1054. elesize:=eledef.size;
  1055. end
  1056. else
  1057. begin
  1058. eledef:=tarraydef(resultdef).elementdef;
  1059. elesize:=tarraydef(resultdef).elesize;
  1060. end;
  1061. { alignment is filled in by tg.gethltemp below }
  1062. location_reset_ref(location,LOC_CREFERENCE,OS_NO,0);
  1063. fillchar(paraloc,sizeof(paraloc),0);
  1064. { Allocate always a temp, also if no elements are required, to
  1065. be sure that location is valid (PFV) }
  1066. { on the JVM platform, an array can have 0 elements; since the length
  1067. of the array is part of the array itself, make sure we allocate one
  1068. of the proper length to avoid getting unexpected results later }
  1069. if tarraydef(resultdef).highrange=-1 then
  1070. tg.gethltemp(current_asmdata.CurrAsmList,resultdef,{$ifdef jvm}0{$else}elesize{$endif},tt_normal,location.reference)
  1071. else
  1072. tg.gethltemp(current_asmdata.CurrAsmList,resultdef,(tarraydef(resultdef).highrange+1)*elesize,tt_normal,location.reference);
  1073. href:=location.reference;
  1074. makearrayref(href,eledef);
  1075. { Process nodes in array constructor }
  1076. hp:=self;
  1077. while assigned(hp) do
  1078. begin
  1079. if assigned(hp.left) then
  1080. begin
  1081. freetemp:=true;
  1082. if (hp.left.expectloc=LOC_JUMP) then
  1083. begin
  1084. otlabel:=current_procinfo.CurrTrueLabel;
  1085. oflabel:=current_procinfo.CurrFalseLabel;
  1086. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  1087. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  1088. end;
  1089. secondpass(hp.left);
  1090. { Move flags and jump in register }
  1091. if hp.left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  1092. hlcg.location_force_reg(current_asmdata.CurrAsmList,hp.left.location,hp.left.resultdef,hp.left.resultdef,false);
  1093. if (hp.left.location.loc=LOC_JUMP) then
  1094. begin
  1095. if (hp.left.expectloc<>LOC_JUMP) then
  1096. internalerror(2007103101);
  1097. current_procinfo.CurrTrueLabel:=otlabel;
  1098. current_procinfo.CurrFalseLabel:=oflabel;
  1099. end;
  1100. if dovariant then
  1101. begin
  1102. { find the correct vtype value }
  1103. vtype:=$ff;
  1104. vaddr:=false;
  1105. lt:=hp.left.resultdef;
  1106. case lt.typ of
  1107. enumdef,
  1108. orddef :
  1109. begin
  1110. if is_64bit(lt) then
  1111. begin
  1112. case torddef(lt).ordtype of
  1113. scurrency:
  1114. vtype:=vtCurrency;
  1115. s64bit:
  1116. vtype:=vtInt64;
  1117. u64bit:
  1118. vtype:=vtQWord;
  1119. end;
  1120. freetemp:=false;
  1121. vaddr:=true;
  1122. end
  1123. else if (lt.typ=enumdef) or
  1124. is_integer(lt) then
  1125. vtype:=vtInteger
  1126. else
  1127. if is_boolean(lt) then
  1128. vtype:=vtBoolean
  1129. else
  1130. if (lt.typ=orddef) then
  1131. begin
  1132. case torddef(lt).ordtype of
  1133. uchar:
  1134. vtype:=vtChar;
  1135. uwidechar:
  1136. vtype:=vtWideChar;
  1137. end;
  1138. end;
  1139. end;
  1140. floatdef :
  1141. begin
  1142. if is_currency(lt) then
  1143. vtype:=vtCurrency
  1144. else
  1145. vtype:=vtExtended;
  1146. freetemp:=false;
  1147. vaddr:=true;
  1148. end;
  1149. procvardef,
  1150. pointerdef :
  1151. begin
  1152. if is_pchar(lt) then
  1153. vtype:=vtPChar
  1154. else if is_pwidechar(lt) then
  1155. vtype:=vtPWideChar
  1156. else
  1157. vtype:=vtPointer;
  1158. end;
  1159. variantdef :
  1160. begin
  1161. vtype:=vtVariant;
  1162. vaddr:=true;
  1163. freetemp:=false;
  1164. end;
  1165. classrefdef :
  1166. vtype:=vtClass;
  1167. objectdef :
  1168. if is_interface(lt) then
  1169. vtype:=vtInterface
  1170. { vtObject really means a class based on TObject }
  1171. else if is_class(lt) then
  1172. vtype:=vtObject
  1173. else
  1174. internalerror(200505171);
  1175. stringdef :
  1176. begin
  1177. if is_shortstring(lt) then
  1178. begin
  1179. vtype:=vtString;
  1180. vaddr:=true;
  1181. freetemp:=false;
  1182. end
  1183. else
  1184. if is_ansistring(lt) then
  1185. begin
  1186. vtype:=vtAnsiString;
  1187. freetemp:=false;
  1188. end
  1189. else
  1190. if is_widestring(lt) then
  1191. begin
  1192. vtype:=vtWideString;
  1193. freetemp:=false;
  1194. end
  1195. else
  1196. if is_unicodestring(lt) then
  1197. begin
  1198. vtype:=vtUnicodeString;
  1199. freetemp:=false;
  1200. end;
  1201. end;
  1202. end;
  1203. if vtype=$ff then
  1204. internalerror(14357);
  1205. { write changing field update href to the next element }
  1206. inc(href.offset,sizeof(pint));
  1207. if vaddr then
  1208. begin
  1209. hlcg.location_force_mem(current_asmdata.CurrAsmList,hp.left.location,hp.left.resultdef);
  1210. tmpreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
  1211. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,hp.left.location.reference,tmpreg);
  1212. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,tmpreg,href);
  1213. end
  1214. else
  1215. { todo: proper type information for hlcg }
  1216. hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,hp.left.resultdef,voidpointertype,hp.left.location,href);
  1217. { update href to the vtype field and write it }
  1218. dec(href.offset,sizeof(pint));
  1219. cg.a_load_const_ref(current_asmdata.CurrAsmList, OS_INT,vtype,href);
  1220. { goto next array element }
  1221. advancearrayoffset(href,sizeof(pint)*2);
  1222. end
  1223. else
  1224. { normal array constructor of the same type }
  1225. begin
  1226. if is_managed_type(resultdef) then
  1227. freetemp:=false;
  1228. case hp.left.location.loc of
  1229. LOC_MMREGISTER,
  1230. LOC_CMMREGISTER:
  1231. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location.size,
  1232. hp.left.location.register,href,mms_movescalar);
  1233. LOC_FPUREGISTER,
  1234. LOC_CFPUREGISTER :
  1235. hlcg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,hp.left.resultdef,hp.left.resultdef,hp.left.location.register,href);
  1236. LOC_REFERENCE,
  1237. LOC_CREFERENCE :
  1238. begin
  1239. if is_shortstring(hp.left.resultdef) then
  1240. hlcg.g_copyshortstring(current_asmdata.CurrAsmList,hp.left.location.reference,href,
  1241. Tstringdef(hp.left.resultdef))
  1242. else
  1243. hlcg.g_concatcopy(current_asmdata.CurrAsmList,eledef,hp.left.location.reference,href);
  1244. end;
  1245. else
  1246. begin
  1247. {$ifdef cpu64bitalu}
  1248. if hp.left.location.size in [OS_128,OS_S128] then
  1249. cg128.a_load128_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
  1250. else
  1251. {$else cpu64bitalu}
  1252. if hp.left.location.size in [OS_64,OS_S64] then
  1253. cg64.a_load64_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
  1254. else
  1255. {$endif cpu64bitalu}
  1256. hlcg.a_load_loc_ref(current_asmdata.CurrAsmList,eledef,eledef,hp.left.location,href);
  1257. end;
  1258. end;
  1259. advancearrayoffset(href,elesize);
  1260. end;
  1261. if freetemp then
  1262. location_freetemp(current_asmdata.CurrAsmList,hp.left.location);
  1263. end;
  1264. { load next entry }
  1265. hp:=tarrayconstructornode(hp.right);
  1266. end;
  1267. end;
  1268. {*****************************************************************************
  1269. SecondRTTI
  1270. *****************************************************************************}
  1271. procedure tcgrttinode.pass_generate_code;
  1272. begin
  1273. location_reset_ref(location,LOC_CREFERENCE,OS_NO,sizeof(pint));
  1274. case rttidatatype of
  1275. rdt_normal:
  1276. location.reference.symbol:=RTTIWriter.get_rtti_label(rttidef,rttitype);
  1277. rdt_ord2str:
  1278. location.reference.symbol:=RTTIWriter.get_rtti_label_ord2str(rttidef,rttitype);
  1279. rdt_str2ord:
  1280. location.reference.symbol:=RTTIWriter.get_rtti_label_str2ord(rttidef,rttitype);
  1281. end;
  1282. end;
  1283. begin
  1284. cloadnode:=tcgloadnode;
  1285. cassignmentnode:=tcgassignmentnode;
  1286. carrayconstructornode:=tcgarrayconstructornode;
  1287. crttinode:=tcgrttinode;
  1288. end.