nobj.pas 52 KB

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