nobj.pas 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370
  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. objectlibrary.getdatalabel(p^.nl);
  239. if assigned(p^.l) then
  240. writenames(p^.l);
  241. dataSegment.concat(Tai_label.Create(p^.nl));
  242. dataSegment.concat(Tai_const.Create_8bit(strlen(p^.data.messageinf.str)));
  243. dataSegment.concat(Tai_string.Create_pchar(p^.data.messageinf.str));
  244. if assigned(p^.r) then
  245. writenames(p^.r);
  246. end;
  247. procedure tclassheader.writestrentry(p : pprocdeftree);
  248. begin
  249. if assigned(p^.l) then
  250. writestrentry(p^.l);
  251. { write name label }
  252. dataSegment.concat(Tai_const_symbol.Create(p^.nl));
  253. dataSegment.concat(Tai_const_symbol.Createname(p^.data.mangledname));
  254. if assigned(p^.r) then
  255. writestrentry(p^.r);
  256. end;
  257. function tclassheader.genstrmsgtab : tasmlabel;
  258. var
  259. r : tasmlabel;
  260. begin
  261. root:=nil;
  262. count:=0;
  263. { insert all message handlers into a tree, sorted by name }
  264. _class.symtable.foreach({$ifdef FPCPROCVAR}@{$endif}insertmsgstr,nil);
  265. { write all names }
  266. if assigned(root) then
  267. writenames(root);
  268. { now start writing of the message string table }
  269. objectlibrary.getdatalabel(r);
  270. dataSegment.concat(Tai_label.Create(r));
  271. genstrmsgtab:=r;
  272. dataSegment.concat(Tai_const.Create_32bit(count));
  273. if assigned(root) then
  274. begin
  275. writestrentry(root);
  276. disposeprocdeftree(root);
  277. end;
  278. end;
  279. procedure tclassheader.writeintentry(p : pprocdeftree);
  280. begin
  281. if assigned(p^.l) then
  282. writeintentry(p^.l);
  283. { write name label }
  284. dataSegment.concat(Tai_const.Create_32bit(p^.data.messageinf.i));
  285. dataSegment.concat(Tai_const_symbol.Createname(p^.data.mangledname));
  286. if assigned(p^.r) then
  287. writeintentry(p^.r);
  288. end;
  289. function tclassheader.genintmsgtab : tasmlabel;
  290. var
  291. r : tasmlabel;
  292. begin
  293. root:=nil;
  294. count:=0;
  295. { insert all message handlers into a tree, sorted by name }
  296. _class.symtable.foreach({$ifdef FPCPROCVAR}@{$endif}insertmsgint,nil);
  297. { now start writing of the message string table }
  298. objectlibrary.getdatalabel(r);
  299. dataSegment.concat(Tai_label.Create(r));
  300. genintmsgtab:=r;
  301. dataSegment.concat(Tai_const.Create_32bit(count));
  302. if assigned(root) then
  303. begin
  304. writeintentry(root);
  305. disposeprocdeftree(root);
  306. end;
  307. end;
  308. {$ifdef WITHDMT}
  309. {**************************************
  310. DMT
  311. **************************************}
  312. procedure tclassheader.insertdmtentry(p : tnamedindexitem;arg:pointer);
  313. var
  314. hp : tprocdef;
  315. pt : pprocdeftree;
  316. begin
  317. if tsym(p).typ=procsym then
  318. begin
  319. hp:=tprocsym(p).definition;
  320. while assigned(hp) do
  321. begin
  322. if (po_msgint in hp.procoptions) then
  323. begin
  324. new(pt);
  325. pt^.p:=hp;
  326. pt^.l:=nil;
  327. pt^.r:=nil;
  328. insertint(pt,root);
  329. end;
  330. hp:=hp.nextoverloaded;
  331. end;
  332. end;
  333. end;
  334. procedure tclassheader.writedmtindexentry(p : pprocdeftree);
  335. begin
  336. if assigned(p^.l) then
  337. writedmtindexentry(p^.l);
  338. dataSegment.concat(Tai_const.Create_32bit(p^.data.messageinf.i));
  339. if assigned(p^.r) then
  340. writedmtindexentry(p^.r);
  341. end;
  342. procedure tclassheader.writedmtaddressentry(p : pprocdeftree);
  343. begin
  344. if assigned(p^.l) then
  345. writedmtaddressentry(p^.l);
  346. dataSegment.concat(Tai_const_symbol.Createname(p^.data.mangledname));
  347. if assigned(p^.r) then
  348. writedmtaddressentry(p^.r);
  349. end;
  350. function tclassheader.gendmt : tasmlabel;
  351. var
  352. r : tasmlabel;
  353. begin
  354. root:=nil;
  355. count:=0;
  356. gendmt:=nil;
  357. { insert all message handlers into a tree, sorted by number }
  358. _class.symtable.foreach({$ifdef FPCPROCVAR}@{$endif}insertdmtentry);
  359. if count>0 then
  360. begin
  361. objectlibrary.getdatalabel(r);
  362. gendmt:=r;
  363. dataSegment.concat(Tai_label.Create(r));
  364. { entries for caching }
  365. dataSegment.concat(Tai_const.Create_32bit(0));
  366. dataSegment.concat(Tai_const.Create_32bit(0));
  367. dataSegment.concat(Tai_const.Create_32bit(count));
  368. if assigned(root) then
  369. begin
  370. writedmtindexentry(root);
  371. writedmtaddressentry(root);
  372. disposeprocdeftree(root);
  373. end;
  374. end;
  375. end;
  376. {$endif WITHDMT}
  377. {**************************************
  378. Published Methods
  379. **************************************}
  380. procedure tclassheader.do_count(p : tnamedindexitem;arg:pointer);
  381. begin
  382. if (tsym(p).typ=procsym) and (sp_published in tsym(p).symoptions) then
  383. inc(count);
  384. end;
  385. procedure tclassheader.genpubmethodtableentry(p : tnamedindexitem;arg:pointer);
  386. var
  387. hp : tprocdef;
  388. l : tasmlabel;
  389. begin
  390. if (tsym(p).typ=procsym) and (sp_published in tsym(p).symoptions) then
  391. begin
  392. if assigned(tprocsym(p).defs^.next) then
  393. internalerror(1209992);
  394. hp:=tprocsym(p).defs^.def;
  395. objectlibrary.getdatalabel(l);
  396. Consts.concat(Tai_label.Create(l));
  397. Consts.concat(Tai_const.Create_8bit(length(p.name)));
  398. Consts.concat(Tai_string.Create(p.name));
  399. dataSegment.concat(Tai_const_symbol.Create(l));
  400. dataSegment.concat(Tai_const_symbol.Createname(hp.mangledname));
  401. end;
  402. end;
  403. function tclassheader.genpublishedmethodstable : tasmlabel;
  404. var
  405. l : tasmlabel;
  406. begin
  407. count:=0;
  408. _class.symtable.foreach({$ifdef FPCPROCVAR}@{$endif}do_count,nil);
  409. if count>0 then
  410. begin
  411. objectlibrary.getdatalabel(l);
  412. dataSegment.concat(Tai_label.Create(l));
  413. dataSegment.concat(Tai_const.Create_32bit(count));
  414. _class.symtable.foreach({$ifdef FPCPROCVAR}@{$endif}genpubmethodtableentry,nil);
  415. genpublishedmethodstable:=l;
  416. end
  417. else
  418. genpublishedmethodstable:=nil;
  419. end;
  420. {**************************************
  421. VMT
  422. **************************************}
  423. procedure tclassheader.eachsym(sym : tnamedindexitem;arg:pointer);
  424. var
  425. procdefcoll : pprocdefcoll;
  426. hp : pprocdeflist;
  427. symcoll : psymcoll;
  428. _name : string;
  429. procedure newdefentry(pd:tprocdef);
  430. begin
  431. new(procdefcoll);
  432. procdefcoll^.data:=pd;
  433. procdefcoll^.hidden:=false;
  434. procdefcoll^.next:=symcoll^.data;
  435. symcoll^.data:=procdefcoll;
  436. { if it's a virtual method }
  437. if (po_virtualmethod in pd.procoptions) then
  438. begin
  439. { then it gets a number ... }
  440. pd.extnumber:=nextvirtnumber;
  441. { and we inc the number }
  442. inc(nextvirtnumber);
  443. has_virtual_method:=true;
  444. end;
  445. if (pd.proctypeoption=potype_constructor) then
  446. has_constructor:=true;
  447. { check, if a method should be overridden }
  448. if (pd._class=_class) and
  449. (po_overridingmethod in pd.procoptions) then
  450. MessagePos1(pd.fileinfo,parser_e_nothing_to_be_overridden,pd.fullprocname);
  451. end;
  452. { creates a new entry in the procsym list }
  453. procedure newentry;
  454. 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. objectlibrary.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. objectlibrary.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. objectlibrary.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. objectlibrary.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.25 2002-08-11 14:32:27 peter
  1152. * renamed current_library to objectlibrary
  1153. Revision 1.24 2002/08/11 13:24:12 peter
  1154. * saving of asmsymbols in ppu supported
  1155. * asmsymbollist global is removed and moved into a new class
  1156. tasmlibrarydata that will hold the info of a .a file which
  1157. corresponds with a single module. Added librarydata to tmodule
  1158. to keep the library info stored for the module. In the future the
  1159. objectfiles will also be stored to the tasmlibrarydata class
  1160. * all getlabel/newasmsymbol and friends are moved to the new class
  1161. Revision 1.23 2002/08/09 07:33:01 florian
  1162. * a couple of interface related fixes
  1163. Revision 1.22 2002/07/20 11:57:55 florian
  1164. * types.pas renamed to defbase.pas because D6 contains a types
  1165. unit so this would conflicts if D6 programms are compiled
  1166. + Willamette/SSE2 instructions to assembler added
  1167. Revision 1.21 2002/07/01 18:46:23 peter
  1168. * internal linker
  1169. * reorganized aasm layer
  1170. Revision 1.20 2002/05/18 13:34:10 peter
  1171. * readded missing revisions
  1172. Revision 1.19 2002/05/16 19:46:39 carl
  1173. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1174. + try to fix temp allocation (still in ifdef)
  1175. + generic constructor calls
  1176. + start of tassembler / tmodulebase class cleanup
  1177. Revision 1.17 2002/05/12 16:53:08 peter
  1178. * moved entry and exitcode to ncgutil and cgobj
  1179. * foreach gets extra argument for passing local data to the
  1180. iterator function
  1181. * -CR checks also class typecasts at runtime by changing them
  1182. into as
  1183. * fixed compiler to cycle with the -CR option
  1184. * fixed stabs with elf writer, finally the global variables can
  1185. be watched
  1186. * removed a lot of routines from cga unit and replaced them by
  1187. calls to cgobj
  1188. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  1189. u32bit then the other is typecasted also to u32bit without giving
  1190. a rangecheck warning/error.
  1191. * fixed pascal calling method with reversing also the high tree in
  1192. the parast, detected by tcalcst3 test
  1193. Revision 1.16 2002/04/20 21:32:24 carl
  1194. + generic FPC_CHECKPOINTER
  1195. + first parameter offset in stack now portable
  1196. * rename some constants
  1197. + move some cpu stuff to other units
  1198. - remove unused constents
  1199. * fix stacksize for some targets
  1200. * fix generic size problems which depend now on EXTEND_SIZE constant
  1201. Revision 1.15 2002/04/19 15:46:01 peter
  1202. * mangledname rewrite, tprocdef.mangledname is now created dynamicly
  1203. in most cases and not written to the ppu
  1204. * add mangeledname_prefix() routine to generate the prefix of
  1205. manglednames depending on the current procedure, object and module
  1206. * removed static procprefix since the mangledname is now build only
  1207. on demand from tprocdef.mangledname
  1208. Revision 1.14 2002/04/15 18:59:07 carl
  1209. + target_info.size_of_pointer -> pointer_Size
  1210. Revision 1.13 2002/02/11 18:51:35 peter
  1211. * fixed vmt generation for private procedures that were skipped after
  1212. my previous changes
  1213. }