* 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 -
This commit is contained in:
Jonas Maebe 2009-09-08 16:05:41 +00:00
parent cd24bb4df6
commit e393446769
6 changed files with 75 additions and 19 deletions

View File

@ -254,7 +254,7 @@ interface
TAsmDirective=( TAsmDirective=(
asd_non_lazy_symbol_pointer,asd_indirect_symbol,asd_lazy_symbol_pointer, 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_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 const
@ -264,7 +264,7 @@ interface
directivestr : array[TAsmDirective] of string[23]=( directivestr : array[TAsmDirective] of string[23]=(
'non_lazy_symbol_pointer','indirect_symbol','lazy_symbol_pointer', 'non_lazy_symbol_pointer','indirect_symbol','lazy_symbol_pointer',
'extern','nasm_import', 'tc', 'mod_init_func', 'mod_term_func', 'reference', 'extern','nasm_import', 'tc', 'mod_init_func', 'mod_term_func', 'reference',
'no_dead_strip','weak_reference' 'no_dead_strip','weak_reference','lazy_reference'
); );
type type
@ -313,13 +313,16 @@ interface
{ Generates a common label } { Generates a common label }
tai_symbol = class(tai) tai_symbol = class(tai)
is_global : boolean;
sym : tasmsymbol; sym : tasmsymbol;
value : puint;
size : longint; size : longint;
is_global,
has_value : boolean;
constructor Create(_sym:tasmsymbol;siz:longint); constructor Create(_sym:tasmsymbol;siz:longint);
constructor Create_Global(_sym:tasmsymbol;siz:longint); constructor Create_Global(_sym:tasmsymbol;siz:longint);
constructor Createname(const _name : string;_symtyp:Tasmsymtype;siz:longint); constructor Createname(const _name : string;_symtyp:Tasmsymtype;siz:longint);
constructor Createname_global(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; constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
procedure ppuwrite(ppufile:tcompilerppufile);override; procedure ppuwrite(ppufile:tcompilerppufile);override;
procedure derefimpl;override; procedure derefimpl;override;
@ -946,6 +949,14 @@ implementation
end; 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); constructor tai_symbol.ppuload(t:taitype;ppufile:tcompilerppufile);
begin begin
inherited ppuload(t,ppufile); inherited ppuload(t,ppufile);

View File

@ -1042,7 +1042,10 @@ implementation
AsmWriteLn(',' + sepChar + 'function'); AsmWriteLn(',' + sepChar + 'function');
end; end;
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; end;
ait_symbol_end : ait_symbol_end :

View File

@ -992,7 +992,12 @@ Implementation
Tai_section(hp).sec:=ObjData.CurrObjSec; Tai_section(hp).sec:=ObjData.CurrObjSec;
end; end;
ait_symbol : 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 : ait_label :
ObjData.SymbolDefine(Tai_label(hp).labsym); ObjData.SymbolDefine(Tai_label(hp).labsym);
ait_string : ait_string :

View File

@ -895,6 +895,8 @@ interface
ait_symbol : ait_symbol :
begin begin
if tai_symbol(hp).has_value then
internalerror(2009090803);
if tai_symbol(hp).is_global then if tai_symbol(hp).is_global then
begin begin
AsmWrite(#9'GLOBAL '); AsmWrite(#9'GLOBAL ');

View File

@ -89,6 +89,7 @@ procedure objcfinishstringrefpoolentry(entry: phashsetitem; stringpool: tconstpo
var var
reflab : tasmlabel; reflab : tasmlabel;
strlab : tasmsymbol; strlab : tasmsymbol;
classname: string;
begin begin
{ have we already generated a reference for this string entry? } { have we already generated a reference for this string entry? }
if not assigned(entry^.Data) then 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)); 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_label.Create(reflab));
current_asmdata.asmlists[al_objc_pools].concat(Tai_const.Create_sym(strlab)); 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; 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 { Generate the rtti sections for all obj-c classes defined in st, and return
these classes in the classes list. } 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 var
i: longint; i: longint;
def: tdef; 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 not(oo_is_external in tobjectdef(def).objectoptions) then
begin begin
gen_objc1_classes_sections(list,tobjectdef(def),sym); gen_objc1_classes_sections(list,tobjectdef(def),sym);
classes.add(sym); classsyms.add(sym);
classdefs.add(def);
end; end;
end; 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) { Generate the global information sections (objc_symbols and objc_module_info)
for this module. } for this module. }
procedure gen_objc1_info_sections(list: tasmlist; classes: tfpobjectlist); procedure gen_objc1_info_sections(list: tasmlist; classsyms,classdefs: tfpobjectlist);
var var
i: longint; i: longint;
sym : TAsmSymbol; sym : TAsmSymbol;
parent: tobjectdef;
superclasses: tfpobjectlist;
begin begin
if (classes.count<>0) then if (classsyms.count<>0) then
begin begin
new_section(list,sec_objc_symbols,'_OBJC_SYMBOLS',sizeof(pint)); new_section(list,sec_objc_symbols,'_OBJC_SYMBOLS',sizeof(pint));
sym := current_asmdata.RefAsmSymbol(target_asm.labelprefix+'_OBJC_SYMBOLS'); 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) } { ??? (From Clang: always 0, pointer to some selector) }
list.Concat(Tai_const.Create_pint(0)); list.Concat(Tai_const.Create_pint(0));
{ From Clang: number of defined classes } { 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 } { From Clang: number of defined categories }
list.Concat(Tai_const.Create_16bit(0)); list.Concat(Tai_const.Create_16bit(0));
{ first all classes } { first all classes }
for i:=0 to classes.count-1 do for i:=0 to classsyms.count-1 do
list.Concat(Tai_const.Create_sym(tasmsymbol(classes[i]))); list.Concat(Tai_const.Create_sym(tasmsymbol(classsyms[i])));
{ then all categories } { then all categories }
end end
else else
@ -451,12 +464,30 @@ procedure gen_objc1_info_sections(list: tasmlist; classes: tfpobjectlist);
list.Concat(Tai_const.Create_sym(sym)) list.Concat(Tai_const.Create_sym(sym))
else else
list.concat(tai_const.create_pint(0)); 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; end;
procedure MaybeGenerateObjectiveCImageInfo(globalst, localst: tsymtable); procedure MaybeGenerateObjectiveCImageInfo(globalst, localst: tsymtable);
var var
classes: tfpobjectlist; classsyms,
classdefs: tfpobjectlist;
begin begin
if (m_objectivec1 in current_settings.modeswitches) then if (m_objectivec1 in current_settings.modeswitches) then
begin begin
@ -470,11 +501,13 @@ procedure MaybeGenerateObjectiveCImageInfo(globalst, localst: tsymtable);
{ generate rtti for all obj-c classes, protocols (todo) and categories (todo) { generate rtti for all obj-c classes, protocols (todo) and categories (todo)
defined in this module. } defined in this module. }
classes:=tfpobjectlist.create(false); classsyms:=tfpobjectlist.create(false);
gen_objc1_rtti_sections(current_asmdata.asmlists[al_objc_data],globalst,classes); classdefs:=tfpobjectlist.create(false);
gen_objc1_rtti_sections(current_asmdata.asmlists[al_objc_data],localst,classes); gen_objc1_rtti_sections(current_asmdata.asmlists[al_objc_data],globalst,classsyms,classdefs);
gen_objc1_info_sections(current_asmdata.asmlists[al_objc_data],classes); gen_objc1_rtti_sections(current_asmdata.asmlists[al_objc_data],localst,classsyms,classdefs);
classes.free; gen_objc1_info_sections(current_asmdata.asmlists[al_objc_data],classsyms,classdefs);
classsyms.free;
classdefs.free;
end; end;
end; end;

View File

@ -705,6 +705,8 @@ implementation
end; end;
ait_symbol : ait_symbol :
begin begin
if tai_symbol(hp).has_value then
internalerror(2009090802);
if tai_symbol(hp).is_global then if tai_symbol(hp).is_global then
AsmWriteLn(#9'PUBLIC'#9+tai_symbol(hp).sym.name); AsmWriteLn(#9'PUBLIC'#9+tai_symbol(hp).sym.name);
AsmWrite(tai_symbol(hp).sym.name); AsmWrite(tai_symbol(hp).sym.name);