Przeglądaj źródła

+ PIC support for Darwin/ARM:
o does not use GOT
o enabled by default like for other Darwin platforms
- removed Darwin/ARM call stub support: no longer needed with current
Xcode versions (at least Xcode 4.2+), and we didn't support PIC
in them yet

git-svn-id: trunk@25325 -

Jonas Maebe 12 lat temu
rodzic
commit
4ec9ec2009
3 zmienionych plików z 54 dodań i 73 usunięć
  1. 50 71
      compiler/arm/cgcpu.pas
  2. 3 1
      compiler/arm/cpupi.pas
  3. 1 1
      compiler/systems/i_bsd.pas

+ 50 - 71
compiler/arm/cgcpu.pas

@@ -112,7 +112,6 @@ unit cgcpu;
         { clear out potential overflow bits from 8 or 16 bit operations  }
         { clear out potential overflow bits from 8 or 16 bit operations  }
         { the upper 24/16 bits of a register after an operation          }
         { the upper 24/16 bits of a register after an operation          }
         procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
         procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
-        function get_darwin_call_stub(const s: string; weak: boolean): tasmsymbol;
       end;
       end;
 
 
       { tcgarm is shared between normal arm and thumb-2 }
       { tcgarm is shared between normal arm and thumb-2 }
@@ -633,26 +632,22 @@ unit cgcpu;
           branchopcode:=A_BLX
           branchopcode:=A_BLX
         else
         else
           branchopcode:=A_BL;
           branchopcode:=A_BL;
-        if target_info.system<>system_arm_darwin then
-          begin
-            if not(weak) then
-              sym:=current_asmdata.RefAsmSymbol(s)
-            else
-              sym:=current_asmdata.WeakRefAsmSymbol(s);
-            reference_reset_symbol(r,sym,0,sizeof(pint));
-
-            if cs_create_pic in current_settings.moduleswitches then
-              begin
-                include(current_procinfo.flags,pi_needs_got);
-                r.refaddr:=addr_pic
-              end
-            else
-              r.refaddr:=addr_full;
+        if not(weak) then
+          sym:=current_asmdata.RefAsmSymbol(s)
+        else
+          sym:=current_asmdata.WeakRefAsmSymbol(s);
+        reference_reset_symbol(r,sym,0,sizeof(pint));
 
 
-            list.concat(taicpu.op_ref(branchopcode,r));
+        if (tf_pic_uses_got in target_info.flags) and
+           (cs_create_pic in current_settings.moduleswitches) then
+          begin
+            include(current_procinfo.flags,pi_needs_got);
+            r.refaddr:=addr_pic
           end
           end
         else
         else
