ncgrtti.pas 86 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208
  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,constexp,globtype,
  22. aasmbase,aasmcnst,
  23. symbase,symconst,symtype,symdef,symsym,
  24. parabase;
  25. type
  26. { TRTTIWriter }
  27. TRTTIWriter=class
  28. private
  29. { required internal alignment of the rtti data }
  30. reqalign: shortint;
  31. { required packing of all structures except for ttypeinfo and tpropinfo,
  32. which always use packrecords 1 }
  33. defaultpacking: shortint;
  34. procedure fields_write_rtti(st:tsymtable;rt:trttitype);
  35. procedure params_write_rtti(def:tabstractprocdef;rt:trttitype;allow_hidden:boolean);
  36. procedure fields_write_rtti_data(tcb: ttai_typedconstbuilder; def: tabstractrecorddef; rt: trttitype);
  37. procedure methods_write_rtti(st:tsymtable;rt:trttitype;visibilities:tvisibilities;allow_hidden:boolean);
  38. procedure write_rtti_extrasyms(def:Tdef;rt:Trttitype;mainrtti:Tasmsymbol);
  39. procedure published_write_rtti(st:tsymtable;rt:trttitype);
  40. function published_properties_count(st:tsymtable):longint;
  41. procedure published_properties_write_rtti_data(tcb: ttai_typedconstbuilder; propnamelist: TFPHashObjectList; st: tsymtable);
  42. procedure collect_propnamelist(propnamelist:TFPHashObjectList;objdef:tobjectdef);
  43. { only use a direct reference if the referenced type can *only* reside
  44. in the same unit as the current one }
  45. function ref_rtti(def:tdef;rt:trttitype;indirect:boolean;suffix:tsymstr):tasmsymbol;
  46. procedure write_rtti_name(tcb: ttai_typedconstbuilder; def: tdef);
  47. procedure write_rtti_data(tcb: ttai_typedconstbuilder; def:tdef; rt: trttitype);
  48. procedure write_attribute_data(tcb: ttai_typedconstbuilder;attr_list:trtti_attribute_list);
  49. procedure write_unit_info_reference(tcb: ttai_typedconstbuilder);
  50. procedure write_child_rtti_data(def:tdef;rt:trttitype);
  51. procedure write_rtti_reference(tcb: ttai_typedconstbuilder; def: tdef; rt: trttitype);
  52. procedure write_methods(tcb:ttai_typedconstbuilder;st:tsymtable;visibilities:tvisibilities);
  53. procedure write_header(tcb: ttai_typedconstbuilder; def: tdef; typekind: byte);
  54. function write_methodkind(tcb:ttai_typedconstbuilder;def:tabstractprocdef):byte;
  55. procedure write_callconv(tcb:ttai_typedconstbuilder;def:tabstractprocdef);
  56. procedure write_paralocs(tcb:ttai_typedconstbuilder;para:pcgpara);
  57. procedure write_param_flag(tcb:ttai_typedconstbuilder;parasym:tparavarsym);
  58. procedure write_mop_offset_table(tcb:ttai_typedconstbuilder;def:tabstractrecorddef;mop:tmanagementoperator);
  59. public
  60. constructor create;
  61. procedure write_rtti(def:tdef;rt:trttitype);
  62. function get_rtti_label(def:tdef;rt:trttitype;indirect:boolean):tasmsymbol; inline;
  63. function get_rtti_label_ord2str(def:tdef;rt:trttitype;indirect:boolean):tasmsymbol; inline;
  64. function get_rtti_label_str2ord(def:tdef;rt:trttitype;indirect:boolean):tasmsymbol; inline;
  65. procedure start_write_unit_info;
  66. procedure after_write_unit_info(st: TSymtable);
  67. end;
  68. { generate RTTI and init tables }
  69. procedure write_persistent_type_info(st:tsymtable;is_global:boolean);
  70. var
  71. RTTIWriter : TRTTIWriter;
  72. implementation
  73. uses
  74. cutils,
  75. globals,verbose,systems,
  76. fmodule, procinfo,
  77. symtable,
  78. aasmtai,aasmdata,
  79. defutil,
  80. paramgr
  81. ;
  82. const
  83. rttidefstate : array[trttitype] of tdefstate =
  84. (ds_rtti_table_written,ds_init_table_written,
  85. { Objective-C related, does not pass here }
  86. symconst.ds_none,symconst.ds_none,
  87. symconst.ds_none,symconst.ds_none);
  88. type
  89. TPropNameListItem = class(TFPHashObject)
  90. propindex : longint;
  91. propowner : TSymtable;
  92. end;
  93. procedure write_persistent_type_info(st: tsymtable; is_global: boolean);
  94. var
  95. i : longint;
  96. def : tdef;
  97. begin
  98. { no Delphi-style RTTI for managed platforms }
  99. if target_info.system in systems_managed_vm then
  100. exit;
  101. if current_module.rttiunitinfo=nil then
  102. RTTIWriter.start_write_unit_info;
  103. for i:=0 to st.DefList.Count-1 do
  104. begin
  105. def:=tdef(st.DefList[i]);
  106. { skip generics }
  107. if [df_generic,df_genconstraint]*def.defoptions<>[] then
  108. continue;
  109. case def.typ of
  110. recorddef:
  111. write_persistent_type_info(trecorddef(def).symtable,is_global);
  112. objectdef :
  113. begin
  114. { Skip forward defs }
  115. if (oo_is_forward in tobjectdef(def).objectoptions) then
  116. continue;
  117. write_persistent_type_info(tobjectdef(def).symtable,is_global);
  118. end;
  119. procdef :
  120. begin
  121. if assigned(tprocdef(def).localst) and
  122. (tprocdef(def).localst.symtabletype=localsymtable) then
  123. write_persistent_type_info(tprocdef(def).localst,false);
  124. if assigned(tprocdef(def).parast) then
  125. write_persistent_type_info(tprocdef(def).parast,false);
  126. end;
  127. errordef:
  128. { we shouldn't have come this far if we have an errordef somewhere }
  129. internalerror(2017010701);
  130. undefineddef:
  131. { don't write any RTTI for these }
  132. continue;
  133. else
  134. ;
  135. end;
  136. { always generate persistent tables for types in the interface so
  137. they can be reused in other units and give always the same pointer
  138. location. }
  139. { Init }
  140. if (
  141. assigned(def.typesym) and
  142. is_global and
  143. not is_objc_class_or_protocol(def)
  144. ) or
  145. is_managed_type(def) or
  146. (ds_init_table_used in def.defstates) then
  147. RTTIWriter.write_rtti(def,initrtti);
  148. { RTTI }
  149. if (
  150. assigned(def.typesym) and
  151. is_global and
  152. not is_objc_class_or_protocol(def)
  153. ) or
  154. (ds_rtti_table_used in def.defstates) then
  155. RTTIWriter.write_rtti(def,fullrtti);
  156. end;
  157. if st.symtabletype = staticsymtable then
  158. RTTIWriter.after_write_unit_info(st);
  159. end;
  160. {***************************************************************************
  161. TRTTIWriter
  162. ***************************************************************************}
  163. function TRTTIWriter.get_rtti_label(def:tdef;rt:trttitype;indirect:boolean):tasmsymbol;
  164. begin
  165. result:=ref_rtti(def,rt,indirect,'');
  166. end;
  167. function TRTTIWriter.get_rtti_label_ord2str(def:tdef;rt:trttitype;indirect:boolean):tasmsymbol;
  168. begin
  169. result:=ref_rtti(def,rt,indirect,'_o2s');
  170. end;
  171. function TRTTIWriter.get_rtti_label_str2ord(def:tdef;rt:trttitype;indirect:boolean):tasmsymbol;
  172. begin
  173. result:=ref_rtti(def,rt,indirect,'_s2o');
  174. end;
  175. procedure TRTTIWriter.write_methods(tcb:ttai_typedconstbuilder;st:tsymtable;visibilities:tvisibilities);
  176. var
  177. rtticount,
  178. totalcount,
  179. i,j,k : longint;
  180. sym : tprocsym;
  181. def : tprocdef;
  182. para : tparavarsym;
  183. begin
  184. tcb.begin_anonymous_record('',defaultpacking,min(reqalign,SizeOf(PInt)),
  185. targetinfos[target_info.system]^.alignment.recordalignmin,
  186. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  187. totalcount:=0;
  188. rtticount:=0;
  189. for i:=0 to st.symlist.count-1 do
  190. if tsym(st.symlist[i]).typ=procsym then
  191. begin
  192. sym:=tprocsym(st.symlist[i]);
  193. inc(totalcount,sym.procdeflist.count);
  194. for j:=0 to sym.procdeflist.count-1 do
  195. if tprocdef(sym.procdeflist[j]).visibility in visibilities then
  196. inc(rtticount);
  197. end;
  198. tcb.emit_ord_const(totalcount,u16inttype);
  199. if rtticount = 0 then
  200. tcb.emit_ord_const($FFFF,u16inttype)
  201. else
  202. begin
  203. tcb.emit_ord_const(rtticount,u16inttype);
  204. for i:=0 to st.symlist.count-1 do
  205. if tsym(st.symlist[i]).typ=procsym then
  206. begin
  207. sym:=tprocsym(st.symlist[i]);
  208. for j:=0 to sym.procdeflist.count-1 do
  209. begin
  210. def:=tprocdef(sym.procdeflist[j]);
  211. if not (def.visibility in visibilities) then
  212. continue;
  213. def.init_paraloc_info(callerside);
  214. tcb.begin_anonymous_record('',defaultpacking,min(reqalign,SizeOf(PInt)),
  215. targetinfos[target_info.system]^.alignment.recordalignmin,
  216. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  217. write_rtti_reference(tcb,def.returndef,fullrtti);
  218. write_callconv(tcb,def);
  219. write_methodkind(tcb,def);
  220. tcb.emit_ord_const(def.paras.count,u16inttype);
  221. tcb.emit_ord_const(def.callerargareasize,ptrsinttype);
  222. tcb.emit_pooled_shortstring_const_ref(sym.realname);
  223. for k:=0 to def.paras.count-1 do
  224. begin
  225. para:=tparavarsym(def.paras[k]);
  226. tcb.begin_anonymous_record('',defaultpacking,min(reqalign,SizeOf(PInt)),
  227. targetinfos[target_info.system]^.alignment.recordalignmin,
  228. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  229. if is_open_array(para.vardef) or is_array_of_const(para.vardef) then
  230. write_rtti_reference(tcb,tarraydef(para.vardef).elementdef,fullrtti)
  231. else if para.vardef=cformaltype then
  232. write_rtti_reference(tcb,nil,fullrtti)
  233. else
  234. write_rtti_reference(tcb,para.vardef,fullrtti);
  235. write_param_flag(tcb,para);
  236. tcb.emit_pooled_shortstring_const_ref(para.realname);
  237. write_paralocs(tcb,@para.paraloc[callerside]);
  238. tcb.end_anonymous_record;
  239. end;
  240. if not is_void(def.returndef) then
  241. write_paralocs(tcb,@def.funcretloc[callerside]);
  242. tcb.end_anonymous_record;
  243. end;
  244. end;
  245. end;
  246. tcb.end_anonymous_record;
  247. end;
  248. procedure TRTTIWriter.write_header(tcb: ttai_typedconstbuilder; def: tdef; typekind: byte);
  249. var
  250. name: shortstring;
  251. begin
  252. if assigned(def.typesym) then
  253. name:=ttypesym(def.typesym).realname
  254. else
  255. name:='';
  256. { TTypeInfo, always packed and doesn't need alignment }
  257. tcb.begin_anonymous_record(
  258. internaltypeprefixName[itp_rtti_header]+tostr(length(name)),1,1,
  259. targetinfos[target_info.system]^.alignment.recordalignmin,
  260. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  261. if def.typ=arraydef then
  262. InternalError(201012211);
  263. tcb.emit_tai(Tai_const.Create_8bit(typekind),u8inttype);
  264. tcb.emit_shortstring_const(name);
  265. tcb.end_anonymous_record;
  266. end;
  267. function TRTTIWriter.write_methodkind(tcb:ttai_typedconstbuilder;def:tabstractprocdef):byte;
  268. begin
  269. case def.proctypeoption of
  270. potype_constructor: result:=mkConstructor;
  271. potype_destructor: result:=mkDestructor;
  272. potype_class_constructor: result:=mkClassConstructor;
  273. potype_class_destructor: result:=mkClassDestructor;
  274. potype_operator: result:=mkOperatorOverload;
  275. potype_procedure:
  276. if po_classmethod in def.procoptions then
  277. result:=mkClassProcedure
  278. else
  279. result:=mkProcedure;
  280. potype_function:
  281. if po_classmethod in def.procoptions then
  282. result:=mkClassFunction
  283. else
  284. result:=mkFunction;
  285. else
  286. begin
  287. if def.returndef = voidtype then
  288. result:=mkProcedure
  289. else
  290. result:=mkFunction;
  291. end;
  292. end;
  293. tcb.emit_ord_const(result,u8inttype);
  294. end;
  295. procedure TRTTIWriter.write_callconv(tcb:ttai_typedconstbuilder;def:tabstractprocdef);
  296. const
  297. ProcCallOptionToCallConv: array[tproccalloption] of byte = (
  298. { pocall_none } 0,
  299. { pocall_cdecl } 1,
  300. { pocall_cppdecl } 5,
  301. { pocall_far16 } 6,
  302. { pocall_oldfpccall } 7,
  303. { pocall_internproc } 8,
  304. { pocall_syscall } 9,
  305. { pocall_pascal } 2,
  306. { pocall_register } 0,
  307. { pocall_safecall } 4,
  308. { pocall_stdcall } 3,
  309. { pocall_softfloat } 10,
  310. { pocall_mwpascal } 11,
  311. { pocall_interrupt } 12,
  312. { pocall_hardfloat } 13,
  313. { pocall_sysv_abi_default } 14,
  314. { pocall_sysv_abi_cdecl } 15,
  315. { pocall_ms_abi_default } 16,
  316. { pocall_ms_abi_cdecl } 17,
  317. { pocall_vectorcall } 18
  318. );
  319. begin
  320. tcb.emit_ord_const(ProcCallOptionToCallConv[def.proccalloption],u8inttype);
  321. end;
  322. procedure TRTTIWriter.write_paralocs(tcb:ttai_typedconstbuilder;para:pcgpara);
  323. var
  324. locs : trttiparalocs;
  325. i : longint;
  326. pool : THashSet;
  327. entry : PHashSetItem;
  328. loclab : TAsmLabel;
  329. loctcb : ttai_typedconstbuilder;
  330. datadef : tdef;
  331. begin
  332. locs:=paramanager.cgparalocs_to_rttiparalocs(para^.location);
  333. if length(locs)>high(byte) then
  334. internalerror(2017010601);
  335. if length(locs)=0 then
  336. begin
  337. { *shrugs* }
  338. tcb.emit_tai(Tai_const.Create_nil_codeptr,voidpointertype);
  339. exit;
  340. end;
  341. { do we have such a paraloc already in the pool? }
  342. pool:=current_asmdata.ConstPools[sp_paraloc];
  343. entry:=pool.FindOrAdd(@locs[0],length(locs)*sizeof(trttiparaloc));
  344. if not assigned(entry^.Data) then
  345. begin
  346. current_asmdata.getglobaldatalabel(loclab);
  347. loctcb:=ctai_typedconstbuilder.create([tcalo_is_lab,tcalo_make_dead_strippable,tcalo_apply_constalign]);
  348. loctcb.begin_anonymous_record('',defaultpacking,min(reqalign,SizeOf(PInt)),
  349. targetinfos[target_info.system]^.alignment.recordalignmin,
  350. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  351. loctcb.emit_ord_const(length(locs),u8inttype);
  352. for i:=low(locs) to high(locs) do
  353. begin
  354. loctcb.begin_anonymous_record('',defaultpacking,min(reqalign,SizeOf(PInt)),
  355. targetinfos[target_info.system]^.alignment.recordalignmin,
  356. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  357. loctcb.emit_ord_const(locs[i].loctype,u8inttype);
  358. loctcb.emit_ord_const(locs[i].regsub,u8inttype);
  359. loctcb.emit_ord_const(locs[i].regindex,u16inttype);
  360. { the corresponding type for aint is alusinttype }
  361. loctcb.emit_ord_const(locs[i].offset,alusinttype);
  362. loctcb.end_anonymous_record;
  363. end;
  364. datadef:=loctcb.end_anonymous_record;
  365. current_asmdata.asmlists[al_typedconsts].concatList(
  366. loctcb.get_final_asmlist(loclab,datadef,sec_rodata_norel,loclab.name,const_align(sizeof(pint)))
  367. );
  368. loctcb.free;
  369. entry^.data:=loclab;
  370. end
  371. else
  372. loclab:=TAsmLabel(entry^.Data);
  373. tcb.emit_tai(Tai_const.Create_sym(loclab),voidpointertype);
  374. end;
  375. procedure TRTTIWriter.write_param_flag(tcb:ttai_typedconstbuilder;parasym:tparavarsym);
  376. var
  377. paraspec : word;
  378. begin
  379. case parasym.varspez of
  380. vs_value : paraspec := 0;
  381. vs_const : paraspec := pfConst;
  382. vs_var : paraspec := pfVar;
  383. vs_out : paraspec := pfOut;
  384. vs_constref: paraspec := pfConstRef;
  385. else
  386. internalerror(2013112904);
  387. end;
  388. { Kylix also seems to always add both pfArray and pfReference
  389. in this case
  390. }
  391. if is_open_array(parasym.vardef) or is_array_of_const(parasym.vardef) then
  392. paraspec:=paraspec or pfArray or pfReference;
  393. { and these for classes and interfaces (maybe because they
  394. are themselves addresses?)
  395. }
  396. if is_class_or_interface(parasym.vardef) then
  397. paraspec:=paraspec or pfAddress;
  398. { flags for the hidden parameters }
  399. if vo_is_hidden_para in parasym.varoptions then
  400. paraspec:=paraspec or pfHidden;
  401. if vo_is_high_para in parasym.varoptions then
  402. paraspec:=paraspec or pfHigh;
  403. if vo_is_self in parasym.varoptions then
  404. paraspec:=paraspec or pfSelf;
  405. if vo_is_vmt in parasym.varoptions then
  406. paraspec:=paraspec or pfVmt;
  407. if vo_is_funcret in parasym.varoptions then
  408. paraspec:=paraspec or pfResult;
  409. { set bits run from the highest to the lowest bit on
  410. big endian systems
  411. }
  412. if (target_info.endian = endian_big) then
  413. paraspec:=reverse_word(paraspec);
  414. { write flags for current parameter }
  415. tcb.emit_ord_const(paraspec,u16inttype);
  416. end;
  417. function compare_mop_offset_entry(item1,item2:pointer):longint;
  418. var
  419. entry1: pmanagementoperator_offset_entry absolute item1;
  420. entry2: pmanagementoperator_offset_entry absolute item2;
  421. begin
  422. if entry1^.offset<entry2^.offset then
  423. result:=-1
  424. else if entry1^.offset>entry2^.offset then
  425. result:=1
  426. else
  427. result:=0;
  428. end;
  429. procedure TRTTIWriter.write_mop_offset_table(tcb:ttai_typedconstbuilder;def:tabstractrecorddef;mop:tmanagementoperator);
  430. var
  431. list : tfplist;
  432. datatcb : ttai_typedconstbuilder;
  433. tbllbl : TAsmLabel;
  434. entry : pmanagementoperator_offset_entry;
  435. datadef,entrydef : tdef;
  436. i : longint;
  437. pdef : tobjectdef;
  438. begin
  439. list:=tfplist.create;
  440. tabstractrecordsymtable(def.symtable).get_managementoperator_offset_list(mop,list);
  441. if (def.typ=objectdef) then
  442. begin
  443. pdef:=tobjectdef(def).childof;
  444. while assigned(pdef) do
  445. begin
  446. tabstractrecordsymtable(pdef.symtable).get_managementoperator_offset_list(mop,list);
  447. pdef:=pdef.childof;
  448. end;
  449. list.sort(@compare_mop_offset_entry);
  450. end;
  451. if list.count=0 then
  452. tcb.emit_tai(tai_const.create_nil_dataptr,voidpointertype)
  453. else
  454. begin
  455. tcb.start_internal_data_builder(current_asmdata.AsmLists[al_rtti],sec_rodata,'',datatcb,tbllbl);
  456. datatcb.begin_anonymous_record('',defaultpacking,min(reqalign,SizeOf(PInt)),
  457. targetinfos[target_info.system]^.alignment.recordalignmin,
  458. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  459. datatcb.emit_ord_const(list.count,u32inttype);
  460. entrydef:=get_recorddef(itp_init_mop_offset_entry,[voidcodepointertype,sizeuinttype],defaultpacking);
  461. for i:=0 to list.count-1 do
  462. begin
  463. entry:=pmanagementoperator_offset_entry(list[i]);
  464. datatcb.maybe_begin_aggregate(entrydef);
  465. datatcb.queue_init(voidcodepointertype);
  466. datatcb.queue_emit_proc(entry^.pd);
  467. datatcb.queue_init(sizeuinttype);
  468. datatcb.queue_emit_ordconst(entry^.offset,sizeuinttype);
  469. datatcb.maybe_end_aggregate(entrydef);
  470. dispose(entry);
  471. end;
  472. datadef:=datatcb.end_anonymous_record;
  473. tcb.finish_internal_data_builder(datatcb,tbllbl,datadef,sizeof(pint));
  474. tcb.emit_tai(tai_const.Create_sym(tbllbl),voidpointertype);
  475. end;
  476. list.free;
  477. end;
  478. procedure TRTTIWriter.write_rtti_name(tcb: ttai_typedconstbuilder; def: tdef);
  479. begin
  480. if is_open_array(def) then
  481. { open arrays never have a typesym with a name, since you cannot
  482. define an "open array type". Kylix prints the type of the
  483. elements in the array in this case (so together with the pfArray
  484. flag, you can reconstruct the full typename, I assume (JM))
  485. }
  486. def:=tarraydef(def).elementdef;
  487. { name }
  488. if assigned(def.typesym) then
  489. tcb.emit_shortstring_const(ttypesym(def.typesym).realname)
  490. else
  491. tcb.emit_shortstring_const('');
  492. end;
  493. { writes a 32-bit count followed by array of field infos for given symtable }
  494. procedure TRTTIWriter.fields_write_rtti_data(tcb: ttai_typedconstbuilder; def: tabstractrecorddef; rt: trttitype);
  495. var
  496. i : longint;
  497. sym : tsym;
  498. fieldcnt: longint;
  499. st: tsymtable;
  500. fields: tfplist;
  501. parentrtti: boolean;
  502. begin
  503. fieldcnt:=0;
  504. parentrtti:=false;
  505. st:=def.symtable;
  506. fields:=tfplist.create;
  507. fields.capacity:=st.symlist.count+1;
  508. { For objects, treat parent (if any) as a field with offset 0. This
  509. provides correct handling of entire instance with RTL rtti routines. }
  510. if (def.typ=objectdef) and (tobjectdef(def).objecttype=odt_object) and
  511. Assigned(tobjectdef(def).childof) and
  512. ((rt=fullrtti) or (tobjectdef(def).childof.needs_inittable)) then
  513. begin
  514. parentrtti:=true;
  515. inc(fieldcnt);
  516. end;
  517. for i:=0 to st.SymList.Count-1 do
  518. begin
  519. sym:=tsym(st.SymList[i]);
  520. if (tsym(sym).typ=fieldvarsym) and
  521. not(sp_static in tsym(sym).symoptions) and
  522. (
  523. (rt=fullrtti) or
  524. tfieldvarsym(sym).vardef.needs_inittable
  525. ) and
  526. not is_objc_class_or_protocol(tfieldvarsym(sym).vardef) then
  527. begin
  528. fields.add(tfieldvarsym(sym));
  529. inc(fieldcnt);
  530. end;
  531. end;
  532. { insert field count before data }
  533. tcb.emit_ord_const(fieldcnt,u32inttype);
  534. { parent object? }
  535. if parentrtti then
  536. begin
  537. write_rtti_reference(tcb,tobjectdef(def).childof,rt);
  538. tcb.emit_ord_const(0,ptruinttype);
  539. end;
  540. { fields }
  541. for i:=0 to fields.count-1 do
  542. begin
  543. sym:=tsym(fields[i]);
  544. write_rtti_reference(tcb,tfieldvarsym(sym).vardef,rt);
  545. tcb.emit_ord_const(tfieldvarsym(sym).fieldoffset,ptruinttype);
  546. end;
  547. fields.free;
  548. end;
  549. procedure TRTTIWriter.fields_write_rtti(st:tsymtable;rt:trttitype);
  550. var
  551. i : longint;
  552. sym : tsym;
  553. begin
  554. for i:=0 to st.SymList.Count-1 do
  555. begin
  556. sym:=tsym(st.SymList[i]);
  557. if (tsym(sym).typ=fieldvarsym) and
  558. not(sp_static in tsym(sym).symoptions) and
  559. (
  560. (rt=fullrtti) or
  561. tfieldvarsym(sym).vardef.needs_inittable
  562. ) then
  563. write_rtti(tfieldvarsym(sym).vardef,rt);
  564. end;
  565. end;
  566. procedure TRTTIWriter.params_write_rtti(def:tabstractprocdef;rt:trttitype;allow_hidden:boolean);
  567. var
  568. i : longint;
  569. sym : tparavarsym;
  570. begin
  571. for i:=0 to def.paras.count-1 do
  572. begin
  573. sym:=tparavarsym(def.paras[i]);
  574. if not (vo_is_hidden_para in sym.varoptions) or allow_hidden then
  575. begin
  576. if is_open_array(sym.vardef) or is_array_of_const(sym.vardef) then
  577. write_rtti(tarraydef(sym.vardef).elementdef,rt)
  578. else
  579. write_rtti(sym.vardef,rt);
  580. end;
  581. end;
  582. end;
  583. procedure TRTTIWriter.methods_write_rtti(st:tsymtable;rt:trttitype;visibilities:tvisibilities;allow_hidden:boolean);
  584. var
  585. i,j : longint;
  586. sym : tprocsym;
  587. def : tabstractprocdef;
  588. begin
  589. for i:=0 to st.symlist.count-1 do
  590. if tsym(st.symlist[i]).typ=procsym then
  591. begin
  592. sym:=tprocsym(st.symlist[i]);
  593. for j:=0 to sym.procdeflist.count-1 do
  594. begin
  595. def:=tabstractprocdef(sym.procdeflist[j]);
  596. write_rtti(def.returndef,rt);
  597. params_write_rtti(def,rt,allow_hidden);
  598. end;
  599. end;
  600. end;
  601. procedure TRTTIWriter.published_write_rtti(st:tsymtable;rt:trttitype);
  602. var
  603. i : longint;
  604. sym : tsym;
  605. begin
  606. for i:=0 to st.SymList.Count-1 do
  607. begin
  608. sym:=tsym(st.SymList[i]);
  609. if (sym.visibility=vis_published) then
  610. begin
  611. case tsym(sym).typ of
  612. propertysym:
  613. write_rtti(tpropertysym(sym).propdef,rt);
  614. fieldvarsym:
  615. write_rtti(tfieldvarsym(sym).vardef,rt);
  616. else
  617. ;
  618. end;
  619. end;
  620. end;
  621. end;
  622. function TRTTIWriter.published_properties_count(st:tsymtable):longint;
  623. var
  624. i : longint;
  625. sym : tsym;
  626. begin
  627. result:=0;
  628. for i:=0 to st.SymList.Count-1 do
  629. begin
  630. sym:=tsym(st.SymList[i]);
  631. if (tsym(sym).typ=propertysym) and
  632. (sym.visibility=vis_published) then
  633. inc(result);
  634. end;
  635. end;
  636. procedure TRTTIWriter.collect_propnamelist(propnamelist:TFPHashObjectList;objdef:tobjectdef);
  637. var
  638. i : longint;
  639. sym : tsym;
  640. pn : tpropnamelistitem;
  641. begin
  642. if assigned(objdef.childof) then
  643. collect_propnamelist(propnamelist,objdef.childof);
  644. for i:=0 to objdef.symtable.SymList.Count-1 do
  645. begin
  646. sym:=tsym(objdef.symtable.SymList[i]);
  647. if (tsym(sym).typ=propertysym) and
  648. (sym.visibility=vis_published) then
  649. begin
  650. pn:=TPropNameListItem(propnamelist.Find(tsym(sym).name));
  651. if not assigned(pn) then
  652. begin
  653. pn:=tpropnamelistitem.create(propnamelist,tsym(sym).name);
  654. pn.propindex:=propnamelist.count-1;
  655. pn.propowner:=tsym(sym).owner;
  656. end;
  657. end;
  658. end;
  659. end;
  660. procedure TRTTIWriter.published_properties_write_rtti_data(tcb: ttai_typedconstbuilder; propnamelist:TFPHashObjectList;st:tsymtable);
  661. var
  662. i : longint;
  663. sym : tsym;
  664. proctypesinfo : byte;
  665. propnameitem : tpropnamelistitem;
  666. propdefname : string;
  667. procedure writeaccessproc(pap:tpropaccesslisttypes; shiftvalue : byte; unsetvalue: byte);
  668. var
  669. typvalue : byte;
  670. hp : ppropaccesslistitem;
  671. extnumber: longint;
  672. address,space : longint;
  673. def : tdef;
  674. hpropsym : tpropertysym;
  675. propaccesslist : tpropaccesslist;
  676. begin
  677. hpropsym:=tpropertysym(sym);
  678. repeat
  679. propaccesslist:=hpropsym.propaccesslist[pap];
  680. if not propaccesslist.empty then
  681. break;
  682. hpropsym:=hpropsym.overriddenpropsym;
  683. until not assigned(hpropsym);
  684. if not(assigned(propaccesslist) and assigned(propaccesslist.firstsym)) then
  685. begin
  686. tcb.emit_tai(Tai_const.Create_int_codeptr(unsetvalue),codeptruinttype);
  687. typvalue:=3;
  688. end
  689. else if propaccesslist.firstsym^.sym.typ=fieldvarsym then
  690. begin
  691. address:=0;
  692. hp:=propaccesslist.firstsym;
  693. def:=nil;
  694. while assigned(hp) do
  695. begin
  696. case hp^.sltype of
  697. sl_load :
  698. begin
  699. def:=tfieldvarsym(hp^.sym).vardef;
  700. inc(address,tfieldvarsym(hp^.sym).fieldoffset);
  701. end;
  702. sl_subscript :
  703. begin
  704. if not(assigned(def) and
  705. ((def.typ=recorddef) or
  706. is_object(def))) then
  707. internalerror(200402171);
  708. inc(address,tfieldvarsym(hp^.sym).fieldoffset);
  709. def:=tfieldvarsym(hp^.sym).vardef;
  710. end;
  711. sl_vec :
  712. begin
  713. if not(assigned(def) and (def.typ=arraydef)) then
  714. internalerror(200402172);
  715. def:=tarraydef(def).elementdef;
  716. {Hp.value is a Tconstexprint, which can be rather large,
  717. sanity check for longint overflow.}
  718. space:=(high(address)-address) div def.size;
  719. if int64(space)<hp^.value then
  720. internalerror(200706101);
  721. inc(address,int64(def.size*hp^.value));
  722. end;
  723. else
  724. internalerror(2019050523);
  725. end;
  726. hp:=hp^.next;
  727. end;
  728. tcb.emit_tai(Tai_const.Create_int_codeptr(address),codeptruinttype);
  729. typvalue:=0;
  730. end
  731. else
  732. begin
  733. { When there was an error then procdef is not assigned }
  734. if not assigned(propaccesslist.procdef) then
  735. exit;
  736. if not(po_virtualmethod in tprocdef(propaccesslist.procdef).procoptions) or
  737. is_objectpascal_helper(tprocdef(propaccesslist.procdef).struct) then
  738. begin
  739. tcb.queue_init(codeptruinttype);
  740. tcb.queue_emit_proc(tprocdef(propaccesslist.procdef));
  741. typvalue:=1;
  742. end
  743. else
  744. begin
  745. { virtual method, write vmt offset }
  746. extnumber:=tprocdef(propaccesslist.procdef).extnumber;
  747. tcb.emit_tai(Tai_const.Create_int_codeptr(
  748. tobjectdef(tprocdef(propaccesslist.procdef).struct).vmtmethodoffset(extnumber)),
  749. codeptruinttype);
  750. { register for wpo }
  751. tobjectdef(tprocdef(propaccesslist.procdef).struct).register_vmt_call(extnumber);
  752. {$ifdef vtentry}
  753. { not sure if we can insert those vtentry symbols safely here }
  754. {$error register methods used for published properties}
  755. {$endif vtentry}
  756. typvalue:=2;
  757. end;
  758. end;
  759. proctypesinfo:=proctypesinfo or (typvalue shl shiftvalue);
  760. end;
  761. begin
  762. tcb.begin_anonymous_record('',defaultpacking,min(reqalign,SizeOf(PInt)),
  763. targetinfos[target_info.system]^.alignment.recordalignmin,
  764. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  765. tcb.emit_ord_const(published_properties_count(st),u16inttype);
  766. for i:=0 to st.SymList.Count-1 do
  767. begin
  768. sym:=tsym(st.SymList[i]);
  769. if (sym.typ=propertysym) and
  770. (sym.visibility=vis_published) then
  771. begin
  772. { we can only easily reuse defs if the property is not stored,
  773. because otherwise the rtti layout depends on how the "stored"
  774. is defined (field, indexed expression, virtual method, ...) }
  775. if not(ppo_stored in tpropertysym(sym).propoptions) then
  776. propdefname:=internaltypeprefixName[itp_rtti_prop]+tostr(length(tpropertysym(sym).realname))
  777. else
  778. propdefname:='';
  779. { TPropInfo is a packed record (even on targets that require
  780. alignment), but it starts aligned }
  781. tcb.begin_anonymous_record(
  782. propdefname,
  783. 1,min(reqalign,SizeOf(PInt)),
  784. targetinfos[target_info.system]^.alignment.recordalignmin,
  785. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  786. if ppo_indexed in tpropertysym(sym).propoptions then
  787. proctypesinfo:=$40
  788. else
  789. proctypesinfo:=0;
  790. write_rtti_reference(tcb,tpropertysym(sym).propdef,fullrtti);
  791. writeaccessproc(palt_read,0,0);
  792. writeaccessproc(palt_write,2,0);
  793. { is it stored ? }
  794. if not(ppo_stored in tpropertysym(sym).propoptions) then
  795. begin
  796. { no, so put a constant zero }
  797. tcb.emit_tai(Tai_const.Create_nil_codeptr,codeptruinttype);
  798. proctypesinfo:=proctypesinfo or (3 shl 4);
  799. end
  800. else
  801. writeaccessproc(palt_stored,4,1); { maybe; if no procedure put a constant 1 (=true) }
  802. tcb.emit_ord_const(tpropertysym(sym).index,u32inttype);
  803. tcb.emit_ord_const(tpropertysym(sym).default,u32inttype);
  804. propnameitem:=TPropNameListItem(propnamelist.Find(tpropertysym(sym).name));
  805. if not assigned(propnameitem) then
  806. internalerror(200512201);
  807. tcb.emit_ord_const(propnameitem.propindex,u16inttype);
  808. tcb.emit_ord_const(proctypesinfo,u8inttype);
  809. { write reference to attribute table }
  810. write_attribute_data(tcb,tpropertysym(sym).rtti_attribute_list);
  811. { Write property name }
  812. tcb.emit_shortstring_const(tpropertysym(sym).realname);
  813. tcb.end_anonymous_record;
  814. end;
  815. end;
  816. tcb.end_anonymous_record;
  817. end;
  818. procedure TRTTIWriter.write_rtti_data(tcb: ttai_typedconstbuilder; def: tdef; rt: trttitype);
  819. procedure unknown_rtti(def:tstoreddef);
  820. begin
  821. tcb.emit_ord_const(tkUnknown,u8inttype);
  822. write_rtti_name(tcb,def);
  823. end;
  824. procedure variantdef_rtti(def:tvariantdef);
  825. begin
  826. write_header(tcb,def,tkVariant);
  827. end;
  828. procedure stringdef_rtti(def:tstringdef);
  829. begin
  830. case def.stringtype of
  831. st_ansistring:
  832. begin
  833. write_header(tcb,def,tkAString);
  834. { align }
  835. tcb.begin_anonymous_record(
  836. internaltypeprefixName[itp_rtti_ansistr],
  837. defaultpacking,reqalign,
  838. targetinfos[target_info.system]^.alignment.recordalignmin,
  839. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  840. tcb.emit_ord_const(def.encoding,u16inttype);
  841. tcb.end_anonymous_record;
  842. end;
  843. st_widestring:
  844. write_header(tcb,def,tkWString);
  845. st_unicodestring:
  846. write_header(tcb,def,tkUString);
  847. st_longstring:
  848. write_header(tcb,def,tkLString);
  849. st_shortstring:
  850. begin
  851. write_header(tcb,def,tkSString);
  852. tcb.emit_ord_const(def.len,u8inttype);
  853. end;
  854. end;
  855. end;
  856. procedure enumdef_rtti(def: tenumdef);
  857. var
  858. i : integer;
  859. hp : tenumsym;
  860. begin
  861. write_header(tcb,def,tkEnumeration);
  862. { align; the named fields are so that we can let the compiler
  863. calculate the string offsets later on }
  864. tcb.next_field_name:='size_start_rec';
  865. { add a typename so that it can be reused when writing the the s2o
  866. and o2s arrays for llvm (otherwise we have to write out the entire
  867. type definition every time we access an element from this record) }
  868. tcb.begin_anonymous_record(internaltypeprefixName[itp_rtti_enum_size_start_rec]+def.unique_id_str,defaultpacking,reqalign,
  869. targetinfos[target_info.system]^.alignment.recordalignmin,
  870. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  871. case longint(def.size) of
  872. 1 :
  873. tcb.emit_ord_const(otUByte,u8inttype);
  874. 2 :
  875. tcb.emit_ord_const(otUWord,u8inttype);
  876. 4 :
  877. tcb.emit_ord_const(otULong,u8inttype);
  878. end;
  879. { we need to align by Tconstptruint here to satisfy the alignment
  880. rules set by records: in the typinfo unit we overlay a TTypeData
  881. record on this data, which at the innermost variant record needs an
  882. alignment of TConstPtrUint due to e.g. the "CompType" member for
  883. tkSet (also the "BaseType" member for tkEnumeration).
  884. We need to adhere to this, otherwise things will break. }
  885. tcb.next_field_name:='min_max_rec';
  886. tcb.begin_anonymous_record(internaltypeprefixName[itp_rtti_enum_min_max_rec]+def.unique_id_str,defaultpacking,reqalign,
  887. targetinfos[target_info.system]^.alignment.recordalignmin,
  888. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  889. tcb.emit_ord_const(def.min,s32inttype);
  890. tcb.emit_ord_const(def.max,s32inttype);
  891. tcb.next_field_name:='basetype_array_rec';
  892. { all strings must appear right after each other -> from now on
  893. packrecords 1 (but the start must still be aligned) }
  894. tcb.begin_anonymous_record(internaltypeprefixName[itp_rtti_enum_basetype_array_rec]+def.unique_id_str,1,reqalign,
  895. targetinfos[target_info.system]^.alignment.recordalignmin,
  896. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  897. { write base type }
  898. write_rtti_reference(tcb,def.basedef,rt);
  899. for i:=0 to def.symtable.SymList.Count-1 do
  900. begin
  901. hp:=tenumsym(def.symtable.SymList[i]);
  902. if hp.value<def.minval then
  903. continue
  904. else
  905. if hp.value>def.maxval then
  906. break;
  907. tcb.next_field_name:=hp.name;
  908. tcb.emit_shortstring_const(hp.realname);
  909. end;
  910. { write unit name }
  911. tcb.emit_shortstring_const(current_module.realmodulename^);
  912. { write zero which is required by RTL }
  913. tcb.emit_ord_const(0,u8inttype);
  914. { terminate all records }
  915. tcb.end_anonymous_record;
  916. tcb.end_anonymous_record;
  917. tcb.end_anonymous_record;
  918. end;
  919. procedure orddef_rtti(def:torddef);
  920. procedure doint32_64(typekind: byte;min,max:int64);
  921. const
  922. trans : array[tordtype] of byte =
  923. (otUByte{otNone},
  924. otUByte,otUWord,otULong,otUQWord,otUByte{otNone},
  925. otSByte,otSWord,otSLong,otSQWord,otUByte{otNone},
  926. otUByte,otUByte,otUWord,otULong,otUQWord,
  927. otSByte,otSWord,otSLong,otSQWord,
  928. otUByte,otUWord,otUByte,255);
  929. var
  930. elesize: string[1];
  931. deftrans: byte;
  932. begin
  933. write_header(tcb,def,typekind);
  934. deftrans:=trans[def.ordtype];
  935. case deftrans of
  936. otUQWord,
  937. otSQWord:
  938. elesize:='8';
  939. 255:
  940. begin
  941. if def.packedbitsize<=32 then
  942. begin
  943. elesize:='4';
  944. if def.low<0 then
  945. deftrans:=otSLong
  946. else
  947. deftrans:=otULong;
  948. end
  949. else
  950. begin
  951. elesize:='8';
  952. if def.low<0 then
  953. deftrans:=otSQWord
  954. else
  955. deftrans:=otUQWord;
  956. end;
  957. end
  958. else
  959. elesize:='4'
  960. end;
  961. tcb.begin_anonymous_record(
  962. internaltypeprefixName[itp_rtti_ord_outer]+elesize,
  963. defaultpacking,reqalign,
  964. targetinfos[target_info.system]^.alignment.recordalignmin,
  965. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  966. tcb.emit_ord_const(byte(trans[def.ordtype]),u8inttype);
  967. tcb.begin_anonymous_record(
  968. internaltypeprefixName[itp_rtti_ord_inner]+elesize,
  969. defaultpacking,reqalign,
  970. targetinfos[target_info.system]^.alignment.recordalignmin,
  971. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  972. {Convert to longint to smuggle values in high(longint)+1..high(cardinal) into asmlist.}
  973. case deftrans of
  974. otUQWord:
  975. begin
  976. tcb.emit_ord_const(min,u64inttype);
  977. tcb.emit_ord_const(max,u64inttype);
  978. end;
  979. otSQWord:
  980. begin
  981. tcb.emit_ord_const(min,s64inttype);
  982. tcb.emit_ord_const(max,s64inttype);
  983. end;
  984. else
  985. begin
  986. tcb.emit_ord_const(longint(min),s32inttype);
  987. tcb.emit_ord_const(longint(max),s32inttype);
  988. end;
  989. end;
  990. tcb.end_anonymous_record;
  991. tcb.end_anonymous_record;
  992. end;
  993. procedure dointeger(typekind:byte);inline;
  994. begin
  995. doint32_64(typekind,int64(def.low.svalue),int64(def.high.svalue));
  996. end;
  997. begin
  998. case def.ordtype of
  999. s64bit :
  1000. dointeger(tkInt64);
  1001. u64bit :
  1002. dointeger(tkQWord);
  1003. pasbool1,
  1004. pasbool8,
  1005. pasbool16,
  1006. pasbool32,
  1007. pasbool64:
  1008. dointeger(tkBool);
  1009. { use different low/high values to be Delphi compatible }
  1010. bool8bit,
  1011. bool16bit,
  1012. bool32bit:
  1013. doint32_64(tkBool,longint(low(longint)),longint(high(longint)));
  1014. bool64bit:
  1015. doint32_64(tkBool,low(int64),high(int64));
  1016. uchar:
  1017. dointeger(tkChar);
  1018. uwidechar:
  1019. dointeger(tkWChar);
  1020. scurrency:
  1021. begin
  1022. write_header(tcb,def,tkFloat);
  1023. tcb.begin_anonymous_record(
  1024. internaltypeprefixName[itp_1byte],
  1025. defaultpacking,reqalign,
  1026. targetinfos[target_info.system]^.alignment.recordalignmin,
  1027. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  1028. tcb.emit_ord_const(ftCurr,u8inttype);
  1029. tcb.end_anonymous_record;
  1030. end;
  1031. else
  1032. dointeger(tkInteger);
  1033. end;
  1034. end;
  1035. procedure floatdef_rtti(def:tfloatdef);
  1036. const
  1037. {tfloattype = (s32real,s64real,s80real,sc80real,s64bit,s128bit);}
  1038. translate : array[tfloattype] of byte =
  1039. (ftSingle,ftDouble,ftExtended,ftExtended,ftComp,ftCurr,ftFloat128);
  1040. begin
  1041. write_header(tcb,def,tkFloat);
  1042. tcb.begin_anonymous_record(
  1043. internaltypeprefixName[itp_1byte],
  1044. defaultpacking,reqalign,
  1045. targetinfos[target_info.system]^.alignment.recordalignmin,
  1046. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  1047. tcb.emit_ord_const(translate[def.floattype],u8inttype);
  1048. tcb.end_anonymous_record;
  1049. end;
  1050. procedure setdef_rtti(def:tsetdef);
  1051. begin
  1052. write_header(tcb,def,tkSet);
  1053. tcb.begin_anonymous_record(
  1054. internaltypeprefixName[itp_rtti_set_outer],
  1055. defaultpacking,reqalign,
  1056. targetinfos[target_info.system]^.alignment.recordalignmin,
  1057. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  1058. case def.size of
  1059. 1:
  1060. tcb.emit_ord_const(otUByte,u8inttype);
  1061. 2:
  1062. tcb.emit_ord_const(otUWord,u8inttype);
  1063. 4:
  1064. tcb.emit_ord_const(otULong,u8inttype);
  1065. else
  1066. tcb.emit_ord_const(otUByte,u8inttype);
  1067. end;
  1068. tcb.begin_anonymous_record(
  1069. internaltypeprefixName[itp_rtti_set_inner],
  1070. defaultpacking,reqalign,
  1071. targetinfos[target_info.system]^.alignment.recordalignmin,
  1072. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  1073. tcb.emit_ord_const(def.size,sizesinttype);
  1074. write_rtti_reference(tcb,def.elementdef,rt);
  1075. tcb.end_anonymous_record;
  1076. tcb.end_anonymous_record;
  1077. end;
  1078. procedure arraydef_rtti(def:tarraydef);
  1079. var
  1080. i,dimcount: byte;
  1081. totalcount: asizeuint;
  1082. finaldef: tdef;
  1083. curdef:tarraydef;
  1084. begin
  1085. if ado_IsDynamicArray in def.arrayoptions then
  1086. tcb.emit_ord_const(tkDynArray,u8inttype)
  1087. else
  1088. tcb.emit_ord_const(tkArray,u8inttype);
  1089. write_rtti_name(tcb,def);
  1090. if not(ado_IsDynamicArray in def.arrayoptions) then
  1091. begin
  1092. { remember tha last instruction. we will need to insert some
  1093. calculated values after it }
  1094. finaldef:=def;
  1095. totalcount:=1;
  1096. dimcount:=0;
  1097. repeat
  1098. curdef:=tarraydef(finaldef);
  1099. finaldef:=curdef.elementdef;
  1100. { Dims[i] PTypeInfo }
  1101. inc(dimcount);
  1102. totalcount:=totalcount*curdef.elecount;
  1103. until (finaldef.typ<>arraydef) or
  1104. (ado_IsDynamicArray in tarraydef(finaldef).arrayoptions);
  1105. tcb.begin_anonymous_record(
  1106. internaltypeprefixName[itp_rtti_normal_array]+tostr(dimcount),
  1107. defaultpacking,reqalign,
  1108. targetinfos[target_info.system]^.alignment.recordalignmin,
  1109. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  1110. { total size = elecount * elesize of the first arraydef }
  1111. tcb.emit_tai(Tai_const.Create_sizeint(def.elecount*def.elesize),sizeuinttype);
  1112. { total element count }
  1113. tcb.emit_tai(Tai_const.Create_sizeint(asizeint(totalcount)),sizeuinttype);
  1114. { last dimension element type }
  1115. tcb.emit_tai(Tai_const.Create_sym(get_rtti_label(curdef.elementdef,rt,true)),voidpointertype);
  1116. { dimension count }
  1117. tcb.emit_ord_const(dimcount,u8inttype);
  1118. finaldef:=def;
  1119. { ranges of the dimensions }
  1120. for i:=1 to dimcount do
  1121. begin
  1122. curdef:=tarraydef(finaldef);
  1123. finaldef:=curdef.elementdef;
  1124. { Dims[i] PPTypeInfo }
  1125. write_rtti_reference(tcb,curdef.rangedef,rt);
  1126. end;
  1127. end
  1128. else
  1129. { write a delphi almost compatible dyn. array entry:
  1130. there are two types, eltype and eltype2, the latter is nil if the element type needs
  1131. no finalization, the former is always valid, delphi has this swapped, but for
  1132. compatibility with older fpc versions we do it different, to be delphi compatible,
  1133. the names are swapped in typinfo.pp
  1134. }
  1135. begin
  1136. tcb.begin_anonymous_record(
  1137. internaltypeprefixName[itp_rtti_dyn_array],
  1138. defaultpacking,reqalign,
  1139. targetinfos[target_info.system]^.alignment.recordalignmin,
  1140. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  1141. { size of elements }
  1142. tcb.emit_tai(Tai_const.Create_sizeint(def.elesize),sizeuinttype);
  1143. { element type }
  1144. write_rtti_reference(tcb,def.elementdef,rt);
  1145. { variant type }
  1146. tcb.emit_ord_const(tstoreddef(def.elementdef).getvardef,s32inttype);
  1147. { element type }
  1148. if def.elementdef.needs_inittable then
  1149. write_rtti_reference(tcb,def.elementdef,rt)
  1150. else
  1151. tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype);
  1152. { write unit name }
  1153. tcb.emit_shortstring_const(current_module.realmodulename^);
  1154. end;
  1155. tcb.end_anonymous_record;
  1156. end;
  1157. procedure classrefdef_rtti(def:tclassrefdef);
  1158. begin
  1159. write_header(tcb,def,tkClassRef);
  1160. tcb.begin_anonymous_record(
  1161. internaltypeprefixName[itp_rtti_ref],
  1162. defaultpacking,reqalign,
  1163. targetinfos[target_info.system]^.alignment.recordalignmin,
  1164. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  1165. write_rtti_reference(tcb,def.pointeddef,rt);
  1166. tcb.end_anonymous_record;
  1167. end;
  1168. procedure pointerdef_rtti(def:tpointerdef);
  1169. begin
  1170. write_header(tcb,def,tkPointer);
  1171. tcb.begin_anonymous_record(
  1172. internaltypeprefixName[itp_rtti_ref],
  1173. defaultpacking,reqalign,
  1174. targetinfos[target_info.system]^.alignment.recordalignmin,
  1175. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  1176. write_rtti_reference(tcb,def.pointeddef,rt);
  1177. tcb.end_anonymous_record;
  1178. end;
  1179. procedure recorddef_rtti(def:trecorddef);
  1180. procedure write_record_operators;
  1181. var
  1182. rttilab: Tasmsymbol;
  1183. rttidef: tdef;
  1184. tcb: ttai_typedconstbuilder;
  1185. mop: tmanagementoperator;
  1186. procdef: tprocdef;
  1187. begin
  1188. rttilab := current_asmdata.DefineAsmSymbol(
  1189. internaltypeprefixName[itp_init_record_operators]+def.rtti_mangledname(rt),
  1190. AB_GLOBAL,AT_DATA,def);
  1191. tcb:=ctai_typedconstbuilder.create([tcalo_make_dead_strippable]);
  1192. tcb.begin_anonymous_record(
  1193. rttilab.Name,
  1194. defaultpacking,reqalign,
  1195. targetinfos[target_info.system]^.alignment.recordalignmin,
  1196. targetinfos[target_info.system]^.alignment.maxCrecordalign
  1197. );
  1198. { use "succ" to omit first enum item "mop_none" }
  1199. for mop := succ(low(tmanagementoperator)) to high(tmanagementoperator) do
  1200. begin
  1201. if not (mop in trecordsymtable(def.symtable).managementoperators) then
  1202. tcb.emit_tai(Tai_const.Create_nil_codeptr,voidcodepointertype)
  1203. else
  1204. begin
  1205. procdef := search_management_operator(mop, def);
  1206. if procdef = nil then
  1207. internalerror(201603021)
  1208. else
  1209. tcb.emit_tai(Tai_const.Createname(procdef.mangledname,AT_FUNCTION,0),
  1210. cprocvardef.getreusableprocaddr(procdef));
  1211. end;
  1212. end;
  1213. rttidef := tcb.end_anonymous_record;
  1214. current_asmdata.AsmLists[al_rtti].concatList(
  1215. tcb.get_final_asmlist(rttilab,rttidef,sec_rodata,rttilab.name,
  1216. sizeof(PInt)));
  1217. tcb.free;
  1218. end;
  1219. begin
  1220. write_header(tcb,def,tkRecord);
  1221. { need extra reqalign record, because otherwise the u32 int will
  1222. only be aligned to 4 even on 64 bit target (while the rtti code
  1223. in typinfo expects alignments to sizeof(pointer)) }
  1224. tcb.begin_anonymous_record('',defaultpacking,reqalign,
  1225. targetinfos[target_info.system]^.alignment.recordalignmin,
  1226. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  1227. { store special terminator for init table for more optimal rtl operations
  1228. strictly related to RecordRTTI procedure in rtti.inc (directly
  1229. related to RTTIRecordRttiInfoToInitInfo function) }
  1230. if (rt=initrtti) then
  1231. tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype)
  1232. else
  1233. { we use a direct reference as the init RTTI is always in the same
  1234. unit as the full RTTI }
  1235. tcb.emit_tai(Tai_const.Create_sym(get_rtti_label(def,initrtti,false)),voidpointertype);
  1236. tcb.emit_ord_const(def.size,u32inttype);
  1237. { store rtti management operators only for init table }
  1238. if (rt=initrtti) then
  1239. begin
  1240. { for now records don't have the initializer table }
  1241. tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype);
  1242. if (trecordsymtable(def.symtable).managementoperators=[]) then
  1243. tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype)
  1244. else
  1245. tcb.emit_tai(Tai_const.Createname(
  1246. internaltypeprefixName[itp_init_record_operators]+def.rtti_mangledname(rt),
  1247. AT_DATA_FORCEINDIRECT,0),voidpointertype);
  1248. end;
  1249. fields_write_rtti_data(tcb,def,rt);
  1250. tcb.end_anonymous_record;
  1251. { write pointers to operators if needed }
  1252. if (rt=initrtti) and (trecordsymtable(def.symtable).managementoperators<>[]) then
  1253. write_record_operators;
  1254. end;
  1255. procedure procvardef_rtti(def:tprocvardef);
  1256. procedure write_para(parasym:tparavarsym);
  1257. begin
  1258. { write flags for current parameter }
  1259. write_param_flag(tcb,parasym);
  1260. { write name of current parameter }
  1261. tcb.emit_shortstring_const(parasym.realname);
  1262. { write name of type of current parameter }
  1263. write_rtti_name(tcb,parasym.vardef);
  1264. end;
  1265. procedure write_procedure_param(parasym:tparavarsym);
  1266. begin
  1267. { every parameter is expected to start aligned }
  1268. tcb.begin_anonymous_record(
  1269. internaltypeprefixName[itp_rtti_proc_param]+tostr(length(parasym.realname)),
  1270. defaultpacking,min(reqalign,SizeOf(PInt)),
  1271. targetinfos[target_info.system]^.alignment.recordalignmin,
  1272. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  1273. { write flags for current parameter }
  1274. write_param_flag(tcb,parasym);
  1275. { write param type }
  1276. if is_open_array(parasym.vardef) or is_array_of_const(parasym.vardef) then
  1277. write_rtti_reference(tcb,tarraydef(parasym.vardef).elementdef,fullrtti)
  1278. else if parasym.vardef=cformaltype then
  1279. write_rtti_reference(tcb,nil,fullrtti)
  1280. else
  1281. write_rtti_reference(tcb,parasym.vardef,fullrtti);
  1282. { write name of current parameter }
  1283. tcb.emit_shortstring_const(parasym.realname);
  1284. tcb.end_anonymous_record;
  1285. end;
  1286. var
  1287. methodkind : byte;
  1288. i : integer;
  1289. begin
  1290. if po_methodpointer in def.procoptions then
  1291. begin
  1292. { write method id and name }
  1293. write_header(tcb,def,tkMethod);
  1294. tcb.begin_anonymous_record('',defaultpacking,reqalign,
  1295. targetinfos[target_info.system]^.alignment.recordalignmin,
  1296. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  1297. { write kind of method }
  1298. methodkind:=write_methodkind(tcb,def);
  1299. { write parameter info. The parameters must be written in reverse order
  1300. if this method uses right to left parameter pushing! }
  1301. tcb.emit_ord_const(def.paras.count,u8inttype);
  1302. for i:=0 to def.paras.count-1 do
  1303. write_para(tparavarsym(def.paras[i]));
  1304. if (methodkind=mkFunction) or (methodkind=mkClassFunction) then
  1305. begin
  1306. { write name of result type }
  1307. write_rtti_name(tcb,def.returndef);
  1308. { enclosing record takes care of alignment }
  1309. { write result typeinfo }
  1310. write_rtti_reference(tcb,def.returndef,fullrtti);
  1311. end;
  1312. { write calling convention }
  1313. write_callconv(tcb,def);
  1314. { enclosing record takes care of alignment }
  1315. { write params typeinfo }
  1316. for i:=0 to def.paras.count-1 do
  1317. begin
  1318. if is_open_array(tparavarsym(def.paras[i]).vardef) or is_array_of_const(tparavarsym(def.paras[i]).vardef) then
  1319. write_rtti_reference(tcb,tarraydef(tparavarsym(def.paras[i]).vardef).elementdef,fullrtti)
  1320. else if tparavarsym(def.paras[i]).vardef=cformaltype then
  1321. write_rtti_reference(tcb,nil,fullrtti)
  1322. else
  1323. write_rtti_reference(tcb,tparavarsym(def.paras[i]).vardef,fullrtti);
  1324. end;
  1325. tcb.end_anonymous_record;
  1326. end
  1327. else
  1328. begin
  1329. write_header(tcb,def,tkProcvar);
  1330. tcb.begin_anonymous_record('',defaultpacking,reqalign,
  1331. targetinfos[target_info.system]^.alignment.recordalignmin,
  1332. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  1333. { flags }
  1334. tcb.emit_ord_const(0,u8inttype);
  1335. { write calling convention }
  1336. write_callconv(tcb,def);
  1337. { enclosing record takes care of alignment }
  1338. { write result typeinfo }
  1339. write_rtti_reference(tcb,def.returndef,fullrtti);
  1340. { write parameter count }
  1341. tcb.emit_ord_const(def.paras.count,u8inttype);
  1342. for i:=0 to def.paras.count-1 do
  1343. write_procedure_param(tparavarsym(def.paras[i]));
  1344. tcb.end_anonymous_record;
  1345. end;
  1346. end;
  1347. procedure objectdef_rtti(def: tobjectdef);
  1348. procedure objectdef_rtti_fields(def:tobjectdef);
  1349. begin
  1350. { - for compatiblity with record RTTI we need to write a terminator-
  1351. Nil pointer for initrtti as well for objects
  1352. - for RTTI consistency for objects we need point from fullrtti
  1353. to initrtti
  1354. - classes are assumed to have the same INIT RTTI as records
  1355. (see TObject.CleanupInstance)
  1356. - neither helper nor class type have fullrtti for fields
  1357. }
  1358. if (rt=initrtti) then
  1359. tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype)
  1360. else
  1361. if (def.objecttype=odt_object) then
  1362. tcb.emit_tai(Tai_const.Create_sym(get_rtti_label(def,initrtti,false)),voidpointertype)
  1363. else
  1364. internalerror(2017011801);
  1365. tcb.emit_ord_const(def.size, u32inttype);
  1366. { pointer to management operators available only for initrtti }
  1367. if (rt=initrtti) then
  1368. begin
  1369. { initializer table only available for classes currently }
  1370. if def.objecttype=odt_class then
  1371. write_mop_offset_table(tcb,def,mop_initialize)
  1372. else
  1373. tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype);
  1374. tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype);
  1375. end;
  1376. { enclosing record takes care of alignment }
  1377. fields_write_rtti_data(tcb,def,rt);
  1378. end;
  1379. procedure objectdef_rtti_interface_init(def:tobjectdef);
  1380. begin
  1381. tcb.emit_ord_const(def.size, u32inttype);
  1382. end;
  1383. procedure objectdef_rtti_class_full(def:tobjectdef);
  1384. var
  1385. propnamelist : TFPHashObjectList;
  1386. begin
  1387. { Collect unique property names with nameindex }
  1388. propnamelist:=TFPHashObjectList.Create;
  1389. collect_propnamelist(propnamelist,def);
  1390. if not is_objectpascal_helper(def) then
  1391. if (oo_has_vmt in def.objectoptions) then
  1392. tcb.emit_tai(
  1393. Tai_const.Createname(def.vmt_mangledname,AT_DATA_FORCEINDIRECT,0),
  1394. cpointerdef.getreusable(def.vmt_def))
  1395. else
  1396. tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype);
  1397. { write parent typeinfo }
  1398. write_rtti_reference(tcb,def.childof,fullrtti);
  1399. { write typeinfo of extended type }
  1400. if is_objectpascal_helper(def) then
  1401. if assigned(def.extendeddef) then
  1402. write_rtti_reference(tcb,def.extendeddef,fullrtti)
  1403. else
  1404. InternalError(2011033001);
  1405. { total number of unique properties }
  1406. tcb.emit_ord_const(propnamelist.count,u16inttype);
  1407. { reference to unitinfo with unit-name }
  1408. write_unit_info_reference(tcb);
  1409. { TAttributeData }
  1410. if rmo_hasattributes in current_module.rtti_options then
  1411. write_attribute_data(tcb, def.rtti_attribute_list);
  1412. { write published properties for this object }
  1413. published_properties_write_rtti_data(tcb,propnamelist,def.symtable);
  1414. propnamelist.free;
  1415. end;
  1416. procedure objectdef_rtti_interface_full(def:tobjectdef);
  1417. var
  1418. propnamelist : TFPHashObjectList;
  1419. { if changed to a set, make sure it's still a byte large, and
  1420. swap appropriately when cross-compiling
  1421. }
  1422. IntfFlags: byte;
  1423. begin
  1424. { Collect unique property names with nameindex }
  1425. propnamelist:=TFPHashObjectList.Create;
  1426. collect_propnamelist(propnamelist,def);
  1427. tcb.begin_anonymous_record('',defaultpacking,reqalign,
  1428. targetinfos[target_info.system]^.alignment.recordalignmin,
  1429. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  1430. { write parent typeinfo }
  1431. write_rtti_reference(tcb,def.childof,fullrtti);
  1432. { interface: write flags, iid and iidstr }
  1433. IntfFlags:=0;
  1434. if assigned(def.iidguid) then
  1435. IntfFlags:=IntfFlags or (1 shl ord(ifHasGuid));
  1436. if (def.objecttype=odt_interfacecorba) and (def.iidstr^<>'') then
  1437. IntfFlags:=IntfFlags or (1 shl ord(ifHasStrGUID));
  1438. if (def.objecttype=odt_dispinterface) then
  1439. IntfFlags:=IntfFlags or (1 shl ord(ifDispInterface));
  1440. if (target_info.endian=endian_big) then
  1441. IntfFlags:=reverse_byte(IntfFlags);
  1442. {
  1443. ifDispatch, }
  1444. tcb.emit_ord_const(IntfFlags,u8inttype);
  1445. { write GUID }
  1446. tcb.emit_guid_const(def.iidguid^);
  1447. { write unit name }
  1448. tcb.emit_shortstring_const(current_module.realmodulename^);
  1449. tcb.begin_anonymous_record('',defaultpacking,reqalign,
  1450. targetinfos[target_info.system]^.alignment.recordalignmin,
  1451. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  1452. { write iidstr }
  1453. if def.objecttype=odt_interfacecorba then
  1454. begin
  1455. { prepareguid always allocates an empty string }
  1456. if not assigned(def.iidstr) then
  1457. internalerror(2016021901);
  1458. tcb.emit_shortstring_const(def.iidstr^)
  1459. end;
  1460. { write published properties for this object }
  1461. published_properties_write_rtti_data(tcb,propnamelist,def.symtable);
  1462. { write published methods for this interface }
  1463. write_methods(tcb,def.symtable,[vis_published]);
  1464. tcb.end_anonymous_record;
  1465. tcb.end_anonymous_record;
  1466. propnamelist.free;
  1467. end;
  1468. begin
  1469. case def.objecttype of
  1470. odt_class:
  1471. tcb.emit_ord_const(tkclass,u8inttype);
  1472. odt_object:
  1473. tcb.emit_ord_const(tkobject,u8inttype);
  1474. odt_dispinterface,
  1475. odt_interfacecom:
  1476. tcb.emit_ord_const(tkInterface,u8inttype);
  1477. odt_interfacecorba:
  1478. tcb.emit_ord_const(tkinterfaceCorba,u8inttype);
  1479. odt_helper:
  1480. tcb.emit_ord_const(tkhelper,u8inttype);
  1481. else
  1482. internalerror(200611034);
  1483. end;
  1484. { generate the name }
  1485. tcb.emit_shortstring_const(def.objrealname^);
  1486. tcb.begin_anonymous_record('',defaultpacking,reqalign,
  1487. targetinfos[target_info.system]^.alignment.recordalignmin,
  1488. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  1489. case rt of
  1490. initrtti :
  1491. begin
  1492. if def.objecttype in [odt_class,odt_object,odt_helper] then
  1493. objectdef_rtti_fields(def)
  1494. else
  1495. objectdef_rtti_interface_init(def);
  1496. end;
  1497. fullrtti :
  1498. begin
  1499. case def.objecttype of
  1500. odt_helper,
  1501. odt_class:
  1502. objectdef_rtti_class_full(def);
  1503. odt_object:
  1504. objectdef_rtti_fields(def);
  1505. else
  1506. objectdef_rtti_interface_full(def);
  1507. end;
  1508. end;
  1509. else
  1510. ;
  1511. end;
  1512. tcb.end_anonymous_record;
  1513. end;
  1514. begin
  1515. case def.typ of
  1516. variantdef :
  1517. variantdef_rtti(tvariantdef(def));
  1518. stringdef :
  1519. stringdef_rtti(tstringdef(def));
  1520. enumdef :
  1521. enumdef_rtti(tenumdef(def));
  1522. orddef :
  1523. orddef_rtti(torddef(def));
  1524. floatdef :
  1525. floatdef_rtti(tfloatdef(def));
  1526. setdef :
  1527. setdef_rtti(tsetdef(def));
  1528. procvardef :
  1529. procvardef_rtti(tprocvardef(def));
  1530. arraydef :
  1531. begin
  1532. if ado_IsBitPacked in tarraydef(def).arrayoptions then
  1533. unknown_rtti(tstoreddef(def))
  1534. else
  1535. arraydef_rtti(tarraydef(def));
  1536. end;
  1537. recorddef :
  1538. begin
  1539. if trecorddef(def).is_packed then
  1540. unknown_rtti(tstoreddef(def))
  1541. else
  1542. recorddef_rtti(trecorddef(def));
  1543. end;
  1544. objectdef :
  1545. objectdef_rtti(tobjectdef(def));
  1546. classrefdef :
  1547. classrefdef_rtti(tclassrefdef(def));
  1548. pointerdef :
  1549. pointerdef_rtti(tpointerdef(def));
  1550. else
  1551. unknown_rtti(tstoreddef(def));
  1552. end;
  1553. end;
  1554. procedure TRTTIWriter.write_attribute_data(tcb:ttai_typedconstbuilder;attr_list:trtti_attribute_list);
  1555. var
  1556. count, i: word;
  1557. attr : trtti_attribute;
  1558. tbltcb : ttai_typedconstbuilder;
  1559. tbllab : tasmlabel;
  1560. tbldef : tdef;
  1561. begin
  1562. if assigned(attr_list) then
  1563. count:=attr_list.get_attribute_count
  1564. else
  1565. count:=0;
  1566. if count=0 then
  1567. begin
  1568. { write a Nil reference }
  1569. tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype);
  1570. exit;
  1571. end;
  1572. { first write the attribute list as a separate table }
  1573. current_asmdata.getglobaldatalabel(tbllab);
  1574. tbltcb:=ctai_typedconstbuilder.create([tcalo_is_lab,tcalo_make_dead_strippable,tcalo_apply_constalign]);
  1575. tbltcb.begin_anonymous_record('',defaultpacking,min(reqalign,SizeOf(PInt)),
  1576. targetinfos[target_info.system]^.alignment.recordalignmin,
  1577. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  1578. tbltcb.emit_ord_const(count,u16inttype);
  1579. for i:=0 to count-1 do
  1580. begin
  1581. tbltcb.begin_anonymous_record('',defaultpacking,min(reqalign,SizeOf(PInt)),
  1582. targetinfos[target_info.system]^.alignment.recordalignmin,
  1583. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  1584. attr:=trtti_attribute(attr_list.rtti_attributes[i]);
  1585. tbltcb.emit_tai(tai_const.Createname(attr.symbolname,AT_DATA_FORCEINDIRECT,0),cpointerdef.getreusable(ttypesym(attr.typesym).typedef));
  1586. tbltcb.end_anonymous_record;
  1587. end;
  1588. tbldef:=tbltcb.end_anonymous_record;
  1589. current_asmdata.asmlists[al_rtti].concatlist(
  1590. tbltcb.get_final_asmlist(tbllab,tbldef,sec_rodata,tbllab.name,const_align(sizeof(pint)))
  1591. );
  1592. tbltcb.free;
  1593. { write the reference to the attribute table }
  1594. tcb.emit_tai(Tai_const.Create_sym(tbllab),voidpointertype);
  1595. end;
  1596. procedure TRTTIWriter.write_unit_info_reference(tcb: ttai_typedconstbuilder);
  1597. begin
  1598. tcb.emit_tai(Tai_const.Create_sym(current_module.rttiunitinfo), current_module.rttiunitinfodef);
  1599. end;
  1600. function enumsym_compare_name(item1, item2: pointer): Integer;
  1601. var
  1602. enum1: tenumsym absolute item1;
  1603. enum2: tenumsym absolute item2;
  1604. begin
  1605. if enum1=enum2 then
  1606. result:=0
  1607. else if enum1.name>enum2.name then
  1608. result:=1
  1609. else
  1610. { there can't be equal names, identifiers are unique }
  1611. result:=-1;
  1612. end;
  1613. function enumsym_compare_value(item1, item2: pointer): Integer;
  1614. var
  1615. enum1: tenumsym absolute item1;
  1616. enum2: tenumsym absolute item2;
  1617. begin
  1618. if enum1.value>enum2.value then
  1619. result:=1
  1620. else if enum1.value<enum2.value then
  1621. result:=-1
  1622. else
  1623. result:=0;
  1624. end;
  1625. procedure TRTTIWriter.write_rtti_extrasyms(def:Tdef;rt:Trttitype;mainrtti:Tasmsymbol);
  1626. type Penumsym = ^Tenumsym;
  1627. { Writes a helper table for accelerated conversion of ordinal enum values to strings.
  1628. If you change something in this method, make sure to adapt the corresponding code
  1629. in sstrings.inc. }
  1630. procedure enumdef_rtti_ord2stringindex(rttidef: trecorddef; const syms: tfplist);
  1631. var rttilab:Tasmsymbol;
  1632. h,i,o,prev_value:longint;
  1633. mode:(lookup,search); {Modify with care, ordinal value of enum is written.}
  1634. r:single; {Must be real type because of integer overflow risk.}
  1635. tcb: ttai_typedconstbuilder;
  1636. sym_count: integer;
  1637. tabledef: tdef;
  1638. begin
  1639. {Decide wether a lookup array is size efficient.}
  1640. mode:=lookup;
  1641. sym_count:=syms.count;
  1642. if sym_count>0 then
  1643. begin
  1644. i:=1;
  1645. r:=0;
  1646. h:=tenumsym(syms[0]).value; {Next expected enum value is min.}
  1647. { set prev_value for the first iteration to a value that is
  1648. different from the first one without risking overflow (it's used
  1649. to detect whether two enum values are the same) }
  1650. if h=0 then
  1651. prev_value:=1
  1652. else
  1653. prev_value:=0;
  1654. while i<sym_count do
  1655. begin
  1656. { if two enum values are the same, we have to create a table }
  1657. if (prev_value=h) then
  1658. begin
  1659. mode:=search;
  1660. break;
  1661. end;
  1662. {Calculate size of hole between values. Avoid integer overflows.}
  1663. r:=r+(single(tenumsym(syms[i]).value)-single(h))-1;
  1664. prev_value:=h;
  1665. h:=tenumsym(syms[i]).value;
  1666. inc(i);
  1667. end;
  1668. if r>sym_count then
  1669. mode:=search; {Don't waste more than 50% space.}
  1670. end;
  1671. { write rtti data; make sure that the alignment matches the corresponding data structure
  1672. in the code that uses it (if alignment is required). }
  1673. tcb:=ctai_typedconstbuilder.create([tcalo_make_dead_strippable,tcalo_data_force_indirect]);
  1674. { use TConstPtrUInt packrecords to ensure good alignment }
  1675. tcb.begin_anonymous_record('',defaultpacking,reqalign,
  1676. targetinfos[target_info.system]^.alignment.recordalignmin,
  1677. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  1678. { now emit the data: first the mode }
  1679. tcb.emit_tai(Tai_const.create_32bit(longint(mode)),u32inttype);
  1680. { align }
  1681. tcb.begin_anonymous_record('',defaultpacking,min(reqalign,sizeof(PInt)),
  1682. targetinfos[target_info.system]^.alignment.recordalignmin,
  1683. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  1684. if mode=lookup then
  1685. begin
  1686. o:=tenumsym(syms[0]).value; {Start with min value.}
  1687. for i:=0 to sym_count-1 do
  1688. begin
  1689. while o<tenumsym(syms[i]).value do
  1690. begin
  1691. tcb.emit_tai(Tai_const.create_nil_dataptr,ptruinttype);
  1692. inc(o);
  1693. end;
  1694. inc(o);
  1695. tcb.queue_init(voidpointertype);
  1696. tcb.queue_subscriptn_multiple_by_name(rttidef,
  1697. ['size_start_rec',
  1698. 'min_max_rec',
  1699. 'basetype_array_rec',
  1700. tsym(syms[i]).Name]
  1701. );
  1702. tcb.queue_emit_asmsym(mainrtti,rttidef);
  1703. end;
  1704. end
  1705. else
  1706. begin
  1707. tcb.emit_ord_const(sym_count,u32inttype);
  1708. tcb.begin_anonymous_record('',defaultpacking,min(reqalign,sizeof(PInt)),
  1709. targetinfos[target_info.system]^.alignment.recordalignmin,
  1710. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  1711. for i:=0 to sym_count-1 do
  1712. begin
  1713. tcb.emit_ord_const(tenumsym(syms[i]).value,s32inttype);
  1714. tcb.queue_init(voidpointertype);
  1715. tcb.queue_subscriptn_multiple_by_name(rttidef,
  1716. ['size_start_rec',
  1717. 'min_max_rec',
  1718. 'basetype_array_rec',
  1719. tsym(syms[i]).Name]
  1720. );
  1721. tcb.queue_emit_asmsym(mainrtti,rttidef);
  1722. end;
  1723. tcb.end_anonymous_record;
  1724. end;
  1725. tcb.end_anonymous_record;
  1726. tabledef:=tcb.end_anonymous_record;
  1727. rttilab:=current_asmdata.DefineAsmSymbol(Tstoreddef(def).rtti_mangledname(rt)+'_o2s',AB_GLOBAL,AT_DATA_NOINDIRECT,tabledef);
  1728. current_asmdata.asmlists[al_rtti].concatlist(tcb.get_final_asmlist(
  1729. rttilab,tabledef,sec_rodata,
  1730. rttilab.name,sizeof(PInt)));
  1731. tcb.free;
  1732. current_module.add_public_asmsym(rttilab);
  1733. end;
  1734. { Writes a helper table for accelerated conversion of string to ordinal enum values.
  1735. If you change something in this method, make sure to adapt the corresponding code
  1736. in sstrings.inc. }
  1737. procedure enumdef_rtti_string2ordindex(rttidef: trecorddef; const syms: tfplist);
  1738. var
  1739. tcb: ttai_typedconstbuilder;
  1740. rttilab: Tasmsymbol;
  1741. i:longint;
  1742. tabledef: tdef;
  1743. begin
  1744. { write rtti data }
  1745. tcb:=ctai_typedconstbuilder.create([tcalo_make_dead_strippable,tcalo_data_force_indirect]);
  1746. { begin of Tstring_to_ord }
  1747. tcb.begin_anonymous_record('',defaultpacking,min(reqalign,sizeof(PInt)),
  1748. targetinfos[target_info.system]^.alignment.recordalignmin,
  1749. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  1750. tcb.emit_ord_const(syms.count,s32inttype);
  1751. { begin of "data" array in Tstring_to_ord }
  1752. tcb.begin_anonymous_record('',defaultpacking,min(reqalign,sizeof(PInt)),
  1753. targetinfos[target_info.system]^.alignment.recordalignmin,
  1754. targetinfos[target_info.system]^.alignment.maxCrecordalign);
  1755. for i:=0 to syms.count-1 do
  1756. begin
  1757. tcb.emit_ord_const(tenumsym(syms[i]).value,s32inttype);
  1758. { alignment of pointer value handled by enclosing record already }
  1759. tcb.queue_init(voidpointertype);
  1760. tcb.queue_subscriptn_multiple_by_name(rttidef,
  1761. ['size_start_rec',
  1762. 'min_max_rec',
  1763. 'basetype_array_rec',
  1764. tsym(syms[i]).Name]
  1765. );
  1766. tcb.queue_emit_asmsym(mainrtti,rttidef);
  1767. end;
  1768. tcb.end_anonymous_record;
  1769. tabledef:=tcb.end_anonymous_record;
  1770. rttilab:=current_asmdata.DefineAsmSymbol(Tstoreddef(def).rtti_mangledname(rt)+'_s2o',AB_GLOBAL,AT_DATA_NOINDIRECT,tabledef);
  1771. current_asmdata.asmlists[al_rtti].concatlist(tcb.get_final_asmlist(
  1772. rttilab,tabledef,sec_rodata,
  1773. rttilab.name,sizeof(PInt)));
  1774. tcb.free;
  1775. current_module.add_public_asmsym(rttilab);
  1776. end;
  1777. procedure enumdef_rtti_extrasyms(def:Tenumdef);
  1778. var
  1779. t:Tenumsym;
  1780. syms:tfplist;
  1781. i:longint;
  1782. rttitypesym: ttypesym;
  1783. rttidef: trecorddef;
  1784. begin
  1785. { collect enumsyms belonging to this enum type (could be a subsection
  1786. in case of a subrange type) }
  1787. syms:=tfplist.create;
  1788. for i := 0 to def.symtable.SymList.Count - 1 do
  1789. begin
  1790. t:=tenumsym(def.symtable.SymList[i]);
  1791. if t.value<def.minval then
  1792. continue
  1793. else
  1794. if t.value>def.maxval then
  1795. break;
  1796. syms.add(t);
  1797. end;
  1798. { sort the syms by enum name }
  1799. syms.sort(@enumsym_compare_name);
  1800. rttitypesym:=try_search_current_module_type(internaltypeprefixName[itp_rttidef]+def.rtti_mangledname(fullrtti));
  1801. if not assigned(rttitypesym) or
  1802. (ttypesym(rttitypesym).typedef.typ<>recorddef) then
  1803. internalerror(2015071402);
  1804. rttidef:=trecorddef(ttypesym(rttitypesym).typedef);
  1805. enumdef_rtti_string2ordindex(rttidef,syms);
  1806. { sort the syms by enum value }
  1807. syms.sort(@enumsym_compare_value);
  1808. enumdef_rtti_ord2stringindex(rttidef,syms);
  1809. syms.free;
  1810. end;
  1811. begin
  1812. case def.typ of
  1813. enumdef:
  1814. if rt=fullrtti then
  1815. begin
  1816. enumdef_rtti_extrasyms(Tenumdef(def));
  1817. end;
  1818. else
  1819. ;
  1820. end;
  1821. end;
  1822. procedure TRTTIWriter.write_child_rtti_data(def:tdef;rt:trttitype);
  1823. begin
  1824. case def.typ of
  1825. enumdef :
  1826. if assigned(tenumdef(def).basedef) then
  1827. write_rtti(tenumdef(def).basedef,rt);
  1828. setdef :
  1829. write_rtti(tsetdef(def).elementdef,rt);
  1830. arraydef :
  1831. begin
  1832. write_rtti(tarraydef(def).rangedef,rt);
  1833. write_rtti(tarraydef(def).elementdef,rt);
  1834. end;
  1835. recorddef :
  1836. begin
  1837. { guarantee initrtti for any record for RTTI purposes
  1838. also for fpc_initialize, fpc_finalize }
  1839. if (rt=fullrtti) then
  1840. begin
  1841. include(def.defstates,ds_init_table_used);
  1842. write_rtti(def, initrtti);
  1843. end;
  1844. fields_write_rtti(trecorddef(def).symtable,rt);
  1845. end;
  1846. objectdef :
  1847. begin
  1848. if assigned(tobjectdef(def).childof) then
  1849. write_rtti(tobjectdef(def).childof,rt);
  1850. if (rt=initrtti) or (tobjectdef(def).objecttype=odt_object) then
  1851. fields_write_rtti(tobjectdef(def).symtable,rt)
  1852. else
  1853. published_write_rtti(tobjectdef(def).symtable,rt);
  1854. if (rt=fullrtti) then
  1855. begin
  1856. { guarantee initrtti for any object for RTTI purposes
  1857. also for fpc_initialize, fpc_finalize }
  1858. if (tobjectdef(def).objecttype=odt_object) then
  1859. begin
  1860. include(def.defstates,ds_init_table_used);
  1861. write_rtti(def,initrtti);
  1862. end;
  1863. if (is_interface(def) or is_dispinterface(def))
  1864. and (oo_can_have_published in tobjectdef(def).objectoptions) then
  1865. methods_write_rtti(tobjectdef(def).symtable,rt,[vis_published],true);
  1866. end;
  1867. end;
  1868. classrefdef,
  1869. pointerdef:
  1870. if not is_objc_class_or_protocol(tabstractpointerdef(def).pointeddef) then
  1871. write_rtti(tabstractpointerdef(def).pointeddef,rt);
  1872. procvardef:
  1873. params_write_rtti(tabstractprocdef(def),rt,false);
  1874. else
  1875. ;
  1876. end;
  1877. end;
  1878. procedure TRTTIWriter.write_rtti_reference(tcb: ttai_typedconstbuilder; def: tdef; rt: trttitype);
  1879. begin
  1880. { we don't care about the real type here, because
  1881. a) we don't index into these elements
  1882. b) we may not have the rtti type available at the point that we
  1883. are emitting this data, because of forward definitions etc
  1884. c) if the rtti is emitted in another unit, we won't have the type
  1885. available at all
  1886. For the cases where the type is emitted in the current unit and hence
  1887. the underlying system will detect and complain about symbol def
  1888. mismatches, type conversions will have to be inserted afterwards (like
  1889. in llvm/llvmtype)
  1890. }
  1891. if not assigned(def) or is_void(def) or ((rt<>initrtti) and is_objc_class_or_protocol(def)) then
  1892. tcb.emit_tai(Tai_const.Create_nil_dataptr,voidpointertype)
  1893. else
  1894. tcb.emit_tai(Tai_const.Create_sym(get_rtti_label(def,rt,true)),voidpointertype);
  1895. end;
  1896. function TRTTIWriter.ref_rtti(def:tdef;rt:trttitype;indirect:boolean;suffix:tsymstr):tasmsymbol;
  1897. var
  1898. s : tsymstr;
  1899. begin
  1900. s:=def.rtti_mangledname(rt)+suffix;
  1901. result:=current_asmdata.RefAsmSymbol(s,AT_DATA,indirect);
  1902. if def.owner.moduleid<>current_module.moduleid then
  1903. current_module.add_extern_asmsym(s,AB_EXTERNAL,AT_DATA);
  1904. end;
  1905. procedure TRTTIWriter.write_rtti(def:tdef;rt:trttitype);
  1906. var
  1907. tcb: ttai_typedconstbuilder;
  1908. rttilab: tasmsymbol;
  1909. rttidef: tdef;
  1910. begin
  1911. { only write rtti of definitions from the current module }
  1912. if not findunitsymtable(def.owner).iscurrentunit then
  1913. exit;
  1914. { check if separate initrtti is actually needed }
  1915. if (rt=initrtti) and (not def.needs_separate_initrtti) then
  1916. rt:=fullrtti;
  1917. { prevent recursion }
  1918. if rttidefstate[rt] in def.defstates then
  1919. exit;
  1920. include(def.defstates,rttidefstate[rt]);
  1921. { write first all dependencies }
  1922. write_child_rtti_data(def,rt);
  1923. { write rtti data }
  1924. tcb:=ctai_typedconstbuilder.create([tcalo_make_dead_strippable,tcalo_data_force_indirect]);
  1925. tcb.begin_anonymous_record(
  1926. internaltypeprefixName[itp_rttidef]+tstoreddef(def).rtti_mangledname(rt),
  1927. defaultpacking,reqalign,
  1928. targetinfos[target_info.system]^.alignment.recordalignmin,
  1929. targetinfos[target_info.system]^.alignment.maxCrecordalign
  1930. );
  1931. write_rtti_data(tcb,def,rt);
  1932. rttidef:=tcb.end_anonymous_record;
  1933. rttilab:=current_asmdata.DefineAsmSymbol(tstoreddef(def).rtti_mangledname(rt),AB_GLOBAL,AT_DATA_NOINDIRECT,rttidef);
  1934. current_asmdata.AsmLists[al_rtti].concatList(
  1935. tcb.get_final_asmlist(rttilab,rttidef,sec_rodata,rttilab.name,min(target_info.alignment.maxCrecordalign,SizeOf(QWord))));
  1936. tcb.free;
  1937. current_module.add_public_asmsym(rttilab);
  1938. { write additional data }
  1939. write_rtti_extrasyms(def,rt,rttilab);
  1940. end;
  1941. constructor TRTTIWriter.create;
  1942. begin
  1943. if tf_requires_proper_alignment in target_info.flags then
  1944. begin
  1945. reqalign:=min(sizeof(QWord),target_info.alignment.maxCrecordalign);
  1946. defaultpacking:=C_alignment;
  1947. end
  1948. else
  1949. begin
  1950. reqalign:=1;
  1951. defaultpacking:=1;
  1952. end;
  1953. end;
  1954. procedure TRTTIWriter.start_write_unit_info;
  1955. var
  1956. s : string;
  1957. tcb: ttai_typedconstbuilder;
  1958. begin
  1959. tcb:=ctai_typedconstbuilder.create([tcalo_make_dead_strippable,tcalo_new_section]);
  1960. tcb.begin_anonymous_record(make_mangledname('RTTIU',current_module.localsymtable,''), 1, sizeof(pint), 1, 1);
  1961. { write the TRTTIUnitOptions }
  1962. tcb.emit_ord_const(byte(longint(current_module.rtti_options)),u8inttype);
  1963. { Write the unit-name }
  1964. s := current_module.realmodulename^;
  1965. tcb.emit_shortstring_const(current_module.realmodulename^);
  1966. current_module.rttiunitinfodef := tcb.end_anonymous_record;
  1967. current_module.rttiunitinfo := current_asmdata.DefineAsmSymbol(make_mangledname('RTTIU_',current_module.localsymtable,''),AB_GLOBAL,AT_DATA, current_module.rttiunitinfodef);
  1968. current_asmdata.AsmLists[al_rtti].concatList(
  1969. tcb.get_final_asmlist(current_module.rttiunitinfo,current_module.rttiunitinfodef,sec_rodata,current_module.rttiunitinfo.name,const_align(sizeof(pint))));
  1970. tcb.free;
  1971. end;
  1972. procedure TRTTIWriter.after_write_unit_info(st: TSymtable);
  1973. begin
  1974. if current_module.rttiunitinfo<>nil then
  1975. begin
  1976. { Write a trailing 255 to mark the end of the symbols-list }
  1977. current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
  1978. current_asmdata.asmlists[al_rtti].concat(Tai_const.Create_8bit(255));
  1979. end;
  1980. end;
  1981. end.