nobj.pas 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382
  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. systems
  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^.next:=symcoll^.data;
  430. symcoll^.data:=procdefcoll;
  431. { if it's a virtual method }
  432. if (po_virtualmethod in pd.procoptions) then
  433. begin
  434. { then it gets a number ... }
  435. pd.extnumber:=nextvirtnumber;
  436. { and we inc the number }
  437. inc(nextvirtnumber);
  438. has_virtual_method:=true;
  439. end;
  440. if (pd.proctypeoption=potype_constructor) then
  441. has_constructor:=true;
  442. { check, if a method should be overridden }
  443. if (pd._class=_class) and
  444. (po_overridingmethod in pd.procoptions) then
  445. MessagePos1(pd.fileinfo,parser_e_nothing_to_be_overridden,pd.fullprocname);
  446. end;
  447. { creates a new entry in the procsym list }
  448. procedure newentry;
  449. begin
  450. { if not, generate a new symbol item }
  451. new(symcoll);
  452. symcoll^.name:=stringdup(sym.name);
  453. symcoll^.next:=wurzel;
  454. symcoll^.data:=nil;
  455. wurzel:=symcoll;
  456. { inserts all definitions }
  457. hp:=tprocsym(sym).defs;
  458. while assigned(hp) do
  459. begin
  460. newdefentry(hp^.def);
  461. hp:=hp^.next;
  462. end;
  463. end;
  464. label
  465. handlenextdef;
  466. var
  467. pd : tprocdef;
  468. pdoverload : boolean;
  469. begin
  470. { put only sub routines into the VMT }
  471. if tsym(sym).typ=procsym then
  472. begin
  473. { skip private symbols that can not been seen }
  474. if not tsym(sym).check_private then
  475. exit;
  476. { check the current list of symbols }
  477. _name:=sym.name;
  478. symcoll:=wurzel;
  479. while assigned(symcoll) do
  480. begin
  481. { does the symbol already exist in the list ? }
  482. if _name=symcoll^.name^ then
  483. begin
  484. { walk through all defs of the symbol }
  485. hp:=tprocsym(sym).defs;
  486. while assigned(hp) do
  487. begin
  488. pd:=hp^.def;
  489. if pd.procsym=sym then
  490. begin
  491. pdoverload:=(po_overload in pd.procoptions);
  492. { compare with all stored definitions }
  493. procdefcoll:=symcoll^.data;
  494. while assigned(procdefcoll) do
  495. begin
  496. { compare only if the definition is not hidden }
  497. if not procdefcoll^.hidden then
  498. begin
  499. { check if one of the two methods has virtual }
  500. if (po_virtualmethod in procdefcoll^.data.procoptions) or
  501. (po_virtualmethod in pd.procoptions) then
  502. begin
  503. { if the current definition has no virtual then hide the
  504. old virtual if the new definition has the same arguments or
  505. has no overload directive }
  506. if not(po_virtualmethod in pd.procoptions) then
  507. begin
  508. if not pdoverload or
  509. equal_paras(procdefcoll^.data.para,pd.para,cp_value_equal_const) then
  510. begin
  511. procdefcoll^.hidden:=true;
  512. if _class=pd._class then
  513. MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname);
  514. end;
  515. end
  516. { if both are virtual we check the header }
  517. else if (po_virtualmethod in pd.procoptions) and
  518. (po_virtualmethod in procdefcoll^.data.procoptions) then
  519. begin
  520. { new one has not override }
  521. if is_class(_class) and
  522. not(po_overridingmethod in pd.procoptions) then
  523. begin
  524. { we start a new virtual tree, hide the old }
  525. if not pdoverload or
  526. equal_paras(procdefcoll^.data.para,pd.para,cp_value_equal_const) 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. { same parameters }
  534. else if (equal_paras(procdefcoll^.data.para,pd.para,cp_value_equal_const)) then
  535. begin
  536. { overload is inherited }
  537. if (po_overload in procdefcoll^.data.procoptions) then
  538. include(pd.procoptions,po_overload);
  539. { the flags have to match except abstract and override }
  540. { only if both are virtual !! }
  541. if (procdefcoll^.data.proccalloption<>pd.proccalloption) or
  542. (procdefcoll^.data.proctypeoption<>pd.proctypeoption) or
  543. ((procdefcoll^.data.procoptions-
  544. [po_abstractmethod,po_overridingmethod,po_assembler,po_overload])<>
  545. (pd.procoptions-[po_abstractmethod,po_overridingmethod,po_assembler,po_overload])) then
  546. MessagePos1(pd.fileinfo,parser_e_header_dont_match_forward,pd.fullprocname);
  547. { error, if the return types aren't equal }
  548. if not(is_equal(procdefcoll^.data.rettype.def,pd.rettype.def)) and
  549. not((procdefcoll^.data.rettype.def.deftype=objectdef) and
  550. (pd.rettype.def.deftype=objectdef) and
  551. is_class(procdefcoll^.data.rettype.def) and
  552. is_class(pd.rettype.def) and
  553. (tobjectdef(pd.rettype.def).is_related(
  554. tobjectdef(procdefcoll^.data.rettype.def)))) then
  555. Message2(parser_e_overridden_methods_not_same_ret,pd.fullprocnamewithret,
  556. procdefcoll^.data.fullprocnamewithret);
  557. { now set the number }
  558. pd.extnumber:=procdefcoll^.data.extnumber;
  559. { and exchange }
  560. procdefcoll^.data:=pd;
  561. goto handlenextdef;
  562. end
  563. { different parameters }
  564. else
  565. begin
  566. { when we got an override directive then can search futher for
  567. the procedure to override.
  568. If we are starting a new virtual tree then hide the old tree }
  569. if not(po_overridingmethod in pd.procoptions) and
  570. not pdoverload then
  571. begin
  572. procdefcoll^.hidden:=true;
  573. if _class=pd._class then
  574. MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname);
  575. end;
  576. end;
  577. end
  578. else
  579. begin
  580. { the new definition is virtual and the old static, we hide the old one
  581. if the new defintion has not the overload directive }
  582. if not pdoverload or
  583. equal_paras(procdefcoll^.data.para,pd.para,cp_value_equal_const) then
  584. procdefcoll^.hidden:=true;
  585. end;
  586. end
  587. else
  588. begin
  589. { both are static, we hide the old one if the new defintion
  590. has not the overload directive }
  591. if equal_paras(procdefcoll^.data.para,pd.para,cp_value_equal_const) or
  592. not pdoverload then
  593. procdefcoll^.hidden:=true;
  594. end;
  595. end; { not hidden }
  596. procdefcoll:=procdefcoll^.next;
  597. end;
  598. { if it isn't saved in the list we create a new entry }
  599. newdefentry(pd);
  600. end;
  601. handlenextdef:
  602. hp:=hp^.next;
  603. end;
  604. exit;
  605. end;
  606. symcoll:=symcoll^.next;
  607. end;
  608. newentry;
  609. end;
  610. end;
  611. procedure tclassheader.disposevmttree;
  612. var
  613. symcoll : psymcoll;
  614. procdefcoll : pprocdefcoll;
  615. begin
  616. { disposes the above generated tree }
  617. symcoll:=wurzel;
  618. while assigned(symcoll) do
  619. begin
  620. wurzel:=symcoll^.next;
  621. stringdispose(symcoll^.name);
  622. procdefcoll:=symcoll^.data;
  623. while assigned(procdefcoll) do
  624. begin
  625. symcoll^.data:=procdefcoll^.next;
  626. dispose(procdefcoll);
  627. procdefcoll:=symcoll^.data;
  628. end;
  629. dispose(symcoll);
  630. symcoll:=wurzel;
  631. end;
  632. end;
  633. procedure tclassheader.genvmt;
  634. procedure do_genvmt(p : tobjectdef);
  635. begin
  636. { start with the base class }
  637. if assigned(p.childof) then
  638. do_genvmt(p.childof);
  639. { walk through all public syms }
  640. p.symtable.foreach({$ifdef FPCPROCVAR}@{$endif}eachsym);
  641. end;
  642. begin
  643. wurzel:=nil;
  644. nextvirtnumber:=0;
  645. has_constructor:=false;
  646. has_virtual_method:=false;
  647. { generates a tree of all used methods }
  648. do_genvmt(_class);
  649. if not(is_interface(_class)) and
  650. has_virtual_method and
  651. not(has_constructor) then
  652. Message1(parser_w_virtual_without_constructor,_class.objname^);
  653. end;
  654. {**************************************
  655. Interface tables
  656. **************************************}
  657. function tclassheader.gintfgetvtbllabelname(intfindex: integer): string;
  658. begin
  659. gintfgetvtbllabelname:='VTBL_'+current_module.modulename^+'$_'+upper(_class.objname^)+
  660. '_$$_'+upper(_class.implementedinterfaces.interfaces(intfindex).objname^);
  661. end;
  662. procedure tclassheader.gintfcreatevtbl(intfindex: integer; rawdata,rawcode: TAAsmoutput);
  663. var
  664. implintf: timplementedinterfaces;
  665. curintf: tobjectdef;
  666. proccount: integer;
  667. tmps: string;
  668. i: longint;
  669. begin
  670. implintf:=_class.implementedinterfaces;
  671. curintf:=implintf.interfaces(intfindex);
  672. if (cs_create_smart in aktmoduleswitches) then
  673. rawdata.concat(Tai_symbol.Createname_global(gintfgetvtbllabelname(intfindex),0))
  674. else
  675. rawdata.concat(Tai_symbol.Createname(gintfgetvtbllabelname(intfindex),0));
  676. proccount:=implintf.implproccount(intfindex);
  677. for i:=1 to proccount do
  678. begin
  679. tmps:=implintf.implprocs(intfindex,i).mangledname+'_$$_'+upper(curintf.objname^);
  680. { create wrapper code }
  681. cgintfwrapper(rawcode,implintf.implprocs(intfindex,i),tmps,implintf.ioffsets(intfindex)^);
  682. { create reference }
  683. rawdata.concat(Tai_const_symbol.Createname(tmps));
  684. end;
  685. end;
  686. procedure tclassheader.gintfgenentry(intfindex, contintfindex: integer; rawdata: TAAsmoutput);
  687. var
  688. implintf: timplementedinterfaces;
  689. curintf: tobjectdef;
  690. tmplabel: tasmlabel;
  691. i: longint;
  692. begin
  693. implintf:=_class.implementedinterfaces;
  694. curintf:=implintf.interfaces(intfindex);
  695. { GUID }
  696. if curintf.objecttype in [odt_interfacecom] then
  697. begin
  698. { label for GUID }
  699. getdatalabel(tmplabel);
  700. rawdata.concat(Tai_label.Create(tmplabel));
  701. rawdata.concat(Tai_const.Create_32bit(curintf.iidguid.D1));
  702. rawdata.concat(Tai_const.Create_16bit(curintf.iidguid.D2));
  703. rawdata.concat(Tai_const.Create_16bit(curintf.iidguid.D3));
  704. for i:=Low(curintf.iidguid.D4) to High(curintf.iidguid.D4) do
  705. rawdata.concat(Tai_const.Create_8bit(curintf.iidguid.D4[i]));
  706. dataSegment.concat(Tai_const_symbol.Create(tmplabel));
  707. end
  708. else
  709. begin
  710. { nil for Corba interfaces }
  711. dataSegment.concat(Tai_const.Create_32bit(0)); { nil }
  712. end;
  713. { VTable }
  714. dataSegment.concat(Tai_const_symbol.Createname(gintfgetvtbllabelname(contintfindex)));
  715. { IOffset field }
  716. dataSegment.concat(Tai_const.Create_32bit(implintf.ioffsets(contintfindex)^));
  717. { IIDStr }
  718. getdatalabel(tmplabel);
  719. rawdata.concat(Tai_label.Create(tmplabel));
  720. rawdata.concat(Tai_const.Create_8bit(length(curintf.iidstr^)));
  721. if curintf.objecttype=odt_interfacecom then
  722. rawdata.concat(Tai_string.Create(upper(curintf.iidstr^)))
  723. else
  724. rawdata.concat(Tai_string.Create(curintf.iidstr^));
  725. dataSegment.concat(Tai_const_symbol.Create(tmplabel));
  726. end;
  727. procedure tclassheader.gintfoptimizevtbls(implvtbl : plongint);
  728. type
  729. tcompintfentry = record
  730. weight: longint;
  731. compintf: longint;
  732. end;
  733. { Max 1000 interface in the class header interfaces it's enough imho }
  734. tcompintfs = packed array[1..1000] of tcompintfentry;
  735. pcompintfs = ^tcompintfs;
  736. tequals = packed array[1..1000] of longint;
  737. pequals = ^tequals;
  738. var
  739. max: longint;
  740. equals: pequals;
  741. compats: pcompintfs;
  742. i: longint;
  743. j: longint;
  744. w: longint;
  745. cij: boolean;
  746. cji: boolean;
  747. begin
  748. max:=_class.implementedinterfaces.count;
  749. if max>High(tequals) then
  750. Internalerror(200006135);
  751. getmem(compats,sizeof(tcompintfentry)*max);
  752. getmem(equals,sizeof(longint)*max);
  753. fillchar(compats^,sizeof(tcompintfentry)*max,0);
  754. fillchar(equals^,sizeof(longint)*max,0);
  755. { ismergepossible is a containing relation
  756. meaning of ismergepossible(a,b,w) =
  757. if implementorfunction map of a is contained implementorfunction map of b
  758. imp(a,b) and imp(b,c) => imp(a,c) ; imp(a,b) and imp(b,a) => a == b
  759. }
  760. { the order is very important for correct allocation }
  761. for i:=1 to max do
  762. begin
  763. for j:=i+1 to max do
  764. begin
  765. cij:=_class.implementedinterfaces.isimplmergepossible(i,j,w);
  766. cji:=_class.implementedinterfaces.isimplmergepossible(j,i,w);
  767. if cij and cji then { i equal j }
  768. begin
  769. { get minimum index of equal }
  770. if equals^[j]=0 then
  771. equals^[j]:=i;
  772. end
  773. else if cij then
  774. begin
  775. { get minimum index of maximum weight }
  776. if compats^[i].weight<w then
  777. begin
  778. compats^[i].weight:=w;
  779. compats^[i].compintf:=j;
  780. end;
  781. end
  782. else if cji then
  783. begin
  784. { get minimum index of maximum weight }
  785. if (compats^[j].weight<w) then
  786. begin
  787. compats^[j].weight:=w;
  788. compats^[j].compintf:=i;
  789. end;
  790. end;
  791. end;
  792. end;
  793. for i:=1 to max do
  794. begin
  795. if compats^[i].compintf<>0 then
  796. implvtbl[i]:=compats^[i].compintf
  797. else if equals^[i]<>0 then
  798. implvtbl[i]:=equals^[i]
  799. else
  800. implvtbl[i]:=i;
  801. end;
  802. freemem(compats,sizeof(tcompintfentry)*max);
  803. freemem(equals,sizeof(longint)*max);
  804. end;
  805. procedure tclassheader.gintfwritedata;
  806. var
  807. rawdata,rawcode: taasmoutput;
  808. impintfindexes: plongint;
  809. max: longint;
  810. i: longint;
  811. begin
  812. max:=_class.implementedinterfaces.count;
  813. getmem(impintfindexes,(max+1)*sizeof(longint));
  814. gintfoptimizevtbls(impintfindexes);
  815. rawdata:=TAAsmOutput.Create;
  816. rawcode:=TAAsmOutput.Create;
  817. dataSegment.concat(Tai_const.Create_16bit(max));
  818. { Two pass, one for allocation and vtbl creation }
  819. for i:=1 to max do
  820. begin
  821. if impintfindexes[i]=i then { if implement itself }
  822. begin
  823. { allocate a pointer in the object memory }
  824. with tstoredsymtable(_class.symtable) do
  825. begin
  826. if (dataalignment>=target_info.size_of_pointer) then
  827. datasize:=align(datasize,dataalignment)
  828. else
  829. datasize:=align(datasize,target_info.size_of_pointer);
  830. _class.implementedinterfaces.ioffsets(i)^:=datasize;
  831. datasize:=datasize+target_info.size_of_pointer;
  832. end;
  833. { write vtbl }
  834. gintfcreatevtbl(i,rawdata,rawcode);
  835. end;
  836. end;
  837. { second pass: for fill interfacetable and remained ioffsets }
  838. for i:=1 to max do
  839. begin
  840. if i<>impintfindexes[i] then { why execute x:=x ? }
  841. with _class.implementedinterfaces do
  842. ioffsets(i)^:=ioffsets(impintfindexes[i])^;
  843. gintfgenentry(i,impintfindexes[i],rawdata);
  844. end;
  845. dataSegment.concatlist(rawdata);
  846. rawdata.free;
  847. codeSegment.concatlist(rawcode);
  848. rawcode.free;
  849. freemem(impintfindexes,(max+1)*sizeof(longint));
  850. end;
  851. function tclassheader.gintfgetcprocdef(proc: tprocdef;const name: string): tprocdef;
  852. var
  853. sym: tprocsym;
  854. implprocdef : pprocdeflist;
  855. begin
  856. gintfgetcprocdef:=nil;
  857. sym:=tprocsym(search_class_member(_class,name));
  858. if assigned(sym) and (sym.typ=procsym) then
  859. begin
  860. implprocdef:=sym.defs;
  861. while assigned(implprocdef) do
  862. begin
  863. if equal_paras(proc.para,implprocdef^.def.para,cp_none) and
  864. (proc.proccalloption=implprocdef^.def.proccalloption) then
  865. begin
  866. gintfgetcprocdef:=implprocdef^.def;
  867. exit;
  868. end;
  869. implprocdef:=implprocdef^.next;
  870. end;
  871. end;
  872. end;
  873. procedure tclassheader.gintfdoonintf(intf: tobjectdef; intfindex: longint);
  874. var
  875. i: longint;
  876. proc: tprocdef;
  877. procname: string; { for error }
  878. mappedname: string;
  879. nextexist: pointer;
  880. implprocdef: tprocdef;
  881. begin
  882. for i:=1 to intf.symtable.defindex.count do
  883. begin
  884. proc:=tprocdef(intf.symtable.defindex.search(i));
  885. if proc.deftype=procdef then
  886. begin
  887. procname:='';
  888. implprocdef:=nil;
  889. nextexist:=nil;
  890. repeat
  891. mappedname:=_class.implementedinterfaces.getmappings(intfindex,proc.procsym.name,nextexist);
  892. if procname='' then
  893. procname:=proc.procsym.name;
  894. //mappedname; { for error messages }
  895. if mappedname<>'' then
  896. implprocdef:=gintfgetcprocdef(proc,mappedname);
  897. until assigned(implprocdef) or not assigned(nextexist);
  898. if not assigned(implprocdef) then
  899. implprocdef:=gintfgetcprocdef(proc,proc.procsym.name);
  900. if procname='' then
  901. procname:=proc.procsym.name;
  902. if assigned(implprocdef) then
  903. _class.implementedinterfaces.addimplproc(intfindex,implprocdef)
  904. else
  905. Message1(sym_e_id_not_found,procname);
  906. end;
  907. end;
  908. end;
  909. procedure tclassheader.gintfwalkdowninterface(intf: tobjectdef; intfindex: longint);
  910. begin
  911. if assigned(intf.childof) then
  912. gintfwalkdowninterface(intf.childof,intfindex);
  913. gintfdoonintf(intf,intfindex);
  914. end;
  915. function tclassheader.genintftable: tasmlabel;
  916. var
  917. intfindex: longint;
  918. curintf: tobjectdef;
  919. intftable: tasmlabel;
  920. begin
  921. { 1. step collect implementor functions into the implementedinterfaces.implprocs }
  922. for intfindex:=1 to _class.implementedinterfaces.count do
  923. begin
  924. curintf:=_class.implementedinterfaces.interfaces(intfindex);
  925. gintfwalkdowninterface(curintf,intfindex);
  926. end;
  927. { 2. step calc required fieldcount and their offsets in the object memory map
  928. and write data }
  929. getdatalabel(intftable);
  930. dataSegment.concat(Tai_label.Create(intftable));
  931. gintfwritedata;
  932. _class.implementedinterfaces.clearimplprocs; { release temporary information }
  933. genintftable:=intftable;
  934. end;
  935. { Write interface identifiers to the data section }
  936. procedure tclassheader.writeinterfaceids;
  937. var
  938. i: longint;
  939. s1,s2 : string;
  940. begin
  941. if _class.owner.name=nil then
  942. s1:=''
  943. else
  944. s1:=upper(_class.owner.name^);
  945. if _class.objname=nil then
  946. s2:=''
  947. else
  948. s2:=upper(_class.objname^);
  949. s1:=s1+'$_'+s2;
  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('IID$_'+s1,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('IIDSTR$_'+s1,0));
  964. dataSegment.concat(Tai_const.Create_8bit(length(_class.iidstr^)));
  965. dataSegment.concat(Tai_string.Create(_class.iidstr^));
  966. end;
  967. procedure tclassheader.writevirtualmethods(List:TAAsmoutput);
  968. var
  969. symcoll : psymcoll;
  970. procdefcoll : pprocdefcoll;
  971. i : longint;
  972. begin
  973. { walk trough all numbers for virtual methods and search }
  974. { the method }
  975. for i:=0 to nextvirtnumber-1 do
  976. begin
  977. symcoll:=wurzel;
  978. { walk trough all symbols }
  979. while assigned(symcoll) do
  980. begin
  981. { walk trough all methods }
  982. procdefcoll:=symcoll^.data;
  983. while assigned(procdefcoll) do
  984. begin
  985. { writes the addresses to the VMT }
  986. { but only this which are declared as virtual }
  987. if procdefcoll^.data.extnumber=i then
  988. begin
  989. if (po_virtualmethod in procdefcoll^.data.procoptions) then
  990. begin
  991. { if a method is abstract, then is also the }
  992. { class abstract and it's not allow to }
  993. { generates an instance }
  994. if (po_abstractmethod in procdefcoll^.data.procoptions) then
  995. begin
  996. include(_class.objectoptions,oo_has_abstract);
  997. List.concat(Tai_const_symbol.Createname('FPC_ABSTRACTERROR'));
  998. end
  999. else
  1000. begin
  1001. List.concat(Tai_const_symbol.createname(procdefcoll^.data.mangledname));
  1002. end;
  1003. end;
  1004. end;
  1005. procdefcoll:=procdefcoll^.next;
  1006. end;
  1007. symcoll:=symcoll^.next;
  1008. end;
  1009. end;
  1010. end;
  1011. { generates the vmt for classes as well as for objects }
  1012. procedure tclassheader.writevmt;
  1013. var
  1014. methodnametable,intmessagetable,
  1015. strmessagetable,classnamelabel,
  1016. fieldtablelabel : tasmlabel;
  1017. {$ifdef WITHDMT}
  1018. dmtlabel : tasmlabel;
  1019. {$endif WITHDMT}
  1020. interfacetable : tasmlabel;
  1021. begin
  1022. {$ifdef WITHDMT}
  1023. dmtlabel:=gendmt;
  1024. {$endif WITHDMT}
  1025. if (cs_create_smart in aktmoduleswitches) then
  1026. dataSegment.concat(Tai_cut.Create);
  1027. { write tables for classes, this must be done before the actual
  1028. class is written, because we need the labels defined }
  1029. if is_class(_class) then
  1030. begin
  1031. { interface table }
  1032. if _class.implementedinterfaces.count>0 then
  1033. begin
  1034. if (cs_create_smart in aktmoduleswitches) then
  1035. codeSegment.concat(Tai_cut.Create);
  1036. interfacetable:=genintftable;
  1037. end;
  1038. methodnametable:=genpublishedmethodstable;
  1039. fieldtablelabel:=_class.generate_field_table;
  1040. { write class name }
  1041. getdatalabel(classnamelabel);
  1042. dataSegment.concat(Tai_label.Create(classnamelabel));
  1043. dataSegment.concat(Tai_const.Create_8bit(length(_class.objname^)));
  1044. dataSegment.concat(Tai_string.Create(_class.objname^));
  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. initialization
  1129. cclassheader:=tclassheader;
  1130. end.
  1131. {
  1132. $Log$
  1133. Revision 1.11 2001-11-20 18:49:43 peter
  1134. * require overload for cross object overloading
  1135. Revision 1.10 2001/11/18 20:18:54 peter
  1136. * use cp_value_equal_const instead of cp_all
  1137. Revision 1.9 2001/11/18 18:43:14 peter
  1138. * overloading supported in child classes
  1139. * fixed parsing of classes with private and virtual and overloaded
  1140. so it is compatible with delphi
  1141. Revision 1.8 2001/11/02 22:58:02 peter
  1142. * procsym definition rewrite
  1143. Revision 1.7 2001/10/25 21:22:35 peter
  1144. * calling convention rewrite
  1145. Revision 1.6 2001/10/20 19:28:38 peter
  1146. * interface 2 guid support
  1147. * guid constants support
  1148. Revision 1.5 2001/10/20 17:20:14 peter
  1149. * fixed generation of rtti for virtualmethods
  1150. Revision 1.4 2001/09/19 11:04:42 michael
  1151. * Smartlinking with interfaces fixed
  1152. * Better smartlinking for rtti and init tables
  1153. Revision 1.3 2001/08/30 20:13:53 peter
  1154. * rtti/init table updates
  1155. * rttisym for reusable global rtti/init info
  1156. * support published for interfaces
  1157. Revision 1.2 2001/08/22 21:16:20 florian
  1158. * some interfaces related problems regarding
  1159. mapping of interface implementions fixed
  1160. Revision 1.1 2001/04/21 13:37:16 peter
  1161. * made tclassheader using class of to implement cpu dependent code
  1162. Revision 1.20 2001/04/18 22:01:54 peter
  1163. * registration of targets and assemblers
  1164. Revision 1.19 2001/04/13 01:22:07 peter
  1165. * symtable change to classes
  1166. * range check generation and errors fixed, make cycle DEBUG=1 works
  1167. * memory leaks fixed
  1168. Revision 1.18 2001/04/04 21:30:43 florian
  1169. * applied several fixes to get the DD8 Delphi Unit compiled
  1170. e.g. "forward"-interfaces are working now
  1171. Revision 1.17 2000/12/25 00:07:26 peter
  1172. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  1173. tlinkedlist objects)
  1174. Revision 1.16 2000/11/29 00:30:30 florian
  1175. * unused units removed from uses clause
  1176. * some changes for widestrings
  1177. Revision 1.15 2000/11/19 16:23:35 florian
  1178. *** empty log message ***
  1179. Revision 1.14 2000/11/12 23:24:10 florian
  1180. * interfaces are basically running
  1181. Revision 1.13 2000/11/08 00:07:40 florian
  1182. * potential range check error fixed
  1183. Revision 1.12 2000/11/06 23:13:53 peter
  1184. * uppercase manglednames
  1185. Revision 1.11 2000/11/04 17:31:00 florian
  1186. * fixed some problems of previous commit
  1187. Revision 1.10 2000/11/04 14:25:19 florian
  1188. + merged Attila's changes for interfaces, not tested yet
  1189. Revision 1.9 2000/11/01 23:04:37 peter
  1190. * tprocdef.fullprocname added for better casesensitve writing of
  1191. procedures
  1192. Revision 1.8 2000/10/31 22:02:47 peter
  1193. * symtable splitted, no real code changes
  1194. Revision 1.7 2000/10/14 10:14:47 peter
  1195. * moehrendorf oct 2000 rewrite
  1196. Revision 1.6 2000/09/24 21:19:50 peter
  1197. * delphi compile fixes
  1198. Revision 1.5 2000/09/24 15:06:17 peter
  1199. * use defines.inc
  1200. Revision 1.4 2000/08/27 16:11:51 peter
  1201. * moved some util functions from globals,cobjects to cutils
  1202. * splitted files into finput,fmodule
  1203. Revision 1.3 2000/07/13 12:08:26 michael
  1204. + patched to 1.1.0 with former 1.09patch from peter
  1205. Revision 1.2 2000/07/13 11:32:41 michael
  1206. + removed logs
  1207. }