-          list.concat(taicpu.op_sym(branchopcode,get_darwin_call_stub(s,weak)));
+          r.refaddr:=addr_full;
+
+        list.concat(taicpu.op_ref(branchopcode,r));
 {
 {
         the compiler does not properly set this flag anymore in pass 1, and
         the compiler does not properly set this flag anymore in pass 1, and
         for now we only need it after pass 2 (I hope) (JM)
         for now we only need it after pass 2 (I hope) (JM)
@@ -2126,7 +2121,8 @@ unit cgcpu;
         l : TAsmLabel;
         l : TAsmLabel;
       begin
       begin
         if (cs_create_pic in current_settings.moduleswitches) and
         if (cs_create_pic in current_settings.moduleswitches) and
-           (pi_needs_got in current_procinfo.flags) then
+           (pi_needs_got in current_procinfo.flags) and
+           (tf_pic_uses_got in target_info.flags) then
           begin
           begin
             reference_reset(ref,4);
             reference_reset(ref,4);
             current_asmdata.getdatalabel(l);
             current_asmdata.getdatalabel(l);
@@ -2203,9 +2199,9 @@ unit cgcpu;
 
 
     procedure tbasecgarm.fixref(list : TAsmList;var ref : treference);
     procedure tbasecgarm.fixref(list : TAsmList;var ref : treference);
       var
       var
-        tmpreg : tregister;
+        tmpreg, tmpreg2 : tregister;
         tmpref : treference;
         tmpref : treference;
-        l : tasmlabel;
+        l, piclabel : tasmlabel;
         indirection_done : boolean;
         indirection_done : boolean;
       begin
       begin
         { absolute symbols can't be handled directly, we've to store the symbol reference
         { absolute symbols can't be handled directly, we've to store the symbol reference
@@ -2223,6 +2219,7 @@ unit cgcpu;
         current_asmdata.getjumplabel(l);
         current_asmdata.getjumplabel(l);
         cg.a_label(current_procinfo.aktlocaldata,l);
         cg.a_label(current_procinfo.aktlocaldata,l);
         tmpref.symboldata:=current_procinfo.aktlocaldata.last;
         tmpref.symboldata:=current_procinfo.aktlocaldata.last;
+        piclabel:=nil;
 
 
         indirection_done:=false;
         indirection_done:=false;
         if assigned(ref.symbol) then
         if assigned(ref.symbol) then
@@ -2235,12 +2232,30 @@ unit cgcpu;
                   a_op_const_reg(list,OP_ADD,OS_ADDR,ref.offset,tmpreg);
                   a_op_const_reg(list,OP_ADD,OS_ADDR,ref.offset,tmpreg);
                 indirection_done:=true;
                 indirection_done:=true;
               end
               end
-            else
-              if (cs_create_pic in current_settings.moduleswitches) and
-                (tf_pic_uses_got in target_info.flags) then
+            else if (cs_create_pic in current_settings.moduleswitches) then
+              if (tf_pic_uses_got in target_info.flags) then
                 current_procinfo.aktlocaldata.concat(tai_const.Create_type_sym_offset(aitconst_got,ref.symbol,ref.offset))
                 current_procinfo.aktlocaldata.concat(tai_const.Create_type_sym_offset(aitconst_got,ref.symbol,ref.offset))
               else
               else
-                current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset))
+                begin
+                  { ideally, we would want to generate
+
+                      ldr       r1, LPICConstPool
+                    LPICLocal:
+                      ldr/str   r2,[pc,r1]
+
+                    ...
+                      LPICConstPool:
+                        .long _globsym-(LPICLocal+8)
+
+                    However, we cannot be sure that the ldr/str will follow
+                    right after the call to fixref, so we have to load the
+                    complete address already in a register.
+                  }
+                  current_asmdata.getaddrlabel(piclabel);
+                  current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_ptr,piclabel,ref.symbol,ref.offset-8));
+                end
+            else
+              current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset))
           end
           end
         else
         else
           current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset));
           current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset));
@@ -2254,8 +2269,8 @@ unit cgcpu;
             list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
             list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
 
 
             if (cs_create_pic in current_settings.moduleswitches) and
             if (cs_create_pic in current_settings.moduleswitches) and
-              (tf_pic_uses_got in target_info.flags) and
-              assigned(ref.symbol) then
+               (tf_pic_uses_got in target_info.flags) and
+               assigned(ref.symbol) then
               begin
               begin
                 reference_reset(tmpref,4);
                 reference_reset(tmpref,4);
                 tmpref.base:=current_procinfo.got;
                 tmpref.base:=current_procinfo.got;
@@ -2264,6 +2279,14 @@ unit cgcpu;
               end;
               end;
           end;
           end;
 
 
