ncgld.pas 66 KB

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