cg386ld.pas 47 KB

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