ncgld.pas 48 KB

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