nobj.pas 52 KB

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