ncgld.pas 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133
  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,defutil,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. r,hregister : tregister;
  53. supreg:Tsuperregister;
  54. symtabletype : tsymtabletype;
  55. i : longint;
  56. href : treference;
  57. newsize : tcgsize;
  58. pushed : tpushedsavedint;
  59. dorelocatelab,
  60. norelocatelab : tasmlabel;
  61. begin
  62. { we don't know the size of all arrays }
  63. newsize:=def_cgsize(resulttype.def);
  64. location_reset(location,LOC_REFERENCE,newsize);
  65. case symtableentry.typ of
  66. absolutesym :
  67. begin
  68. { this is only for toasm and toaddr }
  69. if (tabsolutesym(symtableentry).abstyp=toaddr) then
  70. begin
  71. {$ifdef i386}
  72. if tabsolutesym(symtableentry).absseg then
  73. location.reference.segment.enum:=R_FS;
  74. {$endif i386}
  75. location.reference.offset:=tabsolutesym(symtableentry).address;
  76. end
  77. else
  78. location.reference.symbol:=objectlibrary.newasmsymboldata(tabsolutesym(symtableentry).mangledname);
  79. end;
  80. constsym:
  81. begin
  82. if tconstsym(symtableentry).consttyp=constresourcestring then
  83. begin
  84. location_reset(location,LOC_CREFERENCE,OS_ADDR);
  85. location.reference.symbol:=objectlibrary.newasmsymboldata(tconstsym(symtableentry).owner.name^+'_RESOURCESTRINGLIST');
  86. location.reference.offset:=tconstsym(symtableentry).resstrindex*16+8;
  87. end
  88. else
  89. internalerror(22798);
  90. end;
  91. varsym :
  92. begin
  93. symtabletype:=symtable.symtabletype;
  94. hregister.enum:=R_NO;
  95. { C variable }
  96. if (vo_is_C_var in tvarsym(symtableentry).varoptions) then
  97. begin
  98. location.reference.symbol:=objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname);
  99. end
  100. { DLL variable }
  101. else if (vo_is_dll_var in tvarsym(symtableentry).varoptions) then
  102. begin
  103. hregister:=rg.getaddressregister(exprasmlist);
  104. location.reference.symbol:=objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname);
  105. cg.a_load_ref_reg(exprasmlist,OS_ADDR,location.reference,hregister);
  106. reference_reset_base(location.reference,hregister,0);
  107. end
  108. { external variable }
  109. else if (vo_is_external in tvarsym(symtableentry).varoptions) then
  110. begin
  111. location.reference.symbol:=objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname);
  112. end
  113. { thread variable }
  114. else if (vo_is_thread_var in tvarsym(symtableentry).varoptions) then
  115. begin
  116. objectlibrary.getlabel(dorelocatelab);
  117. objectlibrary.getlabel(norelocatelab);
  118. { we've to allocate the register before we save the used registers }
  119. hregister:=rg.getaddressregister(exprasmlist);
  120. reference_reset_symbol(href,objectlibrary.newasmsymboldata('FPC_THREADVAR_RELOCATE'),0);
  121. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  122. cg.a_cmp_const_reg_label(exprasmlist,OS_ADDR,OC_NE,0,hregister,dorelocatelab);
  123. { no relocation needed, load the address of the variable only, the
  124. layout of a threadvar is (4 bytes pointer):
  125. 0 - Threadvar index
  126. 4 - Threadvar value in single threading }
  127. reference_reset_symbol(href,objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname),POINTER_SIZE);
  128. cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
  129. cg.a_jmp_always(exprasmlist,norelocatelab);
  130. cg.a_label(exprasmlist,dorelocatelab);
  131. if hregister.enum<>R_INTREGISTER then
  132. internalerror(200301171);
  133. { don't save the allocated register else the result will be destroyed later }
  134. rg.saveusedintregisters(exprasmlist,pushed,[RS_ACCUMULATOR]-[hregister.number shr 8]);
  135. reference_reset_symbol(href,objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname),0);
  136. cg.a_param_ref(exprasmlist,OS_ADDR,href,paramanager.getintparaloc(1));
  137. { the called procedure isn't allowed to change }
  138. { any register except EAX }
  139. cg.a_call_reg(exprasmlist,hregister);
  140. r.enum:=R_INTREGISTER;
  141. r.number:=NR_ACCUMULATOR;
  142. cg.a_load_reg_reg(exprasmlist,OS_INT,OS_ADDR,r,hregister);
  143. rg.restoreusedintregisters(exprasmlist,pushed);
  144. cg.a_label(exprasmlist,norelocatelab);
  145. location.reference.base:=hregister;
  146. end
  147. { normal variable }
  148. else
  149. begin
  150. { in case it is a register variable: }
  151. if tvarsym(symtableentry).reg.enum<>R_NO then
  152. begin
  153. if tvarsym(symtableentry).reg.enum in fpuregs then
  154. begin
  155. location_reset(location,LOC_CFPUREGISTER,def_cgsize(resulttype.def));
  156. location.register:=tvarsym(symtableentry).reg;
  157. end
  158. else if Tvarsym(symtableentry).reg.enum=R_INTREGISTER then
  159. begin
  160. supreg:=Tvarsym(symtableentry).reg.number shr 8;
  161. if (supreg in general_superregisters) and
  162. not (supreg in rg.regvar_loaded_int) then
  163. load_regvar(exprasmlist,tvarsym(symtableentry));
  164. location_reset(location,LOC_CREGISTER,cg.reg_cgsize(tvarsym(symtableentry).reg));
  165. location.register:=tvarsym(symtableentry).reg;
  166. exclude(rg.unusedregsint,supreg);
  167. end
  168. else
  169. internalerror(200301172);
  170. end
  171. else
  172. begin
  173. case symtabletype of
  174. localsymtable,
  175. parasymtable,
  176. inlinelocalsymtable,
  177. inlineparasymtable :
  178. begin
  179. location.reference.base:=procinfo.framepointer;
  180. if (symtabletype in [inlinelocalsymtable,
  181. localsymtable])
  182. {$ifdef powerpc}
  183. { the ifdef is only for speed reasons }
  184. and not(target_info.system in [system_powerpc_linux,system_powerpc_macos])
  185. {$endif powerpc}
  186. then
  187. location.reference.offset:=
  188. tvarsym(symtableentry).address-symtable.address_fixup
  189. else
  190. location.reference.offset:=
  191. tvarsym(symtableentry).address+symtable.address_fixup;
  192. {$ifndef powerpc}
  193. if (symtabletype in [localsymtable,inlinelocalsymtable]) then
  194. begin
  195. if use_esp_stackframe then
  196. dec(location.reference.offset,
  197. tvarsym(symtableentry).getvaluesize)
  198. else
  199. location.reference.offset:=-location.reference.offset;
  200. end;
  201. {$endif powerpc}
  202. if (lexlevel>symtable.symtablelevel) then
  203. begin
  204. hregister:=rg.getaddressregister(exprasmlist);
  205. { make a reference }
  206. reference_reset_base(href,procinfo.framepointer,procinfo.framepointer_offset);
  207. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  208. { walk parents }
  209. i:=lexlevel-1;
  210. while (i>symtable.symtablelevel) do
  211. begin
  212. { make a reference }
  213. reference_reset_base(href,hregister,target_info.first_parm_offset);
  214. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  215. dec(i);
  216. end;
  217. location.reference.base:=hregister;
  218. end;
  219. end;
  220. globalsymtable,
  221. staticsymtable :
  222. begin
  223. location.reference.symbol:=objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname);
  224. end;
  225. stt_exceptsymtable:
  226. begin
  227. location.reference.base:=procinfo.framepointer;
  228. location.reference.offset:=tvarsym(symtableentry).address;
  229. end;
  230. objectsymtable:
  231. begin
  232. if (sp_static in tvarsym(symtableentry).symoptions) then
  233. location.reference.symbol:=objectlibrary.newasmsymboldata(tvarsym(symtableentry).mangledname)
  234. else
  235. begin
  236. location.reference.base:=cg.g_load_self(exprasmlist);
  237. location.reference.offset:=tvarsym(symtableentry).address;
  238. end;
  239. end;
  240. withsymtable:
  241. begin
  242. if nf_islocal in tnode(twithsymtable(symtable).withnode).flags then
  243. location.reference:=twithnode(twithsymtable(symtable).withnode).withreference
  244. else
  245. begin
  246. location.reference.base:=rg.getaddressregister(exprasmlist);
  247. cg.a_load_ref_reg(exprasmlist,OS_ADDR,
  248. twithnode(twithsymtable(symtable).withnode).withreference,
  249. location.reference.base);
  250. end;
  251. inc(location.reference.offset,tvarsym(symtableentry).address);
  252. end;
  253. end;
  254. end;
  255. end;
  256. { handle call by reference variables }
  257. if (symtabletype in [parasymtable,inlineparasymtable]) then
  258. begin
  259. { in case call by reference, then calculate. Open array
  260. is always an reference! }
  261. if (tvarsym(symtableentry).varspez in [vs_var,vs_out]) or
  262. paramanager.push_addr_param(tvarsym(symtableentry).vartype.def,tprocdef(symtable.defowner).proccalloption) then
  263. begin
  264. if hregister.enum=R_NO then
  265. hregister:=rg.getaddressregister(exprasmlist);
  266. { we need to load only an address }
  267. location.size:=OS_ADDR;
  268. cg.a_load_loc_reg(exprasmlist,location,hregister);
  269. location_reset(location,LOC_REFERENCE,newsize);
  270. location.reference.base:=hregister;
  271. end;
  272. end;
  273. end;
  274. procsym:
  275. begin
  276. if assigned(left) then
  277. begin
  278. {
  279. THIS IS A TERRIBLE HACK!!!!!! WHICH WILL NOT WORK
  280. ON 64-BIT SYSTEMS: SINCE PROCSYM FOR METHODS
  281. CONSISTS OF TWO OS_ADDR, so you cannot set it
  282. to OS_64 - how to solve?? Carl
  283. }
  284. if (sizeof(aword) = 4) then
  285. location_reset(location,LOC_CREFERENCE,OS_64)
  286. else
  287. internalerror(20020520);
  288. tg.GetTemp(exprasmlist,2*POINTER_SIZE,tt_normal,location.reference);
  289. secondpass(left);
  290. { load class instance address }
  291. case left.location.loc of
  292. LOC_CREGISTER,
  293. LOC_REGISTER:
  294. begin
  295. hregister:=left.location.register;
  296. if is_object(left.resulttype.def) then
  297. CGMessage(cg_e_illegal_expression);
  298. end;
  299. LOC_CREFERENCE,
  300. LOC_REFERENCE:
  301. begin
  302. hregister:=rg.getaddressregister(exprasmlist);
  303. if is_class_or_interface(left.resulttype.def) then
  304. cg.a_load_ref_reg(exprasmlist,OS_ADDR,left.location.reference,hregister)
  305. else
  306. cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,hregister);
  307. location_release(exprasmlist,left.location);
  308. location_freetemp(exprasmlist,left.location);
  309. end;
  310. else
  311. internalerror(26019);
  312. end;
  313. { store the class instance address }
  314. href:=location.reference;
  315. inc(href.offset,POINTER_SIZE);
  316. cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,href);
  317. { virtual method ? }
  318. if (po_virtualmethod in tprocdef(resulttype.def).procoptions) then
  319. begin
  320. { load vmt pointer }
  321. reference_reset_base(href,hregister,0);
  322. reference_release(exprasmlist,href);
  323. hregister:=rg.getaddressregister(exprasmlist);
  324. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  325. reference_reset_base(href,hregister,tprocdef(resulttype.def)._class.vmtmethodoffset(
  326. tprocdef(resulttype.def).extnumber));
  327. reference_release(exprasmlist,href);
  328. { load method address }
  329. hregister:=rg.getaddressregister(exprasmlist);
  330. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hregister);
  331. { ... and store it }
  332. cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,location.reference);
  333. rg.ungetaddressregister(exprasmlist,hregister);
  334. end
  335. else
  336. begin
  337. { we don't use the hregister }
  338. rg.ungetregisterint(exprasmlist,hregister);
  339. { load address of the function }
  340. reference_reset_symbol(href,objectlibrary.newasmsymbol(tprocdef(resulttype.def).mangledname),0);
  341. hregister:=cg.get_scratch_reg_address(exprasmlist);
  342. cg.a_loadaddr_ref_reg(exprasmlist,href,hregister);
  343. cg.a_load_reg_ref(exprasmlist,OS_ADDR,hregister,location.reference);
  344. cg.free_scratch_reg(exprasmlist,hregister);
  345. end;
  346. end
  347. else
  348. begin
  349. {!!!!! Be aware, work on virtual methods too }
  350. location.reference.symbol:=objectlibrary.newasmsymbol(tprocdef(resulttype.def).mangledname);
  351. end;
  352. end;
  353. typedconstsym :
  354. begin
  355. location.reference.symbol:=objectlibrary.newasmsymboldata(ttypedconstsym(symtableentry).mangledname);
  356. end;
  357. else internalerror(4);
  358. end;
  359. end;
  360. {*****************************************************************************
  361. SecondAssignment
  362. *****************************************************************************}
  363. procedure tcgassignmentnode.pass_2;
  364. var
  365. otlabel,hlabel,oflabel : tasmlabel;
  366. fputyp : tfloattype;
  367. href : treference;
  368. releaseright : boolean;
  369. pushedregs : tmaybesave;
  370. cgsize : tcgsize;
  371. r:Tregister;
  372. begin
  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. But not when the result is in the flags, then
  380. loading the left node afterwards can destroy the flags.
  381. when the right node returns as LOC_JUMP then we will generate
  382. the following code:
  383. rightnode
  384. true:
  385. leftnode
  386. assign 1
  387. false:
  388. leftnode
  389. assign 0
  390. }
  391. { Try to determine which side to calculate first, }
  392. if (right.location.loc<>LOC_FLAGS) and
  393. ((right.location.loc=LOC_JUMP) or
  394. (right.nodetype=calln) or
  395. (right.registers32>=left.registers32)) then
  396. begin
  397. secondpass(right);
  398. { increment source reference counter, this is
  399. useless for string constants}
  400. if (right.resulttype.def.needs_inittable) and
  401. (right.nodetype<>stringconstn) then
  402. cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference);
  403. if codegenerror then
  404. exit;
  405. { We skip the generation of the left node when it's a jump, see
  406. explanation above }
  407. if (right.location.loc<>LOC_JUMP) and
  408. not(nf_concat_string in flags) then
  409. begin
  410. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  411. { can be false }
  412. maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
  413. secondpass(left);
  414. { decrement destination reference counter }
  415. if (left.resulttype.def.needs_inittable) then
  416. cg.g_decrrefcount(exprasmlist,left.resulttype.def,left.location.reference);
  417. maybe_restore(exprasmlist,right.location,pushedregs);
  418. if codegenerror then
  419. exit;
  420. end;
  421. end
  422. else
  423. begin
  424. { calculate left sides }
  425. { don't do it yet if it's a crgister (JM) }
  426. if not(nf_concat_string in flags) then
  427. begin
  428. secondpass(left);
  429. { decrement destination reference counter }
  430. if (left.resulttype.def.needs_inittable) then
  431. cg.g_decrrefcount(exprasmlist,left.resulttype.def,left.location.reference);
  432. if codegenerror then
  433. exit;
  434. end;
  435. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  436. { can be false }
  437. maybe_save(exprasmlist,right.registers32,left.location,pushedregs);
  438. secondpass(right);
  439. { increment source reference counter, this is
  440. useless for string constants}
  441. if (right.resulttype.def.needs_inittable) and
  442. (right.nodetype<>stringconstn) then
  443. cg.g_incrrefcount(exprasmlist,right.resulttype.def,right.location.reference);
  444. maybe_restore(exprasmlist,left.location,pushedregs);
  445. if codegenerror then
  446. exit;
  447. end;
  448. if not(left.location.loc in [LOC_REFERENCE,LOC_CFPUREGISTER,
  449. {$ifdef SUPPORT_MMX}LOC_CMMXREGISTER,{$endif}
  450. LOC_CREGISTER]) then
  451. begin
  452. CGMessage(cg_e_illegal_expression);
  453. exit;
  454. end;
  455. releaseright:=true;
  456. { shortstring assignments are handled separately }
  457. if is_shortstring(left.resulttype.def) then
  458. begin
  459. {
  460. we can get here only in the following situations
  461. for the right node:
  462. - empty constant string
  463. - char
  464. }
  465. { empty constant string }
  466. if (right.nodetype=stringconstn) and
  467. (tstringconstnode(right).len=0) then
  468. begin
  469. cg.a_load_const_ref(exprasmlist,OS_8,0,left.location.reference);
  470. end
  471. { char loading }
  472. else if is_char(right.resulttype.def) then
  473. begin
  474. if right.nodetype=ordconstn then
  475. begin
  476. if (target_info.endian = endian_little) then
  477. cg.a_load_const_ref(exprasmlist,OS_16,(tordconstnode(right).value shl 8) or 1,
  478. left.location.reference)
  479. else
  480. cg.a_load_const_ref(exprasmlist,OS_16,tordconstnode(right).value or (1 shl 8),
  481. left.location.reference);
  482. end
  483. else
  484. begin
  485. href:=left.location.reference;
  486. cg.a_load_const_ref(exprasmlist,OS_8,1,href);
  487. inc(href.offset,1);
  488. case right.location.loc of
  489. LOC_REGISTER,
  490. LOC_CREGISTER :
  491. begin
  492. r.enum:=R_INTREGISTER;
  493. r.number:=(right.location.register.number and not $ff) or R_SUBL;
  494. cg.a_load_reg_ref(exprasmlist,OS_8,r,href);
  495. end;
  496. LOC_REFERENCE,
  497. LOC_CREFERENCE :
  498. cg.a_load_ref_ref(exprasmlist,OS_8,right.location.reference,href);
  499. else
  500. internalerror(200205111);
  501. end;
  502. end;
  503. end
  504. else
  505. internalerror(200204249);
  506. end
  507. else
  508. begin
  509. case right.location.loc of
  510. LOC_CONSTANT :
  511. begin
  512. if right.location.size in [OS_64,OS_S64] then
  513. cg64.a_load64_const_loc(exprasmlist,
  514. right.location.valueqword,left.location)
  515. else
  516. cg.a_load_const_loc(exprasmlist,right.location.value,left.location);
  517. end;
  518. LOC_REFERENCE,
  519. LOC_CREFERENCE :
  520. begin
  521. case left.location.loc of
  522. LOC_CREGISTER :
  523. begin
  524. cgsize:=def_cgsize(left.resulttype.def);
  525. if cgsize in [OS_64,OS_S64] then
  526. cg64.a_load64_ref_reg(exprasmlist,
  527. right.location.reference,left.location.register64)
  528. else
  529. cg.a_load_ref_reg(exprasmlist,cgsize,
  530. right.location.reference,left.location.register);
  531. location_release(exprasmlist,right.location);
  532. end;
  533. LOC_CFPUREGISTER :
  534. begin
  535. cg.a_loadfpu_ref_reg(exprasmlist,
  536. def_cgsize(right.resulttype.def),
  537. right.location.reference,
  538. left.location.register);
  539. end;
  540. LOC_REFERENCE,
  541. LOC_CREFERENCE :
  542. begin
  543. cg.g_concatcopy(exprasmlist,right.location.reference,
  544. left.location.reference,left.resulttype.def.size,true,false);
  545. { right.location is already released by concatcopy }
  546. releaseright:=false;
  547. end;
  548. else
  549. internalerror(200203284);
  550. end;
  551. end;
  552. {$ifdef SUPPORT_MMX}
  553. LOC_CMMXREGISTER,
  554. LOC_MMXREGISTER:
  555. begin
  556. if left.location.loc=LOC_CMMXREGISTER then
  557. cg.a_loadmm_reg_reg(exprasmlist,right.location.register,left.location.register)
  558. else
  559. cg.a_loadmm_reg_ref(exprasmlist,right.location.register,left.location.reference);
  560. end;
  561. {$endif SUPPORT_MMX}
  562. LOC_REGISTER,
  563. LOC_CREGISTER :
  564. begin
  565. cgsize:=def_cgsize(left.resulttype.def);
  566. if cgsize in [OS_64,OS_S64] then
  567. cg64.a_load64_reg_loc(exprasmlist,
  568. right.location.register64,left.location)
  569. else
  570. cg.a_load_reg_loc(exprasmlist,right.location.size,right.location.register,left.location);
  571. end;
  572. LOC_FPUREGISTER,LOC_CFPUREGISTER :
  573. begin
  574. if (left.resulttype.def.deftype=floatdef) then
  575. fputyp:=tfloatdef(left.resulttype.def).typ
  576. else
  577. if (right.resulttype.def.deftype=floatdef) then
  578. fputyp:=tfloatdef(right.resulttype.def).typ
  579. else
  580. if (right.nodetype=typeconvn) and
  581. (ttypeconvnode(right).left.resulttype.def.deftype=floatdef) then
  582. fputyp:=tfloatdef(ttypeconvnode(right).left.resulttype.def).typ
  583. else
  584. fputyp:=s32real;
  585. cg.a_loadfpu_reg_loc(exprasmlist,
  586. tfloat2tcgsize[fputyp],
  587. right.location.register,left.location);
  588. end;
  589. LOC_JUMP :
  590. begin
  591. cgsize:=def_cgsize(left.resulttype.def);
  592. objectlibrary.getlabel(hlabel);
  593. { generate the leftnode for the true case, and
  594. release the location }
  595. cg.a_label(exprasmlist,truelabel);
  596. maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
  597. secondpass(left);
  598. maybe_restore(exprasmlist,right.location,pushedregs);
  599. if codegenerror then
  600. exit;
  601. cg.a_load_const_loc(exprasmlist,1,left.location);
  602. location_release(exprasmlist,left.location);
  603. cg.a_jmp_always(exprasmlist,hlabel);
  604. { generate the leftnode for the false case }
  605. cg.a_label(exprasmlist,falselabel);
  606. maybe_save(exprasmlist,left.registers32,right.location,pushedregs);
  607. secondpass(left);
  608. maybe_restore(exprasmlist,right.location,pushedregs);
  609. if codegenerror then
  610. exit;
  611. cg.a_load_const_loc(exprasmlist,0,left.location);
  612. cg.a_label(exprasmlist,hlabel);
  613. end;
  614. {$ifdef cpuflags}
  615. LOC_FLAGS :
  616. begin
  617. {This can be a wordbool or longbool too, no?}
  618. if left.location.loc=LOC_CREGISTER then
  619. cg.g_flags2reg(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.register)
  620. else
  621. begin
  622. if not(left.location.loc = LOC_REFERENCE) then
  623. internalerror(200203273);
  624. cg.g_flags2ref(exprasmlist,def_cgsize(left.resulttype.def),right.location.resflags,left.location.reference);
  625. end;
  626. end;
  627. {$endif cpuflags}
  628. end;
  629. end;
  630. if releaseright then
  631. location_release(exprasmlist,right.location);
  632. location_release(exprasmlist,left.location);
  633. truelabel:=otlabel;
  634. falselabel:=oflabel;
  635. end;
  636. {*****************************************************************************
  637. SecondFuncRet
  638. *****************************************************************************}
  639. procedure tcgfuncretnode.pass_2;
  640. var
  641. hreg : tregister;
  642. href : treference;
  643. pp : tprocinfo;
  644. hr_valid : boolean;
  645. i : integer;
  646. begin
  647. location_reset(location,LOC_REFERENCE,def_cgsize(resulttype.def));
  648. hr_valid:=false;
  649. if (not inlining_procedure) and
  650. (lexlevel<>funcretsym.owner.symtablelevel) then
  651. begin
  652. hreg:=rg.getaddressregister(exprasmlist);
  653. hr_valid:=true;
  654. reference_reset_base(href,procinfo.framepointer,procinfo.framepointer_offset);
  655. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hreg);
  656. { walk up the stack frame }
  657. pp:=procinfo.parent;
  658. i:=lexlevel-1;
  659. while i>funcretsym.owner.symtablelevel do
  660. begin
  661. reference_reset_base(href,hreg,pp.framepointer_offset);
  662. cg.a_load_ref_reg(exprasmlist,OS_ADDR,href,hreg);
  663. pp:=pp.parent;
  664. dec(i);
  665. end;
  666. location.reference.base:=hreg;
  667. location.reference.offset:=pp.return_offset;
  668. end
  669. else
  670. begin
  671. location.reference.base:=procinfo.framepointer;
  672. location.reference.offset:=procinfo.return_offset;
  673. end;
  674. if paramanager.ret_in_param(funcretsym.returntype.def,
  675. tprocdef(funcretsym.owner.defowner).proccalloption) 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. location_reset(location,LOC_REFERENCE,OS_NO);
  725. if not(nf_cargs in flags) then
  726. begin
  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. if not(nf_cargs in flags) then
  763. begin
  764. freetemp:=false;
  765. vaddr:=true;
  766. end;
  767. end
  768. else if (lt.deftype=enumdef) or
  769. is_integer(lt) then
  770. vtype:=vtInteger
  771. else
  772. if is_boolean(lt) then
  773. vtype:=vtBoolean
  774. else
  775. if (lt.deftype=orddef) then
  776. begin
  777. case torddef(lt).typ of
  778. uchar:
  779. vtype:=vtChar;
  780. uwidechar:
  781. vtype:=vtWideChar;
  782. end;
  783. end;
  784. end;
  785. floatdef :
  786. begin
  787. vtype:=vtExtended;
  788. if not(nf_cargs in flags) then
  789. begin
  790. freetemp:=false;
  791. vaddr:=true;
  792. end;
  793. end;
  794. procvardef,
  795. pointerdef :
  796. begin
  797. if is_pchar(lt) then
  798. vtype:=vtPChar
  799. else
  800. vtype:=vtPointer;
  801. end;
  802. variantdef :
  803. begin
  804. vtype:=vtVariant;
  805. vaddr:=true;
  806. freetemp:=false;
  807. end;
  808. classrefdef :
  809. vtype:=vtClass;
  810. objectdef :
  811. vtype:=vtObject;
  812. stringdef :
  813. begin
  814. if is_shortstring(lt) then
  815. begin
  816. vtype:=vtString;
  817. vaddr:=true;
  818. freetemp:=false;
  819. end
  820. else
  821. if is_ansistring(lt) then
  822. begin
  823. vtype:=vtAnsiString;
  824. freetemp:=false;
  825. end
  826. else
  827. if is_widestring(lt) then
  828. begin
  829. vtype:=vtWideString;
  830. freetemp:=false;
  831. end;
  832. end;
  833. end;
  834. if vtype=$ff then
  835. internalerror(14357);
  836. { write C style pushes or an pascal array }
  837. if nf_cargs in flags then
  838. begin
  839. if vaddr then
  840. begin
  841. location_force_mem(exprasmlist,hp.left.location);
  842. cg.a_paramaddr_ref(exprasmlist,hp.left.location.reference,paralocdummy);
  843. location_release(exprasmlist,hp.left.location);
  844. if freetemp then
  845. location_freetemp(exprasmlist,hp.left.location);
  846. inc(pushedparasize,pointer_size);
  847. end
  848. else
  849. if vtype in [vtInt64,vtQword,vtExtended] then
  850. push_value_para(exprasmlist,hp.left,pocall_cdecl,0,4,paralocdummy)
  851. else
  852. begin
  853. cg.a_param_loc(exprasmlist,hp.left.location,paralocdummy);
  854. inc(pushedparasize,pointer_size);
  855. end;
  856. end
  857. else
  858. begin
  859. { write changing field update href to the next element }
  860. inc(href.offset,4);
  861. if vaddr then
  862. begin
  863. location_force_mem(exprasmlist,hp.left.location);
  864. tmpreg:=cg.get_scratch_reg_address(exprasmlist);
  865. cg.a_loadaddr_ref_reg(exprasmlist,hp.left.location.reference,tmpreg);
  866. cg.a_load_reg_ref(exprasmlist,OS_ADDR,tmpreg,href);
  867. cg.free_scratch_reg(exprasmlist,tmpreg);
  868. location_release(exprasmlist,hp.left.location);
  869. if freetemp then
  870. location_freetemp(exprasmlist,hp.left.location);
  871. end
  872. else
  873. begin
  874. location_release(exprasmlist,hp.left.location);
  875. cg.a_load_loc_ref(exprasmlist,hp.left.location,href);
  876. end;
  877. { update href to the vtype field and write it }
  878. dec(href.offset,4);
  879. cg.a_load_const_ref(exprasmlist, OS_INT,vtype,href);
  880. { goto next array element }
  881. inc(href.offset,8);
  882. end;
  883. end
  884. else
  885. { normal array constructor of the same type }
  886. begin
  887. location_release(exprasmlist,hp.left.location);
  888. case hp.left.location.loc of
  889. LOC_FPUREGISTER,
  890. LOC_CFPUREGISTER :
  891. begin
  892. location_release(exprasmlist,hp.left.location);
  893. cg.a_loadfpu_reg_ref(exprasmlist,hp.left.location.size,hp.left.location.register,href);
  894. end;
  895. LOC_REFERENCE,
  896. LOC_CREFERENCE :
  897. begin
  898. cg.g_concatcopy(exprasmlist,hp.left.location.reference,href,elesize,freetemp,false);
  899. end;
  900. else
  901. begin
  902. if hp.left.location.size in [OS_64,OS_S64] then
  903. cg64.a_load64_loc_ref(exprasmlist,hp.left.location,href)
  904. else
  905. cg.a_load_loc_ref(exprasmlist,hp.left.location,href);
  906. end;
  907. end;
  908. inc(href.offset,elesize);
  909. end;
  910. end;
  911. { load next entry }
  912. hp:=tarrayconstructornode(hp.right);
  913. end;
  914. end;
  915. begin
  916. cloadnode:=tcgloadnode;
  917. cassignmentnode:=tcgassignmentnode;
  918. cfuncretnode:=tcgfuncretnode;
  919. carrayconstructornode:=tcgarrayconstructornode;
  920. end.
  921. {
  922. $Log$
  923. Revision 1.47 2003-04-06 21:11:23 olle
  924. * changed newasmsymbol to newasmsymboldata for data symbols
  925. Revision 1.46 2003/03/28 19:16:56 peter
  926. * generic constructor working for i386
  927. * remove fixed self register
  928. * esi added as address register for i386
  929. Revision 1.45 2003/02/19 22:00:14 daniel
  930. * Code generator converted to new register notation
  931. - Horribily outdated todo.txt removed
  932. Revision 1.44 2003/01/08 18:43:56 daniel
  933. * Tregister changed into a record
  934. Revision 1.43 2003/01/05 22:44:14 peter
  935. * remove a lot of code to support typen in loadn-procsym
  936. Revision 1.42 2002/12/20 18:13:46 peter
  937. * fixes for fpu values in arrayconstructor
  938. Revision 1.41 2002/11/27 20:04:39 peter
  939. * cdecl array of const fixes
  940. Revision 1.40 2002/11/25 17:43:18 peter
  941. * splitted defbase in defutil,symutil,defcmp
  942. * merged isconvertable and is_equal into compare_defs(_ext)
  943. * made operator search faster by walking the list only once
  944. Revision 1.39 2002/11/22 16:22:45 jonas
  945. * fixed error in my previous commit (the size of the location of the
  946. funcretnode must be based on the current resulttype of the node and not
  947. the resulttype defined by the function; these can be different in case
  948. of "absolute" declarations)
  949. Revision 1.38 2002/11/18 17:31:54 peter
  950. * pass proccalloption to ret_in_xxx and push_xxx functions
  951. Revision 1.37 2002/11/15 21:16:39 jonas
  952. * proper fix for tw2110, also fixes tb0416 (funcretnode of parent
  953. function was handled wrong inside nested functions/procedures)
  954. Revision 1.36 2002/11/15 01:58:51 peter
  955. * merged changes from 1.0.7 up to 04-11
  956. - -V option for generating bug report tracing
  957. - more tracing for option parsing
  958. - errors for cdecl and high()
  959. - win32 import stabs
  960. - win32 records<=8 are returned in eax:edx (turned off by default)
  961. - heaptrc update
  962. - more info for temp management in .s file with EXTDEBUG
  963. Revision 1.35 2002/10/14 19:44:13 peter
  964. * (hacked) new threadvar relocate code
  965. Revision 1.34 2002/10/13 11:22:06 florian
  966. * fixed threadvars
  967. Revision 1.33 2002/10/03 21:32:02 carl
  968. * bugfix for 2110 (without -Or), wrong checking was done in returntype
  969. Revision 1.32 2002/09/30 07:00:46 florian
  970. * fixes to common code to get the alpha compiler compiled applied
  971. Revision 1.31 2002/09/26 15:02:05 florian
  972. + support of passing variants to "array of const"
  973. Revision 1.30 2002/09/17 18:54:02 jonas
  974. * a_load_reg_reg() now has two size parameters: source and dest. This
  975. allows some optimizations on architectures that don't encode the
  976. register size in the register name.
  977. Revision 1.29 2002/09/07 15:25:03 peter
  978. * old logs removed and tabs fixed
  979. Revision 1.28 2002/09/01 19:26:32 peter
  980. * fixed register variable loading from parasymtable, the call by
  981. reference code was moved wrong
  982. Revision 1.27 2002/09/01 12:15:40 peter
  983. * fixed loading of procvar of object when the object is initialized
  984. with 0
  985. Revision 1.26 2002/08/25 19:25:18 peter
  986. * sym.insert_in_data removed
  987. * symtable.insertvardata/insertconstdata added
  988. * removed insert_in_data call from symtable.insert, it needs to be
  989. called separatly. This allows to deref the address calculation
  990. * procedures now calculate the parast addresses after the procedure
  991. directives are parsed. This fixes the cdecl parast problem
  992. * push_addr_param has an extra argument that specifies if cdecl is used
  993. or not
  994. Revision 1.25 2002/08/23 16:14:48 peter
  995. * tempgen cleanup
  996. * tt_noreuse temp type added that will be used in genentrycode
  997. Revision 1.24 2002/08/17 09:23:35 florian
  998. * first part of procinfo rewrite
  999. Revision 1.23 2002/08/14 18:13:28 jonas
  1000. * adapted previous fix to Peter's asmsymbol patch
  1001. Revision 1.22 2002/08/14 18:00:42 jonas
  1002. * fixed tb0403
  1003. Revision 1.21 2002/08/13 21:40:56 florian
  1004. * more fixes for ppc calling conventions
  1005. Revision 1.20 2002/08/11 14:32:26 peter
  1006. * renamed current_library to objectlibrary
  1007. Revision 1.19 2002/08/11 13:24:12 peter
  1008. * saving of asmsymbols in ppu supported
  1009. * asmsymbollist global is removed and moved into a new class
  1010. tasmlibrarydata that will hold the info of a .a file which
  1011. corresponds with a single module. Added librarydata to tmodule
  1012. to keep the library info stored for the module. In the future the
  1013. objectfiles will also be stored to the tasmlibrarydata class
  1014. * all getlabel/newasmsymbol and friends are moved to the new class
  1015. Revision 1.18 2002/08/06 20:55:21 florian
  1016. * first part of ppc calling conventions fix
  1017. Revision 1.17 2002/07/28 09:25:37 carl
  1018. + correct size of parameter (64-bit portability)
  1019. Revision 1.16 2002/07/27 19:53:51 jonas
  1020. + generic implementation of tcg.g_flags2ref()
  1021. * tcg.flags2xxx() now also needs a size parameter
  1022. Revision 1.15 2002/07/20 11:57:54 florian
  1023. * types.pas renamed to defbase.pas because D6 contains a types
  1024. unit so this would conflicts if D6 programms are compiled
  1025. + Willamette/SSE2 instructions to assembler added
  1026. Revision 1.14 2002/07/16 09:17:44 florian
  1027. * threadvar relocation result wasn't handled properly, it could cause
  1028. a crash
  1029. Revision 1.13 2002/07/11 14:41:28 florian
  1030. * start of the new generic parameter handling
  1031. Revision 1.12 2002/07/07 09:52:32 florian
  1032. * powerpc target fixed, very simple units can be compiled
  1033. * some basic stuff for better callparanode handling, far from being finished
  1034. Revision 1.11 2002/07/01 18:46:23 peter
  1035. * internal linker
  1036. * reorganized aasm layer
  1037. Revision 1.10 2002/07/01 16:23:53 peter
  1038. * cg64 patch
  1039. * basics for currency
  1040. * asnode updates for class and interface (not finished)
  1041. Revision 1.9 2002/05/20 13:30:40 carl
  1042. * bugfix of hdisponen (base must be set, not index)
  1043. * more portability fixes
  1044. }