소스 검색

+ support for the gnu2 general-dynamic tls model on arm, use it instead of the gnu one as the gnu2 one can be relaxed (access optimizations by the linker)
+ support pic relocations in the internal assembler writer

git-svn-id: trunk@43128 -

florian 5 년 전
부모
커밋
16163b74ec
10개의 변경된 파일98개의 추가작업 그리고 10개의 파일을 삭제
  1. 4 1
      compiler/aasmtai.pas
  2. 5 0
      compiler/aggas.pas
  3. 14 4
      compiler/arm/aasmcpu.pas
  4. 3 1
      compiler/arm/agarmgas.pas
  5. 4 0
      compiler/arm/cgcpu.pas
  6. 8 0
      compiler/arm/cpuelf.pas
  7. 40 2
      compiler/arm/narmld.pas
  8. 15 2
      compiler/assemble.pas
  9. 2 0
      compiler/cgbase.pas
  10. 3 0
      compiler/ogbase.pas

+ 4 - 1
compiler/aasmtai.pas

@@ -154,7 +154,8 @@ interface
           { ARM TLS code }
           aitconst_gottpoff,
           aitconst_tpoff,
-          aitconst_tlsgd
+          aitconst_tlsgd,
+          aitconst_tlsdesc
         );
 
         tairealconsttype = (
@@ -2105,6 +2106,8 @@ implementation
             result:=4;
           aitconst_tpoff:
             result:=4;
+          aitconst_tlsdesc:
+            result:=4;
           else
             internalerror(200603253);
         end;

+ 5 - 0
compiler/aggas.pas

@@ -997,6 +997,11 @@ implementation
                      writer.AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(tlsgd)+(.-'+tai_const(hp).endsym.name+tostr_with_plus(tai_const(hp).symofs)+')');
                      writer.Asmln;
                    end;
+                 aitconst_tlsdesc:
+                   begin
+                     writer.AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(tlsdesc)+(.-'+tai_const(hp).endsym.name+tostr_with_plus(tai_const(hp).symofs)+')');
+                     writer.Asmln;
+                   end;
                  aitconst_tpoff:
                    begin
                      if assigned(tai_const(hp).endsym) or (tai_const(hp).symofs<>0) then

+ 14 - 4
compiler/arm/aasmcpu.pas

@@ -1161,7 +1161,7 @@ implementation
                                               if (hp2.typ=ait_const) and (tai_const(hp2).sym=tai_const(hp).sym)
                                                 and (tai_const(hp2).value=tai_const(hp).value) and (tai(hp2.previous).typ=ait_label) and
                                                 { gottpoff and tlsgd symbols are PC relative, so we cannot reuse them }
-                                                (not(tai_const(hp2).consttype in [aitconst_gottpoff,aitconst_tlsgd])) then
+                                                (not(tai_const(hp2).consttype in [aitconst_gottpoff,aitconst_tlsgd,aitconst_tlsdesc])) then
                                                 begin
                                                   with taicpu(curtai).oper[curop]^.ref^ do
                                                     begin
@@ -3051,13 +3051,23 @@ implementation
                 begin
                   currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
 
-                  bytes:=bytes or (((oper[0]^.ref^.offset-8) shr 2) and $ffffff);
+                  { tlscall is not relative so ignore the offset }
+                  if oper[0]^.ref^.refaddr<>addr_tlscall then
+                    bytes:=bytes or (((oper[0]^.ref^.offset-8) shr 2) and $ffffff);
 
                   if (opcode<>A_BL) or (condition<>C_None) then
                     objdata.writereloc(aint(bytes),4,currsym,RELOC_RELATIVE_24)
                   else
-                    objdata.writereloc(aint(bytes),4,currsym,RELOC_RELATIVE_CALL);
-
+                    case oper[0]^.ref^.refaddr of
+                      addr_pic:
+                        objdata.writereloc(aint(bytes),4,currsym,RELOC_ARM_CALL);
+                      addr_full:
+                        objdata.writereloc(aint(bytes),4,currsym,RELOC_RELATIVE_CALL);
+                      addr_tlscall:
+                        objdata.writereloc(aint(bytes),4,currsym,RELOC_TLS_CALL);
+                      else
+                        Internalerror(2019092903);
+                    end;
                   exit;
                 end;
             end;

+ 3 - 1
compiler/arm/agarmgas.pas

@@ -194,7 +194,9 @@ unit agarmgas;
                 if offset<>0 then
                   s:=s+tostr_with_plus(offset);
                 if refaddr=addr_pic then
-                  s:=s+'(PLT)';
+                  s:=s+'(PLT)'
+                else if refaddr=addr_tlscall then
+                  s:=s+'(tlscall)';
               end
             else
               begin

+ 4 - 0
compiler/arm/cgcpu.pas

@@ -2495,6 +2495,8 @@ unit cgcpu;
               current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_gottpoff,ref.symbol,ref.relsymbol,ref.offset))
             else if ref.refaddr=addr_tlsgd then
               current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_tlsgd,ref.symbol,ref.relsymbol,ref.offset))
