nobj.pas 53 KB

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