cg386mem.pas 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089
  1. {
  2. $Id$
  3. Copyright (c) 1993-98 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 cg386mem;
  19. interface
  20. uses
  21. tree;
  22. procedure secondloadvmt(var p : ptree);
  23. procedure secondhnewn(var p : ptree);
  24. procedure secondnewn(var p : ptree);
  25. procedure secondhdisposen(var p : ptree);
  26. procedure secondsimplenewdispose(var p : ptree);
  27. procedure secondaddr(var p : ptree);
  28. procedure seconddoubleaddr(var p : ptree);
  29. procedure secondderef(var p : ptree);
  30. procedure secondsubscriptn(var p : ptree);
  31. procedure secondvecn(var p : ptree);
  32. procedure secondselfn(var p : ptree);
  33. procedure secondwith(var p : ptree);
  34. implementation
  35. uses
  36. globtype,systems,
  37. cobjects,verbose,globals,
  38. symconst,symtable,aasm,types,
  39. hcodegen,temp_gen,pass_2,pass_1,
  40. cpubase,cpuasm,
  41. cgai386,tgeni386;
  42. {*****************************************************************************
  43. SecondLoadVMT
  44. *****************************************************************************}
  45. procedure secondloadvmt(var p : ptree);
  46. begin
  47. p^.location.register:=getregister32;
  48. emit_sym_ofs_reg(A_MOV,
  49. S_L,newasmsymbol(pobjectdef(pclassrefdef(p^.resulttype)^.definition)^.vmt_mangledname),0,
  50. p^.location.register);
  51. end;
  52. {*****************************************************************************
  53. SecondHNewN
  54. *****************************************************************************}
  55. procedure secondhnewn(var p : ptree);
  56. begin
  57. end;
  58. {*****************************************************************************
  59. SecondNewN
  60. *****************************************************************************}
  61. procedure secondnewn(var p : ptree);
  62. var
  63. pushed : tpushed;
  64. r : preference;
  65. begin
  66. if assigned(p^.left) then
  67. begin
  68. secondpass(p^.left);
  69. p^.location.register:=p^.left^.location.register;
  70. end
  71. else
  72. begin
  73. pushusedregisters(pushed,$ff);
  74. { code copied from simplenewdispose PM }
  75. { determines the size of the mem block }
  76. push_int(ppointerdef(p^.resulttype)^.definition^.size);
  77. gettempofsizereference(target_os.size_of_pointer,p^.location.reference);
  78. emitpushreferenceaddr(p^.location.reference);
  79. emitcall('FPC_GETMEM');
  80. if ppointerdef(p^.resulttype)^.definition^.needs_inittable then
  81. begin
  82. new(r);
  83. reset_reference(r^);
  84. r^.symbol:=ppointerdef(p^.left^.resulttype)^.definition^.get_inittable_label;
  85. emitpushreferenceaddr(r^);
  86. dispose(r);
  87. { push pointer we just allocated, we need to initialize the
  88. data located at that pointer not the pointer self (PFV) }
  89. emit_push_loc(p^.location);
  90. emitcall('FPC_INITIALIZE');
  91. end;
  92. popusedregisters(pushed);
  93. { may be load ESI }
  94. maybe_loadesi;
  95. end;
  96. if codegenerror then
  97. exit;
  98. end;
  99. {*****************************************************************************
  100. SecondDisposeN
  101. *****************************************************************************}
  102. procedure secondhdisposen(var p : ptree);
  103. begin
  104. secondpass(p^.left);
  105. if codegenerror then
  106. exit;
  107. reset_reference(p^.location.reference);
  108. case p^.left^.location.loc of
  109. LOC_REGISTER:
  110. p^.location.reference.index:=p^.left^.location.register;
  111. LOC_CREGISTER:
  112. begin
  113. p^.location.reference.index:=getregister32;
  114. emit_reg_reg(A_MOV,S_L,
  115. p^.left^.location.register,
  116. p^.location.reference.index);
  117. end;
  118. LOC_MEM,LOC_REFERENCE :
  119. begin
  120. del_reference(p^.left^.location.reference);
  121. p^.location.reference.index:=getregister32;
  122. emit_ref_reg(A_MOV,S_L,newreference(p^.left^.location.reference),
  123. p^.location.reference.index);
  124. end;
  125. end;
  126. end;
  127. {*****************************************************************************
  128. SecondNewDispose
  129. *****************************************************************************}
  130. procedure secondsimplenewdispose(var p : ptree);
  131. var
  132. pushed : tpushed;
  133. r : preference;
  134. begin
  135. secondpass(p^.left);
  136. if codegenerror then
  137. exit;
  138. pushusedregisters(pushed,$ff);
  139. { determines the size of the mem block }
  140. push_int(ppointerdef(p^.left^.resulttype)^.definition^.size);
  141. { push pointer adress }
  142. case p^.left^.location.loc of
  143. LOC_CREGISTER : emit_reg(A_PUSH,S_L,
  144. p^.left^.location.register);
  145. LOC_REFERENCE:
  146. emitpushreferenceaddr(p^.left^.location.reference);
  147. end;
  148. { call the mem handling procedures }
  149. case p^.treetype of
  150. simpledisposen:
  151. begin
  152. if ppointerdef(p^.left^.resulttype)^.definition^.needs_inittable then
  153. begin
  154. new(r);
  155. reset_reference(r^);
  156. r^.symbol:=ppointerdef(p^.left^.resulttype)^.definition^.get_inittable_label;
  157. emitpushreferenceaddr(r^);
  158. dispose(r);
  159. { push pointer adress }
  160. emit_push_loc(p^.left^.location);
  161. emitcall('FPC_FINALIZE');
  162. end;
  163. emitcall('FPC_FREEMEM');
  164. end;
  165. simplenewn:
  166. begin
  167. emitcall('FPC_GETMEM');
  168. if ppointerdef(p^.left^.resulttype)^.definition^.needs_inittable then
  169. begin
  170. new(r);
  171. reset_reference(r^);
  172. r^.symbol:=ppointerdef(p^.left^.resulttype)^.definition^.get_inittable_label;
  173. emitpushreferenceaddr(r^);
  174. dispose(r);
  175. emit_push_loc(p^.left^.location);
  176. emitcall('FPC_INITIALIZE');
  177. end;
  178. end;
  179. end;
  180. popusedregisters(pushed);
  181. { may be load ESI }
  182. maybe_loadesi;
  183. end;
  184. {*****************************************************************************
  185. SecondAddr
  186. *****************************************************************************}
  187. procedure secondaddr(var p : ptree);
  188. begin
  189. secondpass(p^.left);
  190. { when loading procvar we do nothing with this node, so load the
  191. location of left }
  192. if p^.procvarload then
  193. begin
  194. set_location(p^.location,p^.left^.location);
  195. exit;
  196. end;
  197. p^.location.loc:=LOC_REGISTER;
  198. del_reference(p^.left^.location.reference);
  199. p^.location.register:=getregister32;
  200. {@ on a procvar means returning an address to the procedure that
  201. is stored in it.}
  202. { yes but p^.left^.symtableentry can be nil
  203. for example on @self !! }
  204. { symtableentry can be also invalid, if left is no tree node }
  205. if (m_tp_procvar in aktmodeswitches) and
  206. (p^.left^.treetype=loadn) and
  207. assigned(p^.left^.symtableentry) and
  208. (p^.left^.symtableentry^.typ=varsym) and
  209. (pvarsym(p^.left^.symtableentry)^.definition^.deftype=procvardef) then
  210. emit_ref_reg(A_MOV,S_L,
  211. newreference(p^.left^.location.reference),
  212. p^.location.register)
  213. else
  214. emit_ref_reg(A_LEA,S_L,
  215. newreference(p^.left^.location.reference),
  216. p^.location.register);
  217. { for use of other segments }
  218. if p^.left^.location.reference.segment<>R_NO then
  219. p^.location.segment:=p^.left^.location.reference.segment;
  220. end;
  221. {*****************************************************************************
  222. SecondDoubleAddr
  223. *****************************************************************************}
  224. procedure seconddoubleaddr(var p : ptree);
  225. begin
  226. secondpass(p^.left);
  227. p^.location.loc:=LOC_REGISTER;
  228. del_reference(p^.left^.location.reference);
  229. p^.location.register:=getregister32;
  230. emit_ref_reg(A_LEA,S_L,
  231. newreference(p^.left^.location.reference),
  232. p^.location.register);
  233. end;
  234. {*****************************************************************************
  235. SecondDeRef
  236. *****************************************************************************}
  237. procedure secondderef(var p : ptree);
  238. var
  239. hr : tregister;
  240. begin
  241. secondpass(p^.left);
  242. reset_reference(p^.location.reference);
  243. case p^.left^.location.loc of
  244. LOC_REGISTER:
  245. p^.location.reference.base:=p^.left^.location.register;
  246. LOC_CREGISTER:
  247. begin
  248. { ... and reserve one for the pointer }
  249. hr:=getregister32;
  250. emit_reg_reg(A_MOV,S_L,p^.left^.location.register,hr);
  251. p^.location.reference.base:=hr;
  252. end;
  253. else
  254. begin
  255. { free register }
  256. del_reference(p^.left^.location.reference);
  257. { ...and reserve one for the pointer }
  258. hr:=getregister32;
  259. emit_ref_reg(
  260. A_MOV,S_L,newreference(p^.left^.location.reference),
  261. hr);
  262. p^.location.reference.base:=hr;
  263. end;
  264. end;
  265. if ppointerdef(p^.left^.resulttype)^.is_far then
  266. p^.location.reference.segment:=R_FS;
  267. if not ppointerdef(p^.left^.resulttype)^.is_far and
  268. (cs_gdb_heaptrc in aktglobalswitches) and
  269. (cs_checkpointer in aktglobalswitches) then
  270. begin
  271. emit_reg(
  272. A_PUSH,S_L,p^.location.reference.base);
  273. emitcall('FPC_CHECKPOINTER');
  274. end;
  275. end;
  276. {*****************************************************************************
  277. SecondSubScriptN
  278. *****************************************************************************}
  279. procedure secondsubscriptn(var p : ptree);
  280. var
  281. hr : tregister;
  282. begin
  283. secondpass(p^.left);
  284. if codegenerror then
  285. exit;
  286. { classes must be dereferenced implicit }
  287. if (p^.left^.resulttype^.deftype=objectdef) and
  288. pobjectdef(p^.left^.resulttype)^.is_class then
  289. begin
  290. reset_reference(p^.location.reference);
  291. case p^.left^.location.loc of
  292. LOC_REGISTER:
  293. p^.location.reference.base:=p^.left^.location.register;
  294. LOC_CREGISTER:
  295. begin
  296. { ... and reserve one for the pointer }
  297. hr:=getregister32;
  298. emit_reg_reg(A_MOV,S_L,p^.left^.location.register,hr);
  299. p^.location.reference.base:=hr;
  300. end;
  301. else
  302. begin
  303. { free register }
  304. del_reference(p^.left^.location.reference);
  305. { ... and reserve one for the pointer }
  306. hr:=getregister32;
  307. emit_ref_reg(
  308. A_MOV,S_L,newreference(p^.left^.location.reference),
  309. hr);
  310. p^.location.reference.base:=hr;
  311. end;
  312. end;
  313. end
  314. else
  315. set_location(p^.location,p^.left^.location);
  316. inc(p^.location.reference.offset,p^.vs^.address);
  317. end;
  318. {*****************************************************************************
  319. SecondVecN
  320. *****************************************************************************}
  321. procedure secondvecn(var p : ptree);
  322. var
  323. is_pushed : boolean;
  324. ind,hr : tregister;
  325. _p : ptree;
  326. function get_mul_size:longint;
  327. begin
  328. if p^.memindex then
  329. get_mul_size:=1
  330. else
  331. get_mul_size:=p^.resulttype^.size;
  332. end;
  333. procedure calc_emit_mul;
  334. var
  335. l1,l2 : longint;
  336. begin
  337. l1:=get_mul_size;
  338. case l1 of
  339. 1,2,4,8 : p^.location.reference.scalefactor:=l1;
  340. else
  341. begin
  342. if ispowerof2(l1,l2) then
  343. emit_const_reg(A_SHL,S_L,l2,ind)
  344. else
  345. emit_const_reg(A_IMUL,S_L,l1,ind);
  346. end;
  347. end;
  348. end;
  349. var
  350. extraoffset : longint;
  351. { rl stores the resulttype of the left node, this is necessary }
  352. { to detect if it is an ansistring }
  353. { because in constant nodes which constant index }
  354. { the left tree is removed }
  355. rl : pdef;
  356. t : ptree;
  357. hp : preference;
  358. href : treference;
  359. tai : Paicpu;
  360. pushed : tpushed;
  361. hightree : ptree;
  362. begin
  363. secondpass(p^.left);
  364. rl:=p^.left^.resulttype;
  365. { we load the array reference to p^.location }
  366. { an ansistring needs to be dereferenced }
  367. if is_ansistring(p^.left^.resulttype) or
  368. is_widestring(p^.left^.resulttype) then
  369. begin
  370. reset_reference(p^.location.reference);
  371. if p^.callunique then
  372. begin
  373. if p^.left^.location.loc<>LOC_REFERENCE then
  374. begin
  375. CGMessage(cg_e_illegal_expression);
  376. exit;
  377. end;
  378. pushusedregisters(pushed,$ff);
  379. emitpushreferenceaddr(p^.left^.location.reference);
  380. if is_ansistring(p^.left^.resulttype) then
  381. emitcall('FPC_ANSISTR_UNIQUE')
  382. else
  383. emitcall('FPC_WIDESTR_UNIQUE');
  384. maybe_loadesi;
  385. popusedregisters(pushed);
  386. end;
  387. if p^.left^.location.loc in [LOC_REGISTER,LOC_CREGISTER] then
  388. begin
  389. p^.location.reference.base:=p^.left^.location.register;
  390. end
  391. else
  392. begin
  393. del_reference(p^.left^.location.reference);
  394. p^.location.reference.base:=getregister32;
  395. emit_ref_reg(A_MOV,S_L,
  396. newreference(p^.left^.location.reference),
  397. p^.location.reference.base);
  398. end;
  399. { check for a zero length string,
  400. we can use the ansistring routine here }
  401. if (cs_check_range in aktlocalswitches) then
  402. begin
  403. pushusedregisters(pushed,$ff);
  404. emit_reg(A_PUSH,S_L,p^.location.reference.base);
  405. emitcall('FPC_ANSISTR_CHECKZERO');
  406. maybe_loadesi;
  407. popusedregisters(pushed);
  408. end;
  409. if is_ansistring(p^.left^.resulttype) then
  410. { in ansistrings S[1] is pchar(S)[0] !! }
  411. dec(p^.location.reference.offset)
  412. else
  413. begin
  414. { in widestrings S[1] is pwchar(S)[0] !! }
  415. dec(p^.location.reference.offset,2);
  416. emit_const_reg(A_SHL,S_L,
  417. 1,p^.location.reference.base);
  418. end;
  419. { we've also to keep left up-to-date, because it is used }
  420. { if a constant array index occurs, subject to change (FK) }
  421. set_location(p^.left^.location,p^.location);
  422. end
  423. else
  424. set_location(p^.location,p^.left^.location);
  425. { offset can only differ from 0 if arraydef }
  426. if p^.left^.resulttype^.deftype=arraydef then
  427. dec(p^.location.reference.offset,
  428. get_mul_size*parraydef(p^.left^.resulttype)^.lowrange);
  429. if p^.right^.treetype=ordconstn then
  430. begin
  431. { offset can only differ from 0 if arraydef }
  432. if (p^.left^.resulttype^.deftype=arraydef) then
  433. begin
  434. if not(is_open_array(p^.left^.resulttype)) and
  435. not(is_array_of_const(p^.left^.resulttype)) then
  436. begin
  437. if (p^.right^.value>parraydef(p^.left^.resulttype)^.highrange) or
  438. (p^.right^.value<parraydef(p^.left^.resulttype)^.lowrange) then
  439. begin
  440. if (cs_check_range in aktlocalswitches) then
  441. CGMessage(parser_e_range_check_error)
  442. else
  443. CGMessage(parser_w_range_check_error);
  444. end;
  445. dec(p^.left^.location.reference.offset,
  446. get_mul_size*parraydef(p^.left^.resulttype)^.lowrange);
  447. end
  448. else
  449. begin
  450. { range checking for open arrays !!!! }
  451. {!!!!!!!!!!!!!!!!!}
  452. end;
  453. end
  454. else if (p^.left^.resulttype^.deftype=stringdef) then
  455. begin
  456. if (p^.right^.value=0) and not(is_shortstring(p^.left^.resulttype)) then
  457. CGMessage(cg_e_can_access_element_zero);
  458. if (cs_check_range in aktlocalswitches) then
  459. case pstringdef(p^.left^.resulttype)^.string_typ of
  460. { it's the same for ansi- and wide strings }
  461. st_widestring,
  462. st_ansistring:
  463. begin
  464. pushusedregisters(pushed,$ff);
  465. push_int(p^.right^.value);
  466. hp:=newreference(p^.location.reference);
  467. dec(hp^.offset,7);
  468. emit_ref(A_PUSH,S_L,hp);
  469. emitcall('FPC_ANSISTR_RANGECHECK');
  470. popusedregisters(pushed);
  471. maybe_loadesi;
  472. end;
  473. st_shortstring:
  474. begin
  475. {!!!!!!!!!!!!!!!!!}
  476. end;
  477. st_longstring:
  478. begin
  479. {!!!!!!!!!!!!!!!!!}
  480. end;
  481. end;
  482. end;
  483. inc(p^.left^.location.reference.offset,
  484. get_mul_size*p^.right^.value);
  485. if p^.memseg then
  486. p^.left^.location.reference.segment:=R_FS;
  487. p^.left^.resulttype:=p^.resulttype;
  488. disposetree(p^.right);
  489. _p:=p^.left;
  490. putnode(p);
  491. p:=_p;
  492. end
  493. else
  494. { not treetype=ordconstn }
  495. begin
  496. { quick hack, to overcome Delphi 2 }
  497. if (cs_regalloc in aktglobalswitches) and
  498. (p^.left^.resulttype^.deftype=arraydef) then
  499. begin
  500. extraoffset:=0;
  501. if (p^.right^.treetype=addn) then
  502. begin
  503. if p^.right^.right^.treetype=ordconstn then
  504. begin
  505. extraoffset:=p^.right^.right^.value;
  506. t:=p^.right^.left;
  507. putnode(p^.right);
  508. putnode(p^.right^.right);
  509. p^.right:=t
  510. end
  511. else if p^.right^.left^.treetype=ordconstn then
  512. begin
  513. extraoffset:=p^.right^.left^.value;
  514. t:=p^.right^.right;
  515. putnode(p^.right);
  516. putnode(p^.right^.left);
  517. p^.right:=t
  518. end;
  519. end
  520. else if (p^.right^.treetype=subn) then
  521. begin
  522. if p^.right^.right^.treetype=ordconstn then
  523. begin
  524. extraoffset:=p^.right^.right^.value;
  525. t:=p^.right^.left;
  526. putnode(p^.right);
  527. putnode(p^.right^.right);
  528. p^.right:=t
  529. end
  530. else if p^.right^.left^.treetype=ordconstn then
  531. begin
  532. extraoffset:=p^.right^.left^.value;
  533. t:=p^.right^.right;
  534. putnode(p^.right);
  535. putnode(p^.right^.left);
  536. p^.right:=t
  537. end;
  538. end;
  539. inc(p^.location.reference.offset,
  540. get_mul_size*extraoffset);
  541. end;
  542. { calculate from left to right }
  543. if (p^.location.loc<>LOC_REFERENCE) and
  544. (p^.location.loc<>LOC_MEM) then
  545. CGMessage(cg_e_illegal_expression);
  546. is_pushed:=maybe_push(p^.right^.registers32,p,false);
  547. secondpass(p^.right);
  548. if is_pushed then
  549. restore(p,false);
  550. { here we change the location of p^.right
  551. and the update was forgotten so it
  552. led to wrong code in emitrangecheck later PM
  553. so make range check before }
  554. if cs_check_range in aktlocalswitches then
  555. begin
  556. if p^.left^.resulttype^.deftype=arraydef then
  557. begin
  558. if is_open_array(p^.left^.resulttype) or
  559. is_array_of_const(p^.left^.resulttype) then
  560. begin
  561. reset_reference(href);
  562. parraydef(p^.left^.resulttype)^.genrangecheck;
  563. href.symbol:=newasmsymbol(parraydef(p^.left^.resulttype)^.getrangecheckstring);
  564. href.offset:=4;
  565. getsymonlyin(p^.left^.symtable,'high'+pvarsym(p^.left^.symtableentry)^.name);
  566. hightree:=genloadnode(pvarsym(srsym),p^.left^.symtable);
  567. firstpass(hightree);
  568. secondpass(hightree);
  569. emit_mov_loc_ref(hightree^.location,href,S_L);
  570. disposetree(hightree);
  571. end;
  572. emitrangecheck(p^.right,p^.left^.resulttype);
  573. end;
  574. end;
  575. case p^.right^.location.loc of
  576. LOC_REGISTER:
  577. begin
  578. ind:=p^.right^.location.register;
  579. case p^.right^.resulttype^.size of
  580. 1:
  581. begin
  582. hr:=reg8toreg32(ind);
  583. emit_reg_reg(A_MOVZX,S_BL,ind,hr);
  584. ind:=hr;
  585. end;
  586. 2:
  587. begin
  588. hr:=reg16toreg32(ind);
  589. emit_reg_reg(A_MOVZX,S_WL,ind,hr);
  590. ind:=hr;
  591. end;
  592. end;
  593. end;
  594. LOC_CREGISTER:
  595. begin
  596. ind:=getregister32;
  597. case p^.right^.resulttype^.size of
  598. 1:
  599. emit_reg_reg(A_MOVZX,S_BL,p^.right^.location.register,ind);
  600. 2:
  601. emit_reg_reg(A_MOVZX,S_WL,p^.right^.location.register,ind);
  602. 4:
  603. emit_reg_reg(A_MOV,S_L,p^.right^.location.register,ind);
  604. end;
  605. end;
  606. LOC_FLAGS:
  607. begin
  608. ind:=getregister32;
  609. emit_flag2reg(p^.right^.location.resflags,reg32toreg8(ind));
  610. emit_reg_reg(A_MOVZX,S_BL,reg32toreg8(ind),ind);
  611. end
  612. else
  613. begin
  614. del_reference(p^.right^.location.reference);
  615. ind:=getregister32;
  616. { Booleans are stored in an 8 bit memory location, so
  617. the use of MOVL is not correct }
  618. case p^.right^.resulttype^.size of
  619. 1 : tai:=new(paicpu,op_ref_reg(A_MOVZX,S_BL,newreference(p^.right^.location.reference),ind));
  620. 2 : tai:=new(Paicpu,op_ref_reg(A_MOVZX,S_WL,newreference(p^.right^.location.reference),ind));
  621. 4 : tai:=new(Paicpu,op_ref_reg(A_MOV,S_L,newreference(p^.right^.location.reference),ind));
  622. end;
  623. exprasmlist^.concat(tai);
  624. end;
  625. end;
  626. { produce possible range check code: }
  627. if cs_check_range in aktlocalswitches then
  628. begin
  629. if p^.left^.resulttype^.deftype=arraydef then
  630. begin
  631. { done defore (PM) }
  632. end
  633. else if (p^.left^.resulttype^.deftype=stringdef) then
  634. begin
  635. case pstringdef(p^.left^.resulttype)^.string_typ of
  636. { it's the same for ansi- and wide strings }
  637. st_widestring,
  638. st_ansistring:
  639. begin
  640. pushusedregisters(pushed,$ff);
  641. emit_reg(A_PUSH,S_L,ind);
  642. hp:=newreference(p^.location.reference);
  643. dec(hp^.offset,7);
  644. emit_ref(A_PUSH,S_L,hp);
  645. emitcall('FPC_ANSISTR_RANGECHECK');
  646. popusedregisters(pushed);
  647. maybe_loadesi;
  648. end;
  649. st_shortstring:
  650. begin
  651. {!!!!!!!!!!!!!!!!!}
  652. end;
  653. st_longstring:
  654. begin
  655. {!!!!!!!!!!!!!!!!!}
  656. end;
  657. end;
  658. end;
  659. end;
  660. if p^.location.reference.index=R_NO then
  661. begin
  662. p^.location.reference.index:=ind;
  663. calc_emit_mul;
  664. end
  665. else
  666. begin
  667. if p^.location.reference.base=R_NO then
  668. begin
  669. case p^.location.reference.scalefactor of
  670. 2 : emit_const_reg(A_SHL,S_L,1,p^.location.reference.index);
  671. 4 : emit_const_reg(A_SHL,S_L,2,p^.location.reference.index);
  672. 8 : emit_const_reg(A_SHL,S_L,3,p^.location.reference.index);
  673. end;
  674. calc_emit_mul;
  675. p^.location.reference.base:=p^.location.reference.index;
  676. p^.location.reference.index:=ind;
  677. end
  678. else
  679. begin
  680. emit_ref_reg(
  681. A_LEA,S_L,newreference(p^.location.reference),
  682. p^.location.reference.index);
  683. ungetregister32(p^.location.reference.base);
  684. { the symbol offset is loaded, }
  685. { so release the symbol name and set symbol }
  686. { to nil }
  687. p^.location.reference.symbol:=nil;
  688. p^.location.reference.offset:=0;
  689. calc_emit_mul;
  690. p^.location.reference.base:=p^.location.reference.index;
  691. p^.location.reference.index:=ind;
  692. end;
  693. end;
  694. if p^.memseg then
  695. p^.location.reference.segment:=R_FS;
  696. end;
  697. end;
  698. {*****************************************************************************
  699. SecondSelfN
  700. *****************************************************************************}
  701. procedure secondselfn(var p : ptree);
  702. begin
  703. reset_reference(p^.location.reference);
  704. if (p^.resulttype^.deftype=classrefdef) or
  705. ((p^.resulttype^.deftype=objectdef)
  706. and pobjectdef(p^.resulttype)^.is_class
  707. ) then
  708. p^.location.register:=R_ESI
  709. else
  710. p^.location.reference.base:=R_ESI;
  711. end;
  712. {*****************************************************************************
  713. SecondWithN
  714. *****************************************************************************}
  715. procedure secondwith(var p : ptree);
  716. var
  717. usetemp,with_expr_in_temp : boolean;
  718. begin
  719. if assigned(p^.left) then
  720. begin
  721. secondpass(p^.left);
  722. if p^.left^.location.reference.segment<>R_NO then
  723. message(parser_e_no_with_for_variable_in_other_segments);
  724. new(p^.withreference);
  725. usetemp:=false;
  726. if (p^.left^.treetype=loadn) and
  727. (p^.left^.symtable=aktprocsym^.definition^.localst) then
  728. begin
  729. { for locals use the local storage }
  730. p^.withreference^:=p^.left^.location.reference;
  731. p^.islocal:=true;
  732. end
  733. else
  734. { call can happend with a property }
  735. if { (p^.left^.treetype=calln) and Don't think that
  736. this is necessary (FK) }
  737. (p^.left^.resulttype^.deftype=objectdef) and
  738. pobjectdef(p^.left^.resulttype)^.is_class then
  739. begin
  740. emit_mov_loc_reg(p^.left^.location,R_EDI);
  741. usetemp:=true;
  742. end
  743. else
  744. begin
  745. emit_lea_loc_reg(p^.left^.location,R_EDI,false);
  746. usetemp:=true;
  747. end;
  748. release_loc(p^.left^.location);
  749. { if the with expression is stored in a temp }
  750. { area we must make it persistent and shouldn't }
  751. { release it (FK) }
  752. if (p^.left^.location.loc in [LOC_MEM,LOC_REFERENCE]) and
  753. istemp(p^.left^.location.reference) then
  754. begin
  755. normaltemptopersistant(p^.left^.location.reference.offset);
  756. with_expr_in_temp:=true;
  757. end
  758. else
  759. with_expr_in_temp:=false;
  760. { if usetemp is set the value must be in %edi }
  761. if usetemp then
  762. begin
  763. gettempofsizereference(4,p^.withreference^);
  764. normaltemptopersistant(p^.withreference^.offset);
  765. { move to temp reference }
  766. emit_reg_ref(A_MOV,S_L,
  767. R_EDI,newreference(p^.withreference^));
  768. del_reference(p^.left^.location.reference);
  769. end;
  770. { p^.right can be optimize out !!! }
  771. if assigned(p^.right) then
  772. secondpass(p^.right);
  773. if usetemp then
  774. ungetpersistanttemp(p^.withreference^.offset);
  775. if with_expr_in_temp then
  776. ungetpersistanttemp(p^.left^.location.reference.offset);
  777. dispose(p^.withreference);
  778. p^.withreference:=nil;
  779. end;
  780. end;
  781. end.
  782. {
  783. $Log$
  784. Revision 1.58 1999-09-17 17:14:02 peter
  785. * @procvar fixes for tp mode
  786. * @<id>:= gives now an error
  787. Revision 1.57 1999/09/14 07:59:46 florian
  788. * finally!? fixed
  789. with <function with result in temp> do
  790. My last and also Peter's fix before were wrong :(
  791. Revision 1.56 1999/09/13 20:49:41 florian
  792. * hopefully an error in Peter's previous commit fixed
  793. Revision 1.55 1999/09/10 15:42:50 peter
  794. * fixed with <calln> do
  795. * fixed finalize/initialize call for new/dispose
  796. Revision 1.54 1999/08/25 11:59:46 jonas
  797. * changed pai386, paippc and paiapha (same for tai*) to paicpu (taicpu)
  798. Revision 1.53 1999/08/23 23:49:21 pierre
  799. * hnewn location corrected
  800. Revision 1.52 1999/08/19 13:08:52 pierre
  801. * emit_??? used
  802. Revision 1.51 1999/08/16 23:20:28 peter
  803. * range check for array of const
  804. Revision 1.50 1999/08/14 00:36:05 peter
  805. * array constructor support
  806. Revision 1.49 1999/08/04 00:22:53 florian
  807. * renamed i386asm and i386base to cpuasm and cpubase
  808. Revision 1.48 1999/08/03 22:02:47 peter
  809. * moved bitmask constants to sets
  810. * some other type/const renamings
  811. Revision 1.47 1999/06/02 10:11:45 florian
  812. * make cycle fixed i.e. compilation with 0.99.10
  813. * some fixes for qword
  814. * start of register calling conventions
  815. Revision 1.46 1999/05/27 19:44:17 peter
  816. * removed oldasm
  817. * plabel -> pasmlabel
  818. * -a switches to source writing automaticly
  819. * assembler readers OOPed
  820. * asmsymbol automaticly external
  821. * jumptables and other label fixes for asm readers
  822. Revision 1.45 1999/05/23 18:42:04 florian
  823. * better error recovering in typed constants
  824. * some problems with arrays of const fixed, some problems
  825. due my previous
  826. - the location type of array constructor is now LOC_MEM
  827. - the pushing of high fixed
  828. - parameter copying fixed
  829. - zero temp. allocation removed
  830. * small problem in the assembler writers fixed:
  831. ref to nil wasn't written correctly
  832. Revision 1.44 1999/05/21 13:54:53 peter
  833. * NEWLAB for label as symbol
  834. Revision 1.43 1999/05/19 16:48:21 florian
  835. * tdef.typename: returns a now a proper type name for the most types
  836. Revision 1.42 1999/05/18 22:11:52 pierre
  837. * checkpointer code was wrong!
  838. Revision 1.41 1999/05/18 21:58:29 florian
  839. * fixed some bugs related to temp. ansistrings and functions results
  840. which return records/objects/arrays which need init/final.
  841. Revision 1.40 1999/05/18 14:15:26 peter
  842. * containsself fixes
  843. * checktypes()
  844. Revision 1.39 1999/05/17 23:51:39 peter
  845. * with temp vars now use a reference with a persistant temp instead
  846. of setting datasize
  847. Revision 1.38 1999/05/17 21:57:05 florian
  848. * new temporary ansistring handling
  849. Revision 1.37 1999/05/17 14:14:14 pierre
  850. + -gc for check pointer with heaptrc
  851. Revision 1.36 1999/05/12 00:19:44 peter
  852. * removed R_DEFAULT_SEG
  853. * uniform float names
  854. Revision 1.35 1999/05/01 13:24:13 peter
  855. * merged nasm compiler
  856. * old asm moved to oldasm/
  857. Revision 1.34 1999/04/26 18:29:54 peter
  858. * farpointerdef moved into pointerdef.is_far
  859. Revision 1.33 1999/03/26 11:43:26 pierre
  860. * bug0236 fixed
  861. Revision 1.32 1999/03/24 23:16:53 peter
  862. * fixed bugs 212,222,225,227,229,231,233
  863. Revision 1.31 1999/02/25 21:02:29 peter
  864. * ag386bin updates
  865. + coff writer
  866. Revision 1.30 1999/02/22 02:15:14 peter
  867. * updates for ag386bin
  868. Revision 1.29 1999/02/07 22:53:07 florian
  869. * potential bug in secondvecn fixed
  870. Revision 1.28 1999/02/04 17:16:51 peter
  871. * fixed crash with temp ansistring indexing
  872. Revision 1.27 1999/02/04 11:44:46 florian
  873. * fixed indexed access of ansistrings to temp. ansistring, i.e.
  874. c:=(s1+s2)[i], the temp is now correctly remove and the generated
  875. code is also fixed
  876. Revision 1.26 1999/02/04 10:49:41 florian
  877. + range checking for ansi- and widestrings
  878. * made it compilable with TP
  879. Revision 1.25 1999/01/21 16:40:52 pierre
  880. * fix for constructor inside with statements
  881. Revision 1.24 1999/01/19 12:05:27 pierre
  882. * bug with @procvar=procvar fiwed
  883. Revision 1.23 1998/12/30 22:15:45 peter
  884. + farpointer type
  885. * absolutesym now also stores if its far
  886. Revision 1.22 1998/12/11 00:02:55 peter
  887. + globtype,tokens,version unit splitted from globals
  888. Revision 1.21 1998/12/10 09:47:18 florian
  889. + basic operations with int64/qord (compiler with -dint64)
  890. + rtti of enumerations extended: names are now written
  891. Revision 1.20 1998/11/25 19:12:54 pierre
  892. * var:=new(pointer_type) support added
  893. Revision 1.19 1998/11/20 15:35:55 florian
  894. * problems with rtti fixed, hope it works
  895. Revision 1.18 1998/11/17 00:36:40 peter
  896. * more ansistring fixes
  897. Revision 1.17 1998/11/16 15:35:09 pierre
  898. * added error for with if different segment
  899. Revision 1.16 1998/10/21 11:44:42 florian
  900. + check for access to index 0 of long/wide/ansi strings added,
  901. gives now an error
  902. * problem with access to contant index of ansistrings fixed
  903. Revision 1.15 1998/10/12 09:49:53 florian
  904. + support of <procedure var type>:=<pointer> in delphi mode added
  905. Revision 1.14 1998/10/02 07:20:37 florian
  906. * range checking in units doesn't work if the units are smartlinked, fixed
  907. Revision 1.13 1998/09/27 10:16:23 florian
  908. * type casts pchar<->ansistring fixed
  909. * ansistring[..] calls does now an unique call
  910. Revision 1.12 1998/09/23 15:46:36 florian
  911. * problem with with and classes fixed
  912. Revision 1.11 1998/09/17 09:42:18 peter
  913. + pass_2 for cg386
  914. * Message() -> CGMessage() for pass_1/pass_2
  915. Revision 1.10 1998/09/14 10:43:52 peter
  916. * all internal RTL functions start with FPC_
  917. Revision 1.9 1998/09/03 16:03:15 florian
  918. + rtti generation
  919. * init table generation changed
  920. Revision 1.8 1998/08/23 21:04:34 florian
  921. + rtti generation for classes added
  922. + new/dispose do now also a call to INITIALIZE/FINALIZE, if necessaray
  923. Revision 1.7 1998/08/20 11:27:40 michael
  924. * Applied Peters Fix
  925. Revision 1.6 1998/08/10 14:49:49 peter
  926. + localswitches, moduleswitches, globalswitches splitting
  927. Revision 1.5 1998/07/26 21:58:58 florian
  928. + better support for switch $H
  929. + index access to ansi strings added
  930. + assigment of data (records/arrays) containing ansi strings
  931. Revision 1.4 1998/07/24 22:16:55 florian
  932. * internal error 10 together with array access fixed. I hope
  933. that's the final fix.
  934. Revision 1.3 1998/06/25 08:48:09 florian
  935. * first version of rtti support
  936. Revision 1.2 1998/06/08 13:13:35 pierre
  937. + temporary variables now in temp_gen.pas unit
  938. because it is processor independent
  939. * mppc68k.bat modified to undefine i386 and support_mmx
  940. (which are defaults for i386)
  941. Revision 1.1 1998/06/05 17:44:13 peter
  942. * splitted cgi386
  943. }