cg386mem.pas 40 KB

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