nobj.pas 52 KB

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