mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-16 05:59:28 +02:00
* Changed code generation for assignments of managed types, it now generates a single call to helper procedure (significantly reducing code size) and is handled entirely in firstpass.
git-svn-id: trunk@20118 -
This commit is contained in:
parent
76fb845f4a
commit
afb4992113
@ -574,6 +574,9 @@ implementation
|
||||
oldflowcontrol : tflowcontrol;
|
||||
begin
|
||||
location_reset(location,LOC_VOID,OS_NO);
|
||||
{ managed types should be handled in firstpass }
|
||||
if is_managed_type(left.resultdef) or is_managed_type(right.resultdef) then
|
||||
InternalError(2012011901);
|
||||
|
||||
otlabel:=current_procinfo.CurrTrueLabel;
|
||||
oflabel:=current_procinfo.CurrFalseLabel;
|
||||
@ -594,31 +597,13 @@ implementation
|
||||
loading the left node afterwards can destroy the flags.
|
||||
}
|
||||
if not(right.expectloc in [LOC_FLAGS,LOC_JUMP]) and
|
||||
(is_managed_type(right.resultdef) or
|
||||
(node_complexity(right)>node_complexity(left))) then
|
||||
(node_complexity(right)>node_complexity(left)) then
|
||||
begin
|
||||
secondpass(right);
|
||||
{ increment source reference counter, this is
|
||||
useless for constants }
|
||||
if is_managed_type(right.resultdef) and
|
||||
not is_constnode(right) then
|
||||
begin
|
||||
location_force_mem(current_asmdata.CurrAsmList,right.location);
|
||||
location_get_data_ref(current_asmdata.CurrAsmList,right.location,href,false,sizeof(pint));
|
||||
cg.g_incrrefcount(current_asmdata.CurrAsmList,right.resultdef,href);
|
||||
end;
|
||||
if codegenerror then
|
||||
exit;
|
||||
|
||||
{ left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
|
||||
{ can be false }
|
||||
secondpass(left);
|
||||
{ decrement destination reference counter }
|
||||
if is_managed_type(left.resultdef) then
|
||||
begin
|
||||
location_get_data_ref(current_asmdata.CurrAsmList,left.location,href,false,sizeof(pint));
|
||||
cg.g_decrrefcount(current_asmdata.CurrAsmList,left.resultdef,href);
|
||||
end;
|
||||
if codegenerror then
|
||||
exit;
|
||||
end
|
||||
@ -626,12 +611,6 @@ implementation
|
||||
begin
|
||||
{ calculate left sides }
|
||||
secondpass(left);
|
||||
{ decrement destination reference counter }
|
||||
if is_managed_type(left.resultdef) then
|
||||
begin
|
||||
location_get_data_ref(current_asmdata.CurrAsmList,left.location,href,false,sizeof(pint));
|
||||
cg.g_decrrefcount(current_asmdata.CurrAsmList,left.resultdef,href);
|
||||
end;
|
||||
if codegenerror then
|
||||
exit;
|
||||
|
||||
@ -641,19 +620,8 @@ implementation
|
||||
oldflowcontrol:=flowcontrol;
|
||||
include(flowcontrol,fc_lefthandled);
|
||||
|
||||
{ left can't be never a 64 bit LOC_REGISTER, so the 3. arg }
|
||||
{ can be false }
|
||||
secondpass(right);
|
||||
flowcontrol:=oldflowcontrol;
|
||||
{ increment source reference counter, this is
|
||||
useless for string constants}
|
||||
if is_managed_type(right.resultdef) and
|
||||
(right.nodetype<>stringconstn) then
|
||||
begin
|
||||
location_force_mem(current_asmdata.CurrAsmList,right.location);
|
||||
location_get_data_ref(current_asmdata.CurrAsmList,right.location,href,false,sizeof(pint));
|
||||
cg.g_incrrefcount(current_asmdata.CurrAsmList,right.resultdef,href);
|
||||
end;
|
||||
|
||||
if codegenerror then
|
||||
exit;
|
||||
|
@ -702,6 +702,8 @@ implementation
|
||||
hp: tnode;
|
||||
oldassignmentnode : tassignmentnode;
|
||||
hdef: tdef;
|
||||
hs: string;
|
||||
needrtti: boolean;
|
||||
begin
|
||||
result:=nil;
|
||||
expectloc:=LOC_VOID;
|
||||
@ -731,6 +733,8 @@ implementation
|
||||
if is_managed_type(left.resultdef) then
|
||||
include(current_procinfo.flags,pi_do_call);
|
||||
|
||||
needrtti:=false;
|
||||
|
||||
if (is_shortstring(left.resultdef)) then
|
||||
begin
|
||||
if right.resultdef.typ=stringdef then
|
||||
@ -748,9 +752,9 @@ implementation
|
||||
firstpass(result);
|
||||
left:=nil;
|
||||
right:=nil;
|
||||
exit;
|
||||
end;
|
||||
end;
|
||||
exit;
|
||||
end
|
||||
{ call helpers for composite types containing automated types }
|
||||
else if is_managed_type(left.resultdef) and
|
||||
@ -790,34 +794,51 @@ implementation
|
||||
right:=nil;
|
||||
exit;
|
||||
end
|
||||
{ call helpers for windows widestrings, they aren't ref. counted }
|
||||
else if (tf_winlikewidestring in target_info.flags) and is_widestring(left.resultdef) then
|
||||
begin
|
||||
{ The first argument of fpc_widestr_assign is a var parameter. Properties cannot }
|
||||
{ be passed to var or out parameters, because in that case setters/getters are not }
|
||||
{ used. Further, if we would allow it in case there are no getters or setters, you }
|
||||
{ would need source changes in case these are introduced later on, thus defeating }
|
||||
{ part of the transparency advantages of properties. In this particular case, }
|
||||
{ however: }
|
||||
{ a) if there is a setter, this code will not be used since then the assignment }
|
||||
{ will be converted to a procedure call }
|
||||
{ b) the getter is irrelevant, because fpc_widestr_assign must always decrease }
|
||||
{ the refcount of the field to which we are writing }
|
||||
{ c) source code changes are not required if a setter is added/removed, because }
|
||||
{ this transformation is handled at compile time }
|
||||
{ -> we can remove the nf_isproperty flag (if any) from left, so that in case it }
|
||||
{ is a property which refers to a field without a setter call, we will not get }
|
||||
{ an error about trying to pass a property as a var parameter }
|
||||
exclude(left.flags,nf_isproperty);
|
||||
hp:=ccallparanode.create(ctypeconvnode.create_internal(right,voidpointertype),
|
||||
ccallparanode.create(ctypeconvnode.create_internal(left,voidpointertype),
|
||||
nil));
|
||||
result:=ccallnode.createintern('fpc_widestr_assign',hp);
|
||||
firstpass(result);
|
||||
left:=nil;
|
||||
right:=nil;
|
||||
exit;
|
||||
end;
|
||||
{ call helpers for pointer-sized managed types }
|
||||
else if is_widestring(left.resultdef) then
|
||||
hs:='fpc_widestr_assign'
|
||||
else if is_ansistring(left.resultdef) then
|
||||
hs:='fpc_ansistr_assign'
|
||||
else if is_unicodestring(left.resultdef) then
|
||||
hs:='fpc_unicodestr_assign'
|
||||
else if is_interfacecom_or_dispinterface(left.resultdef) then
|
||||
hs:='fpc_intf_assign'
|
||||
else if is_dynamic_array(left.resultdef) then
|
||||
begin
|
||||
hs:='fpc_dynarray_assign';
|
||||
needrtti:=true;
|
||||
end
|
||||
else
|
||||
exit;
|
||||
|
||||
{ The first argument of these procedures is a var parameter. Properties cannot }
|
||||
{ be passed to var or out parameters, because in that case setters/getters are not }
|
||||
{ used. Further, if we would allow it in case there are no getters or setters, you }
|
||||
{ would need source changes in case these are introduced later on, thus defeating }
|
||||
{ part of the transparency advantages of properties. In this particular case, }
|
||||
{ however: }
|
||||
{ a) if there is a setter, this code will not be used since then the assignment }
|
||||
{ will be converted to a procedure call }
|
||||
{ b) the getter is irrelevant, because fpc_widestr_assign must always decrease }
|
||||
{ the refcount of the field to which we are writing }
|
||||
{ c) source code changes are not required if a setter is added/removed, because }
|
||||
{ this transformation is handled at compile time }
|
||||
{ -> we can remove the nf_isproperty flag (if any) from left, so that in case it }
|
||||
{ is a property which refers to a field without a setter call, we will not get }
|
||||
{ an error about trying to pass a property as a var parameter }
|
||||
exclude(left.flags,nf_isproperty);
|
||||
hp:=ccallparanode.create(ctypeconvnode.create_internal(right,voidpointertype),
|
||||
ccallparanode.create(ctypeconvnode.create_internal(left,voidpointertype),
|
||||
nil));
|
||||
if needrtti then
|
||||
hp:=ccallparanode.create(
|
||||
caddrnode.create_internal(
|
||||
crttinode.create(tstoreddef(left.resultdef),initrtti,rdt_normal)),
|
||||
hp);
|
||||
result:=ccallnode.createintern(hs,hp);
|
||||
firstpass(result);
|
||||
left:=nil;
|
||||
right:=nil;
|
||||
end;
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user