diff --git a/compiler/htypechk.pas b/compiler/htypechk.pas index 98f2e47d46..1139828c6b 100644 --- a/compiler/htypechk.pas +++ b/compiler/htypechk.pas @@ -466,7 +466,7 @@ implementation { the nil as symtable signs firstcalln that this is an overloaded operator } - t:=ccallnode.create(ppn,Tprocsym(operpd.procsym),nil,nil); + t:=ccallnode.create(ppn,Tprocsym(operpd.procsym),nil,nil,[]); { we already know the procdef to use, so it can skip the overload choosing in callnode.det_resulttype } @@ -612,7 +612,7 @@ implementation { the nil as symtable signs firstcalln that this is an overloaded operator } - ht:=ccallnode.create(ppn,Tprocsym(operpd.procsym),nil,nil); + ht:=ccallnode.create(ppn,Tprocsym(operpd.procsym),nil,nil,[]); { we already know the procdef to use, so it can skip the overload choosing in callnode.det_resulttype } @@ -1922,7 +1922,10 @@ implementation end. { $Log$ - Revision 1.87 2004-05-23 15:03:40 peter + Revision 1.88 2004-05-23 18:28:40 peter + * methodpointer is loaded into a temp when it was a calln + + Revision 1.87 2004/05/23 15:03:40 peter * some typeconvs don't allow assignment or passing to var para Revision 1.86 2004/05/16 13:29:46 peter diff --git a/compiler/nbas.pas b/compiler/nbas.pas index fd8fcb1989..db4e6583a0 100644 --- a/compiler/nbas.pas +++ b/compiler/nbas.pas @@ -27,7 +27,7 @@ unit nbas; interface uses - cpubase,cgbase, + cpuinfo,cpubase,cgbase, aasmbase,aasmtai,aasmcpu, node,tgobj, symtype; @@ -393,7 +393,7 @@ implementation not(cs_extsyntax in aktmoduleswitches) and (hp.left.nodetype=calln) and not(is_void(hp.left.resulttype.def)) and - not(nf_return_value_used in tcallnode(hp.left).flags) and + not(cnf_return_value_used in tcallnode(hp.left).callnodeflags) and not((tcallnode(hp.left).procdefinition.proctypeoption=potype_constructor) and assigned(tprocdef(tcallnode(hp.left).procdefinition)._class) and is_object(tprocdef(tcallnode(hp.left).procdefinition)._class)) then @@ -667,6 +667,11 @@ implementation begin create(_restype,_size,_temptype); tempinfo^.may_be_in_reg:= + { temp must fit a single register } + (_size<=sizeof(aint)) and + { size of register operations must be known } + (def_cgsize(_restype.def)<>OS_NO) and + { no init/final needed } not (_restype.def.needs_inittable) and ((_restype.def.deftype <> pointerdef) or (not tpointerdef(_restype.def).pointertype.def.needs_inittable)); @@ -1012,7 +1017,10 @@ begin end. { $Log$ - Revision 1.82 2004-05-23 15:06:20 peter + Revision 1.83 2004-05-23 18:28:41 peter + * methodpointer is loaded into a temp when it was a calln + + Revision 1.82 2004/05/23 15:06:20 peter * implicit_finally flag must be set in pass1 * add check whether the implicit frame is generated when expected diff --git a/compiler/ncal.pas b/compiler/ncal.pas index 8377402be8..aa27b92d63 100644 --- a/compiler/ncal.pas +++ b/compiler/ncal.pas @@ -37,10 +37,16 @@ interface symbase,symtype,symsym,symdef,symtable; type - tcallnodeflags = ( - cnf_restypeset + tcallnodeflag = ( + cnf_restypeset, + cnf_return_value_used, + cnf_inherited, + cnf_anon_inherited, + cnf_new_call, + cnf_dispose_call, + cnf_member_call { called with implicit methodpointer tree } ); - tcallnodeflagset = set of tcallnodeflags; + tcallnodeflags = set of tcallnodeflag; tcallnode = class(tbinarynode) private @@ -68,6 +74,8 @@ interface procdefinition : tabstractprocdef; procdefinitionderef : tderef; { tree that contains the pointer to the object for this method } + methodpointerinit, + methodpointerdone, methodpointer : tnode; { inline function body } inlinecode : tnode; @@ -82,12 +90,11 @@ interface { you can't have a function with an "array of char" resulttype } { the RTL) (JM) } restype: ttype; - callnodeflags : tcallnodeflagset; + callnodeflags : tcallnodeflags; { only the processor specific nodes need to override this } { constructor } - constructor create(l:tnode; v : tprocsym;st : tsymtable; mp : tnode);virtual; - constructor create_def(l:tnode;def:tprocdef;mp:tnode);virtual; + constructor create(l:tnode; v : tprocsym;st : tsymtable; mp: tnode; callflags:tcallnodeflags);virtual; constructor create_procvar(l,r:tnode); constructor createintern(const name: string; params: tnode); constructor createinternres(const name: string; params: tnode; const res: ttype); @@ -120,14 +127,15 @@ interface end; tcallnodeclass = class of tcallnode; - tcallparaflags = ( - { flags used by tcallparanode } - cpf_is_colon_para + tcallparaflag = ( + cpf_is_colon_para, + cpf_varargs_para { belongs this para to varargs } ); + tcallparaflags = set of tcallparaflag; tcallparanode = class(tbinarynode) public - callparaflags : set of tcallparaflags; + callparaflags : tcallparaflags; paraitem : tparaitem; used_by_callnode : boolean; { only the processor specific nodes need to override this } @@ -150,7 +158,6 @@ interface function reverseparameters(p: tcallparanode): tcallparanode; - var ccallnode : tcallnodeclass; ccallparanode : tcallparanodeclass; @@ -388,7 +395,7 @@ type { Handle varargs and hidden paras directly, no typeconvs or } { typechecking needed } - if (nf_varargs_para in flags) then + if (cpf_varargs_para in callparaflags) then begin { convert pascal to C types } case left.resulttype.def.deftype of @@ -608,31 +615,16 @@ type TCALLNODE ****************************************************************************} - constructor tcallnode.create(l:tnode;v : tprocsym;st : tsymtable; mp : tnode); + constructor tcallnode.create(l:tnode;v : tprocsym;st : tsymtable; mp: tnode; callflags:tcallnodeflags); begin inherited create(calln,l,nil); symtableprocentry:=v; symtableproc:=st; - include(flags,nf_return_value_used); + callnodeflags:=callflags+[cnf_return_value_used]; methodpointer:=mp; + methodpointerinit:=nil; + methodpointerdone:=nil; procdefinition:=nil; - callnodeflags:=[]; - _funcretnode:=nil; - inlinecode:=nil; - paralength:=-1; - varargsparas:=nil; - end; - - - constructor tcallnode.create_def(l:tnode;def:tprocdef;mp:tnode); - begin - inherited create(calln,l,nil); - symtableprocentry:=nil; - symtableproc:=nil; - include(flags,nf_return_value_used); - methodpointer:=mp; - procdefinition:=def; - callnodeflags:=[]; _funcretnode:=nil; inlinecode:=nil; paralength:=-1; @@ -645,10 +637,11 @@ type inherited create(calln,l,r); symtableprocentry:=nil; symtableproc:=nil; - include(flags,nf_return_value_used); methodpointer:=nil; + methodpointerinit:=nil; + methodpointerdone:=nil; procdefinition:=nil; - callnodeflags:=[]; + callnodeflags:=[cnf_return_value_used]; _funcretnode:=nil; inlinecode:=nil; paralength:=-1; @@ -680,7 +673,7 @@ type {$endif EXTDEBUG} internalerror(200107271); end; - self.create(params,tprocsym(srsym),symowner,nil); + self.create(params,tprocsym(srsym),symowner,nil,[]); end; @@ -743,6 +736,8 @@ type destructor tcallnode.destroy; begin methodpointer.free; + methodpointerinit.free; + methodpointerdone.free; _funcretnode.free; inlinecode.free; if assigned(varargsparas) then @@ -762,6 +757,8 @@ type ppufile.getderef(procdefinitionderef); ppufile.getsmallset(callnodeflags); methodpointer:=ppuloadnode(ppufile); + methodpointerinit:=ppuloadnode(ppufile); + methodpointerdone:=ppuloadnode(ppufile); _funcretnode:=ppuloadnode(ppufile); inlinecode:=ppuloadnode(ppufile); end; @@ -774,6 +771,8 @@ type ppufile.putderef(procdefinitionderef); ppufile.putsmallset(callnodeflags); ppuwritenode(ppufile,methodpointer); + ppuwritenode(ppufile,methodpointerinit); + ppuwritenode(ppufile,methodpointerdone); ppuwritenode(ppufile,_funcretnode); ppuwritenode(ppufile,inlinecode); end; @@ -811,7 +810,7 @@ type { Connect paraitems } pt:=tcallparanode(left); while assigned(pt) and - (nf_varargs_para in pt.flags) do + (cpf_varargs_para in pt.callparaflags) do pt:=tcallparanode(pt.right); currpara:=tparaitem(procdefinition.Para.last); while assigned(currpara) do @@ -842,6 +841,14 @@ type n.methodpointer:=methodpointer.getcopy else n.methodpointer:=nil; + if assigned(methodpointerinit) then + n.methodpointerinit:=methodpointerinit.getcopy + else + n.methodpointerinit:=nil; + if assigned(methodpointerdone) then + n.methodpointerdone:=methodpointerdone.getcopy + else + n.methodpointerdone:=nil; if assigned(_funcretnode) then n._funcretnode:=_funcretnode.getcopy else @@ -896,7 +903,7 @@ type left:=ccallparanode.create(hp.left,left); { set callparanode resulttype and flags } left.resulttype:=hp.left.resulttype; - include(left.flags,nf_varargs_para); + include(tcallparanode(left).callparaflags,cpf_varargs_para); hp.left:=nil; hp:=tarrayconstructornode(hp.right); end; @@ -1033,7 +1040,7 @@ type selftree:=nil; { inherited } - if (nf_inherited in flags) then + if (cnf_inherited in callnodeflags) then selftree:=load_self_node else { constructors } @@ -1041,7 +1048,7 @@ type begin { push 0 as self when allocation is needed } if (methodpointer.resulttype.def.deftype=classrefdef) or - (nf_new_call in flags) then + (cnf_new_call in callnodeflags) then selftree:=cpointerconstnode.create(0,voidpointertype) else begin @@ -1090,12 +1097,12 @@ type internalerror(200305051); { inherited call, no create/destroy } - if (nf_inherited in flags) then + if (cnf_inherited in callnodeflags) then vmttree:=cpointerconstnode.create(0,voidpointertype) else { do not create/destroy when called from member function without specifying self explicit } - if (nf_member_call in flags) then + if (cnf_member_call in callnodeflags) then begin if (methodpointer.resulttype.def.deftype=classrefdef) and (procdefinition.proctypeoption=potype_constructor) then @@ -1105,11 +1112,11 @@ type end else { constructor with extended syntax called from new } - if (nf_new_call in flags) then + if (cnf_new_call in callnodeflags) then vmttree:=cloadvmtaddrnode.create(ctypenode.create(methodpointer.resulttype)) else { destructor with extended syntax called from dispose } - if (nf_dispose_call in flags) then + if (cnf_dispose_call in callnodeflags) then vmttree:=cloadvmtaddrnode.create(methodpointer.getcopy) else if (methodpointer.resulttype.def.deftype=classrefdef) then @@ -1174,7 +1181,7 @@ type i:=paralength; while (i>procdefinition.maxparacount) do begin - include(pt.flags,nf_varargs_para); + include(pt.callparaflags,cpf_varargs_para); oldppt:=@pt.right; pt:=tcallparanode(pt.right); dec(i); @@ -1182,7 +1189,7 @@ type { skip varargs that are inserted by array of const } while assigned(pt) and - (nf_varargs_para in pt.flags) do + (cpf_varargs_para in pt.callparaflags) do pt:=tcallparanode(pt.right); { process normal parameters and insert hidden parameters } @@ -1271,7 +1278,7 @@ type pt:=tcallparanode(left); while assigned(pt) do begin - if nf_varargs_para in pt.flags then + if cpf_varargs_para in pt.callparaflags then begin if not assigned(varargsparas) then varargsparas:=tvarargspara.create; @@ -1300,6 +1307,9 @@ type i : longint; method_must_be_valid, is_const : boolean; + hp : tnode; + mptemp : ttempcreatenode; + newstatement : tstatementnode; label errorexit; begin @@ -1326,6 +1336,40 @@ type goto errorexit; end; + if assigned(methodpointer) then + begin + resulttypepass(methodpointer); + hp:=methodpointer; + while assigned(hp) and + (hp.nodetype=typeconvn) do + hp:=tunarynode(hp).left; + if assigned(hp) and + ( + { call result must always be loaded in temp to prevent + double creation } + (hp.nodetype=calln) + { Also optimize also complex loads } +{$warning Complex loads can also be optimized} +// not(hp.nodetype in [typen,loadvmtaddrn,loadn]) + ) then + begin + { methodpointer loading } + methodpointerinit:=internalstatements(newstatement); + mptemp:=ctempcreatenode.create_reg(methodpointer.resulttype,methodpointer.resulttype.def.size,tt_persistent); + addstatement(newstatement,mptemp); + addstatement(newstatement,cassignmentnode.create( + ctemprefnode.create(mptemp), + methodpointer)); + resulttypepass(methodpointerinit); + { new methodpointer is only a temp reference } + methodpointer:=ctemprefnode.create(mptemp); + resulttypepass(methodpointer); + { methodpointer cleanup } + methodpointerdone:=ctempdeletenode.create(mptemp); + resulttypepass(methodpointerdone); + end; + end; + { procedure variable ? } if assigned(right) then begin @@ -1404,7 +1448,7 @@ type do this ugly hack in Delphi mode as it looks more like a bug. It's also not documented } if (m_delphi in aktmodeswitches) and - (nf_anon_inherited in flags) and + (cnf_anon_inherited in callnodeflags) and (symtableprocentry.owner.symtabletype=objectsymtable) and (po_overload in symtableprocentry.first_procdef.procoptions) and (symtableprocentry.procdef_count>=2) then @@ -1416,7 +1460,7 @@ type when there is only one proc definition, else the loadnode will give a strange error } if not(assigned(left)) and - not(nf_inherited in flags) and + not(cnf_inherited in callnodeflags) and (m_tp_procvar in aktmodeswitches) and (symtableprocentry.procdef_count=1) then begin @@ -1576,12 +1620,15 @@ type if assigned(methodpointer) then begin - resulttypepass(methodpointer); + { when methodpointer is a callnode we must load it first into a + temp to prevent the processing callnode twice } + if (methodpointer.nodetype=calln) then + internalerror(200405121); { direct call to inherited abstract method, then we can already give a error in the compiler instead of a runtime error } - if (nf_inherited in flags) and + if (cnf_inherited in callnodeflags) and (po_abstractmethod in procdefinition.procoptions) then CGMessage(cg_e_cant_call_abstract_method); @@ -1589,7 +1636,7 @@ type { called in a con- or destructor then a warning } { will be made } { con- and destructors need a pointer to the vmt } - if (nf_inherited in flags) and + if (cnf_inherited in callnodeflags) and (procdefinition.proctypeoption in [potype_constructor,potype_destructor]) and is_object(methodpointer.resulttype.def) and not(current_procinfo.procdef.proctypeoption in [potype_constructor,potype_destructor]) then @@ -1597,9 +1644,10 @@ type if methodpointer.nodetype<>typen then begin - hpt:=methodpointer; - while assigned(hpt) and (hpt.nodetype in [subscriptn,vecn]) do - hpt:=tunarynode(hpt).left; + { Remove all postfix operators } + hpt:=methodpointer; + while assigned(hpt) and (hpt.nodetype in [subscriptn,vecn]) do + hpt:=tunarynode(hpt).left; if (procdefinition.proctypeoption=potype_constructor) and assigned(symtableproc) and @@ -1634,8 +1682,8 @@ type methods. Ignore inherited and member calls, because the class is then already created } if (procdefinition.proctypeoption=potype_constructor) and - not(nf_inherited in flags) and - not(nf_member_call in flags) then + not(cnf_inherited in callnodeflags) and + not(cnf_member_call in callnodeflags) then verifyabstractcalls; end else @@ -1788,6 +1836,12 @@ type { order parameters } order_parameters; + if assigned(methodpointerinit) then + firstpass(methodpointerinit); + + if assigned(methodpointerdone) then + firstpass(methodpointerdone); + { function result node } if assigned(_funcretnode) then firstpass(_funcretnode); @@ -1868,7 +1922,7 @@ type end else { we have only to handle the result if it is used } - if (nf_return_value_used in flags) then + if (cnf_return_value_used in callnodeflags) then begin case resulttype.def.deftype of enumdef, @@ -2056,7 +2110,10 @@ begin end. { $Log$ - Revision 1.234 2004-05-23 15:06:20 peter + Revision 1.235 2004-05-23 18:28:41 peter + * methodpointer is loaded into a temp when it was a calln + + Revision 1.234 2004/05/23 15:06:20 peter * implicit_finally flag must be set in pass1 * add check whether the implicit frame is generated when expected diff --git a/compiler/ncgbas.pas b/compiler/ncgbas.pas index 64476f2b42..77a53378b4 100644 --- a/compiler/ncgbas.pas +++ b/compiler/ncgbas.pas @@ -339,6 +339,7 @@ interface end; end; + {***************************************************************************** TTEMPCREATENODE *****************************************************************************} @@ -476,7 +477,10 @@ begin end. { $Log$ - Revision 1.61 2004-05-23 15:06:20 peter + Revision 1.62 2004-05-23 18:28:41 peter + * methodpointer is loaded into a temp when it was a calln + + Revision 1.61 2004/05/23 15:06:20 peter * implicit_finally flag must be set in pass1 * add check whether the implicit frame is generated when expected diff --git a/compiler/ncgcal.pas b/compiler/ncgcal.pas index 67a31a57c7..b0720983f5 100644 --- a/compiler/ncgcal.pas +++ b/compiler/ncgcal.pas @@ -287,7 +287,7 @@ implementation begin { copy the value on the stack or use normal parameter push? Check for varargs first because that has no paraitem } - if not(nf_varargs_para in flags) and + if not(cpf_varargs_para in callparaflags) and paramanager.copy_value_on_stack(paraitem.paratyp,left.resulttype.def, aktcallnode.procdefinition.proccalloption) then begin @@ -361,7 +361,7 @@ implementation if not(assigned(paraitem)) or not(assigned(paraitem.paratype.def)) or not(assigned(paraitem.parasym) or - (nf_varargs_para in flags)) then + (cpf_varargs_para in callparaflags)) then internalerror(200304242); { Skip nothingn nodes which are used after disabling @@ -377,7 +377,7 @@ implementation allocate_tempparaloc; { handle varargs first, because paraitem.parasym is not valid } - if (nf_varargs_para in flags) then + if (cpf_varargs_para in callparaflags) then begin if paramanager.push_addr_param(vs_value,left.resulttype.def, aktcallnode.procdefinition.proccalloption) then @@ -537,7 +537,7 @@ implementation end else { we have only to handle the result if it is used } - if (nf_return_value_used in flags) then + if (cnf_return_value_used in callnodeflags) then begin if (resulttype.def.deftype=floatdef) then begin @@ -1044,7 +1044,7 @@ implementation release_para_temps; { if return value is not used } - if (not(nf_return_value_used in flags)) and (not is_void(resulttype.def)) then + if (not(cnf_return_value_used in callnodeflags)) and (not is_void(resulttype.def)) then begin if location.loc in [LOC_CREFERENCE,LOC_REFERENCE] then begin @@ -1209,7 +1209,7 @@ implementation { if return value is not used } if (not is_void(resulttype.def)) and - (not(nf_return_value_used in flags)) then + (not(cnf_return_value_used in callnodeflags)) then begin if location.loc in [LOC_CREFERENCE,LOC_REFERENCE] then begin @@ -1259,10 +1259,16 @@ implementation procedure tcgcallnode.pass_2; begin + if assigned(methodpointerinit) then + secondpass(methodpointerinit); + if assigned(inlinecode) then inlined_pass_2 else normal_pass_2; + + if assigned(methodpointerdone) then + secondpass(methodpointerdone); end; @@ -1272,7 +1278,10 @@ begin end. { $Log$ - Revision 1.166 2004-05-22 23:34:27 peter + Revision 1.167 2004-05-23 18:28:41 peter + * methodpointer is loaded into a temp when it was a calln + + Revision 1.166 2004/05/22 23:34:27 peter tai_regalloc.allocation changed to ratype to notify rgobj of register size changes Revision 1.165 2004/04/28 15:19:03 florian diff --git a/compiler/ncnv.pas b/compiler/ncnv.pas index 872c3b8dd1..1291421353 100644 --- a/compiler/ncnv.pas +++ b/compiler/ncnv.pas @@ -1226,8 +1226,7 @@ implementation begin include(current_procinfo.flags,pi_do_call); inc(aprocdef.procsym.refs); - hp:=ccallnode.create(ccallparanode.create(left,nil), - Tprocsym(aprocdef.procsym),nil,nil); + hp:=ccallnode.create(ccallparanode.create(left,nil),Tprocsym(aprocdef.procsym),nil,nil,[]); { tell explicitly which def we must use !! (PM) } tcallnode(hp).procdefinition:=aprocdef; left:=nil; @@ -2447,7 +2446,10 @@ begin end. { $Log$ - Revision 1.146 2004-05-23 15:03:40 peter + Revision 1.147 2004-05-23 18:28:41 peter + * methodpointer is loaded into a temp when it was a calln + + Revision 1.146 2004/05/23 15:03:40 peter * some typeconvs don't allow assignment or passing to var para Revision 1.145 2004/05/23 14:14:18 florian diff --git a/compiler/ninl.pas b/compiler/ninl.pas index e0a29c8f4c..d66b0a3fa8 100644 --- a/compiler/ninl.pas +++ b/compiler/ninl.pas @@ -1741,7 +1741,7 @@ implementation srsym:=searchsymonlyin(systemunit,'SETTEXTBUF'); hp:=ccallparanode.create(cordconstnode.create( tcallparanode(left).left.resulttype.def.size,s32inttype,true),left); - hp:=ccallnode.create(hp,tprocsym(srsym),systemunit,nil); + hp:=ccallnode.create(hp,tprocsym(srsym),systemunit,nil,[]); left:=nil; result:=hp; end; @@ -2374,7 +2374,10 @@ begin end. { $Log$ - Revision 1.133 2004-03-18 16:19:03 peter + Revision 1.134 2004-05-23 18:28:41 peter + * methodpointer is loaded into a temp when it was a calln + + Revision 1.133 2004/03/18 16:19:03 peter * fixed operator overload allowing for pointer-string * replaced some type_e_mismatch with more informational messages diff --git a/compiler/node.pas b/compiler/node.pas index 23a2b65aa8..602afe0103 100644 --- a/compiler/node.pas +++ b/compiler/node.pas @@ -204,17 +204,6 @@ interface nf_write, { Node is written to } nf_isproperty, - { flags used by tcallnode } - nf_return_value_used, - nf_inherited, - nf_anon_inherited, - nf_new_call, - nf_dispose_call, - nf_member_call, { called with implicit methodpointer tree } - - { flags used by tcallparanode } - nf_varargs_para, { belongs this para to varargs } - { taddrnode } nf_procvarload, nf_typedaddr, @@ -1093,7 +1082,10 @@ implementation end. { $Log$ - Revision 1.83 2004-05-23 15:06:21 peter + Revision 1.84 2004-05-23 18:28:41 peter + * methodpointer is loaded into a temp when it was a calln + + Revision 1.83 2004/05/23 15:06:21 peter * implicit_finally flag must be set in pass1 * add check whether the implicit frame is generated when expected diff --git a/compiler/nutils.pas b/compiler/nutils.pas index 1ab2f315f3..424c29c29d 100644 --- a/compiler/nutils.pas +++ b/compiler/nutils.pas @@ -354,7 +354,7 @@ implementation load_vmt_pointer_node, voidpointertype), cpointerconstnode.create(1,voidpointertype))), - ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node), + ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[]), nil)); end else @@ -438,7 +438,10 @@ end. { $Log$ - Revision 1.11 2004-05-23 15:04:49 peter + Revision 1.12 2004-05-23 18:28:41 peter + * methodpointer is loaded into a temp when it was a calln + + Revision 1.11 2004/05/23 15:04:49 peter * generate better code for ansistring initialization Revision 1.10 2004/02/20 21:55:59 peter diff --git a/compiler/pexpr.pas b/compiler/pexpr.pas index ef50f74632..feecb9566f 100644 --- a/compiler/pexpr.pas +++ b/compiler/pexpr.pas @@ -28,7 +28,7 @@ interface uses symtype,symdef,symbase, - node, + node,ncal, globals, cpuinfo; @@ -50,7 +50,7 @@ interface function parse_paras(__colon,in_prop_paras : boolean) : tnode; { the ID token has to be consumed before calling this function } - procedure do_member_read(classh:tobjectdef;getaddr : boolean;sym : tsym;var p1 : tnode;var again : boolean;callnflags:tnodeflags); + procedure do_member_read(classh:tobjectdef;getaddr : boolean;sym : tsym;var p1 : tnode;var again : boolean;callflags:tcallnodeflags); {$ifdef int64funcresok} function get_intconst:TConstExprInt; @@ -75,7 +75,7 @@ implementation symconst,symtable,symsym,defutil,defcmp, { pass 1 } pass_1,htypechk, - nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,nbas,nutils, + nmat,nadd,nmem,nset,ncnv,ninl,ncon,nld,nflw,nbas,nutils, { parser } scanner, pbase,pinline, @@ -711,7 +711,7 @@ implementation { reads the parameter for a subroutine call } - procedure do_proc_call(sym:tsym;st:tsymtable;obj:tobjectdef;getaddr:boolean;var again : boolean;var p1:tnode); + procedure do_proc_call(sym:tsym;st:tsymtable;obj:tobjectdef;getaddr:boolean;var again : boolean;var p1:tnode;callflags:tcallnodeflags); var membercall, prevafterassn : boolean; @@ -798,19 +798,19 @@ implementation consume(_RKLAMMER); end; end; - if assigned(obj) then - begin - if (st.symtabletype<>objectsymtable) then - internalerror(200310031); - p1:=ccallnode.create(para,tprocsym(sym),obj.symtable,p1); - end - else - p1:=ccallnode.create(para,tprocsym(sym),st,p1); { indicate if this call was generated by a member and no explicit self is used, this is needed to determine how to handle a destructor call (PFV) } if membercall then - include(p1.flags,nf_member_call); + include(callflags,cnf_member_call); + if assigned(obj) then + begin + if (st.symtabletype<>objectsymtable) then + internalerror(200310031); + p1:=ccallnode.create(para,tprocsym(sym),obj.symtable,p1,callflags); + end + else + p1:=ccallnode.create(para,tprocsym(sym),st,p1,callflags); end; afterassignment:=prevafterassn; end; @@ -860,6 +860,7 @@ implementation paras : tnode; p2 : tnode; membercall : boolean; + callflags : tcallnodeflags; begin paras:=nil; { property parameters? read them only if the property really } @@ -888,12 +889,12 @@ implementation case tpropertysym(sym).writeaccess.firstsym^.sym.typ of procsym : begin + callflags:=[]; { generate the method call } membercall:=maybe_load_methodpointer(st,p1); - p1:=ccallnode.create(paras, - tprocsym(tpropertysym(sym).writeaccess.firstsym^.sym),st,p1); if membercall then - include(tcallnode(p1).flags,nf_member_call); + include(callflags,cnf_member_call); + p1:=ccallnode.create(paras,tprocsym(tpropertysym(sym).writeaccess.firstsym^.sym),st,p1,callflags); paras:=nil; consume(_ASSIGNMENT); { read the expression } @@ -903,7 +904,8 @@ implementation if assigned(getprocvardef) then handle_procvar(getprocvardef,p2); tcallnode(p1).left:=ccallparanode.create(p2,tcallnode(p1).left); - include(tcallnode(p1).flags,nf_isproperty); + { mark as property, both the tcallnode and the real call block } + include(p1.flags,nf_isproperty); getprocvardef:=nil; end; varsym : @@ -943,11 +945,12 @@ implementation end; procsym : begin + callflags:=[]; { generate the method call } membercall:=maybe_load_methodpointer(st,p1); - p1:=ccallnode.create(paras,tprocsym(tpropertysym(sym).readaccess.firstsym^.sym),st,p1); if membercall then - include(tcallnode(p1).flags,nf_member_call); + include(callflags,cnf_member_call); + p1:=ccallnode.create(paras,tprocsym(tpropertysym(sym).readaccess.firstsym^.sym),st,p1,callflags); paras:=nil; include(p1.flags,nf_isproperty); end @@ -972,16 +975,12 @@ implementation { the ID token has to be consumed before calling this function } - procedure do_member_read(classh:tobjectdef;getaddr : boolean;sym : tsym;var p1 : tnode;var again : boolean;callnflags:tnodeflags); + procedure do_member_read(classh:tobjectdef;getaddr : boolean;sym : tsym;var p1 : tnode;var again : boolean;callflags:tcallnodeflags); var static_name : string; - isclassref : boolean; - srsymtable : tsymtable; -{$ifdef CHECKINHERITEDRESULT} - newstatement : tstatementnode; - newblock : tblocknode; -{$endif CHECKINHERITEDRESULT} + isclassref : boolean; + srsymtable : tsymtable; begin if sym=nil then begin @@ -1011,77 +1010,16 @@ implementation begin do_proc_call(sym,sym.owner,classh, (getaddr and not(token in [_CARET,_POINT])), - again,p1); - { add provided flags } - if (p1.nodetype=calln) then - p1.flags:=p1.flags+callnflags; + again,p1,callflags); { we need to know which procedure is called } do_resulttypepass(p1); - { now we know the method that is called } - if (p1.nodetype=calln) and - assigned(tcallnode(p1).procdefinition) then - begin - { calling using classref? } - if isclassref and - not(po_classmethod in tcallnode(p1).procdefinition.procoptions) and - not(tcallnode(p1).procdefinition.proctypeoption=potype_constructor) then - Message(parser_e_only_class_methods_via_class_ref); -{$ifdef CHECKINHERITEDRESULT} - { when calling inherited constructor we need to check the return value } - if (nf_inherited in callnflags) and - (tcallnode(p1).procdefinition.proctypeoption=potype_constructor) then - begin - { - For Classes: - - self:=inherited constructor - if self=nil then - exit - - For objects: - if inherited constructor=false then - begin - self:=nil; - exit; - end; - } - if is_class(tprocdef(tcallnode(p1).procdefinition)._class) then - begin - newblock:=internalstatements(newstatement,true); - addstatement(newstatement,cassignmentnode.create( - ctypeconvnode.create( - load_self_pointer_node, - voidpointertype), - ctypeconvnode.create( - p1, - voidpointertype))); - addstatement(newstatement,cifnode.create( - caddnode.create(equaln, - load_self_pointer_node, - cnilnode.create), - cexitnode.create(nil), - nil)); - p1:=newblock; - end - else - if is_object(tprocdef(tcallnode(p1).procdefinition)._class) then - begin - newblock:=internalstatements(newstatement,true); - addstatement(newstatement,call_fail_node); - addstatement(newstatement,cexitnode.create(nil)); - p1:=cifnode.create( - caddnode.create(equaln, - cordconstnode.create(0,booltype,false), - p1), - newblock, - nil); - end - else - internalerror(200305133); - end; -{$endif CHECKINHERITEDRESULT} - do_resulttypepass(p1); - end; + { calling using classref? } + if isclassref and + (p1.nodetype=calln) and + assigned(tcallnode(p1).procdefinition) and + not(po_classmethod in tcallnode(p1).procdefinition.procoptions) and + not(tcallnode(p1).procdefinition.proctypeoption=potype_constructor) then + Message(parser_e_only_class_methods_via_class_ref); end; varsym: begin @@ -1386,7 +1324,7 @@ implementation (po_classmethod in current_procinfo.procdef.procoptions); do_proc_call(srsym,srsymtable,nil, (getaddr and not(token in [_CARET,_POINT])), - again,p1); + again,p1,[]); { we need to know which procedure is called } if possible_error then begin @@ -1867,7 +1805,7 @@ implementation htype.setdef(tclassrefdef.create(htype)); p1:=ctypenode.create(htype); end; - do_member_read(classh,false,sym,p1,again,[nf_inherited,nf_anon_inherited]); + do_member_read(classh,false,sym,p1,again,[cnf_inherited,cnf_anon_inherited]); end else begin @@ -1882,7 +1820,7 @@ implementation (sym.typ<>procsym) then internalerror(200303171); p1:=nil; - do_proc_call(sym,sym.owner,classh,false,again,p1); + do_proc_call(sym,sym.owner,classh,false,again,p1,[]); end else begin @@ -2427,7 +2365,10 @@ implementation end. { $Log$ - Revision 1.155 2004-05-16 15:03:48 florian + Revision 1.156 2004-05-23 18:28:41 peter + * methodpointer is loaded into a temp when it was a calln + + Revision 1.155 2004/05/16 15:03:48 florian + support for assigned() added Revision 1.154 2004/04/29 19:56:37 daniel diff --git a/compiler/pinline.pas b/compiler/pinline.pas index 4f3e5e7720..a4d10059a6 100644 --- a/compiler/pinline.pas +++ b/compiler/pinline.pas @@ -75,7 +75,7 @@ implementation destructorname : stringid; sym : tsym; classh : tobjectdef; - callflag : tnodeflag; + callflag : tcallnodeflag; destructorpos, storepos : tfileposinfo; begin @@ -153,9 +153,9 @@ implementation p2:=cderefnode.create(p); do_resulttypepass(p2); if is_new then - callflag:=nf_new_call + callflag:=cnf_new_call else - callflag:=nf_dispose_call; + callflag:=cnf_dispose_call; if is_new then do_member_read(classh,false,sym,p2,again,[callflag]) else @@ -164,11 +164,7 @@ implementation do_member_read(classh,false,sym,p2,again,[callflag]) else begin - p2:=ccallnode.create(nil,tprocsym(sym),sym.owner,p2); - if is_new then - include(p2.flags,nf_new_call) - else - include(p2.flags,nf_dispose_call); + p2:=ccallnode.create(nil,tprocsym(sym),sym.owner,p2,[callflag]); { support dispose(p,done()); } if try_to_consume(_LKLAMMER) then begin @@ -185,7 +181,22 @@ implementation { we need the real called method } do_resulttypepass(p2); - if p2.nodetype<>calln then + if (p2.nodetype=calln) then + begin + if is_new then + begin + if (tcallnode(p2).procdefinition.proctypeoption<>potype_constructor) then + Message(parser_e_expr_have_to_be_constructor_call); + p2.resulttype:=p.resulttype; + p2:=cassignmentnode.create(p,p2); + end + else + begin + if (tcallnode(p2).procdefinition.proctypeoption<>potype_destructor) then + Message(parser_e_expr_have_to_be_destructor_call); + end; + end + else begin if is_new then CGMessage(parser_e_expr_have_to_be_constructor_call) @@ -193,22 +204,7 @@ implementation CGMessage(parser_e_expr_have_to_be_destructor_call); end; - if not codegenerror then - begin - if is_new then - begin - if (tcallnode(p2).procdefinition.proctypeoption<>potype_constructor) then - Message(parser_e_expr_have_to_be_constructor_call); - p2.resulttype:=p.resulttype; - p2:=cassignmentnode.create(p,p2); - end - else - begin - if (tcallnode(p2).procdefinition.proctypeoption<>potype_destructor) then - Message(parser_e_expr_have_to_be_destructor_call); - end; - end; - new_dispose_statement:=p2; + result:=p2; end; end else @@ -373,7 +369,7 @@ implementation afterassignment:=false; sym:=searchsym_in_class(classh,pattern); consume(_ID); - do_member_read(classh,false,sym,p1,again,[nf_new_call]); + do_member_read(classh,false,sym,p1,again,[cnf_new_call]); { we need to know which procedure is called } do_resulttypepass(p1); if not( @@ -531,8 +527,6 @@ implementation var newblock, paras : tnode; - npara, - destppn, ppn : tcallparanode; begin { for easy exiting if something goes wrong } @@ -633,7 +627,9 @@ implementation paradef : tdef; counter : integer; newstatement : tstatementnode; +{$ifdef ansistring_bits} mode : byte; +{$endif ansistring_bits} begin { for easy exiting if something goes wrong } result := cerrornode.create; @@ -763,7 +759,10 @@ implementation end. { $Log$ - Revision 1.30 2004-04-29 19:56:37 daniel + Revision 1.31 2004-05-23 18:28:41 peter + * methodpointer is loaded into a temp when it was a calln + + Revision 1.30 2004/04/29 19:56:37 daniel * Prepare compiler infrastructure for multiple ansistring types Revision 1.29 2004/02/04 18:45:29 jonas diff --git a/compiler/pstatmnt.pas b/compiler/pstatmnt.pas index 742a0ab687..907e8a9360 100644 --- a/compiler/pstatmnt.pas +++ b/compiler/pstatmnt.pas @@ -977,7 +977,7 @@ implementation - dispose of temp stack space - dispose on FPU stack } if (p.nodetype=calln) then - exclude(p.flags,nf_return_value_used); + exclude(tcallnode(p).callnodeflags,cnf_return_value_used); code:=p; end; @@ -1105,7 +1105,10 @@ implementation end. { $Log$ - Revision 1.133 2004-05-23 11:39:38 peter + Revision 1.134 2004-05-23 18:28:41 peter + * methodpointer is loaded into a temp when it was a calln + + Revision 1.133 2004/05/23 11:39:38 peter * give error when goto jumps to label outside current proc scope Revision 1.132 2004/03/04 17:22:10 peter diff --git a/compiler/psub.pas b/compiler/psub.pas index e27c320dd4..649bca989b 100644 --- a/compiler/psub.pas +++ b/compiler/psub.pas @@ -302,7 +302,7 @@ implementation ctypeconvnode.create_explicit( load_self_pointer_node, voidpointertype), - ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_vmt_pointer_node)), + ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_vmt_pointer_node,[])), nil)); end else @@ -361,7 +361,7 @@ implementation caddnode.create(unequaln, load_vmt_pointer_node, cnilnode.create), - ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node), + ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[]), nil)); end else @@ -399,7 +399,7 @@ implementation caddnode.create(unequaln, load_vmt_pointer_node, cnilnode.create)), - ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node), + ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[]), nil)); end else @@ -426,7 +426,7 @@ implementation load_vmt_pointer_node, voidpointertype), cpointerconstnode.create(1,voidpointertype))), - ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node), + ccallnode.create(nil,tprocsym(srsym),srsym.owner,load_self_node,[]), nil)); end else @@ -466,6 +466,7 @@ implementation var pd : tprocdef; newstatement : tstatementnode; + dummycall : tcallnode; begin generate_except_block:=internalstatements(newstatement); @@ -482,7 +483,7 @@ implementation caddnode.create(unequaln, load_vmt_pointer_node, cnilnode.create), - ccallnode.create(nil,tprocsym(pd.procsym),pd.procsym.owner,load_self_node), + ccallnode.create(nil,tprocsym(pd.procsym),pd.procsym.owner,load_self_node,[]), nil)); end; end @@ -1379,7 +1380,10 @@ implementation end. { $Log$ - Revision 1.191 2004-05-23 15:06:21 peter + Revision 1.192 2004-05-23 18:28:41 peter + * methodpointer is loaded into a temp when it was a calln + + Revision 1.191 2004/05/23 15:06:21 peter * implicit_finally flag must be set in pass1 * add check whether the implicit frame is generated when expected