* Proof of concept: Support threadvars using segment registers.

git-svn-id: trunk@740 -
This commit is contained in:
daniel 2005-07-24 21:06:23 +00:00
parent a1dd230825
commit 22e89e1a42
18 changed files with 149 additions and 94 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -686,46 +686,58 @@ unit cgx86;
tmpref : treference; tmpref : treference;
begin begin
with ref do 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 if assigned(ref.symbol) then
begin if cs_create_pic in aktmoduleswitches then
if cs_create_pic in aktmoduleswitches then begin
begin
{$ifdef x86_64} {$ifdef x86_64}
reference_reset_symbol(tmpref,ref.symbol,0); reference_reset_symbol(tmpref,ref.symbol,0);
tmpref.refaddr:=addr_pic; tmpref.refaddr:=addr_pic;
tmpref.base:=NR_RIP; tmpref.base:=NR_RIP;
list.concat(taicpu.op_ref_reg(A_MOV,S_Q,tmpref,r)); list.concat(taicpu.op_ref_reg(A_MOV,S_Q,tmpref,r));
{$else x86_64} {$else x86_64}
reference_reset_symbol(tmpref,ref.symbol,0); reference_reset_symbol(tmpref,ref.symbol,0);
tmpref.refaddr:=addr_pic; tmpref.refaddr:=addr_pic;
tmpref.base:=current_procinfo.got; tmpref.base:=current_procinfo.got;
list.concat(taicpu.op_ref_reg(A_MOV,S_L,tmpref,r)); list.concat(taicpu.op_ref_reg(A_MOV,S_L,tmpref,r));
{$endif x86_64} {$endif x86_64}
end end
else else
begin begin
tmpref:=ref; tmpref:=ref;
tmpref.refaddr:=ADDR_FULL; tmpref.refaddr:=ADDR_FULL;
list.concat(Taicpu.op_ref_reg(A_MOV,tcgsize2opsize[OS_ADDR],tmpref,r)); list.concat(Taicpu.op_ref_reg(A_MOV,tcgsize2opsize[OS_ADDR],tmpref,r));
end; end
end
else else
a_load_const_reg(list,OS_ADDR,offset,r); a_load_const_reg(list,OS_ADDR,offset,r)
end else if (base=NR_NO) and (index<>NR_NO) and
else if (base=NR_NO) and (index<>NR_NO) and (offset=0) and (scalefactor=0) and (symbol=nil) then
(offset=0) and (scalefactor=0) and (symbol=nil) then a_load_reg_reg(list,OS_ADDR,OS_ADDR,index,r)
a_load_reg_reg(list,OS_ADDR,OS_ADDR,index,r) else if (base<>NR_NO) and (index=NR_NO) and
else if (base<>NR_NO) and (index=NR_NO) and (offset=0) and (symbol=nil) then
(offset=0) and (symbol=nil) then a_load_reg_reg(list,OS_ADDR,OS_ADDR,base,r)
a_load_reg_reg(list,OS_ADDR,OS_ADDR,base,r) else
else begin
begin tmpref:=ref;
tmpref:=ref; make_simple_ref(list,tmpref);
make_simple_ref(list,tmpref); list.concat(Taicpu.op_ref_reg(A_LEA,tcgsize2opsize[OS_ADDR],tmpref,r));
list.concat(taicpu.op_ref_reg(A_LEA,tcgsize2opsize[OS_ADDR],tmpref,r)); end;
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; end;