nobj.pas 50 KB

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