objcgutl.pas 58 KB

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