ncgld.pas 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. Generate assembler for nodes that handle loads and assignments which
  5. are the same for all (most) processors
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit ncgld;
  20. {$i fpcdefs.inc}
  21. interface
  22. uses
  23. node,nld;
  24. type
  25. tcgloadnode = class(tloadnode)
  26. procedure pass_2;override;
  27. procedure generate_picvaraccess;virtual;
  28. end;
  29. tcgassignmentnode = class(tassignmentnode)
  30. procedure pass_2;override;
  31. end;
  32. tcgarrayconstructornode = class(tarrayconstructornode)
  33. procedure pass_2;override;
  34. end;
  35. implementation
  36. uses
  37. cutils,
  38. systems,
  39. verbose,globtype,globals,
  40. symconst,symtype,symdef,symsym,defutil,paramgr,
  41. ncnv,ncon,nmem,nbas,
  42. aasmbase,aasmtai,aasmcpu,
  43. cgbase,pass_2,
  44. procinfo,
  45. cpubase,parabase,
  46. tgobj,ncgutil,
  47. cgutils,cgobj,
  48. ncgbas;
  49. {*****************************************************************************
  50. SecondLoad
  51. *****************************************************************************}
  52. procedure tcgloadnode.generate_picvaraccess;
  53. begin
  54. location.reference.base:=current_procinfo.got;
  55. location.reference.symbol:=objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname+'@GOT',AB_EXTERNAL,AT_DATA);
  56. end;
  57. procedure tcgloadnode.pass_2;
  58. var
  59. hregister : tregister;
  60. symtabletype : tsymtabletype;
  61. href : treference;
  62. newsize : tcgsize;
  63. endrelocatelab,
  64. norelocatelab : tasmlabel;
  65. paraloc1 : tcgpara;
  66. begin
  67. { we don't know the size of all arrays }
  68. newsize:=def_cgsize(resulttype.def);
  69. location_reset(location,LOC_REFERENCE,newsize);
  70. case symtableentry.typ of
  71. absolutesym :
  72. begin
  73. { this is only for toasm and toaddr }
  74. case tabsolutesym(symtableentry).abstyp of
  75. toaddr :
  76. begin
  77. {$ifdef i386}
  78. if tabsolutesym(symtableentry).absseg then
  79. location.reference.segment:=NR_FS;
  80. {$endif i386}
  81. location.reference.offset:=tabsolutesym(symtableentry).fieldoffset;
  82. end;
  83. toasm :
  84. location.reference.symbol:=objectlibrary.newasmsymbol(tabsolutesym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA);
  85. else
  86. internalerror(200310283);
  87. end;
  88. end;
  89. constsym:
  90. begin
  91. if tconstsym(symtableentry).consttyp=constresourcestring then
  92. begin
  93. location_reset(location,LOC_CREFERENCE,OS_ADDR);
  94. location.reference.symbol:=objectlibrary.newasmsymbol(make_mangledname('RESOURCESTRINGLIST',tconstsym(symtableentry).owner,''),AB_EXTERNAL,AT_DATA);
  95. location.reference.offset:=tconstsym(symtableentry).resstrindex*(4+sizeof(aint)*3)+4+sizeof(aint);
  96. end
  97. else
  98. internalerror(22798);
  99. end;
  100. varsym :
  101. begin
  102. symtabletype:=symtable.symtabletype;
  103. hregister:=NR_NO;
  104. { DLL variable }
  105. if (vo_is_dll_var in tvarsym(symtableentry).varoptions) then
  106. begin
  107. if target_info.system=system_powerpc_darwin then
  108. begin
  109. generate_picvaraccess;
  110. if not(pi_needs_got in current_procinfo.flags) then
  111. internalerror(200403022);
  112. end
  113. else
  114. begin
  115. hregister:=cg.getaddressregister(exprasmlist);
  116. location.reference.symbol:=objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA);
  117. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,location.reference,hregister);
  118. reference_reset_base(location.reference,hregister,0);
  119. end;
  120. end
  121. { Thread variable }
  122. else if (vo_is_thread_var in tvarsym(symtableentry).varoptions) then
  123. begin
  124. {
  125. Thread var loading is optimized to first check if
  126. a relocate function is available. When the function
  127. is available it is called to retrieve the address.
  128. Otherwise the address is loaded with the symbol
  129. The code needs to be in the order to first handle the
  130. call and then the address load to be sure that the
  131. register that is used for returning is the same (PFV)
  132. }
  133. objectlibrary.getlabel(norelocatelab);
  134. objectlibrary.getlabel(endrelocatelab);
  135. { make sure hregister can't allocate the register necessary for the parameter }
  136. paraloc1.init;
  137. paramanager.getintparaloc(pocall_default,1,paraloc1);
  138. hregister:=cg.getaddressregister(exprasmlist);
  139. reference_reset_symbol(href,objectlibrary.newasmsymbol('FPC_THREADVAR_RELOCATE',AB_EXTERNAL,AT_DATA),0);
  140. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
  141. cg.a_cmp_const_reg_label(exprasmlist,OS_ADDR,OC_EQ,0,hregister,norelocatelab);
  142. { don't save the allocated register else the result will be destroyed later }
  143. reference_reset_symbol(href,objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA),0);
  144. paramanager.allocparaloc(exprasmlist,paraloc1);
  145. cg.a_param_ref(exprasmlist,OS_ADDR,href,paraloc1);
  146. paramanager.freeparaloc(exprasmlist,paraloc1);
  147. paraloc1.done;
  148. cg.alloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  149. cg.a_call_reg(exprasmlist,hregister);
  150. cg.dealloccpuregisters(exprasmlist,R_INTREGISTER,paramanager.get_volatile_registers_int(pocall_default));
  151. cg.getcpuregister(exprasmlist,NR_FUNCTION_RESULT_REG);
  152. cg.ungetcpuregister(exprasmlist,NR_FUNCTION_RESULT_REG);
  153. hregister:=cg.getaddressregister(exprasmlist);
  154. cg.a_load_reg_reg(exprasmlist,OS_INT,OS_ADDR,NR_FUNCTION_RESULT_REG,hregister);
  155. cg.a_jmp_always(exprasmlist,endrelocatelab);
  156. cg.a_label(exprasmlist,norelocatelab);
  157. { no relocation needed, load the address of the variable only, the
  158. layout of a threadvar is (4 bytes pointer):
  159. 0 - Threadvar index
  160. 4 - Threadvar value in single threading }
  161. reference_reset_symbol(href,objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA),sizeof(aint));
  162. cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
  163. cg.a_label(exprasmlist,endrelocatelab);
  164. location.reference.base:=hregister;
  165. end
  166. { Nested variable }
  167. else if assigned(left) then
  168. begin
  169. if not(symtabletype in [localsymtable,parasymtable]) then
  170. internalerror(200309285);
  171. secondpass(left);
  172. if left.location.loc<>LOC_REGISTER then
  173. internalerror(200309286);
  174. if tvarsym(symtableentry).localloc.loc<>LOC_REFERENCE then
  175. internalerror(200409241);
  176. hregister:=left.location.register;
  177. reference_reset_base(location.reference,hregister,tvarsym(symtableentry).localloc.reference.offset);
  178. end
  179. { Normal (or external) variable }
  180. else
  181. begin
  182. {$ifdef OLDREGVARS}
  183. { in case it is a register variable: }
  184. if tvarsym(symtableentry).localloc.loc in [LOC_REGISTER,LOC_FPUREGISTER] then
  185. begin
  186. case getregtype(tvarsym(symtableentry).localloc.register) of
  187. R_FPUREGISTER :
  188. begin
  189. location_reset(location,LOC_CFPUREGISTER,def_cgsize(resulttype.def));
  190. location.register:=tvarsym(symtableentry).localloc.register;
  191. end;
  192. R_INTREGISTER :
  193. begin
  194. location_reset(location,LOC_CREGISTER,def_cgsize(resulttype.def));
  195. location.register:=tvarsym(symtableentry).localloc.register;
  196. hregister := location.register;
  197. end;
  198. else
  199. internalerror(200301172);
  200. end;
  201. end
  202. else
  203. {$endif OLDREGVARS}
  204. begin
  205. case symtabletype of
  206. stt_exceptsymtable,
  207. localsymtable,
  208. parasymtable :
  209. location:=tvarsym(symtableentry).localloc;
  210. globalsymtable,
  211. staticsymtable :
  212. begin
  213. if cs_create_pic in aktmoduleswitches then
  214. begin
  215. generate_picvaraccess;
  216. if not(pi_needs_got in current_procinfo.flags) then
  217. internalerror(200403023);
  218. end
  219. else
  220. begin
  221. if tvarsym(symtableentry).localloc.loc=LOC_INVALID then
  222. reference_reset_symbol(location.reference,objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA),0)
  223. else
  224. location:=tvarsym(symtableentry).localloc;
  225. end;
  226. end;
  227. else
  228. internalerror(200305102);
  229. end;
  230. end;
  231. end;
  232. { handle call by reference variables when they are not
  233. alreayd copied to local copies. Also ignore the reference
  234. when we need to load the self pointer for objects }
  235. if is_addr_param_load then
  236. begin
  237. if (location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
  238. hregister:=location.register
  239. else
  240. begin
  241. hregister:=cg.getaddressregister(exprasmlist);
  242. { we need to load only an address }
  243. location.size:=OS_ADDR;
  244. cg.a_load_loc_reg(exprasmlist,location.size,location,hregister);
  245. end;
  246. location_reset(location,LOC_REFERENCE,newsize);
  247. location.reference.base:=hregister;
  248. end;
  249. { make const a LOC_CREFERENCE }
  250. if (tvarsym(symtableentry).varspez=vs_const) and
  251. (location.loc=LOC_REFERENCE) then
  252. location.loc:=LOC_CREFERENCE;
  253. end;
  254. procsym:
  255. begin
  256. if not assigned(procdef) then
  257. internalerror(200312011);
  258. if assigned(left) then
  259. begin
  260. {
  261. THIS IS A TERRIBLE HACK!!!!!! WHICH WILL NOT WORK
  262. ON 64-BIT SYSTEMS: SINCE PROCSYM FOR METHODS
  263. CONSISTS OF TWO OS_ADDR, so you cannot set it
  264. to OS_64 - how to solve?? Carl
  265. Solved. Florian
  266. }
  267. if (sizeof(aint) = 4) then
  268. location_reset(location,LOC_CREFERENCE,OS_64)
  269. else if (sizeof(aint) = 8) then
  270. location_reset(location,LOC_CREFERENCE,OS_128)
  271. else
  272. internalerror(20020520);
  273. tg.GetTemp(exprasmlist,2*sizeof(aint),tt_normal,location.reference);
  274. secondpass(left);
  275. { load class instance address }
  276. case left.location.loc of
  277. LOC_CREGISTER,
  278. LOC_REGISTER:
  279. begin
  280. { this is not possible for objects }
  281. if is_object(left.resulttype.def) then
  282. internalerror(200304234);
  283. hregister:=left.location.register;
  284. end;
  285. LOC_CREFERENCE,
  286. LOC_REFERENCE:
  287. begin
  288. hregister:=cg.getaddressregister(exprasmlist);
  289. if is_class_or_interface(left.resulttype.def) then
  290. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.reference,hregister)
  291. else
  292. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,hregister);
  293. location_freetemp(exprasmlist,left.location);
  294. end;
  295. else
  296. internalerror(26019);
  297. end;
  298. { store the class instance address }
  299. href:=location.reference;
  300. inc(href.offset,sizeof(aint));
  301. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,href);
  302. { virtual method ? }
  303. if (po_virtualmethod in procdef.procoptions) then
  304. begin
  305. { load vmt pointer }
  306. reference_reset_base(href,hregister,0);
  307. hregister:=cg.getaddressregister(exprasmlist);
  308. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
  309. { load method address }
  310. reference_reset_base(href,hregister,procdef._class.vmtmethodoffset(procdef.extnumber));
  311. hregister:=cg.getaddressregister(exprasmlist);
  312. cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister);
  313. { ... and store it }
  314. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,location.reference);
  315. end
  316. else
  317. begin
  318. { load address of the function }
  319. reference_reset_symbol(href,objectlibrary.newasmsymbol(procdef.mangledname,AB_EXTERNAL,AT_FUNCTION),0);
  320. hregister:=cg.getaddressregister(exprasmlist);
  321. cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
  322. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,location.reference);
  323. end;
  324. end
  325. else
  326. begin
  327. {!!!!! Be aware, work on virtual methods too }
  328. location.reference.symbol:=objectlibrary.newasmsymbol(procdef.mangledname,AB_EXTERNAL,AT_FUNCTION);
  329. end;
  330. end;
  331. typedconstsym :
  332. begin
  333. location.reference.symbol:=objectlibrary.newasmsymbol(ttypedconstsym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA);
  334. end;
  335. else internalerror(4);
  336. end;
  337. end;
  338. {*****************************************************************************
  339. SecondAssignment
  340. *****************************************************************************}
  341. procedure tcgassignmentnode.pass_2;
  342. var
  343. otlabel,hlabel,oflabel : tasmlabel;
  344. fputyp : tfloattype;
  345. href : treference;
  346. old_allow_multi_pass2,
  347. releaseright : boolean;
  348. len : aint;
  349. cgsize : tcgsize;
  350. r:Tregister;
  351. begin
  352. location_reset(location,LOC_VOID,OS_NO);
  353. otlabel:=truelabel;
  354. oflabel:=falselabel;
  355. objectlibrary.getlabel(truelabel);
  356. objectlibrary.getlabel(falselabel);
  357. {
  358. in most cases we can process first the right node which contains
  359. the most complex code. Exceptions for this are:
  360. - result is in flags, loading left will then destroy the flags
  361. - result need reference count, when left points to a value used in
  362. right then decreasing the refcnt on left can possibly release
  363. the memory before right increased the refcnt, result is that an
  364. empty value is assigned
  365. - calln, call destroys most registers and is therefor 'complex'
  366. But not when the result is in the flags, then
  367. loading the left node afterwards can destroy the flags.
  368. when the right node returns as LOC_JUMP then we will generate
  369. the following code:
  370. rightnode
  371. true:
  372. leftnode
  373. assign 1
  374. false:
  375. leftnode
  376. assign 0
  377. }
  378. if (right.expectloc<>LOC_FLAGS) and
  379. ((right.expectloc=LOC_JUMP) or
  380. (right.nodetype=calln) or
  381. (right.resulttype.def.needs_inittable) or
  382. (right.registersint>=left.registersint)) then
  383. begin
  384. secondpass(right);
  385. { increment source reference counter, this is
  386. useless for string constants}
  387. if (right.resulttype.def.needs_inittable) and
  388. (right.nodetype<>stringconstn) then
  389. begin
  390. location_get_data_ref(exprasmlist,right.location,href,false);
  391. cg.g_incrrefcount(exprasmlist,right.resulttype.def,href);
  392. end;
  393. if codegenerror then
  394. exit;
  395. { We skip the generation of the left node when it's a jump, see
  396. explanation above }
  397. if (right.location.loc<>LOC_JUMP) and
  398. not(nf_concat_string in flags) then
  399. begin
  400. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  401. { can be false }
  402. secondpass(left);
  403. { decrement destination reference counter }
  404. if (left.resulttype.def.needs_inittable) then
  405. begin
  406. location_get_data_ref(exprasmlist,left.location,href,false);
  407. cg.g_decrrefcount(exprasmlist,left.resulttype.def,href);
  408. end;
  409. if codegenerror then
  410. exit;
  411. end;
  412. end
  413. else
  414. begin
  415. { calculate left sides }
  416. { don't do it yet if it's a crgister (JM) }
  417. if not(nf_concat_string in flags) then
  418. begin
  419. secondpass(left);
  420. { decrement destination reference counter }
  421. if (left.resulttype.def.needs_inittable) then
  422. begin
  423. location_get_data_ref(exprasmlist,left.location,href,false);
  424. cg.g_decrrefcount(exprasmlist,left.resulttype.def,href);
  425. end;
  426. if codegenerror then
  427. exit;
  428. end;
  429. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  430. { can be false }
  431. secondpass(right);
  432. { increment source reference counter, this is
  433. useless for string constants}
  434. if (right.resulttype.def.needs_inittable) and
  435. (right.nodetype<>stringconstn) then
  436. begin
  437. location_get_data_ref(exprasmlist,right.location,href,false);
  438. cg.g_incrrefcount(exprasmlist,right.resulttype.def,href);
  439. end;
  440. if codegenerror then
  441. exit;
  442. end;
  443. releaseright:=true;
  444. { optimize temp to temp copies }
  445. (* if (left.nodetype = temprefn) and
  446. { we may store certain temps in registers in the future, then this }
  447. { optimization will have to be adapted }
  448. (left.location.loc = LOC_REFERENCE) and
  449. (right.location.loc = LOC_REFERENCE) and
  450. tg.istemp(right.location.reference) and
  451. (tg.sizeoftemp(exprasmlist,right.location.reference) = tg.sizeoftemp(exprasmlist,left.location.reference)) then
  452. begin
  453. { in theory, we should also make sure the left temp type is }
  454. { already more or less of the same kind (ie. we must not }
  455. { assign an ansistring to a normaltemp). In practice, the }
  456. { assignment node will have already taken care of this for us }
  457. tcgtemprefnode(left).changelocation(right.location.reference);
  458. end
  459. { shortstring assignments are handled separately }
  460. else *) if is_shortstring(left.resulttype.def) then
  461. begin
  462. {
  463. we can get here only in the following situations
  464. for the right node:
  465. - empty constant string
  466. - char
  467. }
  468. { empty constant string }
  469. if (right.nodetype=stringconstn) and
  470. (tstringconstnode(right).len=0) then
  471. begin
  472. cg.a_load_const_ref(exprasmlist,OS_8,0,left.location.reference);
  473. end
  474. { char loading }
  475. else if is_char(right.resulttype.def) then
  476. begin
  477. if right.nodetype=ordconstn then
  478. begin
  479. if (target_info.endian = endian_little) then
  480. cg.a_load_const_ref(exprasmlist,OS_16,(tordconstnode(right).value shl 8) or 1,
  481. left.location.reference)
  482. else
  483. cg.a_load_const_ref(exprasmlist,OS_16,tordconstnode(right).value or (1 shl 8),
  484. left.location.reference);
  485. end
  486. else
  487. begin
  488. href:=left.location.reference;
  489. cg.a_load_const_ref(exprasmlist,OS_8,1,href);
  490. inc(href.offset,1);
  491. case right.location.loc of
  492. LOC_REGISTER,
  493. LOC_CREGISTER :
  494. begin
  495. r:=cg.makeregsize(exprasmlist,right.location.register,OS_8);
  496. cg.a_load_reg_ref(exprasmlist,OS_8,OS_8,r,href);
  497. end;
  498. LOC_REFERENCE,
  499. LOC_CREFERENCE :
  500. cg.a_load_ref_ref(exprasmlist,OS_8,OS_8,right.location.reference,href);
  501. else
  502. internalerror(200205111);
  503. end;
  504. end;
  505. end
  506. else
  507. internalerror(200204249);
  508. end
  509. else
  510. begin
  511. case right.location.loc of
  512. LOC_CONSTANT :
  513. begin
  514. {$ifndef cpu64bit}
  515. if right.location.size in [OS_64,OS_S64] then
  516. cg64.a_load64_const_loc(exprasmlist,right.location.value64,left.location)
  517. else
  518. {$endif cpu64bit}
  519. cg.a_load_const_loc(exprasmlist,right.location.value,left.location);
  520. end;
  521. LOC_REFERENCE,
  522. LOC_CREFERENCE :
  523. begin
  524. case left.location.loc of
  525. LOC_REGISTER,
  526. LOC_CREGISTER :
  527. begin
  528. cgsize:=def_cgsize(left.resulttype.def);
  529. {$ifndef cpu64bit}
  530. if cgsize in [OS_64,OS_S64] then
  531. cg64.a_load64_ref_reg(exprasmlist,right.location.reference,left.location.register64)
  532. else
  533. {$endif cpu64bit}
  534. cg.a_load_ref_reg(exprasmlist,cgsize,cgsize,right.location.reference,left.location.register);
  535. end;
  536. LOC_FPUREGISTER,
  537. LOC_CFPUREGISTER :
  538. begin
  539. cg.a_loadfpu_ref_reg(exprasmlist,
  540. def_cgsize(right.resulttype.def),
  541. right.location.reference,
  542. left.location.register);
  543. end;
  544. LOC_REFERENCE,
  545. LOC_CREFERENCE :
  546. begin
  547. {$warning HACK: unaligned test, maybe remove all unaligned locations (array of char) from the compiler}
  548. { Use unaligned copy when the offset is not aligned }
  549. len:=left.resulttype.def.size;
  550. if (right.location.reference.offset mod sizeof(aint)<>0) and
  551. (len>sizeof(aint)) then
  552. cg.g_concatcopy_unaligned(exprasmlist,right.location.reference,left.location.reference,len)
  553. else
  554. cg.g_concatcopy(exprasmlist,right.location.reference,left.location.reference,len);
  555. end;
  556. else
  557. internalerror(200203284);
  558. end;
  559. end;
  560. {$ifdef SUPPORT_MMX}
  561. LOC_CMMXREGISTER,
  562. LOC_MMXREGISTER:
  563. begin
  564. if left.location.loc=LOC_CMMXREGISTER then
  565. cg.a_loadmm_reg_reg(exprasmlist,right.location.register,left.location.register)
  566. else
  567. cg.a_loadmm_reg_ref(exprasmlist,right.location.register,left.location.reference);
  568. end;
  569. {$endif SUPPORT_MMX}
  570. LOC_MMREGISTER,
  571. LOC_CMMREGISTER:
  572. begin
  573. if left.resulttype.def.deftype=arraydef then
  574. begin
  575. end
  576. else
  577. begin
  578. cgsize:=def_cgsize(left.resulttype.def);
  579. if left.location.loc=LOC_CMMREGISTER then
  580. cg.a_loadmm_reg_reg(exprasmlist,right.location.size,left.location.size,right.location.register,left.location.register,mms_movescalar)
  581. else
  582. cg.a_loadmm_reg_ref(exprasmlist,right.location.size,left.location.size,right.location.register,left.location.reference,mms_movescalar);
  583. end;
  584. end;
  585. LOC_REGISTER,
  586. LOC_CREGISTER :
  587. begin
  588. cgsize:=def_cgsize(left.resulttype.def);
  589. {$ifndef cpu64bit}
  590. if cgsize in [OS_64,OS_S64] then
  591. cg64.a_load64_reg_loc(exprasmlist,
  592. right.location.register64,left.location)
  593. else
  594. {$endif cpu64bit}
  595. cg.a_load_reg_loc(exprasmlist,right.location.size,right.location.register,left.location);
  596. end;
  597. LOC_FPUREGISTER,
  598. LOC_CFPUREGISTER :
  599. begin
  600. if (left.resulttype.def.deftype=floatdef) then
  601. fputyp:=tfloatdef(left.resulttype.def).typ
  602. else
  603. if (right.resulttype.def.deftype=floatdef) then
  604. fputyp:=tfloatdef(right.resulttype.def).typ
  605. else
  606. if (right.nodetype=typeconvn) and
  607. (ttypeconvnode(right).left.resulttype.def.deftype=floatdef) then
  608. fputyp:=tfloatdef(ttypeconvnode(right).left.resulttype.def).typ
  609. else
  610. fputyp:=s32real;
  611. cg.a_loadfpu_reg_loc(exprasmlist,
  612. tfloat2tcgsize[fputyp],
  613. right.location.register,left.location);
  614. end;
  615. LOC_JUMP :
  616. begin
  617. cgsize:=def_cgsize(left.resulttype.def);
  618. objectlibrary.getlabel(hlabel);
  619. { generate the leftnode for the true case, and
  620. release the location }
  621. cg.a_label(exprasmlist,truelabel);
  622. secondpass(left);
  623. if codegenerror then
  624. exit;
  625. cg.a_load_const_loc(exprasmlist,1,left.location);
  626. cg.a_jmp_always(exprasmlist,hlabel);
  627. { generate the leftnode for the false case }
  628. cg.a_label(exprasmlist,falselabel);
  629. old_allow_multi_pass2:=allow_multi_pass2;
  630. allow_multi_pass2:=true;
  631. secondpass(left);
  632. allow_multi_pass2:=old_allow_multi_pass2;
  633. if codegenerror then
  634. exit;
  635. cg.a_load_const_loc(exprasmlist,0,left.location);
  636. cg.a_label(exprasmlist,hlabel);
  637. end;
  638. {$ifdef cpuflags}
  639. LOC_FLAGS :
  640. begin
  641. {This can be a wordbool or longbool too, no?}
  642. if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  643. cg.g_flags2reg(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.register)
  644. else
  645. begin
  646. if not(left.location.loc = LOC_REFERENCE) then
  647. internalerror(200203273);
  648. cg.g_flags2ref(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.reference);
  649. end;
  650. end;
  651. {$endif cpuflags}
  652. end;
  653. end;
  654. if releaseright then
  655. location_freetemp(exprasmlist,right.location);
  656. truelabel:=otlabel;
  657. falselabel:=oflabel;
  658. end;
  659. {*****************************************************************************
  660. SecondArrayConstruct
  661. *****************************************************************************}
  662. const
  663. vtInteger = 0;
  664. vtBoolean = 1;
  665. vtChar = 2;
  666. vtExtended = 3;
  667. vtString = 4;
  668. vtPointer = 5;
  669. vtPChar = 6;
  670. vtObject = 7;
  671. vtClass = 8;
  672. vtWideChar = 9;
  673. vtPWideChar = 10;
  674. vtAnsiString32 = 11;
  675. vtCurrency = 12;
  676. vtVariant = 13;
  677. vtInterface = 14;
  678. vtWideString = 15;
  679. vtInt64 = 16;
  680. vtQWord = 17;
  681. vtAnsiString16 = 18;
  682. vtAnsiString64 = 19;
  683. procedure tcgarrayconstructornode.pass_2;
  684. var
  685. hp : tarrayconstructornode;
  686. href : treference;
  687. lt : tdef;
  688. vaddr : boolean;
  689. vtype : longint;
  690. freetemp,
  691. dovariant : boolean;
  692. elesize : longint;
  693. tmpreg : tregister;
  694. paraloc : tcgparalocation;
  695. begin
  696. dovariant:=(nf_forcevaria in flags) or tarraydef(resulttype.def).isvariant;
  697. if dovariant then
  698. elesize:=sizeof(aint)+sizeof(aint)
  699. else
  700. elesize:=tarraydef(resulttype.def).elesize;
  701. location_reset(location,LOC_CREFERENCE,OS_NO);
  702. fillchar(paraloc,sizeof(paraloc),0);
  703. { Allocate always a temp, also if no elements are required, to
  704. be sure that location is valid (PFV) }
  705. if tarraydef(resulttype.def).highrange=-1 then
  706. tg.GetTemp(exprasmlist,elesize,tt_normal,location.reference)
  707. else
  708. tg.GetTemp(exprasmlist,(tarraydef(resulttype.def).highrange+1)*elesize,tt_normal,location.reference);
  709. href:=location.reference;
  710. { Process nodes in array constructor }
  711. hp:=self;
  712. while assigned(hp) do
  713. begin
  714. if assigned(hp.left) then
  715. begin
  716. freetemp:=true;
  717. secondpass(hp.left);
  718. if codegenerror then
  719. exit;
  720. { Move flags and jump in register }
  721. if hp.left.location.loc in [LOC_FLAGS,LOC_JUMP] then
  722. location_force_reg(exprasmlist,hp.left.location,def_cgsize(hp.left.resulttype.def),false);
  723. if dovariant then
  724. begin
  725. { find the correct vtype value }
  726. vtype:=$ff;
  727. vaddr:=false;
  728. lt:=hp.left.resulttype.def;
  729. case lt.deftype of
  730. enumdef,
  731. orddef :
  732. begin
  733. if is_64bit(lt) then
  734. begin
  735. case torddef(lt).typ of
  736. s64bit:
  737. vtype:=vtInt64;
  738. u64bit:
  739. vtype:=vtQWord;
  740. end;
  741. freetemp:=false;
  742. vaddr:=true;
  743. end
  744. else if (lt.deftype=enumdef) or
  745. is_integer(lt) then
  746. vtype:=vtInteger
  747. else
  748. if is_boolean(lt) then
  749. vtype:=vtBoolean
  750. else
  751. if (lt.deftype=orddef) then
  752. begin
  753. case torddef(lt).typ of
  754. uchar:
  755. vtype:=vtChar;
  756. uwidechar:
  757. vtype:=vtWideChar;
  758. end;
  759. end;
  760. end;
  761. floatdef :
  762. begin
  763. vtype:=vtExtended;
  764. freetemp:=false;
  765. vaddr:=true;
  766. end;
  767. procvardef,
  768. pointerdef :
  769. begin
  770. if is_pchar(lt) then
  771. vtype:=vtPChar
  772. else if is_pwidechar(lt) then
  773. vtype:=vtPWideChar
  774. else
  775. vtype:=vtPointer;
  776. end;
  777. variantdef :
  778. begin
  779. vtype:=vtVariant;
  780. vaddr:=true;
  781. freetemp:=false;
  782. end;
  783. classrefdef :
  784. vtype:=vtClass;
  785. objectdef :
  786. vtype:=vtObject;
  787. stringdef :
  788. begin
  789. if is_shortstring(lt) then
  790. begin
  791. vtype:=vtString;
  792. vaddr:=true;
  793. freetemp:=false;
  794. end
  795. else
  796. if is_ansistring(lt) then
  797. {$ifdef ansistring_bits}
  798. begin
  799. case Tstringdef(lt).string_typ of
  800. st_ansistring16:
  801. vtype:=vtAnsiString16;
  802. st_ansistring32:
  803. vtype:=vtAnsiString32;
  804. st_ansistring64:
  805. vtype:=vtAnsiString64;
  806. end;
  807. freetemp:=false;
  808. end
  809. {$else}
  810. begin
  811. vtype:=vtAnsiString;
  812. freetemp:=false;
  813. end
  814. {$endif}
  815. else
  816. if is_widestring(lt) then
  817. begin
  818. vtype:=vtWideString;
  819. freetemp:=false;
  820. end;
  821. end;
  822. end;
  823. if vtype=$ff then
  824. internalerror(14357);
  825. { write changing field update href to the next element }
  826. inc(href.offset,sizeof(aint));
  827. if vaddr then
  828. begin
  829. location_force_mem(exprasmlist,hp.left.location);
  830. tmpreg:=cg.getaddressregister(exprasmlist);
  831. cg.a_loadaddr_ref_reg(exprasmlist,hp.left.location.reference,tmpreg);
  832. cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,tmpreg,href);
  833. end
  834. else
  835. cg.a_load_loc_ref(exprasmlist,OS_ADDR,hp.left.location,href);
  836. { update href to the vtype field and write it }
  837. dec(href.offset,sizeof(aint));
  838. cg.a_load_const_ref(exprasmlist, OS_INT,vtype,href);
  839. { goto next array element }
  840. inc(href.offset,sizeof(aint)*2);
  841. end
  842. else
  843. { normal array constructor of the same type }
  844. begin
  845. if not(
  846. is_ansistring(left.resulttype.def) or
  847. is_widestring(left.resulttype.def) or
  848. (left.resulttype.def.deftype=variantdef)
  849. ) then
  850. freetemp:=true;
  851. case hp.left.location.loc of
  852. LOC_FPUREGISTER,
  853. LOC_CFPUREGISTER :
  854. cg.a_loadfpu_reg_ref(exprasmlist,hp.left.location.size,hp.left.location.register,href);
  855. LOC_REFERENCE,
  856. LOC_CREFERENCE :
  857. begin
  858. if is_shortstring(hp.left.resulttype.def) then
  859. cg.g_copyshortstring(exprasmlist,hp.left.location.reference,href,
  860. Tstringdef(hp.left.resulttype.def).len)
  861. else
  862. cg.g_concatcopy(exprasmlist,hp.left.location.reference,href,elesize);
  863. end;
  864. else
  865. begin
  866. {$ifndef cpu64bit}
  867. if hp.left.location.size in [OS_64,OS_S64] then
  868. cg64.a_load64_loc_ref(exprasmlist,hp.left.location,href)
  869. else
  870. {$endif cpu64bit}
  871. cg.a_load_loc_ref(exprasmlist,hp.left.location.size,hp.left.location,href);
  872. end;
  873. end;
  874. inc(href.offset,elesize);
  875. end;
  876. if freetemp then
  877. location_freetemp(exprasmlist,hp.left.location);
  878. end;
  879. { load next entry }
  880. hp:=tarrayconstructornode(hp.right);
  881. end;
  882. end;
  883. begin
  884. cloadnode:=tcgloadnode;
  885. cassignmentnode:=tcgassignmentnode;
  886. carrayconstructornode:=tcgarrayconstructornode;
  887. end.
  888. {
  889. $Log$
  890. Revision 1.128 2004-10-24 11:44:28 peter
  891. * small regvar fixes
  892. * loadref parameter removed from concatcopy,incrrefcount,etc
  893. Revision 1.127 2004/10/10 20:21:18 peter
  894. * passing a var parameter to var parameter is now also allowed
  895. for register locations (=regvars)
  896. Revision 1.126 2004/09/26 17:45:30 peter
  897. * simple regvar support, not yet finished
  898. Revision 1.125 2004/09/25 14:23:54 peter
  899. * ungetregister is now only used for cpuregisters, renamed to
  900. ungetcpuregister
  901. * renamed (get|unget)explicitregister(s) to ..cpuregister
  902. * removed location-release/reference_release
  903. Revision 1.124 2004/09/21 17:25:12 peter
  904. * paraloc branch merged
  905. Revision 1.123 2004/09/13 20:33:41 peter
  906. * pwidechar support in array of const
  907. Revision 1.122.4.3 2004/09/12 18:31:50 peter
  908. * use normal concatcopy when data < sizeof(aint)
  909. Revision 1.122.4.2 2004/09/12 13:36:40 peter
  910. * fixed alignment issues
  911. Revision 1.122.4.1 2004/08/31 20:43:06 peter
  912. * paraloc patch
  913. Revision 1.122 2004/08/15 13:30:18 florian
  914. * fixed alignment of variant records
  915. * more alignment problems fixed
  916. Revision 1.121 2004/07/15 20:47:53 jonas
  917. - disabled temp-to-temp copy optimization, because it can cause errors
  918. now that the local variables are temps as well (it can cause local
  919. variables to be "freed" in the middle of a procedure)
  920. Revision 1.120 2004/07/03 10:26:35 peter
  921. * always pass right before left when type needs refcnt
  922. Revision 1.119 2004/06/29 20:57:03 peter
  923. * redundant freetemp removed
  924. Revision 1.118 2004/06/20 08:55:29 florian
  925. * logs truncated
  926. Revision 1.117 2004/06/16 20:07:08 florian
  927. * dwarf branch merged
  928. Revision 1.116 2004/05/22 23:34:28 peter
  929. tai_regalloc.allocation changed to ratype to notify rgobj of register size changes
  930. Revision 1.115 2004/04/29 19:56:37 daniel
  931. * Prepare compiler infrastructure for multiple ansistring types
  932. Revision 1.114.2.8 2004/06/13 10:51:16 florian
  933. * fixed several register allocator problems (sparc/arm)
  934. Revision 1.114.2.7 2004/06/12 17:01:01 florian
  935. * fixed compilation of arm compiler
  936. }