mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-10 10:26:17 +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);
|
||||
|
||||
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',
|
||||
|
@ -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);
|
||||
|
@ -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) }
|
||||
|
@ -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);
|
||||
|
@ -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) }
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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',
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 }
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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) }
|
||||
|
@ -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;
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user