Ver Fonte

* initialise local dynamic array variables to empty arrays rather than
to "nil", so that returning them to Java code does not return a nil
pointer

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

Jonas Maebe há 14 anos atrás
pai
commit
761ff19c7f
3 ficheiros alterados com 71 adições e 10 exclusões
  1. 53 5
      compiler/jvm/njvminl.pas
  2. 15 5
      compiler/jvm/njvmutil.pas
  3. 3 0
      compiler/ncginl.pas

+ 53 - 5
compiler/jvm/njvminl.pas

@@ -35,6 +35,8 @@ interface
           function typecheck_length(var handled: boolean): tnode;
           function typecheck_high(var handled: boolean): tnode;
           function typecheck_new(var handled: boolean): tnode;
+
+          function first_setlength_array: tnode;
          public
           { typecheck override to intercept handling }
           function pass_typecheck: tnode; override;
@@ -65,6 +67,7 @@ interface
           procedure second_round_real; override;
 *)
           procedure second_new; override;
+          procedure second_setlength; override;
        protected
           procedure load_fpu_location;
        end;
@@ -74,9 +77,9 @@ implementation
     uses
       cutils,globals,verbose,globtype,constexp,
       aasmbase,aasmtai,aasmdata,aasmcpu,
-      symtype,symconst,symdef,symtable,jvmdef,
+      symtype,symconst,symdef,symsym,symtable,jvmdef,
       defutil,
-      nbas,ncon,ncnv,ncal,nld,
+      nbas,ncon,ncnv,ncal,nld,nflw,nutils,
       cgbase,pass_1,pass_2,
       cpuinfo,ncgutil,
       cgutils,hlcgobj,hlcgcpu;
@@ -216,7 +219,7 @@ implementation
       end;
 
 
-    function tjvminlinenode.first_setlength: tnode;
+    function tjvminlinenode.first_setlength_array: tnode;
       var
         assignmenttarget,
         ppn,
@@ -232,8 +235,6 @@ implementation
         newstatement: tstatementnode;
         primitive: boolean;
       begin
-        { reverse the parameter order so we can process them more easily }
-        left:=reverseparameters(tcallparanode(left));
         { first parameter is the array, the rest are the dimensions }
         newparas:=tcallparanode(left).right;
         tcallparanode(left).right:=nil;
@@ -333,6 +334,29 @@ implementation
       end;
 
 
+    function tjvminlinenode.first_setlength: tnode;
+
+      begin
+        { reverse the parameter order so we can process them more easily }
+        left:=reverseparameters(tcallparanode(left));
+        { treat setlength(x,0) specially: used to init uninitialised locations }
+        if not assigned(tcallparanode(tcallparanode(left).right).right) and
+           is_constintnode(tcallparanode(tcallparanode(left).right).left) and
+           (tordconstnode(tcallparanode(tcallparanode(left).right).left).value=0) then
+          begin
+            result:=nil;
+            expectloc:=LOC_VOID;
+            exit;
+          end;
+        case left.resultdef.typ of
+          arraydef:
+            result:=first_setlength_array;
+          else
+            internalerror(2011031204);
+        end;
+      end;
+
+
     procedure tjvminlinenode.second_length;
       begin
         if is_dynamic_array(left.resultdef) or
@@ -469,6 +493,30 @@ implementation
       end;
 
 
+    procedure tjvminlinenode.second_setlength;
+      var
+        target: tnode;
+        lenpara: tnode;
+      begin
+        target:=tcallparanode(left).left;
+        lenpara:=tcallparanode(tcallparanode(left).right).left;
+        if assigned(tcallparanode(tcallparanode(left).right).right) or
+           not is_constintnode(lenpara) or
+           (tordconstnode(lenpara).value<>0) then
+          internalerror(2011031801);
+
+        secondpass(target);
+        if is_dynamic_array(target.resultdef) then
+          begin
+            thlcgjvm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,s32inttype,0,R_INTREGISTER);
+            thlcgjvm(hlcg).g_newarray(current_asmdata.CurrAsmList,target.resultdef,1);
+          end
+        else
+          internalerror(2011031401);
+        thlcgjvm(hlcg).a_load_stack_loc(current_asmdata.CurrAsmList,target.resultdef,target.location);
+      end;
+
+
 begin
    cinlinenode:=tjvminlinenode;
 end.

+ 15 - 5
compiler/jvm/njvmutil.pas

@@ -42,7 +42,7 @@ implementation
     uses
       verbose,constexp,
       symconst,symtype,symdef,symsym,symbase,symtable,defutil,
-      nbas,ncnv,ncon,nld,
+      nbas,ncnv,ncon,ninl,ncal,
       pass_1;
 
   class function tjvmnodeutils.initialize_data_node(p:tnode):tnode;
@@ -54,10 +54,20 @@ implementation
           not is_longstring(p.resultdef)) or
          is_dynamic_array(p.resultdef) then
         begin
-          result:=cassignmentnode.create(
-             ctypeconvnode.create_internal(p,voidpointertype),
-             cnilnode.create
-             );
+          { Always initialise with empty string/array rather than nil. Java
+            makes a distinction between an empty string/array and a null
+            string/array,  but we don't. We therefore have to pick which one we
+            use to represent empty strings/arrays. I've chosen empty rather than
+            null structures, because otherwise it becomes impossible to return
+            an empty string to Java code (it would return null).
+
+            On the consumer side, we do interpret both null and empty as the same
+            thing, so Java code can pass in null strings/arrays and we'll
+            interpret them correctly.
+          }
+          result:=cinlinenode.create(in_setlength_x,false,
+            ccallparanode.create(genintconstnode(0),
+              ccallparanode.create(p,nil)));
         end
       else
         { records/arrays/... are automatically initialised }

+ 3 - 0
compiler/ncginl.pas

@@ -58,6 +58,7 @@ interface
           procedure second_sar; virtual;
           procedure second_bsfbsr; virtual;
           procedure second_new; virtual;
+          procedure second_setlength; virtual; abstract;
        end;
 
 implementation
@@ -176,6 +177,8 @@ implementation
                second_BsfBsr;
             in_new_x:
                second_new;
+            in_setlength_x:
+               second_setlength;
             else internalerror(9);
          end;
       end;