Преглед на файлове

+ Compiler support for pic on darwin/i386. The i386 rtl still needs
to be made pic-safe (mainly accesses to the global default8087cw)
* At the same time also made the non-pic code abi-compliant (access
external data via indirect symbol pointers etc)

Darwin/i386 also puts the got into a virtual register (like
Darwin/ppc), a.o. because the register allocator fails to colour
a routine in aasmcpu.pas if we take away ebx from it.

git-svn-id: trunk@8657 -

Jonas Maebe преди 18 години
родител
ревизия
3266f4e483
променени са 6 файла, в които са добавени 112 реда и са изтрити 18 реда
  1. 10 0
      compiler/aggas.pas
  2. 22 7
      compiler/i386/cgcpu.pas
  3. 12 3
      compiler/i386/cpupi.pas
  4. 1 1
      compiler/systems/i_bsd.pas
  5. 2 0
      compiler/x86/agx86att.pas
  6. 65 7
      compiler/x86/cgx86.pas

+ 10 - 0
compiler/aggas.pas

@@ -1135,6 +1135,16 @@ implementation
                 result := '.section __TEXT, .fpc, regular, no_dead_strip';
                 exit;
               end;
+            sec_code:
+              begin
+                if (aname='fpc_geteipasebx') or
+                   (aname='fpc_geteipasecx') then
+                  begin
+                    result:='.section __TEXT,__textcoal_nt,coalesced,pure_instructions'#10'.weak_definition '+aname+
+                      #10'.private_extern '+aname;
+                    exit;
+                  end;
+              end;
           end;
         result := inherited sectionname(atype,aname,aorder);
       end;

+ 22 - 7
compiler/i386/cgcpu.pas

@@ -83,7 +83,8 @@ unit cgcpu;
     procedure tcg386.init_register_allocators;
       begin
         inherited init_register_allocators;
-        if cs_create_pic in current_settings.moduleswitches then
+        if (target_info.system<>system_i386_darwin) and
+           (cs_create_pic in current_settings.moduleswitches) then
           rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP])
         else
           rg[R_INTREGISTER]:=trgcpu.create(R_INTREGISTER,R_SUBWHOLE,[RS_EAX,RS_EDX,RS_ECX,RS_EBX,RS_ESI,RS_EDI],first_int_imreg,[RS_EBP]);
@@ -494,12 +495,26 @@ unit cgcpu;
            (pi_needs_got in current_procinfo.flags) and
            not(po_kylixlocal in current_procinfo.procdef.procoptions) then
           begin
