nobj.pas 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362
  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
  118. {$ifdef GDB}
  119. ,gdb
  120. {$endif GDB}
  121. ;
  122. {*****************************************************************************
  123. TClassHeader
  124. *****************************************************************************}
  125. constructor tclassheader.create(c:tobjectdef);
  126. begin
  127. inherited Create;
  128. _Class:=c;
  129. end;
  130. destructor tclassheader.destroy;
  131. begin
  132. disposevmttree;
  133. end;
  134. {**************************************
  135. Message Tables
  136. **************************************}
  137. procedure tclassheader.disposeprocdeftree(p : pprocdeftree);
  138. begin
  139. if assigned(p^.l) then
  140. disposeprocdeftree(p^.l);
  141. if assigned(p^.r) then
  142. disposeprocdeftree(p^.r);
  143. dispose(p);
  144. end;
  145. procedure tclassheader.insertint(p : pprocdeftree;var at : pprocdeftree;var count:longint);
  146. begin
  147. if at=nil then
  148. begin
  149. at:=p;
  150. inc(count);
  151. end
  152. else
  153. begin
  154. if p^.data.messageinf.i<at^.data.messageinf.i then
  155. insertint(p,at^.l,count)
  156. else if p^.data.messageinf.i>at^.data.messageinf.i then
  157. insertint(p,at^.r,count)
  158. else
  159. Message1(parser_e_duplicate_message_label,tostr(p^.data.messageinf.i));
  160. end;
  161. end;
  162. procedure tclassheader.insertstr(p : pprocdeftree;var at : pprocdeftree;var count:longint);
  163. var
  164. i : integer;
  165. begin
  166. if at=nil then
  167. begin
  168. at:=p;
  169. inc(count);
  170. end
  171. else
  172. begin
  173. i:=strcomp(p^.data.messageinf.str,at^.data.messageinf.str);
  174. if i<0 then
  175. insertstr(p,at^.l,count)
  176. else if i>0 then
  177. insertstr(p,at^.r,count)
  178. else
  179. Message1(parser_e_duplicate_message_label,strpas(p^.data.messageinf.str));
  180. end;
  181. end;
  182. procedure tclassheader.insertmsgint(p : tnamedindexitem;arg:pointer);
  183. var
  184. i : cardinal;
  185. def: Tprocdef;
  186. pt : pprocdeftree;
  187. begin
  188. if tsym(p).typ=procsym then
  189. for i:=1 to Tprocsym(p).procdef_count do
  190. begin
  191. def:=Tprocsym(p).procdef[i];
  192. if po_msgint in def.procoptions then
  193. begin
  194. new(pt);
  195. pt^.data:=def;
  196. pt^.l:=nil;
  197. pt^.r:=nil;
  198. insertint(pt,root,plongint(arg)^);
  199. end;
  200. end;
  201. end;
  202. procedure tclassheader.insertmsgstr(p : tnamedindexitem;arg:pointer);
  203. var
  204. i : cardinal;
  205. def: Tprocdef;
  206. pt : pprocdeftree;
  207. begin
  208. if tsym(p).typ=procsym then
  209. for i:=1 to Tprocsym(p).procdef_count do
  210. begin
  211. def:=Tprocsym(p).procdef[i];
  212. if po_msgstr in def.procoptions then
  213. begin
  214. new(pt);
  215. pt^.data:=def;
  216. pt^.l:=nil;
  217. pt^.r:=nil;
  218. insertstr(pt,root,plongint(arg)^);
  219. end;
  220. end;
  221. end;
  222. procedure tclassheader.writenames(p : pprocdeftree);
  223. var
  224. ca : pchar;
  225. len : longint;
  226. begin
  227. objectlibrary.getdatalabel(p^.nl);
  228. if assigned(p^.l) then
  229. writenames(p^.l);
  230. asmlist[al_globals].concat(cai_align.create(const_align(sizeof(aint))));
  231. asmlist[al_globals].concat(Tai_label.Create(p^.nl));
  232. len:=strlen(p^.data.messageinf.str);
  233. asmlist[al_globals].concat(tai_const.create_8bit(len));
  234. getmem(ca,len+1);
  235. move(p^.data.messageinf.str^,ca^,len+1);
  236. asmlist[al_globals].concat(Tai_string.Create_pchar(ca));
  237. if assigned(p^.r) then
  238. writenames(p^.r);
  239. end;
  240. procedure tclassheader.writestrentry(p : pprocdeftree);
  241. begin
  242. if assigned(p^.l) then
  243. writestrentry(p^.l);
  244. { write name label }
  245. asmlist[al_globals].concat(Tai_const.Create_sym(p^.nl));
  246. asmlist[al_globals].concat(Tai_const.Createname(p^.data.mangledname,AT_FUNCTION,0));
  247. if assigned(p^.r) then
  248. writestrentry(p^.r);
  249. end;
  250. function tclassheader.genstrmsgtab : tasmlabel;
  251. var
  252. r : tasmlabel;
  253. count : longint;
  254. begin
  255. root:=nil;
  256. count:=0;
  257. { insert all message handlers into a tree, sorted by name }
  258. _class.symtable.foreach(@insertmsgstr,@count);
  259. { write all names }
  260. if assigned(root) then
  261. writenames(root);
  262. { now start writing of the message string table }
  263. objectlibrary.getdatalabel(r);
  264. asmlist[al_globals].concat(cai_align.create(const_align(sizeof(aint))));
  265. asmlist[al_globals].concat(Tai_label.Create(r));
  266. genstrmsgtab:=r;
  267. asmlist[al_globals].concat(Tai_const.Create_32bit(count));
  268. if assigned(root) then
  269. begin
  270. writestrentry(root);
  271. disposeprocdeftree(root);
  272. end;
  273. end;
  274. procedure tclassheader.writeintentry(p : pprocdeftree);
  275. begin
  276. if assigned(p^.l) then
  277. writeintentry(p^.l);
  278. { write name label }
  279. asmlist[al_globals].concat(Tai_const.Create_32bit(p^.data.messageinf.i));
  280. asmlist[al_globals].concat(Tai_const.Createname(p^.data.mangledname,AT_FUNCTION,0));
  281. if assigned(p^.r) then
  282. writeintentry(p^.r);
  283. end;
  284. function tclassheader.genintmsgtab : tasmlabel;
  285. var
  286. r : tasmlabel;
  287. count : longint;
  288. begin
  289. root:=nil;
  290. count:=0;
  291. { insert all message handlers into a tree, sorted by name }
  292. _class.symtable.foreach(@insertmsgint,@count);
  293. { now start writing of the message string table }
  294. objectlibrary.getdatalabel(r);
  295. asmlist[al_globals].concat(cai_align.create(const_align(sizeof(aint))));
  296. asmlist[al_globals].concat(Tai_label.Create(r));
  297. genintmsgtab:=r;
  298. asmlist[al_globals].concat(Tai_const.Create_32bit(count));
  299. if assigned(root) then
  300. begin
  301. writeintentry(root);
  302. disposeprocdeftree(root);
  303. end;
  304. end;
  305. {$ifdef WITHDMT}
  306. {**************************************
  307. DMT
  308. **************************************}
  309. procedure tclassheader.insertdmtentry(p : tnamedindexitem;arg:pointer);
  310. var
  311. hp : tprocdef;
  312. pt : pprocdeftree;
  313. begin
  314. if tsym(p).typ=procsym then
  315. begin
  316. hp:=tprocsym(p).definition;
  317. while assigned(hp) do
  318. begin
  319. if (po_msgint in hp.procoptions) then
  320. begin
  321. new(pt);
  322. pt^.p:=hp;
  323. pt^.l:=nil;
  324. pt^.r:=nil;
  325. insertint(pt,root);
  326. end;
  327. hp:=hp.nextoverloaded;
  328. end;
  329. end;
  330. end;
  331. procedure tclassheader.writedmtindexentry(p : pprocdeftree);
  332. begin
  333. if assigned(p^.l) then
  334. writedmtindexentry(p^.l);
  335. al_globals.concat(Tai_const.Create_32bit(p^.data.messageinf.i));
  336. if assigned(p^.r) then
  337. writedmtindexentry(p^.r);
  338. end;
  339. procedure tclassheader.writedmtaddressentry(p : pprocdeftree);
  340. begin
  341. if assigned(p^.l) then
  342. writedmtaddressentry(p^.l);
  343. al_globals.concat(Tai_const_symbol.Createname(p^.data.mangledname,AT_FUNCTION,0));
  344. if assigned(p^.r) then
  345. writedmtaddressentry(p^.r);
  346. end;
  347. function tclassheader.gendmt : tasmlabel;
  348. var
  349. r : tasmlabel;
  350. begin
  351. root:=nil;
  352. count:=0;
  353. gendmt:=nil;
  354. { insert all message handlers into a tree, sorted by number }
  355. _class.symtable.foreach(insertdmtentry);
  356. if count>0 then
  357. begin
  358. objectlibrary.getdatalabel(r);
  359. gendmt:=r;
  360. al_globals.concat(cai_align.create(const_align(sizeof(aint))));
  361. al_globals.concat(Tai_label.Create(r));
  362. { entries for caching }
  363. al_globals.concat(Tai_const.Create_ptr(0));
  364. al_globals.concat(Tai_const.Create_ptr(0));
  365. al_globals.concat(Tai_const.Create_32bit(count));
  366. if assigned(root) then
  367. begin
  368. writedmtindexentry(root);
  369. writedmtaddressentry(root);
  370. disposeprocdeftree(root);
  371. end;
  372. end;
  373. end;
  374. {$endif WITHDMT}
  375. {**************************************
  376. Published Methods
  377. **************************************}
  378. procedure tclassheader.do_count_published_methods(p : tnamedindexitem;arg:pointer);
  379. var
  380. i : longint;
  381. pd : tprocdef;
  382. begin
  383. if (tsym(p).typ=procsym) then
  384. begin
  385. for i:=1 to tprocsym(p).procdef_count do
  386. begin
  387. pd:=tprocsym(p).procdef[i];
  388. if (pd.procsym=tsym(p)) and
  389. (sp_published in pd.symoptions) then
  390. inc(plongint(arg)^);
  391. end;
  392. end;
  393. end;
  394. procedure tclassheader.do_gen_published_methods(p : tnamedindexitem;arg:pointer);
  395. var
  396. i : longint;
  397. l : tasmlabel;
  398. pd : tprocdef;
  399. begin
  400. if (tsym(p).typ=procsym) then
  401. begin
  402. for i:=1 to tprocsym(p).procdef_count do
  403. begin
  404. pd:=tprocsym(p).procdef[i];
  405. if (pd.procsym=tsym(p)) and
  406. (sp_published in pd.symoptions) then
  407. begin
  408. objectlibrary.getdatalabel(l);
  409. asmlist[al_typedconsts].concat(cai_align.create(const_align(sizeof(aint))));
  410. asmlist[al_typedconsts].concat(Tai_label.Create(l));
  411. asmlist[al_typedconsts].concat(Tai_const.Create_8bit(length(tsym(p).realname)));
  412. asmlist[al_typedconsts].concat(Tai_string.Create(tsym(p).realname));
  413. asmlist[al_globals].concat(Tai_const.Create_sym(l));
  414. if po_abstractmethod in pd.procoptions then
  415. asmlist[al_globals].concat(Tai_const.Create_sym(nil))
  416. else
  417. asmlist[al_globals].concat(Tai_const.Createname(pd.mangledname,AT_FUNCTION,0));
  418. end;
  419. end;
  420. end;
  421. end;
  422. function tclassheader.genpublishedmethodstable : tasmlabel;
  423. var
  424. l : tasmlabel;
  425. count : longint;
  426. begin
  427. count:=0;
  428. _class.symtable.foreach(@do_count_published_methods,@count);
  429. if count>0 then
  430. begin
  431. objectlibrary.getdatalabel(l);
  432. asmlist[al_globals].concat(cai_align.create(const_align(sizeof(aint))));
  433. asmlist[al_globals].concat(Tai_label.Create(l));
  434. asmlist[al_globals].concat(Tai_const.Create_32bit(count));
  435. _class.symtable.foreach(@do_gen_published_methods,nil);
  436. genpublishedmethodstable:=l;
  437. end
  438. else
  439. genpublishedmethodstable:=nil;
  440. end;
  441. {**************************************
  442. VMT
  443. **************************************}
  444. procedure tclassheader.newdefentry(vmtentry:pvmtentry;pd:tprocdef;is_visible:boolean);
  445. var
  446. procdefcoll : pprocdefcoll;
  447. begin
  448. if (_class=pd._class) then
  449. begin
  450. { new entry is needed, override was not possible }
  451. if (po_overridingmethod in pd.procoptions) then
  452. MessagePos1(pd.fileinfo,parser_e_nothing_to_be_overridden,pd.fullprocname(false));
  453. { check that all methods have overload directive }
  454. if not(m_fpc in aktmodeswitches) then
  455. begin
  456. procdefcoll:=vmtentry^.firstprocdef;
  457. while assigned(procdefcoll) do
  458. begin
  459. if (procdefcoll^.data._class=pd._class) and
  460. ((po_overload in pd.procoptions)<>(po_overload in procdefcoll^.data.procoptions)) then
  461. begin
  462. MessagePos1(pd.fileinfo,parser_e_no_overload_for_all_procs,pd.procsym.realname);
  463. { recover }
  464. include(procdefcoll^.data.procoptions,po_overload);
  465. include(pd.procoptions,po_overload);
  466. end;
  467. procdefcoll:=procdefcoll^.next;
  468. end;
  469. end;
  470. end;
  471. { generate new entry }
  472. new(procdefcoll);
  473. procdefcoll^.data:=pd;
  474. procdefcoll^.hidden:=false;
  475. procdefcoll^.visible:=is_visible;
  476. procdefcoll^.next:=vmtentry^.firstprocdef;
  477. vmtentry^.firstprocdef:=procdefcoll;
  478. { give virtual method a number }
  479. if (po_virtualmethod in pd.procoptions) then
  480. begin
  481. pd.extnumber:=nextvirtnumber;
  482. inc(nextvirtnumber);
  483. has_virtual_method:=true;
  484. end;
  485. if (pd.proctypeoption=potype_constructor) then
  486. has_constructor:=true;
  487. end;
  488. function tclassheader.newvmtentry(sym:tprocsym):pvmtentry;
  489. begin
  490. { generate new vmtentry }
  491. new(result);
  492. result^.speedvalue:=sym.speedvalue;
  493. result^.name:=stringdup(sym.name);
  494. result^.next:=firstvmtentry;
  495. result^.firstprocdef:=nil;
  496. firstvmtentry:=result;
  497. end;
  498. procedure tclassheader.eachsym(sym : tnamedindexitem;arg:pointer);
  499. const
  500. po_comp = [po_classmethod,po_virtualmethod,po_staticmethod,po_interrupt,po_iocheck,po_msgstr,po_msgint,
  501. po_exports,po_varargs,po_explicitparaloc,po_nostackframe];
  502. label
  503. handlenextdef;
  504. var
  505. pd : tprocdef;
  506. i : cardinal;
  507. is_visible,
  508. hasoverloads,
  509. pdoverload : boolean;
  510. procdefcoll : pprocdefcoll;
  511. vmtentry : pvmtentry;
  512. _name : string;
  513. _speed : cardinal;
  514. begin
  515. if (tsym(sym).typ<>procsym) then
  516. exit;
  517. { check the current list of symbols }
  518. _name:=sym.name;
  519. _speed:=sym.speedvalue;
  520. vmtentry:=firstvmtentry;
  521. while assigned(vmtentry) do
  522. begin
  523. { does the symbol already exist in the list? First
  524. compare speedvalue before doing the string compare to
  525. speed it up a little }
  526. if (_speed=vmtentry^.speedvalue) and
  527. (_name=vmtentry^.name^) then
  528. begin
  529. hasoverloads:=(Tprocsym(sym).procdef_count>1);
  530. { walk through all defs of the symbol }
  531. for i:=1 to Tprocsym(sym).procdef_count do
  532. begin
  533. pd:=Tprocsym(sym).procdef[i];
  534. { is this procdef visible from the class that we are
  535. generating. This will be used to hide the other procdefs.
  536. When the symbol is not visible we don't hide the other
  537. procdefs, because they can be reused in the next class.
  538. The check to skip the invisible methods that are in the
  539. list is futher down in the code }
  540. is_visible:=pd.is_visible_for_object(_class);
  541. if pd.procsym=sym then
  542. begin
  543. pdoverload:=(po_overload in pd.procoptions);
  544. { compare with all stored definitions }
  545. procdefcoll:=vmtentry^.firstprocdef;
  546. while assigned(procdefcoll) do
  547. begin
  548. { compare only if the definition is not hidden }
  549. if not procdefcoll^.hidden then
  550. begin
  551. { check if one of the two methods has virtual }
  552. if (po_virtualmethod in procdefcoll^.data.procoptions) or
  553. (po_virtualmethod in pd.procoptions) then
  554. begin
  555. { if the current definition has no virtual then hide the
  556. old virtual if the new definition has the same arguments or
  557. when it has no overload directive and no overloads }
  558. if not(po_virtualmethod in pd.procoptions) then
  559. begin
  560. if procdefcoll^.visible and
  561. (not(pdoverload or hasoverloads) or
  562. (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal)) then
  563. begin
  564. if is_visible then
  565. procdefcoll^.hidden:=true;
  566. if (_class=pd._class) and not(po_reintroduce in pd.procoptions) then
  567. MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false));
  568. end;
  569. end
  570. { if both are virtual we check the header }
  571. else if (po_virtualmethod in pd.procoptions) and
  572. (po_virtualmethod in procdefcoll^.data.procoptions) then
  573. begin
  574. { new one has not override }
  575. if is_class(_class) and
  576. not(po_overridingmethod in pd.procoptions) then
  577. begin
  578. { we start a new virtual tree, hide the old }
  579. if (not(pdoverload or hasoverloads) or
  580. (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal)) and
  581. (procdefcoll^.visible) then
  582. begin
  583. if is_visible then
  584. procdefcoll^.hidden:=true;
  585. if (_class=pd._class) and not(po_reintroduce in pd.procoptions) then
  586. MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false));
  587. end;
  588. end
  589. { same parameters }
  590. else if (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal) then
  591. begin
  592. { overload is inherited }
  593. if (po_overload in procdefcoll^.data.procoptions) then
  594. include(pd.procoptions,po_overload);
  595. { inherite calling convention when it was force and the
  596. current definition has none force }
  597. if (po_hascallingconvention in procdefcoll^.data.procoptions) and
  598. not(po_hascallingconvention in pd.procoptions) then
  599. begin
  600. pd.proccalloption:=procdefcoll^.data.proccalloption;
  601. include(pd.procoptions,po_hascallingconvention);
  602. end;
  603. { the flags have to match except abstract and override }
  604. { only if both are virtual !! }
  605. if (procdefcoll^.data.proccalloption<>pd.proccalloption) or
  606. (procdefcoll^.data.proctypeoption<>pd.proctypeoption) or
  607. ((procdefcoll^.data.procoptions*po_comp)<>(pd.procoptions*po_comp)) then
  608. begin
  609. MessagePos1(pd.fileinfo,parser_e_header_dont_match_forward,pd.fullprocname(false));
  610. tprocsym(procdefcoll^.data.procsym).write_parameter_lists(pd);
  611. end;
  612. { error, if the return types aren't equal }
  613. if not(equal_defs(procdefcoll^.data.rettype.def,pd.rettype.def)) and
  614. not((procdefcoll^.data.rettype.def.deftype=objectdef) and
  615. (pd.rettype.def.deftype=objectdef) and
  616. is_class(procdefcoll^.data.rettype.def) and
  617. is_class(pd.rettype.def) and
  618. (tobjectdef(pd.rettype.def).is_related(
  619. tobjectdef(procdefcoll^.data.rettype.def)))) then
  620. Message2(parser_e_overridden_methods_not_same_ret,pd.fullprocname(false),
  621. procdefcoll^.data.fullprocname(false));
  622. { check if the method to override is visible, check is only needed
  623. for the current parsed class. Parent classes are already validated and
  624. need to include all virtual methods including the ones not visible in the
  625. current class }
  626. if (_class=pd._class) and
  627. (po_overridingmethod in pd.procoptions) and
  628. (not procdefcoll^.visible) then
  629. MessagePos1(pd.fileinfo,parser_e_nothing_to_be_overridden,pd.fullprocname(false));
  630. { override old virtual method in VMT }
  631. pd.extnumber:=procdefcoll^.data.extnumber;
  632. procdefcoll^.data:=pd;
  633. if is_visible then
  634. procdefcoll^.visible:=true;
  635. goto handlenextdef;
  636. end
  637. { different parameters }
  638. else
  639. begin
  640. { when we got an override directive then can search futher for
  641. the procedure to override.
  642. If we are starting a new virtual tree then hide the old tree }
  643. if not(po_overridingmethod in pd.procoptions) and
  644. not pdoverload then
  645. begin
  646. if is_visible then
  647. procdefcoll^.hidden:=true;
  648. if (_class=pd._class) and not(po_reintroduce in pd.procoptions) then
  649. MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false));
  650. end;
  651. end;
  652. end
  653. else
  654. begin
  655. { the new definition is virtual and the old static, we hide the old one
  656. if the new defintion has not the overload directive }
  657. if is_visible and
  658. ((not(pdoverload or hasoverloads)) or
  659. (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal)) then
  660. procdefcoll^.hidden:=true;
  661. end;
  662. end
  663. else
  664. begin
  665. { both are static, we hide the old one if the new defintion
  666. has not the overload directive }
  667. if is_visible and
  668. ((not pdoverload) or
  669. (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal)) then
  670. procdefcoll^.hidden:=true;
  671. end;
  672. end; { not hidden }
  673. procdefcoll:=procdefcoll^.next;
  674. end;
  675. { if it isn't saved in the list we create a new entry }
  676. newdefentry(vmtentry,pd,is_visible);
  677. end;
  678. handlenextdef:
  679. end;
  680. exit;
  681. end;
  682. vmtentry:=vmtentry^.next;
  683. end;
  684. { Generate new procsym entry in vmt }
  685. vmtentry:=newvmtentry(tprocsym(sym));
  686. { Add procdefs }
  687. for i:=1 to Tprocsym(sym).procdef_count do
  688. begin
  689. pd:=Tprocsym(sym).procdef[i];
  690. newdefentry(vmtentry,pd,pd.is_visible_for_object(_class));
  691. end;
  692. end;
  693. procedure tclassheader.disposevmttree;
  694. var
  695. vmtentry : pvmtentry;
  696. procdefcoll : pprocdefcoll;
  697. begin
  698. { disposes the above generated tree }
  699. vmtentry:=firstvmtentry;
  700. while assigned(vmtentry) do
  701. begin
  702. firstvmtentry:=vmtentry^.next;
  703. stringdispose(vmtentry^.name);
  704. procdefcoll:=vmtentry^.firstprocdef;
  705. while assigned(procdefcoll) do
  706. begin
  707. vmtentry^.firstprocdef:=procdefcoll^.next;
  708. dispose(procdefcoll);
  709. procdefcoll:=vmtentry^.firstprocdef;
  710. end;
  711. dispose(vmtentry);
  712. vmtentry:=firstvmtentry;
  713. end;
  714. end;
  715. procedure tclassheader.genvmt;
  716. procedure do_genvmt(p : tobjectdef);
  717. begin
  718. { start with the base class }
  719. if assigned(p.childof) then
  720. do_genvmt(p.childof);
  721. { walk through all public syms }
  722. p.symtable.foreach(@eachsym,nil);
  723. end;
  724. begin
  725. firstvmtentry:=nil;
  726. nextvirtnumber:=0;
  727. has_constructor:=false;
  728. has_virtual_method:=false;
  729. { generates a tree of all used methods }
  730. do_genvmt(_class);
  731. if not(is_interface(_class)) and
  732. has_virtual_method and
  733. not(has_constructor) then
  734. Message1(parser_w_virtual_without_constructor,_class.objrealname^);
  735. end;
  736. {**************************************
  737. Interface tables
  738. **************************************}
  739. function tclassheader.gintfgetvtbllabelname(intfindex: integer): string;
  740. begin
  741. gintfgetvtbllabelname:=make_mangledname('VTBL',_class.owner,_class.objname^+
  742. '_$_'+_class.implementedinterfaces.interfaces(intfindex).objname^);
  743. end;
  744. procedure tclassheader.gintfcreatevtbl(intfindex: integer; rawdata: TAAsmoutput);
  745. var
  746. implintf: timplementedinterfaces;
  747. curintf: tobjectdef;
  748. proccount: integer;
  749. tmps: string;
  750. i: longint;
  751. begin
  752. implintf:=_class.implementedinterfaces;
  753. curintf:=implintf.interfaces(intfindex);
  754. section_symbol_start(rawdata,gintfgetvtbllabelname(intfindex),AT_DATA,true,sec_data,const_align(sizeof(aint)));
  755. proccount:=implintf.implproccount(intfindex);
  756. for i:=1 to proccount do
  757. begin
  758. tmps:=make_mangledname('WRPR',_class.owner,_class.objname^+'_$_'+curintf.objname^+'_$_'+
  759. tostr(i)+'_$_'+
  760. implintf.implprocs(intfindex,i).mangledname);
  761. { create reference }
  762. rawdata.concat(Tai_const.Createname(tmps,AT_FUNCTION,0));
  763. end;
  764. section_symbol_end(rawdata,gintfgetvtbllabelname(intfindex));
  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(cai_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. asmlist[al_globals].concat(Tai_const.Create_sym(tmplabel));
  788. end
  789. else
  790. begin
  791. { nil for Corba interfaces }
  792. asmlist[al_globals].concat(Tai_const.Create_sym(nil));
  793. end;
  794. { VTable }
  795. asmlist[al_globals].concat(Tai_const.Createname(gintfgetvtbllabelname(contintfindex),AT_DATA,0));
  796. { IOffset field }
  797. asmlist[al_globals].concat(Tai_const.Create_32bit(implintf.ioffsets(contintfindex)));
  798. { IIDStr }
  799. objectlibrary.getdatalabel(tmplabel);
  800. rawdata.concat(cai_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. asmlist[al_globals].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. asmlist[al_globals].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. asmlist[al_globals].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_virtualmethod])*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. mappedname: string;
  980. nextexist: pointer;
  981. implprocdef: tprocdef;
  982. begin
  983. def:=tdef(intf.symtable.defindex.first);
  984. while assigned(def) do
  985. begin
  986. if def.deftype=procdef then
  987. begin
  988. implprocdef:=nil;
  989. nextexist:=nil;
  990. repeat
  991. mappedname:=_class.implementedinterfaces.getmappings(intfindex,tprocdef(def).procsym.name,nextexist);
  992. if mappedname<>'' then
  993. implprocdef:=gintfgetcprocdef(tprocdef(def),mappedname);
  994. until assigned(implprocdef) or not assigned(nextexist);
  995. if not assigned(implprocdef) then
  996. implprocdef:=gintfgetcprocdef(tprocdef(def),tprocdef(def).procsym.name);
  997. if assigned(implprocdef) then
  998. _class.implementedinterfaces.addimplproc(intfindex,implprocdef)
  999. else
  1000. Message1(sym_e_no_matching_implementation_found,tprocdef(def).fullprocname(false));
  1001. end;
  1002. def:=tdef(def.indexnext);
  1003. end;
  1004. end;
  1005. procedure tclassheader.gintfwalkdowninterface(intf: tobjectdef; intfindex: longint);
  1006. begin
  1007. if assigned(intf.childof) then
  1008. gintfwalkdowninterface(intf.childof,intfindex);
  1009. gintfdoonintf(intf,intfindex);
  1010. end;
  1011. function tclassheader.genintftable: tasmlabel;
  1012. var
  1013. intfindex: longint;
  1014. curintf: tobjectdef;
  1015. intftable: tasmlabel;
  1016. begin
  1017. { 1. step collect implementor functions into the implementedinterfaces.implprocs }
  1018. for intfindex:=1 to _class.implementedinterfaces.count do
  1019. begin
  1020. curintf:=_class.implementedinterfaces.interfaces(intfindex);
  1021. gintfwalkdowninterface(curintf,intfindex);
  1022. end;
  1023. { 2. step calc required fieldcount and their offsets in the object memory map
  1024. and write data }
  1025. objectlibrary.getdatalabel(intftable);
  1026. asmlist[al_globals].concat(cai_align.create(const_align(sizeof(aint))));
  1027. asmlist[al_globals].concat(Tai_label.Create(intftable));
  1028. { Optimize interface tables to reuse wrappers }
  1029. gintfoptimizevtbls;
  1030. { Write interface tables }
  1031. gintfwritedata;
  1032. genintftable:=intftable;
  1033. end;
  1034. { Write interface identifiers to the data section }
  1035. procedure tclassheader.writeinterfaceids;
  1036. var
  1037. i : longint;
  1038. s : string;
  1039. begin
  1040. if assigned(_class.iidguid) then
  1041. begin
  1042. s:=make_mangledname('IID',_class.owner,_class.objname^);
  1043. maybe_new_object_file(asmlist[al_globals]);
  1044. new_section(asmlist[al_globals],sec_rodata,s,const_align(sizeof(aint)));
  1045. asmlist[al_globals].concat(Tai_symbol.Createname_global(s,AT_DATA,0));
  1046. asmlist[al_globals].concat(Tai_const.Create_32bit(longint(_class.iidguid^.D1)));
  1047. asmlist[al_globals].concat(Tai_const.Create_16bit(_class.iidguid^.D2));
  1048. asmlist[al_globals].concat(Tai_const.Create_16bit(_class.iidguid^.D3));
  1049. for i:=Low(_class.iidguid^.D4) to High(_class.iidguid^.D4) do
  1050. asmlist[al_globals].concat(Tai_const.Create_8bit(_class.iidguid^.D4[i]));
  1051. end;
  1052. maybe_new_object_file(asmlist[al_globals]);
  1053. s:=make_mangledname('IIDSTR',_class.owner,_class.objname^);
  1054. new_section(asmlist[al_globals],sec_rodata,s,0);
  1055. asmlist[al_globals].concat(Tai_symbol.Createname_global(s,AT_DATA,0));
  1056. asmlist[al_globals].concat(Tai_const.Create_8bit(length(_class.iidstr^)));
  1057. asmlist[al_globals].concat(Tai_string.Create(_class.iidstr^));
  1058. end;
  1059. procedure tclassheader.writevirtualmethods(List:TAAsmoutput);
  1060. var
  1061. vmtentry : pvmtentry;
  1062. procdefcoll : pprocdefcoll;
  1063. i : longint;
  1064. begin
  1065. { walk trough all numbers for virtual methods and search }
  1066. { the method }
  1067. for i:=0 to nextvirtnumber-1 do
  1068. begin
  1069. { walk trough all symbols }
  1070. vmtentry:=firstvmtentry;
  1071. while assigned(vmtentry) do
  1072. begin
  1073. { walk trough all methods }
  1074. procdefcoll:=vmtentry^.firstprocdef;
  1075. while assigned(procdefcoll) do
  1076. begin
  1077. { writes the addresses to the VMT }
  1078. { but only this which are declared as virtual }
  1079. if procdefcoll^.data.extnumber=i then
  1080. begin
  1081. if (po_virtualmethod in procdefcoll^.data.procoptions) then
  1082. begin
  1083. { if a method is abstract, then is also the }
  1084. { class abstract and it's not allow to }
  1085. { generates an instance }
  1086. if (po_abstractmethod in procdefcoll^.data.procoptions) then
  1087. List.concat(Tai_const.Createname('FPC_ABSTRACTERROR',AT_FUNCTION,0))
  1088. else
  1089. List.concat(Tai_const.createname(procdefcoll^.data.mangledname,AT_FUNCTION,0));
  1090. end;
  1091. end;
  1092. procdefcoll:=procdefcoll^.next;
  1093. end;
  1094. vmtentry:=vmtentry^.next;
  1095. end;
  1096. end;
  1097. end;
  1098. { generates the vmt for classes as well as for objects }
  1099. procedure tclassheader.writevmt;
  1100. var
  1101. methodnametable,intmessagetable,
  1102. strmessagetable,classnamelabel,
  1103. fieldtablelabel : tasmlabel;
  1104. {$ifdef WITHDMT}
  1105. dmtlabel : tasmlabel;
  1106. {$endif WITHDMT}
  1107. interfacetable : tasmlabel;
  1108. begin
  1109. {$ifdef WITHDMT}
  1110. dmtlabel:=gendmt;
  1111. {$endif WITHDMT}
  1112. { write tables for classes, this must be done before the actual
  1113. class is written, because we need the labels defined }
  1114. if is_class(_class) then
  1115. begin
  1116. objectlibrary.getdatalabel(classnamelabel);
  1117. maybe_new_object_file(asmlist[al_globals]);
  1118. new_section(asmlist[al_globals],sec_rodata,classnamelabel.name,const_align(sizeof(aint)));
  1119. { interface table }
  1120. if _class.implementedinterfaces.count>0 then
  1121. interfacetable:=genintftable;
  1122. methodnametable:=genpublishedmethodstable;
  1123. fieldtablelabel:=_class.generate_field_table;
  1124. { write class name }
  1125. asmlist[al_globals].concat(Tai_label.Create(classnamelabel));
  1126. asmlist[al_globals].concat(Tai_const.Create_8bit(length(_class.objrealname^)));
  1127. asmlist[al_globals].concat(Tai_string.Create(_class.objrealname^));
  1128. { generate message and dynamic tables }
  1129. if (oo_has_msgstr in _class.objectoptions) then
  1130. strmessagetable:=genstrmsgtab;
  1131. if (oo_has_msgint in _class.objectoptions) then
  1132. intmessagetable:=genintmsgtab;
  1133. end;
  1134. { write debug info }
  1135. maybe_new_object_file(asmlist[al_globals]);
  1136. new_section(asmlist[al_globals],sec_rodata,_class.vmt_mangledname,const_align(sizeof(aint)));
  1137. {$ifdef GDB}
  1138. if (cs_debuginfo in aktmoduleswitches) then
  1139. begin
  1140. do_count_dbx:=true;
  1141. if assigned(_class.owner) and assigned(_class.owner.name) then
  1142. asmlist[al_globals].concat(Tai_stabs.Create(strpnew('"vmt_'+_class.owner.name^+_class.name+':S'+
  1143. tstoreddef(vmttype.def).numberstring+'",'+tostr(N_STSYM)+',0,0,'+_class.vmt_mangledname)));
  1144. end;
  1145. {$endif GDB}
  1146. asmlist[al_globals].concat(Tai_symbol.Createname_global(_class.vmt_mangledname,AT_DATA,0));
  1147. { determine the size with symtable.datasize, because }
  1148. { size gives back 4 for classes }
  1149. asmlist[al_globals].concat(Tai_const.Create(ait_const_ptr,tobjectsymtable(_class.symtable).datasize));
  1150. asmlist[al_globals].concat(Tai_const.Create(ait_const_ptr,-int64(tobjectsymtable(_class.symtable).datasize)));
  1151. {$ifdef WITHDMT}
  1152. if _class.classtype=ct_object then
  1153. begin
  1154. if assigned(dmtlabel) then
  1155. asmlist[al_globals].concat(Tai_const_symbol.Create(dmtlabel)))
  1156. else
  1157. asmlist[al_globals].concat(Tai_const.Create_ptr(0));
  1158. end;
  1159. {$endif WITHDMT}
  1160. { write pointer to parent VMT, this isn't implemented in TP }
  1161. { but this is not used in FPC ? (PM) }
  1162. { it's not used yet, but the delphi-operators as and is need it (FK) }
  1163. { it is not written for parents that don't have any vmt !! }
  1164. if assigned(_class.childof) and
  1165. (oo_has_vmt in _class.childof.objectoptions) then
  1166. asmlist[al_globals].concat(Tai_const.Createname(_class.childof.vmt_mangledname,AT_DATA,0))
  1167. else
  1168. asmlist[al_globals].concat(Tai_const.Create_sym(nil));
  1169. { write extended info for classes, for the order see rtl/inc/objpash.inc }
  1170. if is_class(_class) then
  1171. begin
  1172. { pointer to class name string }
  1173. asmlist[al_globals].concat(Tai_const.Create_sym(classnamelabel));
  1174. { pointer to dynamic table or nil }
  1175. if (oo_has_msgint in _class.objectoptions) then
  1176. asmlist[al_globals].concat(Tai_const.Create_sym(intmessagetable))
  1177. else
  1178. asmlist[al_globals].concat(Tai_const.Create_sym(nil));
  1179. { pointer to method table or nil }
  1180. asmlist[al_globals].concat(Tai_const.Create_sym(methodnametable));
  1181. { pointer to field table }
  1182. asmlist[al_globals].concat(Tai_const.Create_sym(fieldtablelabel));
  1183. { pointer to type info of published section }
  1184. if (oo_can_have_published in _class.objectoptions) then
  1185. asmlist[al_globals].concat(Tai_const.Create_sym(_class.get_rtti_label(fullrtti)))
  1186. else
  1187. asmlist[al_globals].concat(Tai_const.Create_sym(nil));
  1188. { inittable for con-/destruction }
  1189. if _class.members_need_inittable then
  1190. asmlist[al_globals].concat(Tai_const.Create_sym(_class.get_rtti_label(initrtti)))
  1191. else
  1192. asmlist[al_globals].concat(Tai_const.Create_sym(nil));
  1193. { auto table }
  1194. asmlist[al_globals].concat(Tai_const.Create_sym(nil));
  1195. { interface table }
  1196. if _class.implementedinterfaces.count>0 then
  1197. asmlist[al_globals].concat(Tai_const.Create_sym(interfacetable))
  1198. else
  1199. asmlist[al_globals].concat(Tai_const.Create_sym(nil));
  1200. { table for string messages }
  1201. if (oo_has_msgstr in _class.objectoptions) then
  1202. asmlist[al_globals].concat(Tai_const.Create_sym(strmessagetable))
  1203. else
  1204. asmlist[al_globals].concat(Tai_const.Create_sym(nil));
  1205. end;
  1206. { write virtual methods }
  1207. writevirtualmethods(asmlist[al_globals]);
  1208. asmlist[al_globals].concat(Tai_const.create(ait_const_ptr,0));
  1209. { write the size of the VMT }
  1210. asmlist[al_globals].concat(Tai_symbol_end.Createname(_class.vmt_mangledname));
  1211. end;
  1212. end.