2
0

ncgrtti.pas 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112
  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. case def.size of
  460. 1:
  461. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(otUByte));
  462. 2:
  463. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(otUWord));
  464. 4:
  465. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(otULong));
  466. end;
  467. if (tf_requires_proper_alignment in target_info.flags) then
  468. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  469. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.elementdef,rt)));
  470. end;
  471. procedure arraydef_rtti(def:tarraydef);
  472. begin
  473. if ado_IsDynamicArray in def.arrayoptions then
  474. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkdynarray))
  475. else
  476. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkarray));
  477. write_rtti_name(def);
  478. if (tf_requires_proper_alignment in target_info.flags) then
  479. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  480. { size of elements }
  481. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_aint(def.elesize));
  482. if not(ado_IsDynamicArray in def.arrayoptions) then
  483. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_aint(def.elecount));
  484. { element type }
  485. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.elementdef,rt)));
  486. { variant type }
  487. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(tstoreddef(def.elementdef).getvardef));
  488. end;
  489. procedure recorddef_rtti(def:trecorddef);
  490. var
  491. fieldcnt : longint;
  492. begin
  493. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkrecord));
  494. write_rtti_name(def);
  495. if (tf_requires_proper_alignment in target_info.flags) then
  496. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  497. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(def.size));
  498. fieldcnt:=fields_count(def.symtable,rt);
  499. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(fieldcnt));
  500. fields_write_rtti_data(def.symtable,rt);
  501. end;
  502. procedure procvardef_rtti(def:tprocvardef);
  503. procedure write_para(parasym:tparavarsym);
  504. var
  505. paraspec : byte;
  506. begin
  507. { only store user visible parameters }
  508. if not(vo_is_hidden_para in parasym.varoptions) then
  509. begin
  510. case parasym.varspez of
  511. vs_value: paraspec := 0;
  512. vs_const: paraspec := pfConst;
  513. vs_var : paraspec := pfVar;
  514. vs_out : paraspec := pfOut;
  515. end;
  516. { write flags for current parameter }
  517. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(paraspec));
  518. { write name of current parameter }
  519. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(parasym.realname)));
  520. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(parasym.realname));
  521. { write name of type of current parameter }
  522. write_rtti_name(parasym.vardef);
  523. end;
  524. end;
  525. var
  526. methodkind : byte;
  527. i : integer;
  528. begin
  529. if po_methodpointer in def.procoptions then
  530. begin
  531. { write method id and name }
  532. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkmethod));
  533. write_rtti_name(def);
  534. if (tf_requires_proper_alignment in target_info.flags) then
  535. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  536. { write kind of method (can only be function or procedure)}
  537. if def.returndef = voidtype then
  538. methodkind := mkProcedure
  539. else
  540. methodkind := mkFunction;
  541. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(methodkind));
  542. { write parameter info. The parameters must be written in reverse order
  543. if this method uses right to left parameter pushing! }
  544. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(def.maxparacount));
  545. if def.proccalloption in pushleftright_pocalls then
  546. begin
  547. for i:=0 to def.paras.count-1 do
  548. write_para(tparavarsym(def.paras[i]));
  549. end
  550. else
  551. begin
  552. for i:=def.paras.count-1 downto 0 do
  553. write_para(tparavarsym(def.paras[i]));
  554. end;
  555. { write name of result type }
  556. write_rtti_name(def.returndef);
  557. end
  558. else
  559. begin
  560. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkprocvar));
  561. write_rtti_name(def);
  562. end;
  563. end;
  564. procedure objectdef_rtti(def:tobjectdef);
  565. procedure objectdef_rtti_class_init(def:tobjectdef);
  566. begin
  567. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(def.size));
  568. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(fields_count(def.symtable,rt)));
  569. fields_write_rtti_data(def.symtable,rt);
  570. end;
  571. procedure objectdef_rtti_interface_init(def:tobjectdef);
  572. begin
  573. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(def.size));
  574. end;
  575. procedure objectdef_rtti_class_full(def:tobjectdef);
  576. var
  577. propnamelist : TFPHashObjectList;
  578. begin
  579. { Collect unique property names with nameindex }
  580. propnamelist:=TFPHashObjectList.Create;
  581. collect_propnamelist(propnamelist,def);
  582. if (oo_has_vmt in def.objectoptions) then
  583. current_asmdata.asmlists[al_rtti].concat(Tai_const.Createname(def.vmt_mangledname,0))
  584. else
  585. current_asmdata.asmlists[al_rtti].concat(Tai_const.create_sym(nil));
  586. { write parent typeinfo }
  587. if assigned(def.childof) and
  588. (oo_can_have_published in def.childof.objectoptions) then
  589. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.childof,fullrtti)))
  590. else
  591. current_asmdata.asmlists[al_rtti].concat(Tai_const.create_sym(nil));
  592. { total number of unique properties }
  593. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(propnamelist.count));
  594. { write unit name }
  595. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(current_module.realmodulename^)));
  596. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(current_module.realmodulename^));
  597. if (tf_requires_proper_alignment in target_info.flags) then
  598. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  599. { write published properties for this object }
  600. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(published_properties_count(def.symtable)));
  601. if (tf_requires_proper_alignment in target_info.flags) then
  602. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  603. published_properties_write_rtti_data(propnamelist,def.symtable);
  604. propnamelist.free;
  605. end;
  606. procedure objectdef_rtti_interface_full(def:tobjectdef);
  607. var
  608. i : longint;
  609. propnamelist : TFPHashObjectList;
  610. begin
  611. { Collect unique property names with nameindex }
  612. propnamelist:=TFPHashObjectList.Create;
  613. collect_propnamelist(propnamelist,def);
  614. { write parent typeinfo }
  615. if assigned(def.childof) then
  616. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_sym(ref_rtti(def.childof,fullrtti)))
  617. else
  618. current_asmdata.asmlists[al_rtti].concat(Tai_const.create_sym(nil));
  619. { interface: write flags, iid and iidstr }
  620. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(
  621. { ugly, but working }
  622. {$ifdef USE_PACKSET1}
  623. byte([
  624. {$else USE_PACKSET1}
  625. longint([
  626. {$endif USE_PACKSET1}
  627. TCompilerIntfFlag(ord(ifHasGuid)*ord(assigned(def.iidguid))),
  628. TCompilerIntfFlag(ord(ifHasStrGUID)*ord(assigned(def.iidstr))),
  629. TCompilerIntfFlag(ord(ifDispInterface)*ord(def.objecttype=odt_dispinterface))
  630. ])
  631. {
  632. ifDispatch, }
  633. ));
  634. if (tf_requires_proper_alignment in target_info.flags) then
  635. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  636. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_32bit(longint(def.iidguid^.D1)));
  637. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(def.iidguid^.D2));
  638. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_16bit(def.iidguid^.D3));
  639. for i:=Low(def.iidguid^.D4) to High(def.iidguid^.D4) do
  640. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(def.iidguid^.D4[i]));
  641. { write unit name }
  642. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(current_module.realmodulename^)));
  643. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(current_module.realmodulename^));
  644. if (tf_requires_proper_alignment in target_info.flags) then
  645. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  646. { write iidstr }
  647. if assigned(def.iidstr) then
  648. begin
  649. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(def.iidstr^)));
  650. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(def.iidstr^));
  651. end
  652. else
  653. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(0));
  654. if (tf_requires_proper_alignment in target_info.flags) then
  655. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  656. { write published properties for this object }
  657. published_properties_write_rtti_data(propnamelist,def.symtable);
  658. propnamelist.free;
  659. end;
  660. begin
  661. case def.objecttype of
  662. odt_class:
  663. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkclass));
  664. odt_object:
  665. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkobject));
  666. odt_dispinterface,
  667. odt_interfacecom:
  668. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkinterface));
  669. odt_interfacecorba:
  670. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(tkinterfaceCorba));
  671. else
  672. internalerror(200611034);
  673. end;
  674. { generate the name }
  675. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(length(def.objrealname^)));
  676. current_asmdata.asmlists[al_rtti].concat(Tai_string.Create(def.objrealname^));
  677. if (tf_requires_proper_alignment in target_info.flags) then
  678. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  679. case rt of
  680. initrtti :
  681. begin
  682. if def.objecttype in [odt_class,odt_object] then
  683. objectdef_rtti_class_init(def)
  684. else
  685. objectdef_rtti_interface_init(def);
  686. end;
  687. fullrtti :
  688. begin
  689. if def.objecttype in [odt_class,odt_object] then
  690. objectdef_rtti_class_full(def)
  691. else
  692. objectdef_rtti_interface_full(def);
  693. end;
  694. end;
  695. end;
  696. begin
  697. case def.typ of
  698. variantdef :
  699. variantdef_rtti(tvariantdef(def));
  700. stringdef :
  701. stringdef_rtti(tstringdef(def));
  702. enumdef :
  703. enumdef_rtti(tenumdef(def));
  704. orddef :
  705. orddef_rtti(torddef(def));
  706. floatdef :
  707. floatdef_rtti(tfloatdef(def));
  708. setdef :
  709. setdef_rtti(tsetdef(def));
  710. procvardef :
  711. procvardef_rtti(tprocvardef(def));
  712. arraydef :
  713. begin
  714. if ado_IsBitPacked in tarraydef(def).arrayoptions then
  715. unknown_rtti(tstoreddef(def))
  716. else
  717. arraydef_rtti(tarraydef(def));
  718. end;
  719. recorddef :
  720. begin
  721. if trecorddef(def).is_packed then
  722. unknown_rtti(tstoreddef(def))
  723. else
  724. recorddef_rtti(trecorddef(def));
  725. end;
  726. objectdef :
  727. objectdef_rtti(tobjectdef(def));
  728. else
  729. unknown_rtti(tstoreddef(def));
  730. end;
  731. end;
  732. procedure TRTTIWriter.write_rtti_extrasyms(def:Tdef;rt:Trttitype;mainrtti:Tasmsymbol);
  733. procedure enumdef_rtti_ord2stringindex(def:Tenumdef);
  734. var rttilab:Tasmsymbol;
  735. t:Tenumsym;
  736. syms:^Tenumsym;
  737. offsets:^longint;
  738. sym_count,sym_alloc:longint;
  739. h,i,p,o,st:longint;
  740. mode:(lookup,search); {Modify with care, ordinal value of enum is written.}
  741. r:single; {Must be real type because of integer overflow risk.}
  742. begin
  743. {Random access needed, put in array.}
  744. getmem(syms,64*sizeof(Tenumsym));
  745. getmem(offsets,64*sizeof(longint));
  746. sym_count:=0;
  747. sym_alloc:=64;
  748. st:=0;
  749. t:=Tenumsym(def.firstenum);
  750. while assigned(t) do
  751. begin
  752. if sym_count>=sym_alloc then
  753. begin
  754. reallocmem(syms,2*sym_alloc*sizeof(Tenumsym));
  755. reallocmem(offsets,2*sym_alloc*sizeof(longint));
  756. sym_alloc:=sym_alloc*2;
  757. end;
  758. syms[sym_count]:=t;
  759. offsets[sym_count]:=st;
  760. inc(sym_count);
  761. st:=st+length(t.realname)+1;
  762. t:=t.nextenum;
  763. end;
  764. {Sort the syms by enum value}
  765. if sym_count>=2 then
  766. begin
  767. p:=1;
  768. while 2*p<sym_count do
  769. p:=2*p;
  770. while p<>0 do
  771. begin
  772. for h:=p to sym_count-1 do
  773. begin
  774. i:=h;
  775. t:=syms[i];
  776. o:=offsets[i];
  777. repeat
  778. if syms[i-p].value<=t.value then
  779. break;
  780. syms[i]:=syms[i-p];
  781. offsets[i]:=offsets[i-p];
  782. dec(i,p);
  783. until i<p;
  784. syms[i]:=t;
  785. offsets[i]:=o;
  786. end;
  787. p:=p shr 1;
  788. end;
  789. end;
  790. {Decide wether a lookup array is size efficient.}
  791. mode:=lookup;
  792. if sym_count>0 then
  793. begin
  794. i:=1;
  795. r:=0;
  796. h:=syms[0].value; {Next expected enum value is min.}
  797. while i<sym_count do
  798. begin
  799. {Calculate size of hole between values. Avoid integer overflows.}
  800. r:=r+(single(syms[i].value)-single(h))-1;
  801. h:=syms[i].value;
  802. inc(i);
  803. end;
  804. if r>sym_count then
  805. mode:=search; {Don't waste more than 50% space.}
  806. end;
  807. {Calculate start of string table.}
  808. st:=1;
  809. if assigned(def.typesym) then
  810. inc(st,length(def.typesym.realname)+1)
  811. else
  812. inc(st);
  813. if (tf_requires_proper_alignment in target_info.flags) then
  814. align(st,sizeof(Tconstptruint));
  815. inc(st);
  816. if (tf_requires_proper_alignment in target_info.flags) then
  817. align(st,sizeof(Tconstptruint));
  818. inc(st,8+sizeof(aint));
  819. { write rtti data }
  820. with current_asmdata do
  821. begin
  822. rttilab:=defineasmsymbol(Tstoreddef(def).rtti_mangledname(rt)+'_o2s',AB_GLOBAL,AT_DATA);
  823. maybe_new_object_file(asmlists[al_rtti]);
  824. new_section(asmlists[al_rtti],sec_rodata,rttilab.name,const_align(sizeof(aint)));
  825. asmlists[al_rtti].concat(Tai_symbol.create_global(rttilab,0));
  826. asmlists[al_rtti].concat(Tai_const.create_32bit(longint(mode)));
  827. if mode=lookup then
  828. begin
  829. o:=syms[0].value; {Start with min value.}
  830. for i:=0 to sym_count-1 do
  831. begin
  832. while o<syms[i].value do
  833. begin
  834. asmlists[al_rtti].concat(Tai_const.create_aint(0));
  835. inc(o);
  836. end;
  837. inc(o);
  838. asmlists[al_rtti].concat(Tai_const.create_sym_offset(mainrtti,st+offsets[i]));
  839. end;
  840. end
  841. else
  842. begin
  843. asmlists[al_rtti].concat(Tai_const.create_32bit(sym_count));
  844. for i:=0 to sym_count-1 do
  845. begin
  846. asmlists[al_rtti].concat(Tai_const.create_32bit(syms[i].value));
  847. asmlists[al_rtti].concat(Tai_const.create_sym_offset(mainrtti,st+offsets[i]));
  848. end;
  849. end;
  850. asmlists[al_rtti].concat(Tai_symbol_end.create(rttilab));
  851. end;
  852. dispose(syms);
  853. dispose(offsets);
  854. end;
  855. procedure enumdef_rtti_string2ordindex(def:Tenumdef);
  856. var rttilab:Tasmsymbol;
  857. t:Tenumsym;
  858. syms:^Tenumsym;
  859. offsets:^longint;
  860. sym_count,sym_alloc:longint;
  861. h,i,p,o,st:longint;
  862. begin
  863. {Random access needed, put in array.}
  864. getmem(syms,64*sizeof(Tenumsym));
  865. getmem(offsets,64*sizeof(longint));
  866. sym_count:=0;
  867. sym_alloc:=64;
  868. st:=0;
  869. t:=Tenumsym(def.firstenum);
  870. while assigned(t) do
  871. begin
  872. if sym_count>=sym_alloc then
  873. begin
  874. reallocmem(syms,2*sym_alloc*sizeof(Tenumsym));
  875. reallocmem(offsets,2*sym_alloc*sizeof(longint));
  876. sym_alloc:=sym_alloc*2;
  877. end;
  878. syms[sym_count]:=t;
  879. offsets[sym_count]:=st;
  880. inc(sym_count);
  881. st:=st+length(t.realname)+1;
  882. t:=t.nextenum;
  883. end;
  884. {Sort the syms by enum name}
  885. if sym_count>=2 then
  886. begin
  887. p:=1;
  888. while 2*p<sym_count do
  889. p:=2*p;
  890. while p<>0 do
  891. begin
  892. for h:=p to sym_count-1 do
  893. begin
  894. i:=h;
  895. t:=syms[i];
  896. o:=offsets[i];
  897. repeat
  898. if syms[i-p].name<=t.name then
  899. break;
  900. syms[i]:=syms[i-p];
  901. offsets[i]:=offsets[i-p];
  902. dec(i,p);
  903. until i<p;
  904. syms[i]:=t;
  905. offsets[i]:=o;
  906. end;
  907. p:=p shr 1;
  908. end;
  909. end;
  910. {Calculate start of string table.}
  911. st:=1;
  912. if assigned(def.typesym) then
  913. inc(st,length(def.typesym.realname)+1)
  914. else
  915. inc(st);
  916. if (tf_requires_proper_alignment in target_info.flags) then
  917. align(st,sizeof(Tconstptruint));
  918. inc(st);
  919. if (tf_requires_proper_alignment in target_info.flags) then
  920. align(st,sizeof(Tconstptruint));
  921. inc(st,8+sizeof(aint));
  922. { write rtti data }
  923. with current_asmdata do
  924. begin
  925. rttilab:=defineasmsymbol(Tstoreddef(def).rtti_mangledname(rt)+'_s2o',AB_GLOBAL,AT_DATA);
  926. maybe_new_object_file(asmlists[al_rtti]);
  927. new_section(asmlists[al_rtti],sec_rodata,rttilab.name,const_align(sizeof(aint)));
  928. asmlists[al_rtti].concat(Tai_symbol.create_global(rttilab,0));
  929. asmlists[al_rtti].concat(Tai_const.create_32bit(sym_count));
  930. for i:=0 to sym_count-1 do
  931. begin
  932. asmlists[al_rtti].concat(Tai_const.create_32bit(syms[i].value));
  933. asmlists[al_rtti].concat(Tai_const.create_sym_offset(mainrtti,st+offsets[i]));
  934. end;
  935. asmlists[al_rtti].concat(Tai_symbol_end.create(rttilab));
  936. end;
  937. dispose(syms);
  938. dispose(offsets);
  939. end;
  940. begin
  941. case def.typ of
  942. enumdef:
  943. if rt=fullrtti then
  944. begin
  945. enumdef_rtti_ord2stringindex(Tenumdef(def));
  946. enumdef_rtti_string2ordindex(Tenumdef(def));
  947. end;
  948. end;
  949. end;
  950. procedure TRTTIWriter.write_child_rtti_data(def:tdef;rt:trttitype);
  951. begin
  952. case def.typ of
  953. enumdef :
  954. if assigned(tenumdef(def).basedef) then
  955. write_rtti(tenumdef(def).basedef,rt);
  956. setdef :
  957. write_rtti(tsetdef(def).elementdef,rt);
  958. arraydef :
  959. write_rtti(tarraydef(def).elementdef,rt);
  960. recorddef :
  961. fields_write_rtti(trecorddef(def).symtable,rt);
  962. objectdef :
  963. begin
  964. if assigned(tobjectdef(def).childof) then
  965. write_rtti(tobjectdef(def).childof,rt);
  966. if rt=initrtti then
  967. fields_write_rtti(tobjectdef(def).symtable,rt)
  968. else
  969. published_write_rtti(tobjectdef(def).symtable,rt);
  970. end;
  971. end;
  972. end;
  973. function TRTTIWriter.ref_rtti(def:tdef;rt:trttitype):tasmsymbol;
  974. begin
  975. result:=current_asmdata.RefAsmSymbol(def.rtti_mangledname(rt));
  976. end;
  977. procedure TRTTIWriter.write_rtti(def:tdef;rt:trttitype);
  978. var
  979. rttilab : tasmsymbol;
  980. begin
  981. { only write rtti of definitions from the current module }
  982. if not findunitsymtable(def.owner).iscurrentunit then
  983. exit;
  984. { prevent recursion }
  985. if rttidefstate[rt] in def.defstates then
  986. exit;
  987. include(def.defstates,rttidefstate[rt]);
  988. { write first all dependencies }
  989. write_child_rtti_data(def,rt);
  990. { write rtti data }
  991. rttilab:=current_asmdata.DefineAsmSymbol(tstoreddef(def).rtti_mangledname(rt),AB_GLOBAL,AT_DATA);
  992. maybe_new_object_file(current_asmdata.asmlists[al_rtti]);
  993. new_section(current_asmdata.asmlists[al_rtti],sec_rodata,rttilab.name,const_align(sizeof(aint)));
  994. current_asmdata.asmlists[al_rtti].concat(Tai_symbol.Create_global(rttilab,0));
  995. write_rtti_data(def,rt);
  996. current_asmdata.asmlists[al_rtti].concat(Tai_symbol_end.Create(rttilab));
  997. write_rtti_extrasyms(def,rt,rttilab);
  998. end;
  999. function TRTTIWriter.get_rtti_label(def:tdef;rt:trttitype):tasmsymbol;
  1000. begin
  1001. result:=current_asmdata.RefAsmSymbol(def.rtti_mangledname(rt));
  1002. end;
  1003. function TRTTIWriter.get_rtti_label_ord2str(def:tdef;rt:trttitype):tasmsymbol;
  1004. begin
  1005. result:=current_asmdata.RefAsmSymbol(def.rtti_mangledname(rt)+'_o2s');
  1006. end;
  1007. function TRTTIWriter.get_rtti_label_str2ord(def:tdef;rt:trttitype):tasmsymbol;
  1008. begin
  1009. result:=current_asmdata.RefAsmSymbol(def.rtti_mangledname(rt)+'_s2o');
  1010. end;
  1011. end.