mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-18 20:49:19 +02:00
* Improvements of tprocinfo class:
* Moved nestedprocs from tcgprocinfo to tprocinfo, in order to be able to access the entire nested procedure hierarchy without depending on psub.pas or code generator. * Creating an instance of tprocinfo automatically inserts it into list of parent's nested procedures. * nestedprocs list is created on demand. Public read-only access is provided by has_nestedprocs and get_first_nestedproc functions. + Method destroy_tree is provided for destroying the entire hierarchy of procinfo's. It can be called on any procinfo object in the tree. + Also added methods save_jump_labels and restore_jump_labels for asmlabel maintenance, which is currently being repeatedly done all over the codegenerator. git-svn-id: trunk@17197 -
This commit is contained in:
parent
ad52fe0f23
commit
1c01d52ea6
@ -544,7 +544,6 @@ implementation
|
|||||||
destructor tmodule.Destroy;
|
destructor tmodule.Destroy;
|
||||||
var
|
var
|
||||||
i : longint;
|
i : longint;
|
||||||
hpi : tprocinfo;
|
|
||||||
begin
|
begin
|
||||||
if assigned(unitmap) then
|
if assigned(unitmap) then
|
||||||
freemem(unitmap);
|
freemem(unitmap);
|
||||||
@ -582,12 +581,7 @@ implementation
|
|||||||
current_specializedef:=nil;
|
current_specializedef:=nil;
|
||||||
end;
|
end;
|
||||||
{ release procinfo tree }
|
{ release procinfo tree }
|
||||||
while assigned(procinfo) do
|
tprocinfo(procinfo).destroy_tree;
|
||||||
begin
|
|
||||||
hpi:=tprocinfo(procinfo).parent;
|
|
||||||
tprocinfo(procinfo).free;
|
|
||||||
procinfo:=hpi;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
DoneDebugInfo(self);
|
DoneDebugInfo(self);
|
||||||
used_units.free;
|
used_units.free;
|
||||||
@ -642,7 +636,6 @@ implementation
|
|||||||
|
|
||||||
procedure tmodule.reset;
|
procedure tmodule.reset;
|
||||||
var
|
var
|
||||||
hpi : tprocinfo;
|
|
||||||
i : longint;
|
i : longint;
|
||||||
begin
|
begin
|
||||||
if assigned(scanner) then
|
if assigned(scanner) then
|
||||||
@ -664,12 +657,7 @@ implementation
|
|||||||
current_specializedef:=nil;
|
current_specializedef:=nil;
|
||||||
end;
|
end;
|
||||||
{ release procinfo tree }
|
{ release procinfo tree }
|
||||||
while assigned(procinfo) do
|
tprocinfo(procinfo).destroy_tree;
|
||||||
begin
|
|
||||||
hpi:=tprocinfo(procinfo).parent;
|
|
||||||
tprocinfo(procinfo).free;
|
|
||||||
procinfo:=hpi;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
if assigned(asmdata) then
|
if assigned(asmdata) then
|
||||||
begin
|
begin
|
||||||
|
@ -47,10 +47,17 @@ unit procinfo;
|
|||||||
|
|
||||||
|
|
||||||
type
|
type
|
||||||
|
tsavedlabels = array[Boolean] of TAsmLabel;
|
||||||
|
|
||||||
{# This object gives information on the current routine being
|
{# This object gives information on the current routine being
|
||||||
compiled.
|
compiled.
|
||||||
}
|
}
|
||||||
tprocinfo = class(tlinkedlistitem)
|
tprocinfo = class(tlinkedlistitem)
|
||||||
|
private
|
||||||
|
{ list to store the procinfo's of the nested procedures }
|
||||||
|
nestedprocs : tlinkedlist;
|
||||||
|
procedure addnestedproc(child: tprocinfo);
|
||||||
|
public
|
||||||
{ pointer to parent in nested procedures }
|
{ pointer to parent in nested procedures }
|
||||||
parent : tprocinfo;
|
parent : tprocinfo;
|
||||||
{# the definition of the routine itself }
|
{# the definition of the routine itself }
|
||||||
@ -123,6 +130,18 @@ unit procinfo;
|
|||||||
|
|
||||||
{ Allocate got register }
|
{ Allocate got register }
|
||||||
procedure allocate_got_register(list: TAsmList);virtual;
|
procedure allocate_got_register(list: TAsmList);virtual;
|
||||||
|
|
||||||
|
{ Destroy the entire procinfo tree, starting from the outermost parent }
|
||||||
|
procedure destroy_tree;
|
||||||
|
|
||||||
|
{ Store CurrTrueLabel and CurrFalseLabel to saved and generate new ones }
|
||||||
|
procedure save_jump_labels(out saved: tsavedlabels);
|
||||||
|
|
||||||
|
{ Restore CurrTrueLabel and CurrFalseLabel from saved }
|
||||||
|
procedure restore_jump_labels(const saved: tsavedlabels);
|
||||||
|
|
||||||
|
function get_first_nestedproc: tprocinfo;
|
||||||
|
function has_nestedprocs: boolean;
|
||||||
end;
|
end;
|
||||||
tcprocinfo = class of tprocinfo;
|
tcprocinfo = class of tprocinfo;
|
||||||
|
|
||||||
@ -165,15 +184,61 @@ implementation
|
|||||||
CurrTrueLabel:=nil;
|
CurrTrueLabel:=nil;
|
||||||
CurrFalseLabel:=nil;
|
CurrFalseLabel:=nil;
|
||||||
maxpushedparasize:=0;
|
maxpushedparasize:=0;
|
||||||
|
if Assigned(parent) and (parent.procdef.parast.symtablelevel>=normal_function_level) then
|
||||||
|
parent.addnestedproc(Self);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
destructor tprocinfo.destroy;
|
destructor tprocinfo.destroy;
|
||||||
begin
|
begin
|
||||||
|
nestedprocs.free;
|
||||||
aktproccode.free;
|
aktproccode.free;
|
||||||
aktlocaldata.free;
|
aktlocaldata.free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure tprocinfo.destroy_tree;
|
||||||
|
var
|
||||||
|
hp: tprocinfo;
|
||||||
|
begin
|
||||||
|
hp:=Self;
|
||||||
|
while Assigned(hp.parent) do
|
||||||
|
hp:=hp.parent;
|
||||||
|
hp.Free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure tprocinfo.addnestedproc(child: tprocinfo);
|
||||||
|
begin
|
||||||
|
if nestedprocs=nil then
|
||||||
|
nestedprocs:=TLinkedList.Create;
|
||||||
|
nestedprocs.insert(child);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function tprocinfo.get_first_nestedproc: tprocinfo;
|
||||||
|
begin
|
||||||
|
if assigned(nestedprocs) then
|
||||||
|
result:=tprocinfo(nestedprocs.first)
|
||||||
|
else
|
||||||
|
result:=nil;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function tprocinfo.has_nestedprocs: boolean;
|
||||||
|
begin
|
||||||
|
result:=assigned(nestedprocs) and (nestedprocs.count>0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure tprocinfo.save_jump_labels(out saved: tsavedlabels);
|
||||||
|
begin
|
||||||
|
saved[false]:=CurrFalseLabel;
|
||||||
|
saved[true]:=CurrTrueLabel;
|
||||||
|
current_asmdata.getjumplabel(CurrTrueLabel);
|
||||||
|
current_asmdata.getjumplabel(CurrFalseLabel);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure tprocinfo.restore_jump_labels(const saved: tsavedlabels);
|
||||||
|
begin
|
||||||
|
CurrFalseLabel:=saved[false];
|
||||||
|
CurrTrueLabel:=saved[true];
|
||||||
|
end;
|
||||||
|
|
||||||
procedure tprocinfo.allocate_push_parasize(size:longint);
|
procedure tprocinfo.allocate_push_parasize(size:longint);
|
||||||
begin
|
begin
|
||||||
|
@ -45,10 +45,7 @@ interface
|
|||||||
stackcheck_asmnode,
|
stackcheck_asmnode,
|
||||||
init_asmnode,
|
init_asmnode,
|
||||||
final_asmnode : tasmnode;
|
final_asmnode : tasmnode;
|
||||||
{ list to store the procinfo's of the nested procedures }
|
|
||||||
nestedprocs : tlinkedlist;
|
|
||||||
dfabuilder : TDFABuilder;
|
dfabuilder : TDFABuilder;
|
||||||
constructor create(aparent:tprocinfo);override;
|
|
||||||
destructor destroy;override;
|
destructor destroy;override;
|
||||||
procedure printproc(pass:string);
|
procedure printproc(pass:string);
|
||||||
procedure generate_code;
|
procedure generate_code;
|
||||||
@ -555,16 +552,8 @@ implementation
|
|||||||
TCGProcInfo
|
TCGProcInfo
|
||||||
****************************************************************************}
|
****************************************************************************}
|
||||||
|
|
||||||
constructor tcgprocinfo.create(aparent:tprocinfo);
|
|
||||||
begin
|
|
||||||
inherited Create(aparent);
|
|
||||||
nestedprocs:=tlinkedlist.create;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
destructor tcgprocinfo.destroy;
|
destructor tcgprocinfo.destroy;
|
||||||
begin
|
begin
|
||||||
nestedprocs.free;
|
|
||||||
if assigned(code) then
|
if assigned(code) then
|
||||||
code.free;
|
code.free;
|
||||||
inherited destroy;
|
inherited destroy;
|
||||||
@ -794,10 +783,10 @@ implementation
|
|||||||
|
|
||||||
function tcgprocinfo.has_assembler_child : boolean;
|
function tcgprocinfo.has_assembler_child : boolean;
|
||||||
var
|
var
|
||||||
hp : tcgprocinfo;
|
hp : tprocinfo;
|
||||||
begin
|
begin
|
||||||
result:=false;
|
result:=false;
|
||||||
hp:=tcgprocinfo(nestedprocs.first);
|
hp:=get_first_nestedproc;
|
||||||
while assigned(hp) do
|
while assigned(hp) do
|
||||||
begin
|
begin
|
||||||
if (hp.flags*[pi_has_assembler_block,pi_is_assembler])<>[] then
|
if (hp.flags*[pi_has_assembler_block,pi_is_assembler])<>[] then
|
||||||
@ -805,7 +794,7 @@ implementation
|
|||||||
result:=true;
|
result:=true;
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
hp:=tcgprocinfo(hp.next);
|
hp:=tprocinfo(hp.next);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1549,7 +1538,7 @@ implementation
|
|||||||
{ generate code for this procedure }
|
{ generate code for this procedure }
|
||||||
pi.generate_code;
|
pi.generate_code;
|
||||||
{ process nested procs }
|
{ process nested procs }
|
||||||
hpi:=tcgprocinfo(pi.nestedprocs.first);
|
hpi:=tcgprocinfo(pi.get_first_nestedproc);
|
||||||
while assigned(hpi) do
|
while assigned(hpi) do
|
||||||
begin
|
begin
|
||||||
do_generate_code(hpi);
|
do_generate_code(hpi);
|
||||||
@ -1602,7 +1591,7 @@ implementation
|
|||||||
{ We can't support inlining for procedures that have nested
|
{ We can't support inlining for procedures that have nested
|
||||||
procedures because the nested procedures use a fixed offset
|
procedures because the nested procedures use a fixed offset
|
||||||
for accessing locals in the parent procedure (PFV) }
|
for accessing locals in the parent procedure (PFV) }
|
||||||
if (tcgprocinfo(current_procinfo).nestedprocs.count>0) then
|
if current_procinfo.has_nestedprocs then
|
||||||
begin
|
begin
|
||||||
if (df_generic in current_procinfo.procdef.defoptions) then
|
if (df_generic in current_procinfo.procdef.defoptions) then
|
||||||
Comment(V_Error,'Generic methods cannot have nested procedures')
|
Comment(V_Error,'Generic methods cannot have nested procedures')
|
||||||
@ -1618,9 +1607,7 @@ implementation
|
|||||||
{ When it's a nested procedure then defer the code generation,
|
{ When it's a nested procedure then defer the code generation,
|
||||||
when back at normal function level then generate the code
|
when back at normal function level then generate the code
|
||||||
for all defered nested procedures and the current procedure }
|
for all defered nested procedures and the current procedure }
|
||||||
if isnestedproc then
|
if not isnestedproc then
|
||||||
tcgprocinfo(current_procinfo.parent).nestedprocs.insert(current_procinfo)
|
|
||||||
else
|
|
||||||
begin
|
begin
|
||||||
if not(df_generic in current_procinfo.procdef.defoptions) then
|
if not(df_generic in current_procinfo.procdef.defoptions) then
|
||||||
do_generate_code(tcgprocinfo(current_procinfo));
|
do_generate_code(tcgprocinfo(current_procinfo));
|
||||||
|
@ -148,7 +148,7 @@ implementation
|
|||||||
if (cs_opt_regvar in current_settings.optimizerswitches) and
|
if (cs_opt_regvar in current_settings.optimizerswitches) and
|
||||||
{ we have to store regvars back to memory in this case (the nested }
|
{ we have to store regvars back to memory in this case (the nested }
|
||||||
{ procedures can access the variables of the parent) }
|
{ procedures can access the variables of the parent) }
|
||||||
(tcgprocinfo(current_procinfo).nestedprocs.count = 0) and
|
(not current_procinfo.has_nestedprocs) and
|
||||||
not(pi_has_assembler_block in current_procinfo.flags) and
|
not(pi_has_assembler_block in current_procinfo.flags) and
|
||||||
not(pi_uses_exceptions in current_procinfo.flags) then
|
not(pi_uses_exceptions in current_procinfo.flags) then
|
||||||
begin
|
begin
|
||||||
|
Loading…
Reference in New Issue
Block a user