objcgutl.pas 58 KB

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