cg386mem.pas 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  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. cobjects,verbose,globals,systems,
  37. symtable,aasm,i386,types,
  38. cgi386,cgai386,temp_gen,tgeni386,hcodegen;
  39. {*****************************************************************************
  40. SecondLoadVMT
  41. *****************************************************************************}
  42. procedure secondloadvmt(var p : ptree);
  43. begin
  44. p^.location.register:=getregister32;
  45. exprasmlist^.concat(new(pai386,op_csymbol_reg(A_MOV,
  46. S_L,newcsymbol(pobjectdef(pclassrefdef(p^.resulttype)^.definition)^.vmt_mangledname,0),
  47. p^.location.register)));
  48. end;
  49. {*****************************************************************************
  50. SecondHNewN
  51. *****************************************************************************}
  52. procedure secondhnewn(var p : ptree);
  53. begin
  54. end;
  55. {*****************************************************************************
  56. SecondNewN
  57. *****************************************************************************}
  58. procedure secondnewn(var p : ptree);
  59. begin
  60. secondpass(p^.left);
  61. if codegenerror then
  62. exit;
  63. p^.location.register:=p^.left^.location.register;
  64. end;
  65. {*****************************************************************************
  66. SecondDisposeN
  67. *****************************************************************************}
  68. procedure secondhdisposen(var p : ptree);
  69. begin
  70. secondpass(p^.left);
  71. if codegenerror then
  72. exit;
  73. clear_reference(p^.location.reference);
  74. case p^.left^.location.loc of
  75. LOC_REGISTER,
  76. LOC_CREGISTER:
  77. begin
  78. p^.location.reference.index:=getregister32;
  79. exprasmlist^.concat(new(pai386,op_reg_reg(A_MOV,S_L,
  80. p^.left^.location.register,
  81. p^.location.reference.index)));
  82. end;
  83. LOC_MEM,LOC_REFERENCE :
  84. begin
  85. del_reference(p^.left^.location.reference);
  86. p^.location.reference.index:=getregister32;
  87. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,newreference(p^.left^.location.reference),
  88. p^.location.reference.index)));
  89. end;
  90. end;
  91. end;
  92. {*****************************************************************************
  93. SecondNewDispose
  94. *****************************************************************************}
  95. procedure secondsimplenewdispose(var p : ptree);
  96. var
  97. pushed : tpushed;
  98. r : preference;
  99. begin
  100. secondpass(p^.left);
  101. if codegenerror then
  102. exit;
  103. pushusedregisters(pushed,$ff);
  104. { determines the size of the mem block }
  105. push_int(ppointerdef(p^.left^.resulttype)^.definition^.size);
  106. { push pointer adress }
  107. case p^.left^.location.loc of
  108. LOC_CREGISTER : exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,
  109. p^.left^.location.register)));
  110. LOC_REFERENCE:
  111. emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
  112. end;
  113. { call the mem handling procedures }
  114. case p^.treetype of
  115. simpledisposen:
  116. begin
  117. if ppointerdef(p^.left^.resulttype)^.definition^.needs_inittable then
  118. begin
  119. new(r);
  120. reset_reference(r^);
  121. r^.symbol:=stringdup(lab2str(ppointerdef(p^.left^.resulttype)^.definition^.get_rtti_label));
  122. emitpushreferenceaddr(exprasmlist,r^);
  123. { push pointer adress }
  124. case p^.left^.location.loc of
  125. LOC_CREGISTER : exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,
  126. p^.left^.location.register)));
  127. LOC_REFERENCE:
  128. emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
  129. end;
  130. emitcall('FINALIZE',true);
  131. end;
  132. emitcall('FREEMEM',true);
  133. end;
  134. simplenewn:
  135. begin
  136. emitcall('GETMEM',true);
  137. if ppointerdef(p^.left^.resulttype)^.definition^.needs_inittable then
  138. begin
  139. new(r);
  140. reset_reference(r^);
  141. r^.symbol:=stringdup(lab2str(ppointerdef(p^.left^.resulttype)^.definition^.get_rtti_label));
  142. emitpushreferenceaddr(exprasmlist,r^);
  143. { push pointer adress }
  144. case p^.left^.location.loc of
  145. LOC_CREGISTER : exprasmlist^.concat(new(pai386,op_reg(A_PUSH,S_L,
  146. p^.left^.location.register)));
  147. LOC_REFERENCE:
  148. emitpushreferenceaddr(exprasmlist,p^.left^.location.reference);
  149. end;
  150. emitcall('INITIALIZE',true);
  151. end;
  152. end;
  153. end;
  154. popusedregisters(pushed);
  155. { may be load ESI }
  156. maybe_loadesi;
  157. end;
  158. {*****************************************************************************
  159. SecondAddr
  160. *****************************************************************************}
  161. procedure secondaddr(var p : ptree);
  162. begin
  163. secondpass(p^.left);
  164. p^.location.loc:=LOC_REGISTER;
  165. del_reference(p^.left^.location.reference);
  166. p^.location.register:=getregister32;
  167. {@ on a procvar means returning an address to the procedure that
  168. is stored in it.}
  169. { yes but p^.left^.symtableentry can be nil
  170. for example on @self !! }
  171. { symtableentry can be also invalid, if left is no tree node }
  172. if (p^.left^.treetype=loadn) and
  173. assigned(p^.left^.symtableentry) and
  174. (p^.left^.symtableentry^.typ=varsym) and
  175. (pvarsym(p^.left^.symtableentry)^.definition^.deftype=procvardef) then
  176. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  177. newreference(p^.left^.location.reference),
  178. p^.location.register)))
  179. else
  180. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,
  181. newreference(p^.left^.location.reference),
  182. p^.location.register)));
  183. { for use of other segments }
  184. if p^.left^.location.reference.segment<>R_DEFAULT_SEG then
  185. p^.location.segment:=p^.left^.location.reference.segment;
  186. end;
  187. {*****************************************************************************
  188. SecondDoubleAddr
  189. *****************************************************************************}
  190. procedure seconddoubleaddr(var p : ptree);
  191. begin
  192. secondpass(p^.left);
  193. p^.location.loc:=LOC_REGISTER;
  194. del_reference(p^.left^.location.reference);
  195. p^.location.register:=getregister32;
  196. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,
  197. newreference(p^.left^.location.reference),
  198. p^.location.register)));
  199. end;
  200. {*****************************************************************************
  201. SecondDeRef
  202. *****************************************************************************}
  203. procedure secondderef(var p : ptree);
  204. var
  205. hr : tregister;
  206. begin
  207. secondpass(p^.left);
  208. clear_reference(p^.location.reference);
  209. case p^.left^.location.loc of
  210. LOC_REGISTER:
  211. p^.location.reference.base:=p^.left^.location.register;
  212. LOC_CREGISTER:
  213. begin
  214. { ... and reserve one for the pointer }
  215. hr:=getregister32;
  216. emit_reg_reg(A_MOV,S_L,p^.left^.location.register,hr);
  217. p^.location.reference.base:=hr;
  218. end;
  219. else
  220. begin
  221. { free register }
  222. del_reference(p^.left^.location.reference);
  223. { ...and reserve one for the pointer }
  224. hr:=getregister32;
  225. exprasmlist^.concat(new(pai386,op_ref_reg(
  226. A_MOV,S_L,newreference(p^.left^.location.reference),
  227. hr)));
  228. p^.location.reference.base:=hr;
  229. end;
  230. end;
  231. end;
  232. {*****************************************************************************
  233. SecondSubScriptN
  234. *****************************************************************************}
  235. procedure secondsubscriptn(var p : ptree);
  236. var
  237. hr : tregister;
  238. begin
  239. secondpass(p^.left);
  240. if codegenerror then
  241. exit;
  242. { classes must be dereferenced implicit }
  243. if (p^.left^.resulttype^.deftype=objectdef) and
  244. pobjectdef(p^.left^.resulttype)^.isclass then
  245. begin
  246. clear_reference(p^.location.reference);
  247. case p^.left^.location.loc of
  248. LOC_REGISTER:
  249. p^.location.reference.base:=p^.left^.location.register;
  250. LOC_CREGISTER:
  251. begin
  252. { ... and reserve one for the pointer }
  253. hr:=getregister32;
  254. emit_reg_reg(A_MOV,S_L,p^.left^.location.register,hr);
  255. p^.location.reference.base:=hr;
  256. end;
  257. else
  258. begin
  259. { free register }
  260. del_reference(p^.left^.location.reference);
  261. { ... and reserve one for the pointer }
  262. hr:=getregister32;
  263. exprasmlist^.concat(new(pai386,op_ref_reg(
  264. A_MOV,S_L,newreference(p^.left^.location.reference),
  265. hr)));
  266. p^.location.reference.base:=hr;
  267. end;
  268. end;
  269. end
  270. else
  271. set_location(p^.location,p^.left^.location);
  272. inc(p^.location.reference.offset,p^.vs^.address);
  273. end;
  274. {*****************************************************************************
  275. SecondVecN
  276. *****************************************************************************}
  277. procedure secondvecn(var p : ptree);
  278. var
  279. pushed : boolean;
  280. ind,hr : tregister;
  281. _p : ptree;
  282. function get_mul_size:longint;
  283. begin
  284. if p^.memindex then
  285. get_mul_size:=1
  286. else
  287. get_mul_size:=p^.resulttype^.size;
  288. end;
  289. procedure calc_emit_mul;
  290. var
  291. l1,l2 : longint;
  292. begin
  293. l1:=get_mul_size;
  294. case l1 of
  295. 1,2,4,8 : p^.location.reference.scalefactor:=l1;
  296. else
  297. begin
  298. if ispowerof2(l1,l2) then
  299. exprasmlist^.concat(new(pai386,op_const_reg(A_SHL,S_L,l2,ind)))
  300. else
  301. exprasmlist^.concat(new(pai386,op_const_reg(A_IMUL,S_L,l1,ind)));
  302. end;
  303. end;
  304. end;
  305. var
  306. extraoffset : longint;
  307. t : ptree;
  308. hp : preference;
  309. tai : Pai386;
  310. begin
  311. secondpass(p^.left);
  312. { we load the array reference to p^.location }
  313. { an ansistring needs to be dereferenced }
  314. if is_ansistring(p^.left^.resulttype) or
  315. is_widestring(p^.left^.resulttype) then
  316. begin
  317. reset_reference(p^.location.reference);
  318. p^.location.loc:=LOC_REFERENCE;
  319. del_reference(p^.left^.location.reference);
  320. p^.location.reference.base:=getregister32;
  321. exprasmlist^.concat(new(pai386,op_ref_reg(A_MOV,S_L,
  322. newreference(p^.left^.location.reference),
  323. p^.location.reference.base)));
  324. if is_ansistring(p^.left^.resulttype) then
  325. begin
  326. { in ansistrings S[1] is pchar(S)[0] !! }
  327. dec(p^.location.reference.offset);
  328. { this is necessary for ansistrings with constant index }
  329. dec(p^.left^.location.reference.offset);
  330. end
  331. else
  332. begin
  333. { in widestrings S[1] is pwchar(S)[0] !! }
  334. dec(p^.location.reference.offset,2);
  335. { this is necessary for ansistrings with constant index }
  336. dec(p^.left^.location.reference.offset,2);
  337. exprasmlist^.concat(new(pai386,op_const_reg(A_SHL,S_L,
  338. 2,p^.location.reference.base)));
  339. end;
  340. end
  341. else
  342. set_location(p^.location,p^.left^.location);
  343. { offset can only differ from 0 if arraydef }
  344. if p^.left^.resulttype^.deftype=arraydef then
  345. dec(p^.location.reference.offset,
  346. get_mul_size*parraydef(p^.left^.resulttype)^.lowrange);
  347. if p^.right^.treetype=ordconstn then
  348. begin
  349. { offset can only differ from 0 if arraydef }
  350. if (p^.left^.resulttype^.deftype=arraydef) then
  351. begin
  352. if not(is_open_array(p^.left^.resulttype)) then
  353. begin
  354. if (p^.right^.value>parraydef(p^.left^.resulttype)^.highrange) or
  355. (p^.right^.value<parraydef(p^.left^.resulttype)^.lowrange) then
  356. Message(parser_e_range_check_error);
  357. dec(p^.left^.location.reference.offset,
  358. get_mul_size*parraydef(p^.left^.resulttype)^.lowrange);
  359. end
  360. else
  361. begin
  362. { range checking for open arrays }
  363. end;
  364. end;
  365. inc(p^.left^.location.reference.offset,
  366. get_mul_size*p^.right^.value);
  367. if p^.memseg then
  368. p^.left^.location.reference.segment:=R_FS;
  369. p^.left^.resulttype:=p^.resulttype;
  370. disposetree(p^.right);
  371. _p:=p^.left;
  372. putnode(p);
  373. p:=_p;
  374. end
  375. else
  376. begin
  377. { quick hack, to overcome Delphi 2 }
  378. if (cs_regalloc in aktglobalswitches) and
  379. (p^.left^.resulttype^.deftype=arraydef) then
  380. begin
  381. extraoffset:=0;
  382. if (p^.right^.treetype=addn) then
  383. begin
  384. if p^.right^.right^.treetype=ordconstn then
  385. begin
  386. extraoffset:=p^.right^.right^.value;
  387. t:=p^.right^.left;
  388. putnode(p^.right);
  389. putnode(p^.right^.right);
  390. p^.right:=t
  391. end
  392. else if p^.right^.left^.treetype=ordconstn then
  393. begin
  394. extraoffset:=p^.right^.left^.value;
  395. t:=p^.right^.right;
  396. putnode(p^.right);
  397. putnode(p^.right^.left);
  398. p^.right:=t
  399. end;
  400. end
  401. else if (p^.right^.treetype=subn) then
  402. begin
  403. if p^.right^.right^.treetype=ordconstn then
  404. begin
  405. extraoffset:=p^.right^.right^.value;
  406. t:=p^.right^.left;
  407. putnode(p^.right);
  408. putnode(p^.right^.right);
  409. p^.right:=t
  410. end
  411. else if p^.right^.left^.treetype=ordconstn then
  412. begin
  413. extraoffset:=p^.right^.left^.value;
  414. t:=p^.right^.right;
  415. putnode(p^.right);
  416. putnode(p^.right^.left);
  417. p^.right:=t
  418. end;
  419. end;
  420. inc(p^.location.reference.offset,
  421. get_mul_size*extraoffset);
  422. end;
  423. { calculate from left to right }
  424. if (p^.location.loc<>LOC_REFERENCE) and
  425. (p^.location.loc<>LOC_MEM) then
  426. Message(cg_e_illegal_expression);
  427. pushed:=maybe_push(p^.right^.registers32,p);
  428. secondpass(p^.right);
  429. if pushed then restore(p);
  430. case p^.right^.location.loc of
  431. LOC_REGISTER:
  432. begin
  433. ind:=p^.right^.location.register;
  434. case p^.right^.resulttype^.size of
  435. 1:
  436. begin
  437. hr:=reg8toreg32(ind);
  438. emit_reg_reg(A_MOVZX,S_BL,ind,hr);
  439. ind:=hr;
  440. end;
  441. 2:
  442. begin
  443. hr:=reg16toreg32(ind);
  444. emit_reg_reg(A_MOVZX,S_WL,ind,hr);
  445. ind:=hr;
  446. end;
  447. end;
  448. end;
  449. LOC_CREGISTER:
  450. begin
  451. ind:=getregister32;
  452. case p^.right^.resulttype^.size of
  453. 1:
  454. emit_reg_reg(A_MOVZX,S_BL,p^.right^.location.register,ind);
  455. 2:
  456. emit_reg_reg(A_MOVZX,S_WL,p^.right^.location.register,ind);
  457. 4:
  458. emit_reg_reg(A_MOV,S_L,p^.right^.location.register,ind);
  459. end;
  460. end;
  461. LOC_FLAGS:
  462. begin
  463. ind:=getregister32;
  464. exprasmlist^.concat(new(pai386,op_reg(flag_2_set[p^.right^.location.resflags],S_B,reg32toreg8(ind))));
  465. emit_reg_reg(A_MOVZX,S_BL,reg32toreg8(ind),ind);
  466. end
  467. else
  468. begin
  469. del_reference(p^.right^.location.reference);
  470. ind:=getregister32;
  471. { Booleans are stored in an 8 bit memory location, so
  472. the use of MOVL is not correct }
  473. case p^.right^.resulttype^.size of
  474. 1:
  475. tai:=new(pai386,op_ref_reg(A_MOVZX,S_BL,newreference(p^.right^.location.reference),ind));
  476. 2:
  477. tai:=new(Pai386,op_ref_reg(A_MOVZX,S_WL,newreference(p^.right^.location.reference),ind));
  478. 4:
  479. tai:=new(Pai386,op_ref_reg(A_MOV,S_L,newreference(p^.right^.location.reference),ind));
  480. end;
  481. exprasmlist^.concat(tai);
  482. end;
  483. end;
  484. { produce possible range check code: }
  485. if cs_check_range in aktlocalswitches then
  486. begin
  487. if p^.left^.resulttype^.deftype=arraydef then
  488. begin
  489. hp:=new_reference(R_NO,0);
  490. parraydef(p^.left^.resulttype)^.genrangecheck;
  491. hp^.symbol:=stringdup('R_'+tostr(parraydef(p^.left^.resulttype)^.rangenr));
  492. exprasmlist^.concat(new(pai386,op_reg_ref(A_BOUND,S_L,ind,hp)));
  493. end;
  494. end;
  495. if p^.location.reference.index=R_NO then
  496. begin
  497. p^.location.reference.index:=ind;
  498. calc_emit_mul;
  499. end
  500. else
  501. begin
  502. if p^.location.reference.base=R_NO then
  503. begin
  504. case p^.location.reference.scalefactor of
  505. 2 : exprasmlist^.concat(new(pai386,op_const_reg(A_SHL,S_L,1,p^.location.reference.index)));
  506. 4 : exprasmlist^.concat(new(pai386,op_const_reg(A_SHL,S_L,2,p^.location.reference.index)));
  507. 8 : exprasmlist^.concat(new(pai386,op_const_reg(A_SHL,S_L,3,p^.location.reference.index)));
  508. end;
  509. calc_emit_mul;
  510. p^.location.reference.base:=p^.location.reference.index;
  511. p^.location.reference.index:=ind;
  512. end
  513. else
  514. begin
  515. exprasmlist^.concat(new(pai386,op_ref_reg(
  516. A_LEA,S_L,newreference(p^.location.reference),
  517. p^.location.reference.index)));
  518. ungetregister32(p^.location.reference.base);
  519. { the symbol offset is loaded, }
  520. { so release the symbol name and set symbol }
  521. { to nil }
  522. stringdispose(p^.location.reference.symbol);
  523. p^.location.reference.offset:=0;
  524. calc_emit_mul;
  525. p^.location.reference.base:=p^.location.reference.index;
  526. p^.location.reference.index:=ind;
  527. end;
  528. end;
  529. if p^.memseg then
  530. p^.location.reference.segment:=R_FS;
  531. end;
  532. end;
  533. {*****************************************************************************
  534. SecondSelfN
  535. *****************************************************************************}
  536. procedure secondselfn(var p : ptree);
  537. begin
  538. clear_reference(p^.location.reference);
  539. if (p^.resulttype^.deftype=classrefdef) or
  540. ((p^.resulttype^.deftype=objectdef)
  541. and pobjectdef(p^.resulttype)^.isclass
  542. ) then
  543. p^.location.register:=R_ESI
  544. else
  545. p^.location.reference.base:=R_ESI;
  546. end;
  547. {*****************************************************************************
  548. SecondWithN
  549. *****************************************************************************}
  550. procedure secondwith(var p : ptree);
  551. var
  552. ref : treference;
  553. symtable : psymtable;
  554. i : longint;
  555. begin
  556. if assigned(p^.left) then
  557. begin
  558. secondpass(p^.left);
  559. ref.symbol:=nil;
  560. gettempofsizereference(4,ref);
  561. exprasmlist^.concat(new(pai386,op_ref_reg(A_LEA,S_L,
  562. newreference(p^.left^.location.reference),R_EDI)));
  563. exprasmlist^.concat(new(pai386,op_reg_ref(A_MOV,S_L,
  564. R_EDI,newreference(ref))));
  565. del_reference(p^.left^.location.reference);
  566. { the offset relative to (%ebp) is only needed here! }
  567. symtable:=p^.withsymtable;
  568. for i:=1 to p^.tablecount do
  569. begin
  570. symtable^.datasize:=ref.offset;
  571. symtable:=symtable^.next;
  572. end;
  573. { p^.right can be optimize out !!! }
  574. if p^.right<>nil then
  575. secondpass(p^.right);
  576. { clear some stuff }
  577. ungetiftemp(ref);
  578. end;
  579. end;
  580. end.
  581. {
  582. $Log$
  583. Revision 1.9 1998-09-03 16:03:15 florian
  584. + rtti generation
  585. * init table generation changed
  586. Revision 1.8 1998/08/23 21:04:34 florian
  587. + rtti generation for classes added
  588. + new/dispose do now also a call to INITIALIZE/FINALIZE, if necessaray
  589. Revision 1.7 1998/08/20 11:27:40 michael
  590. * Applied Peters Fix
  591. Revision 1.6 1998/08/10 14:49:49 peter
  592. + localswitches, moduleswitches, globalswitches splitting
  593. Revision 1.5 1998/07/26 21:58:58 florian
  594. + better support for switch $H
  595. + index access to ansi strings added
  596. + assigment of data (records/arrays) containing ansi strings
  597. Revision 1.4 1998/07/24 22:16:55 florian
  598. * internal error 10 together with array access fixed. I hope
  599. that's the final fix.
  600. Revision 1.3 1998/06/25 08:48:09 florian
  601. * first version of rtti support
  602. Revision 1.2 1998/06/08 13:13:35 pierre
  603. + temporary variables now in temp_gen.pas unit
  604. because it is processor independent
  605. * mppc68k.bat modified to undefine i386 and support_mmx
  606. (which are defaults for i386)
  607. Revision 1.1 1998/06/05 17:44:13 peter
  608. * splitted cgi386
  609. }