nobj.pas 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Routines for the code generation of data structures
  4. like VMT, Messages, VTables, Interfaces descs
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit nobj;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. cutils,cclasses,
  23. globtype,
  24. symdef,symsym,
  25. aasmbase,aasmtai,aasmdata
  26. ;
  27. type
  28. pprocdeftree = ^tprocdeftree;
  29. tprocdeftree = record
  30. data : tprocdef;
  31. nl : tasmlabel;
  32. l,r : pprocdeftree;
  33. end;
  34. pprocdefcoll = ^tprocdefcoll;
  35. tprocdefcoll = record
  36. data : tprocdef;
  37. hidden : boolean;
  38. visible : boolean;
  39. next : pprocdefcoll;
  40. end;
  41. pvmtentry = ^tvmtentry;
  42. tvmtentry = record
  43. speedvalue : cardinal;
  44. name : pshortstring;
  45. firstprocdef : pprocdefcoll;
  46. next : pvmtentry;
  47. end;
  48. tclassheader=class
  49. private
  50. _Class : tobjectdef;
  51. private
  52. { message tables }
  53. root : pprocdeftree;
  54. procedure disposeprocdeftree(p : pprocdeftree);
  55. procedure insertmsgint(p : tnamedindexitem;arg:pointer);
  56. procedure insertmsgstr(p : tnamedindexitem;arg:pointer);
  57. procedure insertint(p : pprocdeftree;var at : pprocdeftree;var count:longint);
  58. procedure insertstr(p : pprocdeftree;var at : pprocdeftree;var count:longint);
  59. procedure writenames(p : pprocdeftree);
  60. procedure writeintentry(p : pprocdeftree);
  61. procedure writestrentry(p : pprocdeftree);
  62. {$ifdef WITHDMT}
  63. private
  64. { dmt }
  65. procedure insertdmtentry(p : tnamedindexitem;arg:pointer);
  66. procedure writedmtindexentry(p : pprocdeftree);
  67. procedure writedmtaddressentry(p : pprocdeftree);
  68. {$endif}
  69. private
  70. { published methods }
  71. procedure do_count_published_methods(p : tnamedindexitem;arg:pointer);
  72. procedure do_gen_published_methods(p : tnamedindexitem;arg:pointer);
  73. private
  74. { vmt }
  75. firstvmtentry : pvmtentry;
  76. nextvirtnumber : integer;
  77. has_constructor,
  78. has_virtual_method : boolean;
  79. procedure newdefentry(vmtentry:pvmtentry;pd:tprocdef;is_visible:boolean);
  80. function newvmtentry(sym:tprocsym):pvmtentry;
  81. procedure eachsym(sym : tnamedindexitem;arg:pointer);
  82. procedure disposevmttree;
  83. procedure writevirtualmethods(List:TAsmList);
  84. private
  85. { interface tables }
  86. function intf_get_vtbl_name(AImplIntf:TImplementedInterface): string;
  87. procedure intf_create_vtbl(rawdata: TAsmList;AImplIntf:TImplementedInterface);
  88. procedure intf_gen_intf_ref(rawdata: TAsmList;AImplIntf:TImplementedInterface);
  89. procedure intf_optimize_vtbls;
  90. procedure intf_write_data;
  91. function intf_search_procdef_by_name(proc: tprocdef;const name: string): tprocdef;
  92. procedure intf_get_procdefs(ImplIntf:TImplementedInterface;IntfDef:TObjectDef);
  93. procedure intf_get_procdefs_recursive(ImplIntf:TImplementedInterface;IntfDef:TObjectDef);
  94. public
  95. constructor create(c:tobjectdef);
  96. destructor destroy;override;
  97. { generates the message tables for a class }
  98. function genstrmsgtab : tasmlabel;
  99. function genintmsgtab : tasmlabel;
  100. function genpublishedmethodstable : tasmlabel;
  101. { generates a VMT entries }
  102. procedure genvmt;
  103. {$ifdef WITHDMT}
  104. { generates a DMT for _class }
  105. function gendmt : tasmlabel;
  106. {$endif WITHDMT}
  107. { interfaces }
  108. function genintftable: tasmlabel;
  109. { write the VMT to al_globals }
  110. procedure writevmt;
  111. procedure writeinterfaceids;
  112. end;
  113. implementation
  114. uses
  115. SysUtils,
  116. globals,verbose,systems,
  117. symtable,symconst,symtype,defcmp,
  118. dbgbase
  119. ;
  120. {*****************************************************************************
  121. TClassHeader
  122. *****************************************************************************}
  123. constructor tclassheader.create(c:tobjectdef);
  124. begin
  125. inherited Create;
  126. _Class:=c;
  127. end;
  128. destructor tclassheader.destroy;
  129. begin
  130. disposevmttree;
  131. end;
  132. {**************************************
  133. Message Tables
  134. **************************************}
  135. procedure tclassheader.disposeprocdeftree(p : pprocdeftree);
  136. begin
  137. if assigned(p^.l) then
  138. disposeprocdeftree(p^.l);
  139. if assigned(p^.r) then
  140. disposeprocdeftree(p^.r);
  141. dispose(p);
  142. end;
  143. procedure tclassheader.insertint(p : pprocdeftree;var at : pprocdeftree;var count:longint);
  144. begin
  145. if at=nil then
  146. begin
  147. at:=p;
  148. inc(count);
  149. end
  150. else
  151. begin
  152. if p^.data.messageinf.i<at^.data.messageinf.i then
  153. insertint(p,at^.l,count)
  154. else if p^.data.messageinf.i>at^.data.messageinf.i then
  155. insertint(p,at^.r,count)
  156. else
  157. Message1(parser_e_duplicate_message_label,tostr(p^.data.messageinf.i));
  158. end;
  159. end;
  160. procedure tclassheader.insertstr(p : pprocdeftree;var at : pprocdeftree;var count:longint);
  161. var
  162. i : integer;
  163. begin
  164. if at=nil then
  165. begin
  166. at:=p;
  167. inc(count);
  168. end
  169. else
  170. begin
  171. i:=CompareStr(p^.data.messageinf.str^,at^.data.messageinf.str^);
  172. if i<0 then
  173. insertstr(p,at^.l,count)
  174. else if i>0 then
  175. insertstr(p,at^.r,count)
  176. else
  177. Message1(parser_e_duplicate_message_label,p^.data.messageinf.str^);
  178. end;
  179. end;
  180. procedure tclassheader.insertmsgint(p : tnamedindexitem;arg:pointer);
  181. var
  182. i : cardinal;
  183. def: Tprocdef;
  184. pt : pprocdeftree;
  185. begin
  186. if tsym(p).typ=procsym then
  187. for i:=1 to Tprocsym(p).procdef_count do
  188. begin
  189. def:=Tprocsym(p).procdef[i];
  190. if po_msgint in def.procoptions then
  191. begin
  192. new(pt);
  193. pt^.data:=def;
  194. pt^.l:=nil;
  195. pt^.r:=nil;
  196. insertint(pt,root,plongint(arg)^);
  197. end;
  198. end;
  199. end;
  200. procedure tclassheader.insertmsgstr(p : tnamedindexitem;arg:pointer);
  201. var
  202. i : cardinal;
  203. def: Tprocdef;
  204. pt : pprocdeftree;
  205. begin
  206. if tsym(p).typ=procsym then
  207. for i:=1 to Tprocsym(p).procdef_count do
  208. begin
  209. def:=Tprocsym(p).procdef[i];
  210. if po_msgstr in def.procoptions then
  211. begin
  212. new(pt);
  213. pt^.data:=def;
  214. pt^.l:=nil;
  215. pt^.r:=nil;
  216. insertstr(pt,root,plongint(arg)^);
  217. end;
  218. end;
  219. end;
  220. procedure tclassheader.writenames(p : pprocdeftree);
  221. var
  222. ca : pchar;
  223. len : byte;
  224. begin
  225. current_asmdata.getdatalabel(p^.nl);
  226. if assigned(p^.l) then
  227. writenames(p^.l);
  228. current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(aint))));
  229. current_asmdata.asmlists[al_globals].concat(Tai_label.Create(p^.nl));
  230. len:=length(p^.data.messageinf.str^);
  231. current_asmdata.asmlists[al_globals].concat(tai_const.create_8bit(len));
  232. getmem(ca,len+1);
  233. move(p^.data.messageinf.str[1],ca^,len);
  234. ca[len]:=#0;
  235. current_asmdata.asmlists[al_globals].concat(Tai_string.Create_pchar(ca,len));
  236. if assigned(p^.r) then
  237. writenames(p^.r);
  238. end;
  239. procedure tclassheader.writestrentry(p : pprocdeftree);
  240. begin
  241. if assigned(p^.l) then
  242. writestrentry(p^.l);
  243. { write name label }
  244. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(p^.nl));
  245. current_asmdata.asmlists[al_globals].concat(Tai_const.Createname(p^.data.mangledname,0));
  246. if assigned(p^.r) then
  247. writestrentry(p^.r);
  248. end;
  249. function tclassheader.genstrmsgtab : tasmlabel;
  250. var
  251. count : aint;
  252. begin
  253. root:=nil;
  254. count:=0;
  255. { insert all message handlers into a tree, sorted by name }
  256. _class.symtable.foreach(@insertmsgstr,@count);
  257. { write all names }
  258. if assigned(root) then
  259. writenames(root);
  260. { now start writing of the message string table }
  261. current_asmdata.getdatalabel(result);
  262. current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(aint))));
  263. current_asmdata.asmlists[al_globals].concat(Tai_label.Create(result));
  264. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_aint(count));
  265. if assigned(root) then
  266. begin
  267. writestrentry(root);
  268. disposeprocdeftree(root);
  269. end;
  270. end;
  271. procedure tclassheader.writeintentry(p : pprocdeftree);
  272. begin
  273. if assigned(p^.l) then
  274. writeintentry(p^.l);
  275. { write name label }
  276. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_32bit(p^.data.messageinf.i));
  277. current_asmdata.asmlists[al_globals].concat(Tai_const.Createname(p^.data.mangledname,0));
  278. if assigned(p^.r) then
  279. writeintentry(p^.r);
  280. end;
  281. function tclassheader.genintmsgtab : tasmlabel;
  282. var
  283. r : tasmlabel;
  284. count : longint;
  285. begin
  286. root:=nil;
  287. count:=0;
  288. { insert all message handlers into a tree, sorted by name }
  289. _class.symtable.foreach(@insertmsgint,@count);
  290. { now start writing of the message string table }
  291. current_asmdata.getdatalabel(r);
  292. current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(aint))));
  293. current_asmdata.asmlists[al_globals].concat(Tai_label.Create(r));
  294. genintmsgtab:=r;
  295. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_32bit(count));
  296. if assigned(root) then
  297. begin
  298. writeintentry(root);
  299. disposeprocdeftree(root);
  300. end;
  301. end;
  302. {$ifdef WITHDMT}
  303. {**************************************
  304. DMT
  305. **************************************}
  306. procedure tclassheader.insertdmtentry(p : tnamedindexitem;arg:pointer);
  307. var
  308. hp : tprocdef;
  309. pt : pprocdeftree;
  310. begin
  311. if tsym(p).typ=procsym then
  312. begin
  313. hp:=tprocsym(p).definition;
  314. while assigned(hp) do
  315. begin
  316. if (po_msgint in hp.procoptions) then
  317. begin
  318. new(pt);
  319. pt^.p:=hp;
  320. pt^.l:=nil;
  321. pt^.r:=nil;
  322. insertint(pt,root);
  323. end;
  324. hp:=hp.nextoverloaded;
  325. end;
  326. end;
  327. end;
  328. procedure tclassheader.writedmtindexentry(p : pprocdeftree);
  329. begin
  330. if assigned(p^.l) then
  331. writedmtindexentry(p^.l);
  332. al_globals.concat(Tai_const.Create_32bit(p^.data.messageinf.i));
  333. if assigned(p^.r) then
  334. writedmtindexentry(p^.r);
  335. end;
  336. procedure tclassheader.writedmtaddressentry(p : pprocdeftree);
  337. begin
  338. if assigned(p^.l) then
  339. writedmtaddressentry(p^.l);
  340. al_globals.concat(Tai_const_symbol.Createname(p^.data.mangledname,0));
  341. if assigned(p^.r) then
  342. writedmtaddressentry(p^.r);
  343. end;
  344. function tclassheader.gendmt : tasmlabel;
  345. var
  346. r : tasmlabel;
  347. begin
  348. root:=nil;
  349. count:=0;
  350. gendmt:=nil;
  351. { insert all message handlers into a tree, sorted by number }
  352. _class.symtable.foreach(insertdmtentry);
  353. if count>0 then
  354. begin
  355. current_asmdata.getdatalabel(r);
  356. gendmt:=r;
  357. al_globals.concat(cai_align.create(const_align(sizeof(aint))));
  358. al_globals.concat(Tai_label.Create(r));
  359. { entries for caching }
  360. al_globals.concat(Tai_const.Create_ptr(0));
  361. al_globals.concat(Tai_const.Create_ptr(0));
  362. al_globals.concat(Tai_const.Create_32bit(count));
  363. if assigned(root) then
  364. begin
  365. writedmtindexentry(root);
  366. writedmtaddressentry(root);
  367. disposeprocdeftree(root);
  368. end;
  369. end;
  370. end;
  371. {$endif WITHDMT}
  372. {**************************************
  373. Published Methods
  374. **************************************}
  375. procedure tclassheader.do_count_published_methods(p : tnamedindexitem;arg:pointer);
  376. var
  377. i : longint;
  378. pd : tprocdef;
  379. begin
  380. if (tsym(p).typ=procsym) then
  381. begin
  382. for i:=1 to tprocsym(p).procdef_count do
  383. begin
  384. pd:=tprocsym(p).procdef[i];
  385. if (pd.procsym=tsym(p)) and
  386. (sp_published in pd.symoptions) then
  387. inc(plongint(arg)^);
  388. end;
  389. end;
  390. end;
  391. procedure tclassheader.do_gen_published_methods(p : tnamedindexitem;arg:pointer);
  392. var
  393. i : longint;
  394. l : tasmlabel;
  395. pd : tprocdef;
  396. begin
  397. if (tsym(p).typ=procsym) then
  398. begin
  399. for i:=1 to tprocsym(p).procdef_count do
  400. begin
  401. pd:=tprocsym(p).procdef[i];
  402. if (pd.procsym=tsym(p)) and
  403. (sp_published in pd.symoptions) then
  404. begin
  405. current_asmdata.getdatalabel(l);
  406. current_asmdata.asmlists[al_typedconsts].concat(cai_align.create(const_align(sizeof(aint))));
  407. current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(l));
  408. current_asmdata.asmlists[al_typedconsts].concat(Tai_const.Create_8bit(length(tsym(p).realname)));
  409. current_asmdata.asmlists[al_typedconsts].concat(Tai_string.Create(tsym(p).realname));
  410. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(l));
  411. if po_abstractmethod in pd.procoptions then
  412. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil))
  413. else
  414. current_asmdata.asmlists[al_globals].concat(Tai_const.Createname(pd.mangledname,0));
  415. end;
  416. end;
  417. end;
  418. end;
  419. function tclassheader.genpublishedmethodstable : tasmlabel;
  420. var
  421. l : tasmlabel;
  422. count : longint;
  423. begin
  424. count:=0;
  425. _class.symtable.foreach(@do_count_published_methods,@count);
  426. if count>0 then
  427. begin
  428. current_asmdata.getdatalabel(l);
  429. current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(aint))));
  430. current_asmdata.asmlists[al_globals].concat(Tai_label.Create(l));
  431. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_32bit(count));
  432. _class.symtable.foreach(@do_gen_published_methods,nil);
  433. genpublishedmethodstable:=l;
  434. end
  435. else
  436. genpublishedmethodstable:=nil;
  437. end;
  438. {**************************************
  439. VMT
  440. **************************************}
  441. procedure tclassheader.newdefentry(vmtentry:pvmtentry;pd:tprocdef;is_visible:boolean);
  442. var
  443. procdefcoll : pprocdefcoll;
  444. begin
  445. if (_class=pd._class) then
  446. begin
  447. { new entry is needed, override was not possible }
  448. if (po_overridingmethod in pd.procoptions) then
  449. MessagePos1(pd.fileinfo,parser_e_nothing_to_be_overridden,pd.fullprocname(false));
  450. { check that all methods have overload directive }
  451. if not(m_fpc in current_settings.modeswitches) then
  452. begin
  453. procdefcoll:=vmtentry^.firstprocdef;
  454. while assigned(procdefcoll) do
  455. begin
  456. if (procdefcoll^.data._class=pd._class) and
  457. ((po_overload in pd.procoptions)<>(po_overload in procdefcoll^.data.procoptions)) then
  458. begin
  459. MessagePos1(pd.fileinfo,parser_e_no_overload_for_all_procs,pd.procsym.realname);
  460. { recover }
  461. include(procdefcoll^.data.procoptions,po_overload);
  462. include(pd.procoptions,po_overload);
  463. end;
  464. procdefcoll:=procdefcoll^.next;
  465. end;
  466. end;
  467. end;
  468. { generate new entry }
  469. new(procdefcoll);
  470. procdefcoll^.data:=pd;
  471. procdefcoll^.hidden:=false;
  472. procdefcoll^.visible:=is_visible;
  473. procdefcoll^.next:=vmtentry^.firstprocdef;
  474. vmtentry^.firstprocdef:=procdefcoll;
  475. { give virtual method a number }
  476. if (po_virtualmethod in pd.procoptions) then
  477. begin
  478. pd.extnumber:=nextvirtnumber;
  479. inc(nextvirtnumber);
  480. has_virtual_method:=true;
  481. end;
  482. if (pd.proctypeoption=potype_constructor) then
  483. has_constructor:=true;
  484. end;
  485. function tclassheader.newvmtentry(sym:tprocsym):pvmtentry;
  486. begin
  487. { generate new vmtentry }
  488. new(result);
  489. result^.speedvalue:=sym.speedvalue;
  490. result^.name:=stringdup(sym.name);
  491. result^.next:=firstvmtentry;
  492. result^.firstprocdef:=nil;
  493. firstvmtentry:=result;
  494. end;
  495. procedure tclassheader.eachsym(sym : tnamedindexitem;arg:pointer);
  496. const
  497. po_comp = [po_classmethod,po_virtualmethod,po_staticmethod,po_interrupt,po_iocheck,po_msgstr,po_msgint,
  498. po_exports,po_varargs,po_explicitparaloc,po_nostackframe];
  499. label
  500. handlenextdef;
  501. var
  502. pd : tprocdef;
  503. i : cardinal;
  504. is_visible,
  505. hasoverloads,
  506. pdoverload : boolean;
  507. procdefcoll : pprocdefcoll;
  508. vmtentry : pvmtentry;
  509. _name : string;
  510. _speed : cardinal;
  511. begin
  512. if (tsym(sym).typ<>procsym) then
  513. exit;
  514. { check the current list of symbols }
  515. _name:=sym.name;
  516. _speed:=sym.speedvalue;
  517. vmtentry:=firstvmtentry;
  518. while assigned(vmtentry) do
  519. begin
  520. { does the symbol already exist in the list? First
  521. compare speedvalue before doing the string compare to
  522. speed it up a little }
  523. if (_speed=vmtentry^.speedvalue) and
  524. (_name=vmtentry^.name^) then
  525. begin
  526. hasoverloads:=(Tprocsym(sym).procdef_count>1);
  527. { walk through all defs of the symbol }
  528. for i:=1 to Tprocsym(sym).procdef_count do
  529. begin
  530. pd:=Tprocsym(sym).procdef[i];
  531. { is this procdef visible from the class that we are
  532. generating. This will be used to hide the other procdefs.
  533. When the symbol is not visible we don't hide the other
  534. procdefs, because they can be reused in the next class.
  535. The check to skip the invisible methods that are in the
  536. list is futher down in the code }
  537. is_visible:=pd.is_visible_for_object(_class,nil);
  538. if pd.procsym=sym then
  539. begin
  540. pdoverload:=(po_overload in pd.procoptions);
  541. { compare with all stored definitions }
  542. procdefcoll:=vmtentry^.firstprocdef;
  543. while assigned(procdefcoll) do
  544. begin
  545. { compare only if the definition is not hidden }
  546. if not procdefcoll^.hidden then
  547. begin
  548. { check if one of the two methods has virtual }
  549. if (po_virtualmethod in procdefcoll^.data.procoptions) or
  550. (po_virtualmethod in pd.procoptions) then
  551. begin
  552. { if the current definition has no virtual then hide the
  553. old virtual if the new definition has the same arguments or
  554. when it has no overload directive and no overloads }
  555. if not(po_virtualmethod in pd.procoptions) then
  556. begin
  557. if procdefcoll^.visible and
  558. (not(pdoverload or hasoverloads) or
  559. (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal)) then
  560. begin
  561. if is_visible then
  562. procdefcoll^.hidden:=true;
  563. if (_class=pd._class) and not(po_reintroduce in pd.procoptions) then
  564. MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false));
  565. end;
  566. end
  567. { if both are virtual we check the header }
  568. else if (po_virtualmethod in pd.procoptions) and
  569. (po_virtualmethod in procdefcoll^.data.procoptions) then
  570. begin
  571. { new one has not override }
  572. if is_class(_class) and
  573. not(po_overridingmethod in pd.procoptions) then
  574. begin
  575. { we start a new virtual tree, hide the old }
  576. if (not(pdoverload or hasoverloads) or
  577. (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal)) and
  578. (procdefcoll^.visible) then
  579. begin
  580. if is_visible then
  581. procdefcoll^.hidden:=true;
  582. if (_class=pd._class) and not(po_reintroduce in pd.procoptions) then
  583. MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false));
  584. end;
  585. end
  586. { same parameters }
  587. else if (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal) then
  588. begin
  589. { overload is inherited }
  590. if (po_overload in procdefcoll^.data.procoptions) then
  591. include(pd.procoptions,po_overload);
  592. { inherite calling convention when it was force and the
  593. current definition has none force }
  594. if (po_hascallingconvention in procdefcoll^.data.procoptions) and
  595. not(po_hascallingconvention in pd.procoptions) then
  596. begin
  597. pd.proccalloption:=procdefcoll^.data.proccalloption;
  598. include(pd.procoptions,po_hascallingconvention);
  599. end;
  600. { the flags have to match except abstract and override }
  601. { only if both are virtual !! }
  602. if (procdefcoll^.data.proccalloption<>pd.proccalloption) or
  603. (procdefcoll^.data.proctypeoption<>pd.proctypeoption) or
  604. ((procdefcoll^.data.procoptions*po_comp)<>(pd.procoptions*po_comp)) then
  605. begin
  606. MessagePos1(pd.fileinfo,parser_e_header_dont_match_forward,pd.fullprocname(false));
  607. tprocsym(procdefcoll^.data.procsym).write_parameter_lists(pd);
  608. end;
  609. { error, if the return types aren't equal }
  610. if not(equal_defs(procdefcoll^.data.returndef,pd.returndef)) and
  611. not((procdefcoll^.data.returndef.deftype=objectdef) and
  612. (pd.returndef.deftype=objectdef) and
  613. is_class_or_interface(procdefcoll^.data.returndef) and
  614. is_class_or_interface(pd.returndef) and
  615. (tobjectdef(pd.returndef).is_related(
  616. tobjectdef(procdefcoll^.data.returndef)))) then
  617. begin
  618. if not((m_delphi in current_settings.modeswitches) and
  619. is_interface(_class)) then
  620. Message2(parser_e_overridden_methods_not_same_ret,pd.fullprocname(false),
  621. procdefcoll^.data.fullprocname(false))
  622. else
  623. { Delphi allows changing the result type }
  624. { of interface methods from anything to }
  625. { anything (JM) }
  626. Message2(parser_w_overridden_methods_not_same_ret,pd.fullprocname(false),
  627. procdefcoll^.data.fullprocname(false));
  628. end;
  629. { check if the method to override is visible, check is only needed
  630. for the current parsed class. Parent classes are already validated and
  631. need to include all virtual methods including the ones not visible in the
  632. current class }
  633. if (_class=pd._class) and
  634. (po_overridingmethod in pd.procoptions) and
  635. (not procdefcoll^.visible) then
  636. MessagePos1(pd.fileinfo,parser_e_nothing_to_be_overridden,pd.fullprocname(false));
  637. { override old virtual method in VMT }
  638. pd.extnumber:=procdefcoll^.data.extnumber;
  639. procdefcoll^.data:=pd;
  640. if is_visible then
  641. procdefcoll^.visible:=true;
  642. goto handlenextdef;
  643. end
  644. { different parameters }
  645. else
  646. begin
  647. { when we got an override directive then can search futher for
  648. the procedure to override.
  649. If we are starting a new virtual tree then hide the old tree }
  650. if not(po_overridingmethod in pd.procoptions) and
  651. not pdoverload then
  652. begin
  653. if is_visible then
  654. procdefcoll^.hidden:=true;
  655. if (_class=pd._class) and not(po_reintroduce in pd.procoptions) then
  656. MessagePos1(pd.fileinfo,parser_w_should_use_override,pd.fullprocname(false));
  657. end;
  658. end;
  659. end
  660. else
  661. begin
  662. { the new definition is virtual and the old static, we hide the old one
  663. if the new defintion has not the overload directive }
  664. if is_visible and
  665. ((not(pdoverload or hasoverloads)) or
  666. (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal)) then
  667. procdefcoll^.hidden:=true;
  668. end;
  669. end
  670. else
  671. begin
  672. { both are static, we hide the old one if the new defintion
  673. has not the overload directive }
  674. if is_visible and
  675. ((not pdoverload) or
  676. (compare_paras(procdefcoll^.data.paras,pd.paras,cp_all,[])>=te_equal)) then
  677. procdefcoll^.hidden:=true;
  678. end;
  679. end; { not hidden }
  680. procdefcoll:=procdefcoll^.next;
  681. end;
  682. { if it isn't saved in the list we create a new entry }
  683. newdefentry(vmtentry,pd,is_visible);
  684. end;
  685. handlenextdef:
  686. end;
  687. exit;
  688. end;
  689. vmtentry:=vmtentry^.next;
  690. end;
  691. { Generate new procsym entry in vmt }
  692. vmtentry:=newvmtentry(tprocsym(sym));
  693. { Add procdefs }
  694. for i:=1 to Tprocsym(sym).procdef_count do
  695. begin
  696. pd:=Tprocsym(sym).procdef[i];
  697. newdefentry(vmtentry,pd,pd.is_visible_for_object(_class,nil));
  698. end;
  699. end;
  700. procedure tclassheader.disposevmttree;
  701. var
  702. vmtentry : pvmtentry;
  703. procdefcoll : pprocdefcoll;
  704. begin
  705. { disposes the above generated tree }
  706. vmtentry:=firstvmtentry;
  707. while assigned(vmtentry) do
  708. begin
  709. firstvmtentry:=vmtentry^.next;
  710. stringdispose(vmtentry^.name);
  711. procdefcoll:=vmtentry^.firstprocdef;
  712. while assigned(procdefcoll) do
  713. begin
  714. vmtentry^.firstprocdef:=procdefcoll^.next;
  715. dispose(procdefcoll);
  716. procdefcoll:=vmtentry^.firstprocdef;
  717. end;
  718. dispose(vmtentry);
  719. vmtentry:=firstvmtentry;
  720. end;
  721. end;
  722. procedure tclassheader.genvmt;
  723. procedure do_genvmt(p : tobjectdef);
  724. begin
  725. { start with the base class }
  726. if assigned(p.childof) then
  727. do_genvmt(p.childof);
  728. { walk through all public syms }
  729. p.symtable.foreach(@eachsym,nil);
  730. end;
  731. begin
  732. firstvmtentry:=nil;
  733. nextvirtnumber:=0;
  734. has_constructor:=false;
  735. has_virtual_method:=false;
  736. { generates a tree of all used methods }
  737. do_genvmt(_class);
  738. if not(is_interface(_class)) and
  739. has_virtual_method and
  740. not(has_constructor) then
  741. Message1(parser_w_virtual_without_constructor,_class.objrealname^);
  742. end;
  743. {**************************************
  744. Interface tables
  745. **************************************}
  746. function tclassheader.intf_get_vtbl_name(AImplIntf:TImplementedInterface): string;
  747. begin
  748. result:=make_mangledname('VTBL',_class.owner,_class.objname^+'_$_'+AImplIntf.IntfDef.objname^);
  749. end;
  750. procedure tclassheader.intf_create_vtbl(rawdata: TAsmList;AImplIntf:TImplementedInterface);
  751. var
  752. pd : tprocdef;
  753. vtblstr,
  754. hs : string;
  755. i : longint;
  756. begin
  757. vtblstr:=intf_get_vtbl_name(AImplIntf);
  758. section_symbol_start(rawdata,vtblstr,AT_DATA,true,sec_data,const_align(sizeof(aint)));
  759. if assigned(AImplIntf.procdefs) then
  760. begin
  761. for i:=0 to AImplIntf.procdefs.count-1 do
  762. begin
  763. pd:=tprocdef(AImplIntf.procdefs[i]);
  764. hs:=make_mangledname('WRPR',_class.owner,_class.objname^+'_$_'+AImplIntf.IntfDef.objname^+'_$_'+
  765. tostr(i)+'_$_'+pd.mangledname);
  766. { create reference }
  767. rawdata.concat(Tai_const.Createname(hs,0));
  768. end;
  769. end;
  770. section_symbol_end(rawdata,vtblstr);
  771. end;
  772. procedure tclassheader.intf_gen_intf_ref(rawdata: TAsmList;AImplIntf:TImplementedInterface);
  773. var
  774. iidlabel,
  775. guidlabel : tasmlabel;
  776. i: longint;
  777. begin
  778. { GUID }
  779. if AImplIntf.IntfDef.objecttype in [odt_interfacecom] then
  780. begin
  781. { label for GUID }
  782. current_asmdata.getdatalabel(guidlabel);
  783. rawdata.concat(cai_align.create(const_align(sizeof(aint))));
  784. rawdata.concat(Tai_label.Create(guidlabel));
  785. with AImplIntf.IntfDef.iidguid^ do
  786. begin
  787. rawdata.concat(Tai_const.Create_32bit(longint(D1)));
  788. rawdata.concat(Tai_const.Create_16bit(D2));
  789. rawdata.concat(Tai_const.Create_16bit(D3));
  790. for i:=Low(D4) to High(D4) do
  791. rawdata.concat(Tai_const.Create_8bit(D4[i]));
  792. end;
  793. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(guidlabel));
  794. end
  795. else
  796. begin
  797. { nil for Corba interfaces }
  798. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil));
  799. end;
  800. { VTable }
  801. current_asmdata.asmlists[al_globals].concat(Tai_const.Createname(intf_get_vtbl_name(AImplIntf.VtblImplIntf),0));
  802. { IOffset field }
  803. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_aint(AImplIntf.VtblImplIntf.ioffset));
  804. { IIDStr }
  805. current_asmdata.getdatalabel(iidlabel);
  806. rawdata.concat(cai_align.create(const_align(sizeof(aint))));
  807. rawdata.concat(Tai_label.Create(iidlabel));
  808. rawdata.concat(Tai_const.Create_8bit(length(AImplIntf.IntfDef.iidstr^)));
  809. if AImplIntf.IntfDef.objecttype=odt_interfacecom then
  810. rawdata.concat(Tai_string.Create(upper(AImplIntf.IntfDef.iidstr^)))
  811. else
  812. rawdata.concat(Tai_string.Create(AImplIntf.IntfDef.iidstr^));
  813. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(iidlabel));
  814. { EntryType }
  815. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_aint(aint(AImplIntf.IntfDef.iitype)));
  816. { EntryOffset }
  817. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_aint(aint(AImplIntf.IntfDef.iioffset)));
  818. end;
  819. procedure tclassheader.intf_optimize_vtbls;
  820. type
  821. tcompintfentry = record
  822. weight: longint;
  823. compintf: longint;
  824. end;
  825. { Max 1000 interface in the class header interfaces it's enough imho }
  826. tcompintfs = array[0..1000] of tcompintfentry;
  827. pcompintfs = ^tcompintfs;
  828. tequals = array[0..1000] of longint;
  829. pequals = ^tequals;
  830. timpls = array[0..1000] of longint;
  831. pimpls = ^timpls;
  832. var
  833. equals: pequals;
  834. compats: pcompintfs;
  835. impls: pimpls;
  836. ImplIntfCount,
  837. w,i,j,k: longint;
  838. ImplIntfI,
  839. ImplIntfJ : TImplementedInterface;
  840. cij: boolean;
  841. cji: boolean;
  842. begin
  843. ImplIntfCount:=_class.ImplementedInterfaces.count;
  844. if ImplIntfCount>=High(tequals) then
  845. Internalerror(200006135);
  846. getmem(compats,sizeof(tcompintfentry)*ImplIntfCount);
  847. getmem(equals,sizeof(longint)*ImplIntfCount);
  848. getmem(impls,sizeof(longint)*ImplIntfCount);
  849. filldword(compats^,(sizeof(tcompintfentry) div sizeof(dword))*ImplIntfCount,dword(-1));
  850. filldword(equals^,ImplIntfCount,dword(-1));
  851. filldword(impls^,ImplIntfCount,dword(-1));
  852. { ismergepossible is a containing relation
  853. meaning of ismergepossible(a,b,w) =
  854. if implementorfunction map of a is contained implementorfunction map of b
  855. imp(a,b) and imp(b,c) => imp(a,c) ; imp(a,b) and imp(b,a) => a == b
  856. }
  857. { the order is very important for correct allocation }
  858. for i:=0 to ImplIntfCount-1 do
  859. begin
  860. for j:=i+1 to ImplIntfCount-1 do
  861. begin
  862. ImplIntfI:=TImplementedInterface(_class.ImplementedInterfaces[i]);
  863. ImplIntfJ:=TImplementedInterface(_class.ImplementedInterfaces[j]);
  864. cij:=ImplIntfI.IsImplMergePossible(ImplIntfJ,w);
  865. cji:=ImplIntfJ.IsImplMergePossible(ImplIntfI,w);
  866. if cij and cji then { i equal j }
  867. begin
  868. { get minimum index of equal }
  869. if equals^[j]=-1 then
  870. equals^[j]:=i;
  871. end
  872. else if cij then
  873. begin
  874. { get minimum index of maximum weight }
  875. if compats^[i].weight<w then
  876. begin
  877. compats^[i].weight:=w;
  878. compats^[i].compintf:=j;
  879. end;
  880. end
  881. else if cji then
  882. begin
  883. { get minimum index of maximum weight }
  884. if (compats^[j].weight<w) then
  885. begin
  886. compats^[j].weight:=w;
  887. compats^[j].compintf:=i;
  888. end;
  889. end;
  890. end;
  891. end;
  892. { Reset, no replacements by default }
  893. for i:=0 to ImplIntfCount-1 do
  894. impls^[i]:=i;
  895. { Replace vtbls when equal or compat, repeat
  896. until there are no replacements possible anymore. This is
  897. needed for the cases like:
  898. First loop: 2->3, 3->1
  899. Second loop: 2->1 (because 3 was replaced with 1)
  900. }
  901. repeat
  902. k:=0;
  903. for i:=0 to ImplIntfCount-1 do
  904. begin
  905. if compats^[impls^[i]].compintf<>-1 then
  906. impls^[i]:=compats^[impls^[i]].compintf
  907. else if equals^[impls^[i]]<>-1 then
  908. impls^[i]:=equals^[impls^[i]]
  909. else
  910. inc(k);
  911. end;
  912. until k=ImplIntfCount;
  913. { Update the VtblImplIntf }
  914. for i:=0 to ImplIntfCount-1 do
  915. begin
  916. ImplIntfI:=TImplementedInterface(_class.ImplementedInterfaces[i]);
  917. ImplIntfI.VtblImplIntf:=TImplementedInterface(_class.ImplementedInterfaces[impls^[i]]);
  918. end;
  919. freemem(compats);
  920. freemem(equals);
  921. freemem(impls);
  922. end;
  923. procedure tclassheader.intf_write_data;
  924. var
  925. rawdata : TAsmList;
  926. i : longint;
  927. ImplIntf : TImplementedInterface;
  928. begin
  929. rawdata:=TAsmList.Create;
  930. { Two pass, one for allocation and vtbl creation }
  931. for i:=0 to _class.ImplementedInterfaces.count-1 do
  932. begin
  933. ImplIntf:=TImplementedInterface(_class.ImplementedInterfaces[i]);
  934. { if it implements itself }
  935. if ImplIntf.VtblImplIntf=ImplIntf then
  936. begin
  937. { allocate a pointer in the object memory }
  938. with tobjectsymtable(_class.symtable) do
  939. begin
  940. datasize:=align(datasize,sizeof(aint));
  941. ImplIntf.Ioffset:=datasize;
  942. inc(datasize,sizeof(aint));
  943. end;
  944. { write vtbl }
  945. intf_create_vtbl(rawdata,ImplIntf);
  946. end;
  947. end;
  948. { second pass: for fill interfacetable and remained ioffsets }
  949. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_aint(_class.ImplementedInterfaces.count));
  950. for i:=0 to _class.ImplementedInterfaces.count-1 do
  951. begin
  952. ImplIntf:=TImplementedInterface(_class.ImplementedInterfaces[i]);
  953. { Update ioffset of current interface with the ioffset from
  954. the interface that is reused to implements this interface }
  955. if ImplIntf.VtblImplIntf<>ImplIntf then
  956. ImplIntf.Ioffset:=ImplIntf.VtblImplIntf.Ioffset;
  957. intf_gen_intf_ref(rawdata,ImplIntf);
  958. end;
  959. current_asmdata.asmlists[al_globals].concatlist(rawdata);
  960. rawdata.free;
  961. end;
  962. function tclassheader.intf_search_procdef_by_name(proc: tprocdef;const name: string): tprocdef;
  963. const
  964. po_comp = [po_classmethod,po_staticmethod,po_interrupt,po_iocheck,po_msgstr,po_msgint,
  965. po_exports,po_varargs,po_explicitparaloc,po_nostackframe];
  966. var
  967. sym: tsym;
  968. implprocdef : Tprocdef;
  969. i: cardinal;
  970. begin
  971. result:=nil;
  972. sym:=tsym(search_class_member(_class,name));
  973. if assigned(sym) and
  974. (sym.typ=procsym) then
  975. begin
  976. { when the definition has overload directive set, we search for
  977. overloaded definitions in the class, this only needs to be done once
  978. for class entries as the tree keeps always the same }
  979. if (not tprocsym(sym).overloadchecked) and
  980. (po_overload in tprocsym(sym).first_procdef.procoptions) and
  981. (tprocsym(sym).owner.symtabletype=objectsymtable) then
  982. search_class_overloads(tprocsym(sym));
  983. for i:=1 to tprocsym(sym).procdef_count do
  984. begin
  985. implprocdef:=tprocsym(sym).procdef[i];
  986. if (compare_paras(proc.paras,implprocdef.paras,cp_none,[])>=te_equal) and
  987. (proc.proccalloption=implprocdef.proccalloption) and
  988. (proc.proctypeoption=implprocdef.proctypeoption) and
  989. ((proc.procoptions*po_comp)=((implprocdef.procoptions+[po_virtualmethod])*po_comp)) then
  990. begin
  991. result:=implprocdef;
  992. exit;
  993. end;
  994. end;
  995. end;
  996. end;
  997. procedure tclassheader.intf_get_procdefs(ImplIntf:TImplementedInterface;IntfDef:TObjectDef);
  998. var
  999. def: tdef;
  1000. hs,
  1001. prefix,
  1002. mappedname: string;
  1003. implprocdef: tprocdef;
  1004. begin
  1005. prefix:=ImplIntf.IntfDef.symtable.name^+'.';
  1006. def:=tdef(IntfDef.symtable.defindex.first);
  1007. while assigned(def) do
  1008. begin
  1009. if def.deftype=procdef then
  1010. begin
  1011. { Find implementing procdef
  1012. 1. Check for mapped name
  1013. 2. Use symbol name }
  1014. implprocdef:=nil;
  1015. hs:=prefix+tprocdef(def).procsym.name;
  1016. mappedname:=ImplIntf.GetMapping(hs);
  1017. if mappedname<>'' then
  1018. implprocdef:=intf_search_procdef_by_name(tprocdef(def),mappedname);
  1019. if not assigned(implprocdef) then
  1020. implprocdef:=intf_search_procdef_by_name(tprocdef(def),tprocdef(def).procsym.name);
  1021. { Add procdef to the implemented interface }
  1022. if assigned(implprocdef) then
  1023. ImplIntf.AddImplProc(implprocdef)
  1024. else
  1025. if ImplIntf.IntfDef.iitype = etStandard then
  1026. Message1(sym_e_no_matching_implementation_found,tprocdef(def).fullprocname(false));
  1027. end;
  1028. def:=tdef(def.indexnext);
  1029. end;
  1030. end;
  1031. procedure tclassheader.intf_get_procdefs_recursive(ImplIntf:TImplementedInterface;IntfDef:TObjectDef);
  1032. begin
  1033. if assigned(IntfDef.childof) then
  1034. intf_get_procdefs_recursive(ImplIntf,IntfDef.childof);
  1035. intf_get_procdefs(ImplIntf,IntfDef);
  1036. end;
  1037. function tclassheader.genintftable: tasmlabel;
  1038. var
  1039. ImplIntf : TImplementedInterface;
  1040. intftable : tasmlabel;
  1041. i : longint;
  1042. begin
  1043. { 1. step collect implementor functions into the tImplementedInterface.procdefs }
  1044. for i:=0 to _class.ImplementedInterfaces.count-1 do
  1045. begin
  1046. ImplIntf:=TImplementedInterface(_class.ImplementedInterfaces[i]);
  1047. intf_get_procdefs_recursive(ImplIntf,ImplIntf.IntfDef);
  1048. end;
  1049. { 2. Optimize interface tables to reuse wrappers }
  1050. intf_optimize_vtbls;
  1051. { 3. Calculate offsets in object map and Write interface tables }
  1052. current_asmdata.getdatalabel(intftable);
  1053. current_asmdata.asmlists[al_globals].concat(cai_align.create(const_align(sizeof(aint))));
  1054. current_asmdata.asmlists[al_globals].concat(Tai_label.Create(intftable));
  1055. intf_write_data;
  1056. genintftable:=intftable;
  1057. end;
  1058. { Write interface identifiers to the data section }
  1059. procedure tclassheader.writeinterfaceids;
  1060. var
  1061. i : longint;
  1062. s : string;
  1063. begin
  1064. if assigned(_class.iidguid) then
  1065. begin
  1066. s:=make_mangledname('IID',_class.owner,_class.objname^);
  1067. maybe_new_object_file(current_asmdata.asmlists[al_globals]);
  1068. new_section(current_asmdata.asmlists[al_globals],sec_rodata,s,const_align(sizeof(aint)));
  1069. current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global(s,AT_DATA,0));
  1070. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_32bit(longint(_class.iidguid^.D1)));
  1071. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_16bit(_class.iidguid^.D2));
  1072. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_16bit(_class.iidguid^.D3));
  1073. for i:=Low(_class.iidguid^.D4) to High(_class.iidguid^.D4) do
  1074. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_8bit(_class.iidguid^.D4[i]));
  1075. end;
  1076. maybe_new_object_file(current_asmdata.asmlists[al_globals]);
  1077. s:=make_mangledname('IIDSTR',_class.owner,_class.objname^);
  1078. new_section(current_asmdata.asmlists[al_globals],sec_rodata,s,0);
  1079. current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global(s,AT_DATA,0));
  1080. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_8bit(length(_class.iidstr^)));
  1081. current_asmdata.asmlists[al_globals].concat(Tai_string.Create(_class.iidstr^));
  1082. end;
  1083. procedure tclassheader.writevirtualmethods(List:TAsmList);
  1084. var
  1085. vmtentry : pvmtentry;
  1086. procdefcoll : pprocdefcoll;
  1087. i : longint;
  1088. procname : string;
  1089. {$ifdef vtentry}
  1090. hs : string;
  1091. {$endif vtentry}
  1092. begin
  1093. { walk trough all numbers for virtual methods and search }
  1094. { the method }
  1095. for i:=0 to nextvirtnumber-1 do
  1096. begin
  1097. { walk trough all symbols }
  1098. vmtentry:=firstvmtentry;
  1099. while assigned(vmtentry) do
  1100. begin
  1101. { walk trough all methods }
  1102. procdefcoll:=vmtentry^.firstprocdef;
  1103. while assigned(procdefcoll) do
  1104. begin
  1105. { writes the addresses to the VMT }
  1106. { but only this which are declared as virtual }
  1107. if (procdefcoll^.data.extnumber=i) and
  1108. (po_virtualmethod in procdefcoll^.data.procoptions) then
  1109. begin
  1110. if (po_abstractmethod in procdefcoll^.data.procoptions) then
  1111. procname:='FPC_ABSTRACTERROR'
  1112. else
  1113. procname:=procdefcoll^.data.mangledname;
  1114. List.concat(Tai_const.createname(procname,0));
  1115. {$ifdef vtentry}
  1116. hs:='VTENTRY'+'_'+_class.vmt_mangledname+'$$'+tostr(_class.vmtmethodoffset(i) div sizeof(aint));
  1117. current_asmdata.asmlists[al_globals].concat(tai_symbol.CreateName(hs,AT_DATA,0));
  1118. {$endif vtentry}
  1119. break;
  1120. end;
  1121. procdefcoll:=procdefcoll^.next;
  1122. end;
  1123. vmtentry:=vmtentry^.next;
  1124. end;
  1125. end;
  1126. end;
  1127. { generates the vmt for classes as well as for objects }
  1128. procedure tclassheader.writevmt;
  1129. var
  1130. methodnametable,intmessagetable,
  1131. strmessagetable,classnamelabel,
  1132. fieldtablelabel : tasmlabel;
  1133. {$ifdef WITHDMT}
  1134. dmtlabel : tasmlabel;
  1135. {$endif WITHDMT}
  1136. interfacetable : tasmlabel;
  1137. {$ifdef vtentry}
  1138. hs: string;
  1139. {$endif vtentry}
  1140. begin
  1141. {$ifdef WITHDMT}
  1142. dmtlabel:=gendmt;
  1143. {$endif WITHDMT}
  1144. { write tables for classes, this must be done before the actual
  1145. class is written, because we need the labels defined }
  1146. if is_class(_class) then
  1147. begin
  1148. current_asmdata.getdatalabel(classnamelabel);
  1149. maybe_new_object_file(current_asmdata.asmlists[al_globals]);
  1150. new_section(current_asmdata.asmlists[al_globals],sec_rodata,classnamelabel.name,const_align(sizeof(aint)));
  1151. { interface table }
  1152. if _class.ImplementedInterfaces.count>0 then
  1153. interfacetable:=genintftable;
  1154. methodnametable:=genpublishedmethodstable;
  1155. fieldtablelabel:=_class.generate_field_table;
  1156. { write class name }
  1157. current_asmdata.asmlists[al_globals].concat(Tai_label.Create(classnamelabel));
  1158. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_8bit(length(_class.objrealname^)));
  1159. current_asmdata.asmlists[al_globals].concat(Tai_string.Create(_class.objrealname^));
  1160. { generate message and dynamic tables }
  1161. if (oo_has_msgstr in _class.objectoptions) then
  1162. strmessagetable:=genstrmsgtab;
  1163. if (oo_has_msgint in _class.objectoptions) then
  1164. intmessagetable:=genintmsgtab;
  1165. end;
  1166. { write debug info }
  1167. maybe_new_object_file(current_asmdata.asmlists[al_globals]);
  1168. new_section(current_asmdata.asmlists[al_globals],sec_rodata,_class.vmt_mangledname,const_align(sizeof(aint)));
  1169. current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global(_class.vmt_mangledname,AT_DATA,0));
  1170. { determine the size with symtable.datasize, because }
  1171. { size gives back 4 for classes }
  1172. current_asmdata.asmlists[al_globals].concat(Tai_const.Create(aitconst_ptr,tobjectsymtable(_class.symtable).datasize));
  1173. current_asmdata.asmlists[al_globals].concat(Tai_const.Create(aitconst_ptr,-int64(tobjectsymtable(_class.symtable).datasize)));
  1174. {$ifdef WITHDMT}
  1175. if _class.classtype=ct_object then
  1176. begin
  1177. if assigned(dmtlabel) then
  1178. current_asmdata.asmlists[al_globals].concat(Tai_const_symbol.Create(dmtlabel)))
  1179. else
  1180. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_ptr(0));
  1181. end;
  1182. {$endif WITHDMT}
  1183. { write pointer to parent VMT, this isn't implemented in TP }
  1184. { but this is not used in FPC ? (PM) }
  1185. { it's not used yet, but the delphi-operators as and is need it (FK) }
  1186. { it is not written for parents that don't have any vmt !! }
  1187. if assigned(_class.childof) and
  1188. (oo_has_vmt in _class.childof.objectoptions) then
  1189. current_asmdata.asmlists[al_globals].concat(Tai_const.Createname(_class.childof.vmt_mangledname,0))
  1190. else
  1191. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil));
  1192. { write extended info for classes, for the order see rtl/inc/objpash.inc }
  1193. if is_class(_class) then
  1194. begin
  1195. { pointer to class name string }
  1196. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(classnamelabel));
  1197. { pointer to dynamic table or nil }
  1198. if (oo_has_msgint in _class.objectoptions) then
  1199. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(intmessagetable))
  1200. else
  1201. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil));
  1202. { pointer to method table or nil }
  1203. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(methodnametable));
  1204. { pointer to field table }
  1205. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(fieldtablelabel));
  1206. { pointer to type info of published section }
  1207. if (oo_can_have_published in _class.objectoptions) then
  1208. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(_class.get_rtti_label(fullrtti)))
  1209. else
  1210. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil));
  1211. { inittable for con-/destruction }
  1212. if _class.members_need_inittable then
  1213. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(_class.get_rtti_label(initrtti)))
  1214. else
  1215. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil));
  1216. { auto table }
  1217. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil));
  1218. { interface table }
  1219. if _class.ImplementedInterfaces.count>0 then
  1220. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(interfacetable))
  1221. else
  1222. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil));
  1223. { table for string messages }
  1224. if (oo_has_msgstr in _class.objectoptions) then
  1225. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(strmessagetable))
  1226. else
  1227. current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil));
  1228. end;
  1229. { write virtual methods }
  1230. writevirtualmethods(current_asmdata.asmlists[al_globals]);
  1231. current_asmdata.asmlists[al_globals].concat(Tai_const.create(aitconst_ptr,0));
  1232. { write the size of the VMT }
  1233. current_asmdata.asmlists[al_globals].concat(Tai_symbol_end.Createname(_class.vmt_mangledname));
  1234. {$ifdef vtentry}
  1235. { write vtinherit symbol to notify the linker of the class inheritance tree }
  1236. hs:='VTINHERIT'+'_'+_class.vmt_mangledname+'$$';
  1237. if assigned(_class.childof) then
  1238. hs:=hs+_class.childof.vmt_mangledname
  1239. else
  1240. hs:=hs+_class.vmt_mangledname;
  1241. current_asmdata.asmlists[al_globals].concat(tai_symbol.CreateName(hs,AT_DATA,0));
  1242. {$endif vtentry}
  1243. end;
  1244. end.