Bläddra i källkod

+ 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 år sedan
förälder
incheckning
4ec9ec2009
3 ändrade filer med 54 tillägg och 73 borttagningar
  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  }
         { the upper 24/16 bits of a register after an operation          }
         procedure maybeadjustresult(list: TAsmList; op: TOpCg; size: tcgsize; dst: tregister);
-        function get_darwin_call_stub(const s: string; weak: boolean): tasmsymbol;
       end;
 
       { tcgarm is shared between normal arm and thumb-2 }
@@ -633,26 +632,22 @@ unit cgcpu;
           branchopcode:=A_BLX
         else
           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
         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
         for now we only need it after pass 2 (I hope) (JM)
@@ -2126,7 +2121,8 @@ unit cgcpu;
         l : TAsmLabel;
       begin
         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
             reference_reset(ref,4);
             current_asmdata.getdatalabel(l);
@@ -2203,9 +2199,9 @@ unit cgcpu;
 
     procedure tbasecgarm.fixref(list : TAsmList;var ref : treference);
       var
-        tmpreg : tregister;
+        tmpreg, tmpreg2 : tregister;
         tmpref : treference;
-        l : tasmlabel;
+        l, piclabel : tasmlabel;
         indirection_done : boolean;
       begin
         { absolute symbols can't be handled directly, we've to store the symbol reference
@@ -2223,6 +2219,7 @@ unit cgcpu;
         current_asmdata.getjumplabel(l);
         cg.a_label(current_procinfo.aktlocaldata,l);
         tmpref.symboldata:=current_procinfo.aktlocaldata.last;
+        piclabel:=nil;
 
         indirection_done:=false;
         if assigned(ref.symbol) then
@@ -2235,12 +2232,30 @@ unit cgcpu;
                   a_op_const_reg(list,OP_ADD,OS_ADDR,ref.offset,tmpreg);
                 indirection_done:=true;
               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))
               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
         else
           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));
 
             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
                 reference_reset(tmpref,4);
                 tmpref.base:=current_procinfo.got;
@@ -2264,6 +2279,14 @@ unit cgcpu;
               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
           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
@@ -3168,50 +3191,6 @@ unit cgcpu;
       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);
       begin
         case op of

+ 3 - 1
compiler/arm/cpupi.pas

@@ -216,7 +216,9 @@ unit cpupi;
 
     procedure tarmprocinfo.allocate_got_register(list: TAsmList);
       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;
 
 

+ 1 - 1
compiler/systems/i_bsd.pas

@@ -891,7 +891,7 @@ unit i_bsd;
             system       : system_arm_darwin;
             name         : 'Darwin for ARM';
             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;
             unit_env     : 'BSDUNITS';
             extradefines : 'UNIX;BSD;HASUNIX;CPUARMEL';