+ Fix for bug #3207 from Peter

This commit is contained in:
michael 2004-07-12 10:47:42 +00:00
parent 1563d986c5
commit 04a69ced17

View File

@ -495,6 +495,7 @@ implementation
begin
resultloc:=procdefinition.funcret_paraloc[callerside];
cgsize:=resultloc.size;
{ structured results are easy to handle....
needed also when result_no_used !! }
if (procdefinition.proctypeoption<>potype_constructor) and
@ -504,114 +505,132 @@ implementation
if location.loc<>LOC_REFERENCE then
internalerror(200304241);
end
{ ansi/widestrings must be registered, so we can dispose them }
else if resulttype.def.needs_inittable then
else
{ ansi/widestrings must be registered, so we can dispose them }
if resulttype.def.needs_inittable then
begin
{ the FUNCTION_RESULT_REG is already allocated }
if not assigned(funcretnode) then
begin
location_reset(location,LOC_REFERENCE,OS_ADDR);
location.reference:=refcountedtemp;
{ a_load_reg_ref may allocate registers! }
cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,NR_FUNCTION_RESULT_REG,location.reference);
cg.ungetregister(exprasmlist,NR_FUNCTION_RESULT_REG);
end
else
begin
cg.ungetregister(exprasmlist,resultloc.register);
hregister := cg.getaddressregister(exprasmlist);
cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,resultloc.register,hregister);
{ 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_2;
location := tempnode.location;
tempnode.free;
cg.g_decrrefcount(exprasmlist,resulttype.def,location.reference,false);
cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,location.reference);
cg.ungetregister(exprasmlist,hregister);
end;
{ When the result is not used we need to finalize the result and
can release the temp }
if not(cnf_return_value_used in callnodeflags) then
begin
cg.g_finalize(exprasmlist,resulttype.def,location.reference,false);
tg.ungetiftemp(exprasmlist,location.reference)
end;
end
else
{ normal (ordinal,float,pointer) result value }
begin
{ the FUNCTION_RESULT_REG is already allocated }
if not assigned(funcretnode) then
{ we have only to handle the result if it is used }
if (cnf_return_value_used in callnodeflags) then
begin
location_reset(location,LOC_REFERENCE,OS_ADDR);
location.reference:=refcountedtemp;
{ a_load_reg_ref may allocate registers! }
cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,NR_FUNCTION_RESULT_REG,location.reference);
cg.ungetregister(exprasmlist,NR_FUNCTION_RESULT_REG);
location.loc:=resultloc.loc;
case resultloc.loc of
LOC_FPUREGISTER:
begin
location_reset(location,LOC_FPUREGISTER,cgsize);
location.register:=procdefinition.funcret_paraloc[callerside].register;
{$ifdef x86}
tcgx86(cg).inc_fpu_stack;
{$else x86}
cg.ungetregister(exprasmlist,location.register);
hregister:=cg.getfpuregister(exprasmlist,location.size);
cg.a_loadfpu_reg_reg(exprasmlist,location.size,location.register,hregister);
location.register:=hregister;
{$endif x86}
end;
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
{ Move the function result to free registers, preferably the
FUNCTION_RESULT_REG/FUNCTION_RESULTHIGH_REG, so no move is necessary.}
{ the FUNCTION_RESULT_LOW_REG/FUNCTION_RESULT_HIGH_REG
are already allocated }
cg.ungetregister(exprasmlist,NR_FUNCTION_RESULT64_LOW_REG);
location.registerlow:=cg.getintregister(exprasmlist,OS_32);
cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,NR_FUNCTION_RESULT64_LOW_REG,location.registerlow);
cg.ungetregister(exprasmlist,NR_FUNCTION_RESULT64_HIGH_REG);
location.registerhigh:=cg.getintregister(exprasmlist,OS_32);
cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,NR_FUNCTION_RESULT64_HIGH_REG,location.registerhigh);
end
else
{$endif cpu64bit}
begin
{ Move the function result to a free register, preferably the
FUNCTION_RESULT_REG, so no move is necessary.}
{ the FUNCTION_RESULT_REG is already allocated }
cg.ungetregister(exprasmlist,resultloc.register);
{ change register size after the unget because the
getregister was done for the full register
def_cgsize(resulttype.def) is used here because
it could be a constructor call }
location.register:=cg.getintregister(exprasmlist,def_cgsize(resulttype.def));
cg.a_load_reg_reg(exprasmlist,cgsize,def_cgsize(resulttype.def),resultloc.register,location.register);
end;
end
else
begin
if resulttype.def.size>0 then
internalerror(200305131);
end;
end;
LOC_MMREGISTER:
begin
location_reset(location,LOC_MMREGISTER,cgsize);
cg.ungetregister(exprasmlist,resultloc.register);
location.register:=cg.getmmregister(exprasmlist,cgsize);
cg.a_loadmm_reg_reg(exprasmlist,cgsize,cgsize,resultloc.register,location.register,mms_movescalar);
end;
else
internalerror(200405023);
end;
end
else
begin
cg.ungetregister(exprasmlist,resultloc.register);
hregister := cg.getaddressregister(exprasmlist);
cg.a_load_reg_reg(exprasmlist,OS_ADDR,OS_ADDR,resultloc.register,hregister);
{ 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_2;
location := tempnode.location;
tempnode.free;
cg.g_decrrefcount(exprasmlist,resulttype.def,location.reference,false);
cg.a_load_reg_ref(exprasmlist,OS_ADDR,OS_ADDR,hregister,location.reference);
cg.ungetregister(exprasmlist,hregister);
end;
end
{ we have only to handle the result if it is used }
else if (cnf_return_value_used in callnodeflags) then
begin
location.loc:=resultloc.loc;
case resultloc.loc of
LOC_FPUREGISTER:
begin
location_reset(location,LOC_FPUREGISTER,cgsize);
location.register:=procdefinition.funcret_paraloc[callerside].register;
{$ifdef x86}
tcgx86(cg).inc_fpu_stack;
{$else x86}
cg.ungetregister(exprasmlist,location.register);
hregister:=cg.getfpuregister(exprasmlist,location.size);
cg.a_loadfpu_reg_reg(exprasmlist,location.size,location.register,hregister);
location.register:=hregister;
{ release FPU stack }
if resultloc.loc=LOC_FPUREGISTER then
emit_reg(A_FSTP,S_NO,NR_FPU_RESULT_REG);
{$endif x86}
end;
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
{ Move the function result to free registers, preferably the
FUNCTION_RESULT_REG/FUNCTION_RESULTHIGH_REG, so no move is necessary.}
{ the FUNCTION_RESULT_LOW_REG/FUNCTION_RESULT_HIGH_REG
are already allocated }
cg.ungetregister(exprasmlist,NR_FUNCTION_RESULT64_LOW_REG);
location.registerlow:=cg.getintregister(exprasmlist,OS_32);
cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,NR_FUNCTION_RESULT64_LOW_REG,location.registerlow);
cg.ungetregister(exprasmlist,NR_FUNCTION_RESULT64_HIGH_REG);
location.registerhigh:=cg.getintregister(exprasmlist,OS_32);
cg.a_load_reg_reg(exprasmlist,OS_32,OS_32,NR_FUNCTION_RESULT64_HIGH_REG,location.registerhigh);
end
else
{$endif cpu64bit}
begin
{ Move the function result to a free register, preferably the
FUNCTION_RESULT_REG, so no move is necessary.}
{ the FUNCTION_RESULT_REG is already allocated }
cg.ungetregister(exprasmlist,resultloc.register);
{ change register size after the unget because the
getregister was done for the full register
def_cgsize(resulttype.def) is used here because
it could be a constructor call }
location.register:=cg.getintregister(exprasmlist,def_cgsize(resulttype.def));
cg.a_load_reg_reg(exprasmlist,cgsize,def_cgsize(resulttype.def),resultloc.register,location.register);
end;
end
else
begin
if resulttype.def.size>0 then
internalerror(200305131);
end;
end;
LOC_MMREGISTER:
begin
location_reset(location,LOC_MMREGISTER,cgsize);
cg.ungetregister(exprasmlist,resultloc.register);
location.register:=cg.getmmregister(exprasmlist,cgsize);
cg.a_loadmm_reg_reg(exprasmlist,cgsize,cgsize,resultloc.register,location.register,mms_movescalar);
end;
else
internalerror(200405023);
end;
end
else
begin
if cgsize<>OS_NO then
paramanager.freeparaloc(exprasmlist,resultloc);
location_reset(location,LOC_VOID,OS_NO);
end;
if cgsize<>OS_NO then
paramanager.freeparaloc(exprasmlist,resultloc);
location_reset(location,LOC_VOID,OS_NO);
end;
end;
end;
@ -1024,26 +1043,6 @@ implementation
{ release temps of paras }
release_para_temps;
{ if return value is not used }
if (not(cnf_return_value_used in callnodeflags)) and (not is_void(resulttype.def)) then
begin
if location.loc in [LOC_CREFERENCE,LOC_REFERENCE] then
begin
{ data which must be finalized ? }
if (resulttype.def.needs_inittable) then
cg.g_finalize(exprasmlist,resulttype.def,location.reference,false);
{ release unused temp }
tg.ungetiftemp(exprasmlist,location.reference)
end
else if location.loc=LOC_FPUREGISTER then
begin
{$ifdef x86}
{ release FPU stack }
emit_reg(A_FSTP,S_NO,NR_FPU_RESULT_REG);
{$endif x86}
end;
end;
end;
@ -1264,7 +1263,10 @@ begin
end.
{
$Log$
Revision 1.172 2004-07-11 19:01:13 peter
Revision 1.173 2004-07-12 10:47:42 michael
+ Fix for bug 3207 from Peter
Revision 1.172 2004/07/11 19:01:13 peter
* comps are passed in int registers
Revision 1.171 2004/07/09 23:41:04 jonas