mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-21 08:29:28 +02:00
* when calling an inline procedure inside a nested procedure, the
framepointer was being pushed on the stack, but this pushed framepointer was never used nor removed from the stack again after the inlining was done. It's now simply not pushed anymore, because the inlined procedure can get the previous framepointer from the procedure in which it is being inlined (merged)
This commit is contained in:
parent
bfa379a802
commit
100a911290
@ -837,57 +837,61 @@ implementation
|
||||
end;
|
||||
|
||||
{ push base pointer ?}
|
||||
if (lexlevel>=normal_function_level) and assigned(tprocdef(procdefinition).parast) and
|
||||
((tprocdef(procdefinition).parast.symtablelevel)>normal_function_level) then
|
||||
begin
|
||||
{ if we call a nested function in a method, we must }
|
||||
{ push also SELF! }
|
||||
{ THAT'S NOT TRUE, we have to load ESI via frame pointer }
|
||||
{ access }
|
||||
{
|
||||
begin
|
||||
loadesi:=false;
|
||||
emit_reg(A_PUSH,S_L,R_ESI);
|
||||
end;
|
||||
}
|
||||
if lexlevel=(tprocdef(procdefinition).parast.symtablelevel) then
|
||||
begin
|
||||
new(r);
|
||||
reset_reference(r^);
|
||||
r^.offset:=procinfo^.framepointer_offset;
|
||||
r^.base:=procinfo^.framepointer;
|
||||
emit_ref(A_PUSH,S_L,r)
|
||||
end
|
||||
{ this is only true if the difference is one !!
|
||||
but it cannot be more !! }
|
||||
else if (lexlevel=tprocdef(procdefinition).parast.symtablelevel-1) then
|
||||
begin
|
||||
emit_reg(A_PUSH,S_L,procinfo^.framepointer)
|
||||
end
|
||||
else if (lexlevel>tprocdef(procdefinition).parast.symtablelevel) then
|
||||
begin
|
||||
hregister:=getregister32;
|
||||
new(r);
|
||||
reset_reference(r^);
|
||||
r^.offset:=procinfo^.framepointer_offset;
|
||||
r^.base:=procinfo^.framepointer;
|
||||
emit_ref_reg(A_MOV,S_L,r,hregister);
|
||||
for i:=(tprocdef(procdefinition).parast.symtablelevel) to lexlevel-1 do
|
||||
begin
|
||||
new(r);
|
||||
reset_reference(r^);
|
||||
{we should get the correct frame_pointer_offset at each level
|
||||
how can we do this !!! }
|
||||
r^.offset:=procinfo^.framepointer_offset;
|
||||
r^.base:=hregister;
|
||||
emit_ref_reg(A_MOV,S_L,r,hregister);
|
||||
end;
|
||||
emit_reg(A_PUSH,S_L,hregister);
|
||||
ungetregister32(hregister);
|
||||
end
|
||||
else
|
||||
internalerror(25000);
|
||||
end;
|
||||
{ never when inlining, since if necessary, the base pointer }
|
||||
{ can/will be gottten from the current procedure's symtable }
|
||||
{ (JM) }
|
||||
if not inlined then
|
||||
if (lexlevel>=normal_function_level) and assigned(tprocdef(procdefinition).parast) and
|
||||
((tprocdef(procdefinition).parast.symtablelevel)>normal_function_level) then
|
||||
begin
|
||||
{ if we call a nested function in a method, we must }
|
||||
{ push also SELF! }
|
||||
{ THAT'S NOT TRUE, we have to load ESI via frame pointer }
|
||||
{ access }
|
||||
{
|
||||
begin
|
||||
loadesi:=false;
|
||||
emit_reg(A_PUSH,S_L,R_ESI);
|
||||
end;
|
||||
}
|
||||
if lexlevel=(tprocdef(procdefinition).parast.symtablelevel) then
|
||||
begin
|
||||
new(r);
|
||||
reset_reference(r^);
|
||||
r^.offset:=procinfo^.framepointer_offset;
|
||||
r^.base:=procinfo^.framepointer;
|
||||
emit_ref(A_PUSH,S_L,r)
|
||||
end
|
||||
{ this is only true if the difference is one !!
|
||||
but it cannot be more !! }
|
||||
else if (lexlevel=(tprocdef(procdefinition).parast.symtablelevel)-1) then
|
||||
begin
|
||||
emit_reg(A_PUSH,S_L,procinfo^.framepointer)
|
||||
end
|
||||
else if (lexlevel>(tprocdef(procdefinition).parast.symtablelevel)) then
|
||||
begin
|
||||
hregister:=getregister32;
|
||||
new(r);
|
||||
reset_reference(r^);
|
||||
r^.offset:=procinfo^.framepointer_offset;
|
||||
r^.base:=procinfo^.framepointer;
|
||||
emit_ref_reg(A_MOV,S_L,r,hregister);
|
||||
for i:=(tprocdef(procdefinition).parast.symtablelevel) to lexlevel-1 do
|
||||
begin
|
||||
new(r);
|
||||
reset_reference(r^);
|
||||
{we should get the correct frame_pointer_offset at each level
|
||||
how can we do this !!! }
|
||||
r^.offset:=procinfo^.framepointer_offset;
|
||||
r^.base:=hregister;
|
||||
emit_ref_reg(A_MOV,S_L,r,hregister);
|
||||
end;
|
||||
emit_reg(A_PUSH,S_L,hregister);
|
||||
ungetregister32(hregister);
|
||||
end
|
||||
else
|
||||
internalerror(25000);
|
||||
end;
|
||||
|
||||
saveregvars(regs_to_push);
|
||||
|
||||
@ -1584,7 +1588,15 @@ begin
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.32 2001-09-01 23:02:30 jonas
|
||||
Revision 1.33 2001-09-09 08:50:15 jonas
|
||||
* when calling an inline procedure inside a nested procedure, the
|
||||
framepointer was being pushed on the stack, but this pushed framepointer
|
||||
was never used nor removed from the stack again after the inlining was
|
||||
done. It's now simply not pushed anymore, because the inlined procedure
|
||||
can get the previous framepointer from the procedure in which it is being
|
||||
inlined (merged)
|
||||
|
||||
Revision 1.32 2001/09/01 23:02:30 jonas
|
||||
* i386*: call and jmp read their first operand
|
||||
* cgcal: deallocate hlper register only after call statement (fixes bug
|
||||
with "procedure of object" and optimizer reported to bugrep on
|
||||
|
Loading…
Reference in New Issue
Block a user