ncgrtti.pas 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125
  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,space : 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. {Hp.value is a Tconstexprint, which can be rather large,
  241. sanity check for longint overflow.}
  242. space:=(high(address)-address) div def.size;
  243. if int64(space)<hp^.value then
  244. internalerror(200706101);
  245. inc(address,int64(def.size*hp^.value));
  246. end;
  247. end;
  248. hp:=hp^.next;
  249. end;
  250. current_asmdata.asmlists[al_rtti].concat(Tai_const.create(aitconst_ptr,address));
  251. typvalue:=0;
  252. end
  253. else
  254. begin
  255. { When there was an error then procdef is not assigned }
  256. if not assigned(propaccesslist.procdef) then
  257. exit;
  258. if not(po_virtualmethod in tprocdef(propaccesslist.procdef).procoptions) then
  259. begin
  260. current_asmdata.asmlists[al_rtti].concat(Tai_const.createname(tprocdef(propaccesslist.procdef).mangledname,0));
  261. typvalue:=1;
  262. end
  263. else
  264. begin
  265. { virtual method, write vmt offset }
  266. current_asmdata.asmlists[al_rtti].concat(Tai_const.create(aitconst_ptr,
  267. tprocdef(propaccesslist.procdef)._class.vmtmethodoffset(tprocdef(propaccesslist.procdef).extnumber)));
  268. typvalue:=2;
  269. end;
  270. end;
  271. proctypesinfo:=proctypesinfo or (typvalue shl shiftvalue);
  272. end;
  273. begin
  274. for i:=0 to st.SymList.Count-1 do
  275. begin
  276. sym:=tsym(st.SymList[i]);
  277. if (sym.typ=propertysym) and
  278. (sp_published in sym.symoptions) then
  279. begin
  280. if ppo_indexed in tpropertysym(sym).propoptions then
  281. proctypesinfo:=$40
  282. else
  283. proctypesinfo:=0;
  284. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(tpropertysym(sym).propdef,fullrtti)));
  285. writeaccessproc(palt_read,0,0);
  286. writeaccessproc(palt_write,2,0);
  287. { is it stored ? }
  288. if not(ppo_stored in tpropertysym(sym).propoptions) then
  289. begin
  290. { no, so put a constant zero }
  291. current_asmdata.asmlists[al_rtti].concat(Tai_const.create(aitconst_ptr,0));
  292. proctypesinfo:=proctypesinfo or (3 shl 4);
  293. end
  294. else
  295. writeaccessproc(palt_stored,4,1); { maybe; if no procedure put a constant 1 (=true) }
  296. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(tpropertysym(sym).index));
  297. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(tpropertysym(sym).default));
  298. propnameitem:=TPropNameListItem(propnamelist.Find(tpropertysym(sym).name));
  299. if not assigned(propnameitem) then
  300. internalerror(200512201);
  301. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(propnameitem.propindex));
  302. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(proctypesinfo));
  303. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(tpropertysym(sym).realname)));
  304. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(tpropertysym(sym).realname));
  305. if (tf_requires_proper_alignment in target_info.flags) then
  306. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  307. end;
  308. end;
  309. end;
  310. procedure TRTTIWriter.write_rtti_data(def:tdef;rt:trttitype);
  311. procedure unknown_rtti(def:tstoreddef);
  312. begin
  313. current_asmdata.asmlists[al_rtti].concat(tai_const.create_8bit(tkUnknown));
  314. write_rtti_name(def);
  315. end;
  316. procedure variantdef_rtti(def:tvariantdef);
  317. begin
  318. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkVariant));
  319. end;
  320. procedure stringdef_rtti(def:tstringdef);
  321. begin
  322. case def.stringtype of
  323. st_ansistring:
  324. begin
  325. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkAString));
  326. write_rtti_name(def);
  327. end;
  328. st_widestring:
  329. begin
  330. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkWString));
  331. write_rtti_name(def);
  332. end;
  333. st_longstring:
  334. begin
  335. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkLString));
  336. write_rtti_name(def);
  337. end;
  338. st_shortstring:
  339. begin
  340. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkSString));
  341. write_rtti_name(def);
  342. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(def.len));
  343. if (tf_requires_proper_alignment in target_info.flags) then
  344. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  345. end;
  346. end;
  347. end;
  348. procedure enumdef_rtti(def:tenumdef);
  349. var
  350. hp : tenumsym;
  351. begin
  352. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkEnumeration));
  353. write_rtti_name(def);
  354. if (tf_requires_proper_alignment in target_info.flags) then
  355. current_asmdata.asmlists[al_rtti].concat(Cai_align.Create(sizeof(TConstPtrUInt)));
  356. case longint(def.size) of
  357. 1 :
  358. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(otUByte));
  359. 2 :
  360. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(otUWord));
  361. 4 :
  362. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(otULong));
  363. end;
  364. if (tf_requires_proper_alignment in target_info.flags) then
  365. current_asmdata.asmlists[al_rtti].concat(Cai_align.Create(sizeof(TConstPtrUInt)));
  366. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(def.min));
  367. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(def.max));
  368. if assigned(def.basedef) then
  369. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.basedef,rt)))
  370. else
  371. current_asmdata.asmlists[al_rtti].concat(Tai_const.create_sym(nil));
  372. hp:=tenumsym(def.firstenum);
  373. while assigned(hp) do
  374. begin
  375. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(hp.realname)));
  376. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(hp.realname));
  377. hp:=hp.nextenum;
  378. end;
  379. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(0));
  380. end;
  381. procedure orddef_rtti(def:torddef);
  382. procedure dointeger;
  383. const
  384. trans : array[tordtype] of byte =
  385. (otUByte{otNone},
  386. otUByte,otUWord,otULong,otUByte{otNone},
  387. otSByte,otSWord,otSLong,otUByte{otNone},
  388. otUByte,otUWord,otULong,otUByte,
  389. otUByte,otUWord,otUByte);
  390. begin
  391. write_rtti_name(def);
  392. if (tf_requires_proper_alignment in target_info.flags) then
  393. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  394. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(byte(trans[def.ordtype])));
  395. if (tf_requires_proper_alignment in target_info.flags) then
  396. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  397. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(longint(def.low)));
  398. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(longint(def.high)));
  399. end;
  400. begin
  401. case def.ordtype of
  402. s64bit :
  403. begin
  404. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkInt64));
  405. write_rtti_name(def);
  406. if (tf_requires_proper_alignment in target_info.flags) then
  407. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  408. { low }
  409. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_64bit(int64($80000000) shl 32));
  410. { high }
  411. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_64bit((int64($7fffffff) shl 32) or int64($ffffffff)));
  412. end;
  413. u64bit :
  414. begin
  415. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkQWord));
  416. write_rtti_name(def);
  417. if (tf_requires_proper_alignment in target_info.flags) then
  418. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  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. scurrency:
  440. begin
  441. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkFloat));
  442. write_rtti_name(def);
  443. if (tf_requires_proper_alignment in target_info.flags) then
  444. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  445. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(ftCurr));
  446. end;
  447. else
  448. begin
  449. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkInteger));
  450. dointeger;
  451. end;
  452. end;
  453. end;
  454. procedure floatdef_rtti(def:tfloatdef);
  455. const
  456. {tfloattype = (s32real,s64real,s80real,s64bit,s128bit);}
  457. translate : array[tfloattype] of byte =
  458. (ftSingle,ftDouble,ftExtended,ftComp,ftCurr,ftFloat128);
  459. begin
  460. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkFloat));
  461. write_rtti_name(def);
  462. if (tf_requires_proper_alignment in target_info.flags) then
  463. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  464. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(translate[def.floattype]));
  465. end;
  466. procedure setdef_rtti(def:tsetdef);
  467. begin
  468. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkSet));
  469. write_rtti_name(def);
  470. if (tf_requires_proper_alignment in target_info.flags) then
  471. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  472. case def.size of
  473. 1:
  474. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(otUByte));
  475. 2:
  476. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(otUWord));
  477. 4:
  478. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(otULong));
  479. end;
  480. if (tf_requires_proper_alignment in target_info.flags) then
  481. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  482. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.elementdef,rt)));
  483. end;
  484. procedure arraydef_rtti(def:tarraydef);
  485. begin
  486. if ado_IsDynamicArray in def.arrayoptions then
  487. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkdynarray))
  488. else
  489. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkarray));
  490. write_rtti_name(def);
  491. if (tf_requires_proper_alignment in target_info.flags) then
  492. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  493. { size of elements }
  494. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_aint(def.elesize));
  495. if not(ado_IsDynamicArray in def.arrayoptions) then
  496. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_aint(aint(def.elecount)));
  497. { element type }
  498. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.elementdef,rt)));
  499. { variant type }
  500. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(tstoreddef(def.elementdef).getvardef));
  501. end;
  502. procedure recorddef_rtti(def:trecorddef);
  503. var
  504. fieldcnt : longint;
  505. begin
  506. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkrecord));
  507. write_rtti_name(def);
  508. if (tf_requires_proper_alignment in target_info.flags) then
  509. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  510. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(def.size));
  511. fieldcnt:=fields_count(def.symtable,rt);
  512. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(fieldcnt));
  513. fields_write_rtti_data(def.symtable,rt);
  514. end;
  515. procedure procvardef_rtti(def:tprocvardef);
  516. procedure write_para(parasym:tparavarsym);
  517. var
  518. paraspec : byte;
  519. begin
  520. { only store user visible parameters }
  521. if not(vo_is_hidden_para in parasym.varoptions) then
  522. begin
  523. case parasym.varspez of
  524. vs_value: paraspec := 0;
  525. vs_const: paraspec := pfConst;
  526. vs_var : paraspec := pfVar;
  527. vs_out : paraspec := pfOut;
  528. end;
  529. { write flags for current parameter }
  530. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(paraspec));
  531. { write name of current parameter }
  532. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(parasym.realname)));
  533. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(parasym.realname));
  534. { write name of type of current parameter }
  535. write_rtti_name(parasym.vardef);
  536. end;
  537. end;
  538. var
  539. methodkind : byte;
  540. i : integer;
  541. begin
  542. if po_methodpointer in def.procoptions then
  543. begin
  544. { write method id and name }
  545. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkmethod));
  546. write_rtti_name(def);
  547. if (tf_requires_proper_alignment in target_info.flags) then
  548. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  549. { write kind of method (can only be function or procedure)}
  550. if def.returndef = voidtype then
  551. methodkind := mkProcedure
  552. else
  553. methodkind := mkFunction;
  554. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(methodkind));
  555. { write parameter info. The parameters must be written in reverse order
  556. if this method uses right to left parameter pushing! }
  557. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(def.maxparacount));
  558. if def.proccalloption in pushleftright_pocalls then
  559. begin
  560. for i:=0 to def.paras.count-1 do
  561. write_para(tparavarsym(def.paras[i]));
  562. end
  563. else
  564. begin
  565. for i:=def.paras.count-1 downto 0 do
  566. write_para(tparavarsym(def.paras[i]));
  567. end;
  568. { write name of result type }
  569. write_rtti_name(def.returndef);
  570. end
  571. else
  572. begin
  573. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkprocvar));
  574. write_rtti_name(def);
  575. end;
  576. end;
  577. procedure objectdef_rtti(def:tobjectdef);
  578. procedure objectdef_rtti_class_init(def:tobjectdef);
  579. begin
  580. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(def.size));
  581. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(fields_count(def.symtable,rt)));
  582. fields_write_rtti_data(def.symtable,rt);
  583. end;
  584. procedure objectdef_rtti_interface_init(def:tobjectdef);
  585. begin
  586. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(def.size));
  587. end;
  588. procedure objectdef_rtti_class_full(def:tobjectdef);
  589. var
  590. propnamelist : TFPHashObjectList;
  591. begin
  592. { Collect unique property names with nameindex }
  593. propnamelist:=TFPHashObjectList.Create;
  594. collect_propnamelist(propnamelist,def);
  595. if (oo_has_vmt in def.objectoptions) then
  596. current_asmdata.asmlists[al_rtti].concat(Tai_const.Createname(def.vmt_mangledname,0))
  597. else
  598. current_asmdata.asmlists[al_rtti].concat(Tai_const.create_sym(nil));
  599. { write parent typeinfo }
  600. if assigned(def.childof) and
  601. (oo_can_have_published in def.childof.objectoptions) then
  602. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.childof,fullrtti)))
  603. else
  604. current_asmdata.asmlists[al_rtti].concat(Tai_const.create_sym(nil));
  605. { total number of unique properties }
  606. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(propnamelist.count));
  607. { write unit name }
  608. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(current_module.realmodulename^)));
  609. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(current_module.realmodulename^));
  610. if (tf_requires_proper_alignment in target_info.flags) then
  611. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  612. { write published properties for this object }
  613. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(published_properties_count(def.symtable)));
  614. if (tf_requires_proper_alignment in target_info.flags) then
  615. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  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. if (tf_requires_proper_alignment in target_info.flags) then
  648. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  649. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(longint(def.iidguid^.D1)));
  650. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(def.iidguid^.D2));
  651. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(def.iidguid^.D3));
  652. for i:=Low(def.iidguid^.D4) to High(def.iidguid^.D4) do
  653. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(def.iidguid^.D4[i]));
  654. { write unit name }
  655. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(current_module.realmodulename^)));
  656. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(current_module.realmodulename^));
  657. if (tf_requires_proper_alignment in target_info.flags) then
  658. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  659. { write iidstr }
  660. if assigned(def.iidstr) then
  661. begin
  662. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(def.iidstr^)));
  663. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(def.iidstr^));
  664. end
  665. else
  666. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(0));
  667. if (tf_requires_proper_alignment in target_info.flags) then
  668. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  669. { write published properties for this object }
  670. published_properties_write_rtti_data(propnamelist,def.symtable);
  671. propnamelist.free;
  672. end;
  673. begin
  674. case def.objecttype of
  675. odt_class:
  676. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkclass));
  677. odt_object:
  678. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkobject));
  679. odt_dispinterface,
  680. odt_interfacecom:
  681. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkinterface));
  682. odt_interfacecorba:
  683. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkinterfaceCorba));
  684. else
  685. internalerror(200611034);
  686. end;
  687. { generate the name }
  688. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(def.objrealname^)));
  689. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(def.objrealname^));
  690. if (tf_requires_proper_alignment in target_info.flags) then
  691. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  692. case rt of
  693. initrtti :
  694. begin
  695. if def.objecttype in [odt_class,odt_object] then
  696. objectdef_rtti_class_init(def)
  697. else
  698. objectdef_rtti_interface_init(def);
  699. end;
  700. fullrtti :
  701. begin
  702. if def.objecttype in [odt_class,odt_object] then
  703. objectdef_rtti_class_full(def)
  704. else
  705. objectdef_rtti_interface_full(def);
  706. end;
  707. end;
  708. end;
  709. begin
  710. case def.typ of
  711. variantdef :
  712. variantdef_rtti(tvariantdef(def));
  713. stringdef :
  714. stringdef_rtti(tstringdef(def));
  715. enumdef :
  716. enumdef_rtti(tenumdef(def));
  717. orddef :
  718. orddef_rtti(torddef(def));
  719. floatdef :
  720. floatdef_rtti(tfloatdef(def));
  721. setdef :
  722. setdef_rtti(tsetdef(def));
  723. procvardef :
  724. procvardef_rtti(tprocvardef(def));
  725. arraydef :
  726. begin
  727. if ado_IsBitPacked in tarraydef(def).arrayoptions then
  728. unknown_rtti(tstoreddef(def))
  729. else
  730. arraydef_rtti(tarraydef(def));
  731. end;
  732. recorddef :
  733. begin
  734. if trecorddef(def).is_packed then
  735. unknown_rtti(tstoreddef(def))
  736. else
  737. recorddef_rtti(trecorddef(def));
  738. end;
  739. objectdef :
  740. objectdef_rtti(tobjectdef(def));
  741. else
  742. unknown_rtti(tstoreddef(def));
  743. end;
  744. end;
  745. procedure TRTTIWriter.write_rtti_extrasyms(def:Tdef;rt:Trttitype;mainrtti:Tasmsymbol);
  746. procedure enumdef_rtti_ord2stringindex(def:Tenumdef);
  747. var rttilab:Tasmsymbol;
  748. t:Tenumsym;
  749. syms:^Tenumsym;
  750. offsets:^longint;
  751. sym_count,sym_alloc:longint;
  752. h,i,p,o,st:longint;
  753. mode:(lookup,search); {Modify with care, ordinal value of enum is written.}
  754. r:single; {Must be real type because of integer overflow risk.}
  755. begin
  756. {Random access needed, put in array.}
  757. getmem(syms,64*sizeof(Tenumsym));
  758. getmem(offsets,64*sizeof(longint));
  759. sym_count:=0;
  760. sym_alloc:=64;
  761. st:=0;
  762. t:=Tenumsym(def.firstenum);
  763. while assigned(t) do
  764. begin
  765. if sym_count>=sym_alloc then
  766. begin
  767. reallocmem(syms,2*sym_alloc*sizeof(Tenumsym));
  768. reallocmem(offsets,2*sym_alloc*sizeof(longint));
  769. sym_alloc:=sym_alloc*2;
  770. end;
  771. syms[sym_count]:=t;
  772. offsets[sym_count]:=st;
  773. inc(sym_count);
  774. st:=st+length(t.realname)+1;
  775. t:=t.nextenum;
  776. end;
  777. {Sort the syms by enum value}
  778. if sym_count>=2 then
  779. begin
  780. p:=1;
  781. while 2*p<sym_count do
  782. p:=2*p;
  783. while p<>0 do
  784. begin
  785. for h:=p to sym_count-1 do
  786. begin
  787. i:=h;
  788. t:=syms[i];
  789. o:=offsets[i];
  790. repeat
  791. if syms[i-p].value<=t.value then
  792. break;
  793. syms[i]:=syms[i-p];
  794. offsets[i]:=offsets[i-p];
  795. dec(i,p);
  796. until i<p;
  797. syms[i]:=t;
  798. offsets[i]:=o;
  799. end;
  800. p:=p shr 1;
  801. end;
  802. end;
  803. {Decide wether a lookup array is size efficient.}
  804. mode:=lookup;
  805. if sym_count>0 then
  806. begin
  807. i:=1;
  808. r:=0;
  809. h:=syms[0].value; {Next expected enum value is min.}
  810. while i<sym_count do
  811. begin
  812. {Calculate size of hole between values. Avoid integer overflows.}
  813. r:=r+(single(syms[i].value)-single(h))-1;
  814. h:=syms[i].value;
  815. inc(i);
  816. end;
  817. if r>sym_count then
  818. mode:=search; {Don't waste more than 50% space.}
  819. end;
  820. {Calculate start of string table.}
  821. st:=1;
  822. if assigned(def.typesym) then
  823. inc(st,length(def.typesym.realname)+1)
  824. else
  825. inc(st);
  826. if (tf_requires_proper_alignment in target_info.flags) then
  827. align(st,sizeof(Tconstptruint));
  828. inc(st);
  829. if (tf_requires_proper_alignment in target_info.flags) then
  830. align(st,sizeof(Tconstptruint));
  831. inc(st,8+sizeof(aint));
  832. { write rtti data }
  833. with current_asmdata do
  834. begin
  835. rttilab:=defineasmsymbol(Tstoreddef(def).rtti_mangledname(rt)+'_o2s',AB_GLOBAL,AT_DATA);
  836. maybe_new_object_file(asmlists[al_rtti]);
  837. new_section(asmlists[al_rtti],sec_rodata,rttilab.name,const_align(sizeof(aint)));
  838. asmlists[al_rtti].concat(Tai_symbol.create_global(rttilab,0));
  839. asmlists[al_rtti].concat(Tai_const.create_32bit(longint(mode)));
  840. if mode=lookup then
  841. begin
  842. o:=syms[0].value; {Start with min value.}
  843. for i:=0 to sym_count-1 do
  844. begin
  845. while o<syms[i].value do
  846. begin
  847. asmlists[al_rtti].concat(Tai_const.create_aint(0));
  848. inc(o);
  849. end;
  850. inc(o);
  851. asmlists[al_rtti].concat(Tai_const.create_sym_offset(mainrtti,st+offsets[i]));
  852. end;
  853. end
  854. else
  855. begin
  856. asmlists[al_rtti].concat(Tai_const.create_32bit(sym_count));
  857. for i:=0 to sym_count-1 do
  858. begin
  859. asmlists[al_rtti].concat(Tai_const.create_32bit(syms[i].value));
  860. asmlists[al_rtti].concat(Tai_const.create_sym_offset(mainrtti,st+offsets[i]));
  861. end;
  862. end;
  863. asmlists[al_rtti].concat(Tai_symbol_end.create(rttilab));
  864. end;
  865. dispose(syms);
  866. dispose(offsets);
  867. end;
  868. procedure enumdef_rtti_string2ordindex(def:Tenumdef);
  869. var rttilab:Tasmsymbol;
  870. t:Tenumsym;
  871. syms:^Tenumsym;
  872. offsets:^longint;
  873. sym_count,sym_alloc:longint;
  874. h,i,p,o,st:longint;
  875. begin
  876. {Random access needed, put in array.}
  877. getmem(syms,64*sizeof(Tenumsym));
  878. getmem(offsets,64*sizeof(longint));
  879. sym_count:=0;
  880. sym_alloc:=64;
  881. st:=0;
  882. t:=Tenumsym(def.firstenum);
  883. while assigned(t) do
  884. begin
  885. if sym_count>=sym_alloc then
  886. begin
  887. reallocmem(syms,2*sym_alloc*sizeof(Tenumsym));
  888. reallocmem(offsets,2*sym_alloc*sizeof(longint));
  889. sym_alloc:=sym_alloc*2;
  890. end;
  891. syms[sym_count]:=t;
  892. offsets[sym_count]:=st;
  893. inc(sym_count);
  894. st:=st+length(t.realname)+1;
  895. t:=t.nextenum;
  896. end;
  897. {Sort the syms by enum name}
  898. if sym_count>=2 then
  899. begin
  900. p:=1;
  901. while 2*p<sym_count do
  902. p:=2*p;
  903. while p<>0 do
  904. begin
  905. for h:=p to sym_count-1 do
  906. begin
  907. i:=h;
  908. t:=syms[i];
  909. o:=offsets[i];
  910. repeat
  911. if syms[i-p].name<=t.name then
  912. break;
  913. syms[i]:=syms[i-p];
  914. offsets[i]:=offsets[i-p];
  915. dec(i,p);
  916. until i<p;
  917. syms[i]:=t;
  918. offsets[i]:=o;
  919. end;
  920. p:=p shr 1;
  921. end;
  922. end;
  923. {Calculate start of string table.}
  924. st:=1;
  925. if assigned(def.typesym) then
  926. inc(st,length(def.typesym.realname)+1)
  927. else
  928. inc(st);
  929. if (tf_requires_proper_alignment in target_info.flags) then
  930. align(st,sizeof(Tconstptruint));
  931. inc(st);
  932. if (tf_requires_proper_alignment in target_info.flags) then
  933. align(st,sizeof(Tconstptruint));
  934. inc(st,8+sizeof(aint));
  935. { write rtti data }
  936. with current_asmdata do
  937. begin
  938. rttilab:=defineasmsymbol(Tstoreddef(def).rtti_mangledname(rt)+'_s2o',AB_GLOBAL,AT_DATA);
  939. maybe_new_object_file(asmlists[al_rtti]);
  940. new_section(asmlists[al_rtti],sec_rodata,rttilab.name,const_align(sizeof(aint)));
  941. asmlists[al_rtti].concat(Tai_symbol.create_global(rttilab,0));
  942. asmlists[al_rtti].concat(Tai_const.create_32bit(sym_count));
  943. for i:=0 to sym_count-1 do
  944. begin
  945. asmlists[al_rtti].concat(Tai_const.create_32bit(syms[i].value));
  946. asmlists[al_rtti].concat(Tai_const.create_sym_offset(mainrtti,st+offsets[i]));
  947. end;
  948. asmlists[al_rtti].concat(Tai_symbol_end.create(rttilab));
  949. end;
  950. dispose(syms);
  951. dispose(offsets);
  952. end;
  953. begin
  954. case def.typ of
  955. enumdef:
  956. if rt=fullrtti then
  957. begin
  958. enumdef_rtti_ord2stringindex(Tenumdef(def));
  959. enumdef_rtti_string2ordindex(Tenumdef(def));
  960. end;
  961. end;
  962. end;
  963. procedure TRTTIWriter.write_child_rtti_data(def:tdef;rt:trttitype);
  964. begin
  965. case def.typ of
  966. enumdef :
  967. if assigned(tenumdef(def).basedef) then
  968. write_rtti(tenumdef(def).basedef,rt);
  969. setdef :
  970. write_rtti(tsetdef(def).elementdef,rt);
  971. arraydef :
  972. write_rtti(tarraydef(def).elementdef,rt);
  973. recorddef :
  974. fields_write_rtti(trecorddef(def).symtable,rt);
  975. objectdef :
  976. begin
  977. if assigned(tobjectdef(def).childof) then
  978. write_rtti(tobjectdef(def).childof,rt);
  979. if rt=initrtti then
  980. fields_write_rtti(tobjectdef(def).symtable,rt)
  981. else
  982. published_write_rtti(tobjectdef(def).symtable,rt);
  983. end;
  984. end;
  985. end;
  986. function TRTTIWriter.ref_rtti(def:tdef;rt:trttitype):tasmsymbol;
  987. begin
  988. result:=current_asmdata.RefAsmSymbol(def.rtti_mangledname(rt));
  989. end;
  990. procedure TRTTIWriter.write_rtti(def:tdef;rt:trttitype);
  991. var
  992. rttilab : tasmsymbol;
  993. begin
  994. { only write rtti of definitions from the current module }
  995. if not findunitsymtable(def.owner).iscurrentunit then
  996. exit;
  997. { prevent recursion }
  998. if rttidefstate[rt] in def.defstates then
  999. exit;
  1000. include(def.defstates,rttidefstate[rt]);
  1001. { write first all dependencies }
  1002. write_child_rtti_data(def,rt);
  1003. { write rtti data }
  1004. rttilab:=current_asmdata.DefineAsmSymbol(tstoreddef(def).rtti_mangledname(rt),AB_GLOBAL,AT_DATA);
  1005. maybe_new_object_file(current_asmdata.asmlists[al_rtti]);
  1006. new_section(current_asmdata.asmlists[al_rtti],sec_rodata,rttilab.name,const_align(sizeof(aint)));
  1007. current_asmdata.asmlists[al_rtti].concat(Tai_symbol.Create_global(rttilab,0));
  1008. write_rtti_data(def,rt);
  1009. current_asmdata.asmlists[al_rtti].concat(Tai_symbol_end.Create(rttilab));
  1010. write_rtti_extrasyms(def,rt,rttilab);
  1011. end;
  1012. function TRTTIWriter.get_rtti_label(def:tdef;rt:trttitype):tasmsymbol;
  1013. begin
  1014. result:=current_asmdata.RefAsmSymbol(def.rtti_mangledname(rt));
  1015. end;
  1016. function TRTTIWriter.get_rtti_label_ord2str(def:tdef;rt:trttitype):tasmsymbol;
  1017. begin
  1018. result:=current_asmdata.RefAsmSymbol(def.rtti_mangledname(rt)+'_o2s');
  1019. end;
  1020. function TRTTIWriter.get_rtti_label_str2ord(def:tdef;rt:trttitype):tasmsymbol;
  1021. begin
  1022. result:=current_asmdata.RefAsmSymbol(def.rtti_mangledname(rt)+'_s2o');
  1023. end;
  1024. end.