ncgld.pas 50 KB

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