+            else if ref.refaddr=addr_tlsdesc then
+              current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_tlsdesc,ref.symbol,ref.relsymbol,ref.offset))
             else if ref.refaddr=addr_tpoff then
               begin
                 if assigned(ref.relsymbol) or (ref.offset<>0) then
@@ -5140,6 +5142,8 @@ unit cgcpu;
                   current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_gottpoff,ref.symbol,ref.relsymbol,ref.offset))
                 else if ref.refaddr=addr_tlsgd then
                   current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_tlsgd,ref.symbol,ref.relsymbol,ref.offset))
+                else if ref.refaddr=addr_tlsdesc then
+                  current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_tlsdesc,ref.symbol,ref.relsymbol,ref.offset))
                 else if ref.refaddr=addr_tpoff then
                   begin
                     if assigned(ref.relsymbol) or (ref.offset<>0) then

+ 8 - 0
compiler/arm/cpuelf.pas

@@ -342,6 +342,14 @@ implementation
             result:=R_ARM_TLS_LE32
           else
             Internalerror(2019092901);
+        RELOC_TLSGD:
+          result:=R_ARM_TLS_GD32;
+        RELOC_TLSDESC:
+          result:=R_ARM_TLS_GOTDESC;
+        RELOC_TLS_CALL:
+          result:=R_ARM_TLS_CALL;
+        RELOC_ARM_CALL:
+          result:=R_ARM_CALL;
       else
         InternalError(2012110602);
       end;

+ 40 - 2
compiler/arm/narmld.pas

@@ -41,7 +41,7 @@ implementation
     uses
       globals,verbose,
       cgbase,cgobj,cgutils,
-      aasmdata,
+      aasmdata,aasmcpu,
       systems,
       symcpu,symdef,
       nld,
@@ -70,6 +70,7 @@ implementation
                 case current_settings.tlsmodel of
                   tlsm_general_dynamic:
                     begin
+{$ifdef use_tls_dialect_gnu}
                       current_asmdata.getjumplabel(l);
                       reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname,AT_TLS),-8,sizeof(AInt),[]);
                       href.refaddr:=addr_tlsgd;
@@ -79,12 +80,49 @@ implementation
                       cg.a_label(current_asmdata.CurrAsmList,l);
                       cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);
                       cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_ADD,OS_ADDR,hregister,NR_PC,NR_R0);
-                      cg.g_call(current_asmdata.CurrAsmList,'___tls_get_addr');
+                      cg.g_call(current_asmdata.CurrAsmList,'__tls_get_addr');
                       cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R0);
                       hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
                       cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,NR_R0,hregister);
                       reference_reset(location.reference,location.reference.alignment,location.reference.volatility);
                       location.reference.base:=hregister;
