Explorar el Código

* factored out the loading of threadvars in its own method, and put the
x86-specific part in nx86ld

git-svn-id: trunk@31639 -

Jonas Maebe hace 10 años
padre
commit
3c6aa91a96
Se han modificado 5 ficheros con 189 adiciones y 112 borrados
  1. 1 0
      .gitattributes
  2. 2 2
      compiler/i386/n386ld.pas
  3. 2 2
      compiler/i8086/n8086ld.pas
  4. 88 108
      compiler/ncgld.pas
  5. 96 0
      compiler/x86/nx86ld.pas

+ 1 - 0
.gitattributes

@@ -816,6 +816,7 @@ compiler/x86/nx86cal.pas svneol=native#text/plain
 compiler/x86/nx86cnv.pas svneol=native#text/plain
 compiler/x86/nx86con.pas svneol=native#text/plain
 compiler/x86/nx86inl.pas svneol=native#text/plain
+compiler/x86/nx86ld.pas svneol=native#text/plain
 compiler/x86/nx86mat.pas svneol=native#text/plain
 compiler/x86/nx86mem.pas svneol=native#text/plain
 compiler/x86/nx86set.pas svneol=native#text/plain

+ 2 - 2
compiler/i386/n386ld.pas

@@ -28,10 +28,10 @@ interface
     uses
       globtype,
       symsym,
-      node,ncgld,pass_1;
+      node,ncgld,nx86ld,pass_1;
 
     type
-      ti386loadnode = class(tcgloadnode)
+      ti386loadnode = class(tx86loadnode)
          procedure generate_absaddr_access(vs: tabsolutevarsym); override;
       end;
 

+ 2 - 2
compiler/i8086/n8086ld.pas

@@ -28,13 +28,13 @@ interface
     uses
       globtype,
       symsym,symtype,
-      node,ncgld, aasmbase;
+      node,ncgld,nx86ld,aasmbase;
 
     type
 
       { ti8086loadnode }
 
-      ti8086loadnode = class(tcgloadnode)
+      ti8086loadnode = class(tx86loadnode)
         protected
          procedure generate_nested_access(vs: tsym); override;
          procedure generate_absaddr_access(vs: tabsolutevarsym); override;

+ 88 - 108
compiler/ncgld.pas

@@ -37,6 +37,7 @@ interface
          protected
           procedure generate_nested_access(vs: tsym);virtual;
           procedure generate_absaddr_access(vs: tabsolutevarsym); virtual;
+          procedure generate_threadvar_access(gvs: tstaticvarsym); virtual;
          public
           procedure pass_generate_code;override;
           procedure changereflocation(const ref: treference);
@@ -252,6 +253,81 @@ implementation
       end;
 
 
+    procedure tcgloadnode.generate_threadvar_access(gvs: tstaticvarsym);
+      var
+        paraloc1 : tcgpara;
+        pvd : tdef;
+        endrelocatelab,
+        norelocatelab : tasmlabel;
+        href : treference;
+        hregister : tregister;
+      begin
+         if (tf_section_threadvars in target_info.flags) then
+           begin
+             if gvs.localloc.loc=LOC_INVALID then
+               if not(vo_is_weak_external in gvs.varoptions) then
+                 reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname),0,location.reference.alignment)
+               else
+                 reference_reset_symbol(location.reference,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0,location.reference.alignment)
+             else
+               location:=gvs.localloc;
+           end
+         else
+           begin
+             {
+               Thread var loading is optimized to first check if
+               a relocate function is available. When the function
+               is available it is called to retrieve the address.
+               Otherwise the address is loaded with the symbol
+
+               The code needs to be in the order to first handle the
+               call and then the address load to be sure that the
+               register that is used for returning is the same (PFV)
+             }
+             current_asmdata.getjumplabel(norelocatelab);
+             current_asmdata.getjumplabel(endrelocatelab);
+             { make sure hregister can't allocate the register necessary for the parameter }
+             pvd:=search_system_type('TRELOCATETHREADVARHANDLER').typedef;
+             if pvd.typ<>procvardef then
+               internalerror(2012120901);
+             paraloc1.init;
+             paramanager.getintparaloc(current_asmdata.CurrAsmList,tprocvardef(pvd),1,paraloc1);
+             hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,pvd);
+             reference_reset_symbol(href,current_asmdata.RefAsmSymbol('FPC_THREADVAR_RELOCATE'),0,pvd.size);
+             hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,pvd,pvd,href,hregister);
+             hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,pvd,OC_EQ,0,hregister,norelocatelab);
+             { don't save the allocated register else the result will be destroyed later }
+             if not(vo_is_weak_external in gvs.varoptions) then
+               reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname),0,sizeof(pint))
+             else
+               reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0,sizeof(pint));
+             cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
+             paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
+             paraloc1.done;
+             cg.allocallcpuregisters(current_asmdata.CurrAsmList);
+             cg.a_call_reg(current_asmdata.CurrAsmList,hregister);
+             cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
+             cg.getcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
+             cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
+             hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,voidpointertype);
+             cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_ADDR,NR_FUNCTION_RESULT_REG,hregister);
+             cg.a_jmp_always(current_asmdata.CurrAsmList,endrelocatelab);
+             cg.a_label(current_asmdata.CurrAsmList,norelocatelab);
+             { no relocation needed, load the address of the variable only, the
+               layout of a threadvar is (4 bytes pointer):
+                 0            - Threadvar index
+                 sizeof(pint) - Threadvar value in single threading }
+             if not(vo_is_weak_external in gvs.varoptions) then
+               reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname),sizeof(pint),sizeof(pint))
+             else
+               reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),sizeof(pint),sizeof(pint));
+             hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,resultdef,voidpointertype,href,hregister);
+             cg.a_label(current_asmdata.CurrAsmList,endrelocatelab);
+             hlcg.reference_reset_base(location.reference,voidpointertype,hregister,0,location.reference.alignment);
+           end;
+       end;
+
+
     procedure tcgloadnode.pass_generate_code;
       var
         hregister : tregister;