-            current_module.requires_ebx_pic_helper:=true;
-            cg.a_call_name_static(list,'fpc_geteipasebx');
-            list.concat(taicpu.op_sym_ofs_reg(A_ADD,S_L,current_asmdata.RefAsmSymbol('_GLOBAL_OFFSET_TABLE_'),0,NR_PIC_OFFSET_REG));
-            list.concat(tai_regalloc.alloc(NR_PIC_OFFSET_REG,nil));
-            { ecx could be used in leave procedures }
-            current_procinfo.got:=NR_EBX;
+            if (target_info.system<>system_i386_darwin) then
+              begin
+                current_module.requires_ebx_pic_helper:=true;
+                cg.a_call_name_static(list,'fpc_geteipasebx');
+                list.concat(taicpu.op_sym_ofs_reg(A_ADD,S_L,current_asmdata.RefAsmSymbol('_GLOBAL_OFFSET_TABLE_'),0,NR_PIC_OFFSET_REG));
+                list.concat(tai_regalloc.alloc(NR_PIC_OFFSET_REG,nil));
+                { ecx could be used in leaf procedures }
+                current_procinfo.got:=NR_EBX;
+              end
+            else
+              begin
+                { can't use ecx, since that one may overwrite a parameter }
+                current_module.requires_ebx_pic_helper:=true;
+                cg.a_call_name_static(list,'fpc_geteipasebx');
+                list.concat(tai_regalloc.alloc(NR_EBX,nil));
+                a_label(list,current_procinfo.CurrGotLabel);
+                { got is already set by ti386procinfo.allocate_got_register }
+                list.concat(tai_regalloc.dealloc(NR_EBX,nil));
+                a_load_reg_reg(list,OS_ADDR,OS_ADDR,NR_EBX,current_procinfo.got);
+              end;
           end;
       end;
 

+ 12 - 3
compiler/i386/cpupi.pas

@@ -28,7 +28,7 @@ unit cpupi;
   interface
 
     uses
-       psub,procinfo;
+       psub,procinfo,aasmdata;
 
     type
        ti386procinfo = class(tcgprocinfo)
@@ -36,6 +36,7 @@ unit cpupi;
          procedure set_first_temp_offset;override;
          function calc_stackframe_size:longint;override;
          procedure generate_parameter_info;override;
+         procedure allocate_got_register(list: tasmlist);override;
        end;
 
 
@@ -43,8 +44,8 @@ unit cpupi;
 
     uses
       cutils,
-      systems,globals,
-      tgobj,
+      systems,globals,globtype,
+      cgobj,tgobj,
       cpubase,
       cgutils,
       symconst;
@@ -88,6 +89,14 @@ unit cpupi;
           para_stack_size := 0;
       end;
 
+    procedure ti386procinfo.allocate_got_register(list: tasmlist);
+      begin
+        if (target_info.system = system_i386_darwin) and
+           (cs_create_pic in current_settings.moduleswitches) then
+          begin
+            got := cg.getaddressregister(list);
+          end;
+      end;
 
 begin
    cprocinfo:=ti386procinfo;

+ 1 - 1
compiler/systems/i_bsd.pas

@@ -460,7 +460,7 @@ unit i_bsd;
             system       : system_i386_darwin;
             name         : 'Darwin for i386';
             shortname    : 'Darwin';
-            flags        : [tf_p_ext_support,tf_files_case_aware,tf_smartlink_sections,tf_dwarf_relative_addresses,tf_dwarf_only_local_labels];
+            flags        : [tf_p_ext_support,tf_files_case_aware,tf_smartlink_sections,tf_dwarf_relative_addresses,tf_dwarf_only_local_labels,tf_pic_uses_got];
             cpu          : cpu_i386;
             unit_env     : 'BSDUNITS';
             extradefines : 'UNIX;BSD;HASUNIX';

+ 2 - 0
compiler/x86/agx86att.pas

@@ -113,6 +113,8 @@ interface
              owner.AsmWrite(gas_regname(segment)+':');
            if assigned(symbol) then
              owner.AsmWrite(symbol.name);
+           if assigned(relsymbol) then
+             owner.AsmWrite('-'+relsymbol.name);
            if ref.refaddr=addr_pic then
 {$ifdef x86_64}
              owner.AsmWrite('@GOTPCREL');

+ 65 - 7
compiler/x86/cgx86.pas

@@ -347,6 +347,9 @@ unit cgx86;
       var
         hreg : tregister;
         href : treference;
+{$ifndef x86_64}
+        add_hreg: boolean;
+{$endif not  x86_64}
       begin
 {$ifdef x86_64}
         { Only 32bit is allowed }
@@ -403,18 +406,45 @@ unit cgx86;
               end;
           end;
 {$else x86_64}
-        if (cs_create_pic in current_settings.moduleswitches) and
-          assigned(ref.symbol) and not((ref.symbol.bind=AB_LOCAL) and (ref.symbol.typ in [AT_LABEL,AT_FUNCTION])) then
+        add_hreg:=false;
+        if (target_info.system=system_i386_darwin) then
+          begin
+            if assigned(ref.symbol) and
+               not(assigned(ref.relsymbol)) and
+               ((ref.symbol.bind = AB_EXTERNAL) or
+                (cs_create_pic in current_settings.moduleswitches)) then
+             begin
+               if (ref.symbol.bind = AB_EXTERNAL) or
+                  ((cs_create_pic in current_settings.moduleswitches) and
+                   (ref.symbol.bind in [AB_COMMON,AB_GLOBAL])) then
+                 begin
+                   hreg:=g_indirect_sym_load(list,ref.symbol.name);
+                   ref.symbol:=nil;
+                 end
+               else
+                 begin
+                   include(current_procinfo.flags,pi_needs_got);
+                   hreg:=current_procinfo.got;
+                   ref.relsymbol:=current_procinfo.CurrGOTLabel;
+                 end;
+               add_hreg:=true
+             end
+          end
+        else if (cs_create_pic in current_settings.moduleswitches) and
+           assigned(ref.symbol) and
+           not((ref.symbol.bind=AB_LOCAL) and
+               (ref.symbol.typ in [AT_LABEL,AT_FUNCTION])) then
           begin
-            reference_reset_symbol(href,ref.symbol,0);
-            hreg:=getaddressregister(list);
             href.refaddr:=addr_pic;
             href.base:=current_procinfo.got;
             include(current_procinfo.flags,pi_needs_got);
             list.concat(taicpu.op_ref_reg(A_MOV,S_L,href,hreg));
-
             ref.symbol:=nil;
+            add_hreg:=true;
+          end;
 
+        if add_hreg then
+          begin
             if ref.base=NR_NO then
               ref.base:=hreg
             else if ref.index=NR_NO then
@@ -770,7 +800,29 @@ unit cgx86;
               begin
                 if assigned(ref.symbol) then
                   begin
-                    if (cs_create_pic in current_settings.moduleswitches) then
+                    if (target_info.system=system_i386_darwin) and
+                       ((ref.symbol.bind = AB_EXTERNAL) or
+                        (cs_create_pic in current_settings.moduleswitches)) then
+                      begin
+                        if (ref.symbol.bind = AB_EXTERNAL) or
+                           ((cs_create_pic in current_settings.moduleswitches) and
+                            (ref.symbol.bind in [AB_COMMON,AB_GLOBAL])) then
+                          begin
+                             reference_reset_base(tmpref,
+                               g_indirect_sym_load(list,ref.symbol.name),
+                               offset);
+                             a_loadaddr_ref_reg(list,tmpref,r);
+                          end
+                       else
+                         begin
+                           include(current_procinfo.flags,pi_needs_got);
+                           reference_reset_base(tmpref,current_procinfo.got,offset);
+                           tmpref.symbol:=symbol;
+                           tmpref.relsymbol:=current_procinfo.CurrGOTLabel;
+                           list.concat(Taicpu.op_ref_reg(A_LEA,tcgsize2opsize[OS_ADDR],tmpref,r));
+                         end;
+                      end
+                    else if (cs_create_pic in current_settings.moduleswitches) then
                       begin
 {$ifdef x86_64}
                         reference_reset_symbol(tmpref,ref.symbol,0);
@@ -1996,7 +2048,13 @@ unit cgx86;
               got loaded
             }
             g_maybe_got_init(list);
-            ref.refaddr:=addr_pic;
+            if (target_info.system<>system_i386_darwin) then
+              ref.refaddr:=addr_pic
+            else
+              begin
+                ref.refaddr:=addr_no;
+                ref.relsymbol:=current_procinfo.CurrGOTLabel;
+              end
           end
         else
           ref.refaddr:=addr_full;