ncgld.pas 47 KB

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