Ver Fonte

* moved support for copy() from pinline to ninl, so it can be (partially)
overridden for targets that require it

git-svn-id: branches/jvmbackend@18500 -

Jonas Maebe há 14 anos atrás
pai
commit
622107c605
2 ficheiros alterados com 138 adições e 89 exclusões
  1. 133 0
      compiler/ninl.pas
  2. 5 89
      compiler/pinline.pas

+ 133 - 0
compiler/ninl.pas

@@ -66,6 +66,7 @@ interface
           function first_int_real: tnode; virtual;
           function first_abs_long: tnode; virtual;
           function first_setlength: tnode; virtual;
+          function first_copy: tnode; virtual;
           { This one by default generates an internal error, because such
             nodes are not generated by the parser. It's however used internally
             by the JVM backend to create new dynamic arrays. }
@@ -79,6 +80,7 @@ interface
           function handle_read_write: tnode;
           function handle_val: tnode;
           function handle_setlength: tnode;
+          function handle_copy: tnode;
        end;
        tinlinenodeclass = class of tinlinenode;
 
@@ -1429,6 +1431,68 @@ implementation
         result:=nil;
       end;
 
+
+    function tinlinenode.handle_copy: tnode;
+      var
+        lowppn,
+        highppn,
+        npara,
+        paras   : tnode;
+        ppn     : tcallparanode;
+        paradef : tdef;
+        counter : integer;
+      begin
+        result:=nil;
+        { determine copy function to use based on the first argument,
+          also count the number of arguments in this loop }
+        counter:=1;
+        paras:=left;
+        ppn:=tcallparanode(paras);
+        while assigned(ppn.right) do
+         begin
+           inc(counter);
+           ppn:=tcallparanode(ppn.right);
+         end;
+        paradef:=ppn.left.resultdef;
+        if is_ansistring(paradef) or
+           (is_chararray(paradef) and
+            (paradef.size>255)) or
+           ((cs_ansistrings in current_settings.localswitches) and
+            is_pchar(paradef)) then
+          resultdef:=cansistringtype
+        else
+         if is_widestring(paradef) then
+           resultdef:=cwidestringtype
+        else
+         if is_unicodestring(paradef) or
+            is_widechararray(paradef) or
+            is_pwidechar(paradef) then
+           resultdef:=cunicodestringtype
+        else
+         if is_char(paradef) then
+           resultdef:=cshortstringtype
+        else
+         if is_dynamic_array(paradef) then
+          begin
+            { Only allow 1 or 3 arguments }
+            if (counter<>1) and (counter<>3) then
+             begin
+               CGMessage1(parser_e_wrong_parameter_size,'Copy');
+               exit;
+             end;
+            resultdef:=paradef;
+          end
+        else
+         begin
+           { generic fallback that will give an error if a wrong
+             type is passed }
+           if (counter=3) then
+             resultdef:=cshortstringtype
+           else
+             CGMessagePos(ppn.left.fileinfo,type_e_mismatch);
+         end;
+      end;
+
 {$maxfpuregisters 0}
 
     function getpi : bestreal;
@@ -2481,6 +2545,9 @@ implementation
                      end;
                 end;
 
+              in_copy_x:
+                result:=handle_copy;
+
               in_initialize_x,
               in_finalize_x:
                 begin
@@ -2964,6 +3031,8 @@ implementation
 
           in_setlength_x:
             result:=first_setlength;
+          in_copy_x:
+            result:=first_copy;
           in_initialize_x,
           in_finalize_x:
             begin
@@ -3417,6 +3486,70 @@ implementation
         result:=newblock;
       end;
 
+    function tinlinenode.first_copy: tnode;
+      var
+        lowppn,
+        highppn,
+        npara,
+        paras   : tnode;
+        ppn     : tcallparanode;
+        paradef : tdef;
+        counter : integer;
+      begin
+        { determine copy function to use based on the first argument,
+          also count the number of arguments in this loop }
+        counter:=1;
+        paras:=left;
+        ppn:=tcallparanode(paras);
+        while assigned(ppn.right) do
+          begin
+            inc(counter);
+            ppn:=tcallparanode(ppn.right);
+          end;
+        paradef:=ppn.left.resultdef;
+        if is_ansistring(resultdef) then
+          result:=ccallnode.createintern('fpc_ansistr_copy',paras)
+        else if is_widestring(resultdef) then
+          result:=ccallnode.createintern('fpc_widestr_copy',paras)
+        else if is_unicodestring(resultdef) then
+          result:=ccallnode.createintern('fpc_unicodestr_copy',paras)
+          { can't check for resultdef = cchartype, because resultdef=
+            cshortstringtype here }
+        else if is_char(paradef) then
+          result:=ccallnode.createintern('fpc_char_copy',paras)
+        else if is_dynamic_array(resultdef) then
+          begin
+            { create statements with call }
+            if (counter=3) then
+             begin
+               highppn:=tcallparanode(paras).left.getcopy;
+               lowppn:=tcallparanode(tcallparanode(paras).right).left.getcopy;
+             end
+            else
+             begin
+               { use special -1,-1 argument to copy the whole array }
+               highppn:=cordconstnode.create(int64(-1),s32inttype,false);
+               lowppn:=cordconstnode.create(int64(-1),s32inttype,false);
+             end;
+
+            { create call to fpc_dynarray_copy }
+            npara:=ccallparanode.create(highppn,
+                   ccallparanode.create(lowppn,
+                   ccallparanode.create(caddrnode.create_internal
+                      (crttinode.create(tstoreddef(ppn.left.resultdef),initrtti,rdt_normal)),
+                   ccallparanode.create
+                      (ctypeconvnode.create_internal(ppn.left,voidpointertype),nil))));
+            result:=ccallnode.createinternres('fpc_dynarray_copy',npara,ppn.left.resultdef);
+
+            ppn.left:=nil;
+            paras.free;
+          end
+        else
+          result:=ccallnode.createintern('fpc_shortstr_copy',paras);
+        { parameters are reused }
+        left:=nil;
+     end;
+
      function tinlinenode.first_new: tnode;
        begin
          internalerror(2011012201);

+ 5 - 89
compiler/pinline.pas

@@ -543,105 +543,21 @@ implementation
 
     function inline_copy : tnode;
       var
-        copynode,
-        lowppn,
-        highppn,
-        npara,
         paras   : tnode;
-        ppn     : tcallparanode;
-        paradef : tdef;
-        counter : integer;
-      begin
         { for easy exiting if something goes wrong }
+      begin
         result := cerrornode.create;
 
         consume(_LKLAMMER);
         paras:=parse_paras(false,false,_RKLAMMER);
         consume(_RKLAMMER);
         if not assigned(paras) then
-         begin
-           CGMessage1(parser_e_wrong_parameter_size,'Copy');
-           exit;
-         end;
-
-        { determine copy function to use based on the first argument,
-          also count the number of arguments in this loop }
-        counter:=1;
-        ppn:=tcallparanode(paras);
-        while assigned(ppn.right) do
-         begin
-           inc(counter);
-           ppn:=tcallparanode(ppn.right);
-         end;
-        paradef:=ppn.left.resultdef;
-        if is_ansistring(paradef) or
-           (is_chararray(paradef) and
-            (paradef.size>255)) or
-           ((cs_ansistrings in current_settings.localswitches) and
-            is_pchar(paradef)) then
-          copynode:=ccallnode.createintern('fpc_ansistr_copy',paras)
-        else
-         if is_widestring(paradef) then
-           copynode:=ccallnode.createintern('fpc_widestr_copy',paras)
-        else
-         if is_unicodestring(paradef) or
-            is_widechararray(paradef) or
-            is_pwidechar(paradef) then
-           copynode:=ccallnode.createintern('fpc_unicodestr_copy',paras)
-        else
-         if is_char(paradef) then
-           copynode:=ccallnode.createintern('fpc_char_copy',paras)
-        else
-         if is_dynamic_array(paradef) then
           begin
-            { Only allow 1 or 3 arguments }
-            if (counter<>1) and (counter<>3) then
-             begin
-               CGMessage1(parser_e_wrong_parameter_size,'Copy');
-               exit;
-             end;
-
-            { create statements with call }
-
-            if (counter=3) then
-             begin
-               highppn:=tcallparanode(paras).left.getcopy;
-               lowppn:=tcallparanode(tcallparanode(paras).right).left.getcopy;
-             end
-            else
-             begin
-               { use special -1,-1 argument to copy the whole array }
-               highppn:=cordconstnode.create(int64(-1),s32inttype,false);
-               lowppn:=cordconstnode.create(int64(-1),s32inttype,false);
-             end;
-
-            { create call to fpc_dynarray_copy }
-            npara:=ccallparanode.create(highppn,
-                   ccallparanode.create(lowppn,
-                   ccallparanode.create(caddrnode.create_internal
-                      (crttinode.create(tstoreddef(ppn.left.resultdef),initrtti,rdt_normal)),
-                   ccallparanode.create
-                      (ctypeconvnode.create_internal(ppn.left,voidpointertype),nil))));
-            copynode:=ccallnode.createinternres('fpc_dynarray_copy',npara,ppn.left.resultdef);
-
-            ppn.left:=nil;
-            paras.free;
-          end
-        else
-         begin
-           { generic fallback that will give an error if a wrong
-             type is passed }
-           if (counter=3) then
-             copynode:=ccallnode.createintern('fpc_shortstr_copy',paras)
-           else
-             begin
-               CGMessagePos(ppn.left.fileinfo,type_e_mismatch);
-               copynode:=cerrornode.create;
-             end
-         end;
-
+            CGMessage1(parser_e_wrong_parameter_size,'Copy');
+            exit;
+          end;
         result.free;
-        result:=copynode;
+        result:=cinlinenode.create(in_copy_x,false,paras);
       end;
 
 end.