nobj.pas 54 KB

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