objcgutl.pas 58 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630
  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. list.Concat(tai_directive.Create(asd_weak_definition,lbl.name));
  997. protocollabel:=lbl;
  998. { protocol's isa - always nil }
  999. list.Concat(Tai_const.Create_pint(0));
  1000. { name }
  1001. namesym:=objcreatestringpoolentry(protocol.objextname^,sp_objcclassnames,sec_objc_class_names);
  1002. list.Concat(Tai_const.Create_sym(namesym));
  1003. { parent protocols list }
  1004. ConcatSymOrNil(list,protolist);
  1005. { required instance methods }
  1006. ConcatSymOrNil(list,reqinstsym);
  1007. { required class methods }
  1008. ConcatSymOrNil(list,reqclssym);
  1009. { optional instance methods }
  1010. ConcatSymOrNil(list,optinstsym);
  1011. { optional class methods }
  1012. ConcatSymOrNil(list,optclssym);
  1013. { TODO: properties }
  1014. list.Concat(Tai_const.Create_pint(0));
  1015. { size of this type }
  1016. prottype:=search_named_unit_globaltype('OBJC','OBJC_PROTOCOL',true).typedef;
  1017. list.concat(tai_const.Create_32bit(prottype.size));
  1018. { flags }
  1019. list.concat(tai_const.Create_32bit(0));
  1020. { also add an entry to the __DATA, __objc_protolist section, required to
  1021. register the protocol with the runtime }
  1022. new_section(list, sec_objc_protolist,'_OBJC_PROTOLIST',sizeof(pint));
  1023. listsym:=current_asmdata.DefineAsmSymbol(protocol.rtti_mangledname(objcmetartti),AB_PRIVATE_EXTERN,AT_DATA);
  1024. list.Concat(tai_symbol.Create_Global(listsym,0));
  1025. list.Concat(tai_const.Create_sym(lbl));
  1026. list.Concat(tai_directive.Create(asd_weak_definition,listsym.name));
  1027. end;
  1028. (*
  1029. From Clang:
  1030. /// struct _category_t {
  1031. /// const char * const name;
  1032. /// struct _class_t *const cls;
  1033. /// const struct _method_list_t * const instance_methods;
  1034. /// const struct _method_list_t * const class_methods;
  1035. /// const struct _protocol_list_t * const protocols;
  1036. /// const struct _prop_list_t * const properties;
  1037. /// }
  1038. *)
  1039. procedure tobjcrttiwriter_nonfragile.gen_objc_category_sections(list:TAsmList; objccat: tobjectdef; out catlabel: TAsmSymbol);
  1040. var
  1041. instmthdlist,
  1042. clsmthdlist,
  1043. protolistsym : TAsmLabel;
  1044. catstrsym,
  1045. clssym,
  1046. catsym : TAsmSymbol;
  1047. begin
  1048. { the category name }
  1049. catstrsym:=objcreatestringpoolentry(objccat.objextname^,sp_objcclassnames,sec_objc_class_names);
  1050. { the class it extends }
  1051. clssym:=current_asmdata.RefAsmSymbol(objccat.childof.rtti_mangledname(objcclassrtti));
  1052. { generate the methods lists }
  1053. gen_objc_methods(list,objccat,instmthdlist,false,true);
  1054. gen_objc_methods(list,objccat,clsmthdlist,true,true);
  1055. { generate implemented protocols list }
  1056. gen_objc_protocol_list(list,objccat.ImplementedInterfaces,protolistsym);
  1057. { category declaration section }
  1058. new_section(list,sec_objc_const,'_OBJC_CATEGORY',sizeof(pint));
  1059. catsym:=current_asmdata.DefineAsmSymbol(objccat.rtti_mangledname(objcclassrtti),AB_LOCAL,AT_DATA);
  1060. list.Concat(tai_symbol.Create(catsym,0));
  1061. list.Concat(Tai_const.Create_sym(catstrsym));
  1062. list.Concat(Tai_const.Create_sym(clssym));
  1063. ConcatSymOrNil(list,instmthdlist);
  1064. ConcatSymOrNil(list,clsmthdlist);
  1065. ConcatSymOrNil(list,protolistsym);
  1066. { properties, not yet supported }
  1067. list.Concat(Tai_const.Create_pint(0));
  1068. catlabel:=catsym;
  1069. end;
  1070. (*
  1071. From Clang:
  1072. /// BuildIvarLayout - Builds ivar layout bitmap for the class
  1073. /// implementation for the __strong or __weak case.
  1074. /// The layout map displays which words in ivar list must be skipped
  1075. /// and which must be scanned by GC (see below). String is built of bytes.
  1076. /// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
  1077. /// of words to skip and right nibble is count of words to scan. So, each
  1078. /// nibble represents up to 15 workds to skip or scan. Skipping the rest is
  1079. /// represented by a 0x00 byte which also ends the string.
  1080. /// 1. when ForStrongLayout is true, following ivars are scanned:
  1081. /// - id, Class
  1082. /// - object * // note: this "object" means "Objective-C object" (JM)
  1083. /// - __strong anything
  1084. ///
  1085. /// 2. When ForStrongLayout is false, following ivars are scanned:
  1086. /// - __weak anything
  1087. *)
  1088. (*
  1089. Only required when supporting garbage collection
  1090. procedure tobjcrttiwriter_nonfragile.gen_objc_ivargc_recursive(st: tabstractrecordsymtable; ptrbset: tbitset; startoffset: puint; il: tivarlayouttype);
  1091. var
  1092. i: longint;
  1093. fs: tfieldvarsym;
  1094. includelen: longint;
  1095. begin
  1096. for i:=0 to st.SymList.count-1 do
  1097. if (tsym(st.symlist[i]).typ=fieldvarsym) then
  1098. begin
  1099. fs:=tfieldvarsym(st.symlist[i]);
  1100. includelen:=0;
  1101. case fs.vardef.typ of
  1102. pointerdef,
  1103. classrefdef:
  1104. if (fs.vardef=objc_idtype) or
  1105. (fs.vardef=objc_metaclasstype) then
  1106. includelen:=1;
  1107. recorddef:
  1108. TODO: bitpacking -> offset differences
  1109. gen_objc_ivargc_recursive(tabstractrecordsymtable(trecorddef(fs.vardef).symtable),ptrbset,startoffset+fs.fieldoffset,il);
  1110. arraydef:
  1111. begin
  1112. if not is_special_
  1113. end;
  1114. objectdef :
  1115. begin
  1116. case tobjectdef(fs.vardef).objecttype of
  1117. odt_objcclass,
  1118. odt_objcprotocol:
  1119. includelen:=1;
  1120. odt_object:
  1121. gen_objc_ivargc_recursive(tabstractrecordsymtable(tobjectdef(fs.vardef).symtable),ptrbset,startoffset+fs.fieldoffset,il);
  1122. end;
  1123. end;
  1124. end;
  1125. end;
  1126. end;
  1127. function tobjcrttiwriter_nonfragile.gen_objc_ivargcstring(objclss: tobjectdef; il: tivarlayouttype): ansistring;
  1128. var
  1129. ptrbset: tbitset;
  1130. parent: tobjectdef;
  1131. size,
  1132. startoffset: puint;
  1133. i: longint;
  1134. begin
  1135. size:=tObjectSymtable(objclss.symtable).datasize;
  1136. if assigned(objclss.childof) then
  1137. startoffset:=tObjectSymtable(objclss.childof.symtable).datasize
  1138. else
  1139. startoffset:=0;
  1140. size:=size-startoffset;
  1141. ptrbset:=tbitset.create_bytesize((size+sizeof(ptruint)-1) div sizeof(ptruint));
  1142. { has to include info for this class' fields and those of all parent
  1143. classes as well
  1144. }
  1145. parent:=obclss;
  1146. repeat
  1147. gen_objc_ivargc_recursive(parent.symtable,ptrbset,0,il);
  1148. parent:=parent.childof;
  1149. until not assigned(parent);
  1150. { convert bits set to encoded string }
  1151. end;
  1152. *)
  1153. (*
  1154. From Clang:
  1155. /// struct _class_ro_t {
  1156. /// uint32_t const flags;
  1157. /// uint32_t const instanceStart;
  1158. /// uint32_t const instanceSize;
  1159. /// uint32_t const reserved; // only when building for 64bit targets
  1160. /// const uint8_t * const ivarLayout;
  1161. /// const char *const name;
  1162. /// const struct _method_list_t * const baseMethods;
  1163. /// const struct _protocol_list_t *const baseProtocols;
  1164. /// const struct _ivar_list_t *const ivars;
  1165. /// const uint8_t * const weakIvarLayout;
  1166. /// const struct _prop_list_t * const properties;
  1167. /// }
  1168. *)
  1169. procedure tobjcrttiwriter_nonfragile.gen_objc_class_ro_part(list: tasmlist; objclss: tobjectdef; protolistsym: TAsmSymbol; out classrolabel: tasmsymbol; metaclass: boolean);
  1170. const
  1171. CLS_CLASS = 0;
  1172. CLS_META = 1;
  1173. CLS_ROOT = 2;
  1174. OBJC2_CLS_HIDDEN = $10;
  1175. CLS_EXCEPTION = $20;
  1176. var
  1177. classStrSym,
  1178. rosym : TAsmSymbol;
  1179. methodslab,
  1180. ivarslab : TAsmLabel;
  1181. class_type : tdef;
  1182. start,
  1183. size,
  1184. flags : cardinal;
  1185. rttitype : trttitype;
  1186. firstfield : tfieldvarsym;
  1187. i : longint;
  1188. begin
  1189. { consider every class declared in the implementation section of a unit
  1190. as "hidden"
  1191. }
  1192. flags:=0;
  1193. if (objclss.owner.symtabletype=staticsymtable) and
  1194. current_module.is_unit then
  1195. flags:=OBJC2_CLS_HIDDEN;
  1196. if metaclass then
  1197. begin
  1198. flags:=flags or CLS_META;
  1199. rttitype:=objcmetarortti;
  1200. { metaclass size/start: always size of objc_object }
  1201. class_type:=search_named_unit_globaltype('OBJC','OBJC_OBJECT',true).typedef;
  1202. start:=class_type.size;
  1203. size:=start;
  1204. end
  1205. else
  1206. begin
  1207. flags:=flags or CLS_CLASS;
  1208. rttitype:=objcclassrortti;
  1209. size:=tObjectSymtable(objclss.symtable).datasize;
  1210. { can't simply use childof's datasize, because alignment may cause the
  1211. first field to skip a couple of bytes after the previous end }
  1212. firstfield:=nil;
  1213. for i:=0 to objclss.symtable.SymList.Count-1 do
  1214. if (tsym(objclss.symtable.SymList[i]).typ=fieldvarsym) then
  1215. begin
  1216. firstfield:=tfieldvarsym(objclss.symtable.SymList[i]);
  1217. break;
  1218. end;
  1219. if assigned(firstfield) then
  1220. start:=firstfield.fieldoffset
  1221. else
  1222. { no extra fields -> start = size }
  1223. start:=size;
  1224. end;
  1225. if not assigned(objclss.childof) then
  1226. flags:=flags or CLS_ROOT;
  1227. classStrSym:=objcreatestringpoolentry(objclss.objextname^,sp_objcclassnames,sec_objc_class_names);
  1228. { generate methods list }
  1229. gen_objc_methods(list,objclss,methodslab,metaclass,false);
  1230. { generate ivars (nil for metaclass) }
  1231. if metaclass then
  1232. ivarslab:=nil
  1233. else
  1234. gen_objc_ivars(list,objclss,ivarslab);
  1235. { class declaration section }
  1236. new_section(list,sec_objc_const,'_OBJC_META_CLASS',sizeof(pint));
  1237. rosym:=current_asmdata.DefineAsmSymbol(objclss.rtti_mangledname(rttitype),AB_LOCAL,AT_DATA);
  1238. classrolabel:=rosym;
  1239. list.Concat(tai_symbol.create(rosym,0));
  1240. list.Concat(tai_const.Create_32bit(longint(flags)));
  1241. list.Concat(tai_const.Create_32bit(longint(start)));
  1242. list.Concat(tai_const.Create_32bit(longint(size)));
  1243. {$ifdef cpu64bitaddr}
  1244. { alignment }
  1245. list.Concat(tai_const.Create_32bit(0));
  1246. {$endif}
  1247. { TODO: strong ivar layout for garbage collection }
  1248. list.concat(tai_const.Create_pint(0));
  1249. list.concat(tai_const.Create_sym(classStrSym));
  1250. ConcatSymOrNil(list,methodslab);
  1251. ConcatSymOrNil(list,protolistsym);
  1252. ConcatSymOrNil(list,ivarslab);
  1253. { TODO: weak ivar layout for garbage collection }
  1254. list.concat(tai_const.Create_pint(0));
  1255. { TODO: properties }
  1256. list.concat(tai_const.Create_pint(0));
  1257. end;
  1258. (*
  1259. From Clang:
  1260. /// struct _class_t {
  1261. /// struct _class_t *isa;
  1262. /// struct _class_t * const superclass;
  1263. /// void *cache;
  1264. /// IMP *vtable;
  1265. /// struct class_ro_t *ro;
  1266. /// }
  1267. ///
  1268. *)
  1269. { Generate rtti for an Objective-C class and its meta-class. }
  1270. procedure tobjcrttiwriter_nonfragile.gen_objc_classes_sections(list:TAsmList; objclss: tobjectdef; out classlabel: TAsmSymbol);
  1271. var
  1272. root : tobjectdef;
  1273. superSym,
  1274. superMetaSym,
  1275. metaisaSym,
  1276. metasym,
  1277. clssym,
  1278. metarosym,
  1279. rosym : TAsmSymbol;
  1280. protolistsym : TAsmLabel;
  1281. vis : TAsmsymbind;
  1282. begin
  1283. { A) Register necessary names }
  1284. { 1) the current class and metaclass }
  1285. if (objclss.owner.symtabletype=globalsymtable) then
  1286. vis:=AB_GLOBAL
  1287. else
  1288. vis:=AB_PRIVATE_EXTERN;
  1289. clssym:=current_asmdata.DefineAsmSymbol(objclss.rtti_mangledname(objcclassrtti),vis,AT_DATA);
  1290. metasym:=current_asmdata.DefineAsmSymbol(objclss.rtti_mangledname(objcmetartti),vis,AT_DATA);
  1291. { 2) the superclass and meta superclass }
  1292. if assigned(objclss.childof) then
  1293. begin
  1294. superSym:=current_asmdata.RefAsmSymbol(objclss.childof.rtti_mangledname(objcclassrtti));
  1295. superMetaSym:=current_asmdata.RefAsmSymbol(objclss.childof.rtti_mangledname(objcmetartti));
  1296. end
  1297. else
  1298. begin
  1299. superSym:=nil;
  1300. { the class itself }
  1301. superMetaSym:=clssym;
  1302. end;
  1303. { 3) the isa }
  1304. { From Clang: The isa for the meta-class is the root of the hierarchy. }
  1305. root:=objclss;
  1306. while assigned(root.childof) do
  1307. root:=root.childof;
  1308. metaisaSym:=current_asmdata.RefAsmSymbol(root.rtti_mangledname(objcmetartti));
  1309. { 4) the implemented protocols (same for metaclass and regular class) }
  1310. gen_objc_protocol_list(list,objclss.ImplementedInterfaces,protolistsym);
  1311. { 5) the read-only parts of the class definitions }
  1312. gen_objc_class_ro_part(list,objclss,protolistsym,metarosym,true);
  1313. gen_objc_class_ro_part(list,objclss,protolistsym,rosym,false);
  1314. { B) Class declaration section }
  1315. { both class and metaclass are in the objc_data section for obj-c 2 }
  1316. new_section(list,sec_objc_data,'_OBJC_CLASS',sizeof(pint));
  1317. { 1) meta-class declaration }
  1318. list.Concat(tai_symbol.Create_Global(metasym,0));
  1319. { the isa }
  1320. list.Concat(Tai_const.Create_sym(metaisaSym));
  1321. { the superclass }
  1322. list.Concat(Tai_const.Create_sym(superMetaSym));
  1323. { pointer to cache }
  1324. if not assigned(ObjCEmptyCacheVar) then
  1325. ObjCEmptyCacheVar:=current_asmdata.RefAsmSymbol(target_info.Cprefix+'_objc_empty_cache');
  1326. list.Concat(Tai_const.Create_sym(ObjCEmptyCacheVar));
  1327. { pointer to vtable }
  1328. if not assigned(ObjCEmptyVtableVar) then
  1329. ObjCEmptyVtableVar:=current_asmdata.RefAsmSymbol(target_info.Cprefix+'_objc_empty_vtable');
  1330. list.Concat(Tai_const.Create_sym(ObjCEmptyVtableVar));
  1331. { the read-only part }
  1332. list.Concat(Tai_const.Create_sym(metarosym));
  1333. { 2) regular class declaration }
  1334. list.Concat(tai_symbol.Create_Global(clssym,0));
  1335. { the isa }
  1336. list.Concat(Tai_const.Create_sym(metasym));
  1337. { the superclass }
  1338. list.Concat(Tai_const.Create_sym(superSym));
  1339. { pointer to cache }
  1340. list.Concat(Tai_const.Create_sym(ObjCEmptyCacheVar));
  1341. { pointer to vtable }
  1342. list.Concat(Tai_const.Create_sym(ObjCEmptyVtableVar));
  1343. { the read-only part }
  1344. list.Concat(Tai_const.Create_sym(rosym));
  1345. classlabel:=clssym;
  1346. end;
  1347. procedure tobjcrttiwriter_nonfragile.addclasslist(list: tasmlist; section: tasmsectiontype; const symname: string; classes: tfpobjectlist);
  1348. var
  1349. i: longint;
  1350. sym: TAsmSymbol;
  1351. begin
  1352. if classes.count=0 then
  1353. exit;
  1354. new_section(list,section,symname,sizeof(pint));
  1355. sym:=current_asmdata.DefineAsmSymbol(symname,AB_LOCAL,AT_DATA);
  1356. list.concat(tai_symbol.Create(sym,0));
  1357. for i:=0 to classes.count-1 do
  1358. list.concat(tai_const.Create_sym(current_asmdata.RefAsmSymbol(tobjectdef(classes[i]).rtti_mangledname(objcclassrtti))));
  1359. end;
  1360. procedure tobjcrttiwriter_nonfragile.gen_objc_info_sections(list: tasmlist);
  1361. function collectnonlazyclasses(classes: tfpobjectlist): tfpobjectlist;
  1362. var
  1363. symentry : tsym;
  1364. procdef : tprocdef;
  1365. i,j : longint;
  1366. begin
  1367. { non-lazy classes are all classes that define a class method with the
  1368. selector called "load" (simply inheriting this class method is not enough,
  1369. they have to implement it themselves)
  1370. -- TODO: this currently only works if the Pascal identifier is also 'load'! }
  1371. result:=tfpobjectlist.create(false);
  1372. for i:=0 to classes.count-1 do
  1373. begin
  1374. symentry:=tsym(tobjectsymtable(tobjectdef(classes[i]).symtable).find('LOAD'));
  1375. if assigned(symentry) and
  1376. (symentry.typ=procsym) then
  1377. begin
  1378. for j:=0 to tprocsym(symentry).ProcdefList.count do
  1379. begin
  1380. procdef:=tprocdef(tprocsym(symentry).ProcdefList[0]);
  1381. if ((po_classmethod in procdef.procoptions) and
  1382. (procdef.messageinf.str^='load')) then
  1383. begin
  1384. result.add(classes[i]);
  1385. break;
  1386. end;
  1387. end;
  1388. end;
  1389. end;
  1390. end;
  1391. var
  1392. nonlazyclasses,
  1393. nonlazycategories : tfpobjectlist;
  1394. begin
  1395. if (classdefs.count=0) and
  1396. (catdefs.count=0) then
  1397. exit;
  1398. nonlazyclasses:=collectnonlazyclasses(classdefs);
  1399. nonlazycategories:=collectnonlazyclasses(catdefs);
  1400. { this list has to include all classes, also the non-lazy ones }
  1401. addclasslist(list,sec_objc_classlist,target_asm.labelprefix+'_OBJC_LABEL_CLASS_$',classdefs);
  1402. addclasslist(list,sec_objc_nlclasslist,target_asm.labelprefix+'_OBJC_LABEL_NONLAZY_CLASS_$',nonlazyclasses);
  1403. { category and non-lazy category lists }
  1404. addclasslist(list,sec_objc_catlist,target_asm.labelprefix+'_OBJC_LABEL_CATEGORY_$',catdefs);
  1405. addclasslist(list,sec_objc_nlcatlist,target_asm.labelprefix+'_OBJC_LABEL_NONLAZY_CATEGORY_$',nonlazycategories);
  1406. nonlazyclasses.free;
  1407. nonlazycategories.free;
  1408. { the non-fragile abi doesn't have any module info, nor lazy references
  1409. to used classes or to parent classes }
  1410. end;
  1411. constructor tobjcrttiwriter_nonfragile.create;
  1412. begin
  1413. inherited create(oa_nonfragile);
  1414. end;
  1415. {******************************************************************
  1416. RTTI generation -- Main function
  1417. *******************************************************************}
  1418. procedure MaybeGenerateObjectiveCImageInfo(globalst, localst: tsymtable);
  1419. var
  1420. objcrttiwriter: tobjcrttiwriter;
  1421. begin
  1422. if (m_objectivec1 in current_settings.modeswitches) then
  1423. begin
  1424. { first 4 bytes contain version information about this section (currently version 0),
  1425. next 4 bytes contain flags (currently only regarding whether the code in the object
  1426. file supports or requires garbage collection)
  1427. }
  1428. new_section(current_asmdata.asmlists[al_objc_data],sec_objc_image_info,'_OBJC_IMAGE_INFO',sizeof(pint));
  1429. current_asmdata.asmlists[al_objc_data].concat(Tai_symbol.Createname(target_asm.labelprefix+'_OBJC_IMAGE_INFO',AT_LABEL,sizeof(pint)));
  1430. current_asmdata.asmlists[al_objc_data].concat(Tai_const.Create_64bit(0));
  1431. { generate rtti for all obj-c classes, protocols and categories
  1432. defined in this module. }
  1433. if not(target_info.system in systems_objc_nfabi) then
  1434. objcrttiwriter:=tobjcrttiwriter_fragile.create
  1435. else
  1436. objcrttiwriter:=tobjcrttiwriter_nonfragile.create;
  1437. objcrttiwriter.gen_objc_rtti_sections(current_asmdata.asmlists[al_objc_data],globalst);
  1438. objcrttiwriter.gen_objc_rtti_sections(current_asmdata.asmlists[al_objc_data],localst);
  1439. objcrttiwriter.gen_objc_info_sections(current_asmdata.asmlists[al_objc_data]);
  1440. objcrttiwriter.free;
  1441. end;
  1442. end;
  1443. end.