nobj.pas 53 KB

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