nobj.pas 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. Routines for the code generation of data structures
  5. like VMT, Messages, VTables, Interfaces descs
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit nobj;
  20. {$i defines.inc}
  21. interface
  22. uses
  23. cutils,cclasses,
  24. symdef,aasm;
  25. type
  26. pprocdeftree = ^tprocdeftree;
  27. tprocdeftree = record
  28. data : tprocdef;
  29. nl : tasmlabel;
  30. l,r : pprocdeftree;
  31. end;
  32. pprocdefcoll = ^tprocdefcoll;
  33. tprocdefcoll = record
  34. data : tprocdef;
  35. next : pprocdefcoll;
  36. end;
  37. psymcoll = ^tsymcoll;
  38. tsymcoll = record
  39. name : pstring;
  40. data : pprocdefcoll;
  41. next : psymcoll;
  42. end;
  43. tclassheader=class
  44. private
  45. _Class : tobjectdef;
  46. count : integer;
  47. private
  48. { message tables }
  49. root : pprocdeftree;
  50. procedure disposeprocdeftree(p : pprocdeftree);
  51. procedure insertmsgint(p : tnamedindexitem);
  52. procedure insertmsgstr(p : tnamedindexitem);
  53. procedure insertint(p : pprocdeftree;var at : pprocdeftree);
  54. procedure insertstr(p : pprocdeftree;var at : pprocdeftree);
  55. procedure writenames(p : pprocdeftree);
  56. procedure writeintentry(p : pprocdeftree);
  57. procedure writestrentry(p : pprocdeftree);
  58. {$ifdef WITHDMT}
  59. private
  60. { dmt }
  61. procedure insertdmtentry(p : tnamedindexitem);
  62. procedure writedmtindexentry(p : pprocdeftree);
  63. procedure writedmtaddressentry(p : pprocdeftree);
  64. {$endif}
  65. private
  66. { published methods }
  67. procedure do_count(p : tnamedindexitem);
  68. procedure genpubmethodtableentry(p : tnamedindexitem);
  69. private
  70. { vmt }
  71. wurzel : psymcoll;
  72. nextvirtnumber : integer;
  73. has_constructor,
  74. has_virtual_method : boolean;
  75. procedure eachsym(sym : tnamedindexitem);
  76. procedure disposevmttree;
  77. private
  78. { interface tables }
  79. function gintfgetvtbllabelname(intfindex: integer): string;
  80. procedure gintfcreatevtbl(intfindex: integer; rawdata,rawcode: TAAsmoutput);
  81. procedure gintfgenentry(intfindex, contintfindex: integer; rawdata: TAAsmoutput);
  82. procedure gintfoptimizevtbls(implvtbl : plongint);
  83. procedure gintfwritedata;
  84. function gintfgetcprocdef(proc: tprocdef;const name: string): tprocdef;
  85. procedure gintfdoonintf(intf: tobjectdef; intfindex: longint);
  86. procedure gintfwalkdowninterface(intf: tobjectdef; intfindex: longint);
  87. protected
  88. procedure cgintfwrapper(asmlist: TAAsmoutput; procdef: tprocdef; const labelname: string; ioffset: longint);virtual;abstract;
  89. public
  90. constructor create(c:tobjectdef);
  91. { generates the message tables for a class }
  92. function genstrmsgtab : tasmlabel;
  93. function genintmsgtab : tasmlabel;
  94. function genpublishedmethodstable : tasmlabel;
  95. {$ifdef WITHDMT}
  96. { generates a DMT for _class }
  97. function gendmt : tasmlabel;
  98. {$endif WITHDMT}
  99. { generates a VMT for _class }
  100. procedure genvmt(list : TAAsmoutput);
  101. { interfaces }
  102. function genintftable: tasmlabel;
  103. procedure writevmt;
  104. procedure writeinterfaceids;
  105. end;
  106. tclassheaderclass=class of tclassheader;
  107. var
  108. cclassheader : tclassheaderclass;
  109. implementation
  110. uses
  111. {$ifdef delphi}
  112. sysutils,
  113. {$else}
  114. strings,
  115. {$endif}
  116. globtype,globals,verbose,
  117. symtable,symconst,symtype,symsym,types,
  118. fmodule,
  119. {$ifdef GDB}
  120. gdb,
  121. {$endif GDB}
  122. systems
  123. ;
  124. {*****************************************************************************
  125. TClassHeader
  126. *****************************************************************************}
  127. constructor tclassheader.create(c:tobjectdef);
  128. begin
  129. inherited Create;
  130. _Class:=c;
  131. end;
  132. {**************************************
  133. Message Tables
  134. **************************************}
  135. procedure tclassheader.disposeprocdeftree(p : pprocdeftree);
  136. begin
  137. if assigned(p^.l) then
  138. disposeprocdeftree(p^.l);
  139. if assigned(p^.r) then
  140. disposeprocdeftree(p^.r);
  141. dispose(p);
  142. end;
  143. procedure tclassheader.insertint(p : pprocdeftree;var at : pprocdeftree);
  144. begin
  145. if at=nil then
  146. begin
  147. at:=p;
  148. inc(count);
  149. end
  150. else
  151. begin
  152. if p^.data.messageinf.i<at^.data.messageinf.i then
  153. insertint(p,at^.l)
  154. else if p^.data.messageinf.i>at^.data.messageinf.i then
  155. insertint(p,at^.r)
  156. else
  157. Message1(parser_e_duplicate_message_label,tostr(p^.data.messageinf.i));
  158. end;
  159. end;
  160. procedure tclassheader.insertstr(p : pprocdeftree;var at : pprocdeftree);
  161. var
  162. i : integer;
  163. begin
  164. if at=nil then
  165. begin
  166. at:=p;
  167. inc(count);
  168. end
  169. else
  170. begin
  171. i:=strcomp(p^.data.messageinf.str,at^.data.messageinf.str);
  172. if i<0 then
  173. insertstr(p,at^.l)
  174. else if i>0 then
  175. insertstr(p,at^.r)
  176. else
  177. Message1(parser_e_duplicate_message_label,strpas(p^.data.messageinf.str));
  178. end;
  179. end;
  180. procedure tclassheader.insertmsgint(p : tnamedindexitem);
  181. var
  182. hp : tprocdef;
  183. pt : pprocdeftree;
  184. begin
  185. if tsym(p).typ=procsym then
  186. begin
  187. hp:=tprocsym(p).definition;
  188. while assigned(hp) do
  189. begin
  190. if (po_msgint in hp.procoptions) then
  191. begin
  192. new(pt);
  193. pt^.data:=hp;
  194. pt^.l:=nil;
  195. pt^.r:=nil;
  196. insertint(pt,root);
  197. end;
  198. hp:=hp.nextoverloaded;
  199. end;
  200. end;
  201. end;
  202. procedure tclassheader.insertmsgstr(p : tnamedindexitem);
  203. var
  204. hp : tprocdef;
  205. pt : pprocdeftree;
  206. begin
  207. if tsym(p).typ=procsym then
  208. begin
  209. hp:=tprocsym(p).definition;
  210. while assigned(hp) do
  211. begin
  212. if (po_msgstr in hp.procoptions) then
  213. begin
  214. new(pt);
  215. pt^.data:=hp;
  216. pt^.l:=nil;
  217. pt^.r:=nil;
  218. insertstr(pt,root);
  219. end;
  220. hp:=hp.nextoverloaded;
  221. end;
  222. end;
  223. end;
  224. procedure tclassheader.writenames(p : pprocdeftree);
  225. begin
  226. getdatalabel(p^.nl);
  227. if assigned(p^.l) then
  228. writenames(p^.l);
  229. dataSegment.concat(Tai_label.Create(p^.nl));
  230. dataSegment.concat(Tai_const.Create_8bit(strlen(p^.data.messageinf.str)));
  231. dataSegment.concat(Tai_string.Create_pchar(p^.data.messageinf.str));
  232. if assigned(p^.r) then
  233. writenames(p^.r);
  234. end;
  235. procedure tclassheader.writestrentry(p : pprocdeftree);
  236. begin
  237. if assigned(p^.l) then
  238. writestrentry(p^.l);
  239. { write name label }
  240. dataSegment.concat(Tai_const_symbol.Create(p^.nl));
  241. dataSegment.concat(Tai_const_symbol.Createname(p^.data.mangledname));
  242. if assigned(p^.r) then
  243. writestrentry(p^.r);
  244. end;
  245. function tclassheader.genstrmsgtab : tasmlabel;
  246. var
  247. r : tasmlabel;
  248. begin
  249. root:=nil;
  250. count:=0;
  251. { insert all message handlers into a tree, sorted by name }
  252. _class.symtable.foreach({$ifdef FPCPROCVAR}@{$endif}insertmsgstr);
  253. { write all names }
  254. if assigned(root) then
  255. writenames(root);
  256. { now start writing of the message string table }
  257. getdatalabel(r);
  258. dataSegment.concat(Tai_label.Create(r));
  259. genstrmsgtab:=r;
  260. dataSegment.concat(Tai_const.Create_32bit(count));
  261. if assigned(root) then
  262. begin
  263. writestrentry(root);
  264. disposeprocdeftree(root);
  265. end;
  266. end;
  267. procedure tclassheader.writeintentry(p : pprocdeftree);
  268. begin
  269. if assigned(p^.l) then
  270. writeintentry(p^.l);
  271. { write name label }
  272. dataSegment.concat(Tai_const.Create_32bit(p^.data.messageinf.i));
  273. dataSegment.concat(Tai_const_symbol.Createname(p^.data.mangledname));
  274. if assigned(p^.r) then
  275. writeintentry(p^.r);
  276. end;
  277. function tclassheader.genintmsgtab : tasmlabel;
  278. var
  279. r : tasmlabel;
  280. begin
  281. root:=nil;
  282. count:=0;
  283. { insert all message handlers into a tree, sorted by name }
  284. _class.symtable.foreach({$ifdef FPCPROCVAR}@{$endif}insertmsgint);
  285. { now start writing of the message string table }
  286. getdatalabel(r);
  287. dataSegment.concat(Tai_label.Create(r));
  288. genintmsgtab:=r;
  289. dataSegment.concat(Tai_const.Create_32bit(count));
  290. if assigned(root) then
  291. begin
  292. writeintentry(root);
  293. disposeprocdeftree(root);
  294. end;
  295. end;
  296. {$ifdef WITHDMT}
  297. {**************************************
  298. DMT
  299. **************************************}
  300. procedure tclassheader.insertdmtentry(p : tnamedindexitem);
  301. var
  302. hp : tprocdef;
  303. pt : pprocdeftree;
  304. begin
  305. if tsym(p).typ=procsym then
  306. begin
  307. hp:=tprocsym(p).definition;
  308. while assigned(hp) do
  309. begin
  310. if (po_msgint in hp.procoptions) then
  311. begin
  312. new(pt);
  313. pt^.p:=hp;
  314. pt^.l:=nil;
  315. pt^.r:=nil;
  316. insertint(pt,root);
  317. end;
  318. hp:=hp.nextoverloaded;
  319. end;
  320. end;
  321. end;
  322. procedure tclassheader.writedmtindexentry(p : pprocdeftree);
  323. begin
  324. if assigned(p^.l) then
  325. writedmtindexentry(p^.l);
  326. dataSegment.concat(Tai_const.Create_32bit(p^.data.messageinf.i));
  327. if assigned(p^.r) then
  328. writedmtindexentry(p^.r);
  329. end;
  330. procedure tclassheader.writedmtaddressentry(p : pprocdeftree);
  331. begin
  332. if assigned(p^.l) then
  333. writedmtaddressentry(p^.l);
  334. dataSegment.concat(Tai_const_symbol.Createname(p^.data.mangledname));
  335. if assigned(p^.r) then
  336. writedmtaddressentry(p^.r);
  337. end;
  338. function tclassheader.gendmt : tasmlabel;
  339. var
  340. r : tasmlabel;
  341. begin
  342. root:=nil;
  343. count:=0;
  344. gendmt:=nil;
  345. { insert all message handlers into a tree, sorted by number }
  346. _class.symtable.foreach({$ifdef FPCPROCVAR}@{$endif}insertdmtentry);
  347. if count>0 then
  348. begin
  349. getdatalabel(r);
  350. gendmt:=r;
  351. dataSegment.concat(Tai_label.Create(r));
  352. { entries for caching }
  353. dataSegment.concat(Tai_const.Create_32bit(0));
  354. dataSegment.concat(Tai_const.Create_32bit(0));
  355. dataSegment.concat(Tai_const.Create_32bit(count));
  356. if assigned(root) then
  357. begin
  358. writedmtindexentry(root);
  359. writedmtaddressentry(root);
  360. disposeprocdeftree(root);
  361. end;
  362. end;
  363. end;
  364. {$endif WITHDMT}
  365. {**************************************
  366. Published Methods
  367. **************************************}
  368. procedure tclassheader.do_count(p : tnamedindexitem);
  369. begin
  370. if (tsym(p).typ=procsym) and (sp_published in tsym(p).symoptions) then
  371. inc(count);
  372. end;
  373. procedure tclassheader.genpubmethodtableentry(p : tnamedindexitem);
  374. var
  375. hp : tprocdef;
  376. l : tasmlabel;
  377. begin
  378. if (tsym(p).typ=procsym) and (sp_published in tsym(p).symoptions) then
  379. begin
  380. hp:=tprocsym(p).definition;
  381. if assigned(hp.nextoverloaded) then
  382. internalerror(1209992);
  383. getdatalabel(l);
  384. Consts.concat(Tai_label.Create(l));
  385. Consts.concat(Tai_const.Create_8bit(length(p.name)));
  386. Consts.concat(Tai_string.Create(p.name));
  387. dataSegment.concat(Tai_const_symbol.Create(l));
  388. dataSegment.concat(Tai_const_symbol.Createname(hp.mangledname));
  389. end;
  390. end;
  391. function tclassheader.genpublishedmethodstable : tasmlabel;
  392. var
  393. l : tasmlabel;
  394. begin
  395. count:=0;
  396. _class.symtable.foreach({$ifdef FPCPROCVAR}@{$endif}do_count);
  397. if count>0 then
  398. begin
  399. getdatalabel(l);
  400. dataSegment.concat(Tai_label.Create(l));
  401. dataSegment.concat(Tai_const.Create_32bit(count));
  402. _class.symtable.foreach({$ifdef FPCPROCVAR}@{$endif}genpubmethodtableentry);
  403. genpublishedmethodstable:=l;
  404. end
  405. else
  406. genpublishedmethodstable:=nil;
  407. end;
  408. {**************************************
  409. VMT
  410. **************************************}
  411. procedure tclassheader.eachsym(sym : tnamedindexitem);
  412. var
  413. procdefcoll : pprocdefcoll;
  414. hp : tprocdef;
  415. symcoll : psymcoll;
  416. _name : string;
  417. stored : boolean;
  418. { creates a new entry in the procsym list }
  419. procedure newentry;
  420. begin
  421. { if not, generate a new symbol item }
  422. new(symcoll);
  423. symcoll^.name:=stringdup(sym.name);
  424. symcoll^.next:=wurzel;
  425. symcoll^.data:=nil;
  426. wurzel:=symcoll;
  427. hp:=tprocsym(sym).definition;
  428. { inserts all definitions }
  429. while assigned(hp) do
  430. begin
  431. new(procdefcoll);
  432. procdefcoll^.data:=hp;
  433. procdefcoll^.next:=symcoll^.data;
  434. symcoll^.data:=procdefcoll;
  435. { if it's a virtual method }
  436. if (po_virtualmethod in hp.procoptions) then
  437. begin
  438. { then it gets a number ... }
  439. hp.extnumber:=nextvirtnumber;
  440. { and we inc the number }
  441. inc(nextvirtnumber);
  442. has_virtual_method:=true;
  443. end;
  444. if (hp.proctypeoption=potype_constructor) then
  445. has_constructor:=true;
  446. { check, if a method should be overridden }
  447. if (po_overridingmethod in hp.procoptions) then
  448. MessagePos1(hp.fileinfo,parser_e_nothing_to_be_overridden,_class.objname^+'.'+_name+hp.demangled_paras);
  449. { next overloaded method }
  450. hp:=hp.nextoverloaded;
  451. end;
  452. end;
  453. procedure newdefentry;
  454. begin
  455. new(procdefcoll);
  456. procdefcoll^.data:=hp;
  457. procdefcoll^.next:=symcoll^.data;
  458. symcoll^.data:=procdefcoll;
  459. { if it's a virtual method }
  460. if (po_virtualmethod in hp.procoptions) then
  461. begin
  462. { then it gets a number ... }
  463. hp.extnumber:=nextvirtnumber;
  464. { and we inc the number }
  465. inc(nextvirtnumber);
  466. has_virtual_method:=true;
  467. end;
  468. if (hp.proctypeoption=potype_constructor) then
  469. has_constructor:=true;
  470. { check, if a method should be overridden }
  471. if (po_overridingmethod in hp.procoptions) then
  472. MessagePos1(hp.fileinfo,parser_e_nothing_to_be_overridden,_class.objname^+'.'+_name+hp.demangled_paras);
  473. end;
  474. label
  475. handlenextdef;
  476. begin
  477. { put only sub routines into the VMT }
  478. if tsym(sym).typ=procsym then
  479. begin
  480. _name:=sym.name;
  481. symcoll:=wurzel;
  482. while assigned(symcoll) do
  483. begin
  484. { does the symbol already exist in the list ? }
  485. if _name=symcoll^.name^ then
  486. begin
  487. { walk through all defs of the symbol }
  488. hp:=tprocsym(sym).definition;
  489. while assigned(hp) do
  490. begin
  491. { compare with all stored definitions }
  492. procdefcoll:=symcoll^.data;
  493. stored:=false;
  494. while assigned(procdefcoll) do
  495. begin
  496. { compare parameters }
  497. if equal_paras(procdefcoll^.data.para,hp.para,cp_all) and
  498. (
  499. (po_virtualmethod in procdefcoll^.data.procoptions) or
  500. (po_virtualmethod in hp.procoptions)
  501. ) then
  502. begin { same parameters }
  503. { wenn sie gleich sind }
  504. { und eine davon virtual deklariert ist }
  505. { Fehler falls nur eine VIRTUAL }
  506. if (po_virtualmethod in procdefcoll^.data.procoptions)<>
  507. (po_virtualmethod in hp.procoptions) then
  508. begin
  509. { in classes, we hide the old method }
  510. if is_class(_class) then
  511. begin
  512. { warn only if it is the first time,
  513. we hide the method }
  514. if _class=hp._class then
  515. Message1(parser_w_should_use_override,hp.fullprocname);
  516. end
  517. else
  518. if _class=hp._class then
  519. begin
  520. if (po_virtualmethod in procdefcoll^.data.procoptions) then
  521. Message1(parser_w_overloaded_are_not_both_virtual,
  522. hp.fullprocname)
  523. else
  524. Message1(parser_w_overloaded_are_not_both_non_virtual,
  525. hp.fullprocname);
  526. end;
  527. { was newentry; exit; (FK) }
  528. newdefentry;
  529. goto handlenextdef;
  530. end
  531. else
  532. { the flags have to match }
  533. { except abstract and override }
  534. { only if both are virtual !! }
  535. if (procdefcoll^.data.proccalloptions<>hp.proccalloptions) or
  536. (procdefcoll^.data.proctypeoption<>hp.proctypeoption) or
  537. ((procdefcoll^.data.procoptions-
  538. [po_abstractmethod,po_overridingmethod,po_assembler,po_overload])<>
  539. (hp.procoptions-[po_abstractmethod,po_overridingmethod,po_assembler,po_overload])) then
  540. Message1(parser_e_header_dont_match_forward,hp.fullprocname);
  541. { check, if the overridden directive is set }
  542. { (povirtualmethod is set! }
  543. { class ? }
  544. if is_class(_class) and
  545. not(po_overridingmethod in hp.procoptions) then
  546. begin
  547. { warn only if it is the first time,
  548. we hide the method }
  549. if _class=hp._class then
  550. Message1(parser_w_should_use_override,hp.fullprocname);
  551. { was newentry; (FK) }
  552. newdefentry;
  553. exit;
  554. end;
  555. { error, if the return types aren't equal }
  556. if not(is_equal(procdefcoll^.data.rettype.def,hp.rettype.def)) and
  557. not((procdefcoll^.data.rettype.def.deftype=objectdef) and
  558. (hp.rettype.def.deftype=objectdef) and
  559. is_class(procdefcoll^.data.rettype.def) and
  560. is_class(hp.rettype.def) and
  561. (tobjectdef(hp.rettype.def).is_related(
  562. tobjectdef(procdefcoll^.data.rettype.def)))) then
  563. Message2(parser_e_overridden_methods_not_same_ret,hp.fullprocnamewithret,
  564. procdefcoll^.data.fullprocnamewithret);
  565. { now set the number }
  566. hp.extnumber:=procdefcoll^.data.extnumber;
  567. { and exchange }
  568. procdefcoll^.data:=hp;
  569. stored:=true;
  570. goto handlenextdef;
  571. end; { same parameters }
  572. procdefcoll:=procdefcoll^.next;
  573. end;
  574. { if it isn't saved in the list }
  575. { we create a new entry }
  576. if not(stored) then
  577. begin
  578. new(procdefcoll);
  579. procdefcoll^.data:=hp;
  580. procdefcoll^.next:=symcoll^.data;
  581. symcoll^.data:=procdefcoll;
  582. { if the method is virtual ... }
  583. if (po_virtualmethod in hp.procoptions) then
  584. begin
  585. { ... it will get a number }
  586. hp.extnumber:=nextvirtnumber;
  587. inc(nextvirtnumber);
  588. end;
  589. { check, if a method should be overridden }
  590. if (po_overridingmethod in hp.procoptions) then
  591. MessagePos1(hp.fileinfo,parser_e_nothing_to_be_overridden,
  592. hp.fullprocname);
  593. end;
  594. handlenextdef:
  595. hp:=hp.nextoverloaded;
  596. end;
  597. exit;
  598. end;
  599. symcoll:=symcoll^.next;
  600. end;
  601. newentry;
  602. end;
  603. end;
  604. procedure tclassheader.disposevmttree;
  605. var
  606. symcoll : psymcoll;
  607. procdefcoll : pprocdefcoll;
  608. begin
  609. { disposes the above generated tree }
  610. symcoll:=wurzel;
  611. while assigned(symcoll) do
  612. begin
  613. wurzel:=symcoll^.next;
  614. stringdispose(symcoll^.name);
  615. procdefcoll:=symcoll^.data;
  616. while assigned(procdefcoll) do
  617. begin
  618. symcoll^.data:=procdefcoll^.next;
  619. dispose(procdefcoll);
  620. procdefcoll:=symcoll^.data;
  621. end;
  622. dispose(symcoll);
  623. symcoll:=wurzel;
  624. end;
  625. end;
  626. procedure tclassheader.genvmt(list : TAAsmoutput);
  627. procedure do_genvmt(p : tobjectdef);
  628. begin
  629. { start with the base class }
  630. if assigned(p.childof) then
  631. do_genvmt(p.childof);
  632. { walk through all public syms }
  633. p.symtable.foreach({$ifdef FPCPROCVAR}@{$endif}eachsym);
  634. end;
  635. var
  636. symcoll : psymcoll;
  637. procdefcoll : pprocdefcoll;
  638. i : longint;
  639. begin
  640. wurzel:=nil;
  641. nextvirtnumber:=0;
  642. has_constructor:=false;
  643. has_virtual_method:=false;
  644. { generates a tree of all used methods }
  645. do_genvmt(_class);
  646. if has_virtual_method and not(has_constructor) then
  647. Message1(parser_w_virtual_without_constructor,_class.objname^);
  648. { generates the VMT }
  649. { walk trough all numbers for virtual methods and search }
  650. { the method }
  651. for i:=0 to nextvirtnumber-1 do
  652. begin
  653. symcoll:=wurzel;
  654. { walk trough all symbols }
  655. while assigned(symcoll) do
  656. begin
  657. { walk trough all methods }
  658. procdefcoll:=symcoll^.data;
  659. while assigned(procdefcoll) do
  660. begin
  661. { writes the addresses to the VMT }
  662. { but only this which are declared as virtual }
  663. if procdefcoll^.data.extnumber=i then
  664. begin
  665. if (po_virtualmethod in procdefcoll^.data.procoptions) then
  666. begin
  667. { if a method is abstract, then is also the }
  668. { class abstract and it's not allow to }
  669. { generates an instance }
  670. if (po_abstractmethod in procdefcoll^.data.procoptions) then
  671. begin
  672. include(_class.objectoptions,oo_has_abstract);
  673. List.concat(Tai_const_symbol.Createname('FPC_ABSTRACTERROR'));
  674. end
  675. else
  676. begin
  677. List.concat(Tai_const_symbol.createname(procdefcoll^.data.mangledname));
  678. end;
  679. end;
  680. end;
  681. procdefcoll:=procdefcoll^.next;
  682. end;
  683. symcoll:=symcoll^.next;
  684. end;
  685. end;
  686. disposevmttree;
  687. end;
  688. {**************************************
  689. Interface tables
  690. **************************************}
  691. function tclassheader.gintfgetvtbllabelname(intfindex: integer): string;
  692. begin
  693. gintfgetvtbllabelname:='VTBL_'+current_module.modulename^+'$_'+upper(_class.objname^)+
  694. '_$$_'+upper(_class.implementedinterfaces.interfaces(intfindex).objname^);
  695. end;
  696. procedure tclassheader.gintfcreatevtbl(intfindex: integer; rawdata,rawcode: TAAsmoutput);
  697. var
  698. implintf: timplementedinterfaces;
  699. curintf: tobjectdef;
  700. proccount: integer;
  701. tmps: string;
  702. i: longint;
  703. begin
  704. implintf:=_class.implementedinterfaces;
  705. curintf:=implintf.interfaces(intfindex);
  706. if (cs_create_smart in aktmoduleswitches) then
  707. rawdata.concat(Tai_symbol.Createname_global(gintfgetvtbllabelname(intfindex),0))
  708. else
  709. rawdata.concat(Tai_symbol.Createname(gintfgetvtbllabelname(intfindex),0));
  710. proccount:=implintf.implproccount(intfindex);
  711. for i:=1 to proccount do
  712. begin
  713. tmps:=implintf.implprocs(intfindex,i).mangledname+'_$$_'+upper(curintf.objname^);
  714. { create wrapper code }
  715. cgintfwrapper(rawcode,implintf.implprocs(intfindex,i),tmps,implintf.ioffsets(intfindex)^);
  716. { create reference }
  717. rawdata.concat(Tai_const_symbol.Createname(tmps));
  718. end;
  719. end;
  720. procedure tclassheader.gintfgenentry(intfindex, contintfindex: integer; rawdata: TAAsmoutput);
  721. var
  722. implintf: timplementedinterfaces;
  723. curintf: tobjectdef;
  724. tmplabel: tasmlabel;
  725. i: longint;
  726. begin
  727. implintf:=_class.implementedinterfaces;
  728. curintf:=implintf.interfaces(intfindex);
  729. { GUID }
  730. if curintf.objecttype in [odt_interfacecom] then
  731. begin
  732. { label for GUID }
  733. getdatalabel(tmplabel);
  734. rawdata.concat(Tai_label.Create(tmplabel));
  735. rawdata.concat(Tai_const.Create_32bit(curintf.iidguid.D1));
  736. rawdata.concat(Tai_const.Create_16bit(curintf.iidguid.D2));
  737. rawdata.concat(Tai_const.Create_16bit(curintf.iidguid.D3));
  738. for i:=Low(curintf.iidguid.D4) to High(curintf.iidguid.D4) do
  739. rawdata.concat(Tai_const.Create_8bit(curintf.iidguid.D4[i]));
  740. dataSegment.concat(Tai_const_symbol.Create(tmplabel));
  741. end
  742. else
  743. begin
  744. { nil for Corba interfaces }
  745. dataSegment.concat(Tai_const.Create_32bit(0)); { nil }
  746. end;
  747. { VTable }
  748. dataSegment.concat(Tai_const_symbol.Createname(gintfgetvtbllabelname(contintfindex)));
  749. { IOffset field }
  750. dataSegment.concat(Tai_const.Create_32bit(implintf.ioffsets(contintfindex)^));
  751. { IIDStr }
  752. getdatalabel(tmplabel);
  753. rawdata.concat(Tai_label.Create(tmplabel));
  754. rawdata.concat(Tai_const.Create_8bit(length(curintf.iidstr^)));
  755. if curintf.objecttype=odt_interfacecom then
  756. rawdata.concat(Tai_string.Create(upper(curintf.iidstr^)))
  757. else
  758. rawdata.concat(Tai_string.Create(curintf.iidstr^));
  759. dataSegment.concat(Tai_const_symbol.Create(tmplabel));
  760. end;
  761. procedure tclassheader.gintfoptimizevtbls(implvtbl : plongint);
  762. type
  763. tcompintfentry = record
  764. weight: longint;
  765. compintf: longint;
  766. end;
  767. { Max 1000 interface in the class header interfaces it's enough imho }
  768. tcompintfs = packed array[1..1000] of tcompintfentry;
  769. pcompintfs = ^tcompintfs;
  770. tequals = packed array[1..1000] of longint;
  771. pequals = ^tequals;
  772. var
  773. max: longint;
  774. equals: pequals;
  775. compats: pcompintfs;
  776. i: longint;
  777. j: longint;
  778. w: longint;
  779. cij: boolean;
  780. cji: boolean;
  781. begin
  782. max:=_class.implementedinterfaces.count;
  783. if max>High(tequals) then
  784. Internalerror(200006135);
  785. getmem(compats,sizeof(tcompintfentry)*max);
  786. getmem(equals,sizeof(longint)*max);
  787. fillchar(compats^,sizeof(tcompintfentry)*max,0);
  788. fillchar(equals^,sizeof(longint)*max,0);
  789. { ismergepossible is a containing relation
  790. meaning of ismergepossible(a,b,w) =
  791. if implementorfunction map of a is contained implementorfunction map of b
  792. imp(a,b) and imp(b,c) => imp(a,c) ; imp(a,b) and imp(b,a) => a == b
  793. }
  794. { the order is very important for correct allocation }
  795. for i:=1 to max do
  796. begin
  797. for j:=i+1 to max do
  798. begin
  799. cij:=_class.implementedinterfaces.isimplmergepossible(i,j,w);
  800. cji:=_class.implementedinterfaces.isimplmergepossible(j,i,w);
  801. if cij and cji then { i equal j }
  802. begin
  803. { get minimum index of equal }
  804. if equals^[j]=0 then
  805. equals^[j]:=i;
  806. end
  807. else if cij then
  808. begin
  809. { get minimum index of maximum weight }
  810. if compats^[i].weight<w then
  811. begin
  812. compats^[i].weight:=w;
  813. compats^[i].compintf:=j;
  814. end;
  815. end
  816. else if cji then
  817. begin
  818. { get minimum index of maximum weight }
  819. if (compats^[j].weight<w) then
  820. begin
  821. compats^[j].weight:=w;
  822. compats^[j].compintf:=i;
  823. end;
  824. end;
  825. end;
  826. end;
  827. for i:=1 to max do
  828. begin
  829. if compats^[i].compintf<>0 then
  830. implvtbl[i]:=compats^[i].compintf
  831. else if equals^[i]<>0 then
  832. implvtbl[i]:=equals^[i]
  833. else
  834. implvtbl[i]:=i;
  835. end;
  836. freemem(compats,sizeof(tcompintfentry)*max);
  837. freemem(equals,sizeof(longint)*max);
  838. end;
  839. procedure tclassheader.gintfwritedata;
  840. var
  841. rawdata,rawcode: taasmoutput;
  842. impintfindexes: plongint;
  843. max: longint;
  844. i: longint;
  845. begin
  846. max:=_class.implementedinterfaces.count;
  847. getmem(impintfindexes,(max+1)*sizeof(longint));
  848. gintfoptimizevtbls(impintfindexes);
  849. rawdata:=TAAsmOutput.Create;
  850. rawcode:=TAAsmOutput.Create;
  851. dataSegment.concat(Tai_const.Create_16bit(max));
  852. { Two pass, one for allocation and vtbl creation }
  853. for i:=1 to max do
  854. begin
  855. if impintfindexes[i]=i then { if implement itself }
  856. begin
  857. { allocate a pointer in the object memory }
  858. with tstoredsymtable(_class.symtable) do
  859. begin
  860. if (dataalignment>=target_info.size_of_pointer) then
  861. datasize:=align(datasize,dataalignment)
  862. else
  863. datasize:=align(datasize,target_info.size_of_pointer);
  864. _class.implementedinterfaces.ioffsets(i)^:=datasize;
  865. datasize:=datasize+target_info.size_of_pointer;
  866. end;
  867. { write vtbl }
  868. gintfcreatevtbl(i,rawdata,rawcode);
  869. end;
  870. end;
  871. { second pass: for fill interfacetable and remained ioffsets }
  872. for i:=1 to max do
  873. begin
  874. if i<>impintfindexes[i] then { why execute x:=x ? }
  875. with _class.implementedinterfaces do
  876. ioffsets(i)^:=ioffsets(impintfindexes[i])^;
  877. gintfgenentry(i,impintfindexes[i],rawdata);
  878. end;
  879. dataSegment.concatlist(rawdata);
  880. rawdata.free;
  881. codeSegment.concatlist(rawcode);
  882. rawcode.free;
  883. freemem(impintfindexes,(max+1)*sizeof(longint));
  884. end;
  885. function tclassheader.gintfgetcprocdef(proc: tprocdef;const name: string): tprocdef;
  886. var
  887. sym: tprocsym;
  888. implprocdef: tprocdef;
  889. begin
  890. implprocdef:=nil;
  891. sym:=tprocsym(search_class_member(_class,name));
  892. if assigned(sym) and (sym.typ=procsym) then
  893. begin
  894. implprocdef:=sym.definition;
  895. while assigned(implprocdef) and not equal_paras(proc.para,implprocdef.para,cp_none) and
  896. (proc.proccalloptions<>implprocdef.proccalloptions) do
  897. implprocdef:=implprocdef.nextoverloaded;
  898. end;
  899. gintfgetcprocdef:=implprocdef;
  900. end;
  901. procedure tclassheader.gintfdoonintf(intf: tobjectdef; intfindex: longint);
  902. var
  903. i: longint;
  904. proc: tprocdef;
  905. procname: string; { for error }
  906. mappedname: string;
  907. nextexist: pointer;
  908. implprocdef: tprocdef;
  909. begin
  910. for i:=1 to intf.symtable.defindex.count do
  911. begin
  912. proc:=tprocdef(intf.symtable.defindex.search(i));
  913. if proc.deftype=procdef then
  914. begin
  915. procname:='';
  916. implprocdef:=nil;
  917. nextexist:=nil;
  918. repeat
  919. mappedname:=_class.implementedinterfaces.getmappings(intfindex,proc.procsym.name,nextexist);
  920. if procname='' then
  921. procname:=proc.procsym.name;
  922. //mappedname; { for error messages }
  923. if mappedname<>'' then
  924. implprocdef:=gintfgetcprocdef(proc,mappedname);
  925. until assigned(implprocdef) or not assigned(nextexist);
  926. if not assigned(implprocdef) then
  927. implprocdef:=gintfgetcprocdef(proc,proc.procsym.name);
  928. if procname='' then
  929. procname:=proc.procsym.name;
  930. if assigned(implprocdef) then
  931. _class.implementedinterfaces.addimplproc(intfindex,implprocdef)
  932. else
  933. Message1(sym_e_id_not_found,procname);
  934. end;
  935. end;
  936. end;
  937. procedure tclassheader.gintfwalkdowninterface(intf: tobjectdef; intfindex: longint);
  938. begin
  939. if assigned(intf.childof) then
  940. gintfwalkdowninterface(intf.childof,intfindex);
  941. gintfdoonintf(intf,intfindex);
  942. end;
  943. function tclassheader.genintftable: tasmlabel;
  944. var
  945. intfindex: longint;
  946. curintf: tobjectdef;
  947. intftable: tasmlabel;
  948. begin
  949. { 1. step collect implementor functions into the implementedinterfaces.implprocs }
  950. for intfindex:=1 to _class.implementedinterfaces.count do
  951. begin
  952. curintf:=_class.implementedinterfaces.interfaces(intfindex);
  953. gintfwalkdowninterface(curintf,intfindex);
  954. end;
  955. { 2. step calc required fieldcount and their offsets in the object memory map
  956. and write data }
  957. getdatalabel(intftable);
  958. dataSegment.concat(Tai_label.Create(intftable));
  959. gintfwritedata;
  960. _class.implementedinterfaces.clearimplprocs; { release temporary information }
  961. genintftable:=intftable;
  962. end;
  963. { Write interface identifiers to the data section }
  964. procedure tclassheader.writeinterfaceids;
  965. var
  966. i: longint;
  967. s1,s2 : string;
  968. begin
  969. if _class.owner.name=nil then
  970. s1:=''
  971. else
  972. s1:=upper(_class.owner.name^);
  973. if _class.objname=nil then
  974. s2:=''
  975. else
  976. s2:=upper(_class.objname^);
  977. s1:=s1+'$_'+s2;
  978. if _class.isiidguidvalid then
  979. begin
  980. if (cs_create_smart in aktmoduleswitches) then
  981. dataSegment.concat(Tai_cut.Create);
  982. dataSegment.concat(Tai_symbol.Createname_global('IID$_'+s1,0));
  983. dataSegment.concat(Tai_const.Create_32bit(longint(_class.iidguid.D1)));
  984. dataSegment.concat(Tai_const.Create_16bit(_class.iidguid.D2));
  985. dataSegment.concat(Tai_const.Create_16bit(_class.iidguid.D3));
  986. for i:=Low(_class.iidguid.D4) to High(_class.iidguid.D4) do
  987. dataSegment.concat(Tai_const.Create_8bit(_class.iidguid.D4[i]));
  988. end;
  989. if (cs_create_smart in aktmoduleswitches) then
  990. dataSegment.concat(Tai_cut.Create);
  991. dataSegment.concat(Tai_symbol.Createname_global('IIDSTR$_'+s1,0));
  992. dataSegment.concat(Tai_const.Create_8bit(length(_class.iidstr^)));
  993. dataSegment.concat(Tai_string.Create(_class.iidstr^));
  994. end;
  995. { generates the vmt for classes as well as for objects }
  996. procedure tclassheader.writevmt;
  997. var
  998. vmtlist : taasmoutput;
  999. methodnametable,intmessagetable,
  1000. strmessagetable,classnamelabel,
  1001. fieldtablelabel : tasmlabel;
  1002. {$ifdef WITHDMT}
  1003. dmtlabel : tasmlabel;
  1004. {$endif WITHDMT}
  1005. interfacetable : tasmlabel;
  1006. begin
  1007. {$ifdef WITHDMT}
  1008. dmtlabel:=gendmt;
  1009. {$endif WITHDMT}
  1010. { this generates the entries }
  1011. vmtlist:=TAasmoutput.Create;
  1012. genvmt(vmtlist);
  1013. if (cs_create_smart in aktmoduleswitches) then
  1014. dataSegment.concat(Tai_cut.Create);
  1015. { write tables for classes, this must be done before the actual
  1016. class is written, because we need the labels defined }
  1017. if is_class(_class) then
  1018. begin
  1019. { interface table }
  1020. if _class.implementedinterfaces.count>0 then
  1021. begin
  1022. if (cs_create_smart in aktmoduleswitches) then
  1023. codeSegment.concat(Tai_cut.Create);
  1024. interfacetable:=genintftable;
  1025. end;
  1026. methodnametable:=genpublishedmethodstable;
  1027. fieldtablelabel:=_class.generate_field_table;
  1028. { write class name }
  1029. getdatalabel(classnamelabel);
  1030. dataSegment.concat(Tai_label.Create(classnamelabel));
  1031. dataSegment.concat(Tai_const.Create_8bit(length(_class.objname^)));
  1032. dataSegment.concat(Tai_string.Create(_class.objname^));
  1033. { generate message and dynamic tables }
  1034. if (oo_has_msgstr in _class.objectoptions) then
  1035. strmessagetable:=genstrmsgtab;
  1036. if (oo_has_msgint in _class.objectoptions) then
  1037. intmessagetable:=genintmsgtab
  1038. else
  1039. dataSegment.concat(Tai_const.Create_32bit(0));
  1040. end;
  1041. { write debug info }
  1042. {$ifdef GDB}
  1043. if (cs_debuginfo in aktmoduleswitches) then
  1044. begin
  1045. do_count_dbx:=true;
  1046. if assigned(_class.owner) and assigned(_class.owner.name) then
  1047. dataSegment.concat(Tai_stabs.Create(strpnew('"vmt_'+_class.owner.name^+_class.name+':S'+
  1048. typeglobalnumber('__vtbl_ptr_type')+'",'+tostr(N_STSYM)+',0,0,'+_class.vmt_mangledname)));
  1049. end;
  1050. {$endif GDB}
  1051. dataSegment.concat(Tai_symbol.Createdataname_global(_class.vmt_mangledname,0));
  1052. { determine the size with symtable.datasize, because }
  1053. { size gives back 4 for classes }
  1054. dataSegment.concat(Tai_const.Create_32bit(_class.symtable.datasize));
  1055. dataSegment.concat(Tai_const.Create_32bit(-_class.symtable.datasize));
  1056. {$ifdef WITHDMT}
  1057. if _class.classtype=ct_object then
  1058. begin
  1059. if assigned(dmtlabel) then
  1060. dataSegment.concat(Tai_const_symbol.Create(dmtlabel)))
  1061. else
  1062. dataSegment.concat(Tai_const.Create_32bit(0));
  1063. end;
  1064. {$endif WITHDMT}
  1065. { write pointer to parent VMT, this isn't implemented in TP }
  1066. { but this is not used in FPC ? (PM) }
  1067. { it's not used yet, but the delphi-operators as and is need it (FK) }
  1068. { it is not written for parents that don't have any vmt !! }
  1069. if assigned(_class.childof) and
  1070. (oo_has_vmt in _class.childof.objectoptions) then
  1071. dataSegment.concat(Tai_const_symbol.Createname(_class.childof.vmt_mangledname))
  1072. else
  1073. dataSegment.concat(Tai_const.Create_32bit(0));
  1074. { write extended info for classes, for the order see rtl/inc/objpash.inc }
  1075. if is_class(_class) then
  1076. begin
  1077. { pointer to class name string }
  1078. dataSegment.concat(Tai_const_symbol.Create(classnamelabel));
  1079. { pointer to dynamic table }
  1080. if (oo_has_msgint in _class.objectoptions) then
  1081. dataSegment.concat(Tai_const_symbol.Create(intmessagetable))
  1082. else
  1083. dataSegment.concat(Tai_const.Create_32bit(0));
  1084. { pointer to method table }
  1085. if assigned(methodnametable) then
  1086. dataSegment.concat(Tai_const_symbol.Create(methodnametable))
  1087. else
  1088. dataSegment.concat(Tai_const.Create_32bit(0));
  1089. { pointer to field table }
  1090. dataSegment.concat(Tai_const_symbol.Create(fieldtablelabel));
  1091. { pointer to type info of published section }
  1092. if (oo_can_have_published in _class.objectoptions) then
  1093. dataSegment.concat(Tai_const_symbol.Create(_class.get_rtti_label(fullrtti)))
  1094. else
  1095. dataSegment.concat(Tai_const.Create_32bit(0));
  1096. { inittable for con-/destruction, for classes this is always generated }
  1097. dataSegment.concat(Tai_const_symbol.Create(_class.get_rtti_label(initrtti)));
  1098. { auto table }
  1099. dataSegment.concat(Tai_const.Create_32bit(0));
  1100. { interface table }
  1101. if _class.implementedinterfaces.count>0 then
  1102. dataSegment.concat(Tai_const_symbol.Create(interfacetable))
  1103. else
  1104. dataSegment.concat(Tai_const.Create_32bit(0));
  1105. { table for string messages }
  1106. if (oo_has_msgstr in _class.objectoptions) then
  1107. dataSegment.concat(Tai_const_symbol.Create(strmessagetable))
  1108. else
  1109. dataSegment.concat(Tai_const.Create_32bit(0));
  1110. end;
  1111. dataSegment.concatlist(vmtlist);
  1112. vmtlist.free;
  1113. { write the size of the VMT }
  1114. dataSegment.concat(Tai_symbol_end.Createname(_class.vmt_mangledname));
  1115. end;
  1116. initialization
  1117. cclassheader:=tclassheader;
  1118. end.
  1119. {
  1120. $Log$
  1121. Revision 1.4 2001-09-19 11:04:42 michael
  1122. * Smartlinking with interfaces fixed
  1123. * Better smartlinking for rtti and init tables
  1124. Revision 1.3 2001/08/30 20:13:53 peter
  1125. * rtti/init table updates
  1126. * rttisym for reusable global rtti/init info
  1127. * support published for interfaces
  1128. Revision 1.2 2001/08/22 21:16:20 florian
  1129. * some interfaces related problems regarding
  1130. mapping of interface implementions fixed
  1131. Revision 1.1 2001/04/21 13:37:16 peter
  1132. * made tclassheader using class of to implement cpu dependent code
  1133. Revision 1.20 2001/04/18 22:01:54 peter
  1134. * registration of targets and assemblers
  1135. Revision 1.19 2001/04/13 01:22:07 peter
  1136. * symtable change to classes
  1137. * range check generation and errors fixed, make cycle DEBUG=1 works
  1138. * memory leaks fixed
  1139. Revision 1.18 2001/04/04 21:30:43 florian
  1140. * applied several fixes to get the DD8 Delphi Unit compiled
  1141. e.g. "forward"-interfaces are working now
  1142. Revision 1.17 2000/12/25 00:07:26 peter
  1143. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  1144. tlinkedlist objects)
  1145. Revision 1.16 2000/11/29 00:30:30 florian
  1146. * unused units removed from uses clause
  1147. * some changes for widestrings
  1148. Revision 1.15 2000/11/19 16:23:35 florian
  1149. *** empty log message ***
  1150. Revision 1.14 2000/11/12 23:24:10 florian
  1151. * interfaces are basically running
  1152. Revision 1.13 2000/11/08 00:07:40 florian
  1153. * potential range check error fixed
  1154. Revision 1.12 2000/11/06 23:13:53 peter
  1155. * uppercase manglednames
  1156. Revision 1.11 2000/11/04 17:31:00 florian
  1157. * fixed some problems of previous commit
  1158. Revision 1.10 2000/11/04 14:25:19 florian
  1159. + merged Attila's changes for interfaces, not tested yet
  1160. Revision 1.9 2000/11/01 23:04:37 peter
  1161. * tprocdef.fullprocname added for better casesensitve writing of
  1162. procedures
  1163. Revision 1.8 2000/10/31 22:02:47 peter
  1164. * symtable splitted, no real code changes
  1165. Revision 1.7 2000/10/14 10:14:47 peter
  1166. * moehrendorf oct 2000 rewrite
  1167. Revision 1.6 2000/09/24 21:19:50 peter
  1168. * delphi compile fixes
  1169. Revision 1.5 2000/09/24 15:06:17 peter
  1170. * use defines.inc
  1171. Revision 1.4 2000/08/27 16:11:51 peter
  1172. * moved some util functions from globals,cobjects to cutils
  1173. * splitted files into finput,fmodule
  1174. Revision 1.3 2000/07/13 12:08:26 michael
  1175. + patched to 1.1.0 with former 1.09patch from peter
  1176. Revision 1.2 2000/07/13 11:32:41 michael
  1177. + removed logs
  1178. }