@@ -260,11 +336,7 @@ implementation
         pd   : tprocdef;
         href : treference;
         newsize : tcgsize;
-        endrelocatelab,
-        norelocatelab : tasmlabel;
-        paraloc1 : tcgpara;
-        vd,
-        pvd : tdef;
+        vd : tdef;
       begin
         { we don't know the size of all arrays }
         newsize:=def_cgsize(resultdef);
@@ -319,110 +391,18 @@ implementation
                  end
                { Thread variable }
                else if (vo_is_thread_var in gvs.varoptions) then
+                 generate_threadvar_access(gvs)
+               { Normal (or external) variable }
+               else
                  begin
-                    if (tf_section_threadvars in target_info.flags) then
-                      begin
-                        if target_info.system in [system_i386_win32,system_x86_64_win64] then
-                          begin
-                            paraloc1.init;
-                            pd:=search_system_proc('fpc_tls_add');
-                            paramanager.getintparaloc(current_asmdata.CurrAsmList,pd,1,paraloc1);
-                            if not(vo_is_weak_external in gvs.varoptions) then
-                              reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname),0,sizeof(pint))
-                            else
-                              reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0,sizeof(pint));
-                            cg.a_loadaddr_ref_cgpara(current_asmdata.CurrAsmList,href,paraloc1);
-                            paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
-                            paraloc1.done;
-
-                            cg.g_call(current_asmdata.CurrAsmList,'FPC_TLS_ADD');
-                            cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
-                            hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
-                            cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,NR_FUNCTION_RESULT_REG,hregister);
-                            location.reference.base:=hregister;
-                          end
-                        else
-                          begin
-                            if gvs.localloc.loc=LOC_INVALID then
-                              if not(vo_is_weak_external in gvs.varoptions) then
-                                reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname),0,location.reference.alignment)
-                              else
-                                reference_reset_symbol(location.reference,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0,location.reference.alignment)
-                            else
-                              location:=gvs.localloc;
-{$ifdef i386}
-                            case target_info.system of
-                              system_i386_linux,system_i386_android:
-                                location.reference.segment:=NR_GS;
-                            end;
-{$endif i386}
-                          end;
-                      end
-                    else
-                      begin
-                        {
-                          Thread var loading is optimized to first check if
-                          a relocate function is available. When the function
-                          is available it is called to retrieve the address.
-                          Otherwise the address is loaded with the symbol
-
-                          The code needs to be in the order to first handle the
-                          call and then the address load to be sure that the
-                          register that is used for returning is the same (PFV)
-                        }
-                        current_asmdata.getjumplabel(norelocatelab);
-                        current_asmdata.getjumplabel(endrelocatelab);
-                        { make sure hregister can't allocate the register necessary for the parameter }
-                        pvd:=search_system_type('TRELOCATETHREADVARHANDLER').typedef;
-                        if pvd.typ<>procvardef then
-                          internalerror(2012120901);
-                        paraloc1.init;
-                        paramanager.getintparaloc(current_asmdata.CurrAsmList,tprocvardef(pvd),1,paraloc1);
-                        hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,pvd);
-                        reference_reset_symbol(href,current_asmdata.RefAsmSymbol('FPC_THREADVAR_RELOCATE'),0,pvd.size);
-                        hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,pvd,pvd,href,hregister);
-                        hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,pvd,OC_EQ,0,hregister,norelocatelab);
-                        { don't save the allocated register else the result will be destroyed later }
-                        if not(vo_is_weak_external in gvs.varoptions) then
-                          reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname),0,sizeof(pint))
-                        else
-                          reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0,sizeof(pint));
-                        cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
-                        paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
-                        paraloc1.done;
-                        cg.allocallcpuregisters(current_asmdata.CurrAsmList);
-                        cg.a_call_reg(current_asmdata.CurrAsmList,hregister);
-                        cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
-                        cg.getcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
-                        cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
-                        hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,voidpointertype);
-                        cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_ADDR,NR_FUNCTION_RESULT_REG,hregister);
-                        cg.a_jmp_always(current_asmdata.CurrAsmList,endrelocatelab);
-                        cg.a_label(current_asmdata.CurrAsmList,norelocatelab);
-                        { no relocation needed, load the address of the variable only, the
-                          layout of a threadvar is (4 bytes pointer):
-                            0 - Threadvar index
-                            4 - Threadvar value in single threading }
-                        if not(vo_is_weak_external in gvs.varoptions) then
-                          reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname),sizeof(pint),sizeof(pint))
-                        else
-                          reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),sizeof(pint),sizeof(pint));
-                        hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,resultdef,voidpointertype,href,hregister);
-                        cg.a_label(current_asmdata.CurrAsmList,endrelocatelab);
-                        hlcg.reference_reset_base(location.reference,voidpointertype,hregister,0,location.reference.alignment);
-                      end;
-                  end
-                { Normal (or external) variable }
-                else
-                  begin
-                    if gvs.localloc.loc=LOC_INVALID then
-                      if not(vo_is_weak_external in gvs.varoptions) then
-                        reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname),0,location.reference.alignment)
-                      else
-                        reference_reset_symbol(location.reference,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0,location.reference.alignment)
-                    else
-                      location:=gvs.localloc;
-                  end;
+                   if gvs.localloc.loc=LOC_INVALID then
+                     if not(vo_is_weak_external in gvs.varoptions) then
+                       reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname),0,location.reference.alignment)
+                     else
+                       reference_reset_symbol(location.reference,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0,location.reference.alignment)
+                   else
+                     location:=gvs.localloc;
+                 end;
 
                 { make const a LOC_CREFERENCE }
                 if (gvs.varspez=vs_const) and

