ncgld.pas 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061
  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. end;
  28. tcgassignmentnode = class(tassignmentnode)
  29. procedure pass_2;override;
  30. end;
  31. tcgfuncretnode = class(tfuncretnode)
  32. procedure pass_2;override;
  33. end;
  34. tcgarrayconstructornode = class(tarrayconstructornode)
  35. procedure pass_2;override;
  36. end;
  37. implementation
  38. uses
  39. systems,
  40. verbose,globtype,globals,
  41. symconst,symtype,symdef,symsym,symtable,defbase,paramgr,
  42. ncnv,ncon,nmem,
  43. aasmbase,aasmtai,aasmcpu,regvars,
  44. cginfo,cgbase,pass_2,
  45. cpubase,cpuinfo,cpupara,
  46. tgobj,ncgutil,cgobj,rgobj,rgcpu;
  47. {*****************************************************************************
  48. SecondLoad
  49. *****************************************************************************}
  50. procedure tcgloadnode.pass_2;
  51. var
  52. intreg,
  53. hregister : tregister;
  54. freereg : boolean;
  55. symtabletype : tsymtabletype;
  56. i : longint;
  57. href : treference;
  58. newsize : tcgsize;
  59. pushed : tpushedsaved;
  60. begin
  61. { we don't know the size of all arrays }
  62. newsize:=def_cgsize(resulttype.def);
  63. location_reset(location,LOC_REFERENCE,newsize);
  64. case symtableentry.typ of
  65. absolutesym :
  66. begin
  67. { this is only for toasm and toaddr }
  68. if (tabsolutesym(symtableentry).abstyp=toaddr) then
  69. begin
  70. {$ifdef i386}
  71. if tabsolutesym(symtableentry).absseg then
  72. location.reference.segment:=R_FS;
  73. {$endif i386}
  74. location.reference.offset:=tabsolutesym(symtableentry).address;
  75. end
  76. else
  77. location.reference.symbol:=objectlibrary.newasmsymbol(tabsolutesym(symtableentry).mangledname);
  78. end;
  79. constsym:
  80. begin
  81. if tconstsym(symtableentry).consttyp=constresourcestring then
  82. begin
  83. location_reset(location,LOC_CREFERENCE,OS_ADDR);
  84. location.reference.symbol:=objectlibrary.newasmsymbol(tconstsym(symtableentry).owner.name^+'_RESOURCESTRINGLIST');
  85. location.reference.offset:=tconstsym(symtableentry).resstrindex*16+8;
  86. end
  87. else
  88. internalerror(22798);
  89. end;
  90. varsym :
  91. begin
  92. symtabletype:=symtable.symtabletype;
  93. hregister:=R_NO;
  94. { C variable }
  95. if (vo_is_C_var in tvarsym(symtableentry).varoptions) then
  96. begin
  97. location.reference.symbol:=objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname);
  98. end
  99. { DLL variable }
  100. else if (vo_is_dll_var in tvarsym(symtableentry).varoptions) then
  101. begin
  102. hregister:=rg.getaddressregister(exprasmlist);
  103. location.reference.symbol:=objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname);
  104. cg.a_load_ref_reg(exprasmlist,OS_ADDR,location.reference,hregister);
  105. reference_reset_base(location.reference,hregister,0);
  106. end
  107. { external variable }
  108. else if (vo_is_external in tvarsym(symtableentry).varoptions) then
  109. begin
  110. location.reference.symbol:=objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname);
  111. end
  112. { thread variable }
  113. else if (vo_is_thread_var in tvarsym(symtableentry).varoptions) then
  114. begin
  115. { we've to allocate the register before we save the used registers }
  116. location.reference.base:=rg.getaddressregister(exprasmlist);
  117. rg.saveusedregisters(exprasmlist,pushed,[accumulator]);
  118. reference_reset_symbol(href,objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname),0);
  119. cg.a_param_ref(exprasmlist,OS_ADDR,href,paramanager.getintparaloc(1));
  120. { the called procedure isn't allowed to change }
  121. { any register except EAX }
  122. cg.a_call_name(exprasmlist,'FPC_RELOCATE_THREADVAR');
  123. cg.a_load_reg_reg(exprasmlist,OS_INT,OS_ADDR,accumulator,location.reference.base);
  124. rg.restoreusedregisters(exprasmlist,pushed);
  125. end
  126. { normal variable }
  127. else
  128. begin
  129. { in case it is a register variable: }
  130. if tvarsym(symtableentry).reg<>R_NO then
  131. begin
  132. if tvarsym(symtableentry).reg in fpuregs then
  133. begin
  134. location_reset(location,LOC_CFPUREGISTER,def_cgsize(resulttype.def));
  135. location.register:=tvarsym(symtableentry).reg;
  136. end
  137. else
  138. begin
  139. intreg:=rg.makeregsize(tvarsym(symtableentry).reg,OS_INT);
  140. if (intreg in general_registers) and
  141. (not rg.regvar_loaded[intreg]) then
  142. load_regvar(exprasmlist,tvarsym(symtableentry));
  143. location_reset(location,LOC_CREGISTER,cg.reg_cgsize(tvarsym(symtableentry).reg));
  144. location.register:=tvarsym(symtableentry).reg;
  145. exclude(rg.unusedregsint,intreg);
  146. end;
  147. end
  148. else
  149. begin
  150. case symtabletype of
  151. localsymtable,
  152. parasymtable,
  153. inlinelocalsymtable,
  154. inlineparasymtable :
  155. begin
  156. location.reference.base:=procinfo.framepointer;
  157. if (symtabletype in [inlinelocalsymtable,
  158. localsymtable])
  159. {$ifdef powerpc}
  160. { the ifdef is only for speed reasons }
  161. and not(target_info.system in [system_powerpc_linux,system_powerpc_macos])
  162. {$endif powerpc}
  163. then
  164. location.reference.offset:=
  165. tvarsym(symtableentry).address-symtable.address_fixup
  166. else
  167. location.reference.offset:=
  168. tvarsym(symtableentry).address+symtable.address_fixup;
  169. {$ifndef powerpc}
  170. if (symtabletype in [localsymtable,inlinelocalsymtable]) then
  171. begin
  172. if use_esp_stackframe then
  173. dec(location.reference.offset,
  174. tvarsym(symtableentry).getvaluesize)
  175. else
  176. location.reference.offset:=-location.reference.offset;
  177. end;
  178. {$endif powerpc}
  179. if (lexlevel>symtable.symtablelevel) then
  180. begin
  181. hregister:=rg.getaddressregister(exprasmlist);
  182. { make a reference }
  183. reference_reset_base(href,procinfo.framepointer,procinfo.framepointer_offset);
  184. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  185. { walk parents }
  186. i:=lexlevel-1;
  187. while (i>symtable.symtablelevel) do
  188. begin
  189. { make a reference }
  190. reference_reset_base(href,hregister,target_info.first_parm_offset);
  191. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  192. dec(i);
  193. end;
  194. location.reference.base:=hregister;
  195. end;
  196. end;
  197. globalsymtable,
  198. staticsymtable :
  199. begin
  200. location.reference.symbol:=objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname);
  201. end;
  202. stt_exceptsymtable:
  203. begin
  204. location.reference.base:=procinfo.framepointer;
  205. location.reference.offset:=tvarsym(symtableentry).address;
  206. end;
  207. objectsymtable:
  208. begin
  209. if (sp_static in tvarsym(symtableentry).symoptions) then
  210. location.reference.symbol:=objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname)
  211. else
  212. begin
  213. rg.getexplicitregisterint(exprasmlist,SELF_POINTER_REG);
  214. location.reference.base:=SELF_POINTER_REG;
  215. location.reference.offset:=tvarsym(symtableentry).address;
  216. end;
  217. end;
  218. withsymtable:
  219. begin
  220. if nf_islocal in tnode(twithsymtable(symtable).withnode).flags then
  221. location.reference:=twithnode(twithsymtable(symtable).withnode).withreference
  222. else
  223. begin
  224. location.reference.base:=rg.getaddressregister(exprasmlist);
  225. cg.a_load_ref_reg(exprasmlist,OS_ADDR,
  226. twithnode(twithsymtable(symtable).withnode).withreference,
  227. location.reference.base);
  228. end;
  229. inc(location.reference.offset,tvarsym(symtableentry).address);
  230. end;
  231. end;
  232. end;
  233. end;
  234. { handle call by reference variables }
  235. if (symtabletype in [parasymtable,inlineparasymtable]) then
  236. begin
  237. { in case call by reference, then calculate. Open array
  238. is always an reference! }
  239. if (tvarsym(symtableentry).varspez in [vs_var,vs_out]) or
  240. is_open_array(tvarsym(symtableentry).vartype.def) or
  241. is_array_of_const(tvarsym(symtableentry).vartype.def) or
  242. paramanager.push_addr_param(tvarsym(symtableentry).vartype.def,
  243. (tprocdef(symtable.defowner).proccalloption in [pocall_cdecl,pocall_cppdecl])) then
  244. begin
  245. if hregister=R_NO then
  246. hregister:=rg.getaddressregister(exprasmlist);
  247. { we need to load only an address }
  248. location.size:=OS_ADDR;
  249. cg.a_load_loc_reg(exprasmlist,location,hregister);
  250. location_reset(location,LOC_REFERENCE,newsize);
  251. location.reference.base:=hregister;
  252. end;
  253. end;
  254. end;
  255. procsym:
  256. begin
  257. if assigned(left) then
  258. begin
  259. {
  260. THIS IS A TERRIBLE HACK!!!!!! WHICH WILL NOT WORK
  261. ON 64-BIT SYSTEMS: SINCE PROCSYM FOR METHODS
  262. CONSISTS OF TWO OS_ADDR, so you cannot set it
  263. to OS_64 - how to solve?? Carl
  264. }
  265. if (sizeof(aword) = 4) then
  266. location_reset(location,LOC_CREFERENCE,OS_64)
  267. else
  268. internalerror(20020520);
  269. tg.GetTemp(exprasmlist,2*POINTER_SIZE,tt_normal,location.reference);
  270. freereg:=false;
  271. { called as type.method, then we only need to return
  272. the address of the function, not the self pointer }
  273. if left.nodetype=typen then
  274. begin
  275. { there is no instance, we return 0 }
  276. href:=location.reference;
  277. inc(href.offset,POINTER_SIZE);
  278. cg.a_load_const_ref(exprasmlist,OS_ADDR,0,href);
  279. end
  280. else
  281. begin
  282. secondpass(left);
  283. { load class instance address }
  284. case left.location.loc of
  285. LOC_CREGISTER,
  286. LOC_REGISTER:
  287. begin
  288. hregister:=left.location.register;
  289. if is_object(left.resulttype.def) then
  290. CGMessage(cg_e_illegal_expression);
  291. end;
  292. LOC_CREFERENCE,
  293. LOC_REFERENCE:
  294. begin
  295. hregister:=rg.getaddressregister(exprasmlist);
  296. if is_class_or_interface(left.resulttype.def) then
  297. cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,hregister)
  298. else
  299. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,hregister);
  300. location_release(exprasmlist,left.location);
  301. location_freetemp(exprasmlist,left.location);
  302. end;
  303. else
  304. internalerror(26019);
  305. end;
  306. { store the class instance address }
  307. href:=location.reference;
  308. inc(href.offset,POINTER_SIZE);
  309. cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,href);
  310. { hregister will be reused when loading a virtual method }
  311. freereg:=true;
  312. end;
  313. { virtual method ? }
  314. if (po_virtualmethod in tprocdef(resulttype.def).procoptions) then
  315. begin
  316. if not freereg then
  317. begin
  318. if left.nodetype <> typen then
  319. internalerror(200205161);
  320. reference_reset_symbol(href,objectlibrary.newasmsymbol(tobjectdef(left.resulttype.def).vmt_mangledname),
  321. tprocdef(resulttype.def)._class.vmtmethodoffset(tprocdef(resulttype.def).extnumber));
  322. end
  323. else
  324. begin
  325. { load vmt pointer }
  326. reference_reset_base(href,hregister,0);
  327. reference_release(exprasmlist,href);
  328. hregister:=rg.getaddressregister(exprasmlist);
  329. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  330. reference_reset_base(href,hregister,tprocdef(resulttype.def)._class.vmtmethodoffset(
  331. tprocdef(resulttype.def).extnumber));
  332. reference_release(exprasmlist,href);
  333. end;
  334. { load method address }
  335. hregister:=rg.getaddressregister(exprasmlist);
  336. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  337. { ... and store it }
  338. cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,location.reference);
  339. rg.ungetaddressregister(exprasmlist,hregister);
  340. end
  341. else
  342. begin
  343. { we don't use the hregister }
  344. if freereg then
  345. rg.ungetregister(exprasmlist,hregister);
  346. { load address of the function }
  347. reference_reset_symbol(href,objectlibrary.newasmsymbol(tprocdef(resulttype.def).mangledname),0);
  348. hregister:=cg.get_scratch_reg_address(exprasmlist);
  349. cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
  350. cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,location.reference);
  351. cg.free_scratch_reg(exprasmlist,hregister);
  352. end;
  353. end
  354. else
  355. begin
  356. {!!!!! Be aware, work on virtual methods too }
  357. location.reference.symbol:=objectlibrary.newasmsymbol(tprocdef(resulttype.def).mangledname);
  358. end;
  359. end;
  360. typedconstsym :
  361. begin
  362. location.reference.symbol:=objectlibrary.newasmsymbol(ttypedconstsym(symtableentry).mangledname);
  363. end;
  364. else internalerror(4);
  365. end;
  366. end;
  367. {*****************************************************************************
  368. SecondAssignment
  369. *****************************************************************************}
  370. procedure tcgassignmentnode.pass_2;
  371. var
  372. otlabel,hlabel,oflabel : tasmlabel;
  373. fputyp : tfloattype;
  374. href : treference;
  375. releaseright : boolean;
  376. pushedregs : tmaybesave;
  377. cgsize : tcgsize;
  378. begin
  379. otlabel:=truelabel;
  380. oflabel:=falselabel;
  381. objectlibrary.getlabel(truelabel);
  382. objectlibrary.getlabel(falselabel);
  383. {
  384. in most cases we can process first the right node which contains
  385. the most complex code. But not when the result is in the flags, then
  386. loading the left node afterwards can destroy the flags.
  387. when the right node returns as LOC_JUMP then we will generate
  388. the following code:
  389. rightnode
  390. true:
  391. leftnode
  392. assign 1
  393. false:
  394. leftnode
  395. assign 0
  396. }
  397. { Try to determine which side to calculate first, }
  398. if (right.location.loc<>LOC_FLAGS) and
  399. ((right.location.loc=LOC_JUMP) or
  400. (right.registers32>=left.registers32)) then
  401. begin
  402. secondpass(right);
  403. { increment source reference counter, this is
  404. useless for string constants}
  405. if (right.resulttype.def.needs_inittable) and
  406. (right.nodetype<>stringconstn) then
  407. cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference);
  408. if codegenerror then
  409. exit;
  410. { We skip the generation of the left node when it's a jump, see
  411. explanation above }
  412. if (right.location.loc<>LOC_JUMP) and
  413. not(nf_concat_string in flags) then
  414. begin
  415. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  416. { can be false }
  417. maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
  418. secondpass(left);
  419. { decrement destination reference counter }
  420. if (left.resulttype.def.needs_inittable) then
  421. cg.g_decrrefcount(exprasmlist,left.resulttype.def,left.location.reference);
  422. maybe_restore(exprasmlist,right.location,pushedregs);
  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);
  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. maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
  443. secondpass(right);
  444. { increment source reference counter, this is
  445. useless for string constants}
  446. if (right.resulttype.def.needs_inittable) and
  447. (right.nodetype<>stringconstn) then
  448. cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference);
  449. maybe_restore(exprasmlist,left.location,pushedregs);
  450. if codegenerror then
  451. exit;
  452. end;
  453. if not(left.location.loc in [LOC_REFERENCE,LOC_CFPUREGISTER,
  454. {$ifdef SUPPORT_MMX}LOC_CMMXREGISTER,{$endif}
  455. LOC_CREGISTER]) then
  456. begin
  457. CGMessage(cg_e_illegal_expression);
  458. exit;
  459. end;
  460. releaseright:=true;
  461. { shortstring assignments are handled separately }
  462. if is_shortstring(left.resulttype.def) then
  463. begin
  464. {
  465. we can get here only in the following situations
  466. for the right node:
  467. - empty constant string
  468. - char
  469. }
  470. { empty constant string }
  471. if (right.nodetype=stringconstn) and
  472. (tstringconstnode(right).len=0) then
  473. begin
  474. cg.a_load_const_ref(exprasmlist,OS_8,0,left.location.reference);
  475. end
  476. { char loading }
  477. else if is_char(right.resulttype.def) then
  478. begin
  479. if right.nodetype=ordconstn then
  480. begin
  481. if (target_info.endian = endian_little) then
  482. cg.a_load_const_ref(exprasmlist,OS_16,(tordconstnode(right).value shl 8) or 1,
  483. left.location.reference)
  484. else
  485. cg.a_load_const_ref(exprasmlist,OS_16,tordconstnode(right).value or (1 shl 8),
  486. left.location.reference);
  487. end
  488. else
  489. begin
  490. href:=left.location.reference;
  491. cg.a_load_const_ref(exprasmlist,OS_8,1,href);
  492. inc(href.offset,1);
  493. case right.location.loc of
  494. LOC_REGISTER,
  495. LOC_CREGISTER :
  496. cg.a_load_reg_ref(exprasmlist,OS_8,rg.makeregsize(right.location.register,OS_8),href);
  497. LOC_REFERENCE,
  498. LOC_CREFERENCE :
  499. cg.a_load_ref_ref(exprasmlist,OS_8,right.location.reference,href);
  500. else
  501. internalerror(200205111);
  502. end;
  503. end;
  504. end
  505. else
  506. internalerror(200204249);
  507. end
  508. else
  509. begin
  510. case right.location.loc of
  511. LOC_CONSTANT :
  512. begin
  513. if right.location.size in [OS_64,OS_S64] then
  514. cg64.a_load64_const_loc(exprasmlist,
  515. right.location.valueqword,left.location)
  516. else
  517. cg.a_load_const_loc(exprasmlist,right.location.value,left.location);
  518. end;
  519. LOC_REFERENCE,
  520. LOC_CREFERENCE :
  521. begin
  522. case left.location.loc of
  523. LOC_CREGISTER :
  524. begin
  525. cgsize:=def_cgsize(left.resulttype.def);
  526. if cgsize in [OS_64,OS_S64] then
  527. cg64.a_load64_ref_reg(exprasmlist,
  528. right.location.reference,left.location.register64)
  529. else
  530. cg.a_load_ref_reg(exprasmlist,cgsize,
  531. right.location.reference,left.location.register);
  532. location_release(exprasmlist,right.location);
  533. end;
  534. LOC_CFPUREGISTER :
  535. begin
  536. cg.a_loadfpu_ref_reg(exprasmlist,
  537. def_cgsize(right.resulttype.def),
  538. right.location.reference,
  539. left.location.register);
  540. end;
  541. LOC_REFERENCE,
  542. LOC_CREFERENCE :
  543. begin
  544. cg.g_concatcopy(exprasmlist,right.location.reference,
  545. left.location.reference,left.resulttype.def.size,true,false);
  546. { right.location is already released by concatcopy }
  547. releaseright:=false;
  548. end;
  549. else
  550. internalerror(200203284);
  551. end;
  552. end;
  553. {$ifdef SUPPORT_MMX}
  554. LOC_CMMXREGISTER,
  555. LOC_MMXREGISTER:
  556. begin
  557. if left.location.loc=LOC_CMMXREGISTER then
  558. cg.a_loadmm_reg_reg(exprasmlist,right.location.register,left.location.register)
  559. else
  560. cg.a_loadmm_reg_ref(exprasmlist,right.location.register,left.location.reference);
  561. end;
  562. {$endif SUPPORT_MMX}
  563. LOC_REGISTER,
  564. LOC_CREGISTER :
  565. begin
  566. cgsize:=def_cgsize(left.resulttype.def);
  567. if cgsize in [OS_64,OS_S64] then
  568. cg64.a_load64_reg_loc(exprasmlist,
  569. right.location.register64,left.location)
  570. else
  571. cg.a_load_reg_loc(exprasmlist,right.location.size,right.location.register,left.location);
  572. end;
  573. LOC_FPUREGISTER,LOC_CFPUREGISTER :
  574. begin
  575. if (left.resulttype.def.deftype=floatdef) then
  576. fputyp:=tfloatdef(left.resulttype.def).typ
  577. else
  578. if (right.resulttype.def.deftype=floatdef) then
  579. fputyp:=tfloatdef(right.resulttype.def).typ
  580. else
  581. if (right.nodetype=typeconvn) and
  582. (ttypeconvnode(right).left.resulttype.def.deftype=floatdef) then
  583. fputyp:=tfloatdef(ttypeconvnode(right).left.resulttype.def).typ
  584. else
  585. fputyp:=s32real;
  586. cg.a_loadfpu_reg_loc(exprasmlist,
  587. tfloat2tcgsize[fputyp],
  588. right.location.register,left.location);
  589. end;
  590. LOC_JUMP :
  591. begin
  592. cgsize:=def_cgsize(left.resulttype.def);
  593. objectlibrary.getlabel(hlabel);
  594. { generate the leftnode for the true case, and
  595. release the location }
  596. cg.a_label(exprasmlist,truelabel);
  597. maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
  598. secondpass(left);
  599. maybe_restore(exprasmlist,right.location,pushedregs);
  600. if codegenerror then
  601. exit;
  602. cg.a_load_const_loc(exprasmlist,1,left.location);
  603. location_release(exprasmlist,left.location);
  604. cg.a_jmp_always(exprasmlist,hlabel);
  605. { generate the leftnode for the false case }
  606. cg.a_label(exprasmlist,falselabel);
  607. maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
  608. secondpass(left);
  609. maybe_restore(exprasmlist,right.location,pushedregs);
  610. if codegenerror then
  611. exit;
  612. cg.a_load_const_loc(exprasmlist,0,left.location);
  613. cg.a_label(exprasmlist,hlabel);
  614. end;
  615. {$ifdef cpuflags}
  616. LOC_FLAGS :
  617. begin
  618. // this can be a wordbool or longbool too, no?
  619. if left.location.loc=LOC_CREGISTER then
  620. cg.g_flags2reg(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.register)
  621. else
  622. begin
  623. if not(left.location.loc = LOC_REFERENCE) then
  624. internalerror(200203273);
  625. cg.g_flags2ref(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.reference);
  626. end;
  627. end;
  628. {$endif cpuflags}
  629. end;
  630. end;
  631. if releaseright then
  632. location_release(exprasmlist,right.location);
  633. location_release(exprasmlist,left.location);
  634. truelabel:=otlabel;
  635. falselabel:=oflabel;
  636. end;
  637. {*****************************************************************************
  638. SecondFuncRet
  639. *****************************************************************************}
  640. procedure tcgfuncretnode.pass_2;
  641. var
  642. hreg : tregister;
  643. href : treference;
  644. pp : tprocinfo;
  645. hr_valid : boolean;
  646. i : integer;
  647. begin
  648. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  649. hr_valid:=false;
  650. if (not inlining_procedure) and
  651. (lexlevel<>funcretsym.owner.symtablelevel) then
  652. begin
  653. hreg:=rg.getaddressregister(exprasmlist);
  654. hr_valid:=true;
  655. reference_reset_base(href,procinfo.framepointer,procinfo.framepointer_offset);
  656. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hreg);
  657. { walk up the stack frame }
  658. pp:=procinfo.parent;
  659. i:=lexlevel-1;
  660. while i>funcretsym.owner.symtablelevel do
  661. begin
  662. reference_reset_base(href,hreg,pp.framepointer_offset);
  663. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hreg);
  664. pp:=pp.parent;
  665. dec(i);
  666. end;
  667. location.reference.base:=hreg;
  668. location.reference.offset:=pp.return_offset;
  669. end
  670. else
  671. begin
  672. location.reference.base:=procinfo.framepointer;
  673. location.reference.offset:=procinfo.return_offset;
  674. end;
  675. if paramanager.ret_in_param(resulttype.def) then
  676. begin
  677. { the parameter is actual a pointer to the value }
  678. if not hr_valid then
  679. hreg:=rg.getaddressregister(exprasmlist);
  680. cg.a_load_ref_reg(exprasmlist,OS_ADDR,location.reference,hreg);
  681. location.reference.base:=hreg;
  682. location.reference.offset:=0;
  683. end;
  684. end;
  685. {*****************************************************************************
  686. SecondArrayConstruct
  687. *****************************************************************************}
  688. const
  689. vtInteger = 0;
  690. vtBoolean = 1;
  691. vtChar = 2;
  692. vtExtended = 3;
  693. vtString = 4;
  694. vtPointer = 5;
  695. vtPChar = 6;
  696. vtObject = 7;
  697. vtClass = 8;
  698. vtWideChar = 9;
  699. vtPWideChar = 10;
  700. vtAnsiString = 11;
  701. vtCurrency = 12;
  702. vtVariant = 13;
  703. vtInterface = 14;
  704. vtWideString = 15;
  705. vtInt64 = 16;
  706. vtQWord = 17;
  707. procedure tcgarrayconstructornode.pass_2;
  708. var
  709. hp : tarrayconstructornode;
  710. href : treference;
  711. lt : tdef;
  712. vaddr : boolean;
  713. vtype : longint;
  714. freetemp,
  715. dovariant : boolean;
  716. elesize : longint;
  717. tmpreg : tregister;
  718. begin
  719. dovariant:=(nf_forcevaria in flags) or tarraydef(resulttype.def).isvariant;
  720. if dovariant then
  721. elesize:=8
  722. else
  723. elesize:=tarraydef(resulttype.def).elesize;
  724. if not(nf_cargs in flags) then
  725. begin
  726. location_reset(location,LOC_REFERENCE,OS_NO);
  727. { Allocate always a temp, also if no elements are required, to
  728. be sure that location is valid (PFV) }
  729. if tarraydef(resulttype.def).highrange=-1 then
  730. tg.GetTemp(exprasmlist,elesize,tt_normal,location.reference)
  731. else
  732. tg.GetTemp(exprasmlist,(tarraydef(resulttype.def).highrange+1)*elesize,tt_normal,location.reference);
  733. href:=location.reference;
  734. end;
  735. hp:=self;
  736. while assigned(hp) do
  737. begin
  738. if assigned(hp.left) then
  739. begin
  740. freetemp:=true;
  741. secondpass(hp.left);
  742. if codegenerror then
  743. exit;
  744. if dovariant then
  745. begin
  746. { find the correct vtype value }
  747. vtype:=$ff;
  748. vaddr:=false;
  749. lt:=hp.left.resulttype.def;
  750. case lt.deftype of
  751. enumdef,
  752. orddef :
  753. begin
  754. if is_64bitint(lt) then
  755. begin
  756. case torddef(lt).typ of
  757. s64bit:
  758. vtype:=vtInt64;
  759. u64bit:
  760. vtype:=vtQWord;
  761. end;
  762. freetemp:=false;
  763. vaddr:=true;
  764. end
  765. else if (lt.deftype=enumdef) or
  766. is_integer(lt) then
  767. vtype:=vtInteger
  768. else
  769. if is_boolean(lt) then
  770. vtype:=vtBoolean
  771. else
  772. if (lt.deftype=orddef) then
  773. begin
  774. case torddef(lt).typ of
  775. uchar:
  776. vtype:=vtChar;
  777. uwidechar:
  778. vtype:=vtWideChar;
  779. end;
  780. end;
  781. end;
  782. floatdef :
  783. begin
  784. vtype:=vtExtended;
  785. vaddr:=true;
  786. freetemp:=false;
  787. end;
  788. procvardef,
  789. pointerdef :
  790. begin
  791. if is_pchar(lt) then
  792. vtype:=vtPChar
  793. else
  794. vtype:=vtPointer;
  795. end;
  796. variantdef :
  797. begin
  798. vtype:=vtVariant;
  799. vaddr:=true;
  800. freetemp:=false;
  801. end;
  802. classrefdef :
  803. vtype:=vtClass;
  804. objectdef :
  805. vtype:=vtObject;
  806. stringdef :
  807. begin
  808. if is_shortstring(lt) then
  809. begin
  810. vtype:=vtString;
  811. vaddr:=true;
  812. freetemp:=false;
  813. end
  814. else
  815. if is_ansistring(lt) then
  816. begin
  817. vtype:=vtAnsiString;
  818. freetemp:=false;
  819. end
  820. else
  821. if is_widestring(lt) then
  822. begin
  823. vtype:=vtWideString;
  824. freetemp:=false;
  825. end;
  826. end;
  827. end;
  828. if vtype=$ff then
  829. internalerror(14357);
  830. { write C style pushes or an pascal array }
  831. if nf_cargs in flags then
  832. begin
  833. if vaddr then
  834. begin
  835. location_force_mem(exprasmlist,hp.left.location);
  836. cg.a_paramaddr_ref(exprasmlist,hp.left.location.reference,paralocdummy);
  837. location_release(exprasmlist,hp.left.location);
  838. if freetemp then
  839. location_freetemp(exprasmlist,hp.left.location);
  840. end
  841. else
  842. cg.a_param_loc(exprasmlist,hp.left.location,paralocdummy);
  843. inc(pushedparasize,pointer_size);
  844. end
  845. else
  846. begin
  847. { write changing field update href to the next element }
  848. inc(href.offset,4);
  849. if vaddr then
  850. begin
  851. location_force_mem(exprasmlist,hp.left.location);
  852. tmpreg:=cg.get_scratch_reg_address(exprasmlist);
  853. cg.a_loadaddr_ref_reg(exprasmlist,hp.left.location.reference,tmpreg);
  854. cg.a_load_reg_ref(exprasmlist,cg.reg_cgsize(tmpreg),tmpreg,href);
  855. cg.free_scratch_reg(exprasmlist,tmpreg);
  856. location_release(exprasmlist,hp.left.location);
  857. if freetemp then
  858. location_freetemp(exprasmlist,hp.left.location);
  859. end
  860. else
  861. begin
  862. location_release(exprasmlist,left.location);
  863. cg.a_load_loc_ref(exprasmlist,hp.left.location,href);
  864. end;
  865. { update href to the vtype field and write it }
  866. dec(href.offset,4);
  867. cg.a_load_const_ref(exprasmlist, OS_INT,vtype,href);
  868. { goto next array element }
  869. inc(href.offset,8);
  870. end;
  871. end
  872. else
  873. { normal array constructor of the same type }
  874. begin
  875. case elesize of
  876. 1,2,4 :
  877. begin
  878. location_release(exprasmlist,left.location);
  879. cg.a_load_loc_ref(exprasmlist,hp.left.location,href);
  880. end;
  881. 8 :
  882. begin
  883. if hp.left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  884. cg64.a_load64_loc_ref(exprasmlist,hp.left.location,href)
  885. else
  886. cg.g_concatcopy(exprasmlist,hp.left.location.reference,href,elesize,freetemp,false);
  887. end;
  888. else
  889. begin
  890. { concatcopy only supports reference }
  891. if not(hp.left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
  892. internalerror(200108012);
  893. cg.g_concatcopy(exprasmlist,hp.left.location.reference,href,elesize,freetemp,false);
  894. end;
  895. end;
  896. inc(href.offset,elesize);
  897. end;
  898. end;
  899. { load next entry }
  900. hp:=tarrayconstructornode(hp.right);
  901. end;
  902. end;
  903. begin
  904. cloadnode:=tcgloadnode;
  905. cassignmentnode:=tcgassignmentnode;
  906. cfuncretnode:=tcgfuncretnode;
  907. carrayconstructornode:=tcgarrayconstructornode;
  908. end.
  909. {
  910. $Log$
  911. Revision 1.32 2002-09-30 07:00:46 florian
  912. * fixes to common code to get the alpha compiler compiled applied
  913. Revision 1.31 2002/09/26 15:02:05 florian
  914. + support of passing variants to "array of const"
  915. Revision 1.30 2002/09/17 18:54:02 jonas
  916. * a_load_reg_reg() now has two size parameters: source and dest. This
  917. allows some optimizations on architectures that don't encode the
  918. register size in the register name.
  919. Revision 1.29 2002/09/07 15:25:03 peter
  920. * old logs removed and tabs fixed
  921. Revision 1.28 2002/09/01 19:26:32 peter
  922. * fixed register variable loading from parasymtable, the call by
  923. reference code was moved wrong
  924. Revision 1.27 2002/09/01 12:15:40 peter
  925. * fixed loading of procvar of object when the object is initialized
  926. with 0
  927. Revision 1.26 2002/08/25 19:25:18 peter
  928. * sym.insert_in_data removed
  929. * symtable.insertvardata/insertconstdata added
  930. * removed insert_in_data call from symtable.insert, it needs to be
  931. called separatly. This allows to deref the address calculation
  932. * procedures now calculate the parast addresses after the procedure
  933. directives are parsed. This fixes the cdecl parast problem
  934. * push_addr_param has an extra argument that specifies if cdecl is used
  935. or not
  936. Revision 1.25 2002/08/23 16:14:48 peter
  937. * tempgen cleanup
  938. * tt_noreuse temp type added that will be used in genentrycode
  939. Revision 1.24 2002/08/17 09:23:35 florian
  940. * first part of procinfo rewrite
  941. Revision 1.23 2002/08/14 18:13:28 jonas
  942. * adapted previous fix to Peter's asmsymbol patch
  943. Revision 1.22 2002/08/14 18:00:42 jonas
  944. * fixed tb0403
  945. Revision 1.21 2002/08/13 21:40:56 florian
  946. * more fixes for ppc calling conventions
  947. Revision 1.20 2002/08/11 14:32:26 peter
  948. * renamed current_library to objectlibrary
  949. Revision 1.19 2002/08/11 13:24:12 peter
  950. * saving of asmsymbols in ppu supported
  951. * asmsymbollist global is removed and moved into a new class
  952. tasmlibrarydata that will hold the info of a .a file which
  953. corresponds with a single module. Added librarydata to tmodule
  954. to keep the library info stored for the module. In the future the
  955. objectfiles will also be stored to the tasmlibrarydata class
  956. * all getlabel/newasmsymbol and friends are moved to the new class
  957. Revision 1.18 2002/08/06 20:55:21 florian
  958. * first part of ppc calling conventions fix
  959. Revision 1.17 2002/07/28 09:25:37 carl
  960. + correct size of parameter (64-bit portability)
  961. Revision 1.16 2002/07/27 19:53:51 jonas
  962. + generic implementation of tcg.g_flags2ref()
  963. * tcg.flags2xxx() now also needs a size parameter
  964. Revision 1.15 2002/07/20 11:57:54 florian
  965. * types.pas renamed to defbase.pas because D6 contains a types
  966. unit so this would conflicts if D6 programms are compiled
  967. + Willamette/SSE2 instructions to assembler added
  968. Revision 1.14 2002/07/16 09:17:44 florian
  969. * threadvar relocation result wasn't handled properly, it could cause
  970. a crash
  971. Revision 1.13 2002/07/11 14:41:28 florian
  972. * start of the new generic parameter handling
  973. Revision 1.12 2002/07/07 09:52:32 florian
  974. * powerpc target fixed, very simple units can be compiled
  975. * some basic stuff for better callparanode handling, far from being finished
  976. Revision 1.11 2002/07/01 18:46:23 peter
  977. * internal linker
  978. * reorganized aasm layer
  979. Revision 1.10 2002/07/01 16:23:53 peter
  980. * cg64 patch
  981. * basics for currency
  982. * asnode updates for class and interface (not finished)
  983. Revision 1.9 2002/05/20 13:30:40 carl
  984. * bugfix of hdisponen (base must be set, not index)
  985. * more portability fixes
  986. }