+        if assigned(piclabel) then
+          begin
+            cg.a_label(list,piclabel);
+            tmpreg2:=getaddressregister(list);
+            a_op_reg_reg_reg(list,OP_ADD,OS_ADDR,tmpreg,NR_PC,tmpreg2);
+            tmpreg:=tmpreg2
+          end;
+
         { This routine can be called with PC as base/index in case the offset
         { This routine can be called with PC as base/index in case the offset
           was too large to encode in a load/store. In that case, the entire
           was too large to encode in a load/store. In that case, the entire
           absolute expression has been re-encoded in a new constpool entry, and
           absolute expression has been re-encoded in a new constpool entry, and
@@ -3168,50 +3191,6 @@ unit cgcpu;
       end;
       end;
 
 
 
 
-    function tbasecgarm.get_darwin_call_stub(const s: string; weak: boolean): tasmsymbol;
-      var
-        stubname: string;
-        l1: tasmsymbol;
-        href: treference;
-      begin
-        stubname := 'L'+s+'$stub';
-        result := current_asmdata.getasmsymbol(stubname);
-        if assigned(result) then
-          exit;
-
-        if current_asmdata.asmlists[al_imports]=nil then
-          current_asmdata.asmlists[al_imports]:=TAsmList.create;
-
-        new_section(current_asmdata.asmlists[al_imports],sec_stub,'',4);
-        result := current_asmdata.DefineAsmSymbol(stubname,AB_LOCAL,AT_FUNCTION);
-        current_asmdata.asmlists[al_imports].concat(Tai_symbol.Create(result,0));
-        { register as a weak symbol if necessary }
-        if weak then
-          current_asmdata.weakrefasmsymbol(s);
-        current_asmdata.asmlists[al_imports].concat(tai_directive.create(asd_indirect_symbol,s));
-
-        if not(cs_create_pic in current_settings.moduleswitches) then
-          begin
-            l1 := current_asmdata.DefineAsmSymbol('L'+s+'$slp',AB_LOCAL,AT_DATA);
-            reference_reset_symbol(href,l1,0,sizeof(pint));
-            href.refaddr:=addr_full;
-            current_asmdata.asmlists[al_imports].concat(taicpu.op_reg_ref(A_LDR,NR_R12,href));
-            reference_reset_base(href,NR_R12,0,sizeof(pint));
-            current_asmdata.asmlists[al_imports].concat(taicpu.op_reg_ref(A_LDR,NR_R15,href));
-            current_asmdata.asmlists[al_imports].concat(Tai_symbol.Create(l1,0));
-            l1 := current_asmdata.DefineAsmSymbol('L'+s+'$lazy_ptr',AB_LOCAL,AT_DATA);
-            current_asmdata.asmlists[al_imports].concat(tai_const.create_sym(l1));
-          end
-        else
-          internalerror(2008100401);
-
-        new_section(current_asmdata.asmlists[al_imports],sec_data_lazy,'',sizeof(pint));
-        current_asmdata.asmlists[al_imports].concat(Tai_symbol.Create(l1,0));
-        current_asmdata.asmlists[al_imports].concat(tai_directive.create(asd_indirect_symbol,s));
-        current_asmdata.asmlists[al_imports].concat(tai_const.createname('dyld_stub_binding_helper',0));
-      end;
-
-
     procedure tcg64farm.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
     procedure tcg64farm.a_op64_reg_reg(list : TAsmList;op:TOpCG;size : tcgsize;regsrc,regdst : tregister64);
       begin
       begin
         case op of
         case op of

+ 3 - 1
compiler/arm/cpupi.pas

@@ -216,7 +216,9 @@ unit cpupi;
 
 
     procedure tarmprocinfo.allocate_got_register(list: TAsmList);
     procedure tarmprocinfo.allocate_got_register(list: TAsmList);
       begin
       begin
-        got := cg.getaddressregister(list);
+        { darwin doesn't use a got }
+        if tf_pic_uses_got in target_info.flags then
+          got := cg.getaddressregister(list);
       end;
       end;
 
 
 
 

+ 1 - 1
compiler/systems/i_bsd.pas

@@ -891,7 +891,7 @@ unit i_bsd;
             system       : system_arm_darwin;
             system       : system_arm_darwin;
             name         : 'Darwin for ARM';
             name         : 'Darwin for ARM';
             shortname    : 'Darwin';
             shortname    : 'Darwin';
-            flags        : [tf_p_ext_support,tf_requires_proper_alignment,tf_files_case_sensitive,tf_smartlink_sections,tf_dwarf_relative_addresses,tf_dwarf_only_local_labels,tf_has_winlike_resources];
+            flags        : [tf_p_ext_support,tf_requires_proper_alignment,tf_files_case_sensitive,tf_smartlink_sections,tf_dwarf_relative_addresses,tf_dwarf_only_local_labels,tf_has_winlike_resources,tf_pic_default];
             cpu          : cpu_arm;
             cpu          : cpu_arm;
             unit_env     : 'BSDUNITS';
             unit_env     : 'BSDUNITS';
             extradefines : 'UNIX;BSD;HASUNIX;CPUARMEL';
             extradefines : 'UNIX;BSD;HASUNIX;CPUARMEL';