nobj.pas 50 KB

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