nobj.pas 55 KB

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