nobj.pas 52 KB

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