mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-21 15:49:26 +02:00
* formatting fix
git-svn-id: trunk@12435 -
This commit is contained in:
parent
23bbb087bd
commit
e512367dbd
@ -223,299 +223,298 @@ implementation
|
||||
norelocatelab : tasmlabel;
|
||||
paraloc1 : tcgpara;
|
||||
begin
|
||||
|
||||
{ we don't know the size of all arrays }
|
||||
newsize:=def_cgsize(resultdef);
|
||||
location_reset(location,LOC_REFERENCE,newsize);
|
||||
case symtableentry.typ of
|
||||
absolutevarsym :
|
||||
begin
|
||||
{ this is only for toasm and toaddr }
|
||||
case tabsolutevarsym(symtableentry).abstyp of
|
||||
toaddr :
|
||||
begin
|
||||
{$ifdef i386}
|
||||
if tabsolutevarsym(symtableentry).absseg then
|
||||
location.reference.segment:=NR_FS;
|
||||
{$endif i386}
|
||||
location.reference.offset:=tabsolutevarsym(symtableentry).addroffset;
|
||||
end;
|
||||
toasm :
|
||||
location.reference.symbol:=current_asmdata.RefAsmSymbol(tabsolutevarsym(symtableentry).mangledname);
|
||||
else
|
||||
internalerror(200310283);
|
||||
end;
|
||||
end;
|
||||
constsym:
|
||||
{ we don't know the size of all arrays }
|
||||
newsize:=def_cgsize(resultdef);
|
||||
location_reset(location,LOC_REFERENCE,newsize);
|
||||
case symtableentry.typ of
|
||||
absolutevarsym :
|
||||
begin
|
||||
if tconstsym(symtableentry).consttyp=constresourcestring then
|
||||
begin
|
||||
location_reset(location,LOC_CREFERENCE,OS_ADDR);
|
||||
location.reference.symbol:=current_asmdata.RefAsmSymbol(make_mangledname('RESSTR',symtableentry.owner,symtableentry.name));
|
||||
{ Resourcestring layout:
|
||||
TResourceStringRecord = Packed Record
|
||||
Name,
|
||||
CurrentValue,
|
||||
DefaultValue : AnsiString;
|
||||
HashValue : LongWord;
|
||||
end;
|
||||
}
|
||||
location.reference.offset:=sizeof(pint);
|
||||
end
|
||||
else
|
||||
internalerror(22798);
|
||||
{ this is only for toasm and toaddr }
|
||||
case tabsolutevarsym(symtableentry).abstyp of
|
||||
toaddr :
|
||||
begin
|
||||
{$ifdef i386}
|
||||
if tabsolutevarsym(symtableentry).absseg then
|
||||
location.reference.segment:=NR_FS;
|
||||
{$endif i386}
|
||||
location.reference.offset:=tabsolutevarsym(symtableentry).addroffset;
|
||||
end;
|
||||
toasm :
|
||||
location.reference.symbol:=current_asmdata.RefAsmSymbol(tabsolutevarsym(symtableentry).mangledname);
|
||||
else
|
||||
internalerror(200310283);
|
||||
end;
|
||||
end;
|
||||
staticvarsym :
|
||||
begin
|
||||
gvs:=tstaticvarsym(symtableentry);
|
||||
if ([vo_is_dll_var,vo_is_external] * gvs.varoptions <> []) then
|
||||
constsym:
|
||||
begin
|
||||
if tconstsym(symtableentry).consttyp=constresourcestring then
|
||||
begin
|
||||
location.reference.base := cg.g_indirect_sym_load(current_asmdata.CurrAsmList,tstaticvarsym(symtableentry).mangledname,
|
||||
vo_is_weak_external in gvs.varoptions);
|
||||
if (location.reference.base <> NR_NO) then
|
||||
exit;
|
||||
location_reset(location,LOC_CREFERENCE,OS_ADDR);
|
||||
location.reference.symbol:=current_asmdata.RefAsmSymbol(make_mangledname('RESSTR',symtableentry.owner,symtableentry.name));
|
||||
{ Resourcestring layout:
|
||||
TResourceStringRecord = Packed Record
|
||||
Name,
|
||||
CurrentValue,
|
||||
DefaultValue : AnsiString;
|
||||
HashValue : LongWord;
|
||||
end;
|
||||
}
|
||||
location.reference.offset:=sizeof(pint);
|
||||
end
|
||||
else
|
||||
internalerror(22798);
|
||||
end;
|
||||
staticvarsym :
|
||||
begin
|
||||
gvs:=tstaticvarsym(symtableentry);
|
||||
if ([vo_is_dll_var,vo_is_external] * gvs.varoptions <> []) then
|
||||
begin
|
||||
location.reference.base := cg.g_indirect_sym_load(current_asmdata.CurrAsmList,tstaticvarsym(symtableentry).mangledname,
|
||||
vo_is_weak_external in gvs.varoptions);
|
||||
if (location.reference.base <> NR_NO) then
|
||||
exit;
|
||||
end;
|
||||
|
||||
if (vo_is_dll_var in gvs.varoptions) then
|
||||
{ DLL variable }
|
||||
begin
|
||||
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
if not(vo_is_weak_external in gvs.varoptions) then
|
||||
location.reference.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname)
|
||||
else
|
||||
location.reference.symbol:=current_asmdata.WeakRefAsmSymbol(tstaticvarsym(symtableentry).mangledname);
|
||||
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,location.reference,hregister);
|
||||
reference_reset_base(location.reference,hregister,0);
|
||||
end
|
||||
{ Thread variable }
|
||||
else if (vo_is_thread_var in gvs.varoptions) and
|
||||
not(tf_section_threadvars in target_info.flags) then
|
||||
begin
|
||||
if (tf_section_threadvars in target_info.flags) then
|
||||
begin
|
||||
if gvs.localloc.loc=LOC_INVALID then
|
||||
if not(vo_is_weak_external in gvs.varoptions) then
|
||||
reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname),0)
|
||||
else
|
||||
reference_reset_symbol(location.reference,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0)
|
||||
else
|
||||
location:=gvs.localloc;
|
||||
{$ifdef i386}
|
||||
case target_info.system of
|
||||
system_i386_linux:
|
||||
location.reference.segment:=NR_GS;
|
||||
system_i386_win32:
|
||||
location.reference.segment:=NR_FS;
|
||||
end;
|
||||
{$endif i386}
|
||||
end
|
||||
else
|
||||
begin
|
||||
{
|
||||
Thread var loading is optimized to first check if
|
||||
a relocate function is available. When the function
|
||||
is available it is called to retrieve the address.
|
||||
Otherwise the address is loaded with the symbol
|
||||
|
||||
The code needs to be in the order to first handle the
|
||||
call and then the address load to be sure that the
|
||||
register that is used for returning is the same (PFV)
|
||||
}
|
||||
current_asmdata.getjumplabel(norelocatelab);
|
||||
current_asmdata.getjumplabel(endrelocatelab);
|
||||
{ make sure hregister can't allocate the register necessary for the parameter }
|
||||
paraloc1.init;
|
||||
paramanager.getintparaloc(pocall_default,1,paraloc1);
|
||||
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
reference_reset_symbol(href,current_asmdata.RefAsmSymbol('FPC_THREADVAR_RELOCATE'),0);
|
||||
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
|
||||
cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_ADDR,OC_EQ,0,hregister,norelocatelab);
|
||||
{ don't save the allocated register else the result will be destroyed later }
|
||||
if not(vo_is_weak_external in gvs.varoptions) then
|
||||
reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname),0)
|
||||
else
|
||||
reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0);
|
||||
paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc1);
|
||||
cg.a_param_ref(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
|
||||
paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc1);
|
||||
paraloc1.done;
|
||||
cg.allocallcpuregisters(current_asmdata.CurrAsmList);
|
||||
cg.a_call_reg(current_asmdata.CurrAsmList,hregister);
|
||||
cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
|
||||
cg.getcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
|
||||
cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
|
||||
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_ADDR,NR_FUNCTION_RESULT_REG,hregister);
|
||||
cg.a_jmp_always(current_asmdata.CurrAsmList,endrelocatelab);
|
||||
cg.a_label(current_asmdata.CurrAsmList,norelocatelab);
|
||||
{ no relocation needed, load the address of the variable only, the
|
||||
layout of a threadvar is (4 bytes pointer):
|
||||
0 - Threadvar index
|
||||
4 - Threadvar value in single threading }
|
||||
if not(vo_is_weak_external in gvs.varoptions) then
|
||||
reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname),sizeof(pint))
|
||||
else
|
||||
reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),sizeof(pint));
|
||||
cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,hregister);
|
||||
cg.a_label(current_asmdata.CurrAsmList,endrelocatelab);
|
||||
location.reference.base:=hregister;
|
||||
end;
|
||||
end
|
||||
{ Normal (or external) variable }
|
||||
else
|
||||
begin
|
||||
if gvs.localloc.loc=LOC_INVALID then
|
||||
if not(vo_is_weak_external in gvs.varoptions) then
|
||||
reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname),0)
|
||||
else
|
||||
reference_reset_symbol(location.reference,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0)
|
||||
else
|
||||
location:=gvs.localloc;
|
||||
end;
|
||||
|
||||
if (vo_is_dll_var in gvs.varoptions) then
|
||||
{ DLL variable }
|
||||
{ make const a LOC_CREFERENCE }
|
||||
if (gvs.varspez=vs_const) and
|
||||
(location.loc=LOC_REFERENCE) then
|
||||
location.loc:=LOC_CREFERENCE;
|
||||
location.reference.alignment:=gvs.vardef.alignment;
|
||||
end;
|
||||
paravarsym,
|
||||
localvarsym :
|
||||
begin
|
||||
vs:=tabstractnormalvarsym(symtableentry);
|
||||
{ Nested variable }
|
||||
if assigned(left) then
|
||||
begin
|
||||
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
if not(vo_is_weak_external in gvs.varoptions) then
|
||||
location.reference.symbol:=current_asmdata.RefAsmSymbol(tstaticvarsym(symtableentry).mangledname)
|
||||
else
|
||||
location.reference.symbol:=current_asmdata.WeakRefAsmSymbol(tstaticvarsym(symtableentry).mangledname);
|
||||
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,location.reference,hregister);
|
||||
reference_reset_base(location.reference,hregister,0);
|
||||
secondpass(left);
|
||||
if left.location.loc<>LOC_REGISTER then
|
||||
internalerror(200309286);
|
||||
if vs.localloc.loc<>LOC_REFERENCE then
|
||||
internalerror(200409241);
|
||||
reference_reset_base(location.reference,left.location.register,vs.localloc.reference.offset);
|
||||
end
|
||||
{ Thread variable }
|
||||
else if (vo_is_thread_var in gvs.varoptions) and
|
||||
not(tf_section_threadvars in target_info.flags) then
|
||||
else
|
||||
location:=vs.localloc;
|
||||
|
||||
{ handle call by reference variables when they are not
|
||||
alreayd copied to local copies. Also ignore the reference
|
||||
when we need to load the self pointer for objects }
|
||||
if is_addr_param_load then
|
||||
begin
|
||||
if (tf_section_threadvars in target_info.flags) then
|
||||
if (location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
|
||||
hregister:=location.register
|
||||
else
|
||||
begin
|
||||
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
{ we need to load only an address }
|
||||
location.size:=OS_ADDR;
|
||||
cg.a_load_loc_reg(current_asmdata.CurrAsmList,location.size,location,hregister);
|
||||
end;
|
||||
location_reset(location,LOC_REFERENCE,newsize);
|
||||
location.reference.base:=hregister;
|
||||
end;
|
||||
|
||||
{ make const a LOC_CREFERENCE }
|
||||
if (vs.varspez=vs_const) and
|
||||
(location.loc=LOC_REFERENCE) then
|
||||
location.loc:=LOC_CREFERENCE;
|
||||
end;
|
||||
procsym:
|
||||
begin
|
||||
if not assigned(procdef) then
|
||||
internalerror(200312011);
|
||||
if assigned(left) then
|
||||
begin
|
||||
{$if sizeof(pint) = 4}
|
||||
location_reset(location,LOC_CREFERENCE,OS_64);
|
||||
{$else} {$if sizeof(pint) = 8}
|
||||
location_reset(location,LOC_CREFERENCE,OS_128);
|
||||
{$else}
|
||||
internalerror(20020520);
|
||||
{$endif} {$endif}
|
||||
tg.GetTemp(current_asmdata.CurrAsmList,2*sizeof(pint),sizeof(pint),tt_normal,location.reference);
|
||||
secondpass(left);
|
||||
|
||||
{ load class instance/classrefdef address }
|
||||
if left.location.loc=LOC_CONSTANT then
|
||||
location_force_reg(current_asmdata.CurrAsmList,left.location,OS_ADDR,false);
|
||||
case left.location.loc of
|
||||
LOC_CREGISTER,
|
||||
LOC_REGISTER:
|
||||
begin
|
||||
{ this is not possible for objects }
|
||||
if is_object(left.resultdef) then
|
||||
internalerror(200304234);
|
||||
hregister:=left.location.register;
|
||||
end;
|
||||
LOC_CREFERENCE,
|
||||
LOC_REFERENCE:
|
||||
begin
|
||||
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
if not is_object(left.resultdef) then
|
||||
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.reference,hregister)
|
||||
else
|
||||
cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,hregister);
|
||||
location_freetemp(current_asmdata.CurrAsmList,left.location);
|
||||
end;
|
||||
else
|
||||
internalerror(200610311);
|
||||
end;
|
||||
|
||||
{ store the class instance or classredef address }
|
||||
href:=location.reference;
|
||||
inc(href.offset,sizeof(pint));
|
||||
cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,href);
|
||||
|
||||
{ virtual method ? }
|
||||
if (po_virtualmethod in procdef.procoptions) and
|
||||
not(nf_inherited in flags) then
|
||||
begin
|
||||
if gvs.localloc.loc=LOC_INVALID then
|
||||
if not(vo_is_weak_external in gvs.varoptions) then
|
||||
reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname),0)
|
||||
else
|
||||
reference_reset_symbol(location.reference,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0)
|
||||
else
|
||||
location:=gvs.localloc;
|
||||
{$ifdef i386}
|
||||
case target_info.system of
|
||||
system_i386_linux:
|
||||
location.reference.segment:=NR_GS;
|
||||
system_i386_win32:
|
||||
location.reference.segment:=NR_FS;
|
||||
end;
|
||||
{$endif i386}
|
||||
{ a classrefdef already points to the VMT }
|
||||
if (left.resultdef.typ<>classrefdef) then
|
||||
begin
|
||||
{ load vmt pointer }
|
||||
reference_reset_base(href,hregister,0);
|
||||
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
|
||||
end;
|
||||
{ load method address }
|
||||
reference_reset_base(href,hregister,procdef._class.vmtmethodoffset(procdef.extnumber));
|
||||
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
|
||||
{ ... and store it }
|
||||
cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,location.reference);
|
||||
end
|
||||
else
|
||||
begin
|
||||
{
|
||||
Thread var loading is optimized to first check if
|
||||
a relocate function is available. When the function
|
||||
is available it is called to retrieve the address.
|
||||
Otherwise the address is loaded with the symbol
|
||||
|
||||
The code needs to be in the order to first handle the
|
||||
call and then the address load to be sure that the
|
||||
register that is used for returning is the same (PFV)
|
||||
}
|
||||
current_asmdata.getjumplabel(norelocatelab);
|
||||
current_asmdata.getjumplabel(endrelocatelab);
|
||||
{ make sure hregister can't allocate the register necessary for the parameter }
|
||||
paraloc1.init;
|
||||
paramanager.getintparaloc(pocall_default,1,paraloc1);
|
||||
{ load address of the function }
|
||||
reference_reset_symbol(href,current_asmdata.RefAsmSymbol(procdef.mangledname),0);
|
||||
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
reference_reset_symbol(href,current_asmdata.RefAsmSymbol('FPC_THREADVAR_RELOCATE'),0);
|
||||
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
|
||||
cg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,OS_ADDR,OC_EQ,0,hregister,norelocatelab);
|
||||
{ don't save the allocated register else the result will be destroyed later }
|
||||
if not(vo_is_weak_external in gvs.varoptions) then
|
||||
reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname),0)
|
||||
else
|
||||
reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0);
|
||||
paramanager.allocparaloc(current_asmdata.CurrAsmList,paraloc1);
|
||||
cg.a_param_ref(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
|
||||
paramanager.freeparaloc(current_asmdata.CurrAsmList,paraloc1);
|
||||
paraloc1.done;
|
||||
cg.allocallcpuregisters(current_asmdata.CurrAsmList);
|
||||
cg.a_call_reg(current_asmdata.CurrAsmList,hregister);
|
||||
cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
|
||||
cg.getcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
|
||||
cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
|
||||
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_INT,OS_ADDR,NR_FUNCTION_RESULT_REG,hregister);
|
||||
cg.a_jmp_always(current_asmdata.CurrAsmList,endrelocatelab);
|
||||
cg.a_label(current_asmdata.CurrAsmList,norelocatelab);
|
||||
{ no relocation needed, load the address of the variable only, the
|
||||
layout of a threadvar is (4 bytes pointer):
|
||||
0 - Threadvar index
|
||||
4 - Threadvar value in single threading }
|
||||
if not(vo_is_weak_external in gvs.varoptions) then
|
||||
reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname),sizeof(pint))
|
||||
else
|
||||
reference_reset_symbol(href,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),sizeof(pint));
|
||||
cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,hregister);
|
||||
cg.a_label(current_asmdata.CurrAsmList,endrelocatelab);
|
||||
location.reference.base:=hregister;
|
||||
cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,location.reference);
|
||||
end;
|
||||
end
|
||||
{ Normal (or external) variable }
|
||||
else
|
||||
begin
|
||||
if gvs.localloc.loc=LOC_INVALID then
|
||||
if not(vo_is_weak_external in gvs.varoptions) then
|
||||
reference_reset_symbol(location.reference,current_asmdata.RefAsmSymbol(gvs.mangledname),0)
|
||||
else
|
||||
reference_reset_symbol(location.reference,current_asmdata.WeakRefAsmSymbol(gvs.mangledname),0)
|
||||
else
|
||||
location:=gvs.localloc;
|
||||
pd:=tprocdef(tprocsym(symtableentry).ProcdefList[0]);
|
||||
if (po_external in pd.procoptions) then
|
||||
location.reference.base :=
|
||||
cg.g_indirect_sym_load(current_asmdata.CurrAsmList,pd.mangledname,
|
||||
po_weakexternal in pd.procoptions);
|
||||
{!!!!! Be aware, work on virtual methods too }
|
||||
if (location.reference.base = NR_NO) then
|
||||
if not(po_weakexternal in pd.procoptions) then
|
||||
location.reference.symbol:=current_asmdata.RefAsmSymbol(procdef.mangledname)
|
||||
else
|
||||
location.reference.symbol:=current_asmdata.WeakRefAsmSymbol(procdef.mangledname);
|
||||
end;
|
||||
|
||||
{ make const a LOC_CREFERENCE }
|
||||
if (gvs.varspez=vs_const) and
|
||||
(location.loc=LOC_REFERENCE) then
|
||||
location.loc:=LOC_CREFERENCE;
|
||||
location.reference.alignment:=gvs.vardef.alignment;
|
||||
end;
|
||||
paravarsym,
|
||||
localvarsym :
|
||||
begin
|
||||
vs:=tabstractnormalvarsym(symtableentry);
|
||||
{ Nested variable }
|
||||
if assigned(left) then
|
||||
begin
|
||||
secondpass(left);
|
||||
if left.location.loc<>LOC_REGISTER then
|
||||
internalerror(200309286);
|
||||
if vs.localloc.loc<>LOC_REFERENCE then
|
||||
internalerror(200409241);
|
||||
reference_reset_base(location.reference,left.location.register,vs.localloc.reference.offset);
|
||||
end
|
||||
else
|
||||
location:=vs.localloc;
|
||||
|
||||
{ handle call by reference variables when they are not
|
||||
alreayd copied to local copies. Also ignore the reference
|
||||
when we need to load the self pointer for objects }
|
||||
if is_addr_param_load then
|
||||
begin
|
||||
if (location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
|
||||
hregister:=location.register
|
||||
else
|
||||
begin
|
||||
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
{ we need to load only an address }
|
||||
location.size:=OS_ADDR;
|
||||
cg.a_load_loc_reg(current_asmdata.CurrAsmList,location.size,location,hregister);
|
||||
end;
|
||||
location_reset(location,LOC_REFERENCE,newsize);
|
||||
location.reference.base:=hregister;
|
||||
end;
|
||||
|
||||
{ make const a LOC_CREFERENCE }
|
||||
if (vs.varspez=vs_const) and
|
||||
(location.loc=LOC_REFERENCE) then
|
||||
location.loc:=LOC_CREFERENCE;
|
||||
end;
|
||||
procsym:
|
||||
begin
|
||||
if not assigned(procdef) then
|
||||
internalerror(200312011);
|
||||
if assigned(left) then
|
||||
begin
|
||||
{$if sizeof(pint) = 4}
|
||||
location_reset(location,LOC_CREFERENCE,OS_64);
|
||||
{$else} {$if sizeof(pint) = 8}
|
||||
location_reset(location,LOC_CREFERENCE,OS_128);
|
||||
{$else}
|
||||
internalerror(20020520);
|
||||
{$endif} {$endif}
|
||||
tg.GetTemp(current_asmdata.CurrAsmList,2*sizeof(pint),sizeof(pint),tt_normal,location.reference);
|
||||
secondpass(left);
|
||||
|
||||
{ load class instance/classrefdef address }
|
||||
if left.location.loc=LOC_CONSTANT then
|
||||
location_force_reg(current_asmdata.CurrAsmList,left.location,OS_ADDR,false);
|
||||
case left.location.loc of
|
||||
LOC_CREGISTER,
|
||||
LOC_REGISTER:
|
||||
begin
|
||||
{ this is not possible for objects }
|
||||
if is_object(left.resultdef) then
|
||||
internalerror(200304234);
|
||||
hregister:=left.location.register;
|
||||
end;
|
||||
LOC_CREFERENCE,
|
||||
LOC_REFERENCE:
|
||||
begin
|
||||
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
if not is_object(left.resultdef) then
|
||||
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,left.location.reference,hregister)
|
||||
else
|
||||
cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.location.reference,hregister);
|
||||
location_freetemp(current_asmdata.CurrAsmList,left.location);
|
||||
end;
|
||||
else
|
||||
internalerror(200610311);
|
||||
end;
|
||||
|
||||
{ store the class instance or classredef address }
|
||||
href:=location.reference;
|
||||
inc(href.offset,sizeof(pint));
|
||||
cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,href);
|
||||
|
||||
{ virtual method ? }
|
||||
if (po_virtualmethod in procdef.procoptions) and
|
||||
not(nf_inherited in flags) then
|
||||
begin
|
||||
{ a classrefdef already points to the VMT }
|
||||
if (left.resultdef.typ<>classrefdef) then
|
||||
begin
|
||||
{ load vmt pointer }
|
||||
reference_reset_base(href,hregister,0);
|
||||
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
|
||||
end;
|
||||
{ load method address }
|
||||
reference_reset_base(href,hregister,procdef._class.vmtmethodoffset(procdef.extnumber));
|
||||
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,hregister);
|
||||
{ ... and store it }
|
||||
cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,location.reference);
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ load address of the function }
|
||||
reference_reset_symbol(href,current_asmdata.RefAsmSymbol(procdef.mangledname),0);
|
||||
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,hregister);
|
||||
cg.a_load_reg_ref(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,hregister,location.reference);
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
pd:=tprocdef(tprocsym(symtableentry).ProcdefList[0]);
|
||||
if (po_external in pd.procoptions) then
|
||||
location.reference.base :=
|
||||
cg.g_indirect_sym_load(current_asmdata.CurrAsmList,pd.mangledname,
|
||||
po_weakexternal in pd.procoptions);
|
||||
{!!!!! Be aware, work on virtual methods too }
|
||||
if (location.reference.base = NR_NO) then
|
||||
if not(po_weakexternal in pd.procoptions) then
|
||||
location.reference.symbol:=current_asmdata.RefAsmSymbol(procdef.mangledname)
|
||||
else
|
||||
location.reference.symbol:=current_asmdata.WeakRefAsmSymbol(procdef.mangledname);
|
||||
end;
|
||||
end;
|
||||
labelsym :
|
||||
if assigned(tlabelsym(symtableentry).asmblocklabel) then
|
||||
location.reference.symbol:=tlabelsym(symtableentry).asmblocklabel
|
||||
else
|
||||
location.reference.symbol:=tcglabelnode((tlabelsym(symtableentry).code)).getasmlabel;
|
||||
else internalerror(200510032);
|
||||
end;
|
||||
labelsym :
|
||||
if assigned(tlabelsym(symtableentry).asmblocklabel) then
|
||||
location.reference.symbol:=tlabelsym(symtableentry).asmblocklabel
|
||||
else
|
||||
location.reference.symbol:=tcglabelnode((tlabelsym(symtableentry).code)).getasmlabel;
|
||||
else internalerror(200510032);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user