nobj.pas 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426
  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,cpuinfo,
  24. symdef,aasmbase,aasmtai,aasmcpu,globtype
  25. {$ifdef Delphi}
  26. ,dmisc
  27. {$endif}
  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. next : pprocdefcoll;
  41. end;
  42. psymcoll = ^tsymcoll;
  43. tsymcoll = record
  44. speedvalue : cardinal;
  45. name : pstring;
  46. data : pprocdefcoll;
  47. next : psymcoll;
  48. end;
  49. tclassheader=class
  50. private
  51. _Class : tobjectdef;
  52. count : integer;
  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);
  60. procedure insertstr(p : pprocdeftree;var at : pprocdeftree);
  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(p : tnamedindexitem;arg:pointer);
  74. procedure genpubmethodtableentry(p : tnamedindexitem;arg:pointer);
  75. private
  76. { vmt }
  77. wurzel : psymcoll;
  78. nextvirtnumber : integer;
  79. has_constructor,
  80. has_virtual_method : boolean;
  81. procedure eachsym(sym : tnamedindexitem;arg:pointer);
  82. procedure disposevmttree;
  83. procedure writevirtualmethods(List:TAAsmoutput);
  84. private
  85. { interface tables }
  86. function gintfgetvtbllabelname(intfindex: integer): string;
  87. procedure gintfcreatevtbl(intfindex: integer; rawdata,rawcode: TAAsmoutput);
  88. procedure gintfgenentry(intfindex, contintfindex: integer; rawdata: TAAsmoutput);
  89. procedure gintfoptimizevtbls(implvtbl : plongintarray);
  90. procedure gintfwritedata;
  91. function gintfgetcprocdef(proc: tprocdef;const name: string): tprocdef;
  92. procedure gintfdoonintf(intf: tobjectdef; intfindex: longint);
  93. procedure gintfwalkdowninterface(intf: tobjectdef; intfindex: longint);
  94. protected
  95. { adjusts the self value with ioffset when casting a interface
  96. to a class
  97. }
  98. procedure adjustselfvalue(procdef: tprocdef;ioffset: aword);virtual;
  99. { generates the wrapper for a call to a method via an interface }
  100. procedure cgintfwrapper(asmlist: TAAsmoutput; procdef: tprocdef; const labelname: string; ioffset: longint);virtual;abstract;
  101. public
  102. constructor create(c:tobjectdef);
  103. destructor destroy;override;
  104. { generates the message tables for a class }
  105. function genstrmsgtab : tasmlabel;
  106. function genintmsgtab : tasmlabel;
  107. function genpublishedmethodstable : tasmlabel;
  108. { generates a VMT entries }
  109. procedure genvmt;
  110. {$ifdef WITHDMT}
  111. { generates a DMT for _class }
  112. function gendmt : tasmlabel;
  113. {$endif WITHDMT}
  114. { interfaces }
  115. function genintftable: tasmlabel;
  116. { write the VMT to datasegment }
  117. procedure writevmt;
  118. procedure writeinterfaceids;
  119. end;
  120. tclassheaderclass=class of tclassheader;
  121. var
  122. cclassheader : tclassheaderclass;
  123. implementation
  124. uses
  125. {$ifdef delphi}
  126. sysutils,
  127. {$else}
  128. strings,
  129. {$endif}
  130. globals,verbose,
  131. symtable,symconst,symtype,symsym,defbase,paramgr,
  132. {$ifdef GDB}
  133. gdb,
  134. {$endif GDB}
  135. cpubase,cgbase,cginfo,cgobj,rgobj
  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);
  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)
  171. else if p^.data.messageinf.i>at^.data.messageinf.i then
  172. insertint(p,at^.r)
  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);
  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)
  191. else if i>0 then
  192. insertstr(p,at^.r)
  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);
  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_msgint 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);
  234. end;
  235. end;
  236. end;
  237. procedure tclassheader.writenames(p : pprocdeftree);
  238. begin
  239. objectlibrary.getdatalabel(p^.nl);
  240. if assigned(p^.l) then
  241. writenames(p^.l);
  242. dataSegment.concat(Tai_label.Create(p^.nl));
  243. dataSegment.concat(Tai_const.Create_8bit(strlen(p^.data.messageinf.str)));
  244. dataSegment.concat(Tai_string.Create_pchar(p^.data.messageinf.str));
  245. if assigned(p^.r) then
  246. writenames(p^.r);
  247. end;
  248. procedure tclassheader.writestrentry(p : pprocdeftree);
  249. begin
  250. if assigned(p^.l) then
  251. writestrentry(p^.l);
  252. { write name label }
  253. dataSegment.concat(Tai_const_symbol.Create(p^.nl));
  254. dataSegment.concat(Tai_const_symbol.Createname(p^.data.mangledname));
  255. if assigned(p^.r) then
  256. writestrentry(p^.r);
  257. end;
  258. function tclassheader.genstrmsgtab : tasmlabel;
  259. var
  260. r : tasmlabel;
  261. begin
  262. root:=nil;
  263. count:=0;
  264. { insert all message handlers into a tree, sorted by name }
  265. _class.symtable.foreach({$ifdef FPCPROCVAR}@{$endif}insertmsgstr,nil);
  266. { write all names }
  267. if assigned(root) then
  268. writenames(root);
  269. { now start writing of the message string table }
  270. objectlibrary.getdatalabel(r);
  271. dataSegment.concat(Tai_label.Create(r));
  272. genstrmsgtab:=r;
  273. dataSegment.concat(Tai_const.Create_32bit(count));
  274. if assigned(root) then
  275. begin
  276. writestrentry(root);
  277. disposeprocdeftree(root);
  278. end;
  279. end;
  280. procedure tclassheader.writeintentry(p : pprocdeftree);
  281. begin
  282. if assigned(p^.l) then
  283. writeintentry(p^.l);
  284. { write name label }
  285. dataSegment.concat(Tai_const.Create_32bit(p^.data.messageinf.i));
  286. dataSegment.concat(Tai_const_symbol.Createname(p^.data.mangledname));
  287. if assigned(p^.r) then
  288. writeintentry(p^.r);
  289. end;
  290. function tclassheader.genintmsgtab : tasmlabel;
  291. var
  292. r : tasmlabel;
  293. begin
  294. root:=nil;
  295. count:=0;
  296. { insert all message handlers into a tree, sorted by name }
  297. _class.symtable.foreach({$ifdef FPCPROCVAR}@{$endif}insertmsgint,nil);
  298. { now start writing of the message string table }
  299. objectlibrary.getdatalabel(r);
  300. dataSegment.concat(Tai_label.Create(r));
  301. genintmsgtab:=r;
  302. dataSegment.concat(Tai_const.Create_32bit(count));
  303. if assigned(root) then
  304. begin
  305. writeintentry(root);
  306. disposeprocdeftree(root);
  307. end;
  308. end;
  309. {$ifdef WITHDMT}
  310. {**************************************
  311. DMT
  312. **************************************}
  313. procedure tclassheader.insertdmtentry(p : tnamedindexitem;arg:pointer);
  314. var
  315. hp : tprocdef;
  316. pt : pprocdeftree;
  317. begin
  318. if tsym(p).typ=procsym then
  319. begin
  320. hp:=tprocsym(p).definition;
  321. while assigned(hp) do
  322. begin
  323. if (po_msgint in hp.procoptions) then
  324. begin
  325. new(pt);
  326. pt^.p:=hp;
  327. pt^.l:=nil;
  328. pt^.r:=nil;
  329. insertint(pt,root);
  330. end;
  331. hp:=hp.nextoverloaded;
  332. end;
  333. end;
  334. end;
  335. procedure tclassheader.writedmtindexentry(p : pprocdeftree);
  336. begin
  337. if assigned(p^.l) then
  338. writedmtindexentry(p^.l);
  339. dataSegment.concat(Tai_const.Create_32bit(p^.data.messageinf.i));
  340. if assigned(p^.r) then
  341. writedmtindexentry(p^.r);
  342. end;
  343. procedure tclassheader.writedmtaddressentry(p : pprocdeftree);
  344. begin
  345. if assigned(p^.l) then
  346. writedmtaddressentry(p^.l);
  347. dataSegment.concat(Tai_const_symbol.Createname(p^.data.mangledname));
  348. if assigned(p^.r) then
  349. writedmtaddressentry(p^.r);
  350. end;
  351. function tclassheader.gendmt : tasmlabel;
  352. var
  353. r : tasmlabel;
  354. begin
  355. root:=nil;
  356. count:=0;
  357. gendmt:=nil;
  358. { insert all message handlers into a tree, sorted by number }
  359. _class.symtable.foreach({$ifdef FPCPROCVAR}@{$endif}insertdmtentry);
  360. if count>0 then
  361. begin
  362. objectlibrary.getdatalabel(r);
  363. gendmt:=r;
  364. dataSegment.concat(Tai_label.Create(r));
  365. { entries for caching }
  366. dataSegment.concat(Tai_const.Create_32bit(0));
  367. dataSegment.concat(Tai_const.Create_32bit(0));
  368. dataSegment.concat(Tai_const.Create_32bit(count));
  369. if assigned(root) then
  370. begin
  371. writedmtindexentry(root);
  372. writedmtaddressentry(root);
  373. disposeprocdeftree(root);
  374. end;
  375. end;
  376. end;
  377. {$endif WITHDMT}
  378. {**************************************
  379. Published Methods
  380. **************************************}
  381. procedure tclassheader.do_count(p : tnamedindexitem;arg:pointer);
  382. begin
  383. if (tsym(p).typ=procsym) and (sp_published in tsym(p).symoptions) then
  384. inc(count);
  385. end;
  386. procedure tclassheader.genpubmethodtableentry(p : tnamedindexitem;arg:pointer);
  387. var
  388. hp : tprocdef;
  389. l : tasmlabel;
  390. begin
  391. if (tsym(p).typ=procsym) and (sp_published in tsym(p).symoptions) then
  392. begin
  393. if Tprocsym(p).procdef_count>1 then
  394. internalerror(1209992);
  395. hp:=tprocsym(p).first_procdef;
  396. objectlibrary.getdatalabel(l);
  397. Consts.concat(Tai_label.Create(l));
  398. Consts.concat(Tai_const.Create_8bit(length(p.name)));
  399. Consts.concat(Tai_string.Create(p.name));
  400. dataSegment.concat(Tai_const_symbol.Create(l));
  401. dataSegment.concat(Tai_const_symbol.Createname(hp.mangledname));
  402. end;
  403. end;
  404. function tclassheader.genpublishedmethodstable : tasmlabel;
  405. var
  406. l : tasmlabel;
  407. begin
  408. count:=0;
  409. _class.symtable.foreach({$ifdef FPCPROCVAR}@{$endif}do_count,nil);
  410. if count>0 then
  411. begin
  412. objectlibrary.getdatalabel(l);
  413. dataSegment.concat(Tai_label.Create(l));
  414. dataSegment.concat(Tai_const.Create_32bit(count));
  415. _class.symtable.foreach({$ifdef FPCPROCVAR}@{$endif}genpubmethodtableentry,nil);
  416. genpublishedmethodstable:=l;
  417. end
  418. else
  419. genpublishedmethodstable:=nil;
  420. end;
  421. {**************************************
  422. VMT
  423. **************************************}
  424. procedure tclassheader.eachsym(sym : tnamedindexitem;arg:pointer);
  425. var
  426. procdefcoll : pprocdefcoll;
  427. hp : pprocdeflist;
  428. symcoll : psymcoll;
  429. _name : string;
  430. _speed : cardinal;
  431. procedure newdefentry(pd:tprocdef);
  432. begin
  433. new(procdefcoll);
  434. procdefcoll^.data:=pd;
  435. procdefcoll^.hidden:=false;
  436. procdefcoll^.next:=symcoll^.data;
  437. symcoll^.data:=procdefcoll;
  438. { if it's a virtual method }
  439. if (po_virtualmethod in pd.procoptions) then
  440. begin
  441. { then it gets a number ... }
  442. pd.extnumber:=nextvirtnumber;
  443. { and we inc the number }
  444. inc(nextvirtnumber);
  445. has_virtual_method:=true;
  446. end;
  447. if (pd.proctypeoption=potype_constructor) then
  448. has_constructor:=true;
  449. { check, if a method should be overridden }
  450. if (pd._class=_class) and
  451. (po_overridingmethod in pd.procoptions) then
  452. MessagePos1(pd.fileinfo,parser_e_nothing_to_be_overridden,pd.fullprocname);
  453. end;
  454. { creates a new entry in the procsym list }
  455. procedure newentry;
  456. var i:cardinal;
  457. begin
  458. { if not, generate a new symbol item }
  459. new(symcoll);
  460. symcoll^.speedvalue:=sym.speedvalue;
  461. symcoll^.name:=stringdup(sym.name);
  462. symcoll^.next:=wurzel;
  463. symcoll^.data:=nil;
  464. wurzel:=symcoll;
  465. { inserts all definitions }
  466. for i:=1 to Tprocsym(sym).procdef_count do
  467. newdefentry(Tprocsym(sym).procdef[i]);
  468. end;
  469. label
  470. handlenextdef;
  471. var
  472. pd : tprocdef;
  473. i : cardinal;
  474. is_visible,
  475. hasoverloads,
  476. pdoverload : boolean;
  477. begin
  478. { put only sub routines into the VMT, and routines
  479. that are visible to the current class. Skip private
  480. methods in other classes }
  481. if (tsym(sym).typ=procsym) then
  482. begin
  483. { is this symbol visible from the class that we are
  484. generating. This will be used to hide the other procdefs.
  485. When the symbol is not visible we don't hide the other
  486. procdefs, because they can be reused in the next class.
  487. The check to skip the invisible methods that are in the
  488. list is futher down in the code }
  489. is_visible:=tprocsym(sym).is_visible_for_object(_class);
  490. { check the current list of symbols }
  491. _name:=sym.name;
  492. _speed:=sym.speedvalue;
  493. symcoll:=wurzel;
  494. while assigned(symcoll) do
  495. begin
  496. { does the symbol already exist in the list? First
  497. compare speedvalue before doing the string compare to
  498. speed it up a little }
  499. if (_speed=symcoll^.speedvalue) and
  500. (_name=symcoll^.name^) then
  501. begin
  502. hasoverloads:=(Tprocsym(sym).procdef_count>1);
  503. { walk through all defs of the symbol }
  504. for i:=1 to Tprocsym(sym).procdef_count do
  505. begin
  506. pd:=Tprocsym(sym).procdef[i];
  507. if pd.procsym=sym then
  508. begin
  509. pdoverload:=(po_overload in pd.procoptions);
  510. { compare with all stored definitions }
  511. procdefcoll:=symcoll^.data;
  512. while assigned(procdefcoll) do
  513. begin
  514. { compare only if the definition is not hidden }
  515. if not procdefcoll^.hidden then
  516. begin
  517. { check if one of the two methods has virtual }
  518. if (po_virtualmethod in procdefcoll^.data.procoptions) or
  519. (po_virtualmethod in pd.procoptions) then
  520. begin
  521. { if the current definition has no virtual then hide the
  522. old virtual if the new definition has the same arguments or
  523. when it has no overload directive and no overloads }
  524. if not(po_virtualmethod in pd.procoptions) then
  525. begin
  526. if tstoredsym(procdefcoll^.data.procsym).is_visible_for_object(pd._class) and
  527. (not(pdoverload or hasoverloads) or
  528. equal_paras(procdefcoll^.data.para,pd.para,cp_value_equal_const,false)) then
  529. begin
  530. if is_visible then
  531. procdefcoll^.hidden:=true;
  532. if _class=pd._class then
  533. MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname);
  534. end;
  535. end
  536. { if both are virtual we check the header }
  537. else if (po_virtualmethod in pd.procoptions) and
  538. (po_virtualmethod in procdefcoll^.data.procoptions) then
  539. begin
  540. { new one has not override }
  541. if is_class(_class) and
  542. not(po_overridingmethod in pd.procoptions) then
  543. begin
  544. { we start a new virtual tree, hide the old }
  545. if (not(pdoverload or hasoverloads) or
  546. equal_paras(procdefcoll^.data.para,pd.para,cp_value_equal_const,false)) and
  547. (tstoredsym(procdefcoll^.data.procsym).is_visible_for_object(pd._class)) then
  548. begin
  549. if is_visible then
  550. procdefcoll^.hidden:=true;
  551. if _class=pd._class then
  552. MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname);
  553. end;
  554. end
  555. { check if the method to override is visible }
  556. else if (po_overridingmethod in pd.procoptions) and
  557. (not tstoredsym(procdefcoll^.data.procsym).is_visible_for_object(pd._class)) then
  558. begin
  559. { do nothing, the error will follow when adding the entry }
  560. end
  561. { same parameters }
  562. else if (equal_paras(procdefcoll^.data.para,pd.para,cp_value_equal_const,false)) then
  563. begin
  564. { overload is inherited }
  565. if (po_overload in procdefcoll^.data.procoptions) then
  566. include(pd.procoptions,po_overload);
  567. { the flags have to match except abstract and override }
  568. { only if both are virtual !! }
  569. if (procdefcoll^.data.proccalloption<>pd.proccalloption) or
  570. (procdefcoll^.data.proctypeoption<>pd.proctypeoption) or
  571. ((procdefcoll^.data.procoptions-
  572. [po_abstractmethod,po_overridingmethod,po_assembler,po_overload])<>
  573. (pd.procoptions-[po_abstractmethod,po_overridingmethod,po_assembler,po_overload])) then
  574. MessagePos1(pd.fileinfo,parser_e_header_dont_match_forward,pd.fullprocname);
  575. { error, if the return types aren't equal }
  576. if not(is_equal(procdefcoll^.data.rettype.def,pd.rettype.def)) and
  577. not((procdefcoll^.data.rettype.def.deftype=objectdef) and
  578. (pd.rettype.def.deftype=objectdef) and
  579. is_class(procdefcoll^.data.rettype.def) and
  580. is_class(pd.rettype.def) and
  581. (tobjectdef(pd.rettype.def).is_related(
  582. tobjectdef(procdefcoll^.data.rettype.def)))) then
  583. Message2(parser_e_overridden_methods_not_same_ret,pd.fullprocnamewithret,
  584. procdefcoll^.data.fullprocnamewithret);
  585. { now set the number }
  586. pd.extnumber:=procdefcoll^.data.extnumber;
  587. { and exchange }
  588. procdefcoll^.data:=pd;
  589. goto handlenextdef;
  590. end
  591. { different parameters }
  592. else
  593. begin
  594. { when we got an override directive then can search futher for
  595. the procedure to override.
  596. If we are starting a new virtual tree then hide the old tree }
  597. if not(po_overridingmethod in pd.procoptions) and
  598. not pdoverload then
  599. begin
  600. if is_visible then
  601. procdefcoll^.hidden:=true;
  602. if _class=pd._class then
  603. MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname);
  604. end;
  605. end;
  606. end
  607. else
  608. begin
  609. { the new definition is virtual and the old static, we hide the old one
  610. if the new defintion has not the overload directive }
  611. if is_visible and
  612. ((not(pdoverload or hasoverloads)) or
  613. equal_paras(procdefcoll^.data.para,pd.para,cp_value_equal_const,false)) then
  614. procdefcoll^.hidden:=true;
  615. end;
  616. end
  617. else
  618. begin
  619. { both are static, we hide the old one if the new defintion
  620. has not the overload directive }
  621. if is_visible and
  622. ((not pdoverload) or
  623. equal_paras(procdefcoll^.data.para,pd.para,cp_value_equal_const,false)) then
  624. procdefcoll^.hidden:=true;
  625. end;
  626. end; { not hidden }
  627. procdefcoll:=procdefcoll^.next;
  628. end;
  629. { if it isn't saved in the list we create a new entry }
  630. newdefentry(pd);
  631. end;
  632. handlenextdef:
  633. end;
  634. exit;
  635. end;
  636. symcoll:=symcoll^.next;
  637. end;
  638. newentry;
  639. end;
  640. end;
  641. procedure tclassheader.disposevmttree;
  642. var
  643. symcoll : psymcoll;
  644. procdefcoll : pprocdefcoll;
  645. begin
  646. { disposes the above generated tree }
  647. symcoll:=wurzel;
  648. while assigned(symcoll) do
  649. begin
  650. wurzel:=symcoll^.next;
  651. stringdispose(symcoll^.name);
  652. procdefcoll:=symcoll^.data;
  653. while assigned(procdefcoll) do
  654. begin
  655. symcoll^.data:=procdefcoll^.next;
  656. dispose(procdefcoll);
  657. procdefcoll:=symcoll^.data;
  658. end;
  659. dispose(symcoll);
  660. symcoll:=wurzel;
  661. end;
  662. end;
  663. procedure tclassheader.genvmt;
  664. procedure do_genvmt(p : tobjectdef);
  665. begin
  666. { start with the base class }
  667. if assigned(p.childof) then
  668. do_genvmt(p.childof);
  669. { walk through all public syms }
  670. p.symtable.foreach({$ifdef FPCPROCVAR}@{$endif}eachsym,nil);
  671. end;
  672. begin
  673. wurzel:=nil;
  674. nextvirtnumber:=0;
  675. has_constructor:=false;
  676. has_virtual_method:=false;
  677. { generates a tree of all used methods }
  678. do_genvmt(_class);
  679. if not(is_interface(_class)) and
  680. has_virtual_method and
  681. not(has_constructor) then
  682. Message1(parser_w_virtual_without_constructor,_class.objrealname^);
  683. end;
  684. {**************************************
  685. Interface tables
  686. **************************************}
  687. function tclassheader.gintfgetvtbllabelname(intfindex: integer): string;
  688. begin
  689. gintfgetvtbllabelname:=mangledname_prefix('VTBL',_class.owner)+_class.objname^+
  690. '_$_'+_class.implementedinterfaces.interfaces(intfindex).objname^;
  691. end;
  692. procedure tclassheader.gintfcreatevtbl(intfindex: integer; rawdata,rawcode: TAAsmoutput);
  693. var
  694. implintf: timplementedinterfaces;
  695. curintf: tobjectdef;
  696. proccount: integer;
  697. tmps: string;
  698. i: longint;
  699. begin
  700. implintf:=_class.implementedinterfaces;
  701. curintf:=implintf.interfaces(intfindex);
  702. if (cs_create_smart in aktmoduleswitches) then
  703. rawdata.concat(Tai_symbol.Createname_global(gintfgetvtbllabelname(intfindex),0))
  704. else
  705. rawdata.concat(Tai_symbol.Createname(gintfgetvtbllabelname(intfindex),0));
  706. proccount:=implintf.implproccount(intfindex);
  707. for i:=1 to proccount do
  708. begin
  709. tmps:=mangledname_prefix('WRPR',_class.owner)+_class.objname^+'_$_'+curintf.objname^+'_$_'+
  710. tostr(i)+'_$_'+
  711. implintf.implprocs(intfindex,i).mangledname;
  712. { create wrapper code }
  713. cgintfwrapper(rawcode,implintf.implprocs(intfindex,i),tmps,implintf.ioffsets(intfindex)^);
  714. { create reference }
  715. rawdata.concat(Tai_const_symbol.Createname(tmps));
  716. end;
  717. end;
  718. procedure tclassheader.gintfgenentry(intfindex, contintfindex: integer; rawdata: TAAsmoutput);
  719. var
  720. implintf: timplementedinterfaces;
  721. curintf: tobjectdef;
  722. tmplabel: tasmlabel;
  723. i: longint;
  724. begin
  725. implintf:=_class.implementedinterfaces;
  726. curintf:=implintf.interfaces(intfindex);
  727. { GUID }
  728. if curintf.objecttype in [odt_interfacecom] then
  729. begin
  730. { label for GUID }
  731. objectlibrary.getdatalabel(tmplabel);
  732. rawdata.concat(Tai_label.Create(tmplabel));
  733. rawdata.concat(Tai_const.Create_32bit(curintf.iidguid.D1));
  734. rawdata.concat(Tai_const.Create_16bit(curintf.iidguid.D2));
  735. rawdata.concat(Tai_const.Create_16bit(curintf.iidguid.D3));
  736. for i:=Low(curintf.iidguid.D4) to High(curintf.iidguid.D4) do
  737. rawdata.concat(Tai_const.Create_8bit(curintf.iidguid.D4[i]));
  738. dataSegment.concat(Tai_const_symbol.Create(tmplabel));
  739. end
  740. else
  741. begin
  742. { nil for Corba interfaces }
  743. dataSegment.concat(Tai_const.Create_32bit(0)); { nil }
  744. end;
  745. { VTable }
  746. dataSegment.concat(Tai_const_symbol.Createname(gintfgetvtbllabelname(contintfindex)));
  747. { IOffset field }
  748. dataSegment.concat(Tai_const.Create_32bit(implintf.ioffsets(contintfindex)^));
  749. { IIDStr }
  750. objectlibrary.getdatalabel(tmplabel);
  751. rawdata.concat(Tai_label.Create(tmplabel));
  752. rawdata.concat(Tai_const.Create_8bit(length(curintf.iidstr^)));
  753. if curintf.objecttype=odt_interfacecom then
  754. rawdata.concat(Tai_string.Create(upper(curintf.iidstr^)))
  755. else
  756. rawdata.concat(Tai_string.Create(curintf.iidstr^));
  757. dataSegment.concat(Tai_const_symbol.Create(tmplabel));
  758. end;
  759. procedure tclassheader.gintfoptimizevtbls(implvtbl : plongintarray);
  760. type
  761. tcompintfentry = record
  762. weight: longint;
  763. compintf: longint;
  764. end;
  765. { Max 1000 interface in the class header interfaces it's enough imho }
  766. tcompintfs = packed array[1..1000] of tcompintfentry;
  767. pcompintfs = ^tcompintfs;
  768. tequals = packed array[1..1000] of longint;
  769. pequals = ^tequals;
  770. var
  771. max: longint;
  772. equals: pequals;
  773. compats: pcompintfs;
  774. i: longint;
  775. j: longint;
  776. w: longint;
  777. cij: boolean;
  778. cji: boolean;
  779. begin
  780. max:=_class.implementedinterfaces.count;
  781. if max>High(tequals) then
  782. Internalerror(200006135);
  783. getmem(compats,sizeof(tcompintfentry)*max);
  784. getmem(equals,sizeof(longint)*max);
  785. fillchar(compats^,sizeof(tcompintfentry)*max,0);
  786. fillchar(equals^,sizeof(longint)*max,0);
  787. { ismergepossible is a containing relation
  788. meaning of ismergepossible(a,b,w) =
  789. if implementorfunction map of a is contained implementorfunction map of b
  790. imp(a,b) and imp(b,c) => imp(a,c) ; imp(a,b) and imp(b,a) => a == b
  791. }
  792. { the order is very important for correct allocation }
  793. for i:=1 to max do
  794. begin
  795. for j:=i+1 to max do
  796. begin
  797. cij:=_class.implementedinterfaces.isimplmergepossible(i,j,w);
  798. cji:=_class.implementedinterfaces.isimplmergepossible(j,i,w);
  799. if cij and cji then { i equal j }
  800. begin
  801. { get minimum index of equal }
  802. if equals^[j]=0 then
  803. equals^[j]:=i;
  804. end
  805. else if cij then
  806. begin
  807. { get minimum index of maximum weight }
  808. if compats^[i].weight<w then
  809. begin
  810. compats^[i].weight:=w;
  811. compats^[i].compintf:=j;
  812. end;
  813. end
  814. else if cji then
  815. begin
  816. { get minimum index of maximum weight }
  817. if (compats^[j].weight<w) then
  818. begin
  819. compats^[j].weight:=w;
  820. compats^[j].compintf:=i;
  821. end;
  822. end;
  823. end;
  824. end;
  825. for i:=1 to max do
  826. begin
  827. if compats^[i].compintf<>0 then
  828. implvtbl[i]:=compats^[i].compintf
  829. else if equals^[i]<>0 then
  830. implvtbl[i]:=equals^[i]
  831. else
  832. implvtbl[i]:=i;
  833. end;
  834. freemem(compats,sizeof(tcompintfentry)*max);
  835. freemem(equals,sizeof(longint)*max);
  836. end;
  837. procedure tclassheader.gintfwritedata;
  838. var
  839. rawdata,rawcode: taasmoutput;
  840. impintfindexes: plongintarray;
  841. max: longint;
  842. i: longint;
  843. begin
  844. max:=_class.implementedinterfaces.count;
  845. getmem(impintfindexes,(max+1)*sizeof(longint));
  846. gintfoptimizevtbls(impintfindexes);
  847. rawdata:=TAAsmOutput.Create;
  848. rawcode:=TAAsmOutput.Create;
  849. dataSegment.concat(Tai_const.Create_16bit(max));
  850. { Two pass, one for allocation and vtbl creation }
  851. for i:=1 to max do
  852. begin
  853. if impintfindexes[i]=i then { if implement itself }
  854. begin
  855. { allocate a pointer in the object memory }
  856. with tstoredsymtable(_class.symtable) do
  857. begin
  858. if (dataalignment>=pointer_size) then
  859. datasize:=align(datasize,dataalignment)
  860. else
  861. datasize:=align(datasize,pointer_size);
  862. _class.implementedinterfaces.ioffsets(i)^:=datasize;
  863. datasize:=datasize+pointer_size;
  864. end;
  865. { write vtbl }
  866. gintfcreatevtbl(i,rawdata,rawcode);
  867. end;
  868. end;
  869. { second pass: for fill interfacetable and remained ioffsets }
  870. for i:=1 to max do
  871. begin
  872. if i<>impintfindexes[i] then { why execute x:=x ? }
  873. with _class.implementedinterfaces do
  874. ioffsets(i)^:=ioffsets(impintfindexes[i])^;
  875. gintfgenentry(i,impintfindexes[i],rawdata);
  876. end;
  877. dataSegment.concatlist(rawdata);
  878. rawdata.free;
  879. codeSegment.concatlist(rawcode);
  880. rawcode.free;
  881. freemem(impintfindexes,(max+1)*sizeof(longint));
  882. end;
  883. function tclassheader.gintfgetcprocdef(proc: tprocdef;const name: string): tprocdef;
  884. var
  885. sym: tprocsym;
  886. implprocdef : Tprocdef;
  887. i: cardinal;
  888. begin
  889. gintfgetcprocdef:=nil;
  890. sym:=tprocsym(search_class_member(_class,name));
  891. if assigned(sym) and (sym.typ=procsym) then
  892. for i:=1 to sym.procdef_count do
  893. begin
  894. implprocdef:=sym.procdef[i];
  895. if equal_paras(proc.para,implprocdef.para,cp_none,false) and
  896. (proc.proccalloption=implprocdef.proccalloption) then
  897. begin
  898. gintfgetcprocdef:=implprocdef;
  899. exit;
  900. end;
  901. end;
  902. end;
  903. procedure tclassheader.gintfdoonintf(intf: tobjectdef; intfindex: longint);
  904. var
  905. i: longint;
  906. proc: tprocdef;
  907. procname: string; { for error }
  908. mappedname: string;
  909. nextexist: pointer;
  910. implprocdef: tprocdef;
  911. begin
  912. for i:=1 to intf.symtable.defindex.count do
  913. begin
  914. proc:=tprocdef(intf.symtable.defindex.search(i));
  915. if proc.deftype=procdef then
  916. begin
  917. procname:='';
  918. implprocdef:=nil;
  919. nextexist:=nil;
  920. repeat
  921. mappedname:=_class.implementedinterfaces.getmappings(intfindex,proc.procsym.name,nextexist);
  922. if procname='' then
  923. procname:=proc.procsym.name;
  924. //mappedname; { for error messages }
  925. if mappedname<>'' then
  926. implprocdef:=gintfgetcprocdef(proc,mappedname);
  927. until assigned(implprocdef) or not assigned(nextexist);
  928. if not assigned(implprocdef) then
  929. implprocdef:=gintfgetcprocdef(proc,proc.procsym.name);
  930. if procname='' then
  931. procname:=proc.procsym.name;
  932. if assigned(implprocdef) then
  933. _class.implementedinterfaces.addimplproc(intfindex,implprocdef)
  934. else
  935. Message1(sym_e_no_matching_implementation_found,proc.fullprocnamewithret);
  936. end;
  937. end;
  938. end;
  939. procedure tclassheader.gintfwalkdowninterface(intf: tobjectdef; intfindex: longint);
  940. begin
  941. if assigned(intf.childof) then
  942. gintfwalkdowninterface(intf.childof,intfindex);
  943. gintfdoonintf(intf,intfindex);
  944. end;
  945. function tclassheader.genintftable: tasmlabel;
  946. var
  947. intfindex: longint;
  948. curintf: tobjectdef;
  949. intftable: tasmlabel;
  950. begin
  951. { 1. step collect implementor functions into the implementedinterfaces.implprocs }
  952. for intfindex:=1 to _class.implementedinterfaces.count do
  953. begin
  954. curintf:=_class.implementedinterfaces.interfaces(intfindex);
  955. gintfwalkdowninterface(curintf,intfindex);
  956. end;
  957. { 2. step calc required fieldcount and their offsets in the object memory map
  958. and write data }
  959. objectlibrary.getdatalabel(intftable);
  960. dataSegment.concat(Tai_label.Create(intftable));
  961. gintfwritedata;
  962. _class.implementedinterfaces.clearimplprocs; { release temporary information }
  963. genintftable:=intftable;
  964. end;
  965. { Write interface identifiers to the data section }
  966. procedure tclassheader.writeinterfaceids;
  967. var
  968. i: longint;
  969. begin
  970. if _class.isiidguidvalid then
  971. begin
  972. if (cs_create_smart in aktmoduleswitches) then
  973. dataSegment.concat(Tai_cut.Create);
  974. dataSegment.concat(Tai_symbol.Createname_global(mangledname_prefix('IID',_class.owner)+_class.objname^,0));
  975. dataSegment.concat(Tai_const.Create_32bit(longint(_class.iidguid.D1)));
  976. dataSegment.concat(Tai_const.Create_16bit(_class.iidguid.D2));
  977. dataSegment.concat(Tai_const.Create_16bit(_class.iidguid.D3));
  978. for i:=Low(_class.iidguid.D4) to High(_class.iidguid.D4) do
  979. dataSegment.concat(Tai_const.Create_8bit(_class.iidguid.D4[i]));
  980. end;
  981. if (cs_create_smart in aktmoduleswitches) then
  982. dataSegment.concat(Tai_cut.Create);
  983. dataSegment.concat(Tai_symbol.Createname_global(mangledname_prefix('IIDSTR',_class.owner)+_class.objname^,0));
  984. dataSegment.concat(Tai_const.Create_8bit(length(_class.iidstr^)));
  985. dataSegment.concat(Tai_string.Create(_class.iidstr^));
  986. end;
  987. procedure tclassheader.writevirtualmethods(List:TAAsmoutput);
  988. var
  989. symcoll : psymcoll;
  990. procdefcoll : pprocdefcoll;
  991. i : longint;
  992. begin
  993. { walk trough all numbers for virtual methods and search }
  994. { the method }
  995. for i:=0 to nextvirtnumber-1 do
  996. begin
  997. symcoll:=wurzel;
  998. { walk trough all symbols }
  999. while assigned(symcoll) do
  1000. begin
  1001. { walk trough all methods }
  1002. procdefcoll:=symcoll^.data;
  1003. while assigned(procdefcoll) do
  1004. begin
  1005. { writes the addresses to the VMT }
  1006. { but only this which are declared as virtual }
  1007. if procdefcoll^.data.extnumber=i then
  1008. begin
  1009. if (po_virtualmethod in procdefcoll^.data.procoptions) then
  1010. begin
  1011. { if a method is abstract, then is also the }
  1012. { class abstract and it's not allow to }
  1013. { generates an instance }
  1014. if (po_abstractmethod in procdefcoll^.data.procoptions) then
  1015. begin
  1016. include(_class.objectoptions,oo_has_abstract);
  1017. List.concat(Tai_const_symbol.Createname('FPC_ABSTRACTERROR'));
  1018. end
  1019. else
  1020. begin
  1021. List.concat(Tai_const_symbol.createname(procdefcoll^.data.mangledname));
  1022. end;
  1023. end;
  1024. end;
  1025. procdefcoll:=procdefcoll^.next;
  1026. end;
  1027. symcoll:=symcoll^.next;
  1028. end;
  1029. end;
  1030. end;
  1031. { generates the vmt for classes as well as for objects }
  1032. procedure tclassheader.writevmt;
  1033. var
  1034. methodnametable,intmessagetable,
  1035. strmessagetable,classnamelabel,
  1036. fieldtablelabel : tasmlabel;
  1037. {$ifdef WITHDMT}
  1038. dmtlabel : tasmlabel;
  1039. {$endif WITHDMT}
  1040. interfacetable : tasmlabel;
  1041. begin
  1042. {$ifdef WITHDMT}
  1043. dmtlabel:=gendmt;
  1044. {$endif WITHDMT}
  1045. if (cs_create_smart in aktmoduleswitches) then
  1046. dataSegment.concat(Tai_cut.Create);
  1047. { write tables for classes, this must be done before the actual
  1048. class is written, because we need the labels defined }
  1049. if is_class(_class) then
  1050. begin
  1051. { interface table }
  1052. if _class.implementedinterfaces.count>0 then
  1053. begin
  1054. if (cs_create_smart in aktmoduleswitches) then
  1055. codeSegment.concat(Tai_cut.Create);
  1056. interfacetable:=genintftable;
  1057. end;
  1058. methodnametable:=genpublishedmethodstable;
  1059. fieldtablelabel:=_class.generate_field_table;
  1060. { write class name }
  1061. objectlibrary.getdatalabel(classnamelabel);
  1062. dataSegment.concat(Tai_label.Create(classnamelabel));
  1063. dataSegment.concat(Tai_const.Create_8bit(length(_class.objrealname^)));
  1064. dataSegment.concat(Tai_string.Create(_class.objrealname^));
  1065. { generate message and dynamic tables }
  1066. if (oo_has_msgstr in _class.objectoptions) then
  1067. strmessagetable:=genstrmsgtab;
  1068. if (oo_has_msgint in _class.objectoptions) then
  1069. intmessagetable:=genintmsgtab
  1070. else
  1071. dataSegment.concat(Tai_const.Create_32bit(0));
  1072. end;
  1073. { write debug info }
  1074. {$ifdef GDB}
  1075. if (cs_debuginfo in aktmoduleswitches) then
  1076. begin
  1077. do_count_dbx:=true;
  1078. if assigned(_class.owner) and assigned(_class.owner.name) then
  1079. dataSegment.concat(Tai_stabs.Create(strpnew('"vmt_'+_class.owner.name^+_class.name+':S'+
  1080. typeglobalnumber('__vtbl_ptr_type')+'",'+tostr(N_STSYM)+',0,0,'+_class.vmt_mangledname)));
  1081. end;
  1082. {$endif GDB}
  1083. dataSegment.concat(Tai_symbol.Createdataname_global(_class.vmt_mangledname,0));
  1084. { determine the size with symtable.datasize, because }
  1085. { size gives back 4 for classes }
  1086. dataSegment.concat(Tai_const.Create_32bit(_class.symtable.datasize));
  1087. dataSegment.concat(Tai_const.Create_32bit(-_class.symtable.datasize));
  1088. {$ifdef WITHDMT}
  1089. if _class.classtype=ct_object then
  1090. begin
  1091. if assigned(dmtlabel) then
  1092. dataSegment.concat(Tai_const_symbol.Create(dmtlabel)))
  1093. else
  1094. dataSegment.concat(Tai_const.Create_32bit(0));
  1095. end;
  1096. {$endif WITHDMT}
  1097. { write pointer to parent VMT, this isn't implemented in TP }
  1098. { but this is not used in FPC ? (PM) }
  1099. { it's not used yet, but the delphi-operators as and is need it (FK) }
  1100. { it is not written for parents that don't have any vmt !! }
  1101. if assigned(_class.childof) and
  1102. (oo_has_vmt in _class.childof.objectoptions) then
  1103. dataSegment.concat(Tai_const_symbol.Createname(_class.childof.vmt_mangledname))
  1104. else
  1105. dataSegment.concat(Tai_const.Create_32bit(0));
  1106. { write extended info for classes, for the order see rtl/inc/objpash.inc }
  1107. if is_class(_class) then
  1108. begin
  1109. { pointer to class name string }
  1110. dataSegment.concat(Tai_const_symbol.Create(classnamelabel));
  1111. { pointer to dynamic table }
  1112. if (oo_has_msgint in _class.objectoptions) then
  1113. dataSegment.concat(Tai_const_symbol.Create(intmessagetable))
  1114. else
  1115. dataSegment.concat(Tai_const.Create_32bit(0));
  1116. { pointer to method table }
  1117. if assigned(methodnametable) then
  1118. dataSegment.concat(Tai_const_symbol.Create(methodnametable))
  1119. else
  1120. dataSegment.concat(Tai_const.Create_32bit(0));
  1121. { pointer to field table }
  1122. dataSegment.concat(Tai_const_symbol.Create(fieldtablelabel));
  1123. { pointer to type info of published section }
  1124. if (oo_can_have_published in _class.objectoptions) then
  1125. dataSegment.concat(Tai_const_symbol.Create(_class.get_rtti_label(fullrtti)))
  1126. else
  1127. dataSegment.concat(Tai_const.Create_32bit(0));
  1128. { inittable for con-/destruction }
  1129. if _class.members_need_inittable then
  1130. dataSegment.concat(Tai_const_symbol.Create(_class.get_rtti_label(initrtti)))
  1131. else
  1132. dataSegment.concat(Tai_const.Create_32bit(0));
  1133. { auto table }
  1134. dataSegment.concat(Tai_const.Create_32bit(0));
  1135. { interface table }
  1136. if _class.implementedinterfaces.count>0 then
  1137. dataSegment.concat(Tai_const_symbol.Create(interfacetable))
  1138. else
  1139. dataSegment.concat(Tai_const.Create_32bit(0));
  1140. { table for string messages }
  1141. if (oo_has_msgstr in _class.objectoptions) then
  1142. dataSegment.concat(Tai_const_symbol.Create(strmessagetable))
  1143. else
  1144. dataSegment.concat(Tai_const.Create_32bit(0));
  1145. end;
  1146. { write virtual methods }
  1147. writevirtualmethods(dataSegment);
  1148. { write the size of the VMT }
  1149. dataSegment.concat(Tai_symbol_end.Createname(_class.vmt_mangledname));
  1150. end;
  1151. procedure tclassheader.adjustselfvalue(procdef: tprocdef;ioffset: aword);
  1152. var
  1153. href : treference;
  1154. l : tparalocation;
  1155. begin
  1156. l:=paramanager.getselflocation(procdef);
  1157. case l.loc of
  1158. LOC_REGISTER:
  1159. cg.a_op_const_reg(exprasmlist,OP_SUB,ioffset,l.register);
  1160. LOC_REFERENCE:
  1161. begin
  1162. reference_reset_base(href,l.reference.index,l.reference.offset);
  1163. cg.a_op_const_ref(exprasmlist,OP_SUB,OS_ADDR,ioffset,href);
  1164. end
  1165. else
  1166. internalerror(2002080801);
  1167. end;
  1168. end;
  1169. initialization
  1170. cclassheader:=tclassheader;
  1171. end.
  1172. {
  1173. $Log$
  1174. Revision 1.33 2002-10-20 15:33:36 peter
  1175. * having overloads is the same as overload directive for hiding of
  1176. parent methods. This is required becuase it can be possible that a
  1177. method will then hide a method in the parent that an overloaded
  1178. method requires. See webbug tw2185
  1179. Revision 1.32 2002/10/19 15:09:24 peter
  1180. + tobjectdef.members_need_inittable that is used to generate only the
  1181. inittable when it is really used. This saves a lot of useless calls
  1182. to fpc_finalize when destroying classes
  1183. Revision 1.31 2002/10/15 19:00:42 peter
  1184. * small tweak to use speedvalue before comparing strings
  1185. Revision 1.30 2002/10/06 16:40:25 florian
  1186. * interface wrapper name mangling improved
  1187. Revision 1.29 2002/10/05 12:43:25 carl
  1188. * fixes for Delphi 6 compilation
  1189. (warning : Some features do not work under Delphi)
  1190. Revision 1.28 2002/09/16 14:11:13 peter
  1191. * add argument to equal_paras() to support default values or not
  1192. Revision 1.27 2002/09/03 16:26:26 daniel
  1193. * Make Tprocdef.defs protected
  1194. Revision 1.26 2002/09/03 15:44:44 peter
  1195. * fixed private methods hiding public virtual methods
  1196. Revision 1.25 2002/08/11 14:32:27 peter
  1197. * renamed current_library to objectlibrary
  1198. Revision 1.24 2002/08/11 13:24:12 peter
  1199. * saving of asmsymbols in ppu supported
  1200. * asmsymbollist global is removed and moved into a new class
  1201. tasmlibrarydata that will hold the info of a .a file which
  1202. corresponds with a single module. Added librarydata to tmodule
  1203. to keep the library info stored for the module. In the future the
  1204. objectfiles will also be stored to the tasmlibrarydata class
  1205. * all getlabel/newasmsymbol and friends are moved to the new class
  1206. Revision 1.23 2002/08/09 07:33:01 florian
  1207. * a couple of interface related fixes
  1208. Revision 1.22 2002/07/20 11:57:55 florian
  1209. * types.pas renamed to defbase.pas because D6 contains a types
  1210. unit so this would conflicts if D6 programms are compiled
  1211. + Willamette/SSE2 instructions to assembler added
  1212. Revision 1.21 2002/07/01 18:46:23 peter
  1213. * internal linker
  1214. * reorganized aasm layer
  1215. Revision 1.20 2002/05/18 13:34:10 peter
  1216. * readded missing revisions
  1217. Revision 1.19 2002/05/16 19:46:39 carl
  1218. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1219. + try to fix temp allocation (still in ifdef)
  1220. + generic constructor calls
  1221. + start of tassembler / tmodulebase class cleanup
  1222. Revision 1.17 2002/05/12 16:53:08 peter
  1223. * moved entry and exitcode to ncgutil and cgobj
  1224. * foreach gets extra argument for passing local data to the
  1225. iterator function
  1226. * -CR checks also class typecasts at runtime by changing them
  1227. into as
  1228. * fixed compiler to cycle with the -CR option
  1229. * fixed stabs with elf writer, finally the global variables can
  1230. be watched
  1231. * removed a lot of routines from cga unit and replaced them by
  1232. calls to cgobj
  1233. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  1234. u32bit then the other is typecasted also to u32bit without giving
  1235. a rangecheck warning/error.
  1236. * fixed pascal calling method with reversing also the high tree in
  1237. the parast, detected by tcalcst3 test
  1238. Revision 1.16 2002/04/20 21:32:24 carl
  1239. + generic FPC_CHECKPOINTER
  1240. + first parameter offset in stack now portable
  1241. * rename some constants
  1242. + move some cpu stuff to other units
  1243. - remove unused constents
  1244. * fix stacksize for some targets
  1245. * fix generic size problems which depend now on EXTEND_SIZE constant
  1246. Revision 1.15 2002/04/19 15:46:01 peter
  1247. * mangledname rewrite, tprocdef.mangledname is now created dynamicly
  1248. in most cases and not written to the ppu
  1249. * add mangeledname_prefix() routine to generate the prefix of
  1250. manglednames depending on the current procedure, object and module
  1251. * removed static procprefix since the mangledname is now build only
  1252. on demand from tprocdef.mangledname
  1253. Revision 1.14 2002/04/15 18:59:07 carl
  1254. + target_info.size_of_pointer -> pointer_Size
  1255. Revision 1.13 2002/02/11 18:51:35 peter
  1256. * fixed vmt generation for private procedures that were skipped after
  1257. my previous changes
  1258. }