nobj.pas 55 KB

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