mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-09 08:30:54 +02:00
* 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:
parent
15aaf36b82
commit
ab5b1fb686
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -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
|
||||
|
@ -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
208
compiler/ngenutil.pas
Normal 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.
|
@ -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 }
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user