nobj.pas 52 KB

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