ncgld.pas 60 KB

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