nobj.pas 56 KB

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