Переглянути джерело

* 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 -

Jonas Maebe 16 роки тому
батько
коміт
e393446769

+ 14 - 3
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);

+ 4 - 1
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 :

+ 6 - 1
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 :

+ 2 - 0
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 ');

+ 47 - 14
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;
 

+ 2 - 0
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);