cg386ld.pas 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Generate i386 assembler for load/assignment nodes
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit cg386ld;
  19. interface
  20. uses
  21. tree;
  22. procedure secondload(var p : ptree);
  23. procedure secondassignment(var p : ptree);
  24. procedure secondfuncret(var p : ptree);
  25. procedure secondarrayconstruct(var p : ptree);
  26. implementation
  27. uses
  28. globtype,systems,
  29. cobjects,verbose,globals,files,
  30. symconst,symtable,aasm,types,
  31. hcodegen,temp_gen,pass_2,
  32. cpubase,cpuasm,
  33. cgai386,tgeni386,cg386cnv,cresstr;
  34. {*****************************************************************************
  35. SecondLoad
  36. *****************************************************************************}
  37. procedure secondload(var p : ptree);
  38. var
  39. hregister : tregister;
  40. symtabletype : tsymtabletype;
  41. i : longint;
  42. hp : preference;
  43. s : pasmsymbol;
  44. popeax : boolean;
  45. pushed : tpushed;
  46. hr : treference;
  47. begin
  48. simple_loadn:=true;
  49. reset_reference(p^.location.reference);
  50. case p^.symtableentry^.typ of
  51. { this is only for toasm and toaddr }
  52. absolutesym :
  53. begin
  54. p^.location.reference.symbol:=nil;
  55. if (pabsolutesym(p^.symtableentry)^.abstyp=toaddr) then
  56. begin
  57. if pabsolutesym(p^.symtableentry)^.absseg then
  58. p^.location.reference.segment:=R_FS;
  59. p^.location.reference.offset:=pabsolutesym(p^.symtableentry)^.address;
  60. end
  61. else
  62. p^.location.reference.symbol:=newasmsymbol(p^.symtableentry^.mangledname);
  63. end;
  64. constsym:
  65. begin
  66. if pconstsym(p^.symtableentry)^.consttyp=constresourcestring then
  67. begin
  68. pushusedregisters(pushed,$ff);
  69. emit_const(A_PUSH,S_L,
  70. pconstsym(p^.symtableentry)^.resstrindex);
  71. emit_sym(A_PUSH,S_L,newasmsymbol(pconstsym(p^.symtableentry)^.owner^.name^+'_RESOURCESTRINGLIST'));
  72. emitcall('FPC_GETRESOURCESTRING');
  73. hregister:=getexplicitregister32(R_EAX);
  74. emit_reg_reg(A_MOV,S_L,R_EAX,hregister);
  75. gettempansistringreference(hr);
  76. decrstringref(p^.resulttype,hr);
  77. emit_reg_ref(A_MOV,S_L,hregister,
  78. newreference(hr));
  79. ungetregister32(hregister);
  80. popusedregisters(pushed);
  81. p^.location.loc:=LOC_MEM;
  82. p^.location.reference:=hr;
  83. end
  84. else
  85. internalerror(22798);
  86. end;
  87. varsym :
  88. begin
  89. hregister:=R_NO;
  90. { C variable }
  91. if (vo_is_C_var in pvarsym(p^.symtableentry)^.varoptions) then
  92. begin
  93. p^.location.reference.symbol:=newasmsymbol(p^.symtableentry^.mangledname);
  94. end
  95. { DLL variable }
  96. else if (vo_is_dll_var in pvarsym(p^.symtableentry)^.varoptions) then
  97. begin
  98. hregister:=getregister32;
  99. p^.location.reference.symbol:=newasmsymbol(p^.symtableentry^.mangledname);
  100. emit_ref_reg(A_MOV,S_L,newreference(p^.location.reference),hregister);
  101. p^.location.reference.symbol:=nil;
  102. p^.location.reference.base:=hregister;
  103. end
  104. { external variable }
  105. else if (vo_is_external in pvarsym(p^.symtableentry)^.varoptions) then
  106. begin
  107. p^.location.reference.symbol:=newasmsymbol(p^.symtableentry^.mangledname);
  108. end
  109. { thread variable }
  110. else if (vo_is_thread_var in pvarsym(p^.symtableentry)^.varoptions) then
  111. begin
  112. popeax:=not(R_EAX in unused);
  113. if popeax then
  114. emit_reg(A_PUSH,S_L,R_EAX);
  115. p^.location.reference.symbol:=newasmsymbol(p^.symtableentry^.mangledname);
  116. emit_ref(A_PUSH,S_L,newreference(p^.location.reference));
  117. { the called procedure isn't allowed to change }
  118. { any register except EAX }
  119. emitcall('FPC_RELOCATE_THREADVAR');
  120. reset_reference(p^.location.reference);
  121. p^.location.reference.base:=getregister32;
  122. emit_reg_reg(A_MOV,S_L,R_EAX,p^.location.reference.base);
  123. if popeax then
  124. emit_reg(A_POP,S_L,R_EAX);
  125. end
  126. { normal variable }
  127. else
  128. begin
  129. symtabletype:=p^.symtable^.symtabletype;
  130. { in case it is a register variable: }
  131. if pvarsym(p^.symtableentry)^.reg<>R_NO then
  132. begin
  133. if pvarsym(p^.symtableentry)^.reg in [R_ST0..R_ST7] then
  134. begin
  135. p^.location.loc:=LOC_CFPUREGISTER;
  136. p^.location.register:=pvarsym(p^.symtableentry)^.reg;
  137. end
  138. else
  139. begin
  140. p^.location.loc:=LOC_CREGISTER;
  141. p^.location.register:=pvarsym(p^.symtableentry)^.reg;
  142. unused:=unused-[pvarsym(p^.symtableentry)^.reg];
  143. end;
  144. end
  145. else
  146. begin
  147. { first handle local and temporary variables }
  148. if (symtabletype in [parasymtable,inlinelocalsymtable,
  149. inlineparasymtable,localsymtable]) then
  150. begin
  151. p^.location.reference.base:=procinfo^.framepointer;
  152. p^.location.reference.offset:=pvarsym(p^.symtableentry)^.address+p^.symtable^.address_fixup;
  153. if (symtabletype in [localsymtable,inlinelocalsymtable]) then
  154. begin
  155. if use_esp_stackframe then
  156. dec(p^.location.reference.offset,
  157. pvarsym(p^.symtableentry)^.getsize)
  158. else
  159. p^.location.reference.offset:=-p^.location.reference.offset;
  160. end;
  161. if (lexlevel>(p^.symtable^.symtablelevel)) then
  162. begin
  163. hregister:=getregister32;
  164. { make a reference }
  165. hp:=new_reference(procinfo^.framepointer,
  166. procinfo^.framepointer_offset);
  167. emit_ref_reg(A_MOV,S_L,hp,hregister);
  168. simple_loadn:=false;
  169. i:=lexlevel-1;
  170. while i>(p^.symtable^.symtablelevel) do
  171. begin
  172. { make a reference }
  173. hp:=new_reference(hregister,8);
  174. emit_ref_reg(A_MOV,S_L,hp,hregister);
  175. dec(i);
  176. end;
  177. p^.location.reference.base:=hregister;
  178. end;
  179. end
  180. else
  181. case symtabletype of
  182. unitsymtable,globalsymtable,
  183. staticsymtable :
  184. begin
  185. p^.location.reference.symbol:=newasmsymbol(p^.symtableentry^.mangledname);
  186. end;
  187. stt_exceptsymtable:
  188. begin
  189. p^.location.reference.base:=procinfo^.framepointer;
  190. p^.location.reference.offset:=pvarsym(p^.symtableentry)^.address;
  191. end;
  192. objectsymtable:
  193. begin
  194. if (sp_static in pvarsym(p^.symtableentry)^.symoptions) then
  195. begin
  196. p^.location.reference.symbol:=newasmsymbol(p^.symtableentry^.mangledname);
  197. end
  198. else
  199. begin
  200. p^.location.reference.base:=R_ESI;
  201. p^.location.reference.offset:=pvarsym(p^.symtableentry)^.address;
  202. end;
  203. end;
  204. withsymtable:
  205. begin
  206. { make a reference }
  207. { symtable datasize field
  208. contains the offset of the temp
  209. stored }
  210. { hp:=new_reference(procinfo^.framepointer,
  211. p^.symtable^.datasize);
  212. emit_ref_reg(A_MOV,S_L,hp,hregister);}
  213. if ptree(pwithsymtable(p^.symtable)^.withnode)^.islocal then
  214. begin
  215. p^.location.reference:=ptree(pwithsymtable(p^.symtable)^.withnode)^.withreference^;
  216. end
  217. else
  218. begin
  219. hregister:=getregister32;
  220. p^.location.reference.base:=hregister;
  221. emit_ref_reg(A_MOV,S_L,
  222. newreference(ptree(pwithsymtable(p^.symtable)^.withnode)^.withreference^),
  223. hregister);
  224. end;
  225. inc(p^.location.reference.offset,pvarsym(p^.symtableentry)^.address);
  226. end;
  227. end;
  228. end;
  229. { in case call by reference, then calculate. Open array
  230. is always an reference! }
  231. if (pvarsym(p^.symtableentry)^.varspez=vs_var) or
  232. is_open_array(pvarsym(p^.symtableentry)^.vartype.def) or
  233. is_array_of_const(pvarsym(p^.symtableentry)^.vartype.def) or
  234. ((pvarsym(p^.symtableentry)^.varspez=vs_const) and
  235. push_addr_param(pvarsym(p^.symtableentry)^.vartype.def)) then
  236. begin
  237. simple_loadn:=false;
  238. if hregister=R_NO then
  239. hregister:=getregister32;
  240. if p^.location.loc=LOC_CREGISTER then
  241. begin
  242. emit_reg_reg(A_MOV,S_L,
  243. p^.location.register,hregister);
  244. p^.location.loc:=LOC_REFERENCE;
  245. end
  246. else
  247. begin
  248. emit_ref_reg(A_MOV,S_L,
  249. newreference(p^.location.reference),
  250. hregister);
  251. end;
  252. reset_reference(p^.location.reference);
  253. p^.location.reference.base:=hregister;
  254. end;
  255. end;
  256. end;
  257. procsym:
  258. begin
  259. if assigned(p^.left) then
  260. begin
  261. secondpass(p^.left);
  262. p^.location.loc:=LOC_MEM;
  263. gettempofsizereference(8,p^.location.reference);
  264. { load class instance address }
  265. case p^.left^.location.loc of
  266. LOC_CREGISTER,
  267. LOC_REGISTER:
  268. begin
  269. hregister:=p^.left^.location.register;
  270. ungetregister32(p^.left^.location.register);
  271. if not(pobjectdef(p^.left^.resulttype)^.is_class) then
  272. CGMessage(cg_e_illegal_expression);
  273. end;
  274. LOC_MEM,
  275. LOC_REFERENCE:
  276. begin
  277. {$ifndef noAllocEdi}
  278. getexplicitregister32(R_EDI);
  279. {$endif noAllocEdi}
  280. hregister:=R_EDI;
  281. if pobjectdef(p^.left^.resulttype)^.is_class then
  282. emit_ref_reg(A_MOV,S_L,
  283. newreference(p^.left^.location.reference),R_EDI)
  284. else
  285. emit_ref_reg(A_LEA,S_L,
  286. newreference(p^.left^.location.reference),R_EDI);
  287. del_reference(p^.left^.location.reference);
  288. ungetiftemp(p^.left^.location.reference);
  289. end;
  290. else internalerror(26019);
  291. end;
  292. { store the class instance address }
  293. new(hp);
  294. hp^:=p^.location.reference;
  295. inc(hp^.offset,4);
  296. emit_reg_ref(A_MOV,S_L,
  297. hregister,hp);
  298. { virtual method ? }
  299. if (po_virtualmethod in pprocsym(p^.symtableentry)^.definition^.procoptions) then
  300. begin
  301. new(hp);
  302. reset_reference(hp^);
  303. hp^.base:=hregister;
  304. { load vmt pointer }
  305. emit_ref_reg(A_MOV,S_L,
  306. hp,R_EDI);
  307. {$IfDef regallocfix}
  308. del_reference(hp^);
  309. {$EndIf regallocfix}
  310. { load method address }
  311. new(hp);
  312. reset_reference(hp^);
  313. hp^.base:=R_EDI;
  314. hp^.offset:=pprocsym(p^.symtableentry)^.definition^._class^.vmtmethodoffset(
  315. pprocsym(p^.symtableentry)^.definition^.extnumber);
  316. emit_ref_reg(A_MOV,S_L,
  317. hp,R_EDI);
  318. { ... and store it }
  319. emit_reg_ref(A_MOV,S_L,
  320. R_EDI,newreference(p^.location.reference));
  321. {$ifndef noAllocEdi}
  322. ungetregister32(R_EDI);
  323. {$endif noAllocEdi}
  324. end
  325. else
  326. begin
  327. {$ifndef noAllocEdi}
  328. ungetregister32(R_EDI);
  329. {$endif noAllocEdi}
  330. s:=newasmsymbol(pprocsym(p^.symtableentry)^.definition^.mangledname);
  331. emit_sym_ofs_ref(A_MOV,S_L,s,0,
  332. newreference(p^.location.reference));
  333. end;
  334. end
  335. else
  336. begin
  337. {!!!!! Be aware, work on virtual methods too }
  338. p^.location.reference.symbol:=newasmsymbol(pprocsym(p^.symtableentry)^.definition^.mangledname);
  339. end;
  340. end;
  341. typedconstsym :
  342. begin
  343. p^.location.reference.symbol:=newasmsymbol(p^.symtableentry^.mangledname);
  344. end;
  345. else internalerror(4);
  346. end;
  347. end;
  348. {*****************************************************************************
  349. SecondAssignment
  350. *****************************************************************************}
  351. procedure secondassignment(var p : ptree);
  352. var
  353. opsize : topsize;
  354. otlabel,hlabel,oflabel : pasmlabel;
  355. fputyp : tfloattype;
  356. loc : tloc;
  357. r : preference;
  358. ai : paicpu;
  359. op : tasmop;
  360. pushed : boolean;
  361. begin
  362. otlabel:=truelabel;
  363. oflabel:=falselabel;
  364. getlabel(truelabel);
  365. getlabel(falselabel);
  366. { calculate left sides }
  367. if not(p^.concat_string) then
  368. secondpass(p^.left);
  369. if codegenerror then
  370. exit;
  371. {$ifdef dummy}
  372. { we use now the standard mechanism via maybe_push/restore
  373. to do that (FK)
  374. }
  375. case p^.left^.location.loc of
  376. LOC_REFERENCE : begin
  377. { in case left operator uses to register }
  378. { but to few are free then LEA }
  379. if (p^.left^.location.reference.base<>R_NO) and
  380. (p^.left^.location.reference.index<>R_NO) and
  381. (usablereg32<p^.right^.registers32) then
  382. begin
  383. del_reference(p^.left^.location.reference);
  384. hregister:=getregister32;
  385. emit_ref_reg(A_LEA,S_L,newreference(
  386. p^.left^.location.reference),
  387. hregister);
  388. reset_reference(p^.left^.location.reference);
  389. p^.left^.location.reference.base:=hregister;
  390. p^.left^.location.reference.index:=R_NO;
  391. end;
  392. loc:=LOC_REFERENCE;
  393. end;
  394. LOC_CFPUREGISTER:
  395. loc:=LOC_CFPUREGISTER;
  396. LOC_CREGISTER:
  397. loc:=LOC_CREGISTER;
  398. LOC_MMXREGISTER:
  399. loc:=LOC_MMXREGISTER;
  400. LOC_CMMXREGISTER:
  401. loc:=LOC_CMMXREGISTER;
  402. else
  403. begin
  404. CGMessage(cg_e_illegal_expression);
  405. exit;
  406. end;
  407. end;
  408. {$endif dummy}
  409. if not(p^.left^.location.loc in [LOC_REFERENCE,LOC_CFPUREGISTER,
  410. LOC_CREGISTER,LOC_MMXREGISTER,LOC_CMMXREGISTER]) then
  411. begin
  412. CGMessage(cg_e_illegal_expression);
  413. exit;
  414. end;
  415. loc:=p^.left^.location.loc;
  416. { lets try to optimize this (PM) }
  417. { define a dest_loc that is the location }
  418. { and a ptree to verify that it is the right }
  419. { place to insert it }
  420. {$ifdef test_dest_loc}
  421. if (aktexprlevel<4) then
  422. begin
  423. dest_loc_known:=true;
  424. dest_loc:=p^.left^.location;
  425. dest_loc_tree:=p^.right;
  426. end;
  427. {$endif test_dest_loc}
  428. { left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
  429. { can be false }
  430. pushed:=maybe_push(p^.right^.registers32,p^.left,false);
  431. secondpass(p^.right);
  432. if pushed then restore(p^.left,false);
  433. if codegenerror then
  434. exit;
  435. {$ifdef test_dest_loc}
  436. dest_loc_known:=false;
  437. if in_dest_loc then
  438. begin
  439. truelabel:=otlabel;
  440. falselabel:=oflabel;
  441. in_dest_loc:=false;
  442. exit;
  443. end;
  444. {$endif test_dest_loc}
  445. if p^.left^.resulttype^.deftype=stringdef then
  446. begin
  447. if is_ansistring(p^.left^.resulttype) then
  448. begin
  449. { the source and destinations are released
  450. in loadansistring, because an ansi string can
  451. also be in a register
  452. }
  453. loadansistring(p);
  454. end
  455. else
  456. if is_shortstring(p^.left^.resulttype) and
  457. not (p^.concat_string) then
  458. begin
  459. if is_ansistring(p^.right^.resulttype) then
  460. begin
  461. if (p^.right^.treetype=stringconstn) and
  462. (p^.right^.length=0) then
  463. begin
  464. emit_const_ref(A_MOV,S_B,
  465. 0,newreference(p^.left^.location.reference));
  466. {$IfDef regallocfix}
  467. del_reference(p^.left^.location.reference);
  468. {$EndIf regallocfix}
  469. end
  470. else
  471. loadansi2short(p^.right,p^.left);
  472. end
  473. else
  474. begin
  475. { we do not need destination anymore }
  476. del_reference(p^.left^.location.reference);
  477. {del_reference(p^.right^.location.reference);
  478. done in loadshortstring }
  479. loadshortstring(p);
  480. ungetiftemp(p^.right^.location.reference);
  481. end;
  482. end
  483. else if is_longstring(p^.left^.resulttype) then
  484. begin
  485. end
  486. else
  487. begin
  488. { its the only thing we have to do }
  489. del_reference(p^.right^.location.reference);
  490. end
  491. end
  492. else case p^.right^.location.loc of
  493. LOC_REFERENCE,
  494. LOC_MEM : begin
  495. { extra handling for ordinal constants }
  496. if (p^.right^.treetype in [ordconstn,fixconstn]) or
  497. (loc=LOC_CREGISTER) then
  498. begin
  499. case p^.left^.resulttype^.size of
  500. 1 : opsize:=S_B;
  501. 2 : opsize:=S_W;
  502. 4 : opsize:=S_L;
  503. { S_L is correct, the copy is done }
  504. { with two moves }
  505. 8 : opsize:=S_L;
  506. end;
  507. if loc=LOC_CREGISTER then
  508. begin
  509. emit_ref_reg(A_MOV,opsize,
  510. newreference(p^.right^.location.reference),
  511. p^.left^.location.register);
  512. if is_64bitint(p^.right^.resulttype) then
  513. begin
  514. r:=newreference(p^.right^.location.reference);
  515. inc(r^.offset,4);
  516. emit_ref_reg(A_MOV,opsize,r,
  517. p^.left^.location.registerhigh);
  518. end;
  519. {$IfDef regallocfix}
  520. del_reference(p^.right^.location.reference);
  521. {$EndIf regallocfix}
  522. end
  523. else
  524. begin
  525. emit_const_ref(A_MOV,opsize,
  526. p^.right^.location.reference.offset,
  527. newreference(p^.left^.location.reference));
  528. if is_64bitint(p^.right^.resulttype) then
  529. begin
  530. r:=newreference(p^.left^.location.reference);
  531. inc(r^.offset,4);
  532. emit_const_ref(A_MOV,opsize,
  533. 0,r);
  534. end;
  535. {$IfDef regallocfix}
  536. del_reference(p^.left^.location.reference);
  537. {$EndIf regallocfix}
  538. {emit_const_loc(A_MOV,opsize,
  539. p^.right^.location.reference.offset,
  540. p^.left^.location);}
  541. end;
  542. end
  543. else if loc=LOC_CFPUREGISTER then
  544. begin
  545. floatloadops(pfloatdef(p^.right^.resulttype)^.typ,op,opsize);
  546. emit_ref(op,opsize,
  547. newreference(p^.right^.location.reference));
  548. emit_reg(A_FSTP,S_NO,
  549. correct_fpuregister(p^.left^.location.register,fpuvaroffset+1));
  550. end
  551. else
  552. begin
  553. if (p^.right^.resulttype^.needs_inittable) and
  554. ( (p^.right^.resulttype^.deftype<>objectdef) or
  555. not(pobjectdef(p^.right^.resulttype)^.is_class)) then
  556. begin
  557. { this would be a problem }
  558. if not(p^.left^.resulttype^.needs_inittable) then
  559. internalerror(3457);
  560. { increment source reference counter }
  561. new(r);
  562. reset_reference(r^);
  563. r^.symbol:=p^.right^.resulttype^.get_inittable_label;
  564. emitpushreferenceaddr(r^);
  565. emitpushreferenceaddr(p^.right^.location.reference);
  566. emitcall('FPC_ADDREF');
  567. { decrement destination reference counter }
  568. new(r);
  569. reset_reference(r^);
  570. r^.symbol:=p^.left^.resulttype^.get_inittable_label;
  571. emitpushreferenceaddr(r^);
  572. emitpushreferenceaddr(p^.left^.location.reference);
  573. emitcall('FPC_DECREF');
  574. end;
  575. {$ifdef regallocfix}
  576. concatcopy(p^.right^.location.reference,
  577. p^.left^.location.reference,p^.left^.resulttype^.size,true,false);
  578. ungetiftemp(p^.right^.location.reference);
  579. {$Else regallocfix}
  580. concatcopy(p^.right^.location.reference,
  581. p^.left^.location.reference,p^.left^.resulttype^.size,false,false);
  582. ungetiftemp(p^.right^.location.reference);
  583. {$endif regallocfix}
  584. end;
  585. end;
  586. {$ifdef SUPPORT_MMX}
  587. LOC_CMMXREGISTER,
  588. LOC_MMXREGISTER:
  589. begin
  590. if loc=LOC_CMMXREGISTER then
  591. emit_reg_reg(A_MOVQ,S_NO,
  592. p^.right^.location.register,p^.left^.location.register)
  593. else
  594. emit_reg_ref(A_MOVQ,S_NO,
  595. p^.right^.location.register,newreference(p^.left^.location.reference));
  596. end;
  597. {$endif SUPPORT_MMX}
  598. LOC_REGISTER,
  599. LOC_CREGISTER : begin
  600. case p^.right^.resulttype^.size of
  601. 1 : opsize:=S_B;
  602. 2 : opsize:=S_W;
  603. 4 : opsize:=S_L;
  604. 8 : opsize:=S_L;
  605. end;
  606. { simplified with op_reg_loc }
  607. if loc=LOC_CREGISTER then
  608. begin
  609. emit_reg_reg(A_MOV,opsize,
  610. p^.right^.location.register,
  611. p^.left^.location.register);
  612. ungetregister(p^.right^.location.register);
  613. end
  614. else
  615. Begin
  616. emit_reg_ref(A_MOV,opsize,
  617. p^.right^.location.register,
  618. newreference(p^.left^.location.reference));
  619. ungetregister(p^.right^.location.register);
  620. {$IfDef regallocfix}
  621. del_reference(p^.left^.location.reference);
  622. {$EndIf regallocfix}
  623. end;
  624. if is_64bitint(p^.right^.resulttype) then
  625. begin
  626. { simplified with op_reg_loc }
  627. if loc=LOC_CREGISTER then
  628. emit_reg_reg(A_MOV,opsize,
  629. p^.right^.location.registerhigh,
  630. p^.left^.location.registerhigh)
  631. else
  632. begin
  633. r:=newreference(p^.left^.location.reference);
  634. inc(r^.offset,4);
  635. emit_reg_ref(A_MOV,opsize,
  636. p^.right^.location.registerhigh,r);
  637. end;
  638. end;
  639. {emit_reg_loc(A_MOV,opsize,
  640. p^.right^.location.register,
  641. p^.left^.location); }
  642. end;
  643. LOC_FPU : begin
  644. if (p^.left^.resulttype^.deftype=floatdef) then
  645. fputyp:=pfloatdef(p^.left^.resulttype)^.typ
  646. else
  647. if (p^.right^.resulttype^.deftype=floatdef) then
  648. fputyp:=pfloatdef(p^.right^.resulttype)^.typ
  649. else
  650. if (p^.right^.treetype=typeconvn) and
  651. (p^.right^.left^.resulttype^.deftype=floatdef) then
  652. fputyp:=pfloatdef(p^.right^.left^.resulttype)^.typ
  653. else
  654. fputyp:=s32real;
  655. case loc of
  656. LOC_CFPUREGISTER:
  657. begin
  658. emit_reg(A_FSTP,S_NO,
  659. correct_fpuregister(p^.left^.location.register,fpuvaroffset));
  660. dec(fpuvaroffset);
  661. end;
  662. LOC_REFERENCE:
  663. floatstore(fputyp,p^.left^.location.reference);
  664. else
  665. internalerror(48991);
  666. end;
  667. end;
  668. LOC_CFPUREGISTER: begin
  669. if (p^.left^.resulttype^.deftype=floatdef) then
  670. fputyp:=pfloatdef(p^.left^.resulttype)^.typ
  671. else
  672. if (p^.right^.resulttype^.deftype=floatdef) then
  673. fputyp:=pfloatdef(p^.right^.resulttype)^.typ
  674. else
  675. if (p^.right^.treetype=typeconvn) and
  676. (p^.right^.left^.resulttype^.deftype=floatdef) then
  677. fputyp:=pfloatdef(p^.right^.left^.resulttype)^.typ
  678. else
  679. fputyp:=s32real;
  680. emit_reg(A_FLD,S_NO,
  681. correct_fpuregister(p^.right^.location.register,fpuvaroffset));
  682. inc(fpuvaroffset);
  683. case loc of
  684. LOC_CFPUREGISTER:
  685. begin
  686. emit_reg(A_FSTP,S_NO,
  687. correct_fpuregister(p^.right^.location.register,fpuvaroffset));
  688. dec(fpuvaroffset);
  689. end;
  690. LOC_REFERENCE:
  691. floatstore(fputyp,p^.left^.location.reference);
  692. else
  693. internalerror(48992);
  694. end;
  695. end;
  696. LOC_JUMP : begin
  697. getlabel(hlabel);
  698. emitlab(truelabel);
  699. if loc=LOC_CREGISTER then
  700. emit_const_reg(A_MOV,S_B,
  701. 1,p^.left^.location.register)
  702. else
  703. emit_const_ref(A_MOV,S_B,
  704. 1,newreference(p^.left^.location.reference));
  705. {emit_const_loc(A_MOV,S_B,
  706. 1,p^.left^.location);}
  707. emitjmp(C_None,hlabel);
  708. emitlab(falselabel);
  709. if loc=LOC_CREGISTER then
  710. emit_reg_reg(A_XOR,S_B,
  711. p^.left^.location.register,
  712. p^.left^.location.register)
  713. else
  714. begin
  715. emit_const_ref(A_MOV,S_B,
  716. 0,newreference(p^.left^.location.reference));
  717. {$IfDef regallocfix}
  718. del_reference(p^.left^.location.reference);
  719. {$EndIf regallocfix}
  720. end;
  721. emitlab(hlabel);
  722. end;
  723. LOC_FLAGS : begin
  724. if loc=LOC_CREGISTER then
  725. emit_flag2reg(p^.right^.location.resflags,p^.left^.location.register)
  726. else
  727. begin
  728. ai:=new(paicpu,op_ref(A_Setcc,S_B,newreference(p^.left^.location.reference)));
  729. ai^.SetCondition(flag_2_cond[p^.right^.location.resflags]);
  730. exprasmlist^.concat(ai);
  731. end;
  732. {$IfDef regallocfix}
  733. del_reference(p^.left^.location.reference);
  734. {$EndIf regallocfix}
  735. end;
  736. end;
  737. truelabel:=otlabel;
  738. falselabel:=oflabel;
  739. end;
  740. {*****************************************************************************
  741. SecondFuncRet
  742. *****************************************************************************}
  743. procedure secondfuncret(var p : ptree);
  744. var
  745. hr : tregister;
  746. hp : preference;
  747. pp : pprocinfo;
  748. hr_valid : boolean;
  749. begin
  750. reset_reference(p^.location.reference);
  751. hr_valid:=false;
  752. if (not inlining_procedure) and
  753. (procinfo<>pprocinfo(p^.funcretprocinfo)) then
  754. begin
  755. hr:=getregister32;
  756. hr_valid:=true;
  757. hp:=new_reference(procinfo^.framepointer,
  758. procinfo^.framepointer_offset);
  759. emit_ref_reg(A_MOV,S_L,hp,hr);
  760. pp:=procinfo^.parent;
  761. { walk up the stack frame }
  762. while pp<>pprocinfo(p^.funcretprocinfo) do
  763. begin
  764. hp:=new_reference(hr,
  765. pp^.framepointer_offset);
  766. emit_ref_reg(A_MOV,S_L,hp,hr);
  767. pp:=pp^.parent;
  768. end;
  769. p^.location.reference.base:=hr;
  770. p^.location.reference.offset:=pp^.return_offset;
  771. end
  772. else
  773. begin
  774. p^.location.reference.base:=procinfo^.framepointer;
  775. p^.location.reference.offset:=procinfo^.return_offset;
  776. end;
  777. if ret_in_param(p^.rettype.def) then
  778. begin
  779. if not hr_valid then
  780. hr:=getregister32;
  781. emit_ref_reg(A_MOV,S_L,newreference(p^.location.reference),hr);
  782. p^.location.reference.base:=hr;
  783. p^.location.reference.offset:=0;
  784. end;
  785. end;
  786. {*****************************************************************************
  787. SecondArrayConstruct
  788. *****************************************************************************}
  789. const
  790. vtInteger = 0;
  791. vtBoolean = 1;
  792. vtChar = 2;
  793. vtExtended = 3;
  794. vtString = 4;
  795. vtPointer = 5;
  796. vtPChar = 6;
  797. vtObject = 7;
  798. vtClass = 8;
  799. vtWideChar = 9;
  800. vtPWideChar = 10;
  801. vtAnsiString = 11;
  802. vtCurrency = 12;
  803. vtVariant = 13;
  804. vtInterface = 14;
  805. vtWideString = 15;
  806. vtInt64 = 16;
  807. procedure secondarrayconstruct(var p : ptree);
  808. var
  809. hp : ptree;
  810. href : treference;
  811. lt : pdef;
  812. vaddr : boolean;
  813. vtype : longint;
  814. freetemp,
  815. dovariant : boolean;
  816. elesize : longint;
  817. begin
  818. dovariant:=p^.forcevaria or parraydef(p^.resulttype)^.isvariant;
  819. if dovariant then
  820. elesize:=8
  821. else
  822. begin
  823. elesize:=parraydef(p^.resulttype)^.elesize;
  824. if elesize>4 then
  825. internalerror(8765678);
  826. end;
  827. if not p^.cargs then
  828. begin
  829. reset_reference(p^.location.reference);
  830. { Allocate always a temp, also if no elements are required, to
  831. be sure that location is valid (PFV) }
  832. if parraydef(p^.resulttype)^.highrange=-1 then
  833. gettempofsizereference(elesize,p^.location.reference)
  834. else
  835. gettempofsizereference((parraydef(p^.resulttype)^.highrange+1)*elesize,p^.location.reference);
  836. href:=p^.location.reference;
  837. end;
  838. hp:=p;
  839. while assigned(hp) do
  840. begin
  841. if assigned(hp^.left) then
  842. begin
  843. freetemp:=true;
  844. secondpass(hp^.left);
  845. if codegenerror then
  846. exit;
  847. if dovariant then
  848. begin
  849. { find the correct vtype value }
  850. vtype:=$ff;
  851. vaddr:=false;
  852. lt:=hp^.left^.resulttype;
  853. case lt^.deftype of
  854. enumdef,
  855. orddef :
  856. begin
  857. if (lt^.deftype=enumdef) or
  858. is_integer(lt) then
  859. vtype:=vtInteger
  860. else
  861. if is_boolean(lt) then
  862. vtype:=vtBoolean
  863. else
  864. if (lt^.deftype=orddef) and (porddef(lt)^.typ=uchar) then
  865. vtype:=vtChar;
  866. end;
  867. floatdef :
  868. begin
  869. vtype:=vtExtended;
  870. vaddr:=true;
  871. end;
  872. procvardef,
  873. pointerdef :
  874. begin
  875. if is_pchar(lt) then
  876. vtype:=vtPChar
  877. else
  878. vtype:=vtPointer;
  879. end;
  880. classrefdef :
  881. vtype:=vtClass;
  882. objectdef :
  883. begin
  884. vtype:=vtObject;
  885. end;
  886. stringdef :
  887. begin
  888. if is_shortstring(lt) then
  889. begin
  890. vtype:=vtString;
  891. vaddr:=true;
  892. freetemp:=false;
  893. end
  894. else
  895. if is_ansistring(lt) then
  896. vtype:=vtAnsiString;
  897. end;
  898. end;
  899. if vtype=$ff then
  900. internalerror(14357);
  901. { write C style pushes or an pascal array }
  902. if p^.cargs then
  903. begin
  904. if vaddr then
  905. begin
  906. emit_to_mem(hp^.left);
  907. emit_push_lea_loc(hp^.left^.location,freetemp);
  908. del_reference(hp^.left^.location.reference);
  909. end
  910. else
  911. emit_push_loc(hp^.left^.location);
  912. end
  913. else
  914. begin
  915. { update href to the vtype field and write it }
  916. emit_const_ref(A_MOV,S_L,
  917. vtype,newreference(href));
  918. inc(href.offset,4);
  919. { write changing field update href to the next element }
  920. if vaddr then
  921. begin
  922. emit_to_mem(hp^.left);
  923. emit_lea_loc_ref(hp^.left^.location,href,freetemp);
  924. end
  925. else
  926. emit_mov_loc_ref(hp^.left^.location,href,S_L);
  927. inc(href.offset,4);
  928. end;
  929. end
  930. else
  931. { normal array constructor of the same type }
  932. begin
  933. case elesize of
  934. 1 :
  935. emit_mov_loc_ref(hp^.left^.location,href,S_B);
  936. 2 :
  937. emit_mov_loc_ref(hp^.left^.location,href,S_W);
  938. 4 :
  939. emit_mov_loc_ref(hp^.left^.location,href,S_L);
  940. else
  941. internalerror(87656781);
  942. end;
  943. inc(href.offset,elesize);
  944. end;
  945. end;
  946. { load next entry }
  947. hp:=hp^.right;
  948. end;
  949. end;
  950. end.
  951. {
  952. $Log$
  953. Revision 1.97 2000-01-21 12:17:42 jonas
  954. * regallocation fixes
  955. Revision 1.96 2000/01/09 12:35:01 jonas
  956. * changed edi allocation to use getexplicitregister32/ungetregister
  957. (adapted tgeni386 a bit for this) and enabled it by default
  958. * fixed very big and stupid bug of mine in cg386mat that broke the
  959. include() code (and make cycle :( ) if you compiled without
  960. -dnewoptimizations
  961. Revision 1.95 2000/01/09 01:44:20 jonas
  962. + (de)allocation info for EDI to fix reported bug on mailinglist.
  963. Also some (de)allocation info for ESI added. Between -dallocEDI
  964. because at this time of the night bugs could easily slip in ;)
  965. Revision 1.94 2000/01/07 01:14:21 peter
  966. * updated copyright to 2000
  967. Revision 1.93 1999/12/30 15:04:31 peter
  968. * fixed funcret within inlined procedure
  969. Revision 1.92 1999/12/22 01:01:47 peter
  970. - removed freelabel()
  971. * added undefined label detection in internal assembler, this prevents
  972. a lot of ld crashes and wrong .o files
  973. * .o files aren't written anymore if errors have occured
  974. * inlining of assembler labels is now correct
  975. Revision 1.91 1999/11/30 10:40:43 peter
  976. + ttype, tsymlist
  977. Revision 1.90 1999/11/06 14:34:18 peter
  978. * truncated log to 20 revs
  979. Revision 1.89 1999/10/12 22:35:48 florian
  980. * compiler didn't complain about l1+l2:=l1+l2; it gave only an assembler
  981. error, fixed
  982. Revision 1.88 1999/09/27 23:44:47 peter
  983. * procinfo is now a pointer
  984. * support for result setting in sub procedure
  985. Revision 1.87 1999/09/26 13:26:06 florian
  986. * exception patch of Romio nevertheless the excpetion handling
  987. needs some corections regarding register saving
  988. * gettempansistring is again a procedure
  989. Revision 1.86 1999/09/16 07:56:46 pierre
  990. * double del_reference removed
  991. Revision 1.85 1999/09/12 08:48:03 florian
  992. * bugs 593 and 607 fixed
  993. * some other potential bugs with array constructors fixed
  994. * for classes compiled in $M+ and it's childs, the default access method
  995. is now published
  996. * fixed copyright message (it is now 1998-2000)
  997. Revision 1.84 1999/09/11 09:08:31 florian
  998. * fixed bug 596
  999. * fixed some problems with procedure variables and procedures of object,
  1000. especially in TP mode. Procedure of object doesn't apply only to classes,
  1001. it is also allowed for objects !!
  1002. Revision 1.83 1999/09/01 09:37:14 peter
  1003. * removed warning
  1004. Revision 1.82 1999/09/01 09:26:21 peter
  1005. * fixed temp allocation for arrayconstructor
  1006. Revision 1.81 1999/08/28 15:34:17 florian
  1007. * bug 519 fixed
  1008. Revision 1.80 1999/08/26 20:24:37 michael
  1009. + Hopefuly last fixes for resourcestrings
  1010. Revision 1.79 1999/08/25 16:41:05 peter
  1011. * resources are working again
  1012. Revision 1.78 1999/08/25 11:59:43 jonas
  1013. * changed pai386, paippc and paiapha (same for tai*) to paicpu (taicpu)
  1014. Revision 1.77 1999/08/24 22:38:51 michael
  1015. * more resourcestring changes
  1016. Revision 1.76 1999/08/23 11:45:39 michael
  1017. * Hopefully final attempt at resourcestrings
  1018. Revision 1.75 1999/08/19 13:08:49 pierre
  1019. * emit_??? used
  1020. Revision 1.74 1999/08/17 13:26:06 peter
  1021. * arrayconstructor -> arrayofconst fixed when arraycosntructor was not
  1022. variant.
  1023. Revision 1.73 1999/08/13 21:33:09 peter
  1024. * support for array constructors extended and more error checking
  1025. Revision 1.72 1999/08/09 22:19:50 peter
  1026. * classes vmt changed to only positive addresses
  1027. * sharedlib creation is working
  1028. Revision 1.71 1999/08/07 14:20:55 florian
  1029. * some small problems fixed
  1030. Revision 1.70 1999/08/04 13:45:22 florian
  1031. + floating point register variables !!
  1032. * pairegalloc is now generated for register variables
  1033. }