From e393446769091d8675cf7efd793c53eaf826e4ed Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Tue, 8 Sep 2009 16:05:41 +0000 Subject: [PATCH] * fixed several omissions that could cause the dynamic linker not to register required classes: + add lazy references to classes referred to in the current unit + define reference symbols for classes defined in the current unit + add lazy references to parent classes of classes defined in the current unit git-svn-id: branches/objc@13679 - --- compiler/aasmtai.pas | 17 +++++++++-- compiler/aggas.pas | 5 +++- compiler/assemble.pas | 7 ++++- compiler/i386/ag386nsm.pas | 2 ++ compiler/objcgutl.pas | 61 +++++++++++++++++++++++++++++--------- compiler/x86/agx86int.pas | 2 ++ 6 files changed, 75 insertions(+), 19 deletions(-) diff --git a/compiler/aasmtai.pas b/compiler/aasmtai.pas index 860e467058..a6a262ab95 100644 --- a/compiler/aasmtai.pas +++ b/compiler/aasmtai.pas @@ -254,7 +254,7 @@ interface TAsmDirective=( asd_non_lazy_symbol_pointer,asd_indirect_symbol,asd_lazy_symbol_pointer, asd_extern,asd_nasm_import, asd_toc_entry, asd_mod_init_func, asd_mod_term_func, - asd_reference,asd_no_dead_strip,asd_weak_reference + asd_reference,asd_no_dead_strip,asd_weak_reference,asd_lazy_reference ); const @@ -264,7 +264,7 @@ interface directivestr : array[TAsmDirective] of string[23]=( 'non_lazy_symbol_pointer','indirect_symbol','lazy_symbol_pointer', 'extern','nasm_import', 'tc', 'mod_init_func', 'mod_term_func', 'reference', - 'no_dead_strip','weak_reference' + 'no_dead_strip','weak_reference','lazy_reference' ); type @@ -313,13 +313,16 @@ interface { Generates a common label } tai_symbol = class(tai) - is_global : boolean; sym : tasmsymbol; + value : puint; size : longint; + is_global, + has_value : boolean; constructor Create(_sym:tasmsymbol;siz:longint); constructor Create_Global(_sym:tasmsymbol;siz:longint); constructor Createname(const _name : string;_symtyp:Tasmsymtype;siz:longint); constructor Createname_global(const _name : string;_symtyp:Tasmsymtype;siz:longint); + constructor Createname_global_value(const _name : string;_symtyp:Tasmsymtype;siz:longint;val:ptruint); constructor ppuload(t:taitype;ppufile:tcompilerppufile);override; procedure ppuwrite(ppufile:tcompilerppufile);override; procedure derefimpl;override; @@ -946,6 +949,14 @@ implementation end; + constructor tai_symbol.createname_global_value(const _name: string;_symtyp: tasmsymtype; siz: longint; val: ptruint); + begin + Createname_global(_name,_symtyp,siz); + value:=val; + has_value:=true; + end; + + constructor tai_symbol.ppuload(t:taitype;ppufile:tcompilerppufile); begin inherited ppuload(t,ppufile); diff --git a/compiler/aggas.pas b/compiler/aggas.pas index 3b27b755e2..ef7082ef88 100644 --- a/compiler/aggas.pas +++ b/compiler/aggas.pas @@ -1042,7 +1042,10 @@ implementation AsmWriteLn(',' + sepChar + 'function'); end; end; - AsmWriteLn(tai_symbol(hp).sym.name + ':'); + if not(tai_symbol(hp).has_value) then + AsmWriteLn(tai_symbol(hp).sym.name + ':') + else + AsmWriteLn(tai_symbol(hp).sym.name + '=' + tostr(tai_symbol(hp).value)); end; ait_symbol_end : diff --git a/compiler/assemble.pas b/compiler/assemble.pas index 17a168d818..2647c7d172 100644 --- a/compiler/assemble.pas +++ b/compiler/assemble.pas @@ -992,7 +992,12 @@ Implementation Tai_section(hp).sec:=ObjData.CurrObjSec; end; ait_symbol : - ObjData.SymbolDefine(Tai_symbol(hp).sym); + begin + { needs extra support in the internal assembler } + if tai_symbol(hp).has_value then + internalerror(2009090804); + ObjData.SymbolDefine(Tai_symbol(hp).sym); + end; ait_label : ObjData.SymbolDefine(Tai_label(hp).labsym); ait_string : diff --git a/compiler/i386/ag386nsm.pas b/compiler/i386/ag386nsm.pas index 89b343292c..75e3ec3b45 100644 --- a/compiler/i386/ag386nsm.pas +++ b/compiler/i386/ag386nsm.pas @@ -895,6 +895,8 @@ interface ait_symbol : begin + if tai_symbol(hp).has_value then + internalerror(2009090803); if tai_symbol(hp).is_global then begin AsmWrite(#9'GLOBAL '); diff --git a/compiler/objcgutl.pas b/compiler/objcgutl.pas index 33bbc78a2b..b75ef5fa7b 100644 --- a/compiler/objcgutl.pas +++ b/compiler/objcgutl.pas @@ -89,6 +89,7 @@ procedure objcfinishstringrefpoolentry(entry: phashsetitem; stringpool: tconstpo var reflab : tasmlabel; strlab : tasmsymbol; + classname: string; begin { have we already generated a reference for this string entry? } if not assigned(entry^.Data) then @@ -104,7 +105,16 @@ procedure objcfinishstringrefpoolentry(entry: phashsetitem; stringpool: tconstpo new_section(current_asmdata.asmlists[al_objc_pools],refsec,reflab.name,sizeof(pint)); current_asmdata.asmlists[al_objc_pools].concat(Tai_label.Create(reflab)); current_asmdata.asmlists[al_objc_pools].concat(Tai_const.Create_sym(strlab)); - end; + + { in case of a class reference, also add a lazy symbol reference for + the class (the linker requires this). } + if (refsec=sec_objc_cls_refs) then + begin + setlength(classname,entry^.keylength); + move(entry^.key^,classname[1],entry^.keylength); + current_asmdata.asmlists[al_objc_pools].concat(tai_directive.Create(asd_lazy_reference,'.objc_class_name_'+classname)); + end; + end; end; @@ -387,7 +397,7 @@ procedure gen_objc1_classes_sections(list:TAsmList; objclss: tobjectdef; out cla { Generate the rtti sections for all obj-c classes defined in st, and return these classes in the classes list. } -procedure gen_objc1_rtti_sections(list:TAsmList; st:TSymtable; var classes: tfpobjectlist); +procedure gen_objc1_rtti_sections(list:TAsmList; st:TSymtable; var classsyms, classdefs: tfpobjectlist); var i: longint; def: tdef; @@ -403,7 +413,8 @@ procedure gen_objc1_rtti_sections(list:TAsmList; st:TSymtable; var classes: tfpo not(oo_is_external in tobjectdef(def).objectoptions) then begin gen_objc1_classes_sections(list,tobjectdef(def),sym); - classes.add(sym); + classsyms.add(sym); + classdefs.add(def); end; end; end; @@ -411,12 +422,14 @@ procedure gen_objc1_rtti_sections(list:TAsmList; st:TSymtable; var classes: tfpo { Generate the global information sections (objc_symbols and objc_module_info) for this module. } -procedure gen_objc1_info_sections(list: tasmlist; classes: tfpobjectlist); +procedure gen_objc1_info_sections(list: tasmlist; classsyms,classdefs: tfpobjectlist); var i: longint; sym : TAsmSymbol; + parent: tobjectdef; + superclasses: tfpobjectlist; begin - if (classes.count<>0) then + if (classsyms.count<>0) then begin new_section(list,sec_objc_symbols,'_OBJC_SYMBOLS',sizeof(pint)); sym := current_asmdata.RefAsmSymbol(target_asm.labelprefix+'_OBJC_SYMBOLS'); @@ -428,12 +441,12 @@ procedure gen_objc1_info_sections(list: tasmlist; classes: tfpobjectlist); { ??? (From Clang: always 0, pointer to some selector) } list.Concat(Tai_const.Create_pint(0)); { From Clang: number of defined classes } - list.Concat(Tai_const.Create_16bit(classes.count)); + list.Concat(Tai_const.Create_16bit(classsyms.count)); { From Clang: number of defined categories } list.Concat(Tai_const.Create_16bit(0)); { first all classes } - for i:=0 to classes.count-1 do - list.Concat(Tai_const.Create_sym(tasmsymbol(classes[i]))); + for i:=0 to classsyms.count-1 do + list.Concat(Tai_const.Create_sym(tasmsymbol(classsyms[i]))); { then all categories } end else @@ -451,12 +464,30 @@ procedure gen_objc1_info_sections(list: tasmlist; classes: tfpobjectlist); list.Concat(Tai_const.Create_sym(sym)) else list.concat(tai_const.create_pint(0)); + + { Add lazy references to parent classes of all classes defined in this unit } + superclasses:=tfpobjectlist.create(false); + for i:=0 to classdefs.count-1 do + begin + parent:=tobjectdef(classdefs[i]).childof; + if assigned(parent) and + (superclasses.indexof(parent)=-1) then + begin + list.concat(tai_directive.create(asd_lazy_reference,'.objc_class_name_'+parent.objextname^)); + superclasses.add(parent); + end; + end; + superclasses.free; + { reference symbols for all classes declaredin this unit } + for i:=0 to classdefs.count-1 do + list.concat(tai_symbol.Createname_global_value('.objc_class_name_'+tobjectdef(classdefs[i]).objextname^,AT_DATA,0,0)); end; procedure MaybeGenerateObjectiveCImageInfo(globalst, localst: tsymtable); var - classes: tfpobjectlist; + classsyms, + classdefs: tfpobjectlist; begin if (m_objectivec1 in current_settings.modeswitches) then begin @@ -470,11 +501,13 @@ procedure MaybeGenerateObjectiveCImageInfo(globalst, localst: tsymtable); { generate rtti for all obj-c classes, protocols (todo) and categories (todo) defined in this module. } - classes:=tfpobjectlist.create(false); - gen_objc1_rtti_sections(current_asmdata.asmlists[al_objc_data],globalst,classes); - gen_objc1_rtti_sections(current_asmdata.asmlists[al_objc_data],localst,classes); - gen_objc1_info_sections(current_asmdata.asmlists[al_objc_data],classes); - classes.free; + classsyms:=tfpobjectlist.create(false); + classdefs:=tfpobjectlist.create(false); + gen_objc1_rtti_sections(current_asmdata.asmlists[al_objc_data],globalst,classsyms,classdefs); + gen_objc1_rtti_sections(current_asmdata.asmlists[al_objc_data],localst,classsyms,classdefs); + gen_objc1_info_sections(current_asmdata.asmlists[al_objc_data],classsyms,classdefs); + classsyms.free; + classdefs.free; end; end; diff --git a/compiler/x86/agx86int.pas b/compiler/x86/agx86int.pas index ee10e78236..35b2d9de65 100644 --- a/compiler/x86/agx86int.pas +++ b/compiler/x86/agx86int.pas @@ -705,6 +705,8 @@ implementation end; ait_symbol : begin + if tai_symbol(hp).has_value then + internalerror(2009090802); if tai_symbol(hp).is_global then AsmWriteLn(#9'PUBLIC'#9+tai_symbol(hp).sym.name); AsmWrite(tai_symbol(hp).sym.name);