* also set aktcallnode during tcallnode.pass_1, so that the callparanode

pass_1 code can make use of it

git-svn-id: trunk@29818 -
This commit is contained in:
Jonas Maebe 2015-02-23 22:47:41 +00:00
parent 863e81315e
commit aae879d28a

View File

@ -3600,123 +3600,131 @@ implementation
var var
para: tcallparanode; para: tcallparanode;
oldcallnode: tcallnode;
begin begin
result:=nil; result:=nil;
{ as pass_1 is never called on the methodpointer node, we must check oldcallnode:=aktcallnode;
here that it's not a helper type } aktcallnode:=self;
if assigned(methodpointer) and
(methodpointer.nodetype=typen) and
is_objectpascal_helper(ttypenode(methodpointer).typedef) and
not ttypenode(methodpointer).helperallowed then
Message(parser_e_no_category_as_types);
{ can we get rid of the call? } try
if (cs_opt_remove_emtpy_proc in current_settings.optimizerswitches) and { as pass_1 is never called on the methodpointer node, we must check
not(cnf_return_value_used in callnodeflags) and here that it's not a helper type }
(procdefinition.typ=procdef) and if assigned(methodpointer) and
tprocdef(procdefinition).isempty and (methodpointer.nodetype=typen) and
{ allow only certain proc options } is_objectpascal_helper(ttypenode(methodpointer).typedef) and
((tprocdef(procdefinition).procoptions-[po_none,po_classmethod,po_staticmethod, not ttypenode(methodpointer).helperallowed then
po_interrupt,po_iocheck,po_assembler,po_msgstr,po_msgint,po_exports,po_external,po_overload, Message(parser_e_no_category_as_types);
po_nostackframe,po_has_mangledname,po_has_public_name,po_forward,po_global,
po_inline,po_compilerproc,po_has_importdll,po_has_importname,po_kylixlocal,po_dispid,po_delphi_nested_cc,
po_rtlproc,po_ignore_for_overload_resolution,po_auto_raised_visibility])=[]) then
begin
{ check parameters for side effects }
para:=tcallparanode(left);
while assigned(para) do
begin
if (para.parasym.typ = paravarsym) and
((para.parasym.refs>0) or
{ array of consts are converted later on so we need to skip them here
else no error detection is done }
is_array_of_const(para.parasym.vardef) or
not(cs_opt_dead_values in current_settings.optimizerswitches) or
might_have_sideeffects(para.left)) then
break;
para:=tcallparanode(para.right);
end;
{ finally, remove it if no parameter with side effect has been found }
if para=nil then
begin
result:=cnothingnode.create;
exit;
end;
end;
{ convert Objective-C calls into a message call } { can we get rid of the call? }
if (procdefinition.typ=procdef) and if (cs_opt_remove_emtpy_proc in current_settings.optimizerswitches) and
(po_objc in tprocdef(procdefinition).procoptions) then not(cnf_return_value_used in callnodeflags) and
begin (procdefinition.typ=procdef) and
if not(cnf_objc_processed in callnodeflags) then tprocdef(procdefinition).isempty and
objc_convert_to_message_send; { allow only certain proc options }
end ((tprocdef(procdefinition).procoptions-[po_none,po_classmethod,po_staticmethod,
else po_interrupt,po_iocheck,po_assembler,po_msgstr,po_msgint,po_exports,po_external,po_overload,
begin po_nostackframe,po_has_mangledname,po_has_public_name,po_forward,po_global,
{ The following don't apply to obj-c: obj-c methods can never be po_inline,po_compilerproc,po_has_importdll,po_has_importname,po_kylixlocal,po_dispid,po_delphi_nested_cc,
inlined because they're always virtual and the destination can po_rtlproc,po_ignore_for_overload_resolution,po_auto_raised_visibility])=[]) then
change at run, and for the same reason we also can't perform begin
WPO on them (+ they have no constructors) } { check parameters for side effects }
para:=tcallparanode(left);
while assigned(para) do
begin
if (para.parasym.typ = paravarsym) and
((para.parasym.refs>0) or
{ array of consts are converted later on so we need to skip them here
else no error detection is done }
is_array_of_const(para.parasym.vardef) or
not(cs_opt_dead_values in current_settings.optimizerswitches) or
might_have_sideeffects(para.left)) then
break;
para:=tcallparanode(para.right);
end;
{ finally, remove it if no parameter with side effect has been found }
if para=nil then
begin
result:=cnothingnode.create;
exit;
end;
end;
{ Check if the call can be inlined, sets the cnf_do_inline flag } { convert Objective-C calls into a message call }
check_inlining; if (procdefinition.typ=procdef) and
(po_objc in tprocdef(procdefinition).procoptions) then
begin
if not(cnf_objc_processed in callnodeflags) then
objc_convert_to_message_send;
end
else
begin
{ The following don't apply to obj-c: obj-c methods can never be
inlined because they're always virtual and the destination can
change at run, and for the same reason we also can't perform
WPO on them (+ they have no constructors) }
{ must be called before maybe_load_in_temp(methodpointer), because { Check if the call can be inlined, sets the cnf_do_inline flag }
it converts the methodpointer into a temp in case it's a call check_inlining;
(and we want to know the original call)
}
register_created_object_types;
end;
{ Maybe optimize the loading of the methodpointer using a temp. When the methodpointer { must be called before maybe_load_in_temp(methodpointer), because
is a calln this is even required to not execute the calln twice. it converts the methodpointer into a temp in case it's a call
This needs to be done after the resulttype pass, because in the resulttype we can still convert the (and we want to know the original call)
calln to a loadn (PFV) } }
if assigned(methodpointer) then register_created_object_types;
maybe_load_in_temp(methodpointer); end;
{ Create destination (temp or assignment-variable reuse) for function result if it not yet set } { Maybe optimize the loading of the methodpointer using a temp. When the methodpointer
maybe_create_funcret_node; is a calln this is even required to not execute the calln twice.
This needs to be done after the resulttype pass, because in the resulttype we can still convert the
calln to a loadn (PFV) }
if assigned(methodpointer) then
maybe_load_in_temp(methodpointer);
{ Insert the self,vmt,function result in the parameters } { Create destination (temp or assignment-variable reuse) for function result if it not yet set }
gen_hidden_parameters; maybe_create_funcret_node;
{ Remove useless nodes from init/final blocks } { Insert the self,vmt,function result in the parameters }
{ (simplify depends on typecheck info) } gen_hidden_parameters;
if assigned(callinitblock) then
begin
typecheckpass(tnode(callinitblock));
doinlinesimplify(tnode(callinitblock));
end;
if assigned(callcleanupblock) then
begin
typecheckpass(tnode(callcleanupblock));
doinlinesimplify(tnode(callcleanupblock));
end;
{ If a constructor calls another constructor of the same or of an { Remove useless nodes from init/final blocks }
inherited class, some targets (jvm) have to generate different { (simplify depends on typecheck info) }
entry code for the constructor. } if assigned(callinitblock) then
if (current_procinfo.procdef.proctypeoption=potype_constructor) and begin
(procdefinition.typ=procdef) and typecheckpass(tnode(callinitblock));
(tprocdef(procdefinition).proctypeoption=potype_constructor) and doinlinesimplify(tnode(callinitblock));
([cnf_member_call,cnf_inherited] * callnodeflags <> []) then end;
current_procinfo.ConstructorCallingConstructor:=true; if assigned(callcleanupblock) then
begin
typecheckpass(tnode(callcleanupblock));
doinlinesimplify(tnode(callcleanupblock));
end;
{ object check helper will load VMT -> needs GOT } { If a constructor calls another constructor of the same or of an
if (cs_check_object in current_settings.localswitches) and inherited class, some targets (jvm) have to generate different
(cs_create_pic in current_settings.moduleswitches) then entry code for the constructor. }
include(current_procinfo.flags,pi_needs_got); if (current_procinfo.procdef.proctypeoption=potype_constructor) and
(procdefinition.typ=procdef) and
(tprocdef(procdefinition).proctypeoption=potype_constructor) and
([cnf_member_call,cnf_inherited] * callnodeflags <> []) then
current_procinfo.ConstructorCallingConstructor:=true;
{ Continue with checking a normal call or generate the inlined code } { object check helper will load VMT -> needs GOT }
if cnf_do_inline in callnodeflags then if (cs_check_object in current_settings.localswitches) and
result:=pass1_inline (cs_create_pic in current_settings.moduleswitches) then
else include(current_procinfo.flags,pi_needs_got);
begin
mark_unregable_parameters; { Continue with checking a normal call or generate the inlined code }
result:=pass1_normal; if cnf_do_inline in callnodeflags then
end; result:=pass1_inline
else
begin
mark_unregable_parameters;
result:=pass1_normal;
end;
finally
aktcallnode:=oldcallnode;
end;
end; end;