ncgrtti.pas 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893
  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 published_write_rtti(st:tsymtable;rt:trttitype);
  32. function published_properties_count(st:tsymtable):longint;
  33. procedure published_properties_write_rtti_data(propnamelist:TFPHashObjectList;st:tsymtable);
  34. procedure collect_propnamelist(propnamelist:TFPHashObjectList;objdef:tobjectdef);
  35. procedure write_rtti_name(def:tdef);
  36. procedure write_rtti_data(def:tdef;rt:trttitype);
  37. procedure write_child_rtti_data(def:tdef;rt:trttitype);
  38. function ref_rtti(def:tdef;rt:trttitype):tasmsymbol;
  39. public
  40. procedure write_rtti(def:tdef;rt:trttitype);
  41. function get_rtti_label(def:tdef;rt:trttitype):tasmsymbol;
  42. end;
  43. var
  44. RTTIWriter : TRTTIWriter;
  45. implementation
  46. uses
  47. cutils,
  48. globals,globtype,verbose,
  49. fmodule,
  50. symsym,
  51. aasmtai,aasmdata
  52. ;
  53. const
  54. rttidefstate : array[trttitype] of tdefstate = (ds_rtti_table_written,ds_init_table_written);
  55. type
  56. TPropNameListItem = class(TFPHashObject)
  57. propindex : longint;
  58. propowner : TSymtable;
  59. end;
  60. {***************************************************************************
  61. TRTTIWriter
  62. ***************************************************************************}
  63. procedure TRTTIWriter.write_rtti_name(def:tdef);
  64. var
  65. hs : string;
  66. begin
  67. { name }
  68. if assigned(def.typesym) then
  69. begin
  70. hs:=ttypesym(def.typesym).realname;
  71. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(chr(length(hs))+hs));
  72. end
  73. else
  74. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(#0));
  75. end;
  76. function TRTTIWriter.fields_count(st:tsymtable;rt:trttitype):longint;
  77. var
  78. i : longint;
  79. sym : tsym;
  80. begin
  81. result:=0;
  82. for i:=0 to st.SymList.Count-1 do
  83. begin
  84. sym:=tsym(st.SymList[i]);
  85. if (rt=fullrtti) or
  86. (
  87. (tsym(sym).typ=fieldvarsym) and
  88. tfieldvarsym(sym).vardef.needs_inittable
  89. ) then
  90. inc(result);
  91. end;
  92. end;
  93. procedure TRTTIWriter.fields_write_rtti_data(st:tsymtable;rt:trttitype);
  94. var
  95. i : longint;
  96. sym : tsym;
  97. begin
  98. for i:=0 to st.SymList.Count-1 do
  99. begin
  100. sym:=tsym(st.SymList[i]);
  101. if (rt=fullrtti) or
  102. (
  103. (tsym(sym).typ=fieldvarsym) and
  104. tfieldvarsym(sym).vardef.needs_inittable
  105. ) then
  106. begin
  107. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(tfieldvarsym(sym).vardef,rt)));
  108. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(tfieldvarsym(sym).fieldoffset));
  109. end;
  110. end;
  111. end;
  112. procedure TRTTIWriter.fields_write_rtti(st:tsymtable;rt:trttitype);
  113. var
  114. i : longint;
  115. sym : tsym;
  116. begin
  117. for i:=0 to st.SymList.Count-1 do
  118. begin
  119. sym:=tsym(st.SymList[i]);
  120. if (rt=fullrtti) or
  121. (
  122. (tsym(sym).typ=fieldvarsym) and
  123. tfieldvarsym(sym).vardef.needs_inittable
  124. ) then
  125. write_rtti(tfieldvarsym(sym).vardef,rt);
  126. end;
  127. end;
  128. procedure TRTTIWriter.published_write_rtti(st:tsymtable;rt:trttitype);
  129. var
  130. i : longint;
  131. sym : tsym;
  132. begin
  133. for i:=0 to st.SymList.Count-1 do
  134. begin
  135. sym:=tsym(st.SymList[i]);
  136. if (sp_published in tsym(sym).symoptions) then
  137. begin
  138. case tsym(sym).typ of
  139. propertysym:
  140. write_rtti(tpropertysym(sym).propdef,rt);
  141. fieldvarsym:
  142. write_rtti(tfieldvarsym(sym).vardef,rt);
  143. end;
  144. end;
  145. end;
  146. end;
  147. function TRTTIWriter.published_properties_count(st:tsymtable):longint;
  148. var
  149. i : longint;
  150. sym : tsym;
  151. begin
  152. result:=0;
  153. for i:=0 to st.SymList.Count-1 do
  154. begin
  155. sym:=tsym(st.SymList[i]);
  156. if (tsym(sym).typ=propertysym) and
  157. (sp_published in tsym(sym).symoptions) then
  158. inc(result);
  159. end;
  160. end;
  161. procedure TRTTIWriter.collect_propnamelist(propnamelist:TFPHashObjectList;objdef:tobjectdef);
  162. var
  163. i : longint;
  164. sym : tsym;
  165. pn : tpropnamelistitem;
  166. begin
  167. if assigned(objdef.childof) then
  168. collect_propnamelist(propnamelist,objdef.childof);
  169. for i:=0 to objdef.symtable.SymList.Count-1 do
  170. begin
  171. sym:=tsym(objdef.symtable.SymList[i]);
  172. if (tsym(sym).typ=propertysym) and
  173. (sp_published in tsym(sym).symoptions) then
  174. begin
  175. pn:=TPropNameListItem(propnamelist.Find(tsym(sym).name));
  176. if not assigned(pn) then
  177. begin
  178. pn:=tpropnamelistitem.create(propnamelist,tsym(sym).name);
  179. pn.propindex:=propnamelist.count-1;
  180. pn.propowner:=tsym(sym).owner;
  181. end;
  182. end;
  183. end;
  184. end;
  185. procedure TRTTIWriter.published_properties_write_rtti_data(propnamelist:TFPHashObjectList;st:tsymtable);
  186. var
  187. i : longint;
  188. sym : tsym;
  189. proctypesinfo : byte;
  190. propnameitem : tpropnamelistitem;
  191. procedure writeaccessproc(pap:tpropaccesslisttypes; shiftvalue : byte; unsetvalue: byte);
  192. var
  193. typvalue : byte;
  194. hp : ppropaccesslistitem;
  195. address : longint;
  196. def : tdef;
  197. hpropsym : tpropertysym;
  198. propaccesslist : tpropaccesslist;
  199. begin
  200. hpropsym:=tpropertysym(sym);
  201. repeat
  202. propaccesslist:=hpropsym.propaccesslist[pap];
  203. if not propaccesslist.empty then
  204. break;
  205. hpropsym:=hpropsym.overridenpropsym;
  206. until not assigned(hpropsym);
  207. if not(assigned(propaccesslist) and assigned(propaccesslist.firstsym)) then
  208. begin
  209. current_asmdata.asmlists[al_rtti].concat(Tai_const.create(aitconst_ptr,unsetvalue));
  210. typvalue:=3;
  211. end
  212. else if propaccesslist.firstsym^.sym.typ=fieldvarsym then
  213. begin
  214. address:=0;
  215. hp:=propaccesslist.firstsym;
  216. def:=nil;
  217. while assigned(hp) do
  218. begin
  219. case hp^.sltype of
  220. sl_load :
  221. begin
  222. def:=tfieldvarsym(hp^.sym).vardef;
  223. inc(address,tfieldvarsym(hp^.sym).fieldoffset);
  224. end;
  225. sl_subscript :
  226. begin
  227. if not(assigned(def) and (def.typ=recorddef)) then
  228. internalerror(200402171);
  229. inc(address,tfieldvarsym(hp^.sym).fieldoffset);
  230. def:=tfieldvarsym(hp^.sym).vardef;
  231. end;
  232. sl_vec :
  233. begin
  234. if not(assigned(def) and (def.typ=arraydef)) then
  235. internalerror(200402172);
  236. def:=tarraydef(def).elementdef;
  237. inc(address,def.size*hp^.value);
  238. end;
  239. end;
  240. hp:=hp^.next;
  241. end;
  242. current_asmdata.asmlists[al_rtti].concat(Tai_const.create(aitconst_ptr,address));
  243. typvalue:=0;
  244. end
  245. else
  246. begin
  247. { When there was an error then procdef is not assigned }
  248. if not assigned(propaccesslist.procdef) then
  249. exit;
  250. if not(po_virtualmethod in tprocdef(propaccesslist.procdef).procoptions) then
  251. begin
  252. current_asmdata.asmlists[al_rtti].concat(Tai_const.createname(tprocdef(propaccesslist.procdef).mangledname,0));
  253. typvalue:=1;
  254. end
  255. else
  256. begin
  257. { virtual method, write vmt offset }
  258. current_asmdata.asmlists[al_rtti].concat(Tai_const.create(aitconst_ptr,
  259. tprocdef(propaccesslist.procdef)._class.vmtmethodoffset(tprocdef(propaccesslist.procdef).extnumber)));
  260. typvalue:=2;
  261. end;
  262. end;
  263. proctypesinfo:=proctypesinfo or (typvalue shl shiftvalue);
  264. end;
  265. begin
  266. for i:=0 to st.SymList.Count-1 do
  267. begin
  268. sym:=tsym(st.SymList[i]);
  269. if (sym.typ=propertysym) and
  270. (sp_published in sym.symoptions) then
  271. begin
  272. if ppo_indexed in tpropertysym(sym).propoptions then
  273. proctypesinfo:=$40
  274. else
  275. proctypesinfo:=0;
  276. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(tpropertysym(sym).propdef,fullrtti)));
  277. writeaccessproc(palt_read,0,0);
  278. writeaccessproc(palt_write,2,0);
  279. { is it stored ? }
  280. if not(ppo_stored in tpropertysym(sym).propoptions) then
  281. begin
  282. { no, so put a constant zero }
  283. current_asmdata.asmlists[al_rtti].concat(Tai_const.create(aitconst_ptr,0));
  284. proctypesinfo:=proctypesinfo or (3 shl 4);
  285. end
  286. else
  287. writeaccessproc(palt_stored,4,1); { maybe; if no procedure put a constant 1 (=true) }
  288. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(tpropertysym(sym).index));
  289. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(tpropertysym(sym).default));
  290. propnameitem:=TPropNameListItem(propnamelist.Find(tpropertysym(sym).name));
  291. if not assigned(propnameitem) then
  292. internalerror(200512201);
  293. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(propnameitem.propindex));
  294. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(proctypesinfo));
  295. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(tpropertysym(sym).realname)));
  296. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(tpropertysym(sym).realname));
  297. {$ifdef cpurequiresproperalignment}
  298. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  299. {$endif cpurequiresproperalignment}
  300. end;
  301. end;
  302. end;
  303. procedure TRTTIWriter.write_rtti_data(def:tdef;rt:trttitype);
  304. procedure unknown_rtti(def:tstoreddef);
  305. begin
  306. current_asmdata.asmlists[al_rtti].concat(tai_const.create_8bit(tkUnknown));
  307. write_rtti_name(def);
  308. end;
  309. procedure variantdef_rtti(def:tvariantdef);
  310. begin
  311. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkVariant));
  312. end;
  313. procedure stringdef_rtti(def:tstringdef);
  314. begin
  315. case def.stringtype of
  316. st_ansistring:
  317. begin
  318. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkAString));
  319. write_rtti_name(def);
  320. end;
  321. st_widestring:
  322. begin
  323. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkWString));
  324. write_rtti_name(def);
  325. end;
  326. st_longstring:
  327. begin
  328. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkLString));
  329. write_rtti_name(def);
  330. end;
  331. st_shortstring:
  332. begin
  333. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkSString));
  334. write_rtti_name(def);
  335. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(def.len));
  336. {$ifdef cpurequiresproperalignment}
  337. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  338. {$endif cpurequiresproperalignment}
  339. end;
  340. end;
  341. end;
  342. procedure enumdef_rtti(def:tenumdef);
  343. var
  344. hp : tenumsym;
  345. begin
  346. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkEnumeration));
  347. write_rtti_name(def);
  348. {$ifdef cpurequiresproperalignment}
  349. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  350. {$endif cpurequiresproperalignment}
  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. {$ifdef cpurequiresproperalignment}
  360. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  361. {$endif cpurequiresproperalignment}
  362. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(def.min));
  363. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(def.max));
  364. if assigned(def.basedef) then
  365. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.basedef,rt)))
  366. else
  367. current_asmdata.asmlists[al_rtti].concat(Tai_const.create_sym(nil));
  368. hp:=tenumsym(def.firstenum);
  369. while assigned(hp) do
  370. begin
  371. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(hp.realname)));
  372. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(hp.realname));
  373. hp:=hp.nextenum;
  374. end;
  375. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(0));
  376. end;
  377. procedure orddef_rtti(def:torddef);
  378. procedure dointeger;
  379. const
  380. trans : array[tordtype] of byte =
  381. (otUByte{otNone},
  382. otUByte,otUWord,otULong,otUByte{otNone},
  383. otSByte,otSWord,otSLong,otUByte{otNone},
  384. otUByte,otUWord,otULong,otUByte,
  385. otUByte,otUWord,otUByte);
  386. begin
  387. write_rtti_name(def);
  388. {$ifdef cpurequiresproperalignment}
  389. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  390. {$endif cpurequiresproperalignment}
  391. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(byte(trans[def.ordtype])));
  392. {$ifdef cpurequiresproperalignment}
  393. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  394. {$endif cpurequiresproperalignment}
  395. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(longint(def.low)));
  396. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(longint(def.high)));
  397. end;
  398. begin
  399. case def.ordtype of
  400. s64bit :
  401. begin
  402. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkInt64));
  403. write_rtti_name(def);
  404. {$ifdef cpurequiresproperalignment}
  405. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  406. {$endif cpurequiresproperalignment}
  407. { low }
  408. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_64bit(int64($80000000) shl 32));
  409. { high }
  410. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_64bit((int64($7fffffff) shl 32) or int64($ffffffff)));
  411. end;
  412. u64bit :
  413. begin
  414. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkQWord));
  415. write_rtti_name(def);
  416. {$ifdef cpurequiresproperalignment}
  417. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  418. {$endif cpurequiresproperalignment}
  419. { low }
  420. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_64bit(0));
  421. { high }
  422. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_64bit(int64((int64($ffffffff) shl 32) or int64($ffffffff))));
  423. end;
  424. bool8bit:
  425. begin
  426. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkBool));
  427. dointeger;
  428. end;
  429. uchar:
  430. begin
  431. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkChar));
  432. dointeger;
  433. end;
  434. uwidechar:
  435. begin
  436. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkWChar));
  437. dointeger;
  438. end;
  439. else
  440. begin
  441. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkInteger));
  442. dointeger;
  443. end;
  444. end;
  445. end;
  446. procedure floatdef_rtti(def:tfloatdef);
  447. const
  448. {tfloattype = (s32real,s64real,s80real,s64bit,s128bit);}
  449. translate : array[tfloattype] of byte =
  450. (ftSingle,ftDouble,ftExtended,ftComp,ftCurr,ftFloat128);
  451. begin
  452. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkFloat));
  453. write_rtti_name(def);
  454. {$ifdef cpurequiresproperalignment}
  455. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  456. {$endif cpurequiresproperalignment}
  457. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(translate[def.floattype]));
  458. end;
  459. procedure setdef_rtti(def:tsetdef);
  460. begin
  461. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkSet));
  462. write_rtti_name(def);
  463. {$ifdef cpurequiresproperalignment}
  464. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  465. {$endif cpurequiresproperalignment}
  466. case def.size of
  467. 1:
  468. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(otUByte));
  469. 2:
  470. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(otUWord));
  471. 4:
  472. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(otULong));
  473. end;
  474. {$ifdef cpurequiresproperalignment}
  475. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  476. {$endif cpurequiresproperalignment}
  477. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.elementdef,rt)));
  478. end;
  479. procedure arraydef_rtti(def:tarraydef);
  480. begin
  481. if ado_IsDynamicArray in def.arrayoptions then
  482. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkdynarray))
  483. else
  484. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkarray));
  485. write_rtti_name(def);
  486. {$ifdef cpurequiresproperalignment}
  487. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  488. {$endif cpurequiresproperalignment}
  489. { size of elements }
  490. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_aint(def.elesize));
  491. if not(ado_IsDynamicArray in def.arrayoptions) then
  492. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_aint(def.elecount));
  493. { element type }
  494. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.elementdef,rt)));
  495. { variant type }
  496. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(tstoreddef(def.elementdef).getvardef));
  497. end;
  498. procedure recorddef_rtti(def:trecorddef);
  499. var
  500. fieldcnt : longint;
  501. begin
  502. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkrecord));
  503. write_rtti_name(def);
  504. {$ifdef cpurequiresproperalignment}
  505. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  506. {$endif cpurequiresproperalignment}
  507. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(def.size));
  508. fieldcnt:=fields_count(def.symtable,rt);
  509. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(fieldcnt));
  510. fields_write_rtti_data(def.symtable,rt);
  511. end;
  512. procedure procvardef_rtti(def:tprocvardef);
  513. procedure write_para(parasym:tparavarsym);
  514. var
  515. paraspec : byte;
  516. begin
  517. { only store user visible parameters }
  518. if not(vo_is_hidden_para in parasym.varoptions) then
  519. begin
  520. case parasym.varspez of
  521. vs_value: paraspec := 0;
  522. vs_const: paraspec := pfConst;
  523. vs_var : paraspec := pfVar;
  524. vs_out : paraspec := pfOut;
  525. end;
  526. { write flags for current parameter }
  527. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(paraspec));
  528. { write name of current parameter }
  529. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(parasym.realname)));
  530. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(parasym.realname));
  531. { write name of type of current parameter }
  532. write_rtti_name(parasym.vardef);
  533. end;
  534. end;
  535. var
  536. methodkind : byte;
  537. i : integer;
  538. begin
  539. if po_methodpointer in def.procoptions then
  540. begin
  541. { write method id and name }
  542. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkmethod));
  543. write_rtti_name(def);
  544. {$ifdef cpurequiresproperalignment}
  545. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  546. {$endif cpurequiresproperalignment}
  547. { write kind of method (can only be function or procedure)}
  548. if def.returndef = voidtype then
  549. methodkind := mkProcedure
  550. else
  551. methodkind := mkFunction;
  552. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(methodkind));
  553. { write parameter info. The parameters must be written in reverse order
  554. if this method uses right to left parameter pushing! }
  555. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(def.maxparacount));
  556. if def.proccalloption in pushleftright_pocalls then
  557. begin
  558. for i:=0 to def.paras.count-1 do
  559. write_para(tparavarsym(def.paras[i]));
  560. end
  561. else
  562. begin
  563. for i:=def.paras.count-1 downto 0 do
  564. write_para(tparavarsym(def.paras[i]));
  565. end;
  566. { write name of result type }
  567. write_rtti_name(def.returndef);
  568. end
  569. else
  570. begin
  571. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkprocvar));
  572. write_rtti_name(def);
  573. end;
  574. end;
  575. procedure objectdef_rtti(def:tobjectdef);
  576. procedure objectdef_rtti_class_init(def:tobjectdef);
  577. begin
  578. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(def.size));
  579. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(fields_count(def.symtable,rt)));
  580. fields_write_rtti_data(def.symtable,rt);
  581. end;
  582. procedure objectdef_rtti_interface_init(def:tobjectdef);
  583. begin
  584. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(def.size));
  585. end;
  586. procedure objectdef_rtti_class_full(def:tobjectdef);
  587. var
  588. propnamelist : TFPHashObjectList;
  589. begin
  590. { Collect unique property names with nameindex }
  591. propnamelist:=TFPHashObjectList.Create;
  592. collect_propnamelist(propnamelist,def);
  593. if (oo_has_vmt in def.objectoptions) then
  594. current_asmdata.asmlists[al_rtti].concat(Tai_const.Createname(def.vmt_mangledname,0))
  595. else
  596. current_asmdata.asmlists[al_rtti].concat(Tai_const.create_sym(nil));
  597. { write parent typeinfo }
  598. if assigned(def.childof) and
  599. (oo_can_have_published in def.childof.objectoptions) then
  600. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.childof,fullrtti)))
  601. else
  602. current_asmdata.asmlists[al_rtti].concat(Tai_const.create_sym(nil));
  603. { total number of unique properties }
  604. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(propnamelist.count));
  605. { write unit name }
  606. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(current_module.realmodulename^)));
  607. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(current_module.realmodulename^));
  608. {$ifdef cpurequiresproperalignment}
  609. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  610. {$endif cpurequiresproperalignment}
  611. { write published properties for this object }
  612. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(published_properties_count(def.symtable)));
  613. {$ifdef cpurequiresproperalignment}
  614. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  615. {$endif cpurequiresproperalignment}
  616. published_properties_write_rtti_data(propnamelist,def.symtable);
  617. propnamelist.free;
  618. end;
  619. procedure objectdef_rtti_interface_full(def:tobjectdef);
  620. var
  621. i : longint;
  622. propnamelist : TFPHashObjectList;
  623. begin
  624. { Collect unique property names with nameindex }
  625. propnamelist:=TFPHashObjectList.Create;
  626. collect_propnamelist(propnamelist,def);
  627. { write parent typeinfo }
  628. if assigned(def.childof) then
  629. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.childof,fullrtti)))
  630. else
  631. current_asmdata.asmlists[al_rtti].concat(Tai_const.create_sym(nil));
  632. { interface: write flags, iid and iidstr }
  633. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(
  634. { ugly, but working }
  635. {$ifdef USE_PACKSET1}
  636. byte([
  637. {$else USE_PACKSET1}
  638. longint([
  639. {$endif USE_PACKSET1}
  640. TCompilerIntfFlag(ord(ifHasGuid)*ord(assigned(def.iidguid))),
  641. TCompilerIntfFlag(ord(ifHasStrGUID)*ord(assigned(def.iidstr))),
  642. TCompilerIntfFlag(ord(ifDispInterface)*ord(def.objecttype=odt_dispinterface))
  643. ])
  644. {
  645. ifDispatch, }
  646. ));
  647. {$ifdef cpurequiresproperalignment}
  648. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  649. {$endif cpurequiresproperalignment}
  650. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(longint(def.iidguid^.D1)));
  651. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(def.iidguid^.D2));
  652. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(def.iidguid^.D3));
  653. for i:=Low(def.iidguid^.D4) to High(def.iidguid^.D4) do
  654. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(def.iidguid^.D4[i]));
  655. { write unit name }
  656. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(current_module.realmodulename^)));
  657. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(current_module.realmodulename^));
  658. {$ifdef cpurequiresproperalignment}
  659. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  660. {$endif cpurequiresproperalignment}
  661. { write iidstr }
  662. if assigned(def.iidstr) then
  663. begin
  664. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(def.iidstr^)));
  665. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(def.iidstr^));
  666. end
  667. else
  668. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(0));
  669. {$ifdef cpurequiresproperalignment}
  670. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  671. {$endif cpurequiresproperalignment}
  672. { write published properties for this object }
  673. published_properties_write_rtti_data(propnamelist,def.symtable);
  674. propnamelist.free;
  675. end;
  676. begin
  677. case def.objecttype of
  678. odt_class:
  679. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkclass));
  680. odt_object:
  681. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkobject));
  682. odt_dispinterface,
  683. odt_interfacecom:
  684. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkinterface));
  685. odt_interfacecorba:
  686. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkinterfaceCorba));
  687. else
  688. internalerror(200611034);
  689. end;
  690. { generate the name }
  691. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(def.objrealname^)));
  692. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(def.objrealname^));
  693. {$ifdef cpurequiresproperalignment}
  694. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  695. {$endif cpurequiresproperalignment}
  696. case rt of
  697. initrtti :
  698. begin
  699. if def.objecttype in [odt_class,odt_object] then
  700. objectdef_rtti_class_init(def)
  701. else
  702. objectdef_rtti_interface_init(def);
  703. end;
  704. fullrtti :
  705. begin
  706. if def.objecttype in [odt_class,odt_object] then
  707. objectdef_rtti_class_full(def)
  708. else
  709. objectdef_rtti_interface_full(def);
  710. end;
  711. end;
  712. end;
  713. begin
  714. case def.typ of
  715. variantdef :
  716. variantdef_rtti(tvariantdef(def));
  717. stringdef :
  718. stringdef_rtti(tstringdef(def));
  719. enumdef :
  720. enumdef_rtti(tenumdef(def));
  721. orddef :
  722. orddef_rtti(torddef(def));
  723. floatdef :
  724. floatdef_rtti(tfloatdef(def));
  725. setdef :
  726. setdef_rtti(tsetdef(def));
  727. procvardef :
  728. procvardef_rtti(tprocvardef(def));
  729. arraydef :
  730. begin
  731. if ado_IsBitPacked in tarraydef(def).arrayoptions then
  732. unknown_rtti(tstoreddef(def))
  733. else
  734. arraydef_rtti(tarraydef(def));
  735. end;
  736. recorddef :
  737. begin
  738. if trecorddef(def).is_packed then
  739. unknown_rtti(tstoreddef(def))
  740. else
  741. recorddef_rtti(trecorddef(def));
  742. end;
  743. objectdef :
  744. objectdef_rtti(tobjectdef(def));
  745. else
  746. unknown_rtti(tstoreddef(def));
  747. end;
  748. end;
  749. procedure TRTTIWriter.write_child_rtti_data(def:tdef;rt:trttitype);
  750. begin
  751. case def.typ of
  752. enumdef :
  753. if assigned(tenumdef(def).basedef) then
  754. write_rtti(tenumdef(def).basedef,rt);
  755. setdef :
  756. write_rtti(tsetdef(def).elementdef,rt);
  757. arraydef :
  758. write_rtti(tarraydef(def).elementdef,rt);
  759. recorddef :
  760. fields_write_rtti(trecorddef(def).symtable,rt);
  761. objectdef :
  762. begin
  763. if assigned(tobjectdef(def).childof) then
  764. write_rtti(tobjectdef(def).childof,rt);
  765. if rt=initrtti then
  766. fields_write_rtti(tobjectdef(def).symtable,rt)
  767. else
  768. published_write_rtti(tobjectdef(def).symtable,rt);
  769. end;
  770. end;
  771. end;
  772. function TRTTIWriter.ref_rtti(def:tdef;rt:trttitype):tasmsymbol;
  773. begin
  774. result:=current_asmdata.RefAsmSymbol(def.rtti_mangledname(rt));
  775. end;
  776. procedure TRTTIWriter.write_rtti(def:tdef;rt:trttitype);
  777. var
  778. rttilab : tasmsymbol;
  779. begin
  780. { only write rtti of definitions from the current module }
  781. if not findunitsymtable(def.owner).iscurrentunit then
  782. exit;
  783. { prevent recursion }
  784. if rttidefstate[rt] in def.defstates then
  785. exit;
  786. include(def.defstates,rttidefstate[rt]);
  787. { write first all dependencies }
  788. write_child_rtti_data(def,rt);
  789. { write rtti data }
  790. rttilab:=current_asmdata.DefineAsmSymbol(tstoreddef(def).rtti_mangledname(rt),AB_GLOBAL,AT_DATA);
  791. maybe_new_object_file(current_asmdata.asmlists[al_rtti]);
  792. new_section(current_asmdata.asmlists[al_rtti],sec_rodata,rttilab.name,const_align(sizeof(aint)));
  793. current_asmdata.asmlists[al_rtti].concat(Tai_symbol.Create_global(rttilab,0));
  794. write_rtti_data(def,rt);
  795. current_asmdata.asmlists[al_rtti].concat(Tai_symbol_end.Create(rttilab));
  796. end;
  797. function TRTTIWriter.get_rtti_label(def:tdef;rt:trttitype):tasmsymbol;
  798. begin
  799. result:=current_asmdata.RefAsmSymbol(def.rtti_mangledname(rt));
  800. end;
  801. end.