+ 96 - 0
compiler/x86/nx86ld.pas

@@ -0,0 +1,96 @@
+{
+    Copyright (c) 1998-2002,2015 by Florian Klaempfl
+
+    Generate x86 assembler for in load nodes
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit nx86ld;
+
+{$i fpcdefs.inc}
+
+interface
+    uses
+      globtype,
+      symtype,symsym,
+      node,nld,ncgld;
+
+    type
+      tx86loadnode = class(tcgloadnode)
+       protected
+         procedure generate_threadvar_access(gvs: tstaticvarsym); override;
+      end;
+
+implementation
+
+    uses
+      cutils,verbose,systems,
+      aasmtai,aasmdata,
+      cgutils,cgobj,
+      symconst,symdef,symtable,
+      cgbase,cpubase,parabase,paramgr;
+
+{*****************************************************************************
+                           TX86LOADNODE
+*****************************************************************************}
+
+    procedure tx86loadnode.generate_threadvar_access(gvs: tstaticvarsym);
+      var
+        paraloc1 : tcgpara;
+        pd: tprocdef;
+        href: treference;
+        hregister : tregister;
+        handled: boolean;
+      begin
+        handled:=false;
+        if (tf_section_threadvars in target_info.flags) then
+          begin
+            if target_info.system in [system_i386_win32,system_x86_64_win64] then
+              begin
+                paraloc1.init;
+                pd:=search_system_proc('fpc_tls_add');
+                paramanager.getintparaloc(current_asmdata.CurrAsmList,pd,1,paraloc1);
+                if not(vo_is_weak_external in gvs.varoptions) then
+                  reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname),0,sizeof(pint))
+                else
+                  reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0,sizeof(pint));
+                cg.a_loadaddr_ref_cgpara(current_asmdata.CurrAsmList,href,paraloc1);
+                paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
+                paraloc1.done;
+
+                cg.g_call(current_asmdata.CurrAsmList,'FPC_TLS_ADD');
+                cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
+                hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
+                cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,NR_FUNCTION_RESULT_REG,hregister);
+                location.reference.base:=hregister;
+                handled:=true;
+              end;
+          end;
+
+        if not handled then
+          inherited;
+
+        case target_info.system of
+          system_i386_linux,system_i386_android:
+            location.reference.segment:=NR_GS;
+        end;
+      end;
+
+
+begin
+   cloadnode:=tx86loadnode;
+end.