n386mem.pas 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Generate i386 assembler for in memory related 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 n386mem;
  19. {$i defines.inc}
  20. interface
  21. uses
  22. node,nmem;
  23. type
  24. ti386loadvmtnode = class(tloadvmtnode)
  25. procedure pass_2;override;
  26. end;
  27. ti386hnewnode = class(thnewnode)
  28. procedure pass_2;override;
  29. end;
  30. ti386newnode = class(tnewnode)
  31. procedure pass_2;override;
  32. end;
  33. ti386hdisposenode = class(thdisposenode)
  34. procedure pass_2;override;
  35. end;
  36. ti386simplenewdisposenode = class(tsimplenewdisposenode)
  37. procedure pass_2;override;
  38. end;
  39. ti386addrnode = class(taddrnode)
  40. procedure pass_2;override;
  41. end;
  42. ti386doubleaddrnode = class(tdoubleaddrnode)
  43. procedure pass_2;override;
  44. end;
  45. ti386derefnode = class(tderefnode)
  46. procedure pass_2;override;
  47. end;
  48. ti386subscriptnode = class(tsubscriptnode)
  49. procedure pass_2;override;
  50. end;
  51. ti386vecnode = class(tvecnode)
  52. procedure pass_2;override;
  53. end;
  54. ti386selfnode = class(tselfnode)
  55. procedure pass_2;override;
  56. end;
  57. ti386withnode = class(twithnode)
  58. procedure pass_2;override;
  59. end;
  60. implementation
  61. uses
  62. {$ifdef delphi}
  63. sysutils,
  64. {$else}
  65. strings,
  66. {$endif}
  67. {$ifdef GDB}
  68. gdb,
  69. {$endif GDB}
  70. globtype,systems,
  71. cutils,cobjects,verbose,globals,
  72. symconst,symtable,aasm,types,
  73. hcodegen,temp_gen,pass_2,
  74. pass_1,nld,ncon,nadd,
  75. cpubase,cpuasm,
  76. cgai386,tgeni386,n386util;
  77. {*****************************************************************************
  78. TI386LOADNODE
  79. *****************************************************************************}
  80. procedure ti386loadvmtnode.pass_2;
  81. begin
  82. location.register:=getregister32;
  83. emit_sym_ofs_reg(A_MOV,
  84. S_L,newasmsymbol(pobjectdef(pclassrefdef(resulttype)^.pointertype.def)^.vmt_mangledname),0,
  85. location.register);
  86. end;
  87. {*****************************************************************************
  88. TI386HNEWNODE
  89. *****************************************************************************}
  90. procedure ti386hnewnode.pass_2;
  91. begin
  92. end;
  93. {*****************************************************************************
  94. TI386NEWNODE
  95. *****************************************************************************}
  96. procedure ti386newnode.pass_2;
  97. var
  98. pushed : tpushed;
  99. r : preference;
  100. begin
  101. if assigned(left) then
  102. begin
  103. secondpass(left);
  104. location.register:=left.location.register;
  105. end
  106. else
  107. begin
  108. pushusedregisters(pushed,$ff);
  109. gettempofsizereference(target_os.size_of_pointer,location.reference);
  110. { determines the size of the mem block }
  111. push_int(ppointerdef(resulttype)^.pointertype.def^.size);
  112. emit_push_lea_loc(location,false);
  113. emitcall('FPC_GETMEM');
  114. if ppointerdef(resulttype)^.pointertype.def^.needs_inittable then
  115. begin
  116. new(r);
  117. reset_reference(r^);
  118. r^.symbol:=ppointerdef(left.resulttype)^.pointertype.def^.get_inittable_label;
  119. emitpushreferenceaddr(r^);
  120. dispose(r);
  121. { push pointer we just allocated, we need to initialize the
  122. data located at that pointer not the pointer self (PFV) }
  123. emit_push_loc(location);
  124. emitcall('FPC_INITIALIZE');
  125. end;
  126. popusedregisters(pushed);
  127. { may be load ESI }
  128. maybe_loadesi;
  129. end;
  130. if codegenerror then
  131. exit;
  132. end;
  133. {*****************************************************************************
  134. TI386HDISPOSENODE
  135. *****************************************************************************}
  136. procedure ti386hdisposenode.pass_2;
  137. begin
  138. secondpass(left);
  139. if codegenerror then
  140. exit;
  141. reset_reference(location.reference);
  142. case left.location.loc of
  143. LOC_REGISTER:
  144. location.reference.index:=left.location.register;
  145. LOC_CREGISTER:
  146. begin
  147. location.reference.index:=getregister32;
  148. emit_reg_reg(A_MOV,S_L,
  149. left.location.register,
  150. location.reference.index);
  151. end;
  152. LOC_MEM,LOC_REFERENCE :
  153. begin
  154. del_reference(left.location.reference);
  155. location.reference.index:=getregister32;
  156. emit_ref_reg(A_MOV,S_L,newreference(left.location.reference),
  157. location.reference.index);
  158. end;
  159. end;
  160. end;
  161. {*****************************************************************************
  162. TI386SIMPLENEWDISPOSENODE
  163. *****************************************************************************}
  164. procedure ti386simplenewdisposenode.pass_2;
  165. var
  166. pushed : tpushed;
  167. r : preference;
  168. begin
  169. secondpass(left);
  170. if codegenerror then
  171. exit;
  172. pushusedregisters(pushed,$ff);
  173. { call the mem handling procedures }
  174. case nodetype of
  175. simpledisposen:
  176. begin
  177. if ppointerdef(left.resulttype)^.pointertype.def^.needs_inittable then
  178. begin
  179. new(r);
  180. reset_reference(r^);
  181. r^.symbol:=ppointerdef(left.resulttype)^.pointertype.def^.get_inittable_label;
  182. emitpushreferenceaddr(r^);
  183. dispose(r);
  184. { push pointer adress }
  185. emit_push_loc(left.location);
  186. emitcall('FPC_FINALIZE');
  187. end;
  188. emit_push_lea_loc(left.location,true);
  189. emitcall('FPC_FREEMEM');
  190. end;
  191. simplenewn:
  192. begin
  193. { determines the size of the mem block }
  194. push_int(ppointerdef(left.resulttype)^.pointertype.def^.size);
  195. emit_push_lea_loc(left.location,true);
  196. emitcall('FPC_GETMEM');
  197. if ppointerdef(left.resulttype)^.pointertype.def^.needs_inittable then
  198. begin
  199. new(r);
  200. reset_reference(r^);
  201. r^.symbol:=ppointerdef(left.resulttype)^.pointertype.def^.get_inittable_label;
  202. emitpushreferenceaddr(r^);
  203. dispose(r);
  204. emit_push_loc(left.location);
  205. emitcall('FPC_INITIALIZE');
  206. end;
  207. end;
  208. end;
  209. popusedregisters(pushed);
  210. { may be load ESI }
  211. maybe_loadesi;
  212. end;
  213. {*****************************************************************************
  214. TI386ADDRNODE
  215. *****************************************************************************}
  216. procedure ti386addrnode.pass_2;
  217. begin
  218. secondpass(left);
  219. { when loading procvar we do nothing with this node, so load the
  220. location of left }
  221. if nf_procvarload in flags then
  222. begin
  223. set_location(location,left.location);
  224. exit;
  225. end;
  226. location.loc:=LOC_REGISTER;
  227. del_reference(left.location.reference);
  228. location.register:=getregister32;
  229. {@ on a procvar means returning an address to the procedure that
  230. is stored in it.}
  231. { yes but left.symtableentry can be nil
  232. for example on @self !! }
  233. { symtableentry can be also invalid, if left is no tree node }
  234. if (m_tp_procvar in aktmodeswitches) and
  235. (left.nodetype=loadn) and
  236. assigned(tloadnode(left).symtableentry) and
  237. (tloadnode(left).symtableentry^.typ=varsym) and
  238. (pvarsym(tloadnode(left).symtableentry)^.vartype.def^.deftype=procvardef) then
  239. emit_ref_reg(A_MOV,S_L,
  240. newreference(left.location.reference),
  241. location.register)
  242. else
  243. emit_ref_reg(A_LEA,S_L,
  244. newreference(left.location.reference),
  245. location.register);
  246. { for use of other segments }
  247. if left.location.reference.segment<>R_NO then
  248. location.segment:=left.location.reference.segment;
  249. end;
  250. {*****************************************************************************
  251. TI386DOUBLEADDRNODE
  252. *****************************************************************************}
  253. procedure ti386doubleaddrnode.pass_2;
  254. begin
  255. secondpass(left);
  256. location.loc:=LOC_REGISTER;
  257. del_reference(left.location.reference);
  258. location.register:=getregister32;
  259. emit_ref_reg(A_LEA,S_L,
  260. newreference(left.location.reference),
  261. location.register);
  262. end;
  263. {*****************************************************************************
  264. TI386DEREFNODE
  265. *****************************************************************************}
  266. procedure ti386derefnode.pass_2;
  267. var
  268. hr : tregister;
  269. begin
  270. secondpass(left);
  271. reset_reference(location.reference);
  272. case left.location.loc of
  273. LOC_REGISTER:
  274. location.reference.base:=left.location.register;
  275. LOC_CREGISTER:
  276. begin
  277. { ... and reserve one for the pointer }
  278. hr:=getregister32;
  279. emit_reg_reg(A_MOV,S_L,left.location.register,hr);
  280. location.reference.base:=hr;
  281. end;
  282. else
  283. begin
  284. { free register }
  285. del_reference(left.location.reference);
  286. { ...and reserve one for the pointer }
  287. hr:=getregister32;
  288. emit_ref_reg(
  289. A_MOV,S_L,newreference(left.location.reference),
  290. hr);
  291. location.reference.base:=hr;
  292. end;
  293. end;
  294. if ppointerdef(left.resulttype)^.is_far then
  295. location.reference.segment:=R_FS;
  296. if not ppointerdef(left.resulttype)^.is_far and
  297. (cs_gdb_heaptrc in aktglobalswitches) and
  298. (cs_checkpointer in aktglobalswitches) then
  299. begin
  300. emit_reg(
  301. A_PUSH,S_L,location.reference.base);
  302. emitcall('FPC_CHECKPOINTER');
  303. end;
  304. end;
  305. {*****************************************************************************
  306. TI386SUBSCRIPTNODE
  307. *****************************************************************************}
  308. procedure ti386subscriptnode.pass_2;
  309. var
  310. hr : tregister;
  311. begin
  312. secondpass(left);
  313. if codegenerror then
  314. exit;
  315. { classes must be dereferenced implicit }
  316. if (left.resulttype^.deftype=objectdef) and
  317. pobjectdef(left.resulttype)^.is_class then
  318. begin
  319. reset_reference(location.reference);
  320. case left.location.loc of
  321. LOC_REGISTER:
  322. location.reference.base:=left.location.register;
  323. LOC_CREGISTER:
  324. begin
  325. { ... and reserve one for the pointer }
  326. hr:=getregister32;
  327. emit_reg_reg(A_MOV,S_L,left.location.register,hr);
  328. location.reference.base:=hr;
  329. end;
  330. else
  331. begin
  332. { free register }
  333. del_reference(left.location.reference);
  334. { ... and reserve one for the pointer }
  335. hr:=getregister32;
  336. emit_ref_reg(
  337. A_MOV,S_L,newreference(left.location.reference),
  338. hr);
  339. location.reference.base:=hr;
  340. end;
  341. end;
  342. end
  343. else
  344. set_location(location,left.location);
  345. inc(location.reference.offset,vs^.address);
  346. end;
  347. {*****************************************************************************
  348. TI386VECNODE
  349. *****************************************************************************}
  350. procedure ti386vecnode.pass_2;
  351. var
  352. is_pushed : boolean;
  353. ind,hr : tregister;
  354. //_p : tnode;
  355. function get_mul_size:longint;
  356. begin
  357. if nf_memindex in flags then
  358. get_mul_size:=1
  359. else
  360. begin
  361. if (left.resulttype^.deftype=arraydef) then
  362. get_mul_size:=parraydef(left.resulttype)^.elesize
  363. else
  364. get_mul_size:=resulttype^.size;
  365. end
  366. end;
  367. procedure calc_emit_mul;
  368. var
  369. l1,l2 : longint;
  370. begin
  371. l1:=get_mul_size;
  372. case l1 of
  373. 1,2,4,8 : location.reference.scalefactor:=l1;
  374. else
  375. begin
  376. if ispowerof2(l1,l2) then
  377. emit_const_reg(A_SHL,S_L,l2,ind)
  378. else
  379. emit_const_reg(A_IMUL,S_L,l1,ind);
  380. end;
  381. end;
  382. end;
  383. var
  384. extraoffset : longint;
  385. { rl stores the resulttype of the left node, this is necessary }
  386. { to detect if it is an ansistring }
  387. { because in constant nodes which constant index }
  388. { the left tree is removed }
  389. t : tnode;
  390. hp : preference;
  391. href : treference;
  392. tai : Paicpu;
  393. pushed : tpushed;
  394. hightree : tnode;
  395. hl,otl,ofl : pasmlabel;
  396. begin
  397. secondpass(left);
  398. { we load the array reference to location }
  399. { an ansistring needs to be dereferenced }
  400. if is_ansistring(left.resulttype) or
  401. is_widestring(left.resulttype) then
  402. begin
  403. reset_reference(location.reference);
  404. if nf_callunique in flags then
  405. begin
  406. if left.location.loc<>LOC_REFERENCE then
  407. begin
  408. CGMessage(cg_e_illegal_expression);
  409. exit;
  410. end;
  411. pushusedregisters(pushed,$ff);
  412. emitpushreferenceaddr(left.location.reference);
  413. if is_ansistring(left.resulttype) then
  414. emitcall('FPC_ANSISTR_UNIQUE')
  415. else
  416. emitcall('FPC_WIDESTR_UNIQUE');
  417. maybe_loadesi;
  418. popusedregisters(pushed);
  419. end;
  420. if left.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  421. begin
  422. location.reference.base:=left.location.register;
  423. end
  424. else
  425. begin
  426. del_reference(left.location.reference);
  427. location.reference.base:=getregister32;
  428. emit_ref_reg(A_MOV,S_L,
  429. newreference(left.location.reference),
  430. location.reference.base);
  431. end;
  432. { check for a zero length string,
  433. we can use the ansistring routine here }
  434. if (cs_check_range in aktlocalswitches) then
  435. begin
  436. pushusedregisters(pushed,$ff);
  437. emit_reg(A_PUSH,S_L,location.reference.base);
  438. emitcall('FPC_ANSISTR_CHECKZERO');
  439. maybe_loadesi;
  440. popusedregisters(pushed);
  441. end;
  442. if is_ansistring(left.resulttype) then
  443. { in ansistrings S[1] is pchar(S)[0] !! }
  444. dec(location.reference.offset)
  445. else
  446. begin
  447. { in widestrings S[1] is pwchar(S)[0] !! }
  448. dec(location.reference.offset,2);
  449. emit_const_reg(A_SHL,S_L,
  450. 1,location.reference.base);
  451. end;
  452. { we've also to keep left up-to-date, because it is used }
  453. { if a constant array index occurs, subject to change (FK) }
  454. set_location(left.location,location);
  455. end
  456. else
  457. set_location(location,left.location);
  458. { offset can only differ from 0 if arraydef }
  459. if left.resulttype^.deftype=arraydef then
  460. dec(location.reference.offset,
  461. get_mul_size*parraydef(left.resulttype)^.lowrange);
  462. if right.nodetype=ordconstn then
  463. begin
  464. { offset can only differ from 0 if arraydef }
  465. if (left.resulttype^.deftype=arraydef) then
  466. begin
  467. if not(is_open_array(left.resulttype)) and
  468. not(is_array_of_const(left.resulttype)) then
  469. begin
  470. if (tordconstnode(right).value>parraydef(left.resulttype)^.highrange) or
  471. (tordconstnode(right).value<parraydef(left.resulttype)^.lowrange) then
  472. begin
  473. if (cs_check_range in aktlocalswitches) then
  474. CGMessage(parser_e_range_check_error)
  475. else
  476. CGMessage(parser_w_range_check_error);
  477. end;
  478. dec(left.location.reference.offset,
  479. get_mul_size*parraydef(left.resulttype)^.lowrange);
  480. end
  481. else
  482. begin
  483. { range checking for open arrays !!!! }
  484. {!!!!!!!!!!!!!!!!!}
  485. end;
  486. end
  487. else if (left.resulttype^.deftype=stringdef) then
  488. begin
  489. if (tordconstnode(right).value=0) and not(is_shortstring(left.resulttype)) then
  490. CGMessage(cg_e_can_access_element_zero);
  491. if (cs_check_range in aktlocalswitches) then
  492. case pstringdef(left.resulttype)^.string_typ of
  493. { it's the same for ansi- and wide strings }
  494. st_widestring,
  495. st_ansistring:
  496. begin
  497. pushusedregisters(pushed,$ff);
  498. push_int(tordconstnode(right).value);
  499. hp:=newreference(location.reference);
  500. dec(hp^.offset,7);
  501. emit_ref(A_PUSH,S_L,hp);
  502. emitcall('FPC_ANSISTR_RANGECHECK');
  503. popusedregisters(pushed);
  504. maybe_loadesi;
  505. end;
  506. st_shortstring:
  507. begin
  508. {!!!!!!!!!!!!!!!!!}
  509. end;
  510. st_longstring:
  511. begin
  512. {!!!!!!!!!!!!!!!!!}
  513. end;
  514. end;
  515. end;
  516. inc(left.location.reference.offset,
  517. get_mul_size*tordconstnode(right).value);
  518. if nf_memseg in flags then
  519. left.location.reference.segment:=R_FS;
  520. {
  521. left.resulttype:=resulttype;
  522. disposetree(right);
  523. _p:=left;
  524. putnode(p);
  525. p:=_p;
  526. }
  527. set_location(location,left.location);
  528. end
  529. else
  530. { not nodetype=ordconstn }
  531. begin
  532. if (cs_regalloc in aktglobalswitches) and
  533. { if we do range checking, we don't }
  534. { need that fancy code (it would be }
  535. { buggy) }
  536. not(cs_check_range in aktlocalswitches) and
  537. (left.resulttype^.deftype=arraydef) then
  538. begin
  539. extraoffset:=0;
  540. if (right.nodetype=addn) then
  541. begin
  542. if taddnode(right).right.nodetype=ordconstn then
  543. begin
  544. extraoffset:=tordconstnode(taddnode(right).right).value;
  545. t:=taddnode(right).left;
  546. { First pass processed this with the assumption }
  547. { that there was an add node which may require an }
  548. { extra register. Fake it or die with IE10 (JM) }
  549. t.registers32 := taddnode(right).registers32;
  550. taddnode(right).left:=nil;
  551. right.free;
  552. right:=t;
  553. end
  554. else if tordconstnode(taddnode(right).left).nodetype=ordconstn then
  555. begin
  556. extraoffset:=tordconstnode(taddnode(right).left).value;
  557. t:=taddnode(right).right;
  558. t.registers32 := right.registers32;
  559. taddnode(right).right:=nil;
  560. right.free;
  561. right:=t;
  562. end;
  563. end
  564. else if (right.nodetype=subn) then
  565. begin
  566. if taddnode(right).right.nodetype=ordconstn then
  567. begin
  568. { this was "extraoffset:=right.right.value;" Looks a bit like
  569. copy-paste bug :) (JM) }
  570. extraoffset:=-tordconstnode(taddnode(right).right).value;
  571. t:=taddnode(right).left;
  572. t.registers32 := right.registers32;
  573. taddnode(right).left:=nil;
  574. right.free;
  575. right:=t;
  576. end
  577. { You also have to negate right.right in this case! I can't add an
  578. unaryminusn without causing a crash, so I've disabled it (JM)
  579. else if right.left.nodetype=ordconstn then
  580. begin
  581. extraoffset:=right.left.value;
  582. t:=right.right;
  583. t^.registers32 := right.registers32;
  584. putnode(right);
  585. putnode(right.left);
  586. right:=t;
  587. end;}
  588. end;
  589. inc(location.reference.offset,
  590. get_mul_size*extraoffset);
  591. end;
  592. { calculate from left to right }
  593. if (location.loc<>LOC_REFERENCE) and
  594. (location.loc<>LOC_MEM) then
  595. CGMessage(cg_e_illegal_expression);
  596. if (right.location.loc=LOC_JUMP) then
  597. begin
  598. otl:=truelabel;
  599. getlabel(truelabel);
  600. ofl:=falselabel;
  601. getlabel(falselabel);
  602. end;
  603. is_pushed:=maybe_push(right.registers32,self,false);
  604. secondpass(right);
  605. if is_pushed then
  606. restore(self,false);
  607. { here we change the location of right
  608. and the update was forgotten so it
  609. led to wrong code in emitrangecheck later PM
  610. so make range check before }
  611. if cs_check_range in aktlocalswitches then
  612. begin
  613. if left.resulttype^.deftype=arraydef then
  614. begin
  615. if is_open_array(left.resulttype) or
  616. is_array_of_const(left.resulttype) then
  617. begin
  618. reset_reference(href);
  619. parraydef(left.resulttype)^.genrangecheck;
  620. href.symbol:=newasmsymbol(parraydef(left.resulttype)^.getrangecheckstring);
  621. href.offset:=4;
  622. getsymonlyin(tloadnode(left).symtable,
  623. 'high'+pvarsym(tloadnode(left).symtableentry)^.name);
  624. hightree:=genloadnode(pvarsym(srsym),tloadnode(left).symtable);
  625. firstpass(hightree);
  626. secondpass(hightree);
  627. emit_mov_loc_ref(hightree.location,href,S_L,true);
  628. hightree.free;
  629. hightree:=nil;
  630. end;
  631. emitrangecheck(right,left.resulttype);
  632. end;
  633. end;
  634. case right.location.loc of
  635. LOC_REGISTER:
  636. begin
  637. ind:=right.location.register;
  638. case right.resulttype^.size of
  639. 1:
  640. begin
  641. hr:=reg8toreg32(ind);
  642. emit_reg_reg(A_MOVZX,S_BL,ind,hr);
  643. ind:=hr;
  644. end;
  645. 2:
  646. begin
  647. hr:=reg16toreg32(ind);
  648. emit_reg_reg(A_MOVZX,S_WL,ind,hr);
  649. ind:=hr;
  650. end;
  651. end;
  652. end;
  653. LOC_CREGISTER:
  654. begin
  655. ind:=getregister32;
  656. case right.resulttype^.size of
  657. 1:
  658. emit_reg_reg(A_MOVZX,S_BL,right.location.register,ind);
  659. 2:
  660. emit_reg_reg(A_MOVZX,S_WL,right.location.register,ind);
  661. 4:
  662. emit_reg_reg(A_MOV,S_L,right.location.register,ind);
  663. end;
  664. end;
  665. LOC_FLAGS:
  666. begin
  667. ind:=getregister32;
  668. emit_flag2reg(right.location.resflags,reg32toreg8(ind));
  669. emit_reg_reg(A_MOVZX,S_BL,reg32toreg8(ind),ind);
  670. end;
  671. LOC_JUMP :
  672. begin
  673. ind:=getregister32;
  674. emitlab(truelabel);
  675. truelabel:=otl;
  676. emit_const_reg(A_MOV,S_L,1,ind);
  677. getlabel(hl);
  678. emitjmp(C_None,hl);
  679. emitlab(falselabel);
  680. falselabel:=ofl;
  681. emit_reg_reg(A_XOR,S_L,ind,ind);
  682. emitlab(hl);
  683. end;
  684. LOC_REFERENCE,LOC_MEM :
  685. begin
  686. del_reference(right.location.reference);
  687. ind:=getregister32;
  688. { Booleans are stored in an 8 bit memory location, so
  689. the use of MOVL is not correct }
  690. case right.resulttype^.size of
  691. 1 : tai:=new(paicpu,op_ref_reg(A_MOVZX,S_BL,newreference(right.location.reference),ind));
  692. 2 : tai:=new(Paicpu,op_ref_reg(A_MOVZX,S_WL,newreference(right.location.reference),ind));
  693. 4 : tai:=new(Paicpu,op_ref_reg(A_MOV,S_L,newreference(right.location.reference),ind));
  694. end;
  695. exprasmlist^.concat(tai);
  696. end;
  697. else
  698. internalerror(5913428);
  699. end;
  700. { produce possible range check code: }
  701. if cs_check_range in aktlocalswitches then
  702. begin
  703. if left.resulttype^.deftype=arraydef then
  704. begin
  705. { done defore (PM) }
  706. end
  707. else if (left.resulttype^.deftype=stringdef) then
  708. begin
  709. case pstringdef(left.resulttype)^.string_typ of
  710. { it's the same for ansi- and wide strings }
  711. st_widestring,
  712. st_ansistring:
  713. begin
  714. pushusedregisters(pushed,$ff);
  715. emit_reg(A_PUSH,S_L,ind);
  716. hp:=newreference(location.reference);
  717. dec(hp^.offset,7);
  718. emit_ref(A_PUSH,S_L,hp);
  719. emitcall('FPC_ANSISTR_RANGECHECK');
  720. popusedregisters(pushed);
  721. maybe_loadesi;
  722. end;
  723. st_shortstring:
  724. begin
  725. {!!!!!!!!!!!!!!!!!}
  726. end;
  727. st_longstring:
  728. begin
  729. {!!!!!!!!!!!!!!!!!}
  730. end;
  731. end;
  732. end;
  733. end;
  734. if location.reference.index=R_NO then
  735. begin
  736. location.reference.index:=ind;
  737. calc_emit_mul;
  738. end
  739. else
  740. begin
  741. if location.reference.base=R_NO then
  742. begin
  743. case location.reference.scalefactor of
  744. 2 : emit_const_reg(A_SHL,S_L,1,location.reference.index);
  745. 4 : emit_const_reg(A_SHL,S_L,2,location.reference.index);
  746. 8 : emit_const_reg(A_SHL,S_L,3,location.reference.index);
  747. end;
  748. calc_emit_mul;
  749. location.reference.base:=location.reference.index;
  750. location.reference.index:=ind;
  751. end
  752. else
  753. begin
  754. emit_ref_reg(
  755. A_LEA,S_L,newreference(location.reference),
  756. location.reference.index);
  757. ungetregister32(location.reference.base);
  758. { the symbol offset is loaded, }
  759. { so release the symbol name and set symbol }
  760. { to nil }
  761. location.reference.symbol:=nil;
  762. location.reference.offset:=0;
  763. calc_emit_mul;
  764. location.reference.base:=location.reference.index;
  765. location.reference.index:=ind;
  766. end;
  767. end;
  768. if nf_memseg in flags then
  769. location.reference.segment:=R_FS;
  770. end;
  771. end;
  772. {*****************************************************************************
  773. TI386SELFNODE
  774. *****************************************************************************}
  775. procedure ti386selfnode.pass_2;
  776. begin
  777. reset_reference(location.reference);
  778. getexplicitregister32(R_ESI);
  779. if (resulttype^.deftype=classrefdef) or
  780. ((resulttype^.deftype=objectdef)
  781. and pobjectdef(resulttype)^.is_class
  782. ) then
  783. location.register:=R_ESI
  784. else
  785. location.reference.base:=R_ESI;
  786. end;
  787. {*****************************************************************************
  788. TI386WITHNODE
  789. *****************************************************************************}
  790. procedure ti386withnode.pass_2;
  791. var
  792. usetemp,with_expr_in_temp : boolean;
  793. {$ifdef GDB}
  794. withstartlabel,withendlabel : pasmlabel;
  795. pp : pchar;
  796. mangled_length : longint;
  797. const
  798. withlevel : longint = 0;
  799. {$endif GDB}
  800. begin
  801. if assigned(left) then
  802. begin
  803. secondpass(left);
  804. if left.location.reference.segment<>R_NO then
  805. message(parser_e_no_with_for_variable_in_other_segments);
  806. new(withreference);
  807. usetemp:=false;
  808. if (left.nodetype=loadn) and
  809. (tloadnode(left).symtable=aktprocsym^.definition^.localst) then
  810. begin
  811. { for locals use the local storage }
  812. withreference^:=left.location.reference;
  813. include(flags,nf_islocal);
  814. end
  815. else
  816. { call can have happend with a property }
  817. if (left.resulttype^.deftype=objectdef) and
  818. pobjectdef(left.resulttype)^.is_class then
  819. begin
  820. {$ifndef noAllocEdi}
  821. getexplicitregister32(R_EDI);
  822. {$endif noAllocEdi}
  823. emit_mov_loc_reg(left.location,R_EDI);
  824. usetemp:=true;
  825. end
  826. else
  827. begin
  828. {$ifndef noAllocEdi}
  829. getexplicitregister32(R_EDI);
  830. {$endif noAllocEdi}
  831. emit_lea_loc_reg(left.location,R_EDI,false);
  832. usetemp:=true;
  833. end;
  834. release_loc(left.location);
  835. { if the with expression is stored in a temp }
  836. { area we must make it persistent and shouldn't }
  837. { release it (FK) }
  838. if (left.location.loc in [LOC_MEM,LOC_REFERENCE]) and
  839. istemp(left.location.reference) then
  840. begin
  841. normaltemptopersistant(left.location.reference.offset);
  842. with_expr_in_temp:=true;
  843. end
  844. else
  845. with_expr_in_temp:=false;
  846. { if usetemp is set the value must be in %edi }
  847. if usetemp then
  848. begin
  849. gettempofsizereference(4,withreference^);
  850. normaltemptopersistant(withreference^.offset);
  851. { move to temp reference }
  852. emit_reg_ref(A_MOV,S_L,R_EDI,newreference(withreference^));
  853. {$ifndef noAllocEdi}
  854. ungetregister32(R_EDI);
  855. {$endif noAllocEdi}
  856. {$ifdef GDB}
  857. if (cs_debuginfo in aktmoduleswitches) then
  858. begin
  859. inc(withlevel);
  860. getaddrlabel(withstartlabel);
  861. getaddrlabel(withendlabel);
  862. emitlab(withstartlabel);
  863. withdebuglist^.concat(new(pai_stabs,init(strpnew(
  864. '"with'+tostr(withlevel)+':'+tostr(symtablestack^.getnewtypecount)+
  865. '=*'+left.resulttype^.numberstring+'",'+
  866. tostr(N_LSYM)+',0,0,'+tostr(withreference^.offset)))));
  867. mangled_length:=length(aktprocsym^.definition^.mangledname);
  868. getmem(pp,mangled_length+50);
  869. strpcopy(pp,'192,0,0,'+withstartlabel^.name);
  870. if (target_os.use_function_relative_addresses) then
  871. begin
  872. strpcopy(strend(pp),'-');
  873. strpcopy(strend(pp),aktprocsym^.definition^.mangledname);
  874. end;
  875. withdebuglist^.concat(new(pai_stabn,init(strnew(pp))));
  876. end;
  877. {$endif GDB}
  878. del_reference(left.location.reference);
  879. end;
  880. { right can be optimize out !!! }
  881. if assigned(right) then
  882. secondpass(right);
  883. if usetemp then
  884. begin
  885. ungetpersistanttemp(withreference^.offset);
  886. {$ifdef GDB}
  887. if (cs_debuginfo in aktmoduleswitches) then
  888. begin
  889. emitlab(withendlabel);
  890. strpcopy(pp,'224,0,0,'+withendlabel^.name);
  891. if (target_os.use_function_relative_addresses) then
  892. begin
  893. strpcopy(strend(pp),'-');
  894. strpcopy(strend(pp),aktprocsym^.definition^.mangledname);
  895. end;
  896. withdebuglist^.concat(new(pai_stabn,init(strnew(pp))));
  897. freemem(pp,mangled_length+50);
  898. dec(withlevel);
  899. end;
  900. {$endif GDB}
  901. end;
  902. if with_expr_in_temp then
  903. ungetpersistanttemp(left.location.reference.offset);
  904. dispose(withreference);
  905. withreference:=nil;
  906. end;
  907. end;
  908. begin
  909. cloadvmtnode:=ti386loadvmtnode;
  910. chnewnode:=ti386hnewnode;
  911. cnewnode:=ti386newnode;
  912. chdisposenode:=ti386hdisposenode;
  913. csimplenewdisposenode:=ti386simplenewdisposenode;
  914. caddrnode:=ti386addrnode;
  915. cdoubleaddrnode:=ti386doubleaddrnode;
  916. cderefnode:=ti386derefnode;
  917. csubscriptnode:=ti386subscriptnode;
  918. cvecnode:=ti386vecnode;
  919. cselfnode:=ti386selfnode;
  920. cwithnode:=ti386withnode;
  921. end.
  922. {
  923. $Log$
  924. Revision 1.1 2000-10-15 09:33:32 peter
  925. * moved n386*.pas to i386/ cpu_target dir
  926. Revision 1.2 2000/10/14 21:52:54 peter
  927. * fixed memory leaks
  928. Revision 1.1 2000/10/14 10:14:49 peter
  929. * moehrendorf oct 2000 rewrite
  930. }