* 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:
sergei 2011-03-27 17:21:48 +00:00
parent ad52fe0f23
commit 1c01d52ea6
4 changed files with 74 additions and 34 deletions

View File

@ -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

View File

@ -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

View File

@ -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));

View File

@ -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