nobj.pas 52 KB

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