* removed a_call_ref

This commit is contained in:
peter 2003-09-28 13:54:43 +00:00
parent dea558b5c7
commit a561878746

View File

@ -2,7 +2,7 @@
$Id$
Copyright (c) 1998-2002 by Florian Klaempfl
Generate i386 assembler for in call nodes
Generate assembler for call nodes
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -134,8 +134,8 @@ implementation
if paramanager.push_addr_param(vs_value,left.resulttype.def,calloption) then
begin
inc(pushedparasize,POINTER_SIZE);
cg.a_paramaddr_ref(exprasmlist,left.location.reference,tempparaloc);
location_release(exprasmlist,left.location);
cg.a_paramaddr_ref(exprasmlist,left.location.reference,tempparaloc);
end
else
push_value_para(exprasmlist,left,vs_value,calloption,alignment,tempparaloc);
@ -153,8 +153,8 @@ implementation
internalerror(200305071);
inc(pushedparasize,POINTER_SIZE);
cg.a_paramaddr_ref(exprasmlist,left.location.reference,tempparaloc);
location_release(exprasmlist,left.location);
cg.a_paramaddr_ref(exprasmlist,left.location.reference,tempparaloc);
end
else
begin
@ -180,64 +180,52 @@ implementation
if (left.nodetype=addrn) and
(not(nf_procvarload in left.flags)) then
begin
cg.a_param_loc(exprasmlist,left.location,tempparaloc);
location_release(exprasmlist,left.location);
cg.a_param_loc(exprasmlist,left.location,tempparaloc);
end
else
begin
if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
internalerror(200304235);
cg.a_paramaddr_ref(exprasmlist,left.location.reference,tempparaloc);
location_release(exprasmlist,left.location);
cg.a_paramaddr_ref(exprasmlist,left.location.reference,tempparaloc);
end;
end
{ Normal parameter }
else
{ don't push a node that already generated a pointer type
by address for implicit hidden parameters }
if (not(
paraitem.is_hidden and
(left.resulttype.def.deftype in [pointerdef,classrefdef])
) and
paramanager.push_addr_param(paraitem.paratyp,paraitem.paratype.def,calloption)) then
begin
{ Check for passing a constant to var,out parameter }
if (paraitem.paratyp in [vs_var,vs_out]) and
(left.location.loc<>LOC_REFERENCE) then
begin
{ passing self to a var parameter is allowed in
TP and delphi }
if not((left.location.loc=LOC_CREFERENCE) and
is_self_node(left)) then
internalerror(200106041);
end;
if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
begin
{ allow passing nil to a procvardef (methodpointer) }
if (left.nodetype=typeconvn) and
(left.resulttype.def.deftype=procvardef) and
(ttypeconvnode(left).left.nodetype=niln) then
begin
tg.GetTemp(exprasmlist,tcgsize2size[left.location.size],tt_normal,href);
if not (left.location.size in [OS_64,OS_S64]) then
cg.a_load_loc_ref(exprasmlist,left.location.size,left.location,href)
else
cg64.a_load64_loc_ref(exprasmlist,left.location,href);
location_reset(left.location,LOC_REFERENCE,left.location.size);
left.location.reference:=href;
end
else
internalerror(200204011);
end;
inc(pushedparasize,POINTER_SIZE);
cg.a_paramaddr_ref(exprasmlist,left.location.reference,tempparaloc);
location_release(exprasmlist,left.location);
end
else
begin
push_value_para(exprasmlist,left,paraitem.paratyp,calloption,alignment,tempparaloc);
end;
begin
{ don't push a node that already generated a pointer type
by address for implicit hidden parameters }
if (not(
paraitem.is_hidden and
(left.resulttype.def.deftype in [pointerdef,classrefdef])
) and
paramanager.push_addr_param(paraitem.paratyp,paraitem.paratype.def,calloption)) then
begin
{ Check for passing a constant to var,out parameter }
if (paraitem.paratyp in [vs_var,vs_out]) and
(left.location.loc<>LOC_REFERENCE) then
begin
{ passing self to a var parameter is allowed in
TP and delphi }
if not((left.location.loc=LOC_CREFERENCE) and
is_self_node(left)) then
internalerror(200106041);
end;
{ Move to memory }
if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
location_force_mem(exprasmlist,left.location);
{ Push address }
inc(pushedparasize,POINTER_SIZE);
location_release(exprasmlist,left.location);
cg.a_paramaddr_ref(exprasmlist,left.location.reference,tempparaloc);
end
else
begin
push_value_para(exprasmlist,left,paraitem.paratyp,calloption,alignment,tempparaloc);
end;
end;
truelabel:=otlabel;
falselabel:=oflabel;
@ -483,9 +471,7 @@ implementation
href,helpref : treference;
para_alignment,
pop_size : longint;
{$ifndef usecallref}
pvreg,
{$endif usecallref}
vmtreg,vmtreg2 : tregister;
oldaktcallnode : tcallnode;
@ -615,50 +601,37 @@ implementation
{ Align stack if required }
pop_size:=align_parasize;
{ Push parameters }
{ Process parameters, register parameters will be loaded
in imaginary registers. The actual load to the correct
register is done just before the call }
oldaktcallnode:=aktcallnode;
aktcallnode:=self;
{$ifndef i386}
{ process procvar. Done here already, because otherwise it may }
{ destroy registers containing a parameter for the actual }
{ function call (e.g. if it's a function, its result will }
{ overwrite r3, which contains the first parameter) (JM) }
if assigned(right) then
secondpass(right);
if (po_virtualmethod in procdefinition.procoptions) and
assigned(methodpointer) then
begin
secondpass(methodpointer);
location_force_reg(exprasmlist,methodpointer.location,OS_ADDR,false);
{ virtual methods require an index }
if tprocdef(procdefinition).extnumber=-1 then
internalerror(200304021);
{ VMT should already be loaded in a register }
if methodpointer.location.register=NR_NO then
internalerror(200304022);
{ test validity of VMT }
if not(is_interface(tprocdef(procdefinition)._class)) and
not(is_cppclass(tprocdef(procdefinition)._class)) then
cg.g_maybe_testvmt(exprasmlist,methodpointer.location.register,tprocdef(procdefinition)._class);
end;
{$endif not i386}
{ Process parameters }
if assigned(left) then
begin
tcallparanode(left).secondcallparan(procdefinition.proccalloption,procdefinition.paraalign);
pushparas;
end;
tcallparanode(left).secondcallparan(procdefinition.proccalloption,procdefinition.paraalign);
aktcallnode:=oldaktcallnode;
{ procedure variable or normal function call ? }
if (right=nil) then
begin
if (po_virtualmethod in procdefinition.procoptions) and
assigned(methodpointer) then
begin
secondpass(methodpointer);
location_force_reg(exprasmlist,methodpointer.location,OS_ADDR,false);
{ virtual methods require an index }
if tprocdef(procdefinition).extnumber=-1 then
internalerror(200304021);
{ VMT should already be loaded in a register }
if methodpointer.location.register=NR_NO then
internalerror(200304022);
{ test validity of VMT }
if not(is_interface(tprocdef(procdefinition)._class)) and
not(is_cppclass(tprocdef(procdefinition)._class)) then
cg.g_maybe_testvmt(exprasmlist,methodpointer.location.register,tprocdef(procdefinition)._class);
end;
{ push base pointer ?}
if (current_procinfo.procdef.parast.symtablelevel>=normal_function_level) and
assigned(tprocdef(procdefinition).parast) and
@ -670,38 +643,25 @@ implementation
if (po_virtualmethod in procdefinition.procoptions) and
assigned(methodpointer) then
begin
{$ifdef i386}
secondpass(methodpointer);
location_force_reg(exprasmlist,methodpointer.location,OS_ADDR,false);
vmtreg:=methodpointer.location.register;
{ virtual methods require an index }
if tprocdef(procdefinition).extnumber=-1 then
internalerror(200304021);
{ VMT should already be loaded in a register }
if vmtreg=NR_NO then
internalerror(200304022);
{ test validity of VMT }
if not(is_interface(tprocdef(procdefinition)._class)) and
not(is_cppclass(tprocdef(procdefinition)._class)) then
cg.g_maybe_testvmt(exprasmlist,vmtreg,tprocdef(procdefinition)._class);
{$else}
vmtreg:=methodpointer.location.register;
{$endif}
{ release self }
rg.ungetaddressregister(exprasmlist,vmtreg);
vmtreg2:=rg.getabtregisterint(exprasmlist,OS_ADDR);
rg.ungetregisterint(exprasmlist,vmtreg2);
cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,vmtreg,vmtreg2);
{$ifndef usecallref}
{ load virtual method (procvar) }
pvreg:=rg.getabtregisterint(exprasmlist,OS_ADDR);
reference_reset_base(href,vmtreg2,
tprocdef(procdefinition)._class.vmtmethodoffset(tprocdef(procdefinition).extnumber));
rg.ungetregisterint(exprasmlist,pvreg);
cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,pvreg);
{$endif usecallref}
{ Load parameters that are in temporary registers in the
correct parameter register }
if assigned(left) then
pushparas;
{ free the resources allocated for the parameters }
freeparas;
@ -709,16 +669,15 @@ implementation
rg.allocexplicitregistersint(exprasmlist,regs_to_alloc);
{ call method }
{$ifdef usecallref}
reference_reset_base(href,vmtreg2,
tprocdef(procdefinition)._class.vmtmethodoffset(tprocdef(procdefinition).extnumber));
cg.a_call_ref(exprasmlist,href);
{$else usecallref}
cg.a_call_reg(exprasmlist,pvreg);
{$endif usecallref}
end
else
begin
{ Load parameters that are in temporary registers in the
correct parameter register }
if assigned(left) then
pushparas;
{ free the resources allocated for the parameters }
freeparas;
@ -733,34 +692,8 @@ implementation
else
{ now procedure variable case }
begin
{$ifdef i386}
secondpass(right);
{$endif i386}
{$ifdef usecallref}
if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
begin
helpref:=right.location.reference;
if (helpref.index<>NR_NO) and (helpref.index<>NR_FRAME_POINTER_REG) then
begin
rg.ungetregisterint(exprasmlist,helpref.index);
helpref.index:=rg.getabtregisterint(exprasmlist,OS_ADDR);
cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,
right.location.reference.index,helpref.index);
end;
if (helpref.base<>NR_NO) and (helpref.base<>NR_FRAME_POINTER_REG) then
begin
rg.ungetregisterint(exprasmlist,helpref.base);
helpref.base:=rg.getabtregisterint(exprasmlist,OS_ADDR);
cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,
right.location.reference.base,helpref.base);
end;
reference_release(exprasmlist,helpref);
end
else
rg.ungetregisterint(exprasmlist,right.location.register);
location_freetemp(exprasmlist,right.location);
{$else usecallref}
location_release(exprasmlist,right.location);
pvreg:=rg.getabtregisterint(exprasmlist,OS_ADDR);
rg.ungetregisterint(exprasmlist,pvreg);
{ Only load OS_ADDR from the reference }
@ -768,9 +701,12 @@ implementation
cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,right.location.reference,pvreg)
else
cg.a_load_loc_reg(exprasmlist,OS_ADDR,right.location,pvreg);
location_release(exprasmlist,right.location);
location_freetemp(exprasmlist,right.location);
{$endif usecallref}
{ Load parameters that are in temporary registers in the
correct parameter register }
if assigned(left) then
pushparas;
{ free the resources allocated for the parameters }
freeparas;
@ -783,14 +719,7 @@ implementation
extra_interrupt_code;
rg.saveotherregvars(exprasmlist,ALL_OTHERREGISTERS);
{$ifdef usecallref}
if right.location.loc in [LOC_REFERENCE,LOC_CREFERENCE] then
cg.a_call_ref(exprasmlist,helpref)
else
cg.a_call_reg(exprasmlist,right.location.register);
{$else usecallref}
cg.a_call_reg(exprasmlist,pvreg);
{$endif usecallref}
end;
{ Need to remove the parameters from the stack? }
@ -1233,7 +1162,10 @@ begin
end.
{
$Log$
Revision 1.117 2003-09-25 21:28:00 peter
Revision 1.118 2003-09-28 13:54:43 peter
* removed a_call_ref
Revision 1.117 2003/09/25 21:28:00 peter
* parameter fixes
Revision 1.116 2003/09/23 17:56:05 peter