|
@@ -43,6 +43,9 @@ interface
|
|
function simplify(forinline : boolean): tnode;override;
|
|
function simplify(forinline : boolean): tnode;override;
|
|
function docompare(p: tnode): boolean; override;
|
|
function docompare(p: tnode): boolean; override;
|
|
|
|
|
|
|
|
+ { returns a node tree where the inc/dec are replaced by add/sub }
|
|
|
|
+ function getaddsub_for_incdec : tnode;
|
|
|
|
+
|
|
{ pack and unpack are changed into for-loops by the compiler }
|
|
{ pack and unpack are changed into for-loops by the compiler }
|
|
function first_pack_unpack: tnode; virtual;
|
|
function first_pack_unpack: tnode; virtual;
|
|
|
|
|
|
@@ -3839,12 +3842,106 @@ implementation
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
- function tinlinenode.first_IncDec: tnode;
|
|
|
|
|
|
+ function tinlinenode.getaddsub_for_incdec : tnode;
|
|
var
|
|
var
|
|
hp,hpp,resultnode : tnode;
|
|
hp,hpp,resultnode : tnode;
|
|
tempnode: ttempcreatenode;
|
|
tempnode: ttempcreatenode;
|
|
newstatement: tstatementnode;
|
|
newstatement: tstatementnode;
|
|
newblock: tblocknode;
|
|
newblock: tblocknode;
|
|
|
|
+ begin
|
|
|
|
+ newblock := internalstatements(newstatement);
|
|
|
|
+ { extra parameter? }
|
|
|
|
+ if assigned(tcallparanode(left).right) then
|
|
|
|
+ begin
|
|
|
|
+ { Yes, use for add node }
|
|
|
|
+ hpp := tcallparanode(tcallparanode(left).right).left;
|
|
|
|
+ tcallparanode(tcallparanode(left).right).left := nil;
|
|
|
|
+ if assigned(tcallparanode(tcallparanode(left).right).right) then
|
|
|
|
+ CGMessage(parser_e_illegal_expression);
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ { no, create constant 1 }
|
|
|
|
+ hpp := cordconstnode.create(1,tcallparanode(left).left.resultdef,false);
|
|
|
|
+ end;
|
|
|
|
+ typecheckpass(hpp);
|
|
|
|
+
|
|
|
|
+ { make sure we don't call functions part of the left node twice (and generally }
|
|
|
|
+ { optimize the code generation) }
|
|
|
|
+ { Storing address is not always an optimization: alignment of left is not known
|
|
|
|
+ at this point, so we must assume the worst and use an unaligned pointer.
|
|
|
|
+ This results in larger and slower code on alignment-sensitive targets.
|
|
|
|
+ Therefore the complexity condition below is questionable, maybe just filtering
|
|
|
|
+ out calls with "= NODE_COMPLEXITY_INF" is sufficient.
|
|
|
|
+ Value of 3 corresponds to subscript nodes, i.e. record field. }
|
|
|
|
+ if node_complexity(tcallparanode(left).left) > 3 then
|
|
|
|
+ begin
|
|
|
|
+ tempnode := ctempcreatenode.create(voidpointertype,voidpointertype.size,tt_persistent,true);
|
|
|
|
+ addstatement(newstatement,tempnode);
|
|
|
|
+ addstatement(newstatement,cassignmentnode.create(ctemprefnode.create(tempnode),
|
|
|
|
+ caddrnode.create_internal(tcallparanode(left).left.getcopy)));
|
|
|
|
+ hp := cderefnode.create(ctemprefnode.create(tempnode));
|
|
|
|
+ inserttypeconv_internal(hp,tcallparanode(left).left.resultdef);
|
|
|
|
+ end
|
|
|
|
+ else
|
|
|
|
+ begin
|
|
|
|
+ hp := tcallparanode(left).left.getcopy;
|
|
|
|
+ tempnode := nil;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ resultnode := hp.getcopy;
|
|
|
|
+ { avoid type errors from the addn/subn }
|
|
|
|
+ if not is_integer(resultnode.resultdef) then
|
|
|
|
+ begin
|
|
|
|
+ inserttypeconv_internal(hp,sinttype);
|
|
|
|
+ inserttypeconv_internal(hpp,sinttype);
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+ { addition/substraction depending on inc/dec }
|
|
|
|
+ if inlinenumber = in_inc_x then
|
|
|
|
+ hpp := caddnode.create(addn,hp,hpp)
|
|
|
|
+ else
|
|
|
|
+ hpp := caddnode.create(subn,hp,hpp);
|
|
|
|
+ { assign result of addition }
|
|
|
|
+ if not(is_integer(resultnode.resultdef)) then
|
|
|
|
+ inserttypeconv(hpp,corddef.create(
|
|
|
|
+{$ifdef cpu64bitaddr}
|
|
|
|
+ s64bit,
|
|
|
|
+{$else cpu64bitaddr}
|
|
|
|
+ s32bit,
|
|
|
|
+{$endif cpu64bitaddr}
|
|
|
|
+ get_min_value(resultnode.resultdef),
|
|
|
|
+ get_max_value(resultnode.resultdef),
|
|
|
|
+ true))
|
|
|
|
+ else
|
|
|
|
+ inserttypeconv(hpp,resultnode.resultdef);
|
|
|
|
+
|
|
|
|
+ { avoid any possible warnings }
|
|
|
|
+ inserttypeconv_internal(hpp,resultnode.resultdef);
|
|
|
|
+
|
|
|
|
+ { get varstates right }
|
|
|
|
+ node_reset_flags(hpp,[nf_pass1_done,nf_modify,nf_write]);
|
|
|
|
+ do_typecheckpass(hpp);
|
|
|
|
+
|
|
|
|
+ addstatement(newstatement,cassignmentnode.create(resultnode,hpp));
|
|
|
|
+
|
|
|
|
+ { force pass 1, so copied tries get first pass'ed as well and flags like nf_write, nf_call_unique
|
|
|
|
+ get set right }
|
|
|
|
+ node_reset_flags(newstatement.statement,[nf_pass1_done]);
|
|
|
|
+ { firstpass it }
|
|
|
|
+ firstpass(tnode(newstatement.left));
|
|
|
|
+
|
|
|
|
+ { deallocate the temp }
|
|
|
|
+ if assigned(tempnode) then
|
|
|
|
+ addstatement(newstatement,ctempdeletenode.create(tempnode));
|
|
|
|
+ { firstpass it }
|
|
|
|
+ firstpass(tnode(newblock));
|
|
|
|
+ { return new node }
|
|
|
|
+ result := newblock;
|
|
|
|
+ end;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ function tinlinenode.first_IncDec: tnode;
|
|
begin
|
|
begin
|
|
expectloc:=LOC_VOID;
|
|
expectloc:=LOC_VOID;
|
|
result:=nil;
|
|
result:=nil;
|
|
@@ -3861,94 +3958,8 @@ implementation
|
|
or (tcallparanode(left).left.resultdef.typ=enumdef)
|
|
or (tcallparanode(left).left.resultdef.typ=enumdef)
|
|
{$endif}
|
|
{$endif}
|
|
then
|
|
then
|
|
- { convert to simple add (JM) }
|
|
|
|
- begin
|
|
|
|
- newblock := internalstatements(newstatement);
|
|
|
|
- { extra parameter? }
|
|
|
|
- if assigned(tcallparanode(left).right) then
|
|
|
|
- begin
|
|
|
|
- { Yes, use for add node }
|
|
|
|
- hpp := tcallparanode(tcallparanode(left).right).left;
|
|
|
|
- tcallparanode(tcallparanode(left).right).left := nil;
|
|
|
|
- if assigned(tcallparanode(tcallparanode(left).right).right) then
|
|
|
|
- CGMessage(parser_e_illegal_expression);
|
|
|
|
- end
|
|
|
|
- else
|
|
|
|
- begin
|
|
|
|
- { no, create constant 1 }
|
|
|
|
- hpp := cordconstnode.create(1,tcallparanode(left).left.resultdef,false);
|
|
|
|
- end;
|
|
|
|
- typecheckpass(hpp);
|
|
|
|
-
|
|
|
|
- { make sure we don't call functions part of the left node twice (and generally }
|
|
|
|
- { optimize the code generation) }
|
|
|
|
- { Storing address is not always an optimization: alignment of left is not known
|
|
|
|
- at this point, so we must assume the worst and use an unaligned pointer.
|
|
|
|
- This results in larger and slower code on alignment-sensitive targets.
|
|
|
|
- Therefore the complexity condition below is questionable, maybe just filtering
|
|
|
|
- out calls with "= NODE_COMPLEXITY_INF" is sufficient.
|
|
|
|
- Value of 3 corresponds to subscript nodes, i.e. record field. }
|
|
|
|
- if node_complexity(tcallparanode(left).left) > 3 then
|
|
|
|
- begin
|
|
|
|
- tempnode := ctempcreatenode.create(voidpointertype,voidpointertype.size,tt_persistent,true);
|
|
|
|
- addstatement(newstatement,tempnode);
|
|
|
|
- addstatement(newstatement,cassignmentnode.create(ctemprefnode.create(tempnode),
|
|
|
|
- caddrnode.create_internal(tcallparanode(left).left.getcopy)));
|
|
|
|
- hp := cderefnode.create(ctemprefnode.create(tempnode));
|
|
|
|
- inserttypeconv_internal(hp,tcallparanode(left).left.resultdef);
|
|
|
|
- end
|
|
|
|
- else
|
|
|
|
- begin
|
|
|
|
- hp := tcallparanode(left).left.getcopy;
|
|
|
|
- tempnode := nil;
|
|
|
|
- end;
|
|
|
|
-
|
|
|
|
- resultnode := hp.getcopy;
|
|
|
|
- { avoid type errors from the addn/subn }
|
|
|
|
- if not is_integer(resultnode.resultdef) then
|
|
|
|
- begin
|
|
|
|
- inserttypeconv_internal(hp,sinttype);
|
|
|
|
- inserttypeconv_internal(hpp,sinttype);
|
|
|
|
- end;
|
|
|
|
-
|
|
|
|
- { addition/substraction depending on inc/dec }
|
|
|
|
- if inlinenumber = in_inc_x then
|
|
|
|
- hpp := caddnode.create(addn,hp,hpp)
|
|
|
|
- else
|
|
|
|
- hpp := caddnode.create(subn,hp,hpp);
|
|
|
|
- { assign result of addition }
|
|
|
|
- if not(is_integer(resultnode.resultdef)) then
|
|
|
|
- inserttypeconv(hpp,corddef.create(
|
|
|
|
-{$ifdef cpu64bitaddr}
|
|
|
|
- s64bit,
|
|
|
|
-{$else cpu64bitaddr}
|
|
|
|
- s32bit,
|
|
|
|
-{$endif cpu64bitaddr}
|
|
|
|
- get_min_value(resultnode.resultdef),
|
|
|
|
- get_max_value(resultnode.resultdef),
|
|
|
|
- true))
|
|
|
|
- else
|
|
|
|
- inserttypeconv(hpp,resultnode.resultdef);
|
|
|
|
-
|
|
|
|
- { avoid any possible warnings }
|
|
|
|
- inserttypeconv_internal(hpp,resultnode.resultdef);
|
|
|
|
-
|
|
|
|
- addstatement(newstatement,cassignmentnode.create(resultnode,hpp));
|
|
|
|
-
|
|
|
|
- { force pass 1, so copied tries get first pass'ed as well and flags like nf_write, nf_call_unique
|
|
|
|
- get set right }
|
|
|
|
- node_reset_flags(newstatement.statement,[nf_pass1_done]);
|
|
|
|
- { firstpass it }
|
|
|
|
- firstpass(tnode(newstatement.left));
|
|
|
|
-
|
|
|
|
- { deallocate the temp }
|
|
|
|
- if assigned(tempnode) then
|
|
|
|
- addstatement(newstatement,ctempdeletenode.create(tempnode));
|
|
|
|
- { firstpass it }
|
|
|
|
- firstpass(tnode(newblock));
|
|
|
|
- { return new node }
|
|
|
|
- result := newblock;
|
|
|
|
- end;
|
|
|
|
|
|
+ { convert to simple add (JM) }
|
|
|
|
+ result:=getaddsub_for_incdec
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|