summaryrefslogtreecommitdiff
path: root/compiler/ngenutil.pas
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/ngenutil.pas')
-rw-r--r--compiler/ngenutil.pas172
1 files changed, 165 insertions, 7 deletions
diff --git a/compiler/ngenutil.pas b/compiler/ngenutil.pas
index e7ea96fafa..0dcb142e64 100644
--- a/compiler/ngenutil.pas
+++ b/compiler/ngenutil.pas
@@ -37,6 +37,17 @@ interface
class function call_fail_node:tnode; virtual;
class function initialize_data_node(p:tnode; force: boolean):tnode; virtual;
class function finalize_data_node(p:tnode):tnode; virtual;
+ strict protected
+ class procedure sym_maybe_initialize(p: TObject; arg: pointer);
+ { generates the code for finalisation of local variables }
+ class procedure local_varsyms_finalize(p:TObject;arg:pointer);
+ { generates the code for finalization of static symtable and
+ all local (static) typed consts }
+ class procedure static_syms_finalize(p: TObject; arg: pointer);
+ class procedure sym_maybe_finalize(var stat: tstatementnode; sym: tsym);
+ public
+ class procedure procdef_block_add_implicit_initialize_nodes(pd: tprocdef; var stat: tstatementnode);
+ class procedure procdef_block_add_implicit_finalize_nodes(pd: tprocdef; var stat: tstatementnode);
{ returns true if the unit requires an initialisation section (e.g.,
to force class constructors for the JVM target to initialise global
records/arrays) }
@@ -260,6 +271,149 @@ implementation
end;
+ class procedure tnodeutils.sym_maybe_initialize(p: TObject; arg: pointer);
+ begin
+ if (tsym(p).typ = localvarsym) and
+ { local (procedure or unit) variables only need initialization if
+ they are used }
+ ((tabstractvarsym(p).refs>0) or
+ { managed return symbols must be inited }
+ ((tsym(p).typ=localvarsym) and (vo_is_funcret in tlocalvarsym(p).varoptions))
+ ) and
+ not(vo_is_typed_const in tabstractvarsym(p).varoptions) and
+ not(vo_is_external in tabstractvarsym(p).varoptions) and
+ not(vo_is_default_var in tabstractvarsym(p).varoptions) and
+ (is_managed_type(tabstractvarsym(p).vardef) or
+ ((m_iso in current_settings.modeswitches) and (tabstractvarsym(p).vardef.typ=filedef))
+ ) then
+ begin
+ addstatement(tstatementnode(arg^),initialize_data_node(cloadnode.create(tsym(p),tsym(p).owner),false));
+ end;
+ end;
+
+
+ class procedure tnodeutils.local_varsyms_finalize(p: TObject; arg: pointer);
+ begin
+ if (tsym(p).typ=localvarsym) and
+ (tlocalvarsym(p).refs>0) and
+ not(vo_is_external in tlocalvarsym(p).varoptions) and
+ not(vo_is_funcret in tlocalvarsym(p).varoptions) and
+ not(vo_is_default_var in tabstractvarsym(p).varoptions) and
+ is_managed_type(tlocalvarsym(p).vardef) then
+ sym_maybe_finalize(tstatementnode(arg^),tsym(p));
+ end;
+
+
+ class procedure tnodeutils.static_syms_finalize(p: TObject; arg: pointer);
+ var
+ i : longint;
+ pd : tprocdef;
+ begin
+ case tsym(p).typ of
+ staticvarsym :
+ begin
+ { local (procedure or unit) variables only need finalization
+ if they are used
+ }
+ if ((tstaticvarsym(p).refs>0) or
+ { global (unit) variables always need finalization, since
+ they may also be used in another unit
+ }
+ (tstaticvarsym(p).owner.symtabletype=globalsymtable)) and
+ (
+ (tstaticvarsym(p).varspez<>vs_const) or
+ (vo_force_finalize in tstaticvarsym(p).varoptions)
+ ) and
+ not(vo_is_funcret in tstaticvarsym(p).varoptions) and
+ not(vo_is_external in tstaticvarsym(p).varoptions) and
+ is_managed_type(tstaticvarsym(p).vardef) and
+ not (
+ assigned(tstaticvarsym(p).fieldvarsym) and
+ assigned(tstaticvarsym(p).fieldvarsym.owner.defowner) and
+ (df_generic in tdef(tstaticvarsym(p).fieldvarsym.owner.defowner).defoptions)
+ )
+ then
+ sym_maybe_finalize(tstatementnode(arg^),tsym(p));
+ end;
+ procsym :
+ begin
+ for i:=0 to tprocsym(p).ProcdefList.Count-1 do
+ begin
+ pd:=tprocdef(tprocsym(p).ProcdefList[i]);
+ if assigned(pd.localst) and
+ (pd.procsym=tprocsym(p)) and
+ (pd.localst.symtabletype<>staticsymtable) then
+ pd.localst.SymList.ForEachCall(@static_syms_finalize,arg);
+ end;
+ end;
+ end;
+ end;
+
+
+ class procedure tnodeutils.sym_maybe_finalize(var stat: tstatementnode; sym: tsym);
+ var
+ hp: tnode;
+ begin
+ include(current_procinfo.flags,pi_needs_implicit_finally);
+ hp:=cloadnode.create(sym,sym.owner);
+ if (sym.typ=staticvarsym) and (vo_force_finalize in tstaticvarsym(sym).varoptions) then
+ include(tloadnode(hp).loadnodeflags,loadnf_isinternal_ignoreconst);
+ addstatement(stat,finalize_data_node(hp));
+ end;
+
+
+ class procedure tnodeutils.procdef_block_add_implicit_initialize_nodes(pd: tprocdef; var stat: tstatementnode);
+ begin
+ { initialize local data like ansistrings }
+ case pd.proctypeoption of
+ potype_unitinit:
+ begin
+ { this is also used for initialization of variables in a
+ program which does not have a globalsymtable }
+ if assigned(current_module.globalsymtable) then
+ TSymtable(current_module.globalsymtable).SymList.ForEachCall(@sym_maybe_initialize,@stat);
+ TSymtable(current_module.localsymtable).SymList.ForEachCall(@sym_maybe_initialize,@stat);
+ TSymtable(current_module.localsymtable).SymList.ForEachCall(@sym_maybe_initialize,@stat);
+ end;
+ { units have seperate code for initilization and finalization }
+ potype_unitfinalize: ;
+ { program init/final is generated in separate procedure }
+ potype_proginit:
+ begin
+ TSymtable(current_module.localsymtable).SymList.ForEachCall(@sym_maybe_initialize,@stat);
+ end;
+ else
+ current_procinfo.procdef.localst.SymList.ForEachCall(@sym_maybe_initialize,@stat);
+ end;
+ end;
+
+
+ class procedure tnodeutils.procdef_block_add_implicit_finalize_nodes(pd: tprocdef; var stat: tstatementnode);
+ begin
+ { no finalization in exceptfilters, they /are/ the finalization code }
+ if current_procinfo.procdef.proctypeoption=potype_exceptfilter then
+ exit;
+
+ { finalize local data like ansistrings}
+ case current_procinfo.procdef.proctypeoption of
+ potype_unitfinalize:
+ begin
+ { this is also used for initialization of variables in a
+ program which does not have a globalsymtable }
+ if assigned(current_module.globalsymtable) then
+ TSymtable(current_module.globalsymtable).SymList.ForEachCall(@static_syms_finalize,@stat);
+ TSymtable(current_module.localsymtable).SymList.ForEachCall(@static_syms_finalize,@stat);
+ end;
+ { units/progs have separate code for initialization and finalization }
+ potype_unitinit: ;
+ { program init/final is generated in separate procedure }
+ potype_proginit: ;
+ else
+ current_procinfo.procdef.localst.SymList.ForEachCall(@local_varsyms_finalize,@stat);
+ end;
+ end;
+
+
class function tnodeutils.force_init: boolean;
begin
result:=
@@ -584,12 +738,15 @@ implementation
else
list.concat(Tai_datablock.create(sym.mangledname,size));
- { add the indirect symbol if needed }
- new_section(list,sec_rodata,lower(sym.mangledname),const_align(sym.vardef.alignment));
- symind:=current_asmdata.DefineAsmSymbol(sym.mangledname,AB_INDIRECT,AT_DATA);
- list.concat(Tai_symbol.Create_Global(symind,0));
- list.concat(Tai_const.Createname(sym.mangledname,AT_DATA,0));
- list.concat(tai_symbol_end.Create(symind));
+ if (tf_supports_packages in target_info.flags) then
+ begin
+ { add the indirect symbol if needed }
+ new_section(list,sec_rodata,lower(sym.mangledname),const_align(sym.vardef.alignment));
+ symind:=current_asmdata.DefineAsmSymbol(sym.mangledname,AB_INDIRECT,AT_DATA);
+ list.concat(Tai_symbol.Create_Global(symind,0));
+ list.concat(Tai_const.Createname(sym.mangledname,AT_DATA,0));
+ list.concat(tai_symbol_end.Create(symind));
+ end;
end;
@@ -1160,7 +1317,8 @@ implementation
);
tcb.free;
- if not(tf_no_generic_stackcheck in target_info.flags) then
+ if (tf_emit_stklen in target_info.flags) or
+ not(tf_no_generic_stackcheck in target_info.flags) then
begin
{ stacksize can be specified and is now simulated }
tcb:=ctai_typedconstbuilder.create([tcalo_new_section,tcalo_make_dead_strippable]);