+{$else use_tls_dialect_gnu}
+                      { On arm, we use the gnu2 tls dialect. It has the advantage that it can be relaxed (optimized) by the linker,
+                        this is not possible with the gnu tls dialect.
+
+                        gnu2 is proposed and documented in
+                          Glauber de Oliveira Costa, Alexandre Oliva: Speeding Up Thread-Local Storage Access in DynamicLibraries in the ARM platform, 2006.
+                          Link: https://www.fsfla.org/~lxoliva/writeups/TLS/paper-lk2006.pdf
+                      }
+                      current_asmdata.getjumplabel(l);
+                      reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname,AT_TLS),0,sizeof(AInt),[]);
+                      href.refaddr:=addr_tlsdesc;
+                      href.relsymbol:=l;
+                      hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
+                      cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);
+                      cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,NR_R0);
+                      cg.a_label(current_asmdata.CurrAsmList,l);
+
+                      { we have to go the ugly way so we can set addr_tlscall }
+                      cg.allocallcpuregisters(current_asmdata.CurrAsmList);
+                      cg.a_call_name(current_asmdata.CurrAsmList,gvs.mangledname,false);
+                      with taicpu(current_asmdata.CurrAsmList.Last) do
+                        begin
+                          if opcode<>A_BL then
+                            Internalerror(2019092902);
+                          oper[0]^.ref^.refaddr:=addr_tlscall;
+                        end;
+                      cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
+
+                      cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);
+                      cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R0);
+                      hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
+                      cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,NR_R0,hregister);
+                      reference_reset(location.reference,location.reference.alignment,location.reference.volatility);
+                      location.reference.base:=current_procinfo.tlsoffset;
+                      include(current_procinfo.flags,pi_needs_tls);
+                      location.reference.index:=hregister;
+{$endif use_tls_dialect_gnu}
                       handled:=true;
                     end;
                   tlsm_initial_exec:

+ 15 - 2
compiler/assemble.pas

@@ -1764,7 +1764,7 @@ Implementation
                    begin
                      objsym:=Objdata.SymbolRef(tai_const(hp).sym);
                      objsymend:=Objdata.SymbolRef(tai_const(hp).endsym);
-                     if Tai_const(hp).consttype in [aitconst_gottpoff,aitconst_tlsgd] then
+                     if Tai_const(hp).consttype in [aitconst_gottpoff,aitconst_tlsgd,aitconst_tlsdesc] then
                        begin
                          if objsymend.objsection<>ObjData.CurrObjSec then
                            Internalerror(2019092801);
@@ -1991,12 +1991,18 @@ Implementation
                      objsym:=Objdata.SymbolRef(tai_const(hp).sym);
                      objsymend:=Objdata.SymbolRef(tai_const(hp).endsym);
                      relative_reloc:=(objsym.objsection<>objsymend.objsection);
-                     if Tai_const(hp).consttype in [aitconst_gottpoff,aitconst_tlsgd] then
+                     if Tai_const(hp).consttype in [aitconst_gottpoff] then
                        begin
                          if objsymend.objsection<>ObjData.CurrObjSec then
                            Internalerror(2019092802);
                          Tai_const(hp).value:=objsymend.address-ObjData.CurrObjSec.Size+Tai_const(hp).symofs;
                        end
+                     else if Tai_const(hp).consttype in [aitconst_tlsgd,aitconst_tlsdesc] then
+                       begin
+                         if objsymend.objsection<>ObjData.CurrObjSec then
+                           Internalerror(2019092802);
+                         Tai_const(hp).value:=ObjData.CurrObjSec.Size-objsymend.address+Tai_const(hp).symofs;
+                       end
                      else if objsymend.objsection<>objsym.objsection then
                        begin
                          if (Tai_const(hp).consttype in [aitconst_uleb128bit,aitconst_sleb128bit]) or
@@ -2066,6 +2072,13 @@ Implementation
                      ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_TPOFF);
                    aitconst_tlsgd:
                      ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_TLSGD);
+                   aitconst_tlsdesc:
+                     begin
+                       { must be a relative symbol, thus value being valid }
+                       if not(assigned(tai_const(hp).sym)) or not(assigned(tai_const(hp).endsym)) then
+                         Internalerror(2019092904);
+                       ObjData.writereloc(Tai_const(hp).value,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_TLSDESC);
+                     end;
 {$endif arm}
                    aitconst_gotoff_symbol:
                      ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_GOTOFF);

+ 2 - 0
compiler/cgbase.pas

@@ -126,6 +126,8 @@ interface
          ,addr_gottpoff
          ,addr_tpoff
          ,addr_tlsgd
+         ,addr_tlsdesc
+         ,addr_tlscall
          {$ENDIF}
          {$IFDEF i386}
          ,addr_ntpoff

+ 3 - 0
compiler/ogbase.pas

@@ -93,6 +93,9 @@ interface
          RELOC_GOT32,
          RELOC_TPOFF,
          RELOC_TLSGD,
+         RELOC_TLSDESC,
+         RELOC_TLS_CALL,
+         RELOC_ARM_CALL,
 {$endif arm}
          { Relative relocation }
          RELOC_RELATIVE,