ncgrtti.pas 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. Routines for the code generation of RTTI data structures
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit ncgrtti;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. cclasses,
  22. aasmbase,
  23. symbase,symconst,symtype,symdef;
  24. type
  25. { TRTTIWriter }
  26. TRTTIWriter=class
  27. private
  28. function fields_count(st:tsymtable;rt:trttitype):longint;
  29. procedure fields_write_rtti(st:tsymtable;rt:trttitype);
  30. procedure fields_write_rtti_data(st:tsymtable;rt:trttitype);
  31. procedure write_rtti_extrasyms(def:Tdef;rt:Trttitype;mainrtti:Tasmsymbol);
  32. procedure published_write_rtti(st:tsymtable;rt:trttitype);
  33. function published_properties_count(st:tsymtable):longint;
  34. procedure published_properties_write_rtti_data(propnamelist:TFPHashObjectList;st:tsymtable);
  35. procedure collect_propnamelist(propnamelist:TFPHashObjectList;objdef:tobjectdef);
  36. procedure write_rtti_name(def:tdef);
  37. procedure write_rtti_data(def:tdef;rt:trttitype);
  38. procedure write_child_rtti_data(def:tdef;rt:trttitype);
  39. function ref_rtti(def:tdef;rt:trttitype):tasmsymbol;
  40. public
  41. procedure write_rtti(def:tdef;rt:trttitype);
  42. function get_rtti_label(def:tdef;rt:trttitype):tasmsymbol;
  43. function get_rtti_label_ord2str(def:tdef;rt:trttitype):tasmsymbol;
  44. function get_rtti_label_str2ord(def:tdef;rt:trttitype):tasmsymbol;
  45. end;
  46. var
  47. RTTIWriter : TRTTIWriter;
  48. implementation
  49. uses
  50. cutils,
  51. globals,globtype,verbose,systems,
  52. fmodule,
  53. symsym,
  54. aasmtai,aasmdata
  55. ;
  56. const
  57. rttidefstate : array[trttitype] of tdefstate = (ds_rtti_table_written,ds_init_table_written);
  58. type
  59. TPropNameListItem = class(TFPHashObject)
  60. propindex : longint;
  61. propowner : TSymtable;
  62. end;
  63. {***************************************************************************
  64. TRTTIWriter
  65. ***************************************************************************}
  66. procedure TRTTIWriter.write_rtti_name(def:tdef);
  67. var
  68. hs : string;
  69. begin
  70. { name }
  71. if assigned(def.typesym) then
  72. begin
  73. hs:=ttypesym(def.typesym).realname;
  74. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(chr(length(hs))+hs));
  75. end
  76. else
  77. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(#0));
  78. end;
  79. function TRTTIWriter.fields_count(st:tsymtable;rt:trttitype):longint;
  80. var
  81. i : longint;
  82. sym : tsym;
  83. begin
  84. result:=0;
  85. for i:=0 to st.SymList.Count-1 do
  86. begin
  87. sym:=tsym(st.SymList[i]);
  88. if (rt=fullrtti) or
  89. (
  90. (tsym(sym).typ=fieldvarsym) and
  91. tfieldvarsym(sym).vardef.needs_inittable
  92. ) then
  93. inc(result);
  94. end;
  95. end;
  96. procedure TRTTIWriter.fields_write_rtti_data(st:tsymtable;rt:trttitype);
  97. var
  98. i : longint;
  99. sym : tsym;
  100. begin
  101. for i:=0 to st.SymList.Count-1 do
  102. begin
  103. sym:=tsym(st.SymList[i]);
  104. if (rt=fullrtti) or
  105. (
  106. (tsym(sym).typ=fieldvarsym) and
  107. tfieldvarsym(sym).vardef.needs_inittable
  108. ) then
  109. begin
  110. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(tfieldvarsym(sym).vardef,rt)));
  111. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(tfieldvarsym(sym).fieldoffset));
  112. end;
  113. end;
  114. end;
  115. procedure TRTTIWriter.fields_write_rtti(st:tsymtable;rt:trttitype);
  116. var
  117. i : longint;
  118. sym : tsym;
  119. begin
  120. for i:=0 to st.SymList.Count-1 do
  121. begin
  122. sym:=tsym(st.SymList[i]);
  123. if (rt=fullrtti) or
  124. (
  125. (tsym(sym).typ=fieldvarsym) and
  126. tfieldvarsym(sym).vardef.needs_inittable
  127. ) then
  128. write_rtti(tfieldvarsym(sym).vardef,rt);
  129. end;
  130. end;
  131. procedure TRTTIWriter.published_write_rtti(st:tsymtable;rt:trttitype);
  132. var
  133. i : longint;
  134. sym : tsym;
  135. begin
  136. for i:=0 to st.SymList.Count-1 do
  137. begin
  138. sym:=tsym(st.SymList[i]);
  139. if (sp_published in tsym(sym).symoptions) then
  140. begin
  141. case tsym(sym).typ of
  142. propertysym:
  143. write_rtti(tpropertysym(sym).propdef,rt);
  144. fieldvarsym:
  145. write_rtti(tfieldvarsym(sym).vardef,rt);
  146. end;
  147. end;
  148. end;
  149. end;
  150. function TRTTIWriter.published_properties_count(st:tsymtable):longint;
  151. var
  152. i : longint;
  153. sym : tsym;
  154. begin
  155. result:=0;
  156. for i:=0 to st.SymList.Count-1 do
  157. begin
  158. sym:=tsym(st.SymList[i]);
  159. if (tsym(sym).typ=propertysym) and
  160. (sp_published in tsym(sym).symoptions) then
  161. inc(result);
  162. end;
  163. end;
  164. procedure TRTTIWriter.collect_propnamelist(propnamelist:TFPHashObjectList;objdef:tobjectdef);
  165. var
  166. i : longint;
  167. sym : tsym;
  168. pn : tpropnamelistitem;
  169. begin
  170. if assigned(objdef.childof) then
  171. collect_propnamelist(propnamelist,objdef.childof);
  172. for i:=0 to objdef.symtable.SymList.Count-1 do
  173. begin
  174. sym:=tsym(objdef.symtable.SymList[i]);
  175. if (tsym(sym).typ=propertysym) and
  176. (sp_published in tsym(sym).symoptions) then
  177. begin
  178. pn:=TPropNameListItem(propnamelist.Find(tsym(sym).name));
  179. if not assigned(pn) then
  180. begin
  181. pn:=tpropnamelistitem.create(propnamelist,tsym(sym).name);
  182. pn.propindex:=propnamelist.count-1;
  183. pn.propowner:=tsym(sym).owner;
  184. end;
  185. end;
  186. end;
  187. end;
  188. procedure TRTTIWriter.published_properties_write_rtti_data(propnamelist:TFPHashObjectList;st:tsymtable);
  189. var
  190. i : longint;
  191. sym : tsym;
  192. proctypesinfo : byte;
  193. propnameitem : tpropnamelistitem;
  194. procedure writeaccessproc(pap:tpropaccesslisttypes; shiftvalue : byte; unsetvalue: byte);
  195. var
  196. typvalue : byte;
  197. hp : ppropaccesslistitem;
  198. address : longint;
  199. def : tdef;
  200. hpropsym : tpropertysym;
  201. propaccesslist : tpropaccesslist;
  202. begin
  203. hpropsym:=tpropertysym(sym);
  204. repeat
  205. propaccesslist:=hpropsym.propaccesslist[pap];
  206. if not propaccesslist.empty then
  207. break;
  208. hpropsym:=hpropsym.overridenpropsym;
  209. until not assigned(hpropsym);
  210. if not(assigned(propaccesslist) and assigned(propaccesslist.firstsym)) then
  211. begin
  212. current_asmdata.asmlists[al_rtti].concat(Tai_const.create(aitconst_ptr,unsetvalue));
  213. typvalue:=3;
  214. end
  215. else if propaccesslist.firstsym^.sym.typ=fieldvarsym then
  216. begin
  217. address:=0;
  218. hp:=propaccesslist.firstsym;
  219. def:=nil;
  220. while assigned(hp) do
  221. begin
  222. case hp^.sltype of
  223. sl_load :
  224. begin
  225. def:=tfieldvarsym(hp^.sym).vardef;
  226. inc(address,tfieldvarsym(hp^.sym).fieldoffset);
  227. end;
  228. sl_subscript :
  229. begin
  230. if not(assigned(def) and (def.typ=recorddef)) then
  231. internalerror(200402171);
  232. inc(address,tfieldvarsym(hp^.sym).fieldoffset);
  233. def:=tfieldvarsym(hp^.sym).vardef;
  234. end;
  235. sl_vec :
  236. begin
  237. if not(assigned(def) and (def.typ=arraydef)) then
  238. internalerror(200402172);
  239. def:=tarraydef(def).elementdef;
  240. inc(address,def.size*hp^.value);
  241. end;
  242. end;
  243. hp:=hp^.next;
  244. end;
  245. current_asmdata.asmlists[al_rtti].concat(Tai_const.create(aitconst_ptr,address));
  246. typvalue:=0;
  247. end
  248. else
  249. begin
  250. { When there was an error then procdef is not assigned }
  251. if not assigned(propaccesslist.procdef) then
  252. exit;
  253. if not(po_virtualmethod in tprocdef(propaccesslist.procdef).procoptions) then
  254. begin
  255. current_asmdata.asmlists[al_rtti].concat(Tai_const.createname(tprocdef(propaccesslist.procdef).mangledname,0));
  256. typvalue:=1;
  257. end
  258. else
  259. begin
  260. { virtual method, write vmt offset }
  261. current_asmdata.asmlists[al_rtti].concat(Tai_const.create(aitconst_ptr,
  262. tprocdef(propaccesslist.procdef)._class.vmtmethodoffset(tprocdef(propaccesslist.procdef).extnumber)));
  263. typvalue:=2;
  264. end;
  265. end;
  266. proctypesinfo:=proctypesinfo or (typvalue shl shiftvalue);
  267. end;
  268. begin
  269. for i:=0 to st.SymList.Count-1 do
  270. begin
  271. sym:=tsym(st.SymList[i]);
  272. if (sym.typ=propertysym) and
  273. (sp_published in sym.symoptions) then
  274. begin
  275. if ppo_indexed in tpropertysym(sym).propoptions then
  276. proctypesinfo:=$40
  277. else
  278. proctypesinfo:=0;
  279. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(tpropertysym(sym).propdef,fullrtti)));
  280. writeaccessproc(palt_read,0,0);
  281. writeaccessproc(palt_write,2,0);
  282. { is it stored ? }
  283. if not(ppo_stored in tpropertysym(sym).propoptions) then
  284. begin
  285. { no, so put a constant zero }
  286. current_asmdata.asmlists[al_rtti].concat(Tai_const.create(aitconst_ptr,0));
  287. proctypesinfo:=proctypesinfo or (3 shl 4);
  288. end
  289. else
  290. writeaccessproc(palt_stored,4,1); { maybe; if no procedure put a constant 1 (=true) }
  291. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(tpropertysym(sym).index));
  292. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(tpropertysym(sym).default));
  293. propnameitem:=TPropNameListItem(propnamelist.Find(tpropertysym(sym).name));
  294. if not assigned(propnameitem) then
  295. internalerror(200512201);
  296. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(propnameitem.propindex));
  297. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(proctypesinfo));
  298. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(tpropertysym(sym).realname)));
  299. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(tpropertysym(sym).realname));
  300. if (tf_requires_proper_alignment in target_info.flags) then
  301. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  302. end;
  303. end;
  304. end;
  305. procedure TRTTIWriter.write_rtti_data(def:tdef;rt:trttitype);
  306. procedure unknown_rtti(def:tstoreddef);
  307. begin
  308. current_asmdata.asmlists[al_rtti].concat(tai_const.create_8bit(tkUnknown));
  309. write_rtti_name(def);
  310. end;
  311. procedure variantdef_rtti(def:tvariantdef);
  312. begin
  313. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkVariant));
  314. end;
  315. procedure stringdef_rtti(def:tstringdef);
  316. begin
  317. case def.stringtype of
  318. st_ansistring:
  319. begin
  320. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkAString));
  321. write_rtti_name(def);
  322. end;
  323. st_widestring:
  324. begin
  325. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkWString));
  326. write_rtti_name(def);
  327. end;
  328. st_longstring:
  329. begin
  330. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkLString));
  331. write_rtti_name(def);
  332. end;
  333. st_shortstring:
  334. begin
  335. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkSString));
  336. write_rtti_name(def);
  337. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(def.len));
  338. if (tf_requires_proper_alignment in target_info.flags) then
  339. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  340. end;
  341. end;
  342. end;
  343. procedure enumdef_rtti(def:tenumdef);
  344. var
  345. hp : tenumsym;
  346. begin
  347. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkEnumeration));
  348. write_rtti_name(def);
  349. if (tf_requires_proper_alignment in target_info.flags) then
  350. current_asmdata.asmlists[al_rtti].concat(Cai_align.Create(sizeof(TConstPtrUInt)));
  351. case longint(def.size) of
  352. 1 :
  353. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(otUByte));
  354. 2 :
  355. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(otUWord));
  356. 4 :
  357. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(otULong));
  358. end;
  359. if (tf_requires_proper_alignment in target_info.flags) then
  360. current_asmdata.asmlists[al_rtti].concat(Cai_align.Create(sizeof(TConstPtrUInt)));
  361. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(def.min));
  362. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(def.max));
  363. if assigned(def.basedef) then
  364. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.basedef,rt)))
  365. else
  366. current_asmdata.asmlists[al_rtti].concat(Tai_const.create_sym(nil));
  367. hp:=tenumsym(def.firstenum);
  368. while assigned(hp) do
  369. begin
  370. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(hp.realname)));
  371. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(hp.realname));
  372. hp:=hp.nextenum;
  373. end;
  374. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(0));
  375. end;
  376. procedure orddef_rtti(def:torddef);
  377. procedure dointeger;
  378. const
  379. trans : array[tordtype] of byte =
  380. (otUByte{otNone},
  381. otUByte,otUWord,otULong,otUByte{otNone},
  382. otSByte,otSWord,otSLong,otUByte{otNone},
  383. otUByte,otUWord,otULong,otUByte,
  384. otUByte,otUWord,otUByte);
  385. begin
  386. write_rtti_name(def);
  387. if (tf_requires_proper_alignment in target_info.flags) then
  388. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  389. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(byte(trans[def.ordtype])));
  390. if (tf_requires_proper_alignment in target_info.flags) then
  391. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  392. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(longint(def.low)));
  393. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(longint(def.high)));
  394. end;
  395. begin
  396. case def.ordtype of
  397. s64bit :
  398. begin
  399. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkInt64));
  400. write_rtti_name(def);
  401. if (tf_requires_proper_alignment in target_info.flags) then
  402. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  403. { low }
  404. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_64bit(int64($80000000) shl 32));
  405. { high }
  406. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_64bit((int64($7fffffff) shl 32) or int64($ffffffff)));
  407. end;
  408. u64bit :
  409. begin
  410. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkQWord));
  411. write_rtti_name(def);
  412. if (tf_requires_proper_alignment in target_info.flags) then
  413. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  414. { low }
  415. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_64bit(0));
  416. { high }
  417. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_64bit(int64((int64($ffffffff) shl 32) or int64($ffffffff))));
  418. end;
  419. bool8bit:
  420. begin
  421. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkBool));
  422. dointeger;
  423. end;
  424. uchar:
  425. begin
  426. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkChar));
  427. dointeger;
  428. end;
  429. uwidechar:
  430. begin
  431. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkWChar));
  432. dointeger;
  433. end;
  434. else
  435. begin
  436. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkInteger));
  437. dointeger;
  438. end;
  439. end;
  440. end;
  441. procedure floatdef_rtti(def:tfloatdef);
  442. const
  443. {tfloattype = (s32real,s64real,s80real,s64bit,s128bit);}
  444. translate : array[tfloattype] of byte =
  445. (ftSingle,ftDouble,ftExtended,ftComp,ftCurr,ftFloat128);
  446. begin
  447. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkFloat));
  448. write_rtti_name(def);
  449. if (tf_requires_proper_alignment in target_info.flags) then
  450. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  451. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(translate[def.floattype]));
  452. end;
  453. procedure setdef_rtti(def:tsetdef);
  454. begin
  455. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkSet));
  456. write_rtti_name(def);
  457. if (tf_requires_proper_alignment in target_info.flags) then
  458. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  459. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(otULong));
  460. if (tf_requires_proper_alignment in target_info.flags) then
  461. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  462. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.elementdef,rt)));
  463. end;
  464. procedure arraydef_rtti(def:tarraydef);
  465. begin
  466. if ado_IsDynamicArray in def.arrayoptions then
  467. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkdynarray))
  468. else
  469. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkarray));
  470. write_rtti_name(def);
  471. if (tf_requires_proper_alignment in target_info.flags) then
  472. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  473. { size of elements }
  474. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_aint(def.elesize));
  475. if not(ado_IsDynamicArray in def.arrayoptions) then
  476. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_aint(def.elecount));
  477. { element type }
  478. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.elementdef,rt)));
  479. { variant type }
  480. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(tstoreddef(def.elementdef).getvardef));
  481. end;
  482. procedure recorddef_rtti(def:trecorddef);
  483. var
  484. fieldcnt : longint;
  485. begin
  486. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkrecord));
  487. write_rtti_name(def);
  488. if (tf_requires_proper_alignment in target_info.flags) then
  489. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  490. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(def.size));
  491. fieldcnt:=fields_count(def.symtable,rt);
  492. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(fieldcnt));
  493. fields_write_rtti_data(def.symtable,rt);
  494. end;
  495. procedure procvardef_rtti(def:tprocvardef);
  496. procedure write_para(parasym:tparavarsym);
  497. var
  498. paraspec : byte;
  499. begin
  500. { only store user visible parameters }
  501. if not(vo_is_hidden_para in parasym.varoptions) then
  502. begin
  503. case parasym.varspez of
  504. vs_value: paraspec := 0;
  505. vs_const: paraspec := pfConst;
  506. vs_var : paraspec := pfVar;
  507. vs_out : paraspec := pfOut;
  508. end;
  509. { write flags for current parameter }
  510. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(paraspec));
  511. { write name of current parameter }
  512. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(parasym.realname)));
  513. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(parasym.realname));
  514. { write name of type of current parameter }
  515. write_rtti_name(parasym.vardef);
  516. end;
  517. end;
  518. var
  519. methodkind : byte;
  520. i : integer;
  521. begin
  522. if po_methodpointer in def.procoptions then
  523. begin
  524. { write method id and name }
  525. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkmethod));
  526. write_rtti_name(def);
  527. if (tf_requires_proper_alignment in target_info.flags) then
  528. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  529. { write kind of method (can only be function or procedure)}
  530. if def.returndef = voidtype then
  531. methodkind := mkProcedure
  532. else
  533. methodkind := mkFunction;
  534. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(methodkind));
  535. { write parameter info. The parameters must be written in reverse order
  536. if this method uses right to left parameter pushing! }
  537. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(def.maxparacount));
  538. if def.proccalloption in pushleftright_pocalls then
  539. begin
  540. for i:=0 to def.paras.count-1 do
  541. write_para(tparavarsym(def.paras[i]));
  542. end
  543. else
  544. begin
  545. for i:=def.paras.count-1 downto 0 do
  546. write_para(tparavarsym(def.paras[i]));
  547. end;
  548. { write name of result type }
  549. write_rtti_name(def.returndef);
  550. end
  551. else
  552. begin
  553. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkprocvar));
  554. write_rtti_name(def);
  555. end;
  556. end;
  557. procedure objectdef_rtti(def:tobjectdef);
  558. procedure objectdef_rtti_class_init(def:tobjectdef);
  559. begin
  560. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(def.size));
  561. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(fields_count(def.symtable,rt)));
  562. fields_write_rtti_data(def.symtable,rt);
  563. end;
  564. procedure objectdef_rtti_interface_init(def:tobjectdef);
  565. begin
  566. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(def.size));
  567. end;
  568. procedure objectdef_rtti_class_full(def:tobjectdef);
  569. var
  570. propnamelist : TFPHashObjectList;
  571. begin
  572. { Collect unique property names with nameindex }
  573. propnamelist:=TFPHashObjectList.Create;
  574. collect_propnamelist(propnamelist,def);
  575. if (oo_has_vmt in def.objectoptions) then
  576. current_asmdata.asmlists[al_rtti].concat(Tai_const.Createname(def.vmt_mangledname,0))
  577. else
  578. current_asmdata.asmlists[al_rtti].concat(Tai_const.create_sym(nil));
  579. { write parent typeinfo }
  580. if assigned(def.childof) and
  581. (oo_can_have_published in def.childof.objectoptions) then
  582. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.childof,fullrtti)))
  583. else
  584. current_asmdata.asmlists[al_rtti].concat(Tai_const.create_sym(nil));
  585. { total number of unique properties }
  586. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(propnamelist.count));
  587. { write unit name }
  588. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(current_module.realmodulename^)));
  589. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(current_module.realmodulename^));
  590. if (tf_requires_proper_alignment in target_info.flags) then
  591. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  592. { write published properties for this object }
  593. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(published_properties_count(def.symtable)));
  594. if (tf_requires_proper_alignment in target_info.flags) then
  595. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  596. published_properties_write_rtti_data(propnamelist,def.symtable);
  597. propnamelist.free;
  598. end;
  599. procedure objectdef_rtti_interface_full(def:tobjectdef);
  600. var
  601. i : longint;
  602. propnamelist : TFPHashObjectList;
  603. begin
  604. { Collect unique property names with nameindex }
  605. propnamelist:=TFPHashObjectList.Create;
  606. collect_propnamelist(propnamelist,def);
  607. { write parent typeinfo }
  608. if assigned(def.childof) then
  609. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.childof,fullrtti)))
  610. else
  611. current_asmdata.asmlists[al_rtti].concat(Tai_const.create_sym(nil));
  612. { interface: write flags, iid and iidstr }
  613. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(
  614. { ugly, but working }
  615. {$ifdef USE_PACKSET1}
  616. byte([
  617. {$else USE_PACKSET1}
  618. longint([
  619. {$endif USE_PACKSET1}
  620. TCompilerIntfFlag(ord(ifHasGuid)*ord(assigned(def.iidguid))),
  621. TCompilerIntfFlag(ord(ifHasStrGUID)*ord(assigned(def.iidstr))),
  622. TCompilerIntfFlag(ord(ifDispInterface)*ord(def.objecttype=odt_dispinterface))
  623. ])
  624. {
  625. ifDispatch, }
  626. ));
  627. if (tf_requires_proper_alignment in target_info.flags) then
  628. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  629. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(longint(def.iidguid^.D1)));
  630. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(def.iidguid^.D2));
  631. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(def.iidguid^.D3));
  632. for i:=Low(def.iidguid^.D4) to High(def.iidguid^.D4) do
  633. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(def.iidguid^.D4[i]));
  634. { write unit name }
  635. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(current_module.realmodulename^)));
  636. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(current_module.realmodulename^));
  637. if (tf_requires_proper_alignment in target_info.flags) then
  638. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  639. { write iidstr }
  640. if assigned(def.iidstr) then
  641. begin
  642. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(def.iidstr^)));
  643. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(def.iidstr^));
  644. end
  645. else
  646. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(0));
  647. if (tf_requires_proper_alignment in target_info.flags) then
  648. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  649. { write published properties for this object }
  650. published_properties_write_rtti_data(propnamelist,def.symtable);
  651. propnamelist.free;
  652. end;
  653. begin
  654. case def.objecttype of
  655. odt_class:
  656. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkclass));
  657. odt_object:
  658. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkobject));
  659. odt_dispinterface,
  660. odt_interfacecom:
  661. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkinterface));
  662. odt_interfacecorba:
  663. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkinterfaceCorba));
  664. else
  665. internalerror(200611034);
  666. end;
  667. { generate the name }
  668. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(def.objrealname^)));
  669. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(def.objrealname^));
  670. if (tf_requires_proper_alignment in target_info.flags) then
  671. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  672. case rt of
  673. initrtti :
  674. begin
  675. if def.objecttype in [odt_class,odt_object] then
  676. objectdef_rtti_class_init(def)
  677. else
  678. objectdef_rtti_interface_init(def);
  679. end;
  680. fullrtti :
  681. begin
  682. if def.objecttype in [odt_class,odt_object] then
  683. objectdef_rtti_class_full(def)
  684. else
  685. objectdef_rtti_interface_full(def);
  686. end;
  687. end;
  688. end;
  689. begin
  690. case def.typ of
  691. variantdef :
  692. variantdef_rtti(tvariantdef(def));
  693. stringdef :
  694. stringdef_rtti(tstringdef(def));
  695. enumdef :
  696. enumdef_rtti(tenumdef(def));
  697. orddef :
  698. orddef_rtti(torddef(def));
  699. floatdef :
  700. floatdef_rtti(tfloatdef(def));
  701. setdef :
  702. setdef_rtti(tsetdef(def));
  703. procvardef :
  704. procvardef_rtti(tprocvardef(def));
  705. arraydef :
  706. begin
  707. if ado_IsBitPacked in tarraydef(def).arrayoptions then
  708. unknown_rtti(tstoreddef(def))
  709. else
  710. arraydef_rtti(tarraydef(def));
  711. end;
  712. recorddef :
  713. begin
  714. if trecorddef(def).is_packed then
  715. unknown_rtti(tstoreddef(def))
  716. else
  717. recorddef_rtti(trecorddef(def));
  718. end;
  719. objectdef :
  720. objectdef_rtti(tobjectdef(def));
  721. else
  722. unknown_rtti(tstoreddef(def));
  723. end;
  724. end;
  725. procedure TRTTIWriter.write_rtti_extrasyms(def:Tdef;rt:Trttitype;mainrtti:Tasmsymbol);
  726. procedure enumdef_rtti_ord2stringindex(def:Tenumdef);
  727. var rttilab:Tasmsymbol;
  728. t:Tenumsym;
  729. syms:^Tenumsym;
  730. offsets:^longint;
  731. sym_count,sym_alloc:longint;
  732. h,i,p,o,st:longint;
  733. mode:(lookup,search); {Modify with care, ordinal value of enum is written.}
  734. r:single; {Must be real type because of integer overflow risk.}
  735. begin
  736. {Random access needed, put in array.}
  737. getmem(syms,64*sizeof(Tenumsym));
  738. getmem(offsets,64*sizeof(longint));
  739. sym_count:=0;
  740. sym_alloc:=64;
  741. st:=0;
  742. t:=Tenumsym(def.firstenum);
  743. while assigned(t) do
  744. begin
  745. if sym_count>=sym_alloc then
  746. begin
  747. reallocmem(syms,2*sym_alloc*sizeof(Tenumsym));
  748. reallocmem(offsets,2*sym_alloc*sizeof(longint));
  749. sym_alloc:=sym_alloc*2;
  750. end;
  751. syms[sym_count]:=t;
  752. offsets[sym_count]:=st;
  753. inc(sym_count);
  754. st:=st+length(t.realname)+1;
  755. t:=t.nextenum;
  756. end;
  757. {Sort the syms by enum value}
  758. if sym_count>=2 then
  759. begin
  760. p:=1;
  761. while 2*p<sym_count do
  762. p:=2*p;
  763. while p<>0 do
  764. begin
  765. for h:=p to sym_count-1 do
  766. begin
  767. i:=h;
  768. t:=syms[i];
  769. o:=offsets[i];
  770. repeat
  771. if syms[i-p].value<=t.value then
  772. break;
  773. syms[i]:=syms[i-p];
  774. offsets[i]:=offsets[i-p];
  775. dec(i,p);
  776. until i<p;
  777. syms[i]:=t;
  778. offsets[i]:=o;
  779. end;
  780. p:=p shr 1;
  781. end;
  782. end;
  783. {Decide wether a lookup array is size efficient.}
  784. mode:=lookup;
  785. if sym_count>0 then
  786. begin
  787. i:=1;
  788. r:=0;
  789. h:=syms[0].value; {Next expected enum value is min.}
  790. while i<sym_count do
  791. begin
  792. {Calculate size of hole between values. Avoid integer overflows.}
  793. r:=r+(single(syms[i].value)-single(h))-1;
  794. h:=syms[i].value;
  795. inc(i);
  796. end;
  797. if r>sym_count then
  798. mode:=search; {Don't waste more than 50% space.}
  799. end;
  800. {Calculate start of string table.}
  801. st:=1;
  802. if assigned(def.typesym) then
  803. inc(st,length(def.typesym.realname)+1)
  804. else
  805. inc(st);
  806. if (tf_requires_proper_alignment in target_info.flags) then
  807. align(st,sizeof(Tconstptruint));
  808. inc(st);
  809. if (tf_requires_proper_alignment in target_info.flags) then
  810. align(st,sizeof(Tconstptruint));
  811. inc(st,8+sizeof(aint));
  812. { write rtti data }
  813. with current_asmdata do
  814. begin
  815. rttilab:=defineasmsymbol(Tstoreddef(def).rtti_mangledname(rt)+'_o2s',AB_GLOBAL,AT_DATA);
  816. maybe_new_object_file(asmlists[al_rtti]);
  817. new_section(asmlists[al_rtti],sec_rodata,rttilab.name,const_align(sizeof(aint)));
  818. asmlists[al_rtti].concat(Tai_symbol.create_global(rttilab,0));
  819. asmlists[al_rtti].concat(Tai_const.create_32bit(longint(mode)));
  820. if mode=lookup then
  821. begin
  822. o:=syms[0].value; {Start with min value.}
  823. for i:=0 to sym_count-1 do
  824. begin
  825. while o<syms[i].value do
  826. begin
  827. asmlists[al_rtti].concat(Tai_const.create_aint(0));
  828. inc(o);
  829. end;
  830. inc(o);
  831. asmlists[al_rtti].concat(Tai_const.create_sym_offset(mainrtti,st+offsets[i]));
  832. end;
  833. end
  834. else
  835. begin
  836. asmlists[al_rtti].concat(Tai_const.create_32bit(sym_count));
  837. for i:=0 to sym_count-1 do
  838. begin
  839. asmlists[al_rtti].concat(Tai_const.create_32bit(syms[i].value));
  840. asmlists[al_rtti].concat(Tai_const.create_sym_offset(mainrtti,st+offsets[i]));
  841. end;
  842. end;
  843. asmlists[al_rtti].concat(Tai_symbol_end.create(rttilab));
  844. end;
  845. dispose(syms);
  846. dispose(offsets);
  847. end;
  848. procedure enumdef_rtti_string2ordindex(def:Tenumdef);
  849. var rttilab:Tasmsymbol;
  850. t:Tenumsym;
  851. syms:^Tenumsym;
  852. offsets:^longint;
  853. sym_count,sym_alloc:longint;
  854. h,i,p,o,st:longint;
  855. begin
  856. {Random access needed, put in array.}
  857. getmem(syms,64*sizeof(Tenumsym));
  858. getmem(offsets,64*sizeof(longint));
  859. sym_count:=0;
  860. sym_alloc:=64;
  861. st:=0;
  862. t:=Tenumsym(def.firstenum);
  863. while assigned(t) do
  864. begin
  865. if sym_count>=sym_alloc then
  866. begin
  867. reallocmem(syms,2*sym_alloc*sizeof(Tenumsym));
  868. reallocmem(offsets,2*sym_alloc*sizeof(longint));
  869. sym_alloc:=sym_alloc*2;
  870. end;
  871. syms[sym_count]:=t;
  872. offsets[sym_count]:=st;
  873. inc(sym_count);
  874. st:=st+length(t.realname)+1;
  875. t:=t.nextenum;
  876. end;
  877. {Sort the syms by enum name}
  878. if sym_count>=2 then
  879. begin
  880. p:=1;
  881. while 2*p<sym_count do
  882. p:=2*p;
  883. while p<>0 do
  884. begin
  885. for h:=p to sym_count-1 do
  886. begin
  887. i:=h;
  888. t:=syms[i];
  889. o:=offsets[i];
  890. repeat
  891. if syms[i-p].name<=t.name then
  892. break;
  893. syms[i]:=syms[i-p];
  894. offsets[i]:=offsets[i-p];
  895. dec(i,p);
  896. until i<p;
  897. syms[i]:=t;
  898. offsets[i]:=o;
  899. end;
  900. p:=p shr 1;
  901. end;
  902. end;
  903. {Calculate start of string table.}
  904. st:=1;
  905. if assigned(def.typesym) then
  906. inc(st,length(def.typesym.realname)+1)
  907. else
  908. inc(st);
  909. if (tf_requires_proper_alignment in target_info.flags) then
  910. align(st,sizeof(Tconstptruint));
  911. inc(st);
  912. if (tf_requires_proper_alignment in target_info.flags) then
  913. align(st,sizeof(Tconstptruint));
  914. inc(st,8+sizeof(aint));
  915. { write rtti data }
  916. with current_asmdata do
  917. begin
  918. rttilab:=defineasmsymbol(Tstoreddef(def).rtti_mangledname(rt)+'_s2o',AB_GLOBAL,AT_DATA);
  919. maybe_new_object_file(asmlists[al_rtti]);
  920. new_section(asmlists[al_rtti],sec_rodata,rttilab.name,const_align(sizeof(aint)));
  921. asmlists[al_rtti].concat(Tai_symbol.create_global(rttilab,0));
  922. asmlists[al_rtti].concat(Tai_const.create_32bit(sym_count));
  923. for i:=0 to sym_count-1 do
  924. begin
  925. asmlists[al_rtti].concat(Tai_const.create_32bit(syms[i].value));
  926. asmlists[al_rtti].concat(Tai_const.create_sym_offset(mainrtti,st+offsets[i]));
  927. end;
  928. asmlists[al_rtti].concat(Tai_symbol_end.create(rttilab));
  929. end;
  930. dispose(syms);
  931. dispose(offsets);
  932. end;
  933. begin
  934. case def.typ of
  935. enumdef:
  936. if rt=fullrtti then
  937. begin
  938. enumdef_rtti_ord2stringindex(Tenumdef(def));
  939. enumdef_rtti_string2ordindex(Tenumdef(def));
  940. end;
  941. end;
  942. end;
  943. procedure TRTTIWriter.write_child_rtti_data(def:tdef;rt:trttitype);
  944. begin
  945. case def.typ of
  946. enumdef :
  947. if assigned(tenumdef(def).basedef) then
  948. write_rtti(tenumdef(def).basedef,rt);
  949. setdef :
  950. write_rtti(tsetdef(def).elementdef,rt);
  951. arraydef :
  952. write_rtti(tarraydef(def).elementdef,rt);
  953. recorddef :
  954. fields_write_rtti(trecorddef(def).symtable,rt);
  955. objectdef :
  956. begin
  957. if assigned(tobjectdef(def).childof) then
  958. write_rtti(tobjectdef(def).childof,rt);
  959. if rt=initrtti then
  960. fields_write_rtti(tobjectdef(def).symtable,rt)
  961. else
  962. published_write_rtti(tobjectdef(def).symtable,rt);
  963. end;
  964. end;
  965. end;
  966. function TRTTIWriter.ref_rtti(def:tdef;rt:trttitype):tasmsymbol;
  967. begin
  968. result:=current_asmdata.RefAsmSymbol(def.rtti_mangledname(rt));
  969. end;
  970. procedure TRTTIWriter.write_rtti(def:tdef;rt:trttitype);
  971. var
  972. rttilab : tasmsymbol;
  973. begin
  974. { only write rtti of definitions from the current module }
  975. if not findunitsymtable(def.owner).iscurrentunit then
  976. exit;
  977. { prevent recursion }
  978. if rttidefstate[rt] in def.defstates then
  979. exit;
  980. include(def.defstates,rttidefstate[rt]);
  981. { write first all dependencies }
  982. write_child_rtti_data(def,rt);
  983. { write rtti data }
  984. rttilab:=current_asmdata.DefineAsmSymbol(tstoreddef(def).rtti_mangledname(rt),AB_GLOBAL,AT_DATA);
  985. maybe_new_object_file(current_asmdata.asmlists[al_rtti]);
  986. new_section(current_asmdata.asmlists[al_rtti],sec_rodata,rttilab.name,const_align(sizeof(aint)));
  987. current_asmdata.asmlists[al_rtti].concat(Tai_symbol.Create_global(rttilab,0));
  988. write_rtti_data(def,rt);
  989. current_asmdata.asmlists[al_rtti].concat(Tai_symbol_end.Create(rttilab));
  990. write_rtti_extrasyms(def,rt,rttilab);
  991. end;
  992. function TRTTIWriter.get_rtti_label(def:tdef;rt:trttitype):tasmsymbol;
  993. begin
  994. result:=current_asmdata.RefAsmSymbol(def.rtti_mangledname(rt));
  995. end;
  996. function TRTTIWriter.get_rtti_label_ord2str(def:tdef;rt:trttitype):tasmsymbol;
  997. begin
  998. result:=current_asmdata.RefAsmSymbol(def.rtti_mangledname(rt)+'_o2s');
  999. end;
  1000. function TRTTIWriter.get_rtti_label_str2ord(def:tdef;rt:trttitype):tasmsymbol;
  1001. begin
  1002. result:=current_asmdata.RefAsmSymbol(def.rtti_mangledname(rt)+'_s2o');
  1003. end;
  1004. end.