Bladeren bron

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 jaren geleden
bovenliggende
commit
3827c66316
4 gewijzigde bestanden met toevoegingen van 92 en 19 verwijderingen
  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;
       var
-        hregister : tregister;
+        hregister,
+        hregister2 : tregister;
         vs   : tabstractnormalvarsym;
         gvs  : tstaticvarsym;
         pd   : tprocdef;
@@ -326,11 +327,22 @@ implementation
                             paraloc1.init;
                             pd:=search_system_proc('fpc_tls_add');
                             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
-                              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);
                             paraloc1.done;
 
@@ -343,10 +355,25 @@ implementation
                         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)
+                              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
                               location:=gvs.localloc;
 {$ifdef i386}
@@ -378,14 +405,35 @@ implementation
                         paraloc1.init;
                         paramanager.getintparaloc(tprocvardef(pvd),1,paraloc1);
                         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_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))
+                        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
-                          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);
                         paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
                         paraloc1.done;
@@ -402,11 +450,25 @@ implementation
                           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))
+                        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
-                          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);
                         hlcg.reference_reset_base(location.reference,voidpointertype,hregister,0,location.reference.alignment);
                       end;

+ 7 - 2
rtl/win/systhrd.inc

@@ -94,12 +94,17 @@ var
     {$ifdef FPC_HAS_INDIRECT_MAIN_INFORMATION}
     function GetTLSKey: DWord; inline;
       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;
 
     procedure SetTLSKey(value : DWord); inline;
       begin
-        EntryInformation.Platform.TLSKeyAddr^:=value;
+        if Assigned(EntryInformation.Platform.TLSKeyAddr) then
+          EntryInformation.Platform.TLSKeyAddr^:=value;
       end;
     {$endif FPC_HAS_INDIRECT_MAIN_INFORMATION}
 

+ 5 - 0
rtl/win/systlsdir.inc

@@ -41,6 +41,8 @@ type
 
 function TlsGetValue(dwTlsIndex : DWord) : pointer; stdcall;
   external 'kernel32' name 'TlsGetValue';
+function TlsAlloc : DWord; stdcall;
+  external 'kernel32' name 'TlsAlloc';
 
 procedure InitSystemThreads; external name '_FPC_InitSystemThreads';
 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 }
        DLL_PROCESS_ATTACH:
          begin
+           {$ifdef FPC_HAS_INDIRECT_MAIN_INFORMATION}
+           TlsKey:=TlsAlloc;
+           {$endif FPC_HAS_INDIRECT_MAIN_INFORMATION}
            InitHeap;
            InitSystemThreads;
          end;

+ 1 - 0
rtl/win32/sysinit.inc

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