nobj.pas 55 KB

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