ncgld.pas 50 KB

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