objcgutl.pas 58 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629
  1. {
  2. Copyright (c) 2009 by Jonas Maebe
  3. This unit implements some Objective-C helper routines at the code generator
  4. level.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License,or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. {$i fpcdefs.inc}
  19. unit objcgutl;
  20. interface
  21. uses
  22. cclasses,
  23. aasmbase,aasmdata,
  24. symbase,symdef;
  25. procedure objcfinishstringrefpoolentry(entry: phashsetitem; stringpool: tconstpooltype; refsec, stringsec: tasmsectiontype);
  26. procedure objcfinishclassrefnfpoolentry(entry: phashsetitem; classdef: tobjectdef);
  27. procedure MaybeGenerateObjectiveCImageInfo(globalst, localst: tsymtable);
  28. implementation
  29. uses
  30. globtype,globals,fmodule,
  31. systems,
  32. aasmtai,
  33. cgbase,
  34. objcdef,objcutil,
  35. symconst,symtype,symsym,symtable,
  36. verbose;
  37. type
  38. tobjcabi = (oa_fragile, oa_nonfragile);
  39. (* tivarlayouttype = (il_weak,il_strong); *)
  40. tobjcrttiwriter = class
  41. protected
  42. fabi: tobjcabi;
  43. classdefs,
  44. catdefs: tfpobjectlist;
  45. classsyms,
  46. catsyms: tfpobjectlist;
  47. procedure gen_objc_methods(list: tasmlist; objccls: tobjectdef; out methodslabel: tasmlabel; classmethods, iscategory: Boolean);
  48. procedure gen_objc_protocol_elements(list: tasmlist; protocol: tobjectdef; out reqinstsym, optinstsym, reqclssym, optclssym: TAsmLabel);
  49. procedure gen_objc_protocol_list(list:TAsmList; protolist: TFPObjectList; out protolistsym: TAsmLabel);
  50. procedure gen_objc_cat_methods(list:TAsmList; items: TFPObjectList; section: tasmsectiontype;const sectname: string; out listsym: TAsmLabel);
  51. procedure gen_objc_protocol(list:TAsmList; protocol: tobjectdef; out protocollabel: TAsmSymbol);virtual;abstract;
  52. procedure gen_objc_category_sections(list:TAsmList; objccat: tobjectdef; out catlabel: TAsmSymbol);virtual;abstract;
  53. procedure gen_objc_classes_sections(list:TAsmList; objclss: tobjectdef; out classlabel: TAsmSymbol);virtual;abstract;
  54. procedure gen_objc_info_sections(list: tasmlist);virtual;abstract;
  55. public
  56. constructor create(_abi: tobjcabi);
  57. destructor destroy;override;
  58. procedure gen_objc_rtti_sections(list:TAsmList; st:TSymtable);
  59. property abi: tobjcabi read fabi;
  60. end;
  61. { Used by by PowerPC/32 and i386 }
  62. tobjcrttiwriter_fragile = class(tobjcrttiwriter)
  63. protected
  64. function gen_objc_protocol_ext(list: TAsmList; optinstsym, optclssym: TAsmLabel): TAsmLabel;
  65. procedure gen_objc_ivars(list: TAsmList; objccls: tobjectdef; out ivarslabel: TAsmLabel);
  66. procedure gen_objc_protocol(list:TAsmList; protocol: tobjectdef; out protocollabel: TAsmSymbol);override;
  67. procedure gen_objc_category_sections(list:TAsmList; objccat: tobjectdef; out catlabel: TAsmSymbol);override;
  68. procedure gen_objc_classes_sections(list:TAsmList; objclss: tobjectdef; out classlabel: TAsmSymbol);override;
  69. procedure gen_objc_info_sections(list: tasmlist);override;
  70. public
  71. constructor create;
  72. end;
  73. { Used by PowerPC/64, ARM, and x86_64 }
  74. tobjcrttiwriter_nonfragile = class(tobjcrttiwriter)
  75. protected
  76. ObjCEmptyCacheVar,
  77. ObjCEmptyVtableVar: TAsmSymbol;
  78. procedure gen_objc_class_ro_part(list: TAsmList; objclss: tobjectdef; protolistsym: TAsmSymbol; out classrolabel: TAsmSymbol; metaclass: boolean);
  79. procedure addclasslist(list: tasmlist; section: tasmsectiontype; const symname: string; classes: tfpobjectlist);
  80. procedure gen_objc_ivars(list: TAsmList; objccls: tobjectdef; out ivarslabel: TAsmLabel);
  81. procedure gen_objc_protocol(list:TAsmList; protocol: tobjectdef; out protocollabel: TAsmSymbol);override;
  82. procedure gen_objc_category_sections(list:TAsmList; objccat: tobjectdef; out catlabel: TAsmSymbol);override;
  83. procedure gen_objc_classes_sections(list:TAsmList; objclss: tobjectdef; out classlabel: TAsmSymbol);override;
  84. procedure gen_objc_info_sections(list: tasmlist);override;
  85. public
  86. constructor create;
  87. end;
  88. {******************************************************************
  89. Protocol declaration helpers
  90. *******************************************************************}
  91. function objcfindprotocolentry(const p: shortstring): TAsmSymbol;
  92. var
  93. item : PHashSetItem;
  94. begin
  95. result:=nil;
  96. if not assigned(current_asmdata.ConstPools[sp_objcprotocolrefs]) then
  97. exit;
  98. item:=current_asmdata.constpools[sp_objcprotocolrefs].Find(@p[1], length(p));
  99. if not assigned(item) then
  100. exit;
  101. result:=TAsmSymbol(item^.Data);
  102. end;
  103. function objcaddprotocolentry(const p: shortstring; ref: TAsmSymbol): Boolean;
  104. var
  105. item : PHashSetItem;
  106. begin
  107. if current_asmdata.ConstPools[sp_objcprotocolrefs]=nil then
  108. current_asmdata.ConstPools[sp_objcprotocolrefs]:=THashSet.Create(64, True, False);
  109. item:=current_asmdata.constpools[sp_objcprotocolrefs].FindOrAdd(@p[1], length(p));
  110. Result:=(item^.Data=nil);
  111. if Result then
  112. item^.Data:=ref;
  113. end;
  114. {******************************************************************
  115. Pool section helpers
  116. *******************************************************************}
  117. function objcreatestringpoolentryintern(p: pchar; len: longint; pooltype: tconstpooltype; stringsec: tasmsectiontype): TAsmSymbol;
  118. var
  119. entry : PHashSetItem;
  120. strlab : tasmlabel;
  121. pc : pchar;
  122. pool : THashSet;
  123. begin
  124. if current_asmdata.ConstPools[pooltype]=nil then
  125. current_asmdata.ConstPools[pooltype]:=THashSet.Create(64, True, False);
  126. pool := current_asmdata.constpools[pooltype];
  127. entry:=pool.FindOrAdd(p,len);
  128. if not assigned(entry^.data) then
  129. begin
  130. { create new entry }
  131. current_asmdata.getlabel(strlab,alt_data);
  132. entry^.Data:=strlab;
  133. getmem(pc,entry^.keylength+1);
  134. move(entry^.key^,pc^,entry^.keylength);
  135. pc[entry^.keylength]:=#0;
  136. { add the string to the approriate section }
  137. new_section(current_asmdata.asmlists[al_objc_pools],stringsec,strlab.name,0);
  138. current_asmdata.asmlists[al_objc_pools].concat(Tai_label.Create(strlab));
  139. current_asmdata.asmlists[al_objc_pools].concat(Tai_string.Create_pchar(pc,entry^.keylength+1));
  140. Result := strlab;
  141. end
  142. else
  143. Result := TAsmLabel(Entry^.Data);
  144. end;
  145. procedure objcfinishstringrefpoolentry(entry: phashsetitem; stringpool: tconstpooltype; refsec, stringsec: tasmsectiontype);
  146. var
  147. reflab : tasmlabel;
  148. strlab : tasmsymbol;
  149. classname: string;
  150. begin
  151. { have we already generated a reference for this string entry? }
  152. if not assigned(entry^.Data) then
  153. begin
  154. { no, add the string to the associated strings section }
  155. strlab:=objcreatestringpoolentryintern(pchar(entry^.key),entry^.keylength,stringpool,stringsec);
  156. { and now finish the reference }
  157. current_asmdata.getlabel(reflab,alt_data);
  158. entry^.Data:=reflab;
  159. { add a pointer to the string in the string references section }
  160. new_section(current_asmdata.asmlists[al_objc_pools],refsec,reflab.name,sizeof(pint));
  161. current_asmdata.asmlists[al_objc_pools].concat(Tai_label.Create(reflab));
  162. current_asmdata.asmlists[al_objc_pools].concat(Tai_const.Create_sym(strlab));
  163. { in case of a class reference, also add a lazy symbol reference for
  164. the class (the linker requires this for the fragile ABI). }
  165. if (refsec=sec_objc_cls_refs) and
  166. not(target_info.system in systems_objc_nfabi) then
  167. begin
  168. setlength(classname,entry^.keylength);
  169. move(entry^.key^,classname[1],entry^.keylength);
  170. current_asmdata.asmlists[al_objc_pools].concat(tai_directive.Create(asd_lazy_reference,'.objc_class_name_'+classname));
  171. end;
  172. end;
  173. end;
  174. function objcreatestringpoolentry(const s: string; pooltype: tconstpooltype; stringsec: tasmsectiontype): TAsmSymbol;
  175. begin
  176. result:=objcreatestringpoolentryintern(@s[1],length(s),pooltype,stringsec);
  177. end;
  178. procedure objcfinishclassrefnfpoolentry(entry: phashsetitem; classdef: tobjectdef);
  179. var
  180. reflab: TAsmLabel;
  181. classym: TasmSymbol;
  182. begin
  183. { have we already generated a reference for this class ref entry? }
  184. if not assigned(entry^.Data) then
  185. begin
  186. { no, add the classref to the sec_objc_cls_refs section }
  187. current_asmdata.getlabel(reflab,alt_data);
  188. entry^.Data:=reflab;
  189. { add a pointer to the class }
  190. new_section(current_asmdata.asmlists[al_objc_pools],sec_objc_cls_refs,reflab.name,sizeof(pint));
  191. current_asmdata.asmlists[al_objc_pools].concat(Tai_label.Create(reflab));
  192. classym:=current_asmdata.RefAsmSymbol(classdef.rtti_mangledname(objcclassrtti));
  193. current_asmdata.asmlists[al_objc_pools].concat(Tai_const.Create_sym(classym));
  194. end;
  195. end;
  196. {******************************************************************
  197. RTTI generation -- Helpers
  198. *******************************************************************}
  199. procedure ConcatSymOrNil(list: tasmlist; sym: TAsmSymbol); inline;
  200. begin
  201. if Assigned(sym) then
  202. list.Concat(tai_const.Create_sym(sym))
  203. else
  204. list.Concat(tai_const.Create_pint(0));
  205. end;
  206. {******************************************************************
  207. RTTI generation -- Common
  208. *******************************************************************}
  209. { generate a method list, either of class methods or of instance methods,
  210. and both for obj-c classes and categories. }
  211. procedure tobjcrttiwriter.gen_objc_methods(list: tasmlist; objccls: tobjectdef; out methodslabel: tasmlabel; classmethods, iscategory: Boolean);
  212. const
  213. clsSectType : array [Boolean] of tasmsectiontype = (sec_objc_inst_meth, sec_objc_cls_meth);
  214. clsSectName : array [Boolean] of string = ('_OBJC_INST_METH','_OBJC_CLS_METH');
  215. catSectType : array [Boolean] of tasmsectiontype = (sec_objc_cat_inst_meth, sec_objc_cat_cls_meth);
  216. catSectName : array [Boolean] of string = ('_OBJC_CAT_INST_METH','_OBJC_CAT_CLS_METH');
  217. type
  218. method_data = record
  219. def : tprocdef;
  220. selsym : TAsmSymbol;
  221. encsym : TAsmSymbol;
  222. end;
  223. var
  224. i : Integer;
  225. def : tprocdef;
  226. defs : array of method_data;
  227. mcnt : integer;
  228. sym : tasmsymbol;
  229. mtype : tdef;
  230. begin
  231. methodslabel:=nil;
  232. mcnt:=0;
  233. { collect all instance/class methods }
  234. SetLength(defs,objccls.vmtentries.count);
  235. for i:=0 to objccls.vmtentries.count-1 do
  236. begin
  237. def:=pvmtentry(objccls.vmtentries[i])^.procdef;
  238. if (def.owner.defowner=objccls) and
  239. (classmethods = (po_classmethod in def.procoptions)) then
  240. begin
  241. defs[mcnt].def:=def;
  242. defs[mcnt].selsym:=objcreatestringpoolentry(def.messageinf.str^,sp_objcvarnames,sec_objc_meth_var_names);
  243. defs[mcnt].encsym:=objcreatestringpoolentry(objcencodemethod(def),sp_objcvartypes,sec_objc_meth_var_types);
  244. inc(mcnt);
  245. end;
  246. end;
  247. if mcnt=0 then
  248. exit;
  249. if iscategory then
  250. new_section(list,catSectType[classmethods],catSectName[classmethods],sizeof(ptrint))
  251. else
  252. new_section(list,clsSectType[classmethods],clsSectName[classmethods],sizeof(ptrint));
  253. current_asmdata.getlabel(methodslabel,alt_data);
  254. list.Concat(tai_label.Create(methodslabel));
  255. if (abi=oa_fragile) then
  256. { not used, always zero }
  257. list.Concat(tai_const.Create_32bit(0))
  258. else
  259. begin
  260. { size of each entry -- always 32 bit value }
  261. mtype:=search_named_unit_globaltype('OBJC','OBJC_METHOD',true).typedef;
  262. list.Concat(tai_const.Create_32bit(mtype.size));
  263. end;
  264. { number of objc_method entries in the method_list array -- always 32 bit}
  265. list.Concat(tai_const.Create_32bit(mcnt));
  266. for i:=0 to mcnt-1 do
  267. begin
  268. { reference to the selector name }
  269. list.Concat(tai_const.Create_sym(defs[i].selsym));
  270. { reference to the obj-c encoded function parameters (signature) }
  271. list.Concat(tai_const.Create_sym(defs[i].encsym));
  272. { mangled name of the method }
  273. sym:=current_asmdata.GetAsmSymbol(defs[i].def.mangledname);
  274. if not assigned(sym) then
  275. internalerror(2009091601);
  276. list.Concat(tai_const.Create_sym(sym));
  277. end;
  278. end;
  279. { generate method (and in the future also property) info for protocols }
  280. procedure tobjcrttiwriter.gen_objc_protocol_elements(list: tasmlist; protocol: tobjectdef; out reqinstsym, optinstsym, reqclssym, optclssym: TAsmLabel);
  281. var
  282. proc : tprocdef;
  283. reqinstmlist,
  284. reqclsmlist,
  285. optinstmlist,
  286. optclsmlist : TFPObjectList;
  287. i : ptrint;
  288. begin
  289. reqinstmlist:=TFPObjectList.Create(false);
  290. reqclsmlist:=TFPObjectList.Create(false);
  291. optinstmlist:=TFPObjectList.Create(false);
  292. optclsmlist:=TFPObjectList.Create(false);
  293. for i:=0 to protocol.vmtentries.Count-1 do
  294. begin
  295. proc:=pvmtentry(protocol.vmtentries[i])^.procdef;
  296. if (po_classmethod in proc.procoptions) then
  297. if not(po_optional in proc.procoptions) then
  298. reqclsmlist.Add(proc)
  299. else
  300. optclsmlist.Add(proc)
  301. else if not(po_optional in proc.procoptions) then
  302. reqinstmlist.Add(proc)
  303. else
  304. optinstmlist.Add(proc);
  305. end;
  306. if reqinstmlist.Count > 0 then
  307. gen_objc_cat_methods(list,reqinstmlist,sec_objc_cat_inst_meth,'_OBJC_CAT_INST_METH',reqinstsym)
  308. else
  309. reqinstsym:=nil;
  310. if optinstmlist.Count > 0 then
  311. gen_objc_cat_methods(list,optinstmlist,sec_objc_cat_inst_meth,'_OBJC_CAT_INST_METH',optinstsym)
  312. else
  313. optinstsym:=nil;
  314. if reqclsmlist.Count>0 then
  315. gen_objc_cat_methods(list,reqclsmlist,sec_objc_cat_cls_meth,'_OBJC_CAT_CLS_METH',reqclssym)
  316. else
  317. reqclssym:=nil;
  318. if optclsmlist.Count>0 then
  319. gen_objc_cat_methods(list,optclsmlist,sec_objc_cat_cls_meth,'_OBJC_CAT_CLS_METH',optclssym)
  320. else
  321. optclssym:=nil;
  322. reqinstmlist.Free;
  323. reqclsmlist.Free;
  324. optinstmlist.Free;
  325. optclsmlist.Free;
  326. end;
  327. (*
  328. From CLang:
  329. struct objc_protocol_list
  330. {
  331. #ifdef FRAGILE_ABI
  332. struct objc_protocol_list *next;
  333. int count;
  334. #else
  335. long count;
  336. #endif
  337. Protocol *list[1];
  338. };
  339. *)
  340. procedure tobjcrttiwriter.gen_objc_protocol_list(list: tasmlist; protolist: tfpobjectlist; out protolistsym: tasmlabel);
  341. var
  342. i : Integer;
  343. protosym : TAsmSymbol;
  344. protodef : tobjectdef;
  345. begin
  346. if not Assigned(protolist) or
  347. (protolist.Count=0) then
  348. begin
  349. protolistsym:=nil;
  350. Exit;
  351. end;
  352. for i:=0 to protolist.Count-1 do
  353. begin
  354. protodef:=TImplementedInterface(protolist[i]).IntfDef;
  355. protosym:=objcfindprotocolentry(protodef.objextname^);
  356. if not assigned(protosym) then
  357. begin
  358. gen_objc_protocol(list,protodef,protosym);
  359. objcaddprotocolentry(protodef.objextname^,protosym);
  360. end;
  361. end;
  362. { protocol lists are stored in .objc_cat_cls_meth section }
  363. new_section(list,sec_objc_cat_cls_meth,'_OBJC_PROTOCOLLIST',sizeof(pint));
  364. current_asmdata.getlabel(protolistsym, alt_data);
  365. list.Concat(tai_label.Create(protolistsym));
  366. if (abi=oa_fragile) then
  367. { From Clang: next, always nil}
  368. list.Concat(tai_const.Create_pint(0));
  369. { From Clang: protocols count}
  370. list.Concat(Tai_const.Create_pint(protolist.Count));
  371. for i:=0 to protolist.Count-1 do
  372. begin
  373. protodef:=(protolist[i] as TImplementedInterface).IntfDef;
  374. protosym:=objcfindprotocolentry(protodef.objextname^);
  375. if not Assigned(protosym) then
  376. begin
  377. { For some reason protosym is not declared, though must be!
  378. Probably gen_obcj1_protocol returned wrong protosym
  379. }
  380. InternalError(2009091602);
  381. end;
  382. list.Concat(tai_const.Create_sym(protosym));
  383. end;
  384. end;
  385. { Generate rtti for an Objective-C methods (methods without implementation) }
  386. { items : TFPObjectList of Tprocdef }
  387. procedure tobjcrttiwriter.gen_objc_cat_methods(list:TAsmList; items: TFPObjectList; section: tasmsectiontype;
  388. const sectname: string; out listsym: TAsmLabel);
  389. var
  390. i : integer;
  391. m : tprocdef;
  392. mtype : tdef;
  393. begin
  394. if not assigned(items) or
  395. (items.count=0) then
  396. exit;
  397. new_section(list, section, sectname, sizeof(pint));
  398. current_asmdata.getlabel(listsym,alt_data);
  399. list.Concat(tai_label.Create(listsym));
  400. if (abi=oa_nonfragile) then
  401. begin
  402. { size of each entry -- always 32 bit value }
  403. mtype:=search_named_unit_globaltype('OBJC','OBJC_METHOD',true).typedef;
  404. list.Concat(tai_const.Create_32bit(mtype.size));
  405. end;
  406. list.Concat(Tai_const.Create_32bit(items.count));
  407. for i:=0 to items.Count-1 do
  408. begin
  409. m:=tprocdef(items[i]);
  410. list.Concat(Tai_const.Create_sym(
  411. objcreatestringpoolentry(m.messageinf.str^,sp_objcvarnames,sec_objc_meth_var_names)));
  412. list.Concat(Tai_const.Create_sym(
  413. objcreatestringpoolentry(objcencodemethod(m),sp_objcvartypes,sec_objc_meth_var_types)));
  414. { placeholder for address of implementation? }
  415. if (abi=oa_nonfragile) then
  416. list.Concat(Tai_const.Create_pint(0));
  417. end;
  418. end;
  419. { Generate the rtti sections for all obj-c classes defined in st, and return
  420. these classes in the classes list. }
  421. procedure tobjcrttiwriter.gen_objc_rtti_sections(list:TAsmList; st:TSymtable);
  422. var
  423. i: longint;
  424. def: tdef;
  425. sym : TAsmSymbol;
  426. begin
  427. if not Assigned(st) then
  428. exit;
  429. for i:=0 to st.DefList.Count-1 do
  430. begin
  431. def:=tdef(st.DefList[i]);
  432. { check whether all types used in Objective-C class/protocol/category
  433. declarations can be used with the Objective-C run time (can only be
  434. done now, because at parse-time some of these types can still be
  435. forwarddefs) }
  436. if is_objc_class_or_protocol(def) then
  437. if not tobjectdef(def).check_objc_types then
  438. continue;
  439. if is_objcclass(def) and
  440. not(oo_is_external in tobjectdef(def).objectoptions) then
  441. begin
  442. if not(oo_is_classhelper in tobjectdef(def).objectoptions) then
  443. begin
  444. gen_objc_classes_sections(list,tobjectdef(def),sym);
  445. classsyms.add(sym);
  446. classdefs.add(def);
  447. end
  448. else
  449. begin
  450. gen_objc_category_sections(list,tobjectdef(def),sym);
  451. catsyms.add(sym);
  452. catdefs.add(def);
  453. end
  454. end;
  455. end;
  456. end;
  457. constructor tobjcrttiwriter.create(_abi: tobjcabi);
  458. begin
  459. fabi:=_abi;
  460. classdefs:=tfpobjectlist.create(false);
  461. classsyms:=tfpobjectlist.create(false);
  462. catdefs:=tfpobjectlist.create(false);
  463. catsyms:=tfpobjectlist.create(false);
  464. end;
  465. destructor tobjcrttiwriter.destroy;
  466. begin
  467. classdefs.free;
  468. classsyms.free;
  469. catdefs.free;
  470. catsyms.free;
  471. inherited destroy;
  472. end;
  473. {******************************************************************
  474. RTTI generation -- Fragile ABI
  475. *******************************************************************}
  476. { generate an instance variables list for an obj-c class. }
  477. procedure tobjcrttiwriter_fragile.gen_objc_ivars(list: TAsmList; objccls: tobjectdef; out ivarslabel: TAsmLabel);
  478. type
  479. ivar_data = record
  480. vf : tfieldvarsym;
  481. namesym : TAsmSymbol;
  482. typesym : TAsmSymbol;
  483. end;
  484. var
  485. i : integer;
  486. vf : tfieldvarsym;
  487. vars : array of ivar_data;
  488. vcnt : Integer;
  489. enctype : ansistring;
  490. encerr : tdef;
  491. begin
  492. ivarslabel:=nil;
  493. vcnt:=0;
  494. setLength(vars,objccls.symtable.SymList.Count);
  495. for i:=0 to objccls.symtable.SymList.Count-1 do
  496. if tsym(objccls.symtable.SymList[i]).typ=fieldvarsym then
  497. begin
  498. vf:=tfieldvarsym(objccls.symtable.SymList[i]);
  499. if objctryencodetype(vf.vardef,enctype,encerr) then
  500. begin
  501. vars[vcnt].vf:=vf;
  502. vars[vcnt].namesym:=objcreatestringpoolentry(vf.RealName,sp_objcvarnames,sec_objc_meth_var_names);
  503. vars[vcnt].typesym:=objcreatestringpoolentry(enctype,sp_objcvartypes,sec_objc_meth_var_types);
  504. inc(vcnt);
  505. end
  506. else
  507. { Should be caught during parsing }
  508. internalerror(2009090601);
  509. end;
  510. if vcnt=0 then
  511. exit;
  512. new_section(list,sec_objc_instance_vars,'_OBJC_INSTANCE_VARS',sizeof(pint));
  513. current_asmdata.getlabel(ivarslabel,alt_data);
  514. list.Concat(tai_label.Create(ivarslabel));
  515. { objc_ivar_list: first the number of elements }
  516. list.Concat(tai_const.Create_32bit(vcnt));
  517. for i:=0 to vcnt-1 do
  518. begin
  519. { reference to the instance variable name }
  520. list.Concat(tai_const.Create_sym(vars[i].namesym));
  521. { reference to the encoded type }
  522. list.Concat(tai_const.Create_sym(vars[i].typesym));
  523. { and the offset of the field }
  524. list.Concat(tai_const.Create_32bit(vars[i].vf.fieldoffset));
  525. end;
  526. end;
  527. (* From GCC:
  528. struct _objc_protocol_extension
  529. {
  530. uint32_t size; // sizeof (struct _objc_protocol_extension)
  531. struct objc_method_list *optional_instance_methods;
  532. struct objc_method_list *optional_class_methods;
  533. struct objc_prop_list *instance_properties;
  534. }
  535. *)
  536. function tobjcrttiwriter_fragile.gen_objc_protocol_ext(list: TAsmList; optinstsym, optclssym: TAsmLabel): TAsmLabel;
  537. begin
  538. if assigned(optinstsym) or
  539. assigned(optclssym) then
  540. begin
  541. new_section(list, sec_objc_protocol_ext,'_OBJC_PROTOCOLEXT',sizeof(pint));
  542. current_asmdata.getlabel(Result,alt_data);
  543. list.Concat(tai_label.Create(Result));
  544. { size of this structure }
  545. list.Concat(Tai_const.Create_32bit(16));
  546. { optional instance methods }
  547. ConcatSymOrNil(list,optinstsym);
  548. { optional class methods }
  549. ConcatSymOrNil(list,optclssym);
  550. { optional properties (todo) }
  551. ConcatSymOrNil(list,nil);
  552. end
  553. else
  554. Result:=nil;
  555. end;
  556. { Generate rtti for an Objective-C protocol }
  557. procedure tobjcrttiwriter_fragile.gen_objc_protocol(list:TAsmList; protocol: tobjectdef; out protocollabel: TAsmSymbol);
  558. var
  559. namesym : TAsmSymbol;
  560. protolist : TAsmLabel;
  561. reqinstsym,
  562. optinstsym,
  563. reqclssym,
  564. optclssym,
  565. protoext,
  566. lbl : TAsmLabel;
  567. begin
  568. gen_objc_protocol_list(list,protocol.ImplementedInterfaces,protolist);
  569. gen_objc_protocol_elements(list,protocol,reqinstsym,optinstsym,reqclssym,optclssym);
  570. protoext:=gen_objc_protocol_ext(list,optinstsym,optclssym);
  571. new_section(list, sec_objc_protocol,'_OBJC_PROTOCOL',sizeof(pint));
  572. current_asmdata.getlabel(lbl,alt_data);
  573. list.Concat(tai_label.Create(lbl));
  574. protocollabel:=lbl;
  575. { protocol's isa - points to information about optional methods/properties }
  576. ConcatSymOrNil(list,protoext);
  577. { name }
  578. namesym:=objcreatestringpoolentry(protocol.objextname^,sp_objcclassnames,sec_objc_class_names);
  579. list.Concat(Tai_const.Create_sym(namesym));
  580. { protocol's list }
  581. ConcatSymOrNil(list,protolist);
  582. { instance methods, in __cat_inst_meth }
  583. ConcatSymOrNil(list,reqinstsym);
  584. { class methods, in __cat_cls_meth }
  585. ConcatSymOrNil(list,reqclssym);
  586. end;
  587. (*
  588. From Clang:
  589. struct _objc_category {
  590. char *category_name;
  591. char *class_name;
  592. struct _objc_method_list *instance_methods;
  593. struct _objc_method_list *class_methods;
  594. struct _objc_protocol_list *protocols;
  595. uint32_t size; // <rdar://4585769>
  596. struct _objc_property_list *instance_properties;
  597. };
  598. *)
  599. { Generate rtti for an Objective-C class and its meta-class. }
  600. procedure tobjcrttiwriter_fragile.gen_objc_category_sections(list:TAsmList; objccat: tobjectdef; out catlabel: TAsmSymbol);
  601. var
  602. instmthdlist,
  603. clsmthdlist,
  604. protolistsym : TAsmLabel;
  605. catstrsym,
  606. clsstrsym,
  607. catsym : TAsmSymbol;
  608. begin
  609. { the category name }
  610. catstrsym:=objcreatestringpoolentry(objccat.objextname^,sp_objcclassnames,sec_objc_class_names);
  611. { the name of the class it extends }
  612. clsstrsym:=objcreatestringpoolentry(objccat.childof.objextname^,sp_objcclassnames,sec_objc_class_names);
  613. { generate the methods lists }
  614. gen_objc_methods(list,objccat,instmthdlist,false,true);
  615. gen_objc_methods(list,objccat,clsmthdlist,true,true);
  616. { generate implemented protocols list }
  617. gen_objc_protocol_list(list,objccat.ImplementedInterfaces,protolistsym);
  618. { category declaration section }
  619. new_section(list,sec_objc_category,'_OBJC_CATEGORY',sizeof(pint));
  620. catsym:=current_asmdata.DefineAsmSymbol(objccat.rtti_mangledname(objcclassrtti),AB_LOCAL,AT_DATA);
  621. list.Concat(tai_symbol.Create(catsym,0));
  622. list.Concat(Tai_const.Create_sym(catstrsym));
  623. list.Concat(Tai_const.Create_sym(clsstrsym));
  624. ConcatSymOrNil(list,instmthdlist);
  625. ConcatSymOrNil(list,clsmthdlist);
  626. ConcatSymOrNil(list,protolistsym);
  627. { size of this structure }
  628. list.Concat(Tai_const.Create_32bit(28));
  629. { properties, not yet supported }
  630. list.Concat(Tai_const.Create_32bit(0));
  631. catlabel:=catsym;
  632. end;
  633. (*
  634. From Clang:
  635. struct _objc_class {
  636. Class isa;
  637. Class super_class;
  638. const char *name;
  639. long version;
  640. long info;
  641. long instance_size;
  642. struct _objc_ivar_list *ivars;
  643. struct _objc_method_list *methods;
  644. struct _objc_cache *cache;
  645. struct _objc_protocol_list *protocols;
  646. // Objective-C 1.0 extensions (<rdr://4585769>) -- for garbage collection
  647. const char *ivar_layout;
  648. struct _objc_class_ext *ext;
  649. };
  650. *)
  651. { Generate rtti for an Objective-C class and its meta-class. }
  652. procedure tobjcrttiwriter_fragile.gen_objc_classes_sections(list:TAsmList; objclss: tobjectdef; out classlabel: TAsmSymbol);
  653. const
  654. CLS_CLASS = 1;
  655. CLS_META = 2;
  656. CLS_HIDDEN = $20000;
  657. META_INST_SIZE = 40+8; // sizeof(objc_class) + 8
  658. var
  659. root : tobjectdef;
  660. superStrSym,
  661. classStrSym,
  662. metaisaStrSym,
  663. metasym,
  664. clssym : TAsmSymbol;
  665. mthdlist,
  666. ivarslist,
  667. protolistsym : TAsmLabel;
  668. hiddenflag : cardinal;
  669. begin
  670. { generate the class methods list }
  671. gen_objc_methods(list,objclss,mthdlist,true,false);
  672. { generate implemented protocols list }
  673. gen_objc_protocol_list(list,objclss.ImplementedInterfaces,protolistsym);
  674. { register necessary names }
  675. { 1) the superclass }
  676. if assigned(objclss.childof) then
  677. superStrSym:=objcreatestringpoolentry(objclss.childof.objextname^,sp_objcclassnames,sec_objc_class_names)
  678. else
  679. { not empty string, but nil! }
  680. superStrSym:=nil;
  681. { 2) the current class }
  682. classStrSym:=objcreatestringpoolentry(objclss.objextname^,sp_objcclassnames,sec_objc_class_names);
  683. { 3) the isa }
  684. { From Clang: The isa for the meta-class is the root of the hierarchy. }
  685. root:=objclss;
  686. while assigned(root.childof) do
  687. root:=root.childof;
  688. metaisaStrSym:=objcreatestringpoolentry(root.objextname^,sp_objcclassnames,sec_objc_class_names);
  689. { 4) the flags }
  690. { consider every class declared in the implementation section of a unit
  691. as "hidden"
  692. }
  693. hiddenflag:=0;
  694. if (objclss.owner.symtabletype=staticsymtable) and
  695. current_module.is_unit then
  696. hiddenflag:=CLS_HIDDEN;
  697. { class declaration section }
  698. new_section(list,sec_objc_meta_class,'_OBJC_META_CLASS',sizeof(pint));
  699. { 1) meta-class declaration }
  700. metasym:=current_asmdata.DefineAsmSymbol(objclss.rtti_mangledname(objcmetartti),AB_LOCAL,AT_DATA);
  701. list.Concat(tai_symbol.Create(metasym,0));
  702. list.Concat(Tai_const.Create_sym(metaisaStrSym));
  703. { pointer to the superclass name if any, otherwise nil }
  704. if assigned(superstrsym) then
  705. list.Concat(Tai_const.Create_sym(superStrSym))
  706. else
  707. list.concat(tai_const.create_32bit(0));
  708. { pointer to the class name }
  709. list.Concat(Tai_const.Create_sym(classStrSym));
  710. { version is always 0 currently }
  711. list.Concat(Tai_const.Create_32bit(0));
  712. { CLS_META for meta-classes }
  713. list.Concat(Tai_const.Create_32bit(hiddenflag or CLS_META));
  714. { size of the meta-class instance: sizeof(objc_class) + 8 bytes }
  715. list.Concat(Tai_const.Create_32bit(META_INST_SIZE) );
  716. { meta-classes don't have ivars list (=0) }
  717. list.Concat(Tai_const.Create_32bit(0));
  718. { class methods list (stored in "__cls_meth" section) }
  719. if Assigned(mthdlist) then
  720. list.Concat(Tai_const.Create_sym(mthdlist))
  721. else
  722. list.Concat(Tai_const.Create_32bit(0));
  723. { From Clang: cache is always nil }
  724. list.Concat(Tai_const.Create_32bit(0));
  725. { protocols }
  726. ConcatSymOrNil(list, protolistsym);
  727. { From Clang: ivar_layout for meta-class is always NULL. }
  728. list.Concat(Tai_const.Create_32bit(0));
  729. { From Clang: The class extension is always unused for meta-classes. }
  730. list.Concat(Tai_const.Create_32bit(0));
  731. { 2) regular class declaration }
  732. { generate the instance methods list }
  733. gen_objc_methods(list,objclss,mthdlist,false,false);
  734. { generate the instance variables list }
  735. gen_objc_ivars(list,objclss,ivarslist);
  736. new_section(list,sec_objc_class,'_OBJC_CLASS',sizeof(pint));
  737. clssym:=current_asmdata.DefineAsmSymbol(objclss.rtti_mangledname(objcclassrtti),AB_LOCAL,AT_DATA);
  738. list.Concat(tai_symbol.Create(clssym,0));
  739. { for class declaration: the isa points to the meta-class declaration }
  740. list.Concat(Tai_const.Create_sym(metasym));
  741. { pointer to the super_class name if any, nil otherwise }
  742. if assigned(superStrSym) then
  743. list.Concat(Tai_const.Create_sym(superStrSym))
  744. else
  745. list.Concat(Tai_const.Create_32bit(0));
  746. { pointer to the class name }
  747. list.Concat(Tai_const.Create_sym(classStrSym));
  748. { version is always 0 currently }
  749. list.Concat(Tai_const.Create_32bit(0));
  750. { CLS_CLASS for classes }
  751. list.Concat(Tai_const.Create_32bit(hiddenflag or CLS_CLASS));
  752. { size of instance: total size of instance variables }
  753. list.Concat(Tai_const.Create_32bit(tobjectsymtable(objclss.symtable).datasize));
  754. { objc_ivar_list (stored in "__instance_vars" section) }
  755. if assigned(ivarslist) then
  756. list.Concat(Tai_const.Create_sym(ivarslist))
  757. else
  758. list.Concat(tai_const.create_32bit(0));
  759. { instance methods list (stored in "__inst_meth" section) }
  760. if Assigned(mthdlist) then
  761. list.Concat(Tai_const.Create_sym(mthdlist))
  762. else
  763. list.Concat(Tai_const.Create_32bit(0));
  764. { From Clang: cache is always NULL }
  765. list.Concat(Tai_const.Create_32bit(0));
  766. { protocols, protolistsym has been created for meta-class, no need to create another one}
  767. ConcatSymOrNil(list, protolistsym);
  768. { TODO: From Clang: strong ivar_layout, necessary for garbage collection support }
  769. list.Concat(Tai_const.Create_32bit(0));
  770. { TODO: From Clang: weak ivar_layout, necessary for garbage collection support }
  771. list.Concat(Tai_const.Create_32bit(0));
  772. classlabel:=clssym;
  773. end;
  774. { Generate the global information sections (objc_symbols and objc_module_info)
  775. for this module. }
  776. procedure tobjcrttiwriter_fragile.gen_objc_info_sections(list: tasmlist);
  777. var
  778. i: longint;
  779. sym : TAsmSymbol;
  780. parent: tobjectdef;
  781. superclasses: tfpobjectlist;
  782. begin
  783. if (classsyms.count<>0) or
  784. (catsyms.count<>0) then
  785. begin
  786. new_section(list,sec_objc_symbols,'_OBJC_SYMBOLS',sizeof(pint));
  787. sym := current_asmdata.DefineAsmSymbol(target_asm.labelprefix+'_OBJC_SYMBOLS_$',AB_LOCAL,AT_DATA);
  788. { symbol to refer to this information }
  789. list.Concat(tai_symbol.Create(sym,0));
  790. { ??? (always 0 in Clang) }
  791. list.Concat(Tai_const.Create_pint(0));
  792. { ??? (From Clang: always 0, pointer to some selector) }
  793. list.Concat(Tai_const.Create_pint(0));
  794. { From Clang: number of defined classes }
  795. list.Concat(Tai_const.Create_16bit(classsyms.count));
  796. { From Clang: number of defined categories }
  797. list.Concat(Tai_const.Create_16bit(catsyms.count));
  798. { first all classes }
  799. for i:=0 to classsyms.count-1 do
  800. list.Concat(Tai_const.Create_sym(tasmsymbol(classsyms[i])));
  801. { then all categories }
  802. for i:=0 to catsyms.count-1 do
  803. list.Concat(Tai_const.Create_sym(tasmsymbol(catsyms[i])));
  804. end
  805. else
  806. sym:=nil;
  807. new_section(list,sec_objc_module_info,'_OBJC_MODULE_INFO',4);
  808. { version number = 7 (always, both for gcc and clang) }
  809. list.Concat(Tai_const.Create_pint(7));
  810. { sizeof(objc_module): 4 pointer-size entities }
  811. list.Concat(Tai_const.Create_pint(sizeof(pint)*4));
  812. { used to be file name, now unused (points to empty string) }
  813. list.Concat(Tai_const.Create_sym(objcreatestringpoolentry('',sp_objcclassnames,sec_objc_class_names)));
  814. { pointer to classes/categories list declared in this module }
  815. if assigned(sym) then
  816. list.Concat(Tai_const.Create_sym(sym))
  817. else
  818. list.concat(tai_const.create_pint(0));
  819. { Add lazy references to parent classes of all classes defined in this unit }
  820. superclasses:=tfpobjectlist.create(false);
  821. for i:=0 to classdefs.count-1 do
  822. begin
  823. parent:=tobjectdef(classdefs[i]).childof;
  824. { warning: linear search, performance hazard if large number of subclasses }
  825. if assigned(parent) and
  826. (superclasses.indexof(parent)=-1) then
  827. begin
  828. list.concat(tai_directive.create(asd_lazy_reference,'.objc_class_name_'+parent.objextname^));
  829. superclasses.add(parent);
  830. end;
  831. end;
  832. for i:=0 to catdefs.count-1 do
  833. begin
  834. parent:=tobjectdef(catdefs[i]).childof;
  835. { warning: linear search, performance hazard if large number of subclasses }
  836. if assigned(parent) and
  837. (superclasses.indexof(parent)=-1) then
  838. begin
  839. list.concat(tai_directive.create(asd_lazy_reference,'.objc_class_name_'+parent.objextname^));
  840. superclasses.add(parent);
  841. end;
  842. end;
  843. superclasses.free;
  844. { reference symbols for all classes and categories defined in this unit }
  845. for i:=0 to classdefs.count-1 do
  846. list.concat(tai_symbol.Createname_global_value('.objc_class_name_'+tobjectdef(classdefs[i]).objextname^,AT_DATA,0,0));
  847. for i:=0 to catdefs.count-1 do
  848. list.concat(tai_symbol.Createname_global_value('.objc_category_name_'+
  849. tobjectdef(catdefs[i]).childof.objextname^+'_'+
  850. tobjectdef(catdefs[i]).objextname^,AT_DATA,0,0));
  851. end;
  852. constructor tobjcrttiwriter_fragile.create;
  853. begin
  854. inherited create(oa_fragile);
  855. end;
  856. {******************************************************************
  857. RTTI generation -- Non-Fragile ABI
  858. *******************************************************************}
  859. (*
  860. From Clang:
  861. /// EmitIvarList - Emit the ivar list for the given
  862. /// implementation. The return value has type
  863. /// IvarListnfABIPtrTy.
  864. /// struct _ivar_t {
  865. /// unsigned long int *offset; // pointer to ivar offset location
  866. /// char *name;
  867. /// char *type;
  868. /// uint32_t alignment;
  869. /// uint32_t size;
  870. /// }
  871. /// struct _ivar_list_t {
  872. /// uint32 entsize; // sizeof(struct _ivar_t)
  873. /// uint32 count;
  874. /// struct _iver_t list[count];
  875. /// }
  876. ///
  877. *)
  878. procedure tobjcrttiwriter_nonfragile.gen_objc_ivars(list: tasmlist; objccls: tobjectdef; out ivarslabel: tasmlabel);
  879. type
  880. ivar_data = record
  881. vf : tfieldvarsym;
  882. namesym : TAsmSymbol;
  883. typesym : TAsmSymbol;
  884. offssym : TAsmSymbol;
  885. end;
  886. var
  887. ivtype: tdef;
  888. vf : tfieldvarsym;
  889. vars : array of ivar_data;
  890. i : integer;
  891. vcnt : integer;
  892. enctype : ansistring;
  893. encerr : tdef;
  894. prefix : shortstring;
  895. vis : TAsmsymbind;
  896. begin
  897. ivarslabel:=nil;
  898. vcnt:=0;
  899. setLength(vars,objccls.symtable.SymList.Count);
  900. for i:=0 to objccls.symtable.SymList.Count-1 do
  901. if tsym(objccls.symtable.SymList[i]).typ=fieldvarsym then
  902. begin
  903. vf:=tfieldvarsym(objccls.symtable.SymList[i]);
  904. if objctryencodetype(vf.vardef,enctype,encerr) then
  905. begin
  906. vars[vcnt].vf:=vf;
  907. vars[vcnt].namesym:=objcreatestringpoolentry(vf.RealName,sp_objcvarnames,sec_objc_meth_var_names);
  908. vars[vcnt].typesym:=objcreatestringpoolentry(enctype,sp_objcvartypes,sec_objc_meth_var_types);
  909. if (vcnt=0) then
  910. begin
  911. new_section(list,sec_objc_const,'_OBJC_IVAR_OFFSETS',sizeof(pint));
  912. prefix:=target_info.cprefix+'OBJC_IVAR_$_'+objccls.objextname^+'.';
  913. end;
  914. { This matches gcc/Clang, but is strange: I would expect private
  915. fields to be local symbols rather than private_extern (which
  916. is "package-global") (JM)
  917. }
  918. if not(vf.visibility in [vis_public,vis_protected,vis_strictprotected]) then
  919. vis:=AB_PRIVATE_EXTERN
  920. else
  921. vis:=AB_GLOBAL;
  922. vars[vcnt].offssym:=current_asmdata.DefineAsmSymbol(prefix+vf.RealName,vis,AT_DATA);
  923. list.concat(tai_symbol.Create_Global(vars[vcnt].offssym,0));
  924. list.concat(tai_const.create_pint(vf.fieldoffset));
  925. inc(vcnt);
  926. end
  927. else
  928. { must be caught during parsing }
  929. internalerror(2009092301);
  930. end;
  931. if vcnt=0 then
  932. exit;
  933. new_section(list,sec_objc_instance_vars,'_OBJC_INSTANCE_VARS',sizeof(pint));
  934. current_asmdata.getlabel(ivarslabel,alt_data);
  935. list.Concat(tai_label.Create(ivarslabel));
  936. { size of each entry -- always 32 bit value }
  937. ivtype:=search_named_unit_globaltype('OBJC','OBJC_IVAR',true).typedef;
  938. list.concat(tai_const.Create_32bit(ivtype.size));
  939. { number of entries -- always 32 bit value }
  940. list.Concat(tai_const.Create_32bit(vcnt));
  941. for i:=0 to vcnt-1 do
  942. begin
  943. { reference to the offset }
  944. list.Concat(tai_const.Create_sym(vars[i].offssym));
  945. { reference to the instance variable name }
  946. list.Concat(tai_const.Create_sym(vars[i].namesym));
  947. { reference to the encoded type }
  948. list.Concat(tai_const.Create_sym(vars[i].typesym));
  949. { alignment -- always 32 bit value }
  950. list.Concat(tai_const.create_32bit(vars[i].vf.vardef.alignment));
  951. { size -- always 32 bit value }
  952. list.Concat(tai_const.Create_32bit(vars[i].vf.vardef.size));
  953. end;
  954. end;
  955. (*
  956. From Clang:
  957. /// GetOrEmitProtocol - Generate the protocol meta-data:
  958. /// @code
  959. /// struct _protocol_t {
  960. /// id isa; // NULL
  961. /// const char * const protocol_name;
  962. /// const struct _protocol_list_t * protocol_list; // super protocols
  963. /// const struct method_list_t * const instance_methods;
  964. /// const struct method_list_t * const class_methods;
  965. /// const struct method_list_t *optionalInstanceMethods;
  966. /// const struct method_list_t *optionalClassMethods;
  967. /// const struct _prop_list_t * properties;
  968. /// const uint32_t size; // sizeof(struct _protocol_t)
  969. /// const uint32_t flags; // = 0
  970. /// }
  971. /// @endcode
  972. *)
  973. procedure tobjcrttiwriter_nonfragile.gen_objc_protocol(list: tasmlist; protocol: tobjectdef; out protocollabel: tasmsymbol);
  974. var
  975. lbl,
  976. namesym,
  977. listsym : TAsmSymbol;
  978. protolist : TAsmLabel;
  979. reqinstsym,
  980. reqclssym,
  981. optinstsym,
  982. optclssym : TAsmLabel;
  983. prottype : tdef;
  984. begin
  985. gen_objc_protocol_list(list,protocol.ImplementedInterfaces,protolist);
  986. gen_objc_protocol_elements(list,protocol,reqinstsym,optinstsym,reqclssym,optclssym);
  987. new_section(list, sec_data_coalesced,'_OBJC_PROTOCOL',sizeof(pint));
  988. { label for the protocol needs to be
  989. a) in a coalesced section (so multiple definitions of the same protocol
  990. can be merged by the linker)
  991. b) private_extern (should only be merged within the same module)
  992. c) weakly defined (so multiple definitions don't cause errors)
  993. }
  994. lbl:=current_asmdata.DefineAsmSymbol(protocol.rtti_mangledname(objcclassrtti),AB_PRIVATE_EXTERN,AT_DATA);
  995. list.Concat(tai_symbol.Create_Global(lbl,0));
  996. protocollabel:=lbl;
  997. { protocol's isa - always nil }
  998. list.Concat(Tai_const.Create_pint(0));
  999. { name }
  1000. namesym:=objcreatestringpoolentry(protocol.objextname^,sp_objcclassnames,sec_objc_class_names);
  1001. list.Concat(Tai_const.Create_sym(namesym));
  1002. { parent protocols list }
  1003. ConcatSymOrNil(list,protolist);
  1004. { required instance methods }
  1005. ConcatSymOrNil(list,reqinstsym);
  1006. { required class methods }
  1007. ConcatSymOrNil(list,reqclssym);
  1008. { optional instance methods }
  1009. ConcatSymOrNil(list,optinstsym);
  1010. { optional class methods }
  1011. ConcatSymOrNil(list,optclssym);
  1012. { TODO: properties }
  1013. list.Concat(Tai_const.Create_pint(0));
  1014. { size of this type }
  1015. prottype:=search_named_unit_globaltype('OBJC','OBJC_PROTOCOL',true).typedef;
  1016. list.concat(tai_const.Create_32bit(prottype.size));
  1017. { flags }
  1018. list.concat(tai_const.Create_32bit(0));
  1019. { also add an entry to the __DATA, __objc_protolist section, required to
  1020. register the protocol with the runtime }
  1021. new_section(list, sec_objc_protolist,'_OBJC_PROTOLIST',sizeof(pint));
  1022. listsym:=current_asmdata.DefineAsmSymbol(protocol.rtti_mangledname(objcmetartti),AB_PRIVATE_EXTERN,AT_DATA);
  1023. list.Concat(tai_symbol.Create_Global(listsym,0));
  1024. list.Concat(tai_const.Create_sym(lbl));
  1025. list.Concat(tai_directive.Create(asd_weak_definition,listsym.name));
  1026. end;
  1027. (*
  1028. From Clang:
  1029. /// struct _category_t {
  1030. /// const char * const name;
  1031. /// struct _class_t *const cls;
  1032. /// const struct _method_list_t * const instance_methods;
  1033. /// const struct _method_list_t * const class_methods;
  1034. /// const struct _protocol_list_t * const protocols;
  1035. /// const struct _prop_list_t * const properties;
  1036. /// }
  1037. *)
  1038. procedure tobjcrttiwriter_nonfragile.gen_objc_category_sections(list:TAsmList; objccat: tobjectdef; out catlabel: TAsmSymbol);
  1039. var
  1040. instmthdlist,
  1041. clsmthdlist,
  1042. protolistsym : TAsmLabel;
  1043. catstrsym,
  1044. clssym,
  1045. catsym : TAsmSymbol;
  1046. begin
  1047. { the category name }
  1048. catstrsym:=objcreatestringpoolentry(objccat.objextname^,sp_objcclassnames,sec_objc_class_names);
  1049. { the class it extends }
  1050. clssym:=current_asmdata.RefAsmSymbol(objccat.childof.rtti_mangledname(objcclassrtti));
  1051. { generate the methods lists }
  1052. gen_objc_methods(list,objccat,instmthdlist,false,true);
  1053. gen_objc_methods(list,objccat,clsmthdlist,true,true);
  1054. { generate implemented protocols list }
  1055. gen_objc_protocol_list(list,objccat.ImplementedInterfaces,protolistsym);
  1056. { category declaration section }
  1057. new_section(list,sec_objc_const,'_OBJC_CATEGORY',sizeof(pint));
  1058. catsym:=current_asmdata.DefineAsmSymbol(objccat.rtti_mangledname(objcclassrtti),AB_LOCAL,AT_DATA);
  1059. list.Concat(tai_symbol.Create(catsym,0));
  1060. list.Concat(Tai_const.Create_sym(catstrsym));
  1061. list.Concat(Tai_const.Create_sym(clssym));
  1062. ConcatSymOrNil(list,instmthdlist);
  1063. ConcatSymOrNil(list,clsmthdlist);
  1064. ConcatSymOrNil(list,protolistsym);
  1065. { properties, not yet supported }
  1066. list.Concat(Tai_const.Create_pint(0));
  1067. catlabel:=catsym;
  1068. end;
  1069. (*
  1070. From Clang:
  1071. /// BuildIvarLayout - Builds ivar layout bitmap for the class
  1072. /// implementation for the __strong or __weak case.
  1073. /// The layout map displays which words in ivar list must be skipped
  1074. /// and which must be scanned by GC (see below). String is built of bytes.
  1075. /// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
  1076. /// of words to skip and right nibble is count of words to scan. So, each
  1077. /// nibble represents up to 15 workds to skip or scan. Skipping the rest is
  1078. /// represented by a 0x00 byte which also ends the string.
  1079. /// 1. when ForStrongLayout is true, following ivars are scanned:
  1080. /// - id, Class
  1081. /// - object * // note: this "object" means "Objective-C object" (JM)
  1082. /// - __strong anything
  1083. ///
  1084. /// 2. When ForStrongLayout is false, following ivars are scanned:
  1085. /// - __weak anything
  1086. *)
  1087. (*
  1088. Only required when supporting garbage collection
  1089. procedure tobjcrttiwriter_nonfragile.gen_objc_ivargc_recursive(st: tabstractrecordsymtable; ptrbset: tbitset; startoffset: puint; il: tivarlayouttype);
  1090. var
  1091. i: longint;
  1092. fs: tfieldvarsym;
  1093. includelen: longint;
  1094. begin
  1095. for i:=0 to st.SymList.count-1 do
  1096. if (tsym(st.symlist[i]).typ=fieldvarsym) then
  1097. begin
  1098. fs:=tfieldvarsym(st.symlist[i]);
  1099. includelen:=0;
  1100. case fs.vardef.typ of
  1101. pointerdef,
  1102. classrefdef:
  1103. if (fs.vardef=objc_idtype) or
  1104. (fs.vardef=objc_metaclasstype) then
  1105. includelen:=1;
  1106. recorddef:
  1107. TODO: bitpacking -> offset differences
  1108. gen_objc_ivargc_recursive(tabstractrecordsymtable(trecorddef(fs.vardef).symtable),ptrbset,startoffset+fs.fieldoffset,il);
  1109. arraydef:
  1110. begin
  1111. if not is_special_
  1112. end;
  1113. objectdef :
  1114. begin
  1115. case tobjectdef(fs.vardef).objecttype of
  1116. odt_objcclass,
  1117. odt_objcprotocol:
  1118. includelen:=1;
  1119. odt_object:
  1120. gen_objc_ivargc_recursive(tabstractrecordsymtable(tobjectdef(fs.vardef).symtable),ptrbset,startoffset+fs.fieldoffset,il);
  1121. end;
  1122. end;
  1123. end;
  1124. end;
  1125. end;
  1126. function tobjcrttiwriter_nonfragile.gen_objc_ivargcstring(objclss: tobjectdef; il: tivarlayouttype): ansistring;
  1127. var
  1128. ptrbset: tbitset;
  1129. parent: tobjectdef;
  1130. size,
  1131. startoffset: puint;
  1132. i: longint;
  1133. begin
  1134. size:=tObjectSymtable(objclss.symtable).datasize;
  1135. if assigned(objclss.childof) then
  1136. startoffset:=tObjectSymtable(objclss.childof.symtable).datasize
  1137. else
  1138. startoffset:=0;
  1139. size:=size-startoffset;
  1140. ptrbset:=tbitset.create_bytesize((size+sizeof(ptruint)-1) div sizeof(ptruint));
  1141. { has to include info for this class' fields and those of all parent
  1142. classes as well
  1143. }
  1144. parent:=obclss;
  1145. repeat
  1146. gen_objc_ivargc_recursive(parent.symtable,ptrbset,0,il);
  1147. parent:=parent.childof;
  1148. until not assigned(parent);
  1149. { convert bits set to encoded string }
  1150. end;
  1151. *)
  1152. (*
  1153. From Clang:
  1154. /// struct _class_ro_t {
  1155. /// uint32_t const flags;
  1156. /// uint32_t const instanceStart;
  1157. /// uint32_t const instanceSize;
  1158. /// uint32_t const reserved; // only when building for 64bit targets
  1159. /// const uint8_t * const ivarLayout;
  1160. /// const char *const name;
  1161. /// const struct _method_list_t * const baseMethods;
  1162. /// const struct _protocol_list_t *const baseProtocols;
  1163. /// const struct _ivar_list_t *const ivars;
  1164. /// const uint8_t * const weakIvarLayout;
  1165. /// const struct _prop_list_t * const properties;
  1166. /// }
  1167. *)
  1168. procedure tobjcrttiwriter_nonfragile.gen_objc_class_ro_part(list: tasmlist; objclss: tobjectdef; protolistsym: TAsmSymbol; out classrolabel: tasmsymbol; metaclass: boolean);
  1169. const
  1170. CLS_CLASS = 0;
  1171. CLS_META = 1;
  1172. CLS_ROOT = 2;
  1173. OBJC2_CLS_HIDDEN = $10;
  1174. CLS_EXCEPTION = $20;
  1175. var
  1176. classStrSym,
  1177. rosym : TAsmSymbol;
  1178. methodslab,
  1179. ivarslab : TAsmLabel;
  1180. class_type : tdef;
  1181. start,
  1182. size,
  1183. flags : cardinal;
  1184. rttitype : trttitype;
  1185. firstfield : tfieldvarsym;
  1186. i : longint;
  1187. begin
  1188. { consider every class declared in the implementation section of a unit
  1189. as "hidden"
  1190. }
  1191. flags:=0;
  1192. if (objclss.owner.symtabletype=staticsymtable) and
  1193. current_module.is_unit then
  1194. flags:=OBJC2_CLS_HIDDEN;
  1195. if metaclass then
  1196. begin
  1197. flags:=flags or CLS_META;
  1198. rttitype:=objcmetarortti;
  1199. { metaclass size/start: always size of objc_object }
  1200. class_type:=search_named_unit_globaltype('OBJC','OBJC_OBJECT',true).typedef;
  1201. start:=class_type.size;
  1202. size:=start;
  1203. end
  1204. else
  1205. begin
  1206. flags:=flags or CLS_CLASS;
  1207. rttitype:=objcclassrortti;
  1208. size:=tObjectSymtable(objclss.symtable).datasize;
  1209. { can't simply use childof's datasize, because alignment may cause the
  1210. first field to skip a couple of bytes after the previous end }
  1211. firstfield:=nil;
  1212. for i:=0 to objclss.symtable.SymList.Count-1 do
  1213. if (tsym(objclss.symtable.SymList[i]).typ=fieldvarsym) then
  1214. begin
  1215. firstfield:=tfieldvarsym(objclss.symtable.SymList[i]);
  1216. break;
  1217. end;
  1218. if assigned(firstfield) then
  1219. start:=firstfield.fieldoffset
  1220. else
  1221. { no extra fields -> start = size }
  1222. start:=size;
  1223. end;
  1224. if not assigned(objclss.childof) then
  1225. flags:=flags or CLS_ROOT;
  1226. classStrSym:=objcreatestringpoolentry(objclss.objextname^,sp_objcclassnames,sec_objc_class_names);
  1227. { generate methods list }
  1228. gen_objc_methods(list,objclss,methodslab,metaclass,false);
  1229. { generate ivars (nil for metaclass) }
  1230. if metaclass then
  1231. ivarslab:=nil
  1232. else
  1233. gen_objc_ivars(list,objclss,ivarslab);
  1234. { class declaration section }
  1235. new_section(list,sec_objc_const,'_OBJC_META_CLASS',sizeof(pint));
  1236. rosym:=current_asmdata.DefineAsmSymbol(objclss.rtti_mangledname(rttitype),AB_LOCAL,AT_DATA);
  1237. classrolabel:=rosym;
  1238. list.Concat(tai_symbol.create(rosym,0));
  1239. list.Concat(tai_const.Create_32bit(longint(flags)));
  1240. list.Concat(tai_const.Create_32bit(longint(start)));
  1241. list.Concat(tai_const.Create_32bit(longint(size)));
  1242. {$ifdef cpu64bitaddr}
  1243. { alignment }
  1244. list.Concat(tai_const.Create_32bit(0));
  1245. {$endif}
  1246. { TODO: strong ivar layout for garbage collection }
  1247. list.concat(tai_const.Create_pint(0));
  1248. list.concat(tai_const.Create_sym(classStrSym));
  1249. ConcatSymOrNil(list,methodslab);
  1250. ConcatSymOrNil(list,protolistsym);
  1251. ConcatSymOrNil(list,ivarslab);
  1252. { TODO: weak ivar layout for garbage collection }
  1253. list.concat(tai_const.Create_pint(0));
  1254. { TODO: properties }
  1255. list.concat(tai_const.Create_pint(0));
  1256. end;
  1257. (*
  1258. From Clang:
  1259. /// struct _class_t {
  1260. /// struct _class_t *isa;
  1261. /// struct _class_t * const superclass;
  1262. /// void *cache;
  1263. /// IMP *vtable;
  1264. /// struct class_ro_t *ro;
  1265. /// }
  1266. ///
  1267. *)
  1268. { Generate rtti for an Objective-C class and its meta-class. }
  1269. procedure tobjcrttiwriter_nonfragile.gen_objc_classes_sections(list:TAsmList; objclss: tobjectdef; out classlabel: TAsmSymbol);
  1270. var
  1271. root : tobjectdef;
  1272. superSym,
  1273. superMetaSym,
  1274. metaisaSym,
  1275. metasym,
  1276. clssym,
  1277. metarosym,
  1278. rosym : TAsmSymbol;
  1279. protolistsym : TAsmLabel;
  1280. vis : TAsmsymbind;
  1281. begin
  1282. { A) Register necessary names }
  1283. { 1) the current class and metaclass }
  1284. if (objclss.owner.symtabletype=globalsymtable) then
  1285. vis:=AB_GLOBAL
  1286. else
  1287. vis:=AB_PRIVATE_EXTERN;
  1288. clssym:=current_asmdata.DefineAsmSymbol(objclss.rtti_mangledname(objcclassrtti),vis,AT_DATA);
  1289. metasym:=current_asmdata.DefineAsmSymbol(objclss.rtti_mangledname(objcmetartti),vis,AT_DATA);
  1290. { 2) the superclass and meta superclass }
  1291. if assigned(objclss.childof) then
  1292. begin
  1293. superSym:=current_asmdata.RefAsmSymbol(objclss.childof.rtti_mangledname(objcclassrtti));
  1294. superMetaSym:=current_asmdata.RefAsmSymbol(objclss.childof.rtti_mangledname(objcmetartti));
  1295. end
  1296. else
  1297. begin
  1298. superSym:=nil;
  1299. { the class itself }
  1300. superMetaSym:=clssym;
  1301. end;
  1302. { 3) the isa }
  1303. { From Clang: The isa for the meta-class is the root of the hierarchy. }
  1304. root:=objclss;
  1305. while assigned(root.childof) do
  1306. root:=root.childof;
  1307. metaisaSym:=current_asmdata.RefAsmSymbol(root.rtti_mangledname(objcmetartti));
  1308. { 4) the implemented protocols (same for metaclass and regular class) }
  1309. gen_objc_protocol_list(list,objclss.ImplementedInterfaces,protolistsym);
  1310. { 5) the read-only parts of the class definitions }
  1311. gen_objc_class_ro_part(list,objclss,protolistsym,metarosym,true);
  1312. gen_objc_class_ro_part(list,objclss,protolistsym,rosym,false);
  1313. { B) Class declaration section }
  1314. { both class and metaclass are in the objc_data section for obj-c 2 }
  1315. new_section(list,sec_objc_data,'_OBJC_CLASS',sizeof(pint));
  1316. { 1) meta-class declaration }
  1317. list.Concat(tai_symbol.Create_Global(metasym,0));
  1318. { the isa }
  1319. list.Concat(Tai_const.Create_sym(metaisaSym));
  1320. { the superclass }
  1321. list.Concat(Tai_const.Create_sym(superMetaSym));
  1322. { pointer to cache }
  1323. if not assigned(ObjCEmptyCacheVar) then
  1324. ObjCEmptyCacheVar:=current_asmdata.RefAsmSymbol(target_info.Cprefix+'_objc_empty_cache');
  1325. list.Concat(Tai_const.Create_sym(ObjCEmptyCacheVar));
  1326. { pointer to vtable }
  1327. if not assigned(ObjCEmptyVtableVar) then
  1328. ObjCEmptyVtableVar:=current_asmdata.RefAsmSymbol(target_info.Cprefix+'_objc_empty_vtable');
  1329. list.Concat(Tai_const.Create_sym(ObjCEmptyVtableVar));
  1330. { the read-only part }
  1331. list.Concat(Tai_const.Create_sym(metarosym));
  1332. { 2) regular class declaration }
  1333. list.Concat(tai_symbol.Create_Global(clssym,0));
  1334. { the isa }
  1335. list.Concat(Tai_const.Create_sym(metasym));
  1336. { the superclass }
  1337. list.Concat(Tai_const.Create_sym(superSym));
  1338. { pointer to cache }
  1339. list.Concat(Tai_const.Create_sym(ObjCEmptyCacheVar));
  1340. { pointer to vtable }
  1341. list.Concat(Tai_const.Create_sym(ObjCEmptyVtableVar));
  1342. { the read-only part }
  1343. list.Concat(Tai_const.Create_sym(rosym));
  1344. classlabel:=clssym;
  1345. end;
  1346. procedure tobjcrttiwriter_nonfragile.addclasslist(list: tasmlist; section: tasmsectiontype; const symname: string; classes: tfpobjectlist);
  1347. var
  1348. i: longint;
  1349. sym: TAsmSymbol;
  1350. begin
  1351. if classes.count=0 then
  1352. exit;
  1353. new_section(list,section,symname,sizeof(pint));
  1354. sym:=current_asmdata.DefineAsmSymbol(symname,AB_LOCAL,AT_DATA);
  1355. list.concat(tai_symbol.Create(sym,0));
  1356. for i:=0 to classes.count-1 do
  1357. list.concat(tai_const.Create_sym(current_asmdata.RefAsmSymbol(tobjectdef(classes[i]).rtti_mangledname(objcclassrtti))));
  1358. end;
  1359. procedure tobjcrttiwriter_nonfragile.gen_objc_info_sections(list: tasmlist);
  1360. function collectnonlazyclasses(classes: tfpobjectlist): tfpobjectlist;
  1361. var
  1362. symentry : tsym;
  1363. procdef : tprocdef;
  1364. i,j : longint;
  1365. begin
  1366. { non-lazy classes are all classes that define a class method with the
  1367. selector called "load" (simply inheriting this class method is not enough,
  1368. they have to implement it themselves)
  1369. -- TODO: this currently only works if the Pascal identifier is also 'load'! }
  1370. result:=tfpobjectlist.create(false);
  1371. for i:=0 to classes.count-1 do
  1372. begin
  1373. symentry:=tsym(tobjectsymtable(tobjectdef(classes[i]).symtable).find('LOAD'));
  1374. if assigned(symentry) and
  1375. (symentry.typ=procsym) then
  1376. begin
  1377. for j:=0 to tprocsym(symentry).ProcdefList.count do
  1378. begin
  1379. procdef:=tprocdef(tprocsym(symentry).ProcdefList[0]);
  1380. if ((po_classmethod in procdef.procoptions) and
  1381. (procdef.messageinf.str^='load')) then
  1382. begin
  1383. result.add(classes[i]);
  1384. break;
  1385. end;
  1386. end;
  1387. end;
  1388. end;
  1389. end;
  1390. var
  1391. nonlazyclasses,
  1392. nonlazycategories : tfpobjectlist;
  1393. begin
  1394. if (classdefs.count=0) and
  1395. (catdefs.count=0) then
  1396. exit;
  1397. nonlazyclasses:=collectnonlazyclasses(classdefs);
  1398. nonlazycategories:=collectnonlazyclasses(catdefs);
  1399. { this list has to include all classes, also the non-lazy ones }
  1400. addclasslist(list,sec_objc_classlist,target_asm.labelprefix+'_OBJC_LABEL_CLASS_$',classdefs);
  1401. addclasslist(list,sec_objc_nlclasslist,target_asm.labelprefix+'_OBJC_LABEL_NONLAZY_CLASS_$',nonlazyclasses);
  1402. { category and non-lazy category lists }
  1403. addclasslist(list,sec_objc_catlist,target_asm.labelprefix+'_OBJC_LABEL_CATEGORY_$',catdefs);
  1404. addclasslist(list,sec_objc_nlcatlist,target_asm.labelprefix+'_OBJC_LABEL_NONLAZY_CATEGORY_$',nonlazycategories);
  1405. nonlazyclasses.free;
  1406. nonlazycategories.free;
  1407. { the non-fragile abi doesn't have any module info, nor lazy references
  1408. to used classes or to parent classes }
  1409. end;
  1410. constructor tobjcrttiwriter_nonfragile.create;
  1411. begin
  1412. inherited create(oa_nonfragile);
  1413. end;
  1414. {******************************************************************
  1415. RTTI generation -- Main function
  1416. *******************************************************************}
  1417. procedure MaybeGenerateObjectiveCImageInfo(globalst, localst: tsymtable);
  1418. var
  1419. objcrttiwriter: tobjcrttiwriter;
  1420. begin
  1421. if (m_objectivec1 in current_settings.modeswitches) then
  1422. begin
  1423. { first 4 bytes contain version information about this section (currently version 0),
  1424. next 4 bytes contain flags (currently only regarding whether the code in the object
  1425. file supports or requires garbage collection)
  1426. }
  1427. new_section(current_asmdata.asmlists[al_objc_data],sec_objc_image_info,'_OBJC_IMAGE_INFO',sizeof(pint));
  1428. current_asmdata.asmlists[al_objc_data].concat(Tai_symbol.Createname(target_asm.labelprefix+'_OBJC_IMAGE_INFO',AT_LABEL,sizeof(pint)));
  1429. current_asmdata.asmlists[al_objc_data].concat(Tai_const.Create_64bit(0));
  1430. { generate rtti for all obj-c classes, protocols and categories
  1431. defined in this module. }
  1432. if not(target_info.system in systems_objc_nfabi) then
  1433. objcrttiwriter:=tobjcrttiwriter_fragile.create
  1434. else
  1435. objcrttiwriter:=tobjcrttiwriter_nonfragile.create;
  1436. objcrttiwriter.gen_objc_rtti_sections(current_asmdata.asmlists[al_objc_data],globalst);
  1437. objcrttiwriter.gen_objc_rtti_sections(current_asmdata.asmlists[al_objc_data],localst);
  1438. objcrttiwriter.gen_objc_info_sections(current_asmdata.asmlists[al_objc_data]);
  1439. objcrttiwriter.free;
  1440. end;
  1441. end;
  1442. end.