* refactor function result handling

* rename methodpointerinit/done to callinitblock/callcleanupblock
  * moved checks in callnode to separate functions
  * funcretnode is now always a simple node instead of a block of
    statements
  * funcret and methodpointer are generated/optimized only in pass_1 so
    a conversion from calln to loadn is much easier
  * function result assignments are much more often optimized to use the
    assignment destination location instead of using a temp

git-svn-id: trunk@8558 -
This commit is contained in:
peter 2007-09-18 22:12:07 +00:00
parent 399a2a86fa
commit e0cf015159
9 changed files with 1296 additions and 1385 deletions

View File

@ -94,12 +94,12 @@ interface
ttempcreatenode = class;
ttempinfoflag = (ti_may_be_in_reg,ti_valid,ti_nextref_set_hookoncopy_nil,ti_is_inlined_result,
ttempinfoflag = (ti_may_be_in_reg,ti_valid,ti_nextref_set_hookoncopy_nil,ti_is_funcret,
ti_addr_taken);
ttempinfoflags = set of ttempinfoflag;
const
tempinfostoreflags = [ti_may_be_in_reg,ti_is_inlined_result,ti_addr_taken];
tempinfostoreflags = [ti_may_be_in_reg,ti_is_funcret,ti_addr_taken];
type
{ to allow access to the location by temp references even after the temp has }
@ -133,7 +133,7 @@ type
{ to it and *not* generate a ttempdeletenode }
constructor create(_typedef: tdef; _size: aint; _temptype: ttemptype;allowreg:boolean); virtual;
constructor create_withnode(_typedef: tdef; _size: aint; _temptype: ttemptype; allowreg:boolean; withnode: tnode); virtual;
constructor create_inlined_result(_typedef: tdef; _size: aint; _temptype: ttemptype; allowreg:boolean); virtual;
constructor create_funcret(_typedef: tdef; _size: aint; _temptype: ttemptype; allowreg:boolean); virtual;
constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
procedure ppuwrite(ppufile:tcompilerppufile);override;
procedure buildderefimpl;override;
@ -742,10 +742,10 @@ implementation
end;
constructor ttempcreatenode.create_inlined_result(_typedef: tdef; _size: aint; _temptype: ttemptype; allowreg:boolean);
constructor ttempcreatenode.create_funcret(_typedef: tdef; _size: aint; _temptype: ttemptype; allowreg:boolean);
begin
self.create(_typedef,_size,_temptype,allowreg);
include(tempinfo^.flags,ti_is_inlined_result);
include(tempinfo^.flags,ti_is_funcret);
end;

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
{
{
Copyright (c) 1998-2002 by Florian Klaempfl
Generate assembler for call nodes
@ -45,13 +45,13 @@ interface
tcgcallnode = class(tcallnode)
private
procedure handle_return_value;
procedure release_unused_return_value;
procedure release_para_temps;
procedure pushparas;
procedure freeparas;
protected
framepointer_paraloc : tcgpara;
refcountedtemp : treference;
procedure handle_return_value;
{# This routine is used to push the current frame pointer
on the stack. This is used in nested routines where the
value of the frame pointer is always pushed as an extra
@ -509,190 +509,159 @@ implementation
var
cgsize : tcgsize;
retloc : tlocation;
hregister : tregister;
tempnode : tnode;
begin
cgsize:=procdefinition.funcretloc[callerside].size;
{ structured results are easy to handle....
needed also when result_no_used !! }
{ Check that the return location is set when the result is passed in
a parameter }
if (procdefinition.proctypeoption<>potype_constructor) and
paramanager.ret_in_param(resultdef,procdefinition.proccalloption) then
begin
{ Location should be setup by the funcret para }
if location.loc<>LOC_REFERENCE then
internalerror(200304241);
end
else
{ ansi/widestrings must be registered, so we can dispose them }
if resultdef.needs_inittable then
begin
if procdefinition.funcretloc[callerside].loc<>LOC_REGISTER then
internalerror(200409261);
internalerror(200304241);
exit;
end;
retloc:=procdefinition.funcretloc[callerside];
{$ifndef cpu64bit}
if cgsize in [OS_64,OS_S64] then
begin
{ the function result registers are already allocated }
if getsupreg(retloc.register64.reglo)<first_int_imreg then
cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register64.reglo);
retloc.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,procdefinition.funcretloc[callerside].register64.reglo,retloc.register64.reglo);
if getsupreg(retloc.register64.reghi)<first_int_imreg then
cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register64.reghi);
retloc.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,procdefinition.funcretloc[callerside].register64.reghi,retloc.register64.reghi);
end
else
{$endif cpu64bit}
begin
{ the FUNCTION_RESULT_REG is already allocated }
if getsupreg(retloc.register)<first_int_imreg then
cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register);
{ reg_ref could generate two instrcutions and allocate a register so we've to
save the result first before releasing it }
retloc.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,procdefinition.funcretloc[callerside].register,retloc.register);
end;
if not assigned(funcretnode) then
begin
location_reset(location,LOC_REFERENCE,cgsize);
location.reference:=refcountedtemp;
end
else
begin
{ in case of a regular funcretnode with ret_in_param, the }
{ original funcretnode isn't touched -> make sure it's }
{ the same here (not sure if it's necessary) }
tempnode := funcretnode.getcopy;
tempnode.pass_generate_code;
location := tempnode.location;
tempnode.free;
cg.g_decrrefcount(current_asmdata.CurrAsmList,resultdef,location.reference);
end;
{$ifndef cpu64bit}
if cgsize in [OS_64,OS_S64] then
cg64.a_load64_reg_ref(current_asmdata.CurrAsmList,retloc.register64,location.reference)
else
{$endif}
cg.a_load_reg_ref(current_asmdata.CurrAsmList,cgsize,cgsize,retloc.register,location.reference);
end
else
{ normal (ordinal,float,pointer) result value }
begin
{ we have only to handle the result if it is used }
if (cnf_return_value_used in callnodeflags) then
begin
location.loc:=procdefinition.funcretloc[callerside].loc;
case procdefinition.funcretloc[callerside].loc of
LOC_FPUREGISTER:
begin
location_reset(location,LOC_FPUREGISTER,cgsize);
location.register:=procdefinition.funcretloc[callerside].register;
{ Load normal (ordinal,float,pointer) result value from accumulator }
cgsize:=procdefinition.funcretloc[callerside].size;
case procdefinition.funcretloc[callerside].loc of
LOC_FPUREGISTER:
begin
location_reset(location,LOC_FPUREGISTER,cgsize);
location.register:=procdefinition.funcretloc[callerside].register;
{$ifdef x86}
tcgx86(cg).inc_fpu_stack;
tcgx86(cg).inc_fpu_stack;
{$else x86}
if getsupreg(procdefinition.funcretloc[callerside].register)<first_fpu_imreg then
cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
hregister:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,location.size,location.size,location.register,hregister);
location.register:=hregister;
if getsupreg(procdefinition.funcretloc[callerside].register)<first_fpu_imreg then
cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
hregister:=cg.getfpuregister(current_asmdata.CurrAsmList,location.size);
cg.a_loadfpu_reg_reg(current_asmdata.CurrAsmList,location.size,location.size,location.register,hregister);
location.register:=hregister;
{$endif x86}
end;
end;
LOC_REGISTER:
begin
if cgsize<>OS_NO then
begin
location_reset(location,LOC_REGISTER,cgsize);
LOC_REGISTER:
begin
if cgsize<>OS_NO then
begin
location_reset(location,LOC_REGISTER,cgsize);
{$ifndef cpu64bit}
if cgsize in [OS_64,OS_S64] then
begin
retloc:=procdefinition.funcretloc[callerside];
if retloc.loc<>LOC_REGISTER then
internalerror(200409141);
{ the function result registers are already allocated }
if getsupreg(retloc.register64.reglo)<first_int_imreg then
cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register64.reglo);
location.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,retloc.register64.reglo,location.register64.reglo);
if getsupreg(retloc.register64.reghi)<first_int_imreg then
cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register64.reghi);
location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,retloc.register64.reghi,location.register64.reghi);
end
else
if cgsize in [OS_64,OS_S64] then
begin
retloc:=procdefinition.funcretloc[callerside];
if retloc.loc<>LOC_REGISTER then
internalerror(200409141);
{ the function result registers are already allocated }
if getsupreg(retloc.register64.reglo)<first_int_imreg then
cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register64.reglo);
location.register64.reglo:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,retloc.register64.reglo,location.register64.reglo);
if getsupreg(retloc.register64.reghi)<first_int_imreg then
cg.ungetcpuregister(current_asmdata.CurrAsmList,retloc.register64.reghi);
location.register64.reghi:=cg.getintregister(current_asmdata.CurrAsmList,OS_32);
cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_32,OS_32,retloc.register64.reghi,location.register64.reghi);
end
else
{$endif cpu64bit}
begin
{ change register size after the unget because the
getregister was done for the full register
def_cgsize(resultdef) is used here because
it could be a constructor call }
if getsupreg(procdefinition.funcretloc[callerside].register)<first_int_imreg then
cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
location.register:=cg.getintregister(current_asmdata.CurrAsmList,def_cgsize(resultdef));
cg.a_load_reg_reg(current_asmdata.CurrAsmList,cgsize,def_cgsize(resultdef),procdefinition.funcretloc[callerside].register,location.register);
end;
begin
{ change register size after the unget because the
getregister was done for the full register
def_cgsize(resultdef) is used here because
it could be a constructor call }
if getsupreg(procdefinition.funcretloc[callerside].register)<first_int_imreg then
cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
location.register:=cg.getintregister(current_asmdata.CurrAsmList,def_cgsize(resultdef));
cg.a_load_reg_reg(current_asmdata.CurrAsmList,cgsize,def_cgsize(resultdef),procdefinition.funcretloc[callerside].register,location.register);
end;
{$ifdef arm}
if (resultdef.typ=floatdef) and (current_settings.fputype in [fpu_fpa,fpu_fpa10,fpu_fpa11]) then
begin
location_force_mem(current_asmdata.CurrAsmList,location);
end;
if (resultdef.typ=floatdef) and (current_settings.fputype in [fpu_fpa,fpu_fpa10,fpu_fpa11]) then
begin
location_force_mem(current_asmdata.CurrAsmList,location);
end;
{$endif arm}
end
else
begin
if resultdef.size>0 then
internalerror(200305131);
end;
end;
LOC_MMREGISTER:
begin
location_reset(location,LOC_MMREGISTER,cgsize);
if getsupreg(procdefinition.funcretloc[callerside].register)<first_mm_imreg then
cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
location.register:=cg.getmmregister(current_asmdata.CurrAsmList,cgsize);
cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,cgsize,cgsize,procdefinition.funcretloc[callerside].register,location.register,mms_movescalar);
end;
else
internalerror(200405023);
end
else
begin
if resultdef.size>0 then
internalerror(200305131);
end;
end
else
begin
{$ifdef x86}
{ release FPU stack }
if procdefinition.funcretloc[callerside].loc=LOC_FPUREGISTER then
emit_reg(A_FSTP,S_NO,NR_FPU_RESULT_REG);
{$endif x86}
if cgsize<>OS_NO then
location_free(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside]);
location_reset(location,LOC_VOID,OS_NO);
end;
end;
end;
LOC_MMREGISTER:
begin
location_reset(location,LOC_MMREGISTER,cgsize);
if getsupreg(procdefinition.funcretloc[callerside].register)<first_mm_imreg then
cg.ungetcpuregister(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside].register);
location.register:=cg.getmmregister(current_asmdata.CurrAsmList,cgsize);
cg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,cgsize,cgsize,procdefinition.funcretloc[callerside].register,location.register,mms_movescalar);
end;
else
internalerror(200405023);
end;
{ copy value to the final location if this was already provided to the
callnode. This must be done after the call node, because the location can
also be used as parameter and may not be finalized yet }
if assigned(funcretnode) then
begin
funcretnode.pass_generate_code;
{ Decrease refcount for refcounted types, this can be skipped when
we have used a temp, because then it is already done from tempcreatenode.
Also no finalize is needed, because there is no risk of exceptions from the
function since this is code is only executed after the function call has returned }
if funcretnode.resultdef.needs_inittable and
(funcretnode.nodetype<>temprefn) then
cg.g_decrrefcount(current_asmdata.CurrAsmList,funcretnode.resultdef,funcretnode.location.reference);
case location.loc of
LOC_REGISTER :
{$ifndef cpu64bit}
if cgsize in [OS_64,OS_S64] then
cg64.a_load64_reg_loc(current_asmdata.CurrAsmList,location.register64,funcretnode.location)
else
{$endif}
cg.a_load_reg_loc(current_asmdata.CurrAsmList,cgsize,location.register,funcretnode.location);
else
internalerror(200709085);
end;
location := funcretnode.location;
end;
end;
procedure tcgcallnode.release_unused_return_value;
begin
{ When the result is not used we need to finalize the result and
can release the temp }
can release the temp. This need to be after the callcleanupblock
tree is generated, because that converts the temp from persistent to normal }
if not(cnf_return_value_used in callnodeflags) then
begin
if location.loc=LOC_REFERENCE then
begin
if resultdef.needs_inittable then
cg.g_finalize(current_asmdata.CurrAsmList,resultdef,location.reference);
tg.ungetiftemp(current_asmdata.CurrAsmList,location.reference)
end;
case location.loc of
LOC_REFERENCE :
begin
if resultdef.needs_inittable then
cg.g_finalize(current_asmdata.CurrAsmList,resultdef,location.reference);
tg.ungetiftemp(current_asmdata.CurrAsmList,location.reference);
end;
{$ifdef x86}
LOC_FPUREGISTER :
begin
{ release FPU stack }
emit_reg(A_FSTP,S_NO,NR_FPU_RESULT_REG);
tcgx86(cg).dec_fpu_stack;
end;
{$endif x86}
end;
if procdefinition.funcretloc[callerside].size<>OS_NO then
location_free(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside]);
location_reset(location,LOC_VOID,OS_NO);
end;
end;
procedure tcgcallnode.release_para_temps;
var
hp : tnode;
hp,
hp2 : tnode;
ppn : tcallparanode;
begin
{ Release temps from parameters }
@ -714,7 +683,13 @@ implementation
begin
while assigned(hp) do
begin
location_freetemp(current_asmdata.CurrAsmList,tarrayconstructornode(hp).left.location);
hp2:=tarrayconstructornode(hp).left;
{ ignore typeconvs and addrn inserted by arrayconstructn for
passing a shortstring }
if (hp2.nodetype=typeconvn) and
(tunarynode(hp2).left.nodetype=addrn) then
hp2:=tunarynode(tunarynode(hp2).left).left;
location_freetemp(current_asmdata.CurrAsmList,hp2.location);
hp:=tarrayconstructornode(hp).right;
end;
end;
@ -864,19 +839,8 @@ implementation
not procdefinition.has_paraloc_info then
internalerror(200305264);
if assigned(methodpointerinit) then
secondpass(methodpointerinit);
if resultdef.needs_inittable and
not paramanager.ret_in_param(resultdef,procdefinition.proccalloption) and
not assigned(funcretnode) then
begin
tg.gettemptyped(current_asmdata.CurrAsmList,resultdef,tt_normal,refcountedtemp);
{ finalize instead of only decrref, because if the called }
{ function throws an exception this temp will be decrref'd }
{ again (tw7100) }
cg.g_finalize(current_asmdata.CurrAsmList,resultdef,refcountedtemp);
end;
if assigned(callinitblock) then
secondpass(callinitblock);
regs_to_save_int:=paramanager.get_volatile_registers_int(procdefinition.proccalloption);
regs_to_save_fpu:=paramanager.get_volatile_registers_fpu(procdefinition.proccalloption);
@ -1120,6 +1084,18 @@ implementation
else
location_reset(location,LOC_VOID,OS_NO);
{ convert persistent temps for parameters and function result to normal temps }
if assigned(callcleanupblock) then
secondpass(callcleanupblock);
{ release temps and finalize unused return values, must be
after the callcleanupblock because that converts temps
from persistent to normal }
release_unused_return_value;
{ release temps of paras }
release_para_temps;
{ perhaps i/o check ? }
if (cs_check_io in current_settings.localswitches) and
(po_iocheck in procdefinition.procoptions) and
@ -1132,13 +1108,6 @@ implementation
cg.a_call_name(current_asmdata.CurrAsmList,'FPC_IOCHECK');
cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
end;
{ release temps of paras }
release_para_temps;
if assigned(methodpointerdone) then
secondpass(methodpointerdone);
end;

View File

@ -2542,7 +2542,7 @@ implementation
if (ti_valid in ttemprefnode(n).tempinfo^.flags) and
(ttemprefnode(n).tempinfo^.location.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMXREGISTER,LOC_CMMREGISTER]) and
(ttemprefnode(n).tempinfo^.location.register = rr^.old) and
(not(ti_is_inlined_result in ttemprefnode(n).tempinfo^.flags) or
(not(ti_is_funcret in ttemprefnode(n).tempinfo^.flags) or
not(fc_exit in flowcontrol)) then
begin
{$ifndef cpu64bit}

View File

@ -1696,7 +1696,7 @@ implementation
if (tcallnode(left).symtableprocentry.owner.symtabletype=ObjectSymtable) then
begin
if assigned(tcallnode(left).methodpointer) then
tloadnode(hp).set_mp(tcallnode(left).get_load_methodpointer)
tloadnode(hp).set_mp(tcallnode(left).methodpointer.getcopy)
else
tloadnode(hp).set_mp(load_self_node);
end;

View File

@ -679,10 +679,7 @@ implementation
is pushed as a parameter. Using the final destination of left directly
save a temp allocation and copy of data (PFV) }
oldassignmentnode:=aktassignmentnode;
if right.nodetype=addn then
aktassignmentnode:=self
else
aktassignmentnode:=nil;
aktassignmentnode:=self;
firstpass(right);
aktassignmentnode:=oldassignmentnode;
if nf_assign_done_in_right in flags then
@ -695,66 +692,11 @@ implementation
if codegenerror then
exit;
{ if right is a function call for which the address of the result }
{ is allocated by the caller and passed to the function via an }
{ invisible function result, try to pass the x in "x:=f(...)" as }
{ that function result instead. Condition: x cannot be accessible }
{ from within f. This is the case if x is a temp, or x is a local }
{ variable or value parameter of the current block and its address }
{ is not passed to f. One problem: what if someone takes the }
{ address of x, puts it in a pointer variable/field and then }
{ accesses it that way from within the function? This is solved }
{ (in a conservative way) using the ti_addr_taken/addr_taken flags }
if (cs_opt_level1 in current_settings.optimizerswitches) and
(right.nodetype = calln) and
(right.resultdef=left.resultdef) and
{ left must be a temp, since otherwise as soon as you modify the }
{ result, the current left node is modified and that one may }
{ still be an argument to the function or even accessed in the }
{ function }
(
(
(((left.nodetype = temprefn) and
not(ti_addr_taken in ttemprefnode(left).tempinfo^.flags) and
not(ti_may_be_in_reg in ttemprefnode(left).tempinfo^.flags)) or
((left.nodetype = loadn) and
{ nested procedures may access the current procedure's locals }
(tcallnode(right).procdefinition.parast.symtablelevel=normal_function_level) and
{ must be a local variable or a value para }
((tloadnode(left).symtableentry.typ = localvarsym) or
((tloadnode(left).symtableentry.typ = paravarsym) and
(tparavarsym(tloadnode(left).symtableentry).varspez = vs_value)
)
) and
{ the address may not have been taken of the variable/parameter, because }
{ otherwise it's possible that the called function can access it via a }
{ global variable or other stored state }
not(tabstractvarsym(tloadnode(left).symtableentry).addr_taken) and
(tabstractvarsym(tloadnode(left).symtableentry).varregable in [vr_none,vr_addr])
)
) and
paramanager.ret_in_param(right.resultdef,tcallnode(right).procdefinition.proccalloption)
) or
{ there's special support for ansi/widestrings in the callnode }
is_ansistring(right.resultdef) or
is_widestring(right.resultdef)
) then
begin
if assigned(tcallnode(right).funcretnode) then
internalerror(2007080201);
tcallnode(right).funcretnode := left;
result := right;
left := nil;
right := nil;
exit;
end;
{ assignment to refcounted variable -> inc/decref }
if (not is_class(left.resultdef) and
left.resultdef.needs_inittable) then
include(current_procinfo.flags,pi_do_call);
if (is_shortstring(left.resultdef)) then
begin
if right.resultdef.typ=stringdef then

View File

@ -121,9 +121,9 @@ implementation
calln:
begin
{ not in one statement, won't work because of b- }
result := foreachnode(tcallnode(n).methodpointerinit,f,arg) or result;
result := foreachnode(tcallnode(n).callinitblock,f,arg) or result;
result := foreachnode(tcallnode(n).methodpointer,f,arg) or result;
result := foreachnode(tcallnode(n).methodpointerdone,f,arg) or result;
result := foreachnode(tcallnode(n).callcleanupblock,f,arg) or result;
end;
ifn, whilerepeatn, forn, tryexceptn, tryfinallyn:
begin
@ -169,9 +169,9 @@ implementation
end;
calln:
begin
result := foreachnodestatic(procmethod,tcallnode(n).methodpointerinit,f,arg) or result;
result := foreachnodestatic(procmethod,tcallnode(n).callinitblock,f,arg) or result;
result := foreachnodestatic(procmethod,tcallnode(n).methodpointer,f,arg) or result;
result := foreachnodestatic(procmethod,tcallnode(n).methodpointerdone,f,arg) or result;
result := foreachnodestatic(procmethod,tcallnode(n).callcleanupblock,f,arg) or result;
end;
ifn, whilerepeatn, forn, tryexceptn, tryfinallyn:
begin
@ -267,7 +267,7 @@ implementation
method without a self pointer }
if assigned(tcallnode(p1).methodpointer) and
(tcallnode(p1).methodpointer.nodetype<>typen) then
tloadnode(p2).set_mp(tcallnode(p1).get_load_methodpointer);
tloadnode(p2).set_mp(tcallnode(p1).methodpointer.getcopy);
end;
typecheckpass(p2);
p1.free;

View File

@ -144,10 +144,10 @@ unit opttail;
oldnodetree:=n;
n:=internalstatements(nodes);
if assigned(usedcallnode.methodpointerinit) then
if assigned(usedcallnode.callinitblock) then
begin
addstatement(nodes,usedcallnode.methodpointerinit);
usedcallnode.methodpointerinit:=nil;
addstatement(nodes,usedcallnode.callinitblock);
usedcallnode.callinitblock:=nil;
end;
addstatement(nodes,calcnodes);
@ -156,13 +156,13 @@ unit opttail;
{ create goto }
addstatement(nodes,cgotonode.create(labelnode));
if assigned(usedcallnode.methodpointerdone) then
if assigned(usedcallnode.callcleanupblock) then
begin
{ methodpointerdone should contain only temp. node clean up }
checktreenodetypes(usedcallnode.methodpointerdone,
{ callcleanupblock should contain only temp. node clean up }
checktreenodetypes(usedcallnode.callcleanupblock,
[tempdeleten,blockn,statementn,temprefn,nothingn]);
addstatement(nodes,usedcallnode.methodpointerdone);
usedcallnode.methodpointerdone:=nil;
addstatement(nodes,usedcallnode.callcleanupblock);
usedcallnode.callcleanupblock:=nil;
end;
oldnodetree.free;

View File

@ -1079,7 +1079,7 @@ implementation
begin
hp2:=cloadnode.create_procvar(tprocsym(tcallnode(hp).symtableprocentry),currprocdef,tcallnode(hp).symtableproc);
if (po_methodpointer in pv.procoptions) then
tloadnode(hp2).set_mp(tcallnode(hp).get_load_methodpointer);
tloadnode(hp2).set_mp(tcallnode(hp).methodpointer.getcopy);
hp.destroy;
{ replace the old callnode with the new loadnode }
hpp^:=hp2;