cg386ld.pas 47 KB

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