浏览代码

* Proof of concept: Support threadvars using segment registers.

git-svn-id: trunk@740 -
daniel 20 年之前
父节点
当前提交
22e89e1a42

+ 2 - 2
compiler/aasmbase.pas

@@ -47,7 +47,7 @@ interface
        TAsmRelocationType = (RELOC_ABSOLUTE,RELOC_RELATIVE,RELOC_RVA);
 
        TAsmSectionType=(sec_none,
-         sec_code,sec_data,sec_rodata,sec_bss,
+         sec_code,sec_data,sec_rodata,sec_bss,sec_tbss,
          sec_common, { used for executable creation }
          sec_custom, { custom section, no prefix }
          { stabs }
@@ -572,7 +572,7 @@ implementation
     function TAsmObjectData.sectionname(atype:tasmsectiontype;const aname:string):string;
       const
         secnames : array[tasmsectiontype] of string[12] = ('',
-          'code','data','rodata','bss',
+          'code','data','rodata','bss','tbss',
           'common',
           'note',
           'stab','stabstr',

+ 1 - 1
compiler/aasmtai.pas

@@ -577,7 +577,7 @@ interface
 
        Tasmlist=({ default lists }
                  datasegment,codesegment,bsssegment,debuglist,consts,
-                 withdebuglist,importsection,exportsection,
+                 threadvarsegment,withdebuglist,importsection,exportsection,
                  resourcesection,rttilist,dwarflist,
                  { data used by pic code }
                  picdata,resourcestrings);

+ 3 - 2
compiler/aggas.pas

@@ -281,7 +281,7 @@ var
       const
         secnames : array[tasmsectiontype] of string[12] = ('',
 {$warning TODO .rodata not yet working}
-          '.text','.data','.data','.bss',
+          '.text','.data','.data','.bss','.tbss',
           'common',
           '.note',
           '.stab','.stabstr',
@@ -291,7 +291,7 @@ var
         );
       begin
         if use_smartlink_section and
-           (atype<>sec_bss) and
+           not (atype in [sec_bss,sec_tbss]) and
            (aname<>'') then
           result:='.gnu.linkonce'+copy(secnames[atype],1,2)+'.'+aname
         else
@@ -976,6 +976,7 @@ var
       WriteTree(asmlist[picdata]);
       Writetree(asmlist[resourcestrings]);
       WriteTree(asmlist[bsssegment]);
+      WriteTree(asmlist[threadvarsegment]);
       Writetree(asmlist[importsection]);
       { exports are written by DLLTOOL
         if we use it so don't insert it twice (PM) }

+ 2 - 2
compiler/assemble.pas

@@ -1085,7 +1085,7 @@ Implementation
                end;
              ait_datablock :
                begin
-                 if objectdata.currsec.sectype<>sec_bss then
+                 if not (objectdata.currsec.sectype in [sec_bss,sec_tbss]) then
                    Message(asmw_e_alloc_data_only_in_bss);
                  l:=used_align(size_2_align(Tai_datablock(hp).size),0,objectdata.currsec.addralign);
                  if Tai_datablock(hp).is_global and
@@ -1256,7 +1256,7 @@ Implementation
            case hp.typ of
              ait_align :
                begin
-                 if objectdata.currsec.sectype=sec_bss then
+                 if objectdata.currsec.sectype in [sec_bss,sec_tbss] then
                    objectdata.alloc(Tai_align(hp).fillsize)
                  else
                    objectdata.writebytes(Tai_align(hp).calculatefillbuf(fillbuffer)^,Tai_align(hp).fillsize);

+ 2 - 1
compiler/i386/ag386nsm.pas

@@ -355,7 +355,7 @@ interface
     procedure T386NasmAssembler.WriteSection(atype:tasmsectiontype;const aname:string);
       const
         secnames : array[tasmsectiontype] of string[12] = ('',
-          '.text','.data','.rodata','.bss',
+          '.text','.data','.rodata','.bss','.tbss',
           'common',
           '.note',
           '.stab','.stabstr',
@@ -803,6 +803,7 @@ interface
       WriteTree(asmlist[rttilist]);
       WriteTree(asmlist[resourcestrings]);
       WriteTree(asmlist[bsssegment]);
+      WriteTree(asmlist[threadvarsegment]);
       Writetree(asmlist[importsection]);
       { exports are written by DLLTOOL
         if we use it so don't insert it twice (PM) }

+ 5 - 3
compiler/i386/cgcpu.pas

@@ -193,23 +193,25 @@ unit cgcpu;
       begin
         with r do
           begin
+{$ifndef segment_threadvars}
             if (segment<>NR_NO) then
               cgmessage(cg_e_cant_use_far_pointer_there);
+{$endif}
             if use_push(cgpara) then
               begin
                 cgpara.check_simple_location;
                 opsize:=tcgsize2opsize[OS_ADDR];
-                if (base=NR_NO) and (index=NR_NO) then
+                if (segment=NR_NO) and (base=NR_NO) and (index=NR_NO) then
                   begin
                     if assigned(symbol) then
                       list.concat(Taicpu.Op_sym_ofs(A_PUSH,opsize,symbol,offset))
                     else
                       list.concat(Taicpu.Op_const(A_PUSH,opsize,offset));
                   end
-                else if (base=NR_NO) and (index<>NR_NO) and
+                else if (segment=NR_NO) and (base=NR_NO) and (index<>NR_NO) and
                         (offset=0) and (scalefactor=0) and (symbol=nil) then
                   list.concat(Taicpu.Op_reg(A_PUSH,opsize,index))
-                else if (base<>NR_NO) and (index=NR_NO) and
+                else if (segment=NR_NO) and (base<>NR_NO) and (index=NR_NO) and
                         (offset=0) and (symbol=nil) then
                   list.concat(Taicpu.Op_reg(A_PUSH,opsize,base))
                 else

+ 6 - 0
compiler/ncgld.pas

@@ -141,6 +141,7 @@ implementation
                       cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,location.reference,hregister);
                       reference_reset_base(location.reference,hregister,0);
                     end
+{$ifndef segment_threadvars}
                   { Thread variable }
                   else if (vo_is_thread_var in tabstractvarsym(symtableentry).varoptions) then
                     begin
@@ -187,6 +188,7 @@ implementation
                        cg.a_label(exprasmlist,endrelocatelab);
                        location.reference.base:=hregister;
                     end
+{$endif}
                   { Nested variable }
                   else if assigned(left) then
                     begin
@@ -247,6 +249,10 @@ implementation
                                         reference_reset_symbol(location.reference,objectlibrary.newasmsymbol(tglobalvarsym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA),0)
                                       else
                                         location:=tglobalvarsym(symtableentry).localloc;
+{$ifdef segment_threadvars}
+                                      if (vo_is_thread_var in tabstractvarsym(symtableentry).varoptions) then
+                                        location.reference.segment:=NR_GS;
+{$endif}
                                     end;
                                 end;
                               else

+ 24 - 7
compiler/ncgutil.pas

@@ -1966,18 +1966,35 @@ implementation
       var
         l,varalign : longint;
         storefilepos : tfileposinfo;
+        list : Taasmoutput;
+        sectype : Tasmsectiontype;
       begin
         storefilepos:=aktfilepos;
         aktfilepos:=sym.fileinfo;
         l:=sym.getsize;
+     {$ifndef segment_threadvars}
         if (vo_is_thread_var in sym.varoptions) then
           inc(l,sizeof(aint));
+        list:=asmlist[bsssegment];
+        sectype:=sec_bss;
+     {$else}
+        if (vo_is_thread_var in sym.varoptions) then
+          begin
+            list:=asmlist[threadvarsegment];
+            sectype:=sec_tbss;
+          end
+        else
+          begin
+            list:=asmlist[bsssegment];
+            sectype:=sec_bss;
+          end;
+     {$endif}
         varalign:=var_align(l);
-        maybe_new_object_file(asmlist[bsssegment]);
-        new_section(asmlist[bsssegment],sec_bss,lower(sym.mangledname),varalign);
+        maybe_new_object_file(list);
+        new_section(list,sectype,lower(sym.mangledname),varalign);
 {$ifdef GDB}
         if (cs_debuginfo in aktmoduleswitches) then
-          sym.concatstabto(asmlist[bsssegment]);
+          sym.concatstabto(list);
 {$endif GDB}
         if (sym.owner.symtabletype=globalsymtable) or
            maybe_smartlink_symbol or
@@ -1986,9 +2003,9 @@ implementation
             (po_inline in current_procinfo.procdef.procoptions)) or
            (vo_is_exported in sym.varoptions) or
            (vo_is_C_var in sym.varoptions) then
-          asmlist[bsssegment].concat(Tai_datablock.Create_global(sym.mangledname,l))
+          list.concat(Tai_datablock.create_global(sym.mangledname,l))
         else
-          asmlist[bsssegment].concat(Tai_datablock.Create(sym.mangledname,l));
+          list.concat(Tai_datablock.create(sym.mangledname,l));
         aktfilepos:=storefilepos;
       end;
 
@@ -2097,8 +2114,8 @@ implementation
                                   { PIC, DLL and Threadvar need extra code and are handled in ncgld }
                                   if not((target_info.system=system_powerpc_darwin) and
                                     (cs_create_pic in aktmoduleswitches)) and
-                                     not(vo_is_dll_var in varoptions) and
-                                     not(vo_is_thread_var in varoptions) then
+                                     not(vo_is_dll_var in varoptions) {$ifndef segment_threadvars} and
+                                     not(vo_is_thread_var in varoptions) {$endif} then
                                     reference_reset_symbol(localloc.reference,objectlibrary.newasmsymbol(mangledname,AB_EXTERNAL,AT_DATA),0);
                                 end;
                               else

+ 1 - 1
compiler/ogcoff.pas

@@ -554,7 +554,7 @@ const go32v2stub : array[0..2047] of byte=(
     function TCoffObjectData.sectionname(atype:tasmsectiontype;const aname:string):string;
       const
         secnames : array[tasmsectiontype] of string[16] = ('',
-          '.text','.data','.data','.bss',
+          '.text','.data','.data','.bss','.tbss',
           'common',
           '.note',
           '.stab','.stabstr',

+ 6 - 5
compiler/ogelf.pas

@@ -236,7 +236,7 @@ implementation
               AshType:=SHT_PROGBITS;
               AAlign:=max(sizeof(aint),AAlign);
             end;
-          sec_bss :
+          sec_bss,sec_tbss :
             begin
               Ashflags:=SHF_ALLOC or SHF_WRITE;
               AshType:=SHT_NOBITS;
@@ -308,6 +308,7 @@ implementation
         createsection(sec_code,'',0,[]);
         createsection(sec_data,'',0,[]);
         createsection(sec_bss,'',0,[]);
+        createsection(sec_tbss,'',0,[]);
         { create stabs sections if debugging }
         if (cs_debuginfo in aktmoduleswitches) then
          begin
@@ -331,9 +332,9 @@ implementation
       const
         secnames : array[tasmsectiontype] of string[12] = ('',
 {$ifdef userodata}
-          '.text','.data','.rodata','.bss',
+          '.text','.data','.rodata','.bss','.tbss',
 {$else userodata}
-          '.text','.data','.data','.bss',
+          '.text','.data','.data','.bss','.tbss',
 {$endif userodata}
           'common',
           '.note',
@@ -344,7 +345,7 @@ implementation
         );
       begin
         if use_smartlink_section and
-           (atype<>sec_bss) and
+           not (atype in [sec_bss,sec_tbss]) and
            (aname<>'') then
           result:='.gnu.linkonce'+copy(secnames[atype],1,2)+'.'+aname
         else
@@ -378,7 +379,7 @@ implementation
         if currsec=nil then
           internalerror(200403292);
 {$ifdef userodata}
-        if currsec.sectype in [sec_rodata,sec_bss] then
+        if currsec.sectype in [sec_rodata,sec_bss,sec_tbss] then
           internalerror(200408252);
 {$endif userodata}
         if assigned(p) then

+ 1 - 1
compiler/parser.pas

@@ -252,7 +252,7 @@ implementation
          exprasmlist:=taasmoutput.create;
          { Create assembler output lists for CG }
          to_create:=[datasegment,codesegment,bsssegment,debuglist,
-                     withdebuglist,consts,rttilist,picdata];
+                     threadvarsegment,withdebuglist,consts,rttilist,picdata];
          for i:=low(Tasmlist) to high(Tasmlist) do
            if i in to_create then
              asmlist[i]:=Taasmoutput.create

+ 2 - 2
compiler/pdecl.pas

@@ -574,7 +574,7 @@ implementation
     { the top symbol table of symtablestack         }
       begin
         consume(_VAR);
-        read_var_decs(false,false,false);
+        read_var_decs([]);
       end;
 
 
@@ -602,7 +602,7 @@ implementation
         consume(_THREADVAR);
         if not(symtablestack.symtabletype in [staticsymtable,globalsymtable]) then
           message(parser_e_threadvars_only_sg);
-        read_var_decs(false,false,true);
+        read_var_decs([vd_threadvar]);
       end;
 
 

+ 1 - 1
compiler/pdecobj.pas

@@ -597,7 +597,7 @@ implementation
                               not(oo_can_have_published in aktclass.objectoptions) then
                               Message(parser_e_cant_have_published);
 
-                            read_var_decs(false,true,false);
+                            read_var_decs([vd_object]);
                           end;
                     end;
                   end;

+ 22 - 21
compiler/pdecvar.pas

@@ -29,9 +29,12 @@ interface
     uses
       symsym,symdef;
 
+    type   Tvar_dec_option=(vd_record,vd_object,vd_threadvar);
+           Tvar_dec_options=set of Tvar_dec_option;
+
     function read_property_dec(aclass:tobjectdef):tpropertysym;
 
-    procedure read_var_decs(is_record,is_object,is_threadvar:boolean);
+    procedure read_var_decs(options:Tvar_dec_options);
 
 
 implementation
@@ -582,7 +585,7 @@ implementation
     const
        variantrecordlevel : longint = 0;
 
-    procedure read_var_decs(is_record,is_object,is_threadvar:boolean);
+    procedure read_var_decs(options:Tvar_dec_options);
     { reads the filed of a record into a        }
     { symtablestack, if record=false        }
     { variants are forbidden, so this procedure }
@@ -710,7 +713,7 @@ implementation
 {$endif powerpc}
          old_current_object_option:=current_object_option;
          { all variables are public if not in a object declaration }
-         if not is_object then
+         if not(vd_object in options) then
           current_object_option:=[sp_public];
          old_block_type:=block_type;
          block_type:=bt_type;
@@ -720,8 +723,9 @@ implementation
           consume(_ID);
          { read vars }
          sc:=tsinglelist.create;
-         while (token=_ID) and
-               not(is_object and (idtoken in [_PUBLIC,_PRIVATE,_PUBLISHED,_PROTECTED,_STRICT])) do
+         while (token=_ID) and 
+            not((vd_object in options) and
+                (idtoken in [_PUBLIC,_PRIVATE,_PUBLISHED,_PROTECTED,_STRICT])) do
            begin
              sorg:=orgpattern;
              semicoloneaten:=false;
@@ -749,8 +753,7 @@ implementation
                consume(_ID);
              until not try_to_consume(_COMMA);
              consume(_COLON);
-             if (m_gpc in aktmodeswitches) and
-                not(is_record or is_object or is_threadvar) and
+             if (m_gpc in aktmodeswitches) and (options=[]) and
                 (token=_ID) and (orgpattern='__asmname__') then
                begin
                  consume(_ID);
@@ -760,7 +763,7 @@ implementation
              { this is needed for Delphi mode at least
                but should be OK for all modes !! (PM) }
              ignore_equal:=true;
-             if is_record or is_object then
+             if options*[vd_record,vd_object]<>[] then
               begin
                 { for records, don't search the recordsymtable for
                   the symbols of the types }
@@ -797,7 +800,7 @@ implementation
                    the alignment of the first field.  */
                }
                if (target_info.system in [system_powerpc_darwin, system_powerpc_macos]) and
-                  is_record and
+                  (vd_record in options) and
                   is_first_field and
                   (trecordsymtable(symtablestack).usefieldalignment = -1) then
                  begin
@@ -840,8 +843,7 @@ implementation
                end;
 
              { check for absolute }
-             if not symdone and
-                (idtoken=_ABSOLUTE) and not(is_record or is_object or is_threadvar) then
+             if not symdone and (idtoken=_ABSOLUTE) and (options=[]) then
               begin
                 consume(_ABSOLUTE);
                 abssym:=nil;
@@ -949,7 +951,7 @@ implementation
              try_consume_hintdirective(dummysymoptions);
 
              { Records and objects can't have default values }
-             if is_record or is_object then
+             if options*[vd_record,vd_object]<>[] then
                begin
                  { for a record there doesn't need to be a ; before the END or )    }
                  if not(token in [_END,_RKLAMMER]) and
@@ -966,7 +968,7 @@ implementation
                    if (tt.def.deftype=procvardef) and
                       (tt.def.typesym=nil) then
                      handle_calling_convention(tprocvardef(tt.def));
-                   read_default_value(sc,tt,is_threadvar);
+                   read_default_value(sc,tt,vd_threadvar in options);
                    consume(_SEMICOLON);
                    { for locals we've created typedconstsym with a different name }
                    if symtablestack.symtabletype<>localsymtable then
@@ -996,12 +998,11 @@ implementation
                  { Add calling convention for procvar }
                  handle_calling_convention(tprocvardef(tt.def));
                  { Handling of Delphi typed const = initialized vars }
-                 if (token=_EQUAL) and
-                    not(is_record or is_object) and
+                 if (token=_EQUAL) and (options*[vd_record,vd_object]=[]) and
                     not(m_tp7 in aktmodeswitches) and
                     (symtablestack.symtabletype<>parasymtable) then
                    begin
-                     read_default_value(sc,tt,is_threadvar);
+                     read_default_value(sc,tt,vd_threadvar in options);
                      consume(_SEMICOLON);
                      symdone:=true;
                      hasdefaultvalue:=true;
@@ -1009,7 +1010,7 @@ implementation
                end;
 
              { Check for EXTERNAL etc directives or, in macpas, if cs_external_var is set}
-             if not symdone and not(is_record or is_object or is_threadvar) then
+             if not symdone and (options=[]) then
               begin
                 if (
                      (token=_ID) and
@@ -1147,7 +1148,7 @@ implementation
               end;
 
              { Check for STATIC directive }
-             if not symdone and (is_object) and
+             if not symdone and (vd_object in options) and
                (cs_static_keyword in aktmoduleswitches) and (idtoken=_STATIC) then
                   begin
                     include(current_object_option,sp_static);
@@ -1183,14 +1184,14 @@ implementation
                       Message(parser_e_only_publishable_classes_can__be_published);
                       exclude(current_object_option,sp_published);
                     end;
-                  insert_syms(sc,tt,is_threadvar,dummysymoptions);
+                  insert_syms(sc,tt,vd_threadvar in options,dummysymoptions);
                   current_object_option:=old_current_object_option;
                end;
 
            end;
 
          { Check for Case }
-         if is_record and (token=_CASE) then
+         if (vd_record in options) and (token=_CASE) then
            begin
               maxsize:=0;
               maxalignment:=0;
@@ -1257,7 +1258,7 @@ implementation
                 consume(_LKLAMMER);
                 inc(variantrecordlevel);
                 if token<>_RKLAMMER then
-                  read_var_decs(true,false,false);
+                  read_var_decs([vd_record]);
                 dec(variantrecordlevel);
                 consume(_RKLAMMER);
                 { calculates maximal variant size }

+ 20 - 7
compiler/pmodules.pas

@@ -165,11 +165,12 @@ implementation
              ' ['+date_string+'] for '+target_cpu_string+' - '+target_info.shortname));
          end;
         { align code segment }
-        asmlist[codesegment].concat(Tai_align.Create(aktalignment.procalign));
+        asmlist[codesegment].concat(Tai_align.create(aktalignment.procalign));
         { Insert start and end of sections }
         fixseg(asmlist[codesegment],sec_code,'____seg_code');
         fixseg(asmlist[datasegment],sec_data,'____seg_data');
         fixseg(asmlist[bsssegment],sec_bss,'____seg_bss');
+        fixseg(asmlist[threadvarsegment],sec_bss,'____seg_tbss');
         { we should use .rdata section for these two no ?
           .rdata is a read only data section (PM) }
         fixseg(asmlist[rttilist],sec_data,'____seg_rtti');
@@ -190,7 +191,7 @@ implementation
 {$endif GDB}
       end;
 
-
+{$ifndef segment_threadvars}
     procedure InsertThreadvarTablesTable;
       var
         hp : tused_unit;
@@ -226,7 +227,6 @@ implementation
         ltvTables.free;
       end;
 
-
     procedure AddToThreadvarList(p:tnamedindexitem;arg:pointer);
       var
         ltvTable : taasmoutput;
@@ -266,6 +266,7 @@ implementation
           end;
          ltvTable.Free;
       end;
+{$endif}
 
 
     Procedure InsertResourceTablesTable;
@@ -912,6 +913,8 @@ implementation
           asmlist[codesegment].empty and
           asmlist[datasegment].empty and
           asmlist[bsssegment].empty and
+          asmlist[threadvarsegment].empty and
+          asmlist[rttilist].empty and
           ((asmlist[importsection]=nil) or asmlist[importsection].empty) and
           ((asmlist[resourcesection]=nil) or asmlist[resourcesection].empty) and
           ((asmlist[aasmtai.resourcestrings]=nil) or asmlist[aasmtai.resourcestrings].empty)
@@ -930,7 +933,7 @@ implementation
          force_init_final : boolean;
          pd : tprocdef;
          unitname8 : string[8];
-         has_impl: boolean;
+         has_impl,ag: boolean;
       begin
          if m_mac in aktmodeswitches then
            begin
@@ -1248,7 +1251,9 @@ implementation
          gen_intf_wrappers(asmlist[codesegment],current_module.localsymtable);
 
          { generate a list of threadvars }
+{$ifndef segment_threadvars}
          InsertThreadvars;
+{$endif}
 
          { generate imports }
          if current_module.uses_imports then
@@ -1256,15 +1261,19 @@ implementation
 
          { insert own objectfile, or say that it's in a library
            (no check for an .o when loading) }
-         if is_assembler_generated then
+         ag:=is_assembler_generated;
+         if ag then
            insertobjectfile
          else
-           current_module.flags:=current_module.flags or uf_no_link;
+           begin
+             current_module.flags:=current_module.flags or uf_no_link;
+             current_module.flags:=current_module.flags and not uf_has_debuginfo;
+           end;
 
          if cs_local_browser in aktmoduleswitches then
            current_module.localsymtable:=refsymtable;
 
-         if is_assembler_generated then
+         if ag then
           begin
             { create dwarf debuginfo }
             create_dwarf;
@@ -1561,8 +1570,10 @@ implementation
          { generate wrappers for interfaces }
          gen_intf_wrappers(asmlist[codesegment],current_module.localsymtable);
 
+{$ifndef segment_threadvars}
          { generate a list of threadvars }
          InsertThreadvars;
+{$endif}
 
          { generate imports }
          if current_module.uses_imports then
@@ -1574,7 +1585,9 @@ implementation
            exportlib.generatelib;
 
          { insert Tables and StackLength }
+{$ifndef segment_threadvars}
          insertThreadVarTablesTable;
+{$endif}
          insertResourceTablesTable;
          insertinitfinaltable;
          insertmemorysizes;

+ 1 - 1
compiler/ptype.pas

@@ -232,7 +232,7 @@ implementation
          { for tp7 don't allow forward types }
          if m_tp7 in aktmodeswitches then
            typecanbeforward:=false;
-         read_var_decs(true,false,false);
+         read_var_decs([vd_record]);
          consume(_END);
          typecanbeforward:=storetypecanbeforward;
          current_object_option:=old_object_option;

+ 3 - 2
compiler/x86/agx86int.pas

@@ -59,13 +59,13 @@ implementation
       line_length = 70;
 
       secnames : array[TAsmSectionType] of string[4] = ('',
-        'CODE','DATA','DATA','BSS',
+        'CODE','DATA','DATA','BSS','',
         '','','','','','',
         '','','','','',''
       );
 
       secnamesml64 : array[TAsmSectionType] of string[7] = ('',
-        '_TEXT','_DATE','_DATA','_BSS',
+        '_TEXT','_DATE','_DATA','_BSS','',
         '','','','',
         'idata$2','idata$4','idata$5','idata$6','idata$7','edata',
         '',''
@@ -881,6 +881,7 @@ implementation
       WriteTree(asmlist[rttilist]);
       WriteTree(asmlist[resourcestrings]);
       WriteTree(asmlist[bsssegment]);
+      WriteTree(asmlist[threadvarsegment]);
       Writetree(asmlist[importsection]);
       { exports are written by DLLTOOL
         if we use it so don't insert it twice (PM) }

+ 47 - 35
compiler/x86/cgx86.pas

@@ -686,46 +686,58 @@ unit cgx86;
         tmpref  : treference;
       begin
         with ref do
-          if (base=NR_NO) and (index=NR_NO) then
-            begin
+          begin
+            if (base=NR_NO) and (index=NR_NO) then
               if assigned(ref.symbol) then
-                begin
-                  if cs_create_pic in aktmoduleswitches then
-                    begin
+                if cs_create_pic in aktmoduleswitches then
+                  begin
 {$ifdef x86_64}
-                      reference_reset_symbol(tmpref,ref.symbol,0);
-                      tmpref.refaddr:=addr_pic;
-                      tmpref.base:=NR_RIP;
-                      list.concat(taicpu.op_ref_reg(A_MOV,S_Q,tmpref,r));
+                    reference_reset_symbol(tmpref,ref.symbol,0);
+                    tmpref.refaddr:=addr_pic;
+                    tmpref.base:=NR_RIP;
+                    list.concat(taicpu.op_ref_reg(A_MOV,S_Q,tmpref,r));
 {$else x86_64}
-                      reference_reset_symbol(tmpref,ref.symbol,0);
-                      tmpref.refaddr:=addr_pic;
-                      tmpref.base:=current_procinfo.got;
-                      list.concat(taicpu.op_ref_reg(A_MOV,S_L,tmpref,r));
+                    reference_reset_symbol(tmpref,ref.symbol,0);
+                    tmpref.refaddr:=addr_pic;
+                    tmpref.base:=current_procinfo.got;
+                    list.concat(taicpu.op_ref_reg(A_MOV,S_L,tmpref,r));
 {$endif x86_64}
-                    end
-                  else
-                    begin
-                      tmpref:=ref;
-                      tmpref.refaddr:=ADDR_FULL;
-                      list.concat(Taicpu.op_ref_reg(A_MOV,tcgsize2opsize[OS_ADDR],tmpref,r));
-                    end;
-                end
+                  end
+                else
+                  begin
+                    tmpref:=ref;
+                    tmpref.refaddr:=ADDR_FULL;
+                    list.concat(Taicpu.op_ref_reg(A_MOV,tcgsize2opsize[OS_ADDR],tmpref,r));
+                  end
               else
-                a_load_const_reg(list,OS_ADDR,offset,r);
-            end
-          else if (base=NR_NO) and (index<>NR_NO) and
-                  (offset=0) and (scalefactor=0) and (symbol=nil) then
-            a_load_reg_reg(list,OS_ADDR,OS_ADDR,index,r)
-          else if (base<>NR_NO) and (index=NR_NO) and
-                  (offset=0) and (symbol=nil) then
-            a_load_reg_reg(list,OS_ADDR,OS_ADDR,base,r)
-          else
-            begin
-              tmpref:=ref;
-              make_simple_ref(list,tmpref);
-              list.concat(taicpu.op_ref_reg(A_LEA,tcgsize2opsize[OS_ADDR],tmpref,r));
-            end;
+                a_load_const_reg(list,OS_ADDR,offset,r)
+            else if (base=NR_NO) and (index<>NR_NO) and
+                    (offset=0) and (scalefactor=0) and (symbol=nil) then
+              a_load_reg_reg(list,OS_ADDR,OS_ADDR,index,r)
+            else if (base<>NR_NO) and (index=NR_NO) and
+                    (offset=0) and (symbol=nil) then
+                a_load_reg_reg(list,OS_ADDR,OS_ADDR,base,r)
+            else
+              begin
+                tmpref:=ref;
+                make_simple_ref(list,tmpref);
+                list.concat(Taicpu.op_ref_reg(A_LEA,tcgsize2opsize[OS_ADDR],tmpref,r));
+              end;
+            if (segment<>NR_NO) then
+              if segment=NR_GS then
+                begin
+{$ifdef segment_threadvars}
+                  {Convert thread local address to a process global addres
+                   as we cannot handle far pointers.}
+                  reference_reset_symbol(tmpref,objectlibrary.newasmsymbol(
+                    '___fpc_threadvar_offset',AB_EXTERNAL,AT_DATA),0);
+                  tmpref.segment:=NR_GS;
+                  list.concat(Taicpu.op_ref_reg(A_ADD,tcgsize2opsize[OS_ADDR],tmpref,r));
+{$endif}
+                end
+            else
+              cgmessage(cg_e_cant_use_far_pointer_there);
+          end;
       end;