cg386ld.pas 48 KB

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