ncgld.pas 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028
  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. location.reference.symbol:=tcglabelnode((tlabelsym(symtableentry).code)).getasmlabel;
  329. else internalerror(200510032);
  330. end;
  331. end;
  332. {*****************************************************************************
  333. SecondAssignment
  334. *****************************************************************************}
  335. procedure tcgassignmentnode.pass_generate_code;
  336. var
  337. otlabel,hlabel,oflabel : tasmlabel;
  338. href : treference;
  339. releaseright : boolean;
  340. len : aint;
  341. r : tregister;
  342. oldflowcontrol : tflowcontrol;
  343. begin
  344. location_reset(location,LOC_VOID,OS_NO);
  345. otlabel:=current_procinfo.CurrTrueLabel;
  346. oflabel:=current_procinfo.CurrFalseLabel;
  347. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  348. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  349. {
  350. in most cases we can process first the right node which contains
  351. the most complex code. Exceptions for this are:
  352. - result is in flags, loading left will then destroy the flags
  353. - result is a jump, loading left must be already done before the jump is made
  354. - result need reference count, when left points to a value used in
  355. right then decreasing the refcnt on left can possibly release
  356. the memory before right increased the refcnt, result is that an
  357. empty value is assigned
  358. - calln, call destroys most registers and is therefor 'complex'
  359. But not when the result is in the flags, then
  360. loading the left node afterwards can destroy the flags.
  361. }
  362. if not(right.expectloc in [LOC_FLAGS,LOC_JUMP]) and
  363. ((right.nodetype=calln) or
  364. (right.resultdef.needs_inittable) or
  365. (right.registersint>=left.registersint)) then
  366. begin
  367. secondpass(right);
  368. { increment source reference counter, this is
  369. useless for constants }
  370. if (right.resultdef.needs_inittable) and
  371. not is_constnode(right) then
  372. begin
  373. location_force_mem(current_asmdata.CurrAsmList,right.location);
  374. location_get_data_ref(current_asmdata.CurrAsmList,right.location,href,false);
  375. cg.g_incrrefcount(current_asmdata.CurrAsmList,right.resultdef,href);
  376. end;
  377. if codegenerror then
  378. exit;
  379. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  380. { can be false }
  381. secondpass(left);
  382. { decrement destination reference counter }
  383. if (left.resultdef.needs_inittable) then
  384. begin
  385. location_get_data_ref(current_asmdata.CurrAsmList,left.location,href,false);
  386. cg.g_decrrefcount(current_asmdata.CurrAsmList,left.resultdef,href);
  387. end;
  388. if codegenerror then
  389. exit;
  390. end
  391. else
  392. begin
  393. { calculate left sides }
  394. secondpass(left);
  395. { decrement destination reference counter }
  396. if (left.resultdef.needs_inittable) then
  397. begin
  398. location_get_data_ref(current_asmdata.CurrAsmList,left.location,href,false);
  399. cg.g_decrrefcount(current_asmdata.CurrAsmList,left.resultdef,href);
  400. end;
  401. if codegenerror then
  402. exit;
  403. { tell the SSA/SSL code that the left side was handled first so
  404. ni SSL is done
  405. }
  406. oldflowcontrol:=flowcontrol;
  407. include(flowcontrol,fc_lefthandled);
  408. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  409. { can be false }
  410. secondpass(right);
  411. flowcontrol:=oldflowcontrol;
  412. { increment source reference counter, this is
  413. useless for string constants}
  414. if (right.resultdef.needs_inittable) and
  415. (right.nodetype<>stringconstn) then
  416. begin
  417. location_force_mem(current_asmdata.CurrAsmList,right.location);
  418. location_get_data_ref(current_asmdata.CurrAsmList,right.location,href,false);
  419. cg.g_incrrefcount(current_asmdata.CurrAsmList,right.resultdef,href);
  420. end;
  421. if codegenerror then
  422. exit;
  423. end;
  424. releaseright:=true;
  425. { optimize temp to temp copies }
  426. {$ifdef old_append_str}
  427. if (left.nodetype = temprefn) and
  428. { we may store certain temps in registers in the future, then this }
  429. { optimization will have to be adapted }
  430. (left.location.loc = LOC_REFERENCE) and
  431. (right.location.loc = LOC_REFERENCE) and
  432. tg.istemp(right.location.reference) and
  433. (tg.sizeoftemp(current_asmdata.CurrAsmList,right.location.reference) = tg.sizeoftemp(current_asmdata.CurrAsmList,left.location.reference)) then
  434. begin
  435. { in theory, we should also make sure the left temp type is }
  436. { already more or less of the same kind (ie. we must not }
  437. { assign an ansistring to a normaltemp). In practice, the }
  438. { assignment node will have already taken care of this for us }
  439. tcgtemprefnode(left).changelocation(right.location.reference);
  440. end
  441. { shortstring assignments are handled separately }
  442. else
  443. {$endif old_append_str}
  444. if is_shortstring(left.resultdef) then
  445. begin
  446. {
  447. we can get here only in the following situations
  448. for the right node:
  449. - empty constant string
  450. - char
  451. }
  452. { The addn is replaced by a blockn or calln that already returns
  453. a shortstring }
  454. if is_shortstring(right.resultdef) and
  455. (right.nodetype in [blockn,calln]) then
  456. begin
  457. { nothing to do }
  458. end
  459. { empty constant string }
  460. else if (right.nodetype=stringconstn) and
  461. (tstringconstnode(right).len=0) then
  462. begin
  463. cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_8,0,left.location.reference);
  464. end
  465. { char loading }
  466. else if is_char(right.resultdef) then
  467. begin
  468. if right.nodetype=ordconstn then
  469. begin
  470. if (target_info.endian = endian_little) then
  471. cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_16,(tordconstnode(right).value shl 8) or 1,
  472. setalignment(left.location.reference,1))
  473. else
  474. cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_16,tordconstnode(right).value or (1 shl 8),
  475. setalignment(left.location.reference,1));
  476. end
  477. else
  478. begin
  479. href:=left.location.reference;
  480. cg.a_load_const_ref(current_asmdata.CurrAsmList,OS_8,1,href);
  481. inc(href.offset,1);
  482. case right.location.loc of
  483. LOC_REGISTER,
  484. LOC_CREGISTER :
  485. begin
  486. r:=cg.makeregsize(current_asmdata.CurrAsmList,right.location.register,OS_8);
  487. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_8,OS_8,r,href);
  488. end;
  489. LOC_REFERENCE,
  490. LOC_CREFERENCE :
  491. cg.a_load_ref_ref(current_asmdata.CurrAsmList,OS_8,OS_8,right.location.reference,href);
  492. else
  493. internalerror(200205111);
  494. end;
  495. end;
  496. end
  497. else
  498. internalerror(200204249);
  499. end
  500. else
  501. begin
  502. { SSA support }
  503. maybechangeloadnodereg(current_asmdata.CurrAsmList,left,false);
  504. maybechangeloadnodereg(current_asmdata.CurrAsmList,right,true);
  505. case right.location.loc of
  506. LOC_CONSTANT :
  507. begin
  508. {$ifndef cpu64bit}
  509. if (left.location.size in [OS_64,OS_S64]) or (right.location.size in [OS_64,OS_S64]) then
  510. cg64.a_load64_const_loc(current_asmdata.CurrAsmList,right.location.value64,left.location)
  511. else
  512. {$endif cpu64bit}
  513. cg.a_load_const_loc(current_asmdata.CurrAsmList,right.location.value,left.location);
  514. end;
  515. LOC_REFERENCE,
  516. LOC_CREFERENCE :
  517. begin
  518. case left.location.loc of
  519. LOC_REGISTER,
  520. LOC_CREGISTER :
  521. begin
  522. {$ifndef cpu64bit}
  523. if left.location.size in [OS_64,OS_S64] then
  524. cg64.a_load64_ref_reg(current_asmdata.CurrAsmList,right.location.reference,left.location.register64)
  525. else
  526. {$endif cpu64bit}
  527. cg.a_load_ref_reg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.register);
  528. end;
  529. LOC_FPUREGISTER,
  530. LOC_CFPUREGISTER :
  531. begin
  532. cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,
  533. right.location.size,left.location.size,
  534. right.location.reference,
  535. left.location.register);
  536. end;
  537. LOC_REFERENCE,
  538. LOC_CREFERENCE :
  539. begin
  540. if (left.resultdef.typ=floatdef) and
  541. (right.resultdef.typ=floatdef) and
  542. (left.location.size<>right.location.size) then
  543. begin
  544. cg.a_loadfpu_ref_ref(current_asmdata.CurrAsmList,
  545. right.location.size,left.location.size,
  546. right.location.reference,left.location.reference)
  547. end
  548. else
  549. begin
  550. {$warning HACK: unaligned test, maybe remove all unaligned locations (array of char) from the compiler}
  551. { Use unaligned copy when the offset is not aligned }
  552. len:=left.resultdef.size;
  553. if (right.location.reference.offset mod sizeof(aint)<>0) or
  554. (left.location.reference.offset mod sizeof(aint)<>0) or
  555. (right.resultdef.alignment<sizeof(aint)) or
  556. ((right.location.reference.alignment<>0) and
  557. (right.location.reference.alignment<sizeof(aint))) or
  558. ((left.location.reference.alignment<>0) and
  559. (left.location.reference.alignment<sizeof(aint))) then
  560. cg.g_concatcopy_unaligned(current_asmdata.CurrAsmList,right.location.reference,left.location.reference,len)
  561. else
  562. cg.g_concatcopy(current_asmdata.CurrAsmList,right.location.reference,left.location.reference,len);
  563. end;
  564. end;
  565. LOC_MMREGISTER,
  566. LOC_CMMREGISTER:
  567. begin
  568. {$ifdef x86}
  569. if not use_sse(right.resultdef) then
  570. begin
  571. { perform size conversion if needed (the mm-code cannot }
  572. { convert an extended into a double/single, since sse }
  573. { doesn't support extended) }
  574. r:=cg.getfpuregister(current_asmdata.CurrAsmList,right.location.size);
  575. tg.gettemp(current_asmdata.CurrAsmList,left.resultdef.size,tt_normal,href);
  576. cg.a_loadfpu_ref_reg(current_asmdata.CurrAsmList,right.location.size,right.location.size,right.location.reference,r);
  577. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,r,href);
  578. if releaseright then
  579. location_freetemp(current_asmdata.CurrAsmList,right.location);
  580. releaseright:=true;
  581. location_reset(right.location,LOC_REFERENCE,left.location.size);
  582. right.location.reference:=href;
  583. end;
  584. {$endif}
  585. cg.a_loadmm_ref_reg(current_asmdata.CurrAsmList,
  586. right.location.size,
  587. left.location.size,
  588. right.location.reference,
  589. left.location.register,mms_movescalar);
  590. end;
  591. LOC_SUBSETREG,
  592. LOC_CSUBSETREG:
  593. cg.a_load_ref_subsetreg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.sreg);
  594. LOC_SUBSETREF,
  595. LOC_CSUBSETREF:
  596. {$ifndef cpu64bit}
  597. if right.location.size in [OS_64,OS_S64] then
  598. cg64.a_load64_ref_subsetref(current_asmdata.CurrAsmList,right.location.reference,left.location.sref)
  599. else
  600. {$endif cpu64bit}
  601. cg.a_load_ref_subsetref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.reference,left.location.sref);
  602. else
  603. internalerror(200203284);
  604. end;
  605. end;
  606. {$ifdef SUPPORT_MMX}
  607. LOC_CMMXREGISTER,
  608. LOC_MMXREGISTER:
  609. begin
  610. if left.location.loc=LOC_CMMXREGISTER then
  611. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.register,nil)
  612. else
  613. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,OS_M64,OS_M64,right.location.register,left.location.reference,nil);
  614. end;
  615. {$endif SUPPORT_MMX}
  616. LOC_MMREGISTER,
  617. LOC_CMMREGISTER:
  618. begin
  619. if left.resultdef.typ=arraydef then
  620. begin
  621. end
  622. else
  623. begin
  624. if left.location.loc=LOC_CMMREGISTER then
  625. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,left.location.register,mms_movescalar)
  626. else
  627. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,left.location.reference,mms_movescalar);
  628. end;
  629. end;
  630. LOC_REGISTER,
  631. LOC_CREGISTER :
  632. begin
  633. {$ifndef cpu64bit}
  634. if left.location.size in [OS_64,OS_S64] then
  635. cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,
  636. right.location.register64,left.location)
  637. else
  638. {$endif cpu64bit}
  639. cg.a_load_reg_loc(current_asmdata.CurrAsmList,right.location.size,right.location.register,left.location);
  640. end;
  641. LOC_FPUREGISTER,
  642. LOC_CFPUREGISTER :
  643. begin
  644. { we can't do direct moves between fpu and mm registers }
  645. if left.location.loc in [LOC_MMREGISTER,LOC_CMMREGISTER] then
  646. begin
  647. {$ifdef x86}
  648. if not use_sse(right.resultdef) then
  649. begin
  650. { perform size conversion if needed (the mm-code cannot convert an }
  651. { extended into a double/single, since sse doesn't support extended) }
  652. tg.gettemp(current_asmdata.CurrAsmList,left.resultdef.size,tt_normal,href);
  653. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,right.location.size,left.location.size,right.location.register,href);
  654. location_reset(right.location,LOC_REFERENCE,left.location.size);
  655. right.location.reference:=href;
  656. end;
  657. {$endif}
  658. location_force_mmregscalar(current_asmdata.CurrAsmList,right.location,false);
  659. cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,
  660. right.location.size,left.location.size,
  661. right.location.register,left.location.register,mms_movescalar);
  662. end
  663. else
  664. cg.a_loadfpu_reg_loc(current_asmdata.CurrAsmList,
  665. right.location.size,
  666. right.location.register,left.location);
  667. end;
  668. LOC_SUBSETREG,
  669. LOC_CSUBSETREG:
  670. begin
  671. cg.a_load_subsetreg_loc(current_asmdata.CurrAsmList,
  672. right.location.size,right.location.sreg,left.location);
  673. end;
  674. LOC_SUBSETREF,
  675. LOC_CSUBSETREF:
  676. begin
  677. {$ifndef cpu64bit}
  678. if right.location.size in [OS_64,OS_S64] then
  679. cg64.a_load64_subsetref_loc(current_asmdata.CurrAsmList,right.location.sref,left.location)
  680. else
  681. {$endif cpu64bit}
  682. cg.a_load_subsetref_loc(current_asmdata.CurrAsmList,
  683. right.location.size,right.location.sref,left.location);
  684. end;
  685. LOC_JUMP :
  686. begin
  687. current_asmdata.getjumplabel(hlabel);
  688. cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrTrueLabel);
  689. cg.a_load_const_loc(current_asmdata.CurrAsmList,1,left.location);
  690. cg.a_jmp_always(current_asmdata.CurrAsmList,hlabel);
  691. cg.a_label(current_asmdata.CurrAsmList,current_procinfo.CurrFalseLabel);
  692. cg.a_load_const_loc(current_asmdata.CurrAsmList,0,left.location);
  693. cg.a_label(current_asmdata.CurrAsmList,hlabel);
  694. end;
  695. {$ifdef cpuflags}
  696. LOC_FLAGS :
  697. begin
  698. {This can be a wordbool or longbool too, no?}
  699. case left.location.loc of
  700. LOC_REGISTER,LOC_CREGISTER:
  701. cg.g_flags2reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),right.location.resflags,left.location.register);
  702. LOC_REFERENCE:
  703. cg.g_flags2ref(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),right.location.resflags,left.location.reference);
  704. LOC_SUBSETREG,LOC_SUBSETREF:
  705. begin
  706. r:=cg.getintregister(current_asmdata.CurrAsmList,def_cgsize(left.resultdef));
  707. cg.g_flags2reg(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),right.location.resflags,r);
  708. cg.a_load_reg_loc(current_asmdata.CurrAsmList,def_cgsize(left.resultdef),r,left.location);
  709. end;
  710. else
  711. internalerror(200203273);
  712. end;
  713. end;
  714. {$endif cpuflags}
  715. end;
  716. end;
  717. if releaseright then
  718. location_freetemp(current_asmdata.CurrAsmList,right.location);
  719. current_procinfo.CurrTrueLabel:=otlabel;
  720. current_procinfo.CurrFalseLabel:=oflabel;
  721. end;
  722. {*****************************************************************************
  723. SecondArrayConstruct
  724. *****************************************************************************}
  725. const
  726. vtInteger = 0;
  727. vtBoolean = 1;
  728. vtChar = 2;
  729. vtExtended = 3;
  730. vtString = 4;
  731. vtPointer = 5;
  732. vtPChar = 6;
  733. vtObject = 7;
  734. vtClass = 8;
  735. vtWideChar = 9;
  736. vtPWideChar = 10;
  737. vtAnsiString32 = 11;
  738. vtCurrency = 12;
  739. vtVariant = 13;
  740. vtInterface = 14;
  741. vtWideString = 15;
  742. vtInt64 = 16;
  743. vtQWord = 17;
  744. vtAnsiString16 = 18;
  745. vtAnsiString64 = 19;
  746. procedure tcgarrayconstructornode.pass_generate_code;
  747. var
  748. hp : tarrayconstructornode;
  749. href : treference;
  750. lt : tdef;
  751. vaddr : boolean;
  752. vtype : longint;
  753. freetemp,
  754. dovariant : boolean;
  755. elesize : longint;
  756. tmpreg : tregister;
  757. paraloc : tcgparalocation;
  758. otlabel,
  759. oflabel : tasmlabel;
  760. begin
  761. if is_packed_array(resultdef) then
  762. internalerror(200608042);
  763. dovariant:=(nf_forcevaria in flags) or is_variant_array(resultdef);
  764. if dovariant then
  765. elesize:=sizeof(aint)+sizeof(aint)
  766. else
  767. elesize:=tarraydef(resultdef).elesize;
  768. location_reset(location,LOC_CREFERENCE,OS_NO);
  769. fillchar(paraloc,sizeof(paraloc),0);
  770. { Allocate always a temp, also if no elements are required, to
  771. be sure that location is valid (PFV) }
  772. if tarraydef(resultdef).highrange=-1 then
  773. tg.GetTemp(current_asmdata.CurrAsmList,elesize,tt_normal,location.reference)
  774. else
  775. tg.GetTemp(current_asmdata.CurrAsmList,(tarraydef(resultdef).highrange+1)*elesize,tt_normal,location.reference);
  776. href:=location.reference;
  777. { Process nodes in array constructor }
  778. hp:=self;
  779. while assigned(hp) do
  780. begin
  781. if assigned(hp.left) then
  782. begin
  783. freetemp:=true;
  784. if (hp.left.expectloc=LOC_JUMP) then
  785. begin
  786. otlabel:=current_procinfo.CurrTrueLabel;
  787. oflabel:=current_procinfo.CurrFalseLabel;
  788. current_asmdata.getjumplabel(current_procinfo.CurrTrueLabel);
  789. current_asmdata.getjumplabel(current_procinfo.CurrFalseLabel);
  790. end;
  791. secondpass(hp.left);
  792. { Move flags and jump in register }
  793. if hp.left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  794. location_force_reg(current_asmdata.CurrAsmList,hp.left.location,def_cgsize(hp.left.resultdef),false);
  795. if (hp.left.location.loc=LOC_JUMP) then
  796. begin
  797. if (hp.left.expectloc<>LOC_JUMP) then
  798. internalerror(2007103101);
  799. current_procinfo.CurrTrueLabel:=otlabel;
  800. current_procinfo.CurrFalseLabel:=oflabel;
  801. end;
  802. if dovariant then
  803. begin
  804. { find the correct vtype value }
  805. vtype:=$ff;
  806. vaddr:=false;
  807. lt:=hp.left.resultdef;
  808. case lt.typ of
  809. enumdef,
  810. orddef :
  811. begin
  812. if is_64bit(lt) then
  813. begin
  814. case torddef(lt).ordtype of
  815. scurrency:
  816. vtype:=vtCurrency;
  817. s64bit:
  818. vtype:=vtInt64;
  819. u64bit:
  820. vtype:=vtQWord;
  821. end;
  822. freetemp:=false;
  823. vaddr:=true;
  824. end
  825. else if (lt.typ=enumdef) or
  826. is_integer(lt) then
  827. vtype:=vtInteger
  828. else
  829. if is_boolean(lt) then
  830. vtype:=vtBoolean
  831. else
  832. if (lt.typ=orddef) then
  833. begin
  834. case torddef(lt).ordtype of
  835. uchar:
  836. vtype:=vtChar;
  837. uwidechar:
  838. vtype:=vtWideChar;
  839. end;
  840. end;
  841. end;
  842. floatdef :
  843. begin
  844. if is_currency(lt) then
  845. vtype:=vtCurrency
  846. else
  847. vtype:=vtExtended;
  848. freetemp:=false;
  849. vaddr:=true;
  850. end;
  851. procvardef,
  852. pointerdef :
  853. begin
  854. if is_pchar(lt) then
  855. vtype:=vtPChar
  856. else if is_pwidechar(lt) then
  857. vtype:=vtPWideChar
  858. else
  859. vtype:=vtPointer;
  860. end;
  861. variantdef :
  862. begin
  863. vtype:=vtVariant;
  864. vaddr:=true;
  865. freetemp:=false;
  866. end;
  867. classrefdef :
  868. vtype:=vtClass;
  869. objectdef :
  870. if is_interface(lt) then
  871. vtype:=vtInterface
  872. { vtObject really means a class based on TObject }
  873. else if is_class(lt) then
  874. vtype:=vtObject
  875. else
  876. internalerror(200505171);
  877. stringdef :
  878. begin
  879. if is_shortstring(lt) then
  880. begin
  881. vtype:=vtString;
  882. vaddr:=true;
  883. freetemp:=false;
  884. end
  885. else
  886. if is_ansistring(lt) then
  887. begin
  888. vtype:=vtAnsiString;
  889. freetemp:=false;
  890. end
  891. else
  892. if is_widestring(lt) then
  893. begin
  894. vtype:=vtWideString;
  895. freetemp:=false;
  896. end;
  897. end;
  898. end;
  899. if vtype=$ff then
  900. internalerror(14357);
  901. { write changing field update href to the next element }
  902. inc(href.offset,sizeof(aint));
  903. if vaddr then
  904. begin
  905. location_force_mem(current_asmdata.CurrAsmList,hp.left.location);
  906. tmpreg:=cg.getaddressregister(current_asmdata.CurrAsmList);
  907. cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,hp.left.location.reference,tmpreg);
  908. cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,tmpreg,href);
  909. end
  910. else
  911. cg.a_load_loc_ref(current_asmdata.CurrAsmList,OS_ADDR,hp.left.location,href);
  912. { update href to the vtype field and write it }
  913. dec(href.offset,sizeof(aint));
  914. cg.a_load_const_ref(current_asmdata.CurrAsmList, OS_INT,vtype,href);
  915. { goto next array element }
  916. inc(href.offset,sizeof(aint)*2);
  917. end
  918. else
  919. { normal array constructor of the same type }
  920. begin
  921. if resultdef.needs_inittable then
  922. freetemp:=false;
  923. case hp.left.location.loc of
  924. LOC_MMREGISTER,
  925. LOC_CMMREGISTER:
  926. cg.a_loadmm_reg_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location.size,
  927. hp.left.location.register,href,mms_movescalar);
  928. LOC_FPUREGISTER,
  929. LOC_CFPUREGISTER :
  930. cg.a_loadfpu_reg_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location.size,hp.left.location.register,href);
  931. LOC_REFERENCE,
  932. LOC_CREFERENCE :
  933. begin
  934. if is_shortstring(hp.left.resultdef) then
  935. cg.g_copyshortstring(current_asmdata.CurrAsmList,hp.left.location.reference,href,
  936. Tstringdef(hp.left.resultdef).len)
  937. else
  938. cg.g_concatcopy(current_asmdata.CurrAsmList,hp.left.location.reference,href,elesize);
  939. end;
  940. else
  941. begin
  942. {$ifndef cpu64bit}
  943. if hp.left.location.size in [OS_64,OS_S64] then
  944. cg64.a_load64_loc_ref(current_asmdata.CurrAsmList,hp.left.location,href)
  945. else
  946. {$endif cpu64bit}
  947. cg.a_load_loc_ref(current_asmdata.CurrAsmList,hp.left.location.size,hp.left.location,href);
  948. end;
  949. end;
  950. inc(href.offset,elesize);
  951. end;
  952. if freetemp then
  953. location_freetemp(current_asmdata.CurrAsmList,hp.left.location);
  954. end;
  955. { load next entry }
  956. hp:=tarrayconstructornode(hp.right);
  957. end;
  958. end;
  959. {*****************************************************************************
  960. SecondRTTI
  961. *****************************************************************************}
  962. procedure tcgrttinode.pass_generate_code;
  963. begin
  964. location_reset(location,LOC_CREFERENCE,OS_NO);
  965. location.reference.symbol:=RTTIWriter.get_rtti_label(rttidef,rttitype);
  966. end;
  967. begin
  968. cloadnode:=tcgloadnode;
  969. cassignmentnode:=tcgassignmentnode;
  970. carrayconstructornode:=tcgarrayconstructornode;
  971. crttinode:=tcgrttinode;
  972. end.