cg386ld.pas 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071
  1. {
  2. $Id$
  3. Copyright (c) 1993-98 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,
  30. symtable,aasm,types,
  31. hcodegen,temp_gen,pass_2,
  32. {$ifndef OLDASM}
  33. i386base,i386asm,
  34. {$else}
  35. i386,
  36. {$endif}
  37. cgai386,tgeni386,cg386cnv;
  38. {*****************************************************************************
  39. SecondLoad
  40. *****************************************************************************}
  41. procedure secondload(var p : ptree);
  42. var
  43. hregister : tregister;
  44. symtabletype : tsymtabletype;
  45. i : longint;
  46. hp : preference;
  47. s : pasmsymbol;
  48. popeax : boolean;
  49. begin
  50. simple_loadn:=true;
  51. reset_reference(p^.location.reference);
  52. case p^.symtableentry^.typ of
  53. { this is only for toasm and toaddr }
  54. absolutesym :
  55. begin
  56. p^.location.reference.symbol:=nil;
  57. if (pabsolutesym(p^.symtableentry)^.abstyp=toaddr) then
  58. begin
  59. if pabsolutesym(p^.symtableentry)^.absseg then
  60. p^.location.reference.segment:=R_FS;
  61. p^.location.reference.offset:=pabsolutesym(p^.symtableentry)^.address;
  62. end
  63. else
  64. p^.location.reference.symbol:=newasmsymbol(p^.symtableentry^.mangledname);
  65. maybe_concat_external(p^.symtableentry^.owner,p^.symtableentry^.mangledname);
  66. end;
  67. varsym :
  68. begin
  69. hregister:=R_NO;
  70. { C variable }
  71. if (pvarsym(p^.symtableentry)^.var_options and vo_is_C_var)<>0 then
  72. begin
  73. p^.location.reference.symbol:=newasmsymbol(p^.symtableentry^.mangledname);
  74. if (pvarsym(p^.symtableentry)^.var_options and vo_is_external)<>0 then
  75. concat_external(p^.symtableentry^.mangledname,EXT_NEAR);
  76. end
  77. { DLL variable }
  78. else if (pvarsym(p^.symtableentry)^.var_options and vo_is_dll_var)<>0 then
  79. begin
  80. hregister:=getregister32;
  81. p^.location.reference.symbol:=newasmsymbol(p^.symtableentry^.mangledname);
  82. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(p^.location.reference),hregister)));
  83. p^.location.reference.symbol:=nil;
  84. p^.location.reference.base:=hregister;
  85. end
  86. { external variable }
  87. else if (pvarsym(p^.symtableentry)^.var_options and vo_is_external)<>0 then
  88. begin
  89. p^.location.reference.symbol:=newasmsymbol(p^.symtableentry^.mangledname);
  90. concat_external(p^.symtableentry^.mangledname,EXT_NEAR);
  91. end
  92. { thread variable }
  93. else if (pvarsym(p^.symtableentry)^.var_options and vo_is_thread_var)<>0 then
  94. begin
  95. popeax:=not(R_EAX in unused);
  96. if popeax then
  97. exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,R_EAX)));
  98. p^.location.reference.symbol:=newasmsymbol(p^.symtableentry^.mangledname);
  99. if p^.symtable^.symtabletype=unitsymtable then
  100. concat_external(p^.symtableentry^.mangledname,EXT_NEAR);
  101. exprasmlist^.concat(new(pai386,op_ref(A_PUSH,S_L,newreference(p^.location.reference))));
  102. { the called procedure isn't allowed to change }
  103. { any register except EAX }
  104. emitcall('FPC_RELOCATE_THREADVAR',true);
  105. reset_reference(p^.location.reference);
  106. p^.location.reference.base:=getregister32;
  107. emit_reg_reg(A_MOV,S_L,R_EAX,p^.location.reference.base);
  108. if popeax then
  109. exprasmlist^.concat(new(pai386,op_reg(A_POP,S_L,R_EAX)));
  110. end
  111. { normal variable }
  112. else
  113. begin
  114. symtabletype:=p^.symtable^.symtabletype;
  115. { in case it is a register variable: }
  116. if pvarsym(p^.symtableentry)^.reg<>R_NO then
  117. begin
  118. p^.location.loc:=LOC_CREGISTER;
  119. p^.location.register:=pvarsym(p^.symtableentry)^.reg;
  120. unused:=unused-[pvarsym(p^.symtableentry)^.reg];
  121. end
  122. else
  123. begin
  124. { first handle local and temporary variables }
  125. if (symtabletype in [parasymtable,inlinelocalsymtable,
  126. inlineparasymtable,localsymtable]) then
  127. begin
  128. p^.location.reference.base:=procinfo.framepointer;
  129. p^.location.reference.offset:=pvarsym(p^.symtableentry)^.address+p^.symtable^.address_fixup;
  130. if (symtabletype in [localsymtable,inlinelocalsymtable]) then
  131. p^.location.reference.offset:=-p^.location.reference.offset;
  132. if (lexlevel>(p^.symtable^.symtablelevel)) then
  133. begin
  134. hregister:=getregister32;
  135. { make a reference }
  136. hp:=new_reference(procinfo.framepointer,
  137. procinfo.framepointer_offset);
  138. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,hp,hregister)));
  139. simple_loadn:=false;
  140. i:=lexlevel-1;
  141. while i>(p^.symtable^.symtablelevel) do
  142. begin
  143. { make a reference }
  144. hp:=new_reference(hregister,8);
  145. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,hp,hregister)));
  146. dec(i);
  147. end;
  148. p^.location.reference.base:=hregister;
  149. end;
  150. end
  151. else
  152. case symtabletype of
  153. unitsymtable,globalsymtable,
  154. staticsymtable :
  155. begin
  156. p^.location.reference.symbol:=newasmsymbol(p^.symtableentry^.mangledname);
  157. if symtabletype=unitsymtable then
  158. concat_external(p^.symtableentry^.mangledname,EXT_NEAR);
  159. end;
  160. stt_exceptsymtable:
  161. begin
  162. p^.location.reference.base:=procinfo.framepointer;
  163. p^.location.reference.offset:=pvarsym(p^.symtableentry)^.address;
  164. end;
  165. objectsymtable:
  166. begin
  167. if (pvarsym(p^.symtableentry)^.properties and sp_static)<>0 then
  168. begin
  169. p^.location.reference.symbol:=newasmsymbol(p^.symtableentry^.mangledname);
  170. if p^.symtable^.defowner^.owner^.symtabletype=unitsymtable then
  171. concat_external(p^.symtableentry^.mangledname,EXT_NEAR);
  172. end
  173. else
  174. begin
  175. p^.location.reference.base:=R_ESI;
  176. p^.location.reference.offset:=pvarsym(p^.symtableentry)^.address;
  177. end;
  178. end;
  179. withsymtable:
  180. begin
  181. { make a reference }
  182. { symtable datasize field
  183. contains the offset of the temp
  184. stored }
  185. { hp:=new_reference(procinfo.framepointer,
  186. p^.symtable^.datasize);
  187. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,hp,hregister)));}
  188. if ptree(pwithsymtable(p^.symtable)^.withnode)^.islocal then
  189. begin
  190. p^.location.reference:=ptree(pwithsymtable(p^.symtable)^.withnode)^.withreference^;
  191. end
  192. else
  193. begin
  194. hregister:=getregister32;
  195. p^.location.reference.base:=hregister;
  196. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  197. newreference(ptree(pwithsymtable(p^.symtable)^.withnode)^.withreference^),
  198. hregister)));
  199. end;
  200. inc(p^.location.reference.offset,pvarsym(p^.symtableentry)^.address);
  201. end;
  202. end;
  203. end;
  204. { in case call by reference, then calculate. Open array
  205. is always an reference! }
  206. if (pvarsym(p^.symtableentry)^.varspez=vs_var) or
  207. is_open_array(pvarsym(p^.symtableentry)^.definition) or
  208. ((pvarsym(p^.symtableentry)^.varspez=vs_const) and
  209. push_addr_param(pvarsym(p^.symtableentry)^.definition)) then
  210. begin
  211. simple_loadn:=false;
  212. if hregister=R_NO then
  213. hregister:=getregister32;
  214. {$ifdef OLDHIGH}
  215. if is_open_array(pvarsym(p^.symtableentry)^.definition) or
  216. is_open_string(pvarsym(p^.symtableentry)^.definition) then
  217. begin
  218. if (p^.location.reference.base=procinfo.framepointer) then
  219. begin
  220. highframepointer:=p^.location.reference.base;
  221. highoffset:=p^.location.reference.offset;
  222. end
  223. else
  224. begin
  225. highframepointer:=R_EDI;
  226. highoffset:=p^.location.reference.offset;
  227. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,S_L,
  228. p^.location.reference.base,R_EDI)));
  229. end;
  230. end;
  231. {$endif}
  232. if p^.location.loc=LOC_CREGISTER then
  233. begin
  234. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,S_L,
  235. p^.location.register,hregister)));
  236. p^.location.loc:=LOC_REFERENCE;
  237. end
  238. else
  239. begin
  240. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  241. newreference(p^.location.reference),
  242. hregister)));
  243. end;
  244. reset_reference(p^.location.reference);
  245. p^.location.reference.base:=hregister;
  246. end;
  247. end;
  248. end;
  249. procsym:
  250. begin
  251. if assigned(p^.left) then
  252. begin
  253. secondpass(p^.left);
  254. p^.location.loc:=LOC_MEM;
  255. gettempofsizereference(8,p^.location.reference);
  256. { load class instance address }
  257. case p^.left^.location.loc of
  258. LOC_CREGISTER,
  259. LOC_REGISTER:
  260. begin
  261. hregister:=p^.left^.location.register;
  262. ungetregister32(p^.left^.location.register);
  263. { such code is allowed !
  264. CGMessage(cg_e_illegal_expression); }
  265. end;
  266. LOC_MEM,
  267. LOC_REFERENCE:
  268. begin
  269. hregister:=R_EDI;
  270. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  271. newreference(p^.left^.location.reference),R_EDI)));
  272. del_reference(p^.left^.location.reference);
  273. ungetiftemp(p^.left^.location.reference);
  274. end;
  275. else internalerror(26019);
  276. end;
  277. { store the class instance address }
  278. new(hp);
  279. hp^:=p^.location.reference;
  280. inc(hp^.offset,4);
  281. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,
  282. R_EDI,hp)));
  283. { virtual method ? }
  284. if (pprocsym(p^.symtableentry)^.definition^.options and povirtualmethod)<>0 then
  285. begin
  286. new(hp);
  287. reset_reference(hp^);
  288. hp^.base:=hregister;
  289. { load vmt pointer }
  290. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  291. hp,R_EDI)));
  292. {$IfDef regallocfix}
  293. del_reference(hp^);
  294. {$EndIf regallocfix}
  295. { load method address }
  296. new(hp);
  297. reset_reference(hp^);
  298. hp^.base:=R_EDI;
  299. hp^.offset:=pprocsym(p^.symtableentry)^.definition^.extnumber*4+12;
  300. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  301. hp,R_EDI)));
  302. { ... and store it }
  303. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,
  304. R_EDI,newreference(p^.location.reference))));
  305. end
  306. else
  307. begin
  308. s:=newasmsymbol(pprocsym(p^.symtableentry)^.definition^.mangledname);
  309. exprasmlist^.concat(new(pai386,op_sym_ofs_ref(A_MOV,S_L,s,0,
  310. newreference(p^.location.reference))));
  311. maybe_concat_external(p^.symtable,p^.symtableentry^.mangledname);
  312. end;
  313. end
  314. else
  315. begin
  316. {!!!!! Be aware, work on virtual methods too }
  317. p^.location.reference.symbol:=newasmsymbol(pprocsym(p^.symtableentry)^.definition^.mangledname);
  318. maybe_concat_external(p^.symtable,p^.symtableentry^.mangledname);
  319. end;
  320. end;
  321. typedconstsym :
  322. begin
  323. p^.location.reference.symbol:=newasmsymbol(p^.symtableentry^.mangledname);
  324. maybe_concat_external(p^.symtable,p^.symtableentry^.mangledname);
  325. end;
  326. else internalerror(4);
  327. end;
  328. end;
  329. {*****************************************************************************
  330. SecondAssignment
  331. *****************************************************************************}
  332. procedure secondassignment(var p : ptree);
  333. var
  334. opsize : topsize;
  335. otlabel,hlabel,oflabel : plabel;
  336. hregister : tregister;
  337. loc : tloc;
  338. r : preference;
  339. {$ifndef OLDASM}
  340. ai : pai386;
  341. {$endif}
  342. begin
  343. otlabel:=truelabel;
  344. oflabel:=falselabel;
  345. getlabel(truelabel);
  346. getlabel(falselabel);
  347. { calculate left sides }
  348. if not(p^.concat_string) then
  349. secondpass(p^.left);
  350. if codegenerror then
  351. exit;
  352. case p^.left^.location.loc of
  353. LOC_REFERENCE : begin
  354. { in case left operator uses to register }
  355. { but to few are free then LEA }
  356. if (p^.left^.location.reference.base<>R_NO) and
  357. (p^.left^.location.reference.index<>R_NO) and
  358. (usablereg32<p^.right^.registers32) then
  359. begin
  360. del_reference(p^.left^.location.reference);
  361. hregister:=getregister32;
  362. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,newreference(
  363. p^.left^.location.reference),
  364. hregister)));
  365. reset_reference(p^.left^.location.reference);
  366. p^.left^.location.reference.base:=hregister;
  367. p^.left^.location.reference.index:=R_NO;
  368. end;
  369. loc:=LOC_REFERENCE;
  370. end;
  371. LOC_CREGISTER:
  372. loc:=LOC_CREGISTER;
  373. LOC_MMXREGISTER:
  374. loc:=LOC_MMXREGISTER;
  375. LOC_CMMXREGISTER:
  376. loc:=LOC_CMMXREGISTER;
  377. else
  378. begin
  379. CGMessage(cg_e_illegal_expression);
  380. exit;
  381. end;
  382. end;
  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. secondpass(p^.right);
  396. if codegenerror then
  397. exit;
  398. {$ifdef test_dest_loc}
  399. dest_loc_known:=false;
  400. if in_dest_loc then
  401. begin
  402. truelabel:=otlabel;
  403. falselabel:=oflabel;
  404. in_dest_loc:=false;
  405. exit;
  406. end;
  407. {$endif test_dest_loc}
  408. if p^.left^.resulttype^.deftype=stringdef then
  409. begin
  410. if is_ansistring(p^.left^.resulttype) then
  411. begin
  412. { the source and destinations are released
  413. in loadansistring, because an ansi string can
  414. also be in a register
  415. }
  416. loadansistring(p);
  417. end
  418. else
  419. if is_shortstring(p^.left^.resulttype) and
  420. not (p^.concat_string) then
  421. begin
  422. if is_ansistring(p^.right^.resulttype) then
  423. begin
  424. if (p^.right^.treetype=stringconstn) and
  425. (p^.right^.length=0) then
  426. begin
  427. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,S_B,
  428. 0,newreference(p^.left^.location.reference))));
  429. {$IfDef regallocfix}
  430. del_reference(p^.left^.location.reference);
  431. {$EndIf regallocfix}
  432. end
  433. else
  434. loadansi2short(p^.right,p^.left);
  435. end
  436. else
  437. begin
  438. { we do not need destination anymore }
  439. del_reference(p^.left^.location.reference);
  440. del_reference(p^.right^.location.reference);
  441. loadshortstring(p);
  442. ungetiftemp(p^.right^.location.reference);
  443. end;
  444. end
  445. else
  446. begin
  447. { its the only thing we have to do }
  448. del_reference(p^.right^.location.reference);
  449. end
  450. end
  451. else case p^.right^.location.loc of
  452. LOC_REFERENCE,
  453. LOC_MEM : begin
  454. { extra handling for ordinal constants }
  455. if (p^.right^.treetype in [ordconstn,fixconstn]) or
  456. (loc=LOC_CREGISTER) then
  457. begin
  458. case p^.left^.resulttype^.size of
  459. 1 : opsize:=S_B;
  460. 2 : opsize:=S_W;
  461. 4 : opsize:=S_L;
  462. end;
  463. if loc=LOC_CREGISTER then
  464. begin
  465. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,opsize,
  466. newreference(p^.right^.location.reference),
  467. p^.left^.location.register)));
  468. {$IfDef regallocfix}
  469. del_reference(p^.right^.location.reference);
  470. {$EndIf regallocfix}
  471. end
  472. else
  473. begin
  474. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,opsize,
  475. p^.right^.location.reference.offset,
  476. newreference(p^.left^.location.reference))));
  477. {$IfDef regallocfix}
  478. del_reference(p^.left^.location.reference);
  479. {$EndIf regallocfix}
  480. {exprasmlist^.concat(new(pai386,op_const_loc(A_MOV,opsize,
  481. p^.right^.location.reference.offset,
  482. p^.left^.location)));}
  483. end;
  484. end
  485. else
  486. begin
  487. if (p^.right^.resulttype^.needs_inittable) and
  488. ( (p^.right^.resulttype^.deftype<>objectdef) or
  489. not(pobjectdef(p^.right^.resulttype)^.isclass)) then
  490. begin
  491. { this would be a problem }
  492. if not(p^.left^.resulttype^.needs_inittable) then
  493. internalerror(3457);
  494. { increment source reference counter }
  495. new(r);
  496. reset_reference(r^);
  497. r^.symbol:=newasmsymbol(lab2str(p^.right^.resulttype^.get_inittable_label));
  498. emitpushreferenceaddr(exprasmlist,r^);
  499. emitpushreferenceaddr(exprasmlist,p^.right^.location.reference);
  500. exprasmlist^.concat(new(pai386,
  501. op_sym(A_CALL,S_NO,newasmsymbol('FPC_ADDREF'))));
  502. if not (cs_compilesystem in aktmoduleswitches) then
  503. concat_external('FPC_ADDREF',EXT_NEAR);
  504. { decrement destination reference counter }
  505. new(r);
  506. reset_reference(r^);
  507. r^.symbol:=newasmsymbol(lab2str(p^.left^.resulttype^.get_inittable_label));
  508. emitpushreferenceaddr(exprasmlist,r^);
  509. emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
  510. exprasmlist^.concat(new(pai386,
  511. op_sym(A_CALL,S_NO,newasmsymbol('FPC_DECREF'))));
  512. if not(cs_compilesystem in aktmoduleswitches) then
  513. concat_external('FPC_DECREF',EXT_NEAR);
  514. end;
  515. {$ifdef regallocfix}
  516. concatcopy(p^.right^.location.reference,
  517. p^.left^.location.reference,p^.left^.resulttype^.size,true,false);
  518. ungetiftemp(p^.right^.location.reference);
  519. {$Else regallocfix}
  520. concatcopy(p^.right^.location.reference,
  521. p^.left^.location.reference,p^.left^.resulttype^.size,false,false);
  522. ungetiftemp(p^.right^.location.reference);
  523. {$endif regallocfix}
  524. end;
  525. end;
  526. {$ifdef SUPPORT_MMX}
  527. LOC_CMMXREGISTER,
  528. LOC_MMXREGISTER:
  529. begin
  530. if loc=LOC_CMMXREGISTER then
  531. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOVQ,S_NO,
  532. p^.right^.location.register,p^.left^.location.register)))
  533. else
  534. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOVQ,S_NO,
  535. p^.right^.location.register,newreference(p^.left^.location.reference))));
  536. end;
  537. {$endif SUPPORT_MMX}
  538. LOC_REGISTER,
  539. LOC_CREGISTER : begin
  540. case p^.right^.resulttype^.size of
  541. 1 : opsize:=S_B;
  542. 2 : opsize:=S_W;
  543. 4 : opsize:=S_L;
  544. 8 : opsize:=S_L;
  545. end;
  546. { simplified with op_reg_loc }
  547. if loc=LOC_CREGISTER then
  548. begin
  549. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,opsize,
  550. p^.right^.location.register,
  551. p^.left^.location.register)));
  552. {$IfDef regallocfix}
  553. ungetregister(p^.right^.location.register);
  554. {$EndIf regallocfix}
  555. end
  556. else
  557. Begin
  558. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,opsize,
  559. p^.right^.location.register,
  560. newreference(p^.left^.location.reference))));
  561. {$IfDef regallocfix}
  562. ungetregister(p^.right^.location.register);
  563. del_reference(p^.left^.location.reference);
  564. {$EndIf regallocfix}
  565. end;
  566. if is_64bitint(p^.right^.resulttype) then
  567. begin
  568. { simplified with op_reg_loc }
  569. if loc=LOC_CREGISTER then
  570. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,opsize,
  571. p^.right^.location.registerhigh,
  572. p^.left^.location.registerhigh)))
  573. else
  574. begin
  575. r:=newreference(p^.left^.location.reference);
  576. inc(r^.offset,4);
  577. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,opsize,
  578. p^.right^.location.registerhigh,r)));
  579. end;
  580. end;
  581. {exprasmlist^.concat(new(pai386,op_reg_loc(A_MOV,opsize,
  582. p^.right^.location.register,
  583. p^.left^.location))); }
  584. end;
  585. LOC_FPU : begin
  586. if loc<>LOC_REFERENCE then
  587. internalerror(10010)
  588. else
  589. floatstore(pfloatdef(p^.left^.resulttype)^.typ,
  590. p^.left^.location.reference);
  591. end;
  592. LOC_JUMP : begin
  593. getlabel(hlabel);
  594. emitlab(truelabel);
  595. if loc=LOC_CREGISTER then
  596. exprasmlist^.concat(new(pai386,op_const_reg(A_MOV,S_B,
  597. 1,p^.left^.location.register)))
  598. else
  599. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,S_B,
  600. 1,newreference(p^.left^.location.reference))));
  601. {exprasmlist^.concat(new(pai386,op_const_loc(A_MOV,S_B,
  602. 1,p^.left^.location)));}
  603. emitjmp(C_None,hlabel);
  604. emitlab(falselabel);
  605. if loc=LOC_CREGISTER then
  606. exprasmlist^.concat(new(pai386,op_reg_reg(A_XOR,S_B,
  607. p^.left^.location.register,
  608. p^.left^.location.register)))
  609. else
  610. begin
  611. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,S_B,
  612. 0,newreference(p^.left^.location.reference))));
  613. {$IfDef regallocfix}
  614. del_reference(p^.left^.location.reference);
  615. {$EndIf regallocfix}
  616. end;
  617. emitlab(hlabel);
  618. end;
  619. LOC_FLAGS : begin
  620. if loc=LOC_CREGISTER then
  621. emit_flag2reg(p^.right^.location.resflags,p^.left^.location.register)
  622. else
  623. {$ifndef OLDASM}
  624. begin
  625. ai:=new(pai386,op_ref(A_Setcc,S_B,newreference(p^.left^.location.reference)));
  626. ai^.SetCondition(flag_2_cond[p^.right^.location.resflags]);
  627. exprasmlist^.concat(ai);
  628. end;
  629. {$else}
  630. exprasmlist^.concat(new(pai386,op_ref(flag_2_set[p^.right^.location.resflags],S_B,
  631. newreference(p^.left^.location.reference))));
  632. {$endif}
  633. {$IfDef regallocfix}
  634. del_reference(p^.left^.location.reference);
  635. {$EndIf regallocfix}
  636. end;
  637. end;
  638. freelabel(truelabel);
  639. freelabel(falselabel);
  640. truelabel:=otlabel;
  641. falselabel:=oflabel;
  642. end;
  643. {*****************************************************************************
  644. SecondFuncRet
  645. *****************************************************************************}
  646. procedure secondfuncret(var p : ptree);
  647. var
  648. hr : tregister;
  649. hp : preference;
  650. pp : pprocinfo;
  651. hr_valid : boolean;
  652. begin
  653. reset_reference(p^.location.reference);
  654. hr_valid:=false;
  655. if @procinfo<>pprocinfo(p^.funcretprocinfo) then
  656. begin
  657. hr:=getregister32;
  658. hr_valid:=true;
  659. hp:=new_reference(procinfo.framepointer,
  660. procinfo.framepointer_offset);
  661. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,hp,hr)));
  662. pp:=procinfo.parent;
  663. { walk up the stack frame }
  664. while pp<>pprocinfo(p^.funcretprocinfo) do
  665. begin
  666. hp:=new_reference(hr,
  667. pp^.framepointer_offset);
  668. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,hp,hr)));
  669. pp:=pp^.parent;
  670. end;
  671. p^.location.reference.base:=hr;
  672. end
  673. else
  674. p^.location.reference.base:=procinfo.framepointer;
  675. p^.location.reference.offset:=procinfo.retoffset;
  676. if ret_in_param(p^.retdef) then
  677. begin
  678. if not hr_valid then
  679. hr:=getregister32;
  680. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(p^.location.reference),hr)));
  681. p^.location.reference.base:=hr;
  682. p^.location.reference.offset:=0;
  683. end;
  684. end;
  685. {*****************************************************************************
  686. SecondArrayConstruct
  687. *****************************************************************************}
  688. const
  689. vtInteger = 0;
  690. vtBoolean = 1;
  691. vtChar = 2;
  692. vtExtended = 3;
  693. vtString = 4;
  694. vtPointer = 5;
  695. vtPChar = 6;
  696. vtObject = 7;
  697. vtClass = 8;
  698. vtWideChar = 9;
  699. vtPWideChar = 10;
  700. vtAnsiString = 11;
  701. vtCurrency = 12;
  702. vtVariant = 13;
  703. vtInterface = 14;
  704. vtWideString = 15;
  705. vtInt64 = 16;
  706. procedure secondarrayconstruct(var p : ptree);
  707. var
  708. hp : ptree;
  709. href : treference;
  710. lt : pdef;
  711. vaddr : boolean;
  712. vtype : longint;
  713. begin
  714. if not p^.cargs then
  715. begin
  716. reset_reference(p^.location.reference);
  717. gettempofsizereference((parraydef(p^.resulttype)^.highrange+1)*8,p^.location.reference);
  718. href:=p^.location.reference;
  719. end;
  720. hp:=p;
  721. while assigned(hp) do
  722. begin
  723. secondpass(hp^.left);
  724. if codegenerror then
  725. exit;
  726. { find the correct vtype value }
  727. vtype:=$ff;
  728. vaddr:=false;
  729. lt:=hp^.left^.resulttype;
  730. case lt^.deftype of
  731. enumdef,
  732. orddef : begin
  733. if (lt^.deftype=enumdef) or
  734. is_integer(lt) then
  735. vtype:=vtInteger
  736. else
  737. if is_boolean(lt) then
  738. vtype:=vtBoolean
  739. else
  740. if (lt^.deftype=orddef) and (porddef(lt)^.typ=uchar) then
  741. vtype:=vtChar;
  742. end;
  743. floatdef : begin
  744. vtype:=vtExtended;
  745. vaddr:=true;
  746. end;
  747. procvardef,
  748. pointerdef : begin
  749. if is_pchar(lt) then
  750. vtype:=vtPChar
  751. else
  752. vtype:=vtPointer;
  753. end;
  754. classrefdef : vtype:=vtClass;
  755. objectdef : begin
  756. vtype:=vtObject;
  757. end;
  758. stringdef : begin
  759. if is_shortstring(lt) then
  760. begin
  761. vtype:=vtString;
  762. vaddr:=true;
  763. end
  764. else
  765. if is_ansistring(lt) then
  766. vtype:=vtAnsiString;
  767. end;
  768. end;
  769. if vtype=$ff then
  770. internalerror(14357);
  771. { write C style pushes or an pascal array }
  772. if p^.cargs then
  773. begin
  774. if vaddr then
  775. begin
  776. emit_to_reference(hp^.left);
  777. emit_push_lea_loc(hp^.left^.location);
  778. end
  779. else
  780. emit_push_loc(hp^.left^.location);
  781. end
  782. else
  783. begin
  784. { update href to the vtype field and write it }
  785. exprasmlist^.concat(new(pai386,op_const_ref(A_MOV,S_L,
  786. vtype,newreference(href))));
  787. inc(href.offset,4);
  788. { write changing field update href to the next element }
  789. if vaddr then
  790. begin
  791. emit_to_reference(hp^.left);
  792. emit_lea_loc_ref(hp^.left^.location,href);
  793. end
  794. else
  795. emit_mov_loc_ref(hp^.left^.location,href);
  796. inc(href.offset,4);
  797. end;
  798. { load next entry }
  799. hp:=hp^.right;
  800. end;
  801. end;
  802. end.
  803. {
  804. $Log$
  805. Revision 1.56 1999-05-17 23:51:38 peter
  806. * with temp vars now use a reference with a persistant temp instead
  807. of setting datasize
  808. Revision 1.55 1999/05/17 21:57:04 florian
  809. * new temporary ansistring handling
  810. Revision 1.54 1999/05/12 00:19:43 peter
  811. * removed R_DEFAULT_SEG
  812. * uniform float names
  813. Revision 1.53 1999/05/06 09:05:16 peter
  814. * generic write_float and str_float
  815. * fixed constant float conversions
  816. Revision 1.52 1999/05/01 13:24:10 peter
  817. * merged nasm compiler
  818. * old asm moved to oldasm/
  819. Revision 1.51 1999/04/28 06:01:55 florian
  820. * changes of Bruessel:
  821. + message handler can now take an explicit self
  822. * typinfo fixed: sometimes the type names weren't written
  823. * the type checking for pointer comparisations and subtraction
  824. and are now more strict (was also buggy)
  825. * small bug fix to link.pas to support compiling on another
  826. drive
  827. * probable bug in popt386 fixed: call/jmp => push/jmp
  828. transformation didn't count correctly the jmp references
  829. + threadvar support
  830. * warning if ln/sqrt gets an invalid constant argument
  831. Revision 1.50 1999/04/16 13:42:26 jonas
  832. * more regalloc fixes (still not complete)
  833. Revision 1.49 1999/04/13 18:57:48 florian
  834. * classes which contain ansistring get unnecessary calls
  835. to addref/decref when they are assigned, fixed
  836. Revision 1.48 1999/04/09 15:48:47 jonas
  837. * added fix for missing register deallocation (-dregallocfix)
  838. Revision 1.47 1999/03/31 13:55:07 peter
  839. * assembler inlining working for ag386bin
  840. Revision 1.46 1999/03/24 23:16:52 peter
  841. * fixed bugs 212,222,225,227,229,231,233
  842. Revision 1.45 1999/02/25 21:02:28 peter
  843. * ag386bin updates
  844. + coff writer
  845. Revision 1.44 1999/02/22 02:15:12 peter
  846. * updates for ag386bin
  847. Revision 1.43 1999/01/27 00:13:54 florian
  848. * "procedure of object"-stuff fixed
  849. Revision 1.42 1999/01/21 22:10:40 peter
  850. * fixed array of const
  851. * generic platform independent high() support
  852. Revision 1.41 1999/01/20 10:20:18 peter
  853. * don't make localvar copies for assembler procedures
  854. Revision 1.40 1998/12/30 13:41:07 peter
  855. * released valuepara
  856. Revision 1.39 1998/12/19 00:23:45 florian
  857. * ansistring memory leaks fixed
  858. Revision 1.38 1998/12/11 00:02:51 peter
  859. + globtype,tokens,version unit splitted from globals
  860. Revision 1.37 1998/12/10 09:47:17 florian
  861. + basic operations with int64/qord (compiler with -dint64)
  862. + rtti of enumerations extended: names are now written
  863. Revision 1.36 1998/12/04 10:18:06 florian
  864. * some stuff for procedures of object added
  865. * bug with overridden virtual constructors fixed (reported by Italo Gomes)
  866. Revision 1.35 1998/11/30 09:43:04 pierre
  867. * some range check bugs fixed (still not working !)
  868. + added DLL writing support for win32 (also accepts variables)
  869. + TempAnsi for code that could be used for Temporary ansi strings
  870. handling
  871. Revision 1.34 1998/11/28 16:20:48 peter
  872. + support for dll variables
  873. Revision 1.33 1998/11/27 14:50:33 peter
  874. + open strings, $P switch support
  875. Revision 1.32 1998/11/26 09:53:36 florian
  876. * for classes no init/final. code is necessary, fixed
  877. Revision 1.31 1998/11/20 15:35:54 florian
  878. * problems with rtti fixed, hope it works
  879. Revision 1.30 1998/11/18 17:45:24 peter
  880. * fixes for VALUEPARA
  881. Revision 1.29 1998/11/18 15:44:11 peter
  882. * VALUEPARA for tp7 compatible value parameters
  883. Revision 1.28 1998/11/17 11:32:44 peter
  884. * optimize str:='' in H+ mode
  885. + -! to test ansistrings
  886. Revision 1.27 1998/11/16 15:35:39 peter
  887. * rename laod/copystring -> load/copyshortstring
  888. * fixed int-bool cnv bug
  889. + char-ansistring conversion
  890. Revision 1.26 1998/11/10 10:09:10 peter
  891. * va_list -> array of const
  892. Revision 1.25 1998/11/05 12:02:35 peter
  893. * released useansistring
  894. * removed -Sv, its now available in fpc modes
  895. Revision 1.24 1998/10/14 08:47:14 pierre
  896. * bugs in secondfuncret for result in subprocedures removed
  897. Revision 1.23 1998/10/06 17:16:44 pierre
  898. * some memory leaks fixed (thanks to Peter for heaptrc !)
  899. Revision 1.22 1998/10/01 09:22:53 peter
  900. * fixed value openarray
  901. * ungettemp of arrayconstruct
  902. Revision 1.21 1998/09/28 11:07:39 peter
  903. + floatdef support for array of const
  904. Revision 1.20 1998/09/24 14:26:03 peter
  905. * updated for new tvarrec
  906. Revision 1.19 1998/09/23 17:49:59 peter
  907. * high(arrayconstructor) is now correct
  908. * procvardef support for variant record
  909. Revision 1.18 1998/09/23 09:58:48 peter
  910. * first working array of const things
  911. Revision 1.17 1998/09/20 18:00:19 florian
  912. * small compiling problems fixed
  913. Revision 1.16 1998/09/20 17:46:48 florian
  914. * some things regarding ansistrings fixed
  915. Revision 1.15 1998/09/17 09:42:16 peter
  916. + pass_2 for cg386
  917. * Message() -> CGMessage() for pass_1/pass_2
  918. Revision 1.14 1998/09/14 10:43:50 peter
  919. * all internal RTL functions start with FPC_
  920. Revision 1.13 1998/09/04 12:24:24 florian
  921. * bug0159 fixed
  922. Revision 1.12 1998/09/04 11:55:17 florian
  923. * problem with -Or fixed
  924. Revision 1.11 1998/09/03 16:03:14 florian
  925. + rtti generation
  926. * init table generation changed
  927. Revision 1.10 1998/08/21 14:08:40 pierre
  928. + TEST_FUNCRET now default (old code removed)
  929. works also for m68k (at least compiles)
  930. Revision 1.9 1998/08/20 09:26:37 pierre
  931. + funcret setting in underproc testing
  932. compile with _dTEST_FUNCRET
  933. Revision 1.8 1998/08/10 14:49:48 peter
  934. + localswitches, moduleswitches, globalswitches splitting
  935. Revision 1.7 1998/07/30 13:30:33 florian
  936. * final implemenation of exception support, maybe it needs
  937. some fixes :)
  938. Revision 1.6 1998/07/26 21:58:57 florian
  939. + better support for switch $H
  940. + index access to ansi strings added
  941. + assigment of data (records/arrays) containing ansi strings
  942. Revision 1.5 1998/07/24 22:16:54 florian
  943. * internal error 10 together with array access fixed. I hope
  944. that's the final fix.
  945. Revision 1.4 1998/06/11 13:58:45 peter
  946. * fixed too long line
  947. Revision 1.3 1998/06/09 16:01:35 pierre
  948. + added procedure directive parsing for procvars
  949. (accepted are popstack cdecl and pascal)
  950. + added C vars with the following syntax
  951. var C calias 'true_c_name';(can be followed by external)
  952. reason is that you must add the Cprefix
  953. which is target dependent
  954. Revision 1.2 1998/06/08 13:13:34 pierre
  955. + temporary variables now in temp_gen.pas unit
  956. because it is processor independent
  957. * mppc68k.bat modified to undefine i386 and support_mmx
  958. (which are defaults for i386)
  959. Revision 1.1 1998/06/05 17:44:12 peter
  960. * splitted cgi386
  961. }