nobj.pas 52 KB

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