nobj.pas 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 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 fpcdefs.inc}
  21. interface
  22. uses
  23. cutils,cclasses,
  24. globtype,
  25. symdef,symsym,
  26. aasmbase,aasmtai
  27. ;
  28. type
  29. pprocdeftree = ^tprocdeftree;
  30. tprocdeftree = record
  31. data : tprocdef;
  32. nl : tasmlabel;
  33. l,r : pprocdeftree;
  34. end;
  35. pprocdefcoll = ^tprocdefcoll;
  36. tprocdefcoll = record
  37. data : tprocdef;
  38. hidden : boolean;
  39. visible : boolean;
  40. next : pprocdefcoll;
  41. end;
  42. pvmtentry = ^tvmtentry;
  43. tvmtentry = record
  44. speedvalue : cardinal;
  45. name : pstring;
  46. firstprocdef : pprocdefcoll;
  47. next : pvmtentry;
  48. end;
  49. tclassheader=class
  50. private
  51. _Class : tobjectdef;
  52. private
  53. { message tables }
  54. root : pprocdeftree;
  55. procedure disposeprocdeftree(p : pprocdeftree);
  56. procedure insertmsgint(p : tnamedindexitem;arg:pointer);
  57. procedure insertmsgstr(p : tnamedindexitem;arg:pointer);
  58. procedure insertint(p : pprocdeftree;var at : pprocdeftree;var count:longint);
  59. procedure insertstr(p : pprocdeftree;var at : pprocdeftree;var count:longint);
  60. procedure writenames(p : pprocdeftree);
  61. procedure writeintentry(p : pprocdeftree);
  62. procedure writestrentry(p : pprocdeftree);
  63. {$ifdef WITHDMT}
  64. private
  65. { dmt }
  66. procedure insertdmtentry(p : tnamedindexitem;arg:pointer);
  67. procedure writedmtindexentry(p : pprocdeftree);
  68. procedure writedmtaddressentry(p : pprocdeftree);
  69. {$endif}
  70. private
  71. { published methods }
  72. procedure do_count_published_methods(p : tnamedindexitem;arg:pointer);
  73. procedure do_gen_published_methods(p : tnamedindexitem;arg:pointer);
  74. private
  75. { vmt }
  76. firstvmtentry : pvmtentry;
  77. nextvirtnumber : integer;
  78. has_constructor,
  79. has_virtual_method : boolean;
  80. procedure newdefentry(vmtentry:pvmtentry;pd:tprocdef;is_visible:boolean);
  81. function newvmtentry(sym:tprocsym):pvmtentry;
  82. procedure eachsym(sym : tnamedindexitem;arg:pointer);
  83. procedure disposevmttree;
  84. procedure writevirtualmethods(List:TAAsmoutput);
  85. private
  86. { interface tables }
  87. function gintfgetvtbllabelname(intfindex: integer): string;
  88. procedure gintfcreatevtbl(intfindex: integer; rawdata: TAAsmoutput);
  89. procedure gintfgenentry(intfindex, contintfindex: integer; rawdata: TAAsmoutput);
  90. procedure gintfoptimizevtbls;
  91. procedure gintfwritedata;
  92. function gintfgetcprocdef(proc: tprocdef;const name: string): tprocdef;
  93. procedure gintfdoonintf(intf: tobjectdef; intfindex: longint);
  94. procedure gintfwalkdowninterface(intf: tobjectdef; intfindex: longint);
  95. public
  96. constructor create(c:tobjectdef);
  97. destructor destroy;override;
  98. { generates the message tables for a class }
  99. function genstrmsgtab : tasmlabel;
  100. function genintmsgtab : tasmlabel;
  101. function genpublishedmethodstable : tasmlabel;
  102. { generates a VMT entries }
  103. procedure genvmt;
  104. {$ifdef WITHDMT}
  105. { generates a DMT for _class }
  106. function gendmt : tasmlabel;
  107. {$endif WITHDMT}
  108. { interfaces }
  109. function genintftable: tasmlabel;
  110. { write the VMT to datasegment }
  111. procedure writevmt;
  112. procedure writeinterfaceids;
  113. end;
  114. implementation
  115. uses
  116. strings,
  117. globals,verbose,systems,
  118. symtable,symconst,symtype,defcmp
  119. {$ifdef GDB}
  120. ,gdb
  121. {$endif GDB}
  122. ;
  123. {*****************************************************************************
  124. TClassHeader
  125. *****************************************************************************}
  126. constructor tclassheader.create(c:tobjectdef);
  127. begin
  128. inherited Create;
  129. _Class:=c;
  130. end;
  131. destructor tclassheader.destroy;
  132. begin
  133. disposevmttree;
  134. end;
  135. {**************************************
  136. Message Tables
  137. **************************************}
  138. procedure tclassheader.disposeprocdeftree(p : pprocdeftree);
  139. begin
  140. if assigned(p^.l) then
  141. disposeprocdeftree(p^.l);
  142. if assigned(p^.r) then
  143. disposeprocdeftree(p^.r);
  144. dispose(p);
  145. end;
  146. procedure tclassheader.insertint(p : pprocdeftree;var at : pprocdeftree;var count:longint);
  147. begin
  148. if at=nil then
  149. begin
  150. at:=p;
  151. inc(count);
  152. end
  153. else
  154. begin
  155. if p^.data.messageinf.i<at^.data.messageinf.i then
  156. insertint(p,at^.l,count)
  157. else if p^.data.messageinf.i>at^.data.messageinf.i then
  158. insertint(p,at^.r,count)
  159. else
  160. Message1(parser_e_duplicate_message_label,tostr(p^.data.messageinf.i));
  161. end;
  162. end;
  163. procedure tclassheader.insertstr(p : pprocdeftree;var at : pprocdeftree;var count:longint);
  164. var
  165. i : integer;
  166. begin
  167. if at=nil then
  168. begin
  169. at:=p;
  170. inc(count);
  171. end
  172. else
  173. begin
  174. i:=strcomp(p^.data.messageinf.str,at^.data.messageinf.str);
  175. if i<0 then
  176. insertstr(p,at^.l,count)
  177. else if i>0 then
  178. insertstr(p,at^.r,count)
  179. else
  180. Message1(parser_e_duplicate_message_label,strpas(p^.data.messageinf.str));
  181. end;
  182. end;
  183. procedure tclassheader.insertmsgint(p : tnamedindexitem;arg:pointer);
  184. var
  185. i : cardinal;
  186. def: Tprocdef;
  187. pt : pprocdeftree;
  188. begin
  189. if tsym(p).typ=procsym then
  190. for i:=1 to Tprocsym(p).procdef_count do
  191. begin
  192. def:=Tprocsym(p).procdef[i];
  193. if po_msgint in def.procoptions then
  194. begin
  195. new(pt);
  196. pt^.data:=def;
  197. pt^.l:=nil;
  198. pt^.r:=nil;
  199. insertint(pt,root,plongint(arg)^);
  200. end;
  201. end;
  202. end;
  203. procedure tclassheader.insertmsgstr(p : tnamedindexitem;arg:pointer);
  204. var
  205. i : cardinal;
  206. def: Tprocdef;
  207. pt : pprocdeftree;
  208. begin
  209. if tsym(p).typ=procsym then
  210. for i:=1 to Tprocsym(p).procdef_count do
  211. begin
  212. def:=Tprocsym(p).procdef[i];
  213. if po_msgstr in def.procoptions then
  214. begin
  215. new(pt);
  216. pt^.data:=def;
  217. pt^.l:=nil;
  218. pt^.r:=nil;
  219. insertstr(pt,root,plongint(arg)^);
  220. end;
  221. end;
  222. end;
  223. procedure tclassheader.writenames(p : pprocdeftree);
  224. var
  225. ca : pchar;
  226. len : longint;
  227. begin
  228. objectlibrary.getdatalabel(p^.nl);
  229. if assigned(p^.l) then
  230. writenames(p^.l);
  231. datasegment.concat(cai_align.create(const_align(sizeof(aint))));
  232. dataSegment.concat(Tai_label.Create(p^.nl));
  233. len:=strlen(p^.data.messageinf.str);
  234. datasegment.concat(tai_const.create_8bit(len));
  235. getmem(ca,len+1);
  236. move(p^.data.messageinf.str^,ca^,len+1);
  237. dataSegment.concat(Tai_string.Create_pchar(ca));
  238. if assigned(p^.r) then
  239. writenames(p^.r);
  240. end;
  241. procedure tclassheader.writestrentry(p : pprocdeftree);
  242. begin
  243. if assigned(p^.l) then
  244. writestrentry(p^.l);
  245. { write name label }
  246. dataSegment.concat(Tai_const.Create_sym(p^.nl));
  247. dataSegment.concat(Tai_const.Createname(p^.data.mangledname,AT_FUNCTION,0));
  248. if assigned(p^.r) then
  249. writestrentry(p^.r);
  250. end;
  251. function tclassheader.genstrmsgtab : tasmlabel;
  252. var
  253. r : tasmlabel;
  254. count : longint;
  255. begin
  256. root:=nil;
  257. count:=0;
  258. { insert all message handlers into a tree, sorted by name }
  259. _class.symtable.foreach(@insertmsgstr,@count);
  260. { write all names }
  261. if assigned(root) then
  262. writenames(root);
  263. { now start writing of the message string table }
  264. objectlibrary.getdatalabel(r);
  265. datasegment.concat(cai_align.create(const_align(sizeof(aint))));
  266. dataSegment.concat(Tai_label.Create(r));
  267. genstrmsgtab:=r;
  268. dataSegment.concat(Tai_const.Create_32bit(count));
  269. if assigned(root) then
  270. begin
  271. writestrentry(root);
  272. disposeprocdeftree(root);
  273. end;
  274. end;
  275. procedure tclassheader.writeintentry(p : pprocdeftree);
  276. begin
  277. if assigned(p^.l) then
  278. writeintentry(p^.l);
  279. { write name label }
  280. dataSegment.concat(Tai_const.Create_32bit(p^.data.messageinf.i));
  281. dataSegment.concat(Tai_const.Createname(p^.data.mangledname,AT_FUNCTION,0));
  282. if assigned(p^.r) then
  283. writeintentry(p^.r);
  284. end;
  285. function tclassheader.genintmsgtab : tasmlabel;
  286. var
  287. r : tasmlabel;
  288. count : longint;
  289. begin
  290. root:=nil;
  291. count:=0;
  292. { insert all message handlers into a tree, sorted by name }
  293. _class.symtable.foreach(@insertmsgint,@count);
  294. { now start writing of the message string table }
  295. objectlibrary.getdatalabel(r);
  296. datasegment.concat(cai_align.create(const_align(sizeof(aint))));
  297. dataSegment.concat(Tai_label.Create(r));
  298. genintmsgtab:=r;
  299. dataSegment.concat(Tai_const.Create_32bit(count));
  300. if assigned(root) then
  301. begin
  302. writeintentry(root);
  303. disposeprocdeftree(root);
  304. end;
  305. end;
  306. {$ifdef WITHDMT}
  307. {**************************************
  308. DMT
  309. **************************************}
  310. procedure tclassheader.insertdmtentry(p : tnamedindexitem;arg:pointer);
  311. var
  312. hp : tprocdef;
  313. pt : pprocdeftree;
  314. begin
  315. if tsym(p).typ=procsym then
  316. begin
  317. hp:=tprocsym(p).definition;
  318. while assigned(hp) do
  319. begin
  320. if (po_msgint in hp.procoptions) then
  321. begin
  322. new(pt);
  323. pt^.p:=hp;
  324. pt^.l:=nil;
  325. pt^.r:=nil;
  326. insertint(pt,root);
  327. end;
  328. hp:=hp.nextoverloaded;
  329. end;
  330. end;
  331. end;
  332. procedure tclassheader.writedmtindexentry(p : pprocdeftree);
  333. begin
  334. if assigned(p^.l) then
  335. writedmtindexentry(p^.l);
  336. dataSegment.concat(Tai_const.Create_32bit(p^.data.messageinf.i));
  337. if assigned(p^.r) then
  338. writedmtindexentry(p^.r);
  339. end;
  340. procedure tclassheader.writedmtaddressentry(p : pprocdeftree);
  341. begin
  342. if assigned(p^.l) then
  343. writedmtaddressentry(p^.l);
  344. dataSegment.concat(Tai_const_symbol.Createname(p^.data.mangledname,AT_FUNCTION,0));
  345. if assigned(p^.r) then
  346. writedmtaddressentry(p^.r);
  347. end;
  348. function tclassheader.gendmt : tasmlabel;
  349. var
  350. r : tasmlabel;
  351. begin
  352. root:=nil;
  353. count:=0;
  354. gendmt:=nil;
  355. { insert all message handlers into a tree, sorted by number }
  356. _class.symtable.foreach(insertdmtentry);
  357. if count>0 then
  358. begin
  359. objectlibrary.getdatalabel(r);
  360. gendmt:=r;
  361. datasegment.concat(cai_align.create(const_align(sizeof(aint))));
  362. dataSegment.concat(Tai_label.Create(r));
  363. { entries for caching }
  364. dataSegment.concat(Tai_const.Create_ptr(0));
  365. dataSegment.concat(Tai_const.Create_ptr(0));
  366. dataSegment.concat(Tai_const.Create_32bit(count));
  367. if assigned(root) then
  368. begin
  369. writedmtindexentry(root);
  370. writedmtaddressentry(root);
  371. disposeprocdeftree(root);
  372. end;
  373. end;
  374. end;
  375. {$endif WITHDMT}
  376. {**************************************
  377. Published Methods
  378. **************************************}
  379. procedure tclassheader.do_count_published_methods(p : tnamedindexitem;arg:pointer);
  380. var
  381. i : longint;
  382. pd : tprocdef;
  383. begin
  384. if (tsym(p).typ=procsym) then
  385. begin
  386. for i:=1 to tprocsym(p).procdef_count do
  387. begin
  388. pd:=tprocsym(p).procdef[i];
  389. if (pd.procsym=tsym(p)) and
  390. (sp_published in pd.symoptions) then
  391. inc(plongint(arg)^);
  392. end;
  393. end;
  394. end;
  395. procedure tclassheader.do_gen_published_methods(p : tnamedindexitem;arg:pointer);
  396. var
  397. i : longint;
  398. l : tasmlabel;
  399. pd : tprocdef;
  400. begin
  401. if (tsym(p).typ=procsym) then
  402. begin
  403. for i:=1 to tprocsym(p).procdef_count do
  404. begin
  405. pd:=tprocsym(p).procdef[i];
  406. if (pd.procsym=tsym(p)) and
  407. (sp_published in pd.symoptions) then
  408. begin
  409. objectlibrary.getdatalabel(l);
  410. consts.concat(cai_align.create(const_align(sizeof(aint))));
  411. Consts.concat(Tai_label.Create(l));
  412. Consts.concat(Tai_const.Create_8bit(length(tsym(p).realname)));
  413. Consts.concat(Tai_string.Create(tsym(p).realname));
  414. dataSegment.concat(Tai_const.Create_sym(l));
  415. if po_abstractmethod in pd.procoptions then
  416. dataSegment.concat(Tai_const.Create_sym(nil))
  417. else
  418. dataSegment.concat(Tai_const.Createname(pd.mangledname,AT_FUNCTION,0));
  419. end;
  420. end;
  421. end;
  422. end;
  423. function tclassheader.genpublishedmethodstable : tasmlabel;
  424. var
  425. l : tasmlabel;
  426. count : longint;
  427. begin
  428. count:=0;
  429. _class.symtable.foreach(@do_count_published_methods,@count);
  430. if count>0 then
  431. begin
  432. objectlibrary.getdatalabel(l);
  433. datasegment.concat(cai_align.create(const_align(sizeof(aint))));
  434. dataSegment.concat(Tai_label.Create(l));
  435. dataSegment.concat(Tai_const.Create_32bit(count));
  436. _class.symtable.foreach(@do_gen_published_methods,nil);
  437. genpublishedmethodstable:=l;
  438. end
  439. else
  440. genpublishedmethodstable:=nil;
  441. end;
  442. {**************************************
  443. VMT
  444. **************************************}
  445. procedure tclassheader.newdefentry(vmtentry:pvmtentry;pd:tprocdef;is_visible:boolean);
  446. var
  447. procdefcoll : pprocdefcoll;
  448. begin
  449. if (_class=pd._class) then
  450. begin
  451. { new entry is needed, override was not possible }
  452. if (po_overridingmethod in pd.procoptions) then
  453. MessagePos1(pd.fileinfo,parser_e_nothing_to_be_overridden,pd.fullprocname(false));
  454. { check that all methods have overload directive }
  455. if not(m_fpc in aktmodeswitches) then
  456. begin
  457. procdefcoll:=vmtentry^.firstprocdef;
  458. while assigned(procdefcoll) do
  459. begin
  460. if (procdefcoll^.data._class=pd._class) and
  461. ((po_overload in pd.procoptions)<>(po_overload in procdefcoll^.data.procoptions)) then
  462. begin
  463. MessagePos1(pd.fileinfo,parser_e_no_overload_for_all_procs,pd.procsym.realname);
  464. { recover }
  465. include(procdefcoll^.data.procoptions,po_overload);
  466. include(pd.procoptions,po_overload);
  467. end;
  468. procdefcoll:=procdefcoll^.next;
  469. end;
  470. end;
  471. end;
  472. { generate new entry }
  473. new(procdefcoll);
  474. procdefcoll^.data:=pd;
  475. procdefcoll^.hidden:=false;
  476. procdefcoll^.visible:=is_visible;
  477. procdefcoll^.next:=vmtentry^.firstprocdef;
  478. vmtentry^.firstprocdef:=procdefcoll;
  479. { give virtual method a number }
  480. if (po_virtualmethod in pd.procoptions) then
  481. begin
  482. pd.extnumber:=nextvirtnumber;
  483. inc(nextvirtnumber);
  484. has_virtual_method:=true;
  485. end;
  486. if (pd.proctypeoption=potype_constructor) then
  487. has_constructor:=true;
  488. end;
  489. function tclassheader.newvmtentry(sym:tprocsym):pvmtentry;
  490. begin
  491. { generate new vmtentry }
  492. new(result);
  493. result^.speedvalue:=sym.speedvalue;
  494. result^.name:=stringdup(sym.name);
  495. result^.next:=firstvmtentry;
  496. result^.firstprocdef:=nil;
  497. firstvmtentry:=result;
  498. end;
  499. procedure tclassheader.eachsym(sym : tnamedindexitem;arg:pointer);
  500. const
  501. po_comp = [po_classmethod,po_virtualmethod,po_staticmethod,po_interrupt,po_iocheck,po_msgstr,po_msgint,
  502. po_exports,po_varargs,po_explicitparaloc,po_nostackframe];
  503. label
  504. handlenextdef;
  505. var
  506. pd : tprocdef;
  507. i : cardinal;
  508. is_visible,
  509. hasoverloads,
  510. pdoverload : boolean;
  511. procdefcoll : pprocdefcoll;
  512. vmtentry : pvmtentry;
  513. _name : string;
  514. _speed : cardinal;
  515. begin
  516. if (tsym(sym).typ<>procsym) then
  517. exit;
  518. { check the current list of symbols }
  519. _name:=sym.name;
  520. _speed:=sym.speedvalue;
  521. vmtentry:=firstvmtentry;
  522. while assigned(vmtentry) do
  523. begin
  524. { does the symbol already exist in the list? First
  525. compare speedvalue before doing the string compare to
  526. speed it up a little }
  527. if (_speed=vmtentry^.speedvalue) and
  528. (_name=vmtentry^.name^) then
  529. begin
  530. hasoverloads:=(Tprocsym(sym).procdef_count>1);
  531. { walk through all defs of the symbol }
  532. for i:=1 to Tprocsym(sym).procdef_count do
  533. begin
  534. pd:=Tprocsym(sym).procdef[i];
  535. { is this procdef visible from the class that we are
  536. generating. This will be used to hide the other procdefs.
  537. When the symbol is not visible we don't hide the other
  538. procdefs, because they can be reused in the next class.
  539. The check to skip the invisible methods that are in the
  540. list is futher down in the code }
  541. is_visible:=pd.is_visible_for_object(_class);
  542. if pd.procsym=sym then
  543. begin
  544. pdoverload:=(po_overload in pd.procoptions);
  545. { compare with all stored definitions }
  546. procdefcoll:=vmtentry^.firstprocdef;
  547. while assigned(procdefcoll) do
  548. begin
  549. { compare only if the definition is not hidden }
  550. if not procdefcoll^.hidden then
  551. begin
  552. { check if one of the two methods has virtual }
  553. if (po_virtualmethod in procdefcoll^.data.procoptions) or
  554. (po_virtualmethod in pd.procoptions) then
  555. begin
  556. { if the current definition has no virtual then hide the
  557. old virtual if the new definition has the same arguments or
  558. when it has no overload directive and no overloads }
  559. if not(po_virtualmethod in pd.procoptions) then
  560. begin
  561. if procdefcoll^.visible and
  562. (not(pdoverload or hasoverloads) or
  563. (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal)) then
  564. begin
  565. if is_visible then
  566. procdefcoll^.hidden:=true;
  567. if (_class=pd._class) and not(po_reintroduce in pd.procoptions) then
  568. MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false));
  569. end;
  570. end
  571. { if both are virtual we check the header }
  572. else if (po_virtualmethod in pd.procoptions) and
  573. (po_virtualmethod in procdefcoll^.data.procoptions) then
  574. begin
  575. { new one has not override }
  576. if is_class(_class) and
  577. not(po_overridingmethod in pd.procoptions) then
  578. begin
  579. { we start a new virtual tree, hide the old }
  580. if (not(pdoverload or hasoverloads) or
  581. (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal)) and
  582. (procdefcoll^.visible) then
  583. begin
  584. if is_visible then
  585. procdefcoll^.hidden:=true;
  586. if (_class=pd._class) and not(po_reintroduce in pd.procoptions) then
  587. MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false));
  588. end;
  589. end
  590. { same parameters }
  591. else if (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal) then
  592. begin
  593. { overload is inherited }
  594. if (po_overload in procdefcoll^.data.procoptions) then
  595. include(pd.procoptions,po_overload);
  596. { inherite calling convention when it was force and the
  597. current definition has none force }
  598. if (po_hascallingconvention in procdefcoll^.data.procoptions) and
  599. not(po_hascallingconvention in pd.procoptions) then
  600. begin
  601. pd.proccalloption:=procdefcoll^.data.proccalloption;
  602. include(pd.procoptions,po_hascallingconvention);
  603. end;
  604. { the flags have to match except abstract and override }
  605. { only if both are virtual !! }
  606. if (procdefcoll^.data.proccalloption<>pd.proccalloption) or
  607. (procdefcoll^.data.proctypeoption<>pd.proctypeoption) or
  608. ((procdefcoll^.data.procoptions*po_comp)<>(pd.procoptions*po_comp)) then
  609. begin
  610. MessagePos1(pd.fileinfo,parser_e_header_dont_match_forward,pd.fullprocname(false));
  611. tprocsym(procdefcoll^.data.procsym).write_parameter_lists(pd);
  612. end;
  613. { error, if the return types aren't equal }
  614. if not(equal_defs(procdefcoll^.data.rettype.def,pd.rettype.def)) and
  615. not((procdefcoll^.data.rettype.def.deftype=objectdef) and
  616. (pd.rettype.def.deftype=objectdef) and
  617. is_class(procdefcoll^.data.rettype.def) and
  618. is_class(pd.rettype.def) and
  619. (tobjectdef(pd.rettype.def).is_related(
  620. tobjectdef(procdefcoll^.data.rettype.def)))) then
  621. Message2(parser_e_overridden_methods_not_same_ret,pd.fullprocname(false),
  622. procdefcoll^.data.fullprocname(false));
  623. { check if the method to override is visible, check is only needed
  624. for the current parsed class. Parent classes are already validated and
  625. need to include all virtual methods including the ones not visible in the
  626. current class }
  627. if (_class=pd._class) and
  628. (po_overridingmethod in pd.procoptions) and
  629. (not procdefcoll^.visible) then
  630. MessagePos1(pd.fileinfo,parser_e_nothing_to_be_overridden,pd.fullprocname(false));
  631. { override old virtual method in VMT }
  632. pd.extnumber:=procdefcoll^.data.extnumber;
  633. procdefcoll^.data:=pd;
  634. if is_visible then
  635. procdefcoll^.visible:=true;
  636. goto handlenextdef;
  637. end
  638. { different parameters }
  639. else
  640. begin
  641. { when we got an override directive then can search futher for
  642. the procedure to override.
  643. If we are starting a new virtual tree then hide the old tree }
  644. if not(po_overridingmethod in pd.procoptions) and
  645. not pdoverload then
  646. begin
  647. if is_visible then
  648. procdefcoll^.hidden:=true;
  649. if (_class=pd._class) and not(po_reintroduce in pd.procoptions) then
  650. MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false));
  651. end;
  652. end;
  653. end
  654. else
  655. begin
  656. { the new definition is virtual and the old static, we hide the old one
  657. if the new defintion has not the overload directive }
  658. if is_visible and
  659. ((not(pdoverload or hasoverloads)) or
  660. (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal)) then
  661. procdefcoll^.hidden:=true;
  662. end;
  663. end
  664. else
  665. begin
  666. { both are static, we hide the old one if the new defintion
  667. has not the overload directive }
  668. if is_visible and
  669. ((not pdoverload) or
  670. (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal)) then
  671. procdefcoll^.hidden:=true;
  672. end;
  673. end; { not hidden }
  674. procdefcoll:=procdefcoll^.next;
  675. end;
  676. { if it isn't saved in the list we create a new entry }
  677. newdefentry(vmtentry,pd,is_visible);
  678. end;
  679. handlenextdef:
  680. end;
  681. exit;
  682. end;
  683. vmtentry:=vmtentry^.next;
  684. end;
  685. { Generate new procsym entry in vmt }
  686. vmtentry:=newvmtentry(tprocsym(sym));
  687. { Add procdefs }
  688. for i:=1 to Tprocsym(sym).procdef_count do
  689. begin
  690. pd:=Tprocsym(sym).procdef[i];
  691. newdefentry(vmtentry,pd,pd.is_visible_for_object(_class));
  692. end;
  693. end;
  694. procedure tclassheader.disposevmttree;
  695. var
  696. vmtentry : pvmtentry;
  697. procdefcoll : pprocdefcoll;
  698. begin
  699. { disposes the above generated tree }
  700. vmtentry:=firstvmtentry;
  701. while assigned(vmtentry) do
  702. begin
  703. firstvmtentry:=vmtentry^.next;
  704. stringdispose(vmtentry^.name);
  705. procdefcoll:=vmtentry^.firstprocdef;
  706. while assigned(procdefcoll) do
  707. begin
  708. vmtentry^.firstprocdef:=procdefcoll^.next;
  709. dispose(procdefcoll);
  710. procdefcoll:=vmtentry^.firstprocdef;
  711. end;
  712. dispose(vmtentry);
  713. vmtentry:=firstvmtentry;
  714. end;
  715. end;
  716. procedure tclassheader.genvmt;
  717. procedure do_genvmt(p : tobjectdef);
  718. begin
  719. { start with the base class }
  720. if assigned(p.childof) then
  721. do_genvmt(p.childof);
  722. { walk through all public syms }
  723. p.symtable.foreach(@eachsym,nil);
  724. end;
  725. begin
  726. firstvmtentry:=nil;
  727. nextvirtnumber:=0;
  728. has_constructor:=false;
  729. has_virtual_method:=false;
  730. { generates a tree of all used methods }
  731. do_genvmt(_class);
  732. if not(is_interface(_class)) and
  733. has_virtual_method and
  734. not(has_constructor) then
  735. Message1(parser_w_virtual_without_constructor,_class.objrealname^);
  736. end;
  737. {**************************************
  738. Interface tables
  739. **************************************}
  740. function tclassheader.gintfgetvtbllabelname(intfindex: integer): string;
  741. begin
  742. gintfgetvtbllabelname:=make_mangledname('VTBL',_class.owner,_class.objname^+
  743. '_$_'+_class.implementedinterfaces.interfaces(intfindex).objname^);
  744. end;
  745. procedure tclassheader.gintfcreatevtbl(intfindex: integer; rawdata: TAAsmoutput);
  746. var
  747. implintf: timplementedinterfaces;
  748. curintf: tobjectdef;
  749. proccount: integer;
  750. tmps: string;
  751. i: longint;
  752. begin
  753. implintf:=_class.implementedinterfaces;
  754. curintf:=implintf.interfaces(intfindex);
  755. rawdata.concat(cai_align.create(const_align(sizeof(aint))));
  756. if maybe_smartlink_symbol then
  757. rawdata.concat(Tai_symbol.Createname_global(gintfgetvtbllabelname(intfindex),AT_DATA ,0))
  758. else
  759. rawdata.concat(Tai_symbol.Createname(gintfgetvtbllabelname(intfindex),AT_DATA,0));
  760. proccount:=implintf.implproccount(intfindex);
  761. for i:=1 to proccount do
  762. begin
  763. tmps:=make_mangledname('WRPR',_class.owner,_class.objname^+'_$_'+curintf.objname^+'_$_'+
  764. tostr(i)+'_$_'+
  765. implintf.implprocs(intfindex,i).mangledname);
  766. { create reference }
  767. rawdata.concat(Tai_const.Createname(tmps,AT_FUNCTION,0));
  768. end;
  769. end;
  770. procedure tclassheader.gintfgenentry(intfindex, contintfindex: integer; rawdata: TAAsmoutput);
  771. var
  772. implintf: timplementedinterfaces;
  773. curintf: tobjectdef;
  774. tmplabel: tasmlabel;
  775. i: longint;
  776. begin
  777. implintf:=_class.implementedinterfaces;
  778. curintf:=implintf.interfaces(intfindex);
  779. { GUID }
  780. if curintf.objecttype in [odt_interfacecom] then
  781. begin
  782. { label for GUID }
  783. objectlibrary.getdatalabel(tmplabel);
  784. rawdata.concat(cai_align.create(const_align(sizeof(aint))));
  785. rawdata.concat(Tai_label.Create(tmplabel));
  786. rawdata.concat(Tai_const.Create_32bit(longint(curintf.iidguid^.D1)));
  787. rawdata.concat(Tai_const.Create_16bit(curintf.iidguid^.D2));
  788. rawdata.concat(Tai_const.Create_16bit(curintf.iidguid^.D3));
  789. for i:=Low(curintf.iidguid^.D4) to High(curintf.iidguid^.D4) do
  790. rawdata.concat(Tai_const.Create_8bit(curintf.iidguid^.D4[i]));
  791. dataSegment.concat(Tai_const.Create_sym(tmplabel));
  792. end
  793. else
  794. begin
  795. { nil for Corba interfaces }
  796. dataSegment.concat(Tai_const.Create_sym(nil));
  797. end;
  798. { VTable }
  799. dataSegment.concat(Tai_const.Createname(gintfgetvtbllabelname(contintfindex),AT_DATA,0));
  800. { IOffset field }
  801. dataSegment.concat(Tai_const.Create_32bit(implintf.ioffsets(contintfindex)));
  802. { IIDStr }
  803. objectlibrary.getdatalabel(tmplabel);
  804. rawdata.concat(cai_align.create(const_align(sizeof(aint))));
  805. rawdata.concat(Tai_label.Create(tmplabel));
  806. rawdata.concat(Tai_const.Create_8bit(length(curintf.iidstr^)));
  807. if curintf.objecttype=odt_interfacecom then
  808. rawdata.concat(Tai_string.Create(upper(curintf.iidstr^)))
  809. else
  810. rawdata.concat(Tai_string.Create(curintf.iidstr^));
  811. dataSegment.concat(Tai_const.Create_sym(tmplabel));
  812. end;
  813. procedure tclassheader.gintfoptimizevtbls;
  814. type
  815. tcompintfentry = record
  816. weight: longint;
  817. compintf: longint;
  818. end;
  819. { Max 1000 interface in the class header interfaces it's enough imho }
  820. tcompintfs = array[1..1000] of tcompintfentry;
  821. pcompintfs = ^tcompintfs;
  822. tequals = array[1..1000] of longint;
  823. pequals = ^tequals;
  824. timpls = array[1..1000] of longint;
  825. pimpls = ^timpls;
  826. var
  827. max: longint;
  828. equals: pequals;
  829. compats: pcompintfs;
  830. impls: pimpls;
  831. w,i,j,k: longint;
  832. cij: boolean;
  833. cji: boolean;
  834. begin
  835. max:=_class.implementedinterfaces.count;
  836. if max>High(tequals) then
  837. Internalerror(200006135);
  838. getmem(compats,sizeof(tcompintfentry)*max);
  839. getmem(equals,sizeof(longint)*max);
  840. getmem(impls,sizeof(longint)*max);
  841. fillchar(compats^,sizeof(tcompintfentry)*max,0);
  842. fillchar(equals^,sizeof(longint)*max,0);
  843. fillchar(impls^,sizeof(longint)*max,0);
  844. { ismergepossible is a containing relation
  845. meaning of ismergepossible(a,b,w) =
  846. if implementorfunction map of a is contained implementorfunction map of b
  847. imp(a,b) and imp(b,c) => imp(a,c) ; imp(a,b) and imp(b,a) => a == b
  848. }
  849. { the order is very important for correct allocation }
  850. for i:=1 to max do
  851. begin
  852. for j:=i+1 to max do
  853. begin
  854. cij:=_class.implementedinterfaces.isimplmergepossible(i,j,w);
  855. cji:=_class.implementedinterfaces.isimplmergepossible(j,i,w);
  856. if cij and cji then { i equal j }
  857. begin
  858. { get minimum index of equal }
  859. if equals^[j]=0 then
  860. equals^[j]:=i;
  861. end
  862. else if cij then
  863. begin
  864. { get minimum index of maximum weight }
  865. if compats^[i].weight<w then
  866. begin
  867. compats^[i].weight:=w;
  868. compats^[i].compintf:=j;
  869. end;
  870. end
  871. else if cji then
  872. begin
  873. { get minimum index of maximum weight }
  874. if (compats^[j].weight<w) then
  875. begin
  876. compats^[j].weight:=w;
  877. compats^[j].compintf:=i;
  878. end;
  879. end;
  880. end;
  881. end;
  882. { Reset, no replacements by default }
  883. for i:=1 to max do
  884. impls^[i]:=i;
  885. { Replace vtbls when equal or compat, repeat
  886. until there are no replacements possible anymore. This is
  887. needed for the cases like:
  888. First loop: 2->3, 3->1
  889. Second loop: 2->1 (because 3 was replaced with 1)
  890. }
  891. repeat
  892. k:=0;
  893. for i:=1 to max do
  894. begin
  895. if compats^[impls^[i]].compintf<>0 then
  896. impls^[i]:=compats^[impls^[i]].compintf
  897. else if equals^[impls^[i]]<>0 then
  898. impls^[i]:=equals^[impls^[i]]
  899. else
  900. inc(k);
  901. end;
  902. until k=max;
  903. { Update the implindex }
  904. for i:=1 to max do
  905. _class.implementedinterfaces.setimplindex(i,impls^[i]);
  906. freemem(compats);
  907. freemem(equals);
  908. freemem(impls);
  909. end;
  910. procedure tclassheader.gintfwritedata;
  911. var
  912. rawdata: taasmoutput;
  913. max,i,j : smallint;
  914. begin
  915. max:=_class.implementedinterfaces.count;
  916. rawdata:=TAAsmOutput.Create;
  917. dataSegment.concat(Tai_const.Create_16bit(max));
  918. { Two pass, one for allocation and vtbl creation }
  919. for i:=1 to max do
  920. begin
  921. if _class.implementedinterfaces.implindex(i)=i then { if implement itself }
  922. begin
  923. { allocate a pointer in the object memory }
  924. with tobjectsymtable(_class.symtable) do
  925. begin
  926. datasize:=align(datasize,min(sizeof(aint),fieldalignment));
  927. _class.implementedinterfaces.setioffsets(i,datasize);
  928. inc(datasize,sizeof(aint));
  929. end;
  930. { write vtbl }
  931. gintfcreatevtbl(i,rawdata);
  932. end;
  933. end;
  934. { second pass: for fill interfacetable and remained ioffsets }
  935. for i:=1 to max do
  936. begin
  937. j:=_class.implementedinterfaces.implindex(i);
  938. if j<>i then
  939. _class.implementedinterfaces.setioffsets(i,_class.implementedinterfaces.ioffsets(j));
  940. gintfgenentry(i,j,rawdata);
  941. end;
  942. dataSegment.concatlist(rawdata);
  943. rawdata.free;
  944. end;
  945. function tclassheader.gintfgetcprocdef(proc: tprocdef;const name: string): tprocdef;
  946. const
  947. po_comp = [po_classmethod,po_staticmethod,po_interrupt,po_iocheck,po_msgstr,po_msgint,
  948. po_exports,po_varargs,po_explicitparaloc,po_nostackframe];
  949. var
  950. sym: tsym;
  951. implprocdef : Tprocdef;
  952. i: cardinal;
  953. begin
  954. gintfgetcprocdef:=nil;
  955. sym:=tsym(search_class_member(_class,name));
  956. if assigned(sym) and
  957. (sym.typ=procsym) then
  958. begin
  959. { when the definition has overload directive set, we search for
  960. overloaded definitions in the class, this only needs to be done once
  961. for class entries as the tree keeps always the same }
  962. if (not tprocsym(sym).overloadchecked) and
  963. (po_overload in tprocsym(sym).first_procdef.procoptions) and
  964. (tprocsym(sym).owner.symtabletype=objectsymtable) then
  965. search_class_overloads(tprocsym(sym));
  966. for i:=1 to tprocsym(sym).procdef_count do
  967. begin
  968. implprocdef:=tprocsym(sym).procdef[i];
  969. if (compare_paras(proc.paras,implprocdef.paras,cp_none,[])>=te_equal) and
  970. (proc.proccalloption=implprocdef.proccalloption) and
  971. (proc.proctypeoption=implprocdef.proctypeoption) and
  972. ((proc.procoptions*po_comp)=((implprocdef.procoptions+[po_virtualmethod])*po_comp)) then
  973. begin
  974. gintfgetcprocdef:=implprocdef;
  975. exit;
  976. end;
  977. end;
  978. end;
  979. end;
  980. procedure tclassheader.gintfdoonintf(intf: tobjectdef; intfindex: longint);
  981. var
  982. def: tdef;
  983. mappedname: string;
  984. nextexist: pointer;
  985. implprocdef: tprocdef;
  986. begin
  987. def:=tdef(intf.symtable.defindex.first);
  988. while assigned(def) do
  989. begin
  990. if def.deftype=procdef then
  991. begin
  992. implprocdef:=nil;
  993. nextexist:=nil;
  994. repeat
  995. mappedname:=_class.implementedinterfaces.getmappings(intfindex,tprocdef(def).procsym.name,nextexist);
  996. if mappedname<>'' then
  997. implprocdef:=gintfgetcprocdef(tprocdef(def),mappedname);
  998. until assigned(implprocdef) or not assigned(nextexist);
  999. if not assigned(implprocdef) then
  1000. implprocdef:=gintfgetcprocdef(tprocdef(def),tprocdef(def).procsym.name);
  1001. if assigned(implprocdef) then
  1002. _class.implementedinterfaces.addimplproc(intfindex,implprocdef)
  1003. else
  1004. Message1(sym_e_no_matching_implementation_found,tprocdef(def).fullprocname(false));
  1005. end;
  1006. def:=tdef(def.indexnext);
  1007. end;
  1008. end;
  1009. procedure tclassheader.gintfwalkdowninterface(intf: tobjectdef; intfindex: longint);
  1010. begin
  1011. if assigned(intf.childof) then
  1012. gintfwalkdowninterface(intf.childof,intfindex);
  1013. gintfdoonintf(intf,intfindex);
  1014. end;
  1015. function tclassheader.genintftable: tasmlabel;
  1016. var
  1017. intfindex: longint;
  1018. curintf: tobjectdef;
  1019. intftable: tasmlabel;
  1020. begin
  1021. { 1. step collect implementor functions into the implementedinterfaces.implprocs }
  1022. for intfindex:=1 to _class.implementedinterfaces.count do
  1023. begin
  1024. curintf:=_class.implementedinterfaces.interfaces(intfindex);
  1025. gintfwalkdowninterface(curintf,intfindex);
  1026. end;
  1027. { 2. step calc required fieldcount and their offsets in the object memory map
  1028. and write data }
  1029. objectlibrary.getdatalabel(intftable);
  1030. dataSegment.concat(cai_align.create(const_align(sizeof(aint))));
  1031. dataSegment.concat(Tai_label.Create(intftable));
  1032. { Optimize interface tables to reuse wrappers }
  1033. gintfoptimizevtbls;
  1034. { Write interface tables }
  1035. gintfwritedata;
  1036. genintftable:=intftable;
  1037. end;
  1038. { Write interface identifiers to the data section }
  1039. procedure tclassheader.writeinterfaceids;
  1040. var
  1041. i : longint;
  1042. s : string;
  1043. begin
  1044. if assigned(_class.iidguid) then
  1045. begin
  1046. s:=make_mangledname('IID',_class.owner,_class.objname^);
  1047. maybe_new_object_file(dataSegment);
  1048. new_section(dataSegment,sec_rodata,s,const_align(sizeof(aint)));
  1049. dataSegment.concat(Tai_symbol.Createname_global(s,AT_DATA,0));
  1050. dataSegment.concat(Tai_const.Create_32bit(longint(_class.iidguid^.D1)));
  1051. dataSegment.concat(Tai_const.Create_16bit(_class.iidguid^.D2));
  1052. dataSegment.concat(Tai_const.Create_16bit(_class.iidguid^.D3));
  1053. for i:=Low(_class.iidguid^.D4) to High(_class.iidguid^.D4) do
  1054. dataSegment.concat(Tai_const.Create_8bit(_class.iidguid^.D4[i]));
  1055. end;
  1056. maybe_new_object_file(dataSegment);
  1057. s:=make_mangledname('IIDSTR',_class.owner,_class.objname^);
  1058. new_section(dataSegment,sec_rodata,s,0);
  1059. dataSegment.concat(Tai_symbol.Createname_global(s,AT_DATA,0));
  1060. dataSegment.concat(Tai_const.Create_8bit(length(_class.iidstr^)));
  1061. dataSegment.concat(Tai_string.Create(_class.iidstr^));
  1062. end;
  1063. procedure tclassheader.writevirtualmethods(List:TAAsmoutput);
  1064. var
  1065. vmtentry : pvmtentry;
  1066. procdefcoll : pprocdefcoll;
  1067. i : longint;
  1068. begin
  1069. { walk trough all numbers for virtual methods and search }
  1070. { the method }
  1071. for i:=0 to nextvirtnumber-1 do
  1072. begin
  1073. { walk trough all symbols }
  1074. vmtentry:=firstvmtentry;
  1075. while assigned(vmtentry) do
  1076. begin
  1077. { walk trough all methods }
  1078. procdefcoll:=vmtentry^.firstprocdef;
  1079. while assigned(procdefcoll) do
  1080. begin
  1081. { writes the addresses to the VMT }
  1082. { but only this which are declared as virtual }
  1083. if procdefcoll^.data.extnumber=i then
  1084. begin
  1085. if (po_virtualmethod in procdefcoll^.data.procoptions) then
  1086. begin
  1087. { if a method is abstract, then is also the }
  1088. { class abstract and it's not allow to }
  1089. { generates an instance }
  1090. if (po_abstractmethod in procdefcoll^.data.procoptions) then
  1091. List.concat(Tai_const.Createname('FPC_ABSTRACTERROR',AT_FUNCTION,0))
  1092. else
  1093. List.concat(Tai_const.createname(procdefcoll^.data.mangledname,AT_FUNCTION,0));
  1094. end;
  1095. end;
  1096. procdefcoll:=procdefcoll^.next;
  1097. end;
  1098. vmtentry:=vmtentry^.next;
  1099. end;
  1100. end;
  1101. end;
  1102. { generates the vmt for classes as well as for objects }
  1103. procedure tclassheader.writevmt;
  1104. var
  1105. methodnametable,intmessagetable,
  1106. strmessagetable,classnamelabel,
  1107. fieldtablelabel : tasmlabel;
  1108. {$ifdef WITHDMT}
  1109. dmtlabel : tasmlabel;
  1110. {$endif WITHDMT}
  1111. interfacetable : tasmlabel;
  1112. begin
  1113. {$ifdef WITHDMT}
  1114. dmtlabel:=gendmt;
  1115. {$endif WITHDMT}
  1116. { write tables for classes, this must be done before the actual
  1117. class is written, because we need the labels defined }
  1118. if is_class(_class) then
  1119. begin
  1120. objectlibrary.getdatalabel(classnamelabel);
  1121. maybe_new_object_file(dataSegment);
  1122. new_section(dataSegment,sec_rodata,classnamelabel.name,const_align(sizeof(aint)));
  1123. { interface table }
  1124. if _class.implementedinterfaces.count>0 then
  1125. interfacetable:=genintftable;
  1126. methodnametable:=genpublishedmethodstable;
  1127. fieldtablelabel:=_class.generate_field_table;
  1128. { write class name }
  1129. dataSegment.concat(Tai_label.Create(classnamelabel));
  1130. dataSegment.concat(Tai_const.Create_8bit(length(_class.objrealname^)));
  1131. dataSegment.concat(Tai_string.Create(_class.objrealname^));
  1132. { generate message and dynamic tables }
  1133. if (oo_has_msgstr in _class.objectoptions) then
  1134. strmessagetable:=genstrmsgtab;
  1135. if (oo_has_msgint in _class.objectoptions) then
  1136. intmessagetable:=genintmsgtab;
  1137. end;
  1138. { write debug info }
  1139. maybe_new_object_file(dataSegment);
  1140. new_section(dataSegment,sec_rodata,_class.vmt_mangledname,const_align(sizeof(aint)));
  1141. {$ifdef GDB}
  1142. if (cs_debuginfo in aktmoduleswitches) then
  1143. begin
  1144. do_count_dbx:=true;
  1145. if assigned(_class.owner) and assigned(_class.owner.name) then
  1146. dataSegment.concat(Tai_stabs.Create(strpnew('"vmt_'+_class.owner.name^+_class.name+':S'+
  1147. tstoreddef(vmttype.def).numberstring+'",'+tostr(N_STSYM)+',0,0,'+_class.vmt_mangledname)));
  1148. end;
  1149. {$endif GDB}
  1150. dataSegment.concat(Tai_symbol.Createname_global(_class.vmt_mangledname,AT_DATA,0));
  1151. { determine the size with symtable.datasize, because }
  1152. { size gives back 4 for classes }
  1153. dataSegment.concat(Tai_const.Create(ait_const_ptr,tobjectsymtable(_class.symtable).datasize));
  1154. dataSegment.concat(Tai_const.Create(ait_const_ptr,-int64(tobjectsymtable(_class.symtable).datasize)));
  1155. {$ifdef WITHDMT}
  1156. if _class.classtype=ct_object then
  1157. begin
  1158. if assigned(dmtlabel) then
  1159. dataSegment.concat(Tai_const_symbol.Create(dmtlabel)))
  1160. else
  1161. dataSegment.concat(Tai_const.Create_ptr(0));
  1162. end;
  1163. {$endif WITHDMT}
  1164. { write pointer to parent VMT, this isn't implemented in TP }
  1165. { but this is not used in FPC ? (PM) }
  1166. { it's not used yet, but the delphi-operators as and is need it (FK) }
  1167. { it is not written for parents that don't have any vmt !! }
  1168. if assigned(_class.childof) and
  1169. (oo_has_vmt in _class.childof.objectoptions) then
  1170. dataSegment.concat(Tai_const.Createname(_class.childof.vmt_mangledname,AT_DATA,0))
  1171. else
  1172. dataSegment.concat(Tai_const.Create_sym(nil));
  1173. { write extended info for classes, for the order see rtl/inc/objpash.inc }
  1174. if is_class(_class) then
  1175. begin
  1176. { pointer to class name string }
  1177. dataSegment.concat(Tai_const.Create_sym(classnamelabel));
  1178. { pointer to dynamic table or nil }
  1179. if (oo_has_msgint in _class.objectoptions) then
  1180. dataSegment.concat(Tai_const.Create_sym(intmessagetable))
  1181. else
  1182. dataSegment.concat(Tai_const.Create_sym(nil));
  1183. { pointer to method table or nil }
  1184. dataSegment.concat(Tai_const.Create_sym(methodnametable));
  1185. { pointer to field table }
  1186. dataSegment.concat(Tai_const.Create_sym(fieldtablelabel));
  1187. { pointer to type info of published section }
  1188. if (oo_can_have_published in _class.objectoptions) then
  1189. dataSegment.concat(Tai_const.Create_sym(_class.get_rtti_label(fullrtti)))
  1190. else
  1191. dataSegment.concat(Tai_const.Create_sym(nil));
  1192. { inittable for con-/destruction }
  1193. if _class.members_need_inittable then
  1194. dataSegment.concat(Tai_const.Create_sym(_class.get_rtti_label(initrtti)))
  1195. else
  1196. dataSegment.concat(Tai_const.Create_sym(nil));
  1197. { auto table }
  1198. dataSegment.concat(Tai_const.Create_sym(nil));
  1199. { interface table }
  1200. if _class.implementedinterfaces.count>0 then
  1201. dataSegment.concat(Tai_const.Create_sym(interfacetable))
  1202. else
  1203. dataSegment.concat(Tai_const.Create_sym(nil));
  1204. { table for string messages }
  1205. if (oo_has_msgstr in _class.objectoptions) then
  1206. dataSegment.concat(Tai_const.Create_sym(strmessagetable))
  1207. else
  1208. dataSegment.concat(Tai_const.Create_sym(nil));
  1209. end;
  1210. { write virtual methods }
  1211. writevirtualmethods(dataSegment);
  1212. datasegment.concat(Tai_const.create(ait_const_ptr,0));
  1213. { write the size of the VMT }
  1214. dataSegment.concat(Tai_symbol_end.Createname(_class.vmt_mangledname));
  1215. end;
  1216. end.
  1217. {
  1218. $Log$
  1219. Revision 1.93 2005-05-05 21:09:10 florian
  1220. * write nil into the method table for abstract methods
  1221. Revision 1.92 2005/03/17 09:08:54 michael
  1222. + Patch from peter to fix overload directive cheking in delphi mode
  1223. Revision 1.91 2005/02/14 17:13:06 peter
  1224. * truncate log
  1225. Revision 1.90 2005/02/10 22:08:03 peter
  1226. * remove obsolete code
  1227. Revision 1.89 2005/02/02 02:19:42 karoly
  1228. * removed debug writelns from florian's previous commit
  1229. Revision 1.88 2005/02/01 23:18:54 florian
  1230. * fixed:
  1231. r1 = record
  1232. p : procedure stdcall;
  1233. i : longint;
  1234. end;
  1235. Revision 1.87 2005/01/24 22:08:32 peter
  1236. * interface wrapper generation moved to cgobj
  1237. * generate interface wrappers after the module is parsed
  1238. Revision 1.86 2005/01/10 20:41:55 peter
  1239. * write realname for published methods
  1240. Revision 1.85 2005/01/09 15:05:29 peter
  1241. * fix interface vtbl optimization
  1242. * replace ugly pointer construct of ioffset()
  1243. }