mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-14 20:49:22 +02:00
* Proof of concept: Support threadvars using segment registers.
git-svn-id: trunk@740 -
This commit is contained in:
parent
a1dd230825
commit
22e89e1a42
@ -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',
|
||||||
|
@ -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);
|
||||||
|
@ -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) }
|
||||||
|
@ -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);
|
||||||
|
@ -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) }
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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',
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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 }
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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) }
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user