ncgld.pas 49 KB

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