* turned call_fail_node, initialize_data_node, and finalize_data_node from

nutils.pas into virtual class methods of a new tnodeutils class defined
    in ngenutil (global factory: cnodeutils), so they can be overridden by
    architecture-specific implementations (required by the JVM backend)

git-svn-id: branches/jvmbackend@18364 -
This commit is contained in:
Jonas Maebe 2011-08-20 07:52:11 +00:00
parent 15aaf36b82
commit ab5b1fb686
7 changed files with 222 additions and 172 deletions

1
.gitattributes vendored
View File

@ -352,6 +352,7 @@ compiler/ncgutil.pas svneol=native#text/plain
compiler/ncnv.pas svneol=native#text/plain
compiler/ncon.pas svneol=native#text/plain
compiler/nflw.pas svneol=native#text/plain
compiler/ngenutil.pas svneol=native#text/plain
compiler/ninl.pas svneol=native#text/plain
compiler/nld.pas svneol=native#text/plain
compiler/nmat.pas svneol=native#text/plain

View File

@ -172,7 +172,7 @@ implementation
procinfo,paramgr,fmodule,
regvars,dbgbase,
pass_1,pass_2,
nbas,ncon,nld,nmem,nutils,
nbas,ncon,nld,nmem,nutils,ngenutil,
tgobj,cgobj,cgcpu,hlcgobj,hlcgcpu
{$ifdef powerpc}
, cpupi
@ -1494,7 +1494,7 @@ implementation
begin
OldAsmList:=current_asmdata.CurrAsmList;
current_asmdata.CurrAsmList:=TAsmList(arg);
hp:=initialize_data_node(cloadnode.create(tsym(p),tsym(p).owner));
hp:=cnodeutils.initialize_data_node(cloadnode.create(tsym(p),tsym(p).owner));
firstpass(hp);
secondpass(hp);
hp.free;
@ -1514,7 +1514,7 @@ implementation
hp:=cloadnode.create(sym,sym.owner);
if (sym.typ=staticvarsym) and (vo_force_finalize in tstaticvarsym(sym).varoptions) then
include(hp.flags,nf_isinternal_ignoreconst);
hp:=finalize_data_node(hp);
hp:=cnodeutils.finalize_data_node(hp);
firstpass(hp);
secondpass(hp);
hp.free;

208
compiler/ngenutil.pas Normal file
View File

@ -0,0 +1,208 @@
{
Copyright (c) 1998-20011 by Florian Klaempfl
Generic version of some node tree helper routines that can be overridden
by cpu-specific versions
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
****************************************************************************
}
unit ngenutil;
{$i fpcdefs.inc}
interface
uses
node;
type
tnodeutils = class
class function call_fail_node:tnode; virtual;
class function initialize_data_node(p:tnode):tnode; virtual;
class function finalize_data_node(p:tnode):tnode; virtual;
end;
tnodeutilsclass = class of tnodeutils;
const
cnodeutils: tnodeutilsclass = tnodeutils;
implementation
uses
verbose,constexp,
symconst,symtype,symdef,symsym,symbase,symtable,defutil,
nadd,nbas,ncal,ncnv,ncon,nflw,nld,nmem,nobj,nutils,
pass_1;
class function tnodeutils.call_fail_node:tnode;
var
para : tcallparanode;
newstatement : tstatementnode;
srsym : tsym;
begin
result:=internalstatements(newstatement);
{ call fail helper and exit normal }
if is_class(current_structdef) then
begin
srsym:=search_struct_member(current_structdef,'FREEINSTANCE');
if assigned(srsym) and
(srsym.typ=procsym) then
begin
{ if self<>0 and vmt<>0 then freeinstance }
addstatement(newstatement,cifnode.create(
caddnode.create(andn,
caddnode.create(unequaln,
load_self_pointer_node,
cnilnode.create),
caddnode.create(unequaln,
load_vmt_pointer_node,
cnilnode.create)),
ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[]),
nil));
end
else
internalerror(200305108);
end
else
if is_object(current_structdef) then
begin
{ parameter 3 : vmt_offset }
{ parameter 2 : pointer to vmt }
{ parameter 1 : self pointer }
para:=ccallparanode.create(
cordconstnode.create(tobjectdef(current_structdef).vmt_offset,s32inttype,false),
ccallparanode.create(
ctypeconvnode.create_internal(
load_vmt_pointer_node,
voidpointertype),
ccallparanode.create(
ctypeconvnode.create_internal(
load_self_pointer_node,
voidpointertype),
nil)));
addstatement(newstatement,
ccallnode.createintern('fpc_help_fail',para));
end
else
internalerror(200305132);
{ self:=nil }
addstatement(newstatement,cassignmentnode.create(
load_self_pointer_node,
cnilnode.create));
{ exit }
addstatement(newstatement,cexitnode.create(nil));
end;
class function tnodeutils.initialize_data_node(p:tnode):tnode;
begin
if not assigned(p.resultdef) then
typecheckpass(p);
if is_ansistring(p.resultdef) or
is_wide_or_unicode_string(p.resultdef) or
is_interfacecom_or_dispinterface(p.resultdef) or
is_dynamic_array(p.resultdef) then
begin
result:=cassignmentnode.create(
ctypeconvnode.create_internal(p,voidpointertype),
cnilnode.create
);
end
else
begin
result:=ccallnode.createintern('fpc_initialize',
ccallparanode.create(
caddrnode.create_internal(
crttinode.create(
tstoreddef(p.resultdef),initrtti,rdt_normal)),
ccallparanode.create(
caddrnode.create_internal(p),
nil)));
end;
end;
class function tnodeutils.finalize_data_node(p:tnode):tnode;
var
newstatement : tstatementnode;
begin
if not assigned(p.resultdef) then
typecheckpass(p);
if is_ansistring(p.resultdef) then
begin
result:=internalstatements(newstatement);
addstatement(newstatement,ccallnode.createintern('fpc_ansistr_decr_ref',
ccallparanode.create(
ctypeconvnode.create_internal(p,voidpointertype),
nil)));
addstatement(newstatement,cassignmentnode.create(
ctypeconvnode.create_internal(p.getcopy,voidpointertype),
cnilnode.create
));
end
else if is_widestring(p.resultdef) then
begin
result:=internalstatements(newstatement);
addstatement(newstatement,ccallnode.createintern('fpc_widestr_decr_ref',
ccallparanode.create(
ctypeconvnode.create_internal(p,voidpointertype),
nil)));
addstatement(newstatement,cassignmentnode.create(
ctypeconvnode.create_internal(p.getcopy,voidpointertype),
cnilnode.create
));
end
else if is_unicodestring(p.resultdef) then
begin
result:=internalstatements(newstatement);
addstatement(newstatement,ccallnode.createintern('fpc_unicodestr_decr_ref',
ccallparanode.create(
ctypeconvnode.create_internal(p,voidpointertype),
nil)));
addstatement(newstatement,cassignmentnode.create(
ctypeconvnode.create_internal(p.getcopy,voidpointertype),
cnilnode.create
));
end
else if is_interfacecom_or_dispinterface(p.resultdef) then
begin
result:=internalstatements(newstatement);
addstatement(newstatement,ccallnode.createintern('fpc_intf_decr_ref',
ccallparanode.create(
ctypeconvnode.create_internal(p,voidpointertype),
nil)));
addstatement(newstatement,cassignmentnode.create(
ctypeconvnode.create_internal(p.getcopy,voidpointertype),
cnilnode.create
));
end
else
result:=ccallnode.createintern('fpc_finalize',
ccallparanode.create(
caddrnode.create_internal(
crttinode.create(
tstoreddef(p.resultdef),initrtti,rdt_normal)),
ccallparanode.create(
caddrnode.create_internal(p),
nil)));
end;
end.

View File

@ -72,10 +72,6 @@ interface
function load_vmt_pointer_node:tnode;
function is_self_node(p:tnode):boolean;
function call_fail_node:tnode;
function initialize_data_node(p:tnode):tnode;
function finalize_data_node(p:tnode):tnode;
function node_complexity(p: tnode): cardinal;
function node_resources_fpu(p: tnode): cardinal;
procedure node_tree_set_filepos(var n:tnode;const filepos:tfileposinfo);
@ -525,161 +521,6 @@ implementation
end;
function call_fail_node:tnode;
var
para : tcallparanode;
newstatement : tstatementnode;
srsym : tsym;
begin
result:=internalstatements(newstatement);
{ call fail helper and exit normal }
if is_class(current_structdef) then
begin
srsym:=search_struct_member(current_structdef,'FREEINSTANCE');
if assigned(srsym) and
(srsym.typ=procsym) then
begin
{ if self<>0 and vmt<>0 then freeinstance }
addstatement(newstatement,cifnode.create(
caddnode.create(andn,
caddnode.create(unequaln,
load_self_pointer_node,
cnilnode.create),
caddnode.create(unequaln,
load_vmt_pointer_node,
cnilnode.create)),
ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[]),
nil));
end
else
internalerror(200305108);
end
else
if is_object(current_structdef) then
begin
{ parameter 3 : vmt_offset }
{ parameter 2 : pointer to vmt }
{ parameter 1 : self pointer }
para:=ccallparanode.create(
cordconstnode.create(tobjectdef(current_structdef).vmt_offset,s32inttype,false),
ccallparanode.create(
ctypeconvnode.create_internal(
load_vmt_pointer_node,
voidpointertype),
ccallparanode.create(
ctypeconvnode.create_internal(
load_self_pointer_node,
voidpointertype),
nil)));
addstatement(newstatement,
ccallnode.createintern('fpc_help_fail',para));
end
else
internalerror(200305132);
{ self:=nil }
addstatement(newstatement,cassignmentnode.create(
load_self_pointer_node,
cnilnode.create));
{ exit }
addstatement(newstatement,cexitnode.create(nil));
end;
function initialize_data_node(p:tnode):tnode;
begin
if not assigned(p.resultdef) then
typecheckpass(p);
if is_ansistring(p.resultdef) or
is_wide_or_unicode_string(p.resultdef) or
is_interfacecom_or_dispinterface(p.resultdef) or
is_dynamic_array(p.resultdef) then
begin
result:=cassignmentnode.create(
ctypeconvnode.create_internal(p,voidpointertype),
cnilnode.create
);
end
else
begin
result:=ccallnode.createintern('fpc_initialize',
ccallparanode.create(
caddrnode.create_internal(
crttinode.create(
tstoreddef(p.resultdef),initrtti,rdt_normal)),
ccallparanode.create(
caddrnode.create_internal(p),
nil)));
end;
end;
function finalize_data_node(p:tnode):tnode;
var
newstatement : tstatementnode;
begin
if not assigned(p.resultdef) then
typecheckpass(p);
if is_ansistring(p.resultdef) then
begin
result:=internalstatements(newstatement);
addstatement(newstatement,ccallnode.createintern('fpc_ansistr_decr_ref',
ccallparanode.create(
ctypeconvnode.create_internal(p,voidpointertype),
nil)));
addstatement(newstatement,cassignmentnode.create(
ctypeconvnode.create_internal(p.getcopy,voidpointertype),
cnilnode.create
));
end
else if is_widestring(p.resultdef) then
begin
result:=internalstatements(newstatement);
addstatement(newstatement,ccallnode.createintern('fpc_widestr_decr_ref',
ccallparanode.create(
ctypeconvnode.create_internal(p,voidpointertype),
nil)));
addstatement(newstatement,cassignmentnode.create(
ctypeconvnode.create_internal(p.getcopy,voidpointertype),
cnilnode.create
));
end
else if is_unicodestring(p.resultdef) then
begin
result:=internalstatements(newstatement);
addstatement(newstatement,ccallnode.createintern('fpc_unicodestr_decr_ref',
ccallparanode.create(
ctypeconvnode.create_internal(p,voidpointertype),
nil)));
addstatement(newstatement,cassignmentnode.create(
ctypeconvnode.create_internal(p.getcopy,voidpointertype),
cnilnode.create
));
end
else if is_interfacecom_or_dispinterface(p.resultdef) then
begin
result:=internalstatements(newstatement);
addstatement(newstatement,ccallnode.createintern('fpc_intf_decr_ref',
ccallparanode.create(
ctypeconvnode.create_internal(p,voidpointertype),
nil)));
addstatement(newstatement,cassignmentnode.create(
ctypeconvnode.create_internal(p.getcopy,voidpointertype),
cnilnode.create
));
end
else
result:=ccallnode.createintern('fpc_finalize',
ccallparanode.create(
caddrnode.create_internal(
crttinode.create(
tstoreddef(p.resultdef),initrtti,rdt_normal)),
ccallparanode.create(
caddrnode.create_internal(p),
nil)));
end;
{ this function must return a very high value ("infinity") for }
{ trees containing a call, the rest can be balanced more or less }
{ at will, probably best mainly in terms of required memory }

View File

@ -52,7 +52,7 @@ implementation
symbase,symconst,symdef,symsym,symtable,defutil,
{ pass 1 }
pass_1,htypechk,
nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,nbas,nutils,
nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,nbas,nutils,ngenutil,
{ parser }
scanner,
pbase,pexpr,
@ -314,7 +314,7 @@ implementation
{ create call to fpc_initialize }
if is_managed_type(tpointerdef(p.resultdef).pointeddef) or
((m_iso in current_settings.modeswitches) and (tpointerdef(p.resultdef).pointeddef.typ=filedef)) then
addstatement(newstatement,initialize_data_node(cderefnode.create(ctemprefnode.create(temp))));
addstatement(newstatement,cnodeutils.initialize_data_node(cderefnode.create(ctemprefnode.create(temp))));
{ copy the temp to the destination }
addstatement(newstatement,cassignmentnode.create(
@ -328,7 +328,7 @@ implementation
begin
{ create call to fpc_finalize }
if is_managed_type(tpointerdef(p.resultdef).pointeddef) then
addstatement(newstatement,finalize_data_node(cderefnode.create(p.getcopy)));
addstatement(newstatement,cnodeutils.finalize_data_node(cderefnode.create(p.getcopy)));
{ create call to fpc_freemem }
para := ccallparanode.create(p,nil);
@ -635,9 +635,9 @@ implementation
else
begin
if isinit then
newblock:=initialize_data_node(ppn.left)
newblock:=cnodeutils.initialize_data_node(ppn.left)
else
newblock:=finalize_data_node(ppn.left);
newblock:=cnodeutils.finalize_data_node(ppn.left);
end;
ppn.left:=nil;
paras.free;

View File

@ -50,7 +50,7 @@ implementation
paramgr,symutil,
{ pass 1 }
pass_1,htypechk,
nutils,nbas,nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
nutils,ngenutil,nbas,nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
{ parser }
scanner,
pbase,pexpr,
@ -1145,7 +1145,7 @@ implementation
if (current_procinfo.procdef.proctypeoption<>potype_constructor) then
Message(parser_e_fail_only_in_constructor);
consume(_FAIL);
code:=call_fail_node;
code:=cnodeutils.call_fail_node;
end;
_ASM :
code:=_asm_statement;

View File

@ -85,7 +85,7 @@ implementation
paramgr,
ppu,fmodule,
{ pass 1 }
nutils,nld,ncal,ncon,nflw,nadd,ncnv,nmem,
nutils,ngenutil,nld,ncal,ncon,nflw,nadd,ncnv,nmem,
pass_1,
{$ifdef state_tracking}
nstate,
@ -467,7 +467,7 @@ implementation
caddnode.create(unequaln,
ctypeconvnode.create_internal(load_vmt_pointer_node,voidpointertype),
cnilnode.create),
finalize_data_node(load_self_node),
cnodeutils.finalize_data_node(load_self_node),
nil));
end;
{ parameter 3 : vmt_offset }
@ -515,7 +515,7 @@ implementation
is_managed_type(current_procinfo.procdef.returndef) and
(not paramanager.ret_in_param(current_procinfo.procdef.returndef, current_procinfo.procdef.proccalloption)) and
(not is_class(current_procinfo.procdef.returndef)) then
addstatement(newstatement,finalize_data_node(load_result_node));
addstatement(newstatement,cnodeutils.finalize_data_node(load_result_node));
{$if defined(x86) or defined(arm)}
{ safecall handling }
if (tf_safecall_exceptions in target_info.flags) and