فهرست منبع

Fix usage of threadvars.

Note: In a Win32 application InitHeap and InitSystemThreads is called before the entrypoint from the TLS entrypoint. In that case entry information is not initialized yet (thus TLSKeyAddr is Nil). Because of this that case needs to be handled specially.

compiler/ncgld.pas, tcgloadnode:
  * pass_generate_code: use the indirect symbols for FPC_THREADVAR_RELOCATE and the threadvar to load
rtl/win/systhrd.inc:
  * GetTLSKey: check whether TLSKeyAddr is assigned and return $fffffff otherwise (to have the remaining initialization work correctly)
  * SetTLSKey: check whether TLSKeyAddr is assigned and ignore the setting otherwise
rtl/win/systlsdir.inc:
  * Exec_Tls_Callback: manually allocate the TLS key
rtl/win32/sysinit.inc:
  * ensure that FPC_HAS_INDIRECT_MAIN_INFORMATION is defined

git-svn-id: branches/svenbarth/packages@29013 -
svenbarth 10 سال پیش
والد
کامیت
3827c66316
4فایلهای تغییر یافته به همراه92 افزوده شده و 19 حذف شده
  1. 79 17
      compiler/ncgld.pas
  2. 7 2
      rtl/win/systhrd.inc
  3. 5 0
      rtl/win/systlsdir.inc
  4. 1 0
      rtl/win32/sysinit.inc

+ 79 - 17
compiler/ncgld.pas

@@ -254,7 +254,8 @@ implementation
 
 
     procedure tcgloadnode.pass_generate_code;
     procedure tcgloadnode.pass_generate_code;
       var
       var
-        hregister : tregister;
+        hregister,
+        hregister2 : tregister;
         vs   : tabstractnormalvarsym;
         vs   : tabstractnormalvarsym;
         gvs  : tstaticvarsym;
         gvs  : tstaticvarsym;
         pd   : tprocdef;
         pd   : tprocdef;
@@ -326,11 +327,22 @@ implementation
                             paraloc1.init;
                             paraloc1.init;
                             pd:=search_system_proc('fpc_tls_add');
                             pd:=search_system_proc('fpc_tls_add');
                             paramanager.getintparaloc(pd,1,paraloc1);
                             paramanager.getintparaloc(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))
+                            if tf_supports_packages in target_info.flags then
+                              begin
+                                if not(vo_is_weak_external in gvs.varoptions) then
+                                  reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname+indirect_suffix),0,sizeof(pint))
+                                else
+                                  reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname+indirect_suffix),0,sizeof(pint));
+                                cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_ADDR,href,paraloc1);
+                              end
                             else
                             else
-                              reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0,sizeof(pint));
-                            cg.a_loadaddr_ref_cgpara(current_asmdata.CurrAsmList,href,paraloc1);
+                              begin
+                                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);
+                              end;
                             paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
                             paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
                             paraloc1.done;
                             paraloc1.done;
 
 
@@ -343,10 +355,25 @@ implementation
                         else
                         else
                           begin
                           begin
                             if gvs.localloc.loc=LOC_INVALID then
                             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)
+                              begin
+                                if tf_supports_packages in target_info.flags then
+                                  begin
+                                    hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
+                                    if not(vo_is_weak_external in gvs.varoptions) then
+                                      reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname+indirect_suffix),0,location.reference.alignment)
+                                    else
+                                      reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname+indirect_suffix),0,location.reference.alignment);
+                                    cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
+                                    location.reference.base:=hregister;
+                                  end
+                                else
+                                  begin
+                                    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)
+                                  end;
+                              end
                             else
                             else
                               location:=gvs.localloc;
                               location:=gvs.localloc;
 {$ifdef i386}
 {$ifdef i386}
@@ -378,14 +405,35 @@ implementation
                         paraloc1.init;
                         paraloc1.init;
                         paramanager.getintparaloc(tprocvardef(pvd),1,paraloc1);
                         paramanager.getintparaloc(tprocvardef(pvd),1,paraloc1);
                         hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,pvd);
                         hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,pvd);
-                        reference_reset_symbol(href,current_asmdata.RefAsmSymbol('FPC_THREADVAR_RELOCATE'),0,pvd.size);
+                        if tf_supports_packages in target_info.flags then
+                          begin
+                            reference_reset_symbol(href,current_asmdata.RefAsmSymbol('FPC_THREADVAR_RELOCATE'+indirect_suffix),0,voidpointertype.size);
+                            hregister2:=hlcg.getaddressregister(current_asmdata.CurrAsmList,voidpointertype);
+                            hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,voidpointertype,voidpointertype,href,hregister2);
+                            reference_reset_base(href,hregister2,0,pvd.size);
+                          end
+                        else
+                          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_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);
                         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 }
                         { 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))
+                        if tf_supports_packages in target_info.flags then
+                          begin
+                            if not(vo_is_weak_external in gvs.varoptions) then
+                              reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname+indirect_suffix),0,sizeof(pint))
+                            else
+                              reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname+indirect_suffix),0,sizeof(pint));
+                            hregister2:=hlcg.getaddressregister(current_asmdata.CurrAsmList,voidpointertype);
+                            hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,voidpointertype,voidpointertype,href,hregister2);
+                            reference_reset_base(href,hregister2,0,sizeof(pint));
+                          end
                         else
                         else
-                          reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0,sizeof(pint));
+                          begin
+                            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));
+                          end;
                         cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
                         cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
                         paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
                         paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
                         paraloc1.done;
                         paraloc1.done;
@@ -402,11 +450,25 @@ implementation
                           layout of a threadvar is (4 bytes pointer):
                           layout of a threadvar is (4 bytes pointer):
                             0 - Threadvar index
                             0 - Threadvar index
                             4 - Threadvar value in single threading }
                             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))
+                        if tf_supports_packages in target_info.flags then
+                          begin
+                            if not(vo_is_weak_external in gvs.varoptions) then
+                              reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname+indirect_suffix),0,sizeof(pint))
+                            else
+                              reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname+indirect_suffix),0,sizeof(pint));
+                            hregister2:=hlcg.getaddressregister(current_asmdata.CurrAsmList,voidpointertype);
+                            hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,voidpointertype,voidpointertype,href,hregister2);
+                            reference_reset_base(href,hregister2,sizeof(pint),sizeof(pint));
+                            hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,resultdef,voidpointertype,href,hregister);
+                          end
                         else
                         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);
+                          begin
+                            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);
+                          end;
                         cg.a_label(current_asmdata.CurrAsmList,endrelocatelab);
                         cg.a_label(current_asmdata.CurrAsmList,endrelocatelab);
                         hlcg.reference_reset_base(location.reference,voidpointertype,hregister,0,location.reference.alignment);
                         hlcg.reference_reset_base(location.reference,voidpointertype,hregister,0,location.reference.alignment);
                       end;
                       end;

+ 7 - 2
rtl/win/systhrd.inc

@@ -94,12 +94,17 @@ var
     {$ifdef FPC_HAS_INDIRECT_MAIN_INFORMATION}
     {$ifdef FPC_HAS_INDIRECT_MAIN_INFORMATION}
     function GetTLSKey: DWord; inline;
     function GetTLSKey: DWord; inline;
       begin
       begin
-        Result:=EntryInformation.Platform.TLSKeyAddr^;
+        if not Assigned(EntryInformation.Platform.TLSKeyAddr) then
+          { this is the case during application startup, as the tlsentry is called first }
+          Result:=$ffffffff
+        else
+          Result:=EntryInformation.Platform.TLSKeyAddr^;
       end;
       end;
 
 
     procedure SetTLSKey(value : DWord); inline;
     procedure SetTLSKey(value : DWord); inline;
       begin
       begin
-        EntryInformation.Platform.TLSKeyAddr^:=value;
+        if Assigned(EntryInformation.Platform.TLSKeyAddr) then
+          EntryInformation.Platform.TLSKeyAddr^:=value;
       end;
       end;
     {$endif FPC_HAS_INDIRECT_MAIN_INFORMATION}
     {$endif FPC_HAS_INDIRECT_MAIN_INFORMATION}
 
 

+ 5 - 0
rtl/win/systlsdir.inc

@@ -41,6 +41,8 @@ type
 
 
 function TlsGetValue(dwTlsIndex : DWord) : pointer; stdcall;
 function TlsGetValue(dwTlsIndex : DWord) : pointer; stdcall;
   external 'kernel32' name 'TlsGetValue';
   external 'kernel32' name 'TlsGetValue';
+function TlsAlloc : DWord; stdcall;
+  external 'kernel32' name 'TlsAlloc';
 
 
 procedure InitSystemThreads; external name '_FPC_InitSystemThreads';
 procedure InitSystemThreads; external name '_FPC_InitSystemThreads';
 procedure SysAllocateThreadVars; external name '_FPC_SysAllocateThreadVars';
 procedure SysAllocateThreadVars; external name '_FPC_SysAllocateThreadVars';
@@ -67,6 +69,9 @@ procedure Exec_Tls_callback(Handle : pointer; reason : Dword; Reserved : pointer
          and the EntryInformation is a constant which sholud prevent troubles }
          and the EntryInformation is a constant which sholud prevent troubles }
        DLL_PROCESS_ATTACH:
        DLL_PROCESS_ATTACH:
          begin
          begin
+           {$ifdef FPC_HAS_INDIRECT_MAIN_INFORMATION}
+           TlsKey:=TlsAlloc;
+           {$endif FPC_HAS_INDIRECT_MAIN_INFORMATION}
            InitHeap;
            InitHeap;
            InitSystemThreads;
            InitSystemThreads;
          end;
          end;

+ 1 - 0
rtl/win32/sysinit.inc

@@ -89,5 +89,6 @@
       end;
       end;
 
 
 {$define FPC_INSSIDE_SYSINIT}
 {$define FPC_INSSIDE_SYSINIT}
+{$define FPC_HAS_INDIRECT_MAIN_INFORMATION}
 {$include systlsdir.inc}
 {$include systlsdir.inc}