ncgld.pas 44 KB

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