Sfoglia il codice sorgente

+ basic support for pic on arm-linux

git-svn-id: trunk@25297 -
florian 12 anni fa
parent
commit
6606955b88

+ 31 - 1
compiler/aasmtai.pas

@@ -140,7 +140,8 @@ interface
           aitconst_32bit_unaligned,
           aitconst_64bit_unaligned,
           { i8086 far pointer; emits: 'DW symbol, SEG symbol' }
-          aitconst_farptr
+          aitconst_farptr,
+          aitconst_got
         );
 
     const
@@ -572,7 +573,9 @@ interface
           constructor Create_sym(_sym:tasmsymbol);
           constructor Create_type_sym(_typ:taiconst_type;_sym:tasmsymbol);
           constructor Create_sym_offset(_sym:tasmsymbol;ofs:aint);
+          constructor Create_type_sym_offset(_typ:taiconst_type;_sym:tasmsymbol;ofs:aint);
           constructor Create_rel_sym(_typ:taiconst_type;_sym,_endsym:tasmsymbol);
+          constructor Create_rel_sym_offset(_typ : taiconst_type; _sym,_endsym : tasmsymbol; _ofs : int64);
           constructor Create_rva_sym(_sym:tasmsymbol);
           constructor Createname(const name:string;ofs:aint);
           constructor Createname(const name:string;_symtyp:Tasmsymtype;ofs:aint);
@@ -1684,6 +1687,24 @@ implementation
       end;
 
 
+    constructor tai_const.Create_type_sym_offset(_typ : taiconst_type;_sym : tasmsymbol; ofs : aint);
+      begin
+         inherited Create;
+         typ:=ait_const;
+         consttype:=_typ;
+         { sym is allowed to be nil, this is used to write nil pointers }
+         sym:=_sym;
+         endsym:=nil;
+         { store the original offset in symofs so that we can recalculate the
+           value field in the assembler }
+         symofs:=ofs;
+         value:=ofs;
+         { update sym info }
+         if assigned(sym) then
+           sym.increfs;
+      end;
+
+
     constructor tai_const.Create_rel_sym(_typ:taiconst_type;_sym,_endsym:tasmsymbol);
       begin
          self.create_sym_offset(_sym,0);
@@ -1693,6 +1714,15 @@ implementation
       end;
 
 
+    constructor tai_const.Create_rel_sym_offset(_typ: taiconst_type; _sym,_endsym: tasmsymbol; _ofs: int64);
+       begin
+         self.create_sym_offset(_sym,_ofs);
+         consttype:=_typ;
+         endsym:=_endsym;
+         endsym.increfs;
+       end;
+
+
     constructor tai_const.Create_rva_sym(_sym:tasmsymbol);
       begin
          self.create_sym_offset(_sym,0);

+ 5 - 0
compiler/aggas.pas

@@ -956,6 +956,11 @@ implementation
                       AsmLn;
                     end;
 {$endif cpu64bitaddr}
+                 aitconst_got:
+                   begin
+                     AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(GOT)');
+                     Asmln;
+                   end;
                  aitconst_uleb128bit,
                  aitconst_sleb128bit,
 {$ifdef cpu64bitaddr}

+ 4 - 4
compiler/arm/agarmgas.pas

@@ -164,10 +164,10 @@ unit agarmgas;
                 if (base<>NR_NO) and not(is_pc(base)) then
                   internalerror(200309011);
                 s:=symbol.name;
-                if offset<0 then
-                  s:=s+tostr(offset)
-                else if offset>0 then
-                  s:=s+'+'+tostr(offset);
+                if offset<>0 then
+                  s:=s+tostr_with_plus(offset);
+                if refaddr=addr_pic then
+                  s:=s+'(PLT)';
               end
             else
               begin

+ 58 - 5
compiler/arm/cgcpu.pas

@@ -74,6 +74,7 @@ unit cgcpu;
 
         procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean);override;
         procedure g_proc_exit(list : TAsmList;parasize : longint;nostackframe:boolean); override;
+        procedure g_maybe_got_init(list : TAsmList); override;
 
         procedure a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);override;
 
@@ -624,6 +625,8 @@ unit cgcpu;
     procedure tbasecgarm.a_call_name(list : TAsmList;const s : string; weak: boolean);
       var
         branchopcode: tasmop;
+        r : treference;
+        sym : TAsmSymbol;
       begin
         { check not really correct: should only be used for non-Thumb cpus }
         if CPUARM_HAS_BLX_LABEL in cpu_capabilities[current_settings.cputype] then
@@ -631,10 +634,23 @@ unit cgcpu;
         else
           branchopcode:=A_BL;
         if target_info.system<>system_arm_darwin then
-          if not weak then
-            list.concat(taicpu.op_sym(branchopcode,current_asmdata.RefAsmSymbol(s)))
-          else
-            list.concat(taicpu.op_sym(branchopcode,current_asmdata.WeakRefAsmSymbol(s)))
+          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;
+
+            list.concat(taicpu.op_ref(branchopcode,r));
+          end
         else
           list.concat(taicpu.op_sym(branchopcode,get_darwin_call_stub(s,weak)));
 {
@@ -2104,6 +2120,29 @@ unit cgcpu;
       end;
 
 
+    procedure tbasecgarm.g_maybe_got_init(list : TAsmList);
+      var
+        ref : treference;
+        l : TAsmLabel;
+      begin
+        if (cs_create_pic in current_settings.moduleswitches) and
+           (pi_needs_got in current_procinfo.flags) then
+          begin
+            reference_reset(ref,4);
+            current_asmdata.getdatalabel(l);
+            cg.a_label(current_procinfo.aktlocaldata,l);
+            ref.symbol:=l;
+            ref.base:=NR_PC;
+            ref.symboldata:=current_procinfo.aktlocaldata.last;
+            list.concat(Taicpu.op_reg_ref(A_LDR,current_procinfo.got,ref));
+            current_asmdata.getaddrlabel(l);
+            current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_32bit,l,current_asmdata.RefAsmSymbol('_GLOBAL_OFFSET_TABLE_'),-8));
+            cg.a_label(list,l);
+            list.concat(Taicpu.op_reg_reg_reg(A_ADD,current_procinfo.got,NR_PC,current_procinfo.got));
+          end;
+      end;
+
+
     procedure tbasecgarm.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
       var
         b : byte;
@@ -2197,7 +2236,11 @@ unit cgcpu;
                 indirection_done:=true;
               end
             else
-              current_procinfo.aktlocaldata.concat(tai_const.create_sym_offset(ref.symbol,ref.offset))
+              if (cs_create_pic in current_settings.moduleswitches) and
+                (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))
           end
         else
           current_procinfo.aktlocaldata.concat(tai_const.Create_32bit(ref.offset));
@@ -2209,6 +2252,16 @@ unit cgcpu;
             tmpref.symbol:=l;
             tmpref.base:=NR_PC;
             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
+              begin
+                reference_reset(tmpref,4);
+                tmpref.base:=current_procinfo.got;
+                tmpref.index:=tmpreg;
+                list.concat(taicpu.op_reg_ref(A_LDR,tmpreg,tmpref));
+              end;
           end;
 
         { This routine can be called with PC as base/index in case the offset

+ 9 - 1
compiler/arm/cpupi.pas

@@ -29,7 +29,8 @@ unit cpupi;
 
     uses
        globtype,cutils,
-       procinfo,cpuinfo,psub;
+       procinfo,cpuinfo,psub,
+       aasmdata;
 
     type
        tarmprocinfo = class(tcgprocinfo)
@@ -45,6 +46,7 @@ unit cpupi;
           function calc_stackframe_size:longint;override;
           procedure init_framepointer; override;
           procedure generate_parameter_info;override;
+          procedure allocate_got_register(list : TAsmList);override;
        end;
 
 
@@ -212,6 +214,12 @@ unit cpupi;
       end;
 
 
+    procedure tarmprocinfo.allocate_got_register(list: TAsmList);
+      begin
+        got := cg.getaddressregister(list);
+      end;
+
+
 begin
    cprocinfo:=tarmprocinfo;
 end.

+ 6 - 3
compiler/systems/i_linux.pas

@@ -553,7 +553,8 @@ unit i_linux;
             shortname    : 'Linux';
             flags        : [tf_needs_symbol_size,tf_needs_symbol_type,tf_files_case_sensitive,
                             tf_requires_proper_alignment,
-                            tf_smartlink_sections,tf_smartlink_library,tf_has_winlike_resources];
+                            tf_smartlink_sections,tf_smartlink_library,tf_pic_uses_got,
+                            tf_has_winlike_resources];
             cpu          : cpu_arm;
             unit_env     : 'LINUXUNITS';
             extradefines : 'UNIX;HASUNIX;CPUARMHF';
@@ -618,7 +619,8 @@ unit i_linux;
             shortname    : 'Linux';
             flags        : [tf_needs_symbol_size,tf_needs_symbol_type,tf_files_case_sensitive,
                             tf_requires_proper_alignment,
-                            tf_smartlink_sections,tf_smartlink_library,tf_has_winlike_resources];
+                            tf_smartlink_sections,tf_smartlink_library,tf_pic_uses_got,
+                            tf_has_winlike_resources];
             cpu          : cpu_arm;
             unit_env     : 'LINUXUNITS';
             extradefines : 'UNIX;HASUNIX;CPUARMEL';
@@ -683,7 +685,8 @@ unit i_linux;
             shortname    : 'Linux';
             flags        : [tf_needs_symbol_size,tf_needs_symbol_type,tf_files_case_sensitive,
                             tf_requires_proper_alignment,
-                            tf_smartlink_sections,tf_smartlink_library,tf_has_winlike_resources];
+                            tf_smartlink_sections,tf_smartlink_library,tf_pic_uses_got,
+                            tf_has_winlike_resources];
             cpu          : cpu_arm;
             unit_env     : 'LINUXUNITS';
             extradefines : 'UNIX;HASUNIX;CPUARMEB';