ncgld.pas 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031
  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. node,nld;
  23. type
  24. tcgloadnode = class(tloadnode)
  25. procedure pass_generate_code;override;
  26. procedure generate_picvaraccess;virtual;
  27. end;
  28. tcgassignmentnode = class(tassignmentnode)
  29. procedure pass_generate_code;override;
  30. end;
  31. tcgarrayconstructornode = class(tarrayconstructornode)
  32. procedure pass_generate_code;override;
  33. end;
  34. tcgrttinode = class(trttinode)
  35. procedure pass_generate_code;override;
  36. end;
  37. implementation
  38. uses
  39. cutils,
  40. systems,
  41. verbose,globtype,globals,
  42. symconst,symtype,symdef,symsym,defutil,paramgr,
  43. ncnv,ncon,nmem,nbas,ncgrtti,
  44. aasmbase,aasmtai,aasmdata,aasmcpu,
  45. cgbase,pass_2,
  46. procinfo,
  47. cpubase,parabase,
  48. tgobj,ncgutil,
  49. cgutils,cgobj,
  50. ncgbas,ncgflw;
  51. {*****************************************************************************
  52. SecondLoad
  53. *****************************************************************************}
  54. procedure tcgloadnode.generate_picvaraccess;
  55. begin
  56. {$ifndef sparc}
  57. location.reference.base:=current_procinfo.got;
  58. location.reference.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname+'@GOT');
  59. {$endif sparc}
  60. end;
  61. procedure tcgloadnode.pass_generate_code;
  62. var
  63. hregister : tregister;
  64. vs : tabstractnormalvarsym;
  65. gvs : tstaticvarsym;
  66. pd : tprocdef;
  67. href : treference;
  68. newsize : tcgsize;
  69. endrelocatelab,
  70. norelocatelab : tasmlabel;
  71. paraloc1 : tcgpara;
  72. begin
  73. { we don't know the size of all arrays }
  74. newsize:=def_cgsize(resultdef);
  75. location_reset(location,LOC_REFERENCE,newsize);
  76. case symtableentry.typ of
  77. absolutevarsym :
  78. begin
  79. { this is only for toasm and toaddr }
  80. case tabsolutevarsym(symtableentry).abstyp of
  81. toaddr :
  82. begin
  83. {$ifdef i386}
  84. if tabsolutevarsym(symtableentry).absseg then
  85. location.reference.segment:=NR_FS;
  86. {$endif i386}
  87. location.reference.offset:=tabsolutevarsym(symtableentry).addroffset;
  88. end;
  89. toasm :
  90. location.reference.symbol:=current_asmdata.RefAsmSymbol(tabsolutevarsym(symtableentry).mangledname);
  91. else
  92. internalerror(200310283);
  93. end;
  94. end;
  95. constsym:
  96. begin
  97. if tconstsym(symtableentry).consttyp=constresourcestring then
  98. begin
  99. location_reset(location,LOC_CREFERENCE,OS_ADDR);
  100. location.reference.symbol:=current_asmdata.RefAsmSymbol(make_mangledname('RESSTR',symtableentry.owner,symtableentry.name));
  101. { Resourcestring layout:
  102. TResourceStringRecord = Packed Record
  103. Name,
  104. CurrentValue,
  105. DefaultValue : AnsiString;
  106. HashValue : LongWord;
  107. end;
  108. }
  109. location.reference.offset:=sizeof(aint);
  110. end
  111. else
  112. internalerror(22798);
  113. end;
  114. staticvarsym :
  115. begin
  116. gvs:=tstaticvarsym(symtableentry);
  117. if ([vo_is_dll_var,vo_is_external] * gvs.varoptions <> []) then
  118. begin
  119. location.reference.base := cg.g_indirect_sym_load(current_asmdata.CurrAsmList,tstaticvarsym(symtableentry).mangledname);
  120. if (location.reference.base <> NR_NO) then
  121. exit;
  122. end;
  123. if (vo_is_dll_var in gvs.varoptions) then
  124. { DLL variable }
  125. begin
  126. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  127. location.reference.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname);
  128. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,location.reference,hregister);
  129. reference_reset_base(location.reference,hregister,0);
  130. end
  131. { Thread variable }
  132. else if (vo_is_thread_var in gvs.varoptions) and
  133. not(tf_section_threadvars in target_info.flags) then
  134. begin
  135. if (tf_section_threadvars in target_info.flags) then
  136. begin
  137. if gvs.localloc.loc=LOC_INVALID then
  138. reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname),0)
  139. else
  140. location:=gvs.localloc;
  141. {$ifdef i386}
  142. case target_info.system of
  143. system_i386_linux:
  144. location.reference.segment:=NR_GS;
  145. system_i386_win32:
  146. location.reference.segment:=NR_FS;
  147. end;
  148. {$endif i386}
  149. end
  150. else
  151. begin
  152. {
  153. Thread var loading is optimized to first check if
  154. a relocate function is available. When the function
  155. is available it is called to retrieve the address.
  156. Otherwise the address is loaded with the symbol
  157. The code needs to be in the order to first handle the
  158. call and then the address load to be sure that the
  159. register that is used for returning is the same (PFV)
  160. }
  161. current_asmdata.getjumplabel(norelocatelab);
  162. current_asmdata.getjumplabel(endrelocatelab);
  163. { make sure hregister can't allocate the register necessary for the parameter }
  164. paraloc1.init;
  165. paramanager.getintparaloc(pocall_default,1,paraloc1);
  166. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  167. reference_reset_symbol(href,current_asmdata.RefAsmSymbol('FPC_THREADVAR_RELOCATE'),0);
  168. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
  169. cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_ADDR,OC_EQ,0,hregister,norelocatelab);
  170. { don't save the allocated register else the result will be destroyed later }
  171. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname),0);
  172. paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc1);
  173. cg.a_param_ref(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
  174. paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc1);
  175. paraloc1.done;
  176. cg.allocallcpuregisters(current_asmdata.CurrAsmList);
  177. cg.a_call_reg(current_asmdata.CurrAsmList,hregister);
  178. cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
  179. cg.getcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
  180. cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
  181. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  182. cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_ADDR,NR_FUNCTION_RESULT_REG,hregister);
  183. cg.a_jmp_always(current_asmdata.CurrAsmList,endrelocatelab);
  184. cg.a_label(current_asmdata.CurrAsmList,norelocatelab);
  185. { no relocation needed, load the address of the variable only, the
  186. layout of a threadvar is (4 bytes pointer):
  187. 0 - Threadvar index
  188. 4 - Threadvar value in single threading }
  189. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname),sizeof(aint));
  190. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,hregister);
  191. cg.a_label(current_asmdata.CurrAsmList,endrelocatelab);
  192. location.reference.base:=hregister;
  193. end;
  194. end
  195. { Normal (or external) variable }
  196. else
  197. begin
  198. if gvs.localloc.loc=LOC_INVALID then
  199. reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname),0)
  200. else
  201. location:=gvs.localloc;
  202. end;
  203. { make const a LOC_CREFERENCE }
  204. if (gvs.varspez=vs_const) and
  205. (location.loc=LOC_REFERENCE) then
  206. location.loc:=LOC_CREFERENCE;
  207. end;
  208. paravarsym,
  209. localvarsym :
  210. begin
  211. vs:=tabstractnormalvarsym(symtableentry);
  212. { Nested variable }
  213. if assigned(left) then
  214. begin
  215. secondpass(left);
  216. if left.location.loc<>LOC_REGISTER then
  217. internalerror(200309286);
  218. if vs.localloc.loc<>LOC_REFERENCE then
  219. internalerror(200409241);
  220. reference_reset_base(location.reference,left.location.register,vs.localloc.reference.offset);
  221. end
  222. else
  223. location:=vs.localloc;
  224. { handle call by reference variables when they are not
  225. alreayd copied to local copies. Also ignore the reference
  226. when we need to load the self pointer for objects }
  227. if is_addr_param_load then
  228. begin
  229. if (location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
  230. hregister:=location.register
  231. else
  232. begin
  233. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  234. { we need to load only an address }
  235. location.size:=OS_ADDR;
  236. cg.a_load_loc_reg(current_asmdata.CurrAsmList,location.size,location,hregister);
  237. end;
  238. location_reset(location,LOC_REFERENCE,newsize);
  239. location.reference.base:=hregister;
  240. end;
  241. { make const a LOC_CREFERENCE }
  242. if (vs.varspez=vs_const) and
  243. (location.loc=LOC_REFERENCE) then
  244. location.loc:=LOC_CREFERENCE;
  245. end;
  246. procsym:
  247. begin
  248. if not assigned(procdef) then
  249. internalerror(200312011);
  250. if assigned(left) then
  251. begin
  252. if (sizeof(aint) = 4) then
  253. location_reset(location,LOC_CREFERENCE,OS_64)
  254. else if (sizeof(aint) = 8) then
  255. location_reset(location,LOC_CREFERENCE,OS_128)
  256. else
  257. internalerror(20020520);
  258. tg.GetTemp(current_asmdata.CurrAsmList,2*sizeof(aint),tt_normal,location.reference);
  259. secondpass(left);
  260. { load class instance/classrefdef address }
  261. if left.location.loc=LOC_CONSTANT then
  262. location_force_reg(current_asmdata.CurrAsmList,left.location,OS_ADDR,false);
  263. case left.location.loc of
  264. LOC_CREGISTER,
  265. LOC_REGISTER:
  266. begin
  267. { this is not possible for objects }
  268. if is_object(left.resultdef) then
  269. internalerror(200304234);
  270. hregister:=left.location.register;
  271. end;
  272. LOC_CREFERENCE,
  273. LOC_REFERENCE:
  274. begin
  275. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  276. if not is_object(left.resultdef) then
  277. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.reference,hregister)
  278. else
  279. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,hregister);
  280. location_freetemp(current_asmdata.CurrAsmList,left.location);
  281. end;
  282. else
  283. internalerror(200610311);
  284. end;
  285. { store the class instance or classredef address }
  286. href:=location.reference;
  287. inc(href.offset,sizeof(aint));
  288. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,href);
  289. { virtual method ? }
  290. if (po_virtualmethod in procdef.procoptions) and
  291. not(nf_inherited in flags) then
  292. begin
  293. { a classrefdef already points to the VMT }
  294. if (left.resultdef.typ<>classrefdef) then
  295. begin
  296. { load vmt pointer }
  297. reference_reset_base(href,hregister,0);
  298. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  299. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
  300. end;
  301. { load method address }
  302. reference_reset_base(href,hregister,procdef._class.vmtmethodoffset(procdef.extnumber));
  303. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  304. cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
  305. { ... and store it }
  306. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,location.reference);
  307. end
  308. else
  309. begin
  310. { load address of the function }
  311. reference_reset_symbol(href,current_asmdata.RefAsmSymbol(procdef.mangledname),0);
  312. hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
  313. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,hregister);
  314. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,location.reference);
  315. end;
  316. end
  317. else
  318. begin
  319. pd:=tprocdef(tprocsym(symtableentry).ProcdefList[0]);
  320. if (po_external in pd.procoptions) then
  321. location.reference.base := cg.g_indirect_sym_load(current_asmdata.CurrAsmList,pd.mangledname);
  322. {!!!!! Be aware, work on virtual methods too }
  323. if (location.reference.base = NR_NO) then
  324. location.reference.symbol:=current_asmdata.RefAsmSymbol(procdef.mangledname);
  325. end;
  326. end;
  327. labelsym :
  328. if assigned(tlabelsym(symtableentry).asmblocklabel) then
  329. location.reference.symbol:=tlabelsym(symtableentry).asmblocklabel
  330. else
  331. location.reference.symbol:=tcglabelnode((tlabelsym(symtableentry).code)).getasmlabel;
  332. else internalerror(200510032);
  333. end;
  334. end;
  335. {*****************************************************************************
  336. SecondAssignment
  337. *****************************************************************************}
  338. procedure tcgassignmentnode.pass_generate_code;
  339. var
  340. otlabel,hlabel,oflabel : tasmlabel;
  341. href : treference;
  342. releaseright : boolean;
  343. len : aint;
  344. r : tregister;
  345. oldflowcontrol : tflowcontrol;
  346. begin
  347. location_reset(location,LOC_VOID,OS_NO);
  348. otlabel:=current_procinfo.CurrTrueLabel;
  349. oflabel:=current_procinfo.CurrFalseLabel;
  350. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  351. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  352. {
  353. in most cases we can process first the right node which contains
  354. the most complex code. Exceptions for this are:
  355. - result is in flags, loading left will then destroy the flags
  356. - result is a jump, loading left must be already done before the jump is made
  357. - result need reference count, when left points to a value used in
  358. right then decreasing the refcnt on left can possibly release
  359. the memory before right increased the refcnt, result is that an
  360. empty value is assigned
  361. - calln, call destroys most registers and is therefor 'complex'
  362. But not when the result is in the flags, then
  363. loading the left node afterwards can destroy the flags.
  364. }
  365. if not(right.expectloc in [LOC_FLAGS,LOC_JUMP]) and
  366. ((right.nodetype=calln) or
  367. (right.resultdef.needs_inittable) or
  368. (right.registersint>=left.registersint)) then
  369. begin
  370. secondpass(right);
  371. { increment source reference counter, this is
  372. useless for constants }
  373. if (right.resultdef.needs_inittable) and
  374. not is_constnode(right) then
  375. begin
  376. location_force_mem(current_asmdata.CurrAsmList,right.location);
  377. location_get_data_ref(current_asmdata.CurrAsmList,right.location,href,false);
  378. cg.g_incrrefcount(current_asmdata.CurrAsmList,right.resultdef,href);
  379. end;
  380. if codegenerror then
  381. exit;
  382. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  383. { can be false }
  384. secondpass(left);
  385. { decrement destination reference counter }
  386. if (left.resultdef.needs_inittable) then
  387. begin
  388. location_get_data_ref(current_asmdata.CurrAsmList,left.location,href,false);
  389. cg.g_decrrefcount(current_asmdata.CurrAsmList,left.resultdef,href);
  390. end;
  391. if codegenerror then
  392. exit;
  393. end
  394. else
  395. begin
  396. { calculate left sides }
  397. secondpass(left);
  398. { decrement destination reference counter }
  399. if (left.resultdef.needs_inittable) then
  400. begin
  401. location_get_data_ref(current_asmdata.CurrAsmList,left.location,href,false);
  402. cg.g_decrrefcount(current_asmdata.CurrAsmList,left.resultdef,href);
  403. end;
  404. if codegenerror then
  405. exit;
  406. { tell the SSA/SSL code that the left side was handled first so
  407. ni SSL is done
  408. }
  409. oldflowcontrol:=flowcontrol;
  410. include(flowcontrol,fc_lefthandled);
  411. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  412. { can be false }
  413. secondpass(right);
  414. flowcontrol:=oldflowcontrol;
  415. { increment source reference counter, this is
  416. useless for string constants}
  417. if (right.resultdef.needs_inittable) and
  418. (right.nodetype<>stringconstn) then
  419. begin
  420. location_force_mem(current_asmdata.CurrAsmList,right.location);
  421. location_get_data_ref(current_asmdata.CurrAsmList,right.location,href,false);
  422. cg.g_incrrefcount(current_asmdata.CurrAsmList,right.resultdef,href);
  423. end;
  424. if codegenerror then
  425. exit;
  426. end;
  427. releaseright:=true;
  428. { optimize temp to temp copies }
  429. {$ifdef old_append_str}
  430. if (left.nodetype = temprefn) and
  431. { we may store certain temps in registers in the future, then this }
  432. { optimization will have to be adapted }
  433. (left.location.loc = LOC_REFERENCE) and
  434. (right.location.loc = LOC_REFERENCE) and
  435. tg.istemp(right.location.reference) and
  436. (tg.sizeoftemp(current_asmdata.CurrAsmList,right.location.reference) = tg.sizeoftemp(current_asmdata.CurrAsmList,left.location.reference)) then
  437. begin
  438. { in theory, we should also make sure the left temp type is }
  439. { already more or less of the same kind (ie. we must not }
  440. { assign an ansistring to a normaltemp). In practice, the }
  441. { assignment node will have already taken care of this for us }
  442. tcgtemprefnode(left).changelocation(right.location.reference);
  443. end
  444. { shortstring assignments are handled separately }
  445. else
  446. {$endif old_append_str}
  447. if is_shortstring(left.resultdef) then
  448. begin
  449. {
  450. we can get here only in the following situations
  451. for the right node:
  452. - empty constant string
  453. - char
  454. }
  455. { The addn is replaced by a blockn or calln that already returns
  456. a shortstring }
  457. if is_shortstring(right.resultdef) and
  458. (right.nodetype in [blockn,calln]) then
  459. begin
  460. { nothing to do }
  461. end
  462. { empty constant string }
  463. else if (right.nodetype=stringconstn) and
  464. (tstringconstnode(right).len=0) then
  465. begin
  466. cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_8,0,left.location.reference);
  467. end
  468. { char loading }
  469. else if is_char(right.resultdef) then
  470. begin
  471. if right.nodetype=ordconstn then
  472. begin
  473. if (target_info.endian = endian_little) then
  474. cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_16,(tordconstnode(right).value shl 8) or 1,
  475. setalignment(left.location.reference,1))
  476. else
  477. cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_16,tordconstnode(right).value or (1 shl 8),
  478. setalignment(left.location.reference,1));
  479. end
  480. else
  481. begin
  482. href:=left.location.reference;
  483. cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_8,1,href);
  484. inc(href.offset,1);
  485. case right.location.loc of
  486. LOC_REGISTER,
  487. LOC_CREGISTER :
  488. begin
  489. r:=cg.makeregsize(current_asmdata.CurrAsmList,right.location.register,OS_8);
  490. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_8,OS_8,r,href);
  491. end;
  492. LOC_REFERENCE,
  493. LOC_CREFERENCE :
  494. cg.a_load_ref_ref(current_asmdata.CurrAsmList,OS_8,OS_8,right.location.reference,href);
  495. else
  496. internalerror(200205111);
  497. end;
  498. end;
  499. end
  500. else
  501. internalerror(200204249);
  502. end
  503. else
  504. begin
  505. { SSA support }
  506. maybechangeloadnodereg(current_asmdata.CurrAsmList,left,false);
  507. maybechangeloadnodereg(current_asmdata.CurrAsmList,right,true);
  508. case right.location.loc of
  509. LOC_CONSTANT :
  510. begin
  511. {$ifndef cpu64bit}
  512. if (left.location.size in [OS_64,OS_S64]) or (right.location.size in [OS_64,OS_S64]) then
  513. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,right.location.value64,left.location)
  514. else
  515. {$endif cpu64bit}
  516. cg.a_load_const_loc(current_asmdata.CurrAsmList,right.location.value,left.location);
  517. end;
  518. LOC_REFERENCE,
  519. LOC_CREFERENCE :
  520. begin
  521. case left.location.loc of
  522. LOC_REGISTER,
  523. LOC_CREGISTER :
  524. begin
  525. {$ifndef cpu64bit}
  526. if left.location.size in [OS_64,OS_S64] then
  527. cg64.a_load64_ref_reg(current_asmdata.CurrAsmList,right.location.reference,left.location.register64)
  528. else
  529. {$endif cpu64bit}
  530. cg.a_load_ref_reg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.register);
  531. end;
  532. LOC_FPUREGISTER,
  533. LOC_CFPUREGISTER :
  534. begin
  535. cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
  536. right.location.size,left.location.size,
  537. right.location.reference,
  538. left.location.register);
  539. end;
  540. LOC_REFERENCE,
  541. LOC_CREFERENCE :
  542. begin
  543. if (left.resultdef.typ=floatdef) and
  544. (right.resultdef.typ=floatdef) and
  545. (left.location.size<>right.location.size) then
  546. begin
  547. cg.a_loadfpu_ref_ref(current_asmdata.CurrAsmList,
  548. right.location.size,left.location.size,
  549. right.location.reference,left.location.reference)
  550. end
  551. else
  552. begin
  553. {$warning HACK: unaligned test, maybe remove all unaligned locations (array of char) from the compiler}
  554. { Use unaligned copy when the offset is not aligned }
  555. len:=left.resultdef.size;
  556. if (right.location.reference.offset mod sizeof(aint)<>0) or
  557. (left.location.reference.offset mod sizeof(aint)<>0) or
  558. (right.resultdef.alignment<sizeof(aint)) or
  559. ((right.location.reference.alignment<>0) and
  560. (right.location.reference.alignment<sizeof(aint))) or
  561. ((left.location.reference.alignment<>0) and
  562. (left.location.reference.alignment<sizeof(aint))) then
  563. cg.g_concatcopy_unaligned(current_asmdata.CurrAsmList,right.location.reference,left.location.reference,len)
  564. else
  565. cg.g_concatcopy(current_asmdata.CurrAsmList,right.location.reference,left.location.reference,len);
  566. end;
  567. end;
  568. LOC_MMREGISTER,
  569. LOC_CMMREGISTER:
  570. begin
  571. {$ifdef x86}
  572. if not use_sse(right.resultdef) then
  573. begin
  574. { perform size conversion if needed (the mm-code cannot }
  575. { convert an extended into a double/single, since sse }
  576. { doesn't support extended) }
  577. r:=cg.getfpuregister(current_asmdata.CurrAsmList,right.location.size);
  578. tg.gettemp(current_asmdata.CurrAsmList,left.resultdef.size,tt_normal,href);
  579. cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,right.location.size,right.location.size,right.location.reference,r);
  580. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,r,href);
  581. if releaseright then
  582. location_freetemp(current_asmdata.CurrAsmList,right.location);
  583. releaseright:=true;
  584. location_reset(right.location,LOC_REFERENCE,left.location.size);
  585. right.location.reference:=href;
  586. end;
  587. {$endif}
  588. cg.a_loadmm_ref_reg(current_asmdata.CurrAsmList,
  589. right.location.size,
  590. left.location.size,
  591. right.location.reference,
  592. left.location.register,mms_movescalar);
  593. end;
  594. LOC_SUBSETREG,
  595. LOC_CSUBSETREG:
  596. cg.a_load_ref_subsetreg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.sreg);
  597. LOC_SUBSETREF,
  598. LOC_CSUBSETREF:
  599. {$ifndef cpu64bit}
  600. if right.location.size in [OS_64,OS_S64] then
  601. cg64.a_load64_ref_subsetref(current_asmdata.CurrAsmList,right.location.reference,left.location.sref)
  602. else
  603. {$endif cpu64bit}
  604. cg.a_load_ref_subsetref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.sref);
  605. else
  606. internalerror(200203284);
  607. end;
  608. end;
  609. {$ifdef SUPPORT_MMX}
  610. LOC_CMMXREGISTER,
  611. LOC_MMXREGISTER:
  612. begin
  613. if left.location.loc=LOC_CMMXREGISTER then
  614. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.register,nil)
  615. else
  616. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.reference,nil);
  617. end;
  618. {$endif SUPPORT_MMX}
  619. LOC_MMREGISTER,
  620. LOC_CMMREGISTER:
  621. begin
  622. if left.resultdef.typ=arraydef then
  623. begin
  624. end
  625. else
  626. begin
  627. if left.location.loc=LOC_CMMREGISTER then
  628. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,left.location.register,mms_movescalar)
  629. else
  630. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,left.location.reference,mms_movescalar);
  631. end;
  632. end;
  633. LOC_REGISTER,
  634. LOC_CREGISTER :
  635. begin
  636. {$ifndef cpu64bit}
  637. if left.location.size in [OS_64,OS_S64] then
  638. cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,
  639. right.location.register64,left.location)
  640. else
  641. {$endif cpu64bit}
  642. cg.a_load_reg_loc(current_asmdata.CurrAsmList,right.location.size,right.location.register,left.location);
  643. end;
  644. LOC_FPUREGISTER,
  645. LOC_CFPUREGISTER :
  646. begin
  647. { we can't do direct moves between fpu and mm registers }
  648. if left.location.loc in [LOC_MMREGISTER,LOC_CMMREGISTER] then
  649. begin
  650. {$ifdef x86}
  651. if not use_sse(right.resultdef) then
  652. begin
  653. { perform size conversion if needed (the mm-code cannot convert an }
  654. { extended into a double/single, since sse doesn't support extended) }
  655. tg.gettemp(current_asmdata.CurrAsmList,left.resultdef.size,tt_normal,href);
  656. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,href);
  657. location_reset(right.location,LOC_REFERENCE,left.location.size);
  658. right.location.reference:=href;
  659. end;
  660. {$endif}
  661. location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,false);
  662. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,
  663. right.location.size,left.location.size,
  664. right.location.register,left.location.register,mms_movescalar);
  665. end
  666. else
  667. cg.a_loadfpu_reg_loc(current_asmdata.CurrAsmList,
  668. right.location.size,
  669. right.location.register,left.location);
  670. end;
  671. LOC_SUBSETREG,
  672. LOC_CSUBSETREG:
  673. begin
  674. cg.a_load_subsetreg_loc(current_asmdata.CurrAsmList,
  675. right.location.size,right.location.sreg,left.location);
  676. end;
  677. LOC_SUBSETREF,
  678. LOC_CSUBSETREF:
  679. begin
  680. {$ifndef cpu64bit}
  681. if right.location.size in [OS_64,OS_S64] then
  682. cg64.a_load64_subsetref_loc(current_asmdata.CurrAsmList,right.location.sref,left.location)
  683. else
  684. {$endif cpu64bit}
  685. cg.a_load_subsetref_loc(current_asmdata.CurrAsmList,
  686. right.location.size,right.location.sref,left.location);
  687. end;
  688. LOC_JUMP :
  689. begin
  690. current_asmdata.getjumplabel(hlabel);
  691. cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
  692. cg.a_load_const_loc(current_asmdata.CurrAsmList,1,left.location);
  693. cg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
  694. cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
  695. cg.a_load_const_loc(current_asmdata.CurrAsmList,0,left.location);
  696. cg.a_label(current_asmdata.CurrAsmList,hlabel);
  697. end;
  698. {$ifdef cpuflags}
  699. LOC_FLAGS :
  700. begin
  701. {This can be a wordbool or longbool too, no?}
  702. case left.location.loc of
  703. LOC_REGISTER,LOC_CREGISTER:
  704. cg.g_flags2reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),right.location.resflags,left.location.register);
  705. LOC_REFERENCE:
  706. cg.g_flags2ref(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),right.location.resflags,left.location.reference);
  707. LOC_SUBSETREG,LOC_SUBSETREF:
  708. begin
  709. r:=cg.getintregister(current_asmdata.CurrAsmList,def_cgsize(left.resultdef));
  710. cg.g_flags2reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),right.location.resflags,r);
  711. cg.a_load_reg_loc(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),r,left.location);
  712. end;
  713. else
  714. internalerror(200203273);
  715. end;
  716. end;
  717. {$endif cpuflags}
  718. end;
  719. end;
  720. if releaseright then
  721. location_freetemp(current_asmdata.CurrAsmList,right.location);
  722. current_procinfo.CurrTrueLabel:=otlabel;
  723. current_procinfo.CurrFalseLabel:=oflabel;
  724. end;
  725. {*****************************************************************************
  726. SecondArrayConstruct
  727. *****************************************************************************}
  728. const
  729. vtInteger = 0;
  730. vtBoolean = 1;
  731. vtChar = 2;
  732. vtExtended = 3;
  733. vtString = 4;
  734. vtPointer = 5;
  735. vtPChar = 6;
  736. vtObject = 7;
  737. vtClass = 8;
  738. vtWideChar = 9;
  739. vtPWideChar = 10;
  740. vtAnsiString32 = 11;
  741. vtCurrency = 12;
  742. vtVariant = 13;
  743. vtInterface = 14;
  744. vtWideString = 15;
  745. vtInt64 = 16;
  746. vtQWord = 17;
  747. vtAnsiString16 = 18;
  748. vtAnsiString64 = 19;
  749. procedure tcgarrayconstructornode.pass_generate_code;
  750. var
  751. hp : tarrayconstructornode;
  752. href : treference;
  753. lt : tdef;
  754. vaddr : boolean;
  755. vtype : longint;
  756. freetemp,
  757. dovariant : boolean;
  758. elesize : longint;
  759. tmpreg : tregister;
  760. paraloc : tcgparalocation;
  761. otlabel,
  762. oflabel : tasmlabel;
  763. begin
  764. if is_packed_array(resultdef) then
  765. internalerror(200608042);
  766. dovariant:=(nf_forcevaria in flags) or is_variant_array(resultdef);
  767. if dovariant then
  768. elesize:=sizeof(aint)+sizeof(aint)
  769. else
  770. elesize:=tarraydef(resultdef).elesize;
  771. location_reset(location,LOC_CREFERENCE,OS_NO);
  772. fillchar(paraloc,sizeof(paraloc),0);
  773. { Allocate always a temp, also if no elements are required, to
  774. be sure that location is valid (PFV) }
  775. if tarraydef(resultdef).highrange=-1 then
  776. tg.GetTemp(current_asmdata.CurrAsmList,elesize,tt_normal,location.reference)
  777. else
  778. tg.GetTemp(current_asmdata.CurrAsmList,(tarraydef(resultdef).highrange+1)*elesize,tt_normal,location.reference);
  779. href:=location.reference;
  780. { Process nodes in array constructor }
  781. hp:=self;
  782. while assigned(hp) do
  783. begin
  784. if assigned(hp.left) then
  785. begin
  786. freetemp:=true;
  787. if (hp.left.expectloc=LOC_JUMP) then
  788. begin
  789. otlabel:=current_procinfo.CurrTrueLabel;
  790. oflabel:=current_procinfo.CurrFalseLabel;
  791. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  792. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  793. end;
  794. secondpass(hp.left);
  795. { Move flags and jump in register }
  796. if hp.left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  797. location_force_reg(current_asmdata.CurrAsmList,hp.left.location,def_cgsize(hp.left.resultdef),false);
  798. if (hp.left.location.loc=LOC_JUMP) then
  799. begin
  800. if (hp.left.expectloc<>LOC_JUMP) then
  801. internalerror(2007103101);
  802. current_procinfo.CurrTrueLabel:=otlabel;
  803. current_procinfo.CurrFalseLabel:=oflabel;
  804. end;
  805. if dovariant then
  806. begin
  807. { find the correct vtype value }
  808. vtype:=$ff;
  809. vaddr:=false;
  810. lt:=hp.left.resultdef;
  811. case lt.typ of
  812. enumdef,
  813. orddef :
  814. begin
  815. if is_64bit(lt) then
  816. begin
  817. case torddef(lt).ordtype of
  818. scurrency:
  819. vtype:=vtCurrency;
  820. s64bit:
  821. vtype:=vtInt64;
  822. u64bit:
  823. vtype:=vtQWord;
  824. end;
  825. freetemp:=false;
  826. vaddr:=true;
  827. end
  828. else if (lt.typ=enumdef) or
  829. is_integer(lt) then
  830. vtype:=vtInteger
  831. else
  832. if is_boolean(lt) then
  833. vtype:=vtBoolean
  834. else
  835. if (lt.typ=orddef) then
  836. begin
  837. case torddef(lt).ordtype of
  838. uchar:
  839. vtype:=vtChar;
  840. uwidechar:
  841. vtype:=vtWideChar;
  842. end;
  843. end;
  844. end;
  845. floatdef :
  846. begin
  847. if is_currency(lt) then
  848. vtype:=vtCurrency
  849. else
  850. vtype:=vtExtended;
  851. freetemp:=false;
  852. vaddr:=true;
  853. end;
  854. procvardef,
  855. pointerdef :
  856. begin
  857. if is_pchar(lt) then
  858. vtype:=vtPChar
  859. else if is_pwidechar(lt) then
  860. vtype:=vtPWideChar
  861. else
  862. vtype:=vtPointer;
  863. end;
  864. variantdef :
  865. begin
  866. vtype:=vtVariant;
  867. vaddr:=true;
  868. freetemp:=false;
  869. end;
  870. classrefdef :
  871. vtype:=vtClass;
  872. objectdef :
  873. if is_interface(lt) then
  874. vtype:=vtInterface
  875. { vtObject really means a class based on TObject }
  876. else if is_class(lt) then
  877. vtype:=vtObject
  878. else
  879. internalerror(200505171);
  880. stringdef :
  881. begin
  882. if is_shortstring(lt) then
  883. begin
  884. vtype:=vtString;
  885. vaddr:=true;
  886. freetemp:=false;
  887. end
  888. else
  889. if is_ansistring(lt) then
  890. begin
  891. vtype:=vtAnsiString;
  892. freetemp:=false;
  893. end
  894. else
  895. if is_widestring(lt) then
  896. begin
  897. vtype:=vtWideString;
  898. freetemp:=false;
  899. end;
  900. end;
  901. end;
  902. if vtype=$ff then
  903. internalerror(14357);
  904. { write changing field update href to the next element }
  905. inc(href.offset,sizeof(aint));
  906. if vaddr then
  907. begin
  908. location_force_mem(current_asmdata.CurrAsmList,hp.left.location);
  909. tmpreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
  910. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,hp.left.location.reference,tmpreg);
  911. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,tmpreg,href);
  912. end
  913. else
  914. cg.a_load_loc_ref(current_asmdata.CurrAsmList,OS_ADDR,hp.left.location,href);
  915. { update href to the vtype field and write it }
  916. dec(href.offset,sizeof(aint));
  917. cg.a_load_const_ref(current_asmdata.CurrAsmList, OS_INT,vtype,href);
  918. { goto next array element }
  919. inc(href.offset,sizeof(aint)*2);
  920. end
  921. else
  922. { normal array constructor of the same type }
  923. begin
  924. if resultdef.needs_inittable then
  925. freetemp:=false;
  926. case hp.left.location.loc of
  927. LOC_MMREGISTER,
  928. LOC_CMMREGISTER:
  929. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location.size,
  930. hp.left.location.register,href,mms_movescalar);
  931. LOC_FPUREGISTER,
  932. LOC_CFPUREGISTER :
  933. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location.size,hp.left.location.register,href);
  934. LOC_REFERENCE,
  935. LOC_CREFERENCE :
  936. begin
  937. if is_shortstring(hp.left.resultdef) then
  938. cg.g_copyshortstring(current_asmdata.CurrAsmList,hp.left.location.reference,href,
  939. Tstringdef(hp.left.resultdef).len)
  940. else
  941. cg.g_concatcopy(current_asmdata.CurrAsmList,hp.left.location.reference,href,elesize);
  942. end;
  943. else
  944. begin
  945. {$ifndef cpu64bit}
  946. if hp.left.location.size in [OS_64,OS_S64] then
  947. cg64.a_load64_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
  948. else
  949. {$endif cpu64bit}
  950. cg.a_load_loc_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location,href);
  951. end;
  952. end;
  953. inc(href.offset,elesize);
  954. end;
  955. if freetemp then
  956. location_freetemp(current_asmdata.CurrAsmList,hp.left.location);
  957. end;
  958. { load next entry }
  959. hp:=tarrayconstructornode(hp.right);
  960. end;
  961. end;
  962. {*****************************************************************************
  963. SecondRTTI
  964. *****************************************************************************}
  965. procedure tcgrttinode.pass_generate_code;
  966. begin
  967. location_reset(location,LOC_CREFERENCE,OS_NO);
  968. location.reference.symbol:=RTTIWriter.get_rtti_label(rttidef,rttitype);
  969. end;
  970. begin
  971. cloadnode:=tcgloadnode;
  972. cassignmentnode:=tcgassignmentnode;
  973. carrayconstructornode:=tcgarrayconstructornode;
  974. crttinode:=tcgrttinode;
  975. end.