ncgld.pas 48 KB

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