mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-10 04:49:07 +02:00
* use destination location instead of a temp when constructing sets, resolves #40384
This commit is contained in:
parent
8aca910435
commit
06fc6f1e6b
@ -3616,6 +3616,7 @@ implementation
|
||||
tempn: tnode;
|
||||
newstatement : tstatementnode;
|
||||
temp : ttempcreatenode;
|
||||
no_temp: Boolean;
|
||||
begin
|
||||
result:=nil;
|
||||
|
||||
@ -3652,40 +3653,31 @@ implementation
|
||||
end;
|
||||
addn:
|
||||
begin
|
||||
{ can we directly write into the result? }
|
||||
no_temp:=assigned(aktassignmentnode) and
|
||||
(aktassignmentnode.right=self) and
|
||||
(aktassignmentnode.left.resultdef=self.resultdef) and
|
||||
valid_for_var(aktassignmentnode.left,false);
|
||||
|
||||
{ optimize first loading of a set }
|
||||
if (right.nodetype=setelementn) and
|
||||
not(assigned(tsetelementnode(right).right)) and
|
||||
is_emptyset(left) then
|
||||
begin
|
||||
result:=internalstatements(newstatement);
|
||||
|
||||
{ create temp for result }
|
||||
temp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,true);
|
||||
addstatement(newstatement,temp);
|
||||
|
||||
{ adjust for set base }
|
||||
tsetelementnode(right).left:=caddnode.create(subn,
|
||||
ctypeconvnode.create_internal(tsetelementnode(right).left,sinttype),
|
||||
cordconstnode.create(tsetdef(resultdef).setbase,sinttype,false));
|
||||
|
||||
addstatement(newstatement,ccallnode.createintern('fpc_varset_create_element',
|
||||
ccallparanode.create(ctemprefnode.create(temp),
|
||||
ccallparanode.create(cordconstnode.create(resultdef.size,sinttype,false),
|
||||
ccallparanode.create(tsetelementnode(right).left,nil))))
|
||||
);
|
||||
|
||||
{ the last statement should return the value as
|
||||
location and type, this is done be referencing the
|
||||
temp and converting it first from a persistent temp to
|
||||
normal temp }
|
||||
addstatement(newstatement,ctempdeletenode.create_normal_temp(temp));
|
||||
addstatement(newstatement,ctemprefnode.create(temp));
|
||||
|
||||
tsetelementnode(right).left := nil;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if right.nodetype=setelementn then
|
||||
if no_temp then
|
||||
begin
|
||||
result:=ccallnode.createintern('fpc_varset_create_element',
|
||||
ccallparanode.create(aktassignmentnode.left.getcopy,
|
||||
ccallparanode.create(cordconstnode.create(resultdef.size,sinttype,false),
|
||||
ccallparanode.create(tsetelementnode(right).left,nil))));
|
||||
include(aktassignmentnode.assignmentnodeflags,anf_assign_done_in_right);
|
||||
end
|
||||
else
|
||||
begin
|
||||
result:=internalstatements(newstatement);
|
||||
|
||||
@ -3693,43 +3685,96 @@ implementation
|
||||
temp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,true);
|
||||
addstatement(newstatement,temp);
|
||||
|
||||
{ adjust for set base }
|
||||
tsetelementnode(right).left:=caddnode.create(subn,
|
||||
ctypeconvnode.create_internal(tsetelementnode(right).left,sinttype),
|
||||
cordconstnode.create(tsetdef(resultdef).setbase,sinttype,false));
|
||||
addstatement(newstatement,ccallnode.createintern('fpc_varset_create_element',
|
||||
ccallparanode.create(ctemprefnode.create(temp),
|
||||
ccallparanode.create(cordconstnode.create(resultdef.size,sinttype,false),
|
||||
ccallparanode.create(tsetelementnode(right).left,nil))))
|
||||
);
|
||||
|
||||
{ add a range or a single element? }
|
||||
if assigned(tsetelementnode(right).right) then
|
||||
begin
|
||||
{ adjust for set base }
|
||||
tsetelementnode(right).right:=caddnode.create(subn,
|
||||
ctypeconvnode.create_internal(tsetelementnode(right).right,sinttype),
|
||||
cordconstnode.create(tsetdef(resultdef).setbase,sinttype,false));
|
||||
addstatement(newstatement,ccallnode.createintern('fpc_varset_set_range',
|
||||
ccallparanode.create(cordconstnode.create(resultdef.size,sinttype,false),
|
||||
ccallparanode.create(tsetelementnode(right).right,
|
||||
ccallparanode.create(tsetelementnode(right).left,
|
||||
ccallparanode.create(ctemprefnode.create(temp),
|
||||
ccallparanode.create(left,nil))))))
|
||||
);
|
||||
end
|
||||
else
|
||||
addstatement(newstatement,ccallnode.createintern('fpc_varset_set',
|
||||
ccallparanode.create(cordconstnode.create(resultdef.size,sinttype,false),
|
||||
ccallparanode.create(ctypeconvnode.create_internal(tsetelementnode(right).left,sinttype),
|
||||
ccallparanode.create(ctemprefnode.create(temp),
|
||||
ccallparanode.create(left,nil)))))
|
||||
);
|
||||
{ remove reused parts from original node }
|
||||
tsetelementnode(right).right:=nil;
|
||||
tsetelementnode(right).left:=nil;
|
||||
left:=nil;
|
||||
{ the last statement should return the value as
|
||||
location and type, this is done be referencing the
|
||||
temp and converting it first from a persistent temp to
|
||||
normal temp }
|
||||
addstatement(newstatement,ctempdeletenode.create_normal_temp(temp));
|
||||
addstatement(newstatement,ctemprefnode.create(temp));
|
||||
end;
|
||||
tsetelementnode(right).left:=nil;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if right.nodetype=setelementn then
|
||||
begin
|
||||
{ adjust for set base }
|
||||
tsetelementnode(right).left:=caddnode.create(subn,
|
||||
ctypeconvnode.create_internal(tsetelementnode(right).left,sinttype),
|
||||
cordconstnode.create(tsetdef(resultdef).setbase,sinttype,false));
|
||||
|
||||
if no_temp then
|
||||
begin
|
||||
{ add a range or a single element? }
|
||||
if assigned(tsetelementnode(right).right) then
|
||||
begin
|
||||
{ adjust for set base }
|
||||
tsetelementnode(right).right:=caddnode.create(subn,
|
||||
ctypeconvnode.create_internal(tsetelementnode(right).right,sinttype),
|
||||
cordconstnode.create(tsetdef(resultdef).setbase,sinttype,false));
|
||||
|
||||
result:=ccallnode.createintern('fpc_varset_set_range',
|
||||
ccallparanode.create(cordconstnode.create(resultdef.size,sinttype,false),
|
||||
ccallparanode.create(tsetelementnode(right).right,
|
||||
ccallparanode.create(tsetelementnode(right).left,
|
||||
ccallparanode.create(aktassignmentnode.left.getcopy,
|
||||
ccallparanode.create(left,nil))))));
|
||||
end
|
||||
else
|
||||
result:=ccallnode.createintern('fpc_varset_set',
|
||||
ccallparanode.create(cordconstnode.create(resultdef.size,sinttype,false),
|
||||
ccallparanode.create(ctypeconvnode.create_internal(tsetelementnode(right).left,sinttype),
|
||||
ccallparanode.create(aktassignmentnode.left.getcopy,
|
||||
ccallparanode.create(left,nil)))));
|
||||
include(aktassignmentnode.assignmentnodeflags,anf_assign_done_in_right);
|
||||
end
|
||||
else
|
||||
begin
|
||||
result:=internalstatements(newstatement);
|
||||
|
||||
{ create temp for result }
|
||||
temp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,true);
|
||||
addstatement(newstatement,temp);
|
||||
|
||||
{ add a range or a single element? }
|
||||
if assigned(tsetelementnode(right).right) then
|
||||
begin
|
||||
{ adjust for set base }
|
||||
tsetelementnode(right).right:=caddnode.create(subn,
|
||||
ctypeconvnode.create_internal(tsetelementnode(right).right,sinttype),
|
||||
cordconstnode.create(tsetdef(resultdef).setbase,sinttype,false));
|
||||
addstatement(newstatement,ccallnode.createintern('fpc_varset_set_range',
|
||||
ccallparanode.create(cordconstnode.create(resultdef.size,sinttype,false),
|
||||
ccallparanode.create(tsetelementnode(right).right,
|
||||
ccallparanode.create(tsetelementnode(right).left,
|
||||
ccallparanode.create(ctemprefnode.create(temp),
|
||||
ccallparanode.create(left,nil))))))
|
||||
);
|
||||
end
|
||||
else
|
||||
addstatement(newstatement,ccallnode.createintern('fpc_varset_set',
|
||||
ccallparanode.create(cordconstnode.create(resultdef.size,sinttype,false),
|
||||
ccallparanode.create(ctypeconvnode.create_internal(tsetelementnode(right).left,sinttype),
|
||||
ccallparanode.create(ctemprefnode.create(temp),
|
||||
ccallparanode.create(left,nil)))))
|
||||
);
|
||||
{ the last statement should return the value as
|
||||
location and type, this is done be referencing the
|
||||
temp and converting it first from a persistent temp to
|
||||
normal temp }
|
||||
addstatement(newstatement,ctempdeletenode.create_normal_temp(temp));
|
||||
addstatement(newstatement,ctemprefnode.create(temp));
|
||||
end;
|
||||
{ remove reused parts from original node }
|
||||
tsetelementnode(right).right:=nil;
|
||||
tsetelementnode(right).left:=nil;
|
||||
left:=nil;
|
||||
end
|
||||
else
|
||||
call_varset_helper('fpc_varset_add_sets');
|
||||
|
Loading…
Reference in New Issue
Block a user