nobj.pas 56 KB

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