ncgld.pas 44 KB

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