From ab5b1fb686c5948c93696edbbca628bb76d77082 Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Sat, 20 Aug 2011 07:52:11 +0000 Subject: [PATCH] * 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 - --- .gitattributes | 1 + compiler/ncgutil.pas | 6 +- compiler/ngenutil.pas | 208 ++++++++++++++++++++++++++++++++++++++++++ compiler/nutils.pas | 159 -------------------------------- compiler/pinline.pas | 10 +- compiler/pstatmnt.pas | 4 +- compiler/psub.pas | 6 +- 7 files changed, 222 insertions(+), 172 deletions(-) create mode 100644 compiler/ngenutil.pas diff --git a/.gitattributes b/.gitattributes index 0ae37537f4..cd522006cd 100644 --- a/.gitattributes +++ b/.gitattributes @@ -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 diff --git a/compiler/ncgutil.pas b/compiler/ncgutil.pas index 76efd24080..db6a8f37c5 100644 --- a/compiler/ncgutil.pas +++ b/compiler/ncgutil.pas @@ -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; diff --git a/compiler/ngenutil.pas b/compiler/ngenutil.pas new file mode 100644 index 0000000000..16fedf0003 --- /dev/null +++ b/compiler/ngenutil.pas @@ -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. diff --git a/compiler/nutils.pas b/compiler/nutils.pas index 7cca235752..d76f4e0d2b 100644 --- a/compiler/nutils.pas +++ b/compiler/nutils.pas @@ -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 } diff --git a/compiler/pinline.pas b/compiler/pinline.pas index 03a26570e4..b736422594 100644 --- a/compiler/pinline.pas +++ b/compiler/pinline.pas @@ -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; diff --git a/compiler/pstatmnt.pas b/compiler/pstatmnt.pas index a8127da398..dc2a34b3c2 100644 --- a/compiler/pstatmnt.pas +++ b/compiler/pstatmnt.pas @@ -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; diff --git a/compiler/psub.pas b/compiler/psub.pas index 7c57a661d8..92c1eac6c3 100644 --- a/compiler/psub.pas +++ b/compiler/psub.pas @@ -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