Browse Source

* factored out tinlinenode.getaddsub_for_incdec from first_IncDec so it can be used independently
* get varstate right of inc/dec nodes which are converted into add/sub nodes

git-svn-id: trunk@34792 -

florian 8 years ago
parent
commit
e4d60b2048
1 changed files with 100 additions and 89 deletions
  1. 100 89
      compiler/ninl.pas

+ 100 - 89
compiler/ninl.pas

@@ -43,6 +43,9 @@ interface
           function simplify(forinline : boolean): tnode;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 }
           function first_pack_unpack: tnode; virtual;
 
@@ -3839,12 +3842,106 @@ implementation
       end;
 
 
-     function tinlinenode.first_IncDec: tnode;
+     function tinlinenode.getaddsub_for_incdec : tnode;
        var
          hp,hpp,resultnode  : tnode;
          tempnode: ttempcreatenode;
          newstatement: tstatementnode;
          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
          expectloc:=LOC_VOID;
          result:=nil;
@@ -3861,94 +3958,8 @@ implementation
              or (tcallparanode(left).left.resultdef.typ=enumdef)
 {$endif}
             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;