nobj.pas 52 KB

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