diff --git a/compiler/aasmbase.pas b/compiler/aasmbase.pas index 86e108917a..3fc55a81bc 100644 --- a/compiler/aasmbase.pas +++ b/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', diff --git a/compiler/aasmtai.pas b/compiler/aasmtai.pas index 3735bd2348..e73d9a26a7 100644 --- a/compiler/aasmtai.pas +++ b/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); diff --git a/compiler/aggas.pas b/compiler/aggas.pas index 986b25c8c9..dbe503ecb7 100644 --- a/compiler/aggas.pas +++ b/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) } diff --git a/compiler/assemble.pas b/compiler/assemble.pas index 0ff5661622..dc5a560a70 100644 --- a/compiler/assemble.pas +++ b/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); diff --git a/compiler/i386/ag386nsm.pas b/compiler/i386/ag386nsm.pas index 2c0dec6e00..a9d4adc146 100644 --- a/compiler/i386/ag386nsm.pas +++ b/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) } diff --git a/compiler/i386/cgcpu.pas b/compiler/i386/cgcpu.pas index d10e6787ca..5440f160c4 100644 --- a/compiler/i386/cgcpu.pas +++ b/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 diff --git a/compiler/ncgld.pas b/compiler/ncgld.pas index 4d3560b4db..e8d5e9dc7d 100644 --- a/compiler/ncgld.pas +++ b/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 diff --git a/compiler/ncgutil.pas b/compiler/ncgutil.pas index cbd83ada5a..baa9e27af5 100644 --- a/compiler/ncgutil.pas +++ b/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 diff --git a/compiler/ogcoff.pas b/compiler/ogcoff.pas index bc6a7d16e9..5078926f5d 100644 --- a/compiler/ogcoff.pas +++ b/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', diff --git a/compiler/ogelf.pas b/compiler/ogelf.pas index c1e1d7b9f6..cde8fc55d0 100644 --- a/compiler/ogelf.pas +++ b/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 diff --git a/compiler/parser.pas b/compiler/parser.pas index ab7d1d687e..8c7babb069 100644 --- a/compiler/parser.pas +++ b/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 diff --git a/compiler/pdecl.pas b/compiler/pdecl.pas index 082efd7ab1..84ba0ac5b9 100644 --- a/compiler/pdecl.pas +++ b/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; diff --git a/compiler/pdecobj.pas b/compiler/pdecobj.pas index 4f904828fd..392ce28f61 100644 --- a/compiler/pdecobj.pas +++ b/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; diff --git a/compiler/pdecvar.pas b/compiler/pdecvar.pas index 45c621bcf0..f28f1674d5 100644 --- a/compiler/pdecvar.pas +++ b/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 } diff --git a/compiler/pmodules.pas b/compiler/pmodules.pas index 347b0dd1ba..5652506950 100644 --- a/compiler/pmodules.pas +++ b/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; diff --git a/compiler/ptype.pas b/compiler/ptype.pas index e4635adc38..1e24339775 100644 --- a/compiler/ptype.pas +++ b/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; diff --git a/compiler/x86/agx86int.pas b/compiler/x86/agx86int.pas index 533dd846f2..b7cd42a55d 100644 --- a/compiler/x86/agx86int.pas +++ b/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) } diff --git a/compiler/x86/cgx86.pas b/compiler/x86/cgx86.pas index b8024c0aa1..ba8f9374e3 100644 --- a/compiler/x86/cgx86.pas +++ b/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;