nobj.pas 